Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 1b255e4

Browse files
committed
Convert src/Lifecycle.ts to TypeScript
1 parent 11eb9b5 commit 1b255e4

File tree

3 files changed

+81
-57
lines changed

3 files changed

+81
-57
lines changed

src/Lifecycle.js renamed to src/Lifecycle.ts

Lines changed: 75 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ limitations under the License.
1818
*/
1919

2020
import Matrix from 'matrix-js-sdk';
21+
import { InvalidStoreError } from "matrix-js-sdk/src/errors";
22+
import { MatrixClient } from "matrix-js-sdk/src/client";
2123

22-
import {MatrixClientPeg} from './MatrixClientPeg';
24+
import {IMatrixClientCreds, MatrixClientPeg} from './MatrixClientPeg';
2325
import EventIndexPeg from './indexing/EventIndexPeg';
2426
import createMatrixClient from './utils/createMatrixClient';
2527
import Analytics from './Analytics';
@@ -47,44 +49,46 @@ import ThreepidInviteStore from "./stores/ThreepidInviteStore";
4749
const HOMESERVER_URL_KEY = "mx_hs_url";
4850
const ID_SERVER_URL_KEY = "mx_is_url";
4951

52+
interface ILoadSessionOpts {
53+
enableGuest?: boolean;
54+
guestHsUrl?: string;
55+
guestIsUrl?: string;
56+
ignoreGuest?: boolean;
57+
defaultDeviceDisplayName?: string;
58+
fragmentQueryParams?: Record<string, string>;
59+
}
60+
5061
/**
5162
* Called at startup, to attempt to build a logged-in Matrix session. It tries
5263
* a number of things:
5364
*
54-
*
5565
* 1. if we have a guest access token in the fragment query params, it uses
5666
* that.
57-
*
5867
* 2. if an access token is stored in local storage (from a previous session),
5968
* it uses that.
60-
*
6169
* 3. it attempts to auto-register as a guest user.
6270
*
6371
* If any of steps 1-4 are successful, it will call {_doSetLoggedIn}, which in
6472
* turn will raise on_logged_in and will_start_client events.
6573
*
66-
* @param {object} opts
67-
*
68-
* @param {object} opts.fragmentQueryParams: string->string map of the
74+
* @param {object} [opts]
75+
* @param {object} [opts.fragmentQueryParams]: string->string map of the
6976
* query-parameters extracted from the #-fragment of the starting URI.
70-
*
71-
* @param {boolean} opts.enableGuest: set to true to enable guest access tokens
72-
* and auto-guest registrations.
73-
*
74-
* @params {string} opts.guestHsUrl: homeserver URL. Only used if enableGuest is
75-
* true; defines the HS to register against.
76-
*
77-
* @params {string} opts.guestIsUrl: homeserver URL. Only used if enableGuest is
78-
* true; defines the IS to use.
79-
*
80-
* @params {bool} opts.ignoreGuest: If the stored session is a guest account, ignore
81-
* it and don't load it.
82-
*
77+
* @param {boolean} [opts.enableGuest]: set to true to enable guest access
78+
* tokens and auto-guest registrations.
79+
* @param {string} [opts.guestHsUrl]: homeserver URL. Only used if enableGuest
80+
* is true; defines the HS to register against.
81+
* @param {string} [opts.guestIsUrl]: homeserver URL. Only used if enableGuest
82+
* is true; defines the IS to use.
83+
* @param {bool} [opts.ignoreGuest]: If the stored session is a guest account,
84+
* ignore it and don't load it.
85+
* @param {string} [opts.defaultDeviceDisplayName]: Default display name to use
86+
* when registering as a guest.
8387
* @returns {Promise} a promise which resolves when the above process completes.
8488
* Resolves to `true` if we ended up starting a session, or `false` if we
8589
* failed.
8690
*/
87-
export async function loadSession(opts) {
91+
export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean> {
8892
try {
8993
let enableGuest = opts.enableGuest || false;
9094
const guestHsUrl = opts.guestHsUrl;
@@ -97,10 +101,11 @@ export async function loadSession(opts) {
97101
enableGuest = false;
98102
}
99103

100-
if (enableGuest &&
104+
if (
105+
enableGuest &&
101106
fragmentQueryParams.guest_user_id &&
102107
fragmentQueryParams.guest_access_token
103-
) {
108+
) {
104109
console.log("Using guest access credentials");
105110
return _doSetLoggedIn({
106111
userId: fragmentQueryParams.guest_user_id,
@@ -139,7 +144,7 @@ export async function loadSession(opts) {
139144
* is associated with them. The session is not loaded.
140145
* @returns {String} The persisted session's owner, if an owner exists. Null otherwise.
141146
*/
142-
export function getStoredSessionOwner() {
147+
export function getStoredSessionOwner(): string {
143148
const {hsUrl, userId, accessToken} = getLocalStorageSessionVars();
144149
return hsUrl && userId && accessToken ? userId : null;
145150
}
@@ -148,7 +153,7 @@ export function getStoredSessionOwner() {
148153
* @returns {bool} True if the stored session is for a guest user or false if it is
149154
* for a real user. If there is no stored session, return null.
150155
*/
151-
export function getStoredSessionIsGuest() {
156+
export function getStoredSessionIsGuest(): boolean {
152157
const sessVars = getLocalStorageSessionVars();
153158
return sessVars.hsUrl && sessVars.userId && sessVars.accessToken ? sessVars.isGuest : null;
154159
}
@@ -163,7 +168,10 @@ export function getStoredSessionIsGuest() {
163168
* @returns {Promise} promise which resolves to true if we completed the token
164169
* login, else false
165170
*/
166-
export function attemptTokenLogin(queryParams, defaultDeviceDisplayName) {
171+
export function attemptTokenLogin(
172+
queryParams: Record<string, string>,
173+
defaultDeviceDisplayName?: string,
174+
): Promise<boolean> {
167175
if (!queryParams.loginToken) {
168176
return Promise.resolve(false);
169177
}
@@ -187,7 +195,7 @@ export function attemptTokenLogin(queryParams, defaultDeviceDisplayName) {
187195
return _clearStorage().then(() => {
188196
_persistCredentialsToLocalStorage(creds);
189197
// remember that we just logged in
190-
sessionStorage.setItem("mx_fresh_login", true);
198+
sessionStorage.setItem("mx_fresh_login", String(true));
191199
return true;
192200
});
193201
}).catch((err) => {
@@ -197,8 +205,8 @@ export function attemptTokenLogin(queryParams, defaultDeviceDisplayName) {
197205
});
198206
}
199207

200-
export function handleInvalidStoreError(e) {
201-
if (e.reason === Matrix.InvalidStoreError.TOGGLED_LAZY_LOADING) {
208+
export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
209+
if (e.reason === InvalidStoreError.TOGGLED_LAZY_LOADING) {
202210
return Promise.resolve().then(() => {
203211
const lazyLoadEnabled = e.value;
204212
if (lazyLoadEnabled) {
@@ -231,7 +239,11 @@ export function handleInvalidStoreError(e) {
231239
}
232240
}
233241

234-
function _registerAsGuest(hsUrl, isUrl, defaultDeviceDisplayName) {
242+
function _registerAsGuest(
243+
hsUrl: string,
244+
isUrl: string,
245+
defaultDeviceDisplayName: string,
246+
): Promise<boolean> {
235247
console.log(`Doing guest login on ${hsUrl}`);
236248

237249
// create a temporary MatrixClient to do the login
@@ -259,12 +271,21 @@ function _registerAsGuest(hsUrl, isUrl, defaultDeviceDisplayName) {
259271
});
260272
}
261273

274+
export interface ILocalStorageSession {
275+
hsUrl: string;
276+
isUrl: string;
277+
accessToken: string;
278+
userId: string;
279+
deviceId: string;
280+
isGuest: boolean;
281+
}
282+
262283
/**
263284
* Retrieves information about the stored session in localstorage. The session
264285
* may not be valid, as it is not tested for consistency here.
265286
* @returns {Object} Information about the session - see implementation for variables.
266287
*/
267-
export function getLocalStorageSessionVars() {
288+
export function getLocalStorageSessionVars(): ILocalStorageSession {
268289
const hsUrl = localStorage.getItem(HOMESERVER_URL_KEY);
269290
const isUrl = localStorage.getItem(ID_SERVER_URL_KEY);
270291
const accessToken = localStorage.getItem("mx_access_token");
@@ -292,8 +313,8 @@ export function getLocalStorageSessionVars() {
292313
// The plan is to gradually move the localStorage access done here into
293314
// SessionStore to avoid bugs where the view becomes out-of-sync with
294315
// localStorage (e.g. isGuest etc.)
295-
async function _restoreFromLocalStorage(opts) {
296-
const ignoreGuest = opts.ignoreGuest;
316+
async function _restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }): Promise<boolean> {
317+
const ignoreGuest = opts?.ignoreGuest;
297318

298319
if (!localStorage) {
299320
return false;
@@ -314,7 +335,7 @@ async function _restoreFromLocalStorage(opts) {
314335
console.log("No pickle key available");
315336
}
316337

317-
const freshLogin = sessionStorage.getItem("mx_fresh_login");
338+
const freshLogin = sessionStorage.getItem("mx_fresh_login") === "true";
318339
sessionStorage.removeItem("mx_fresh_login");
319340

320341
console.log(`Restoring session for ${userId}`);
@@ -335,7 +356,7 @@ async function _restoreFromLocalStorage(opts) {
335356
}
336357
}
337358

338-
async function _handleLoadSessionFailure(e) {
359+
async function _handleLoadSessionFailure(e: Error): Promise<boolean> {
339360
console.error("Unable to load session", e);
340361

341362
const SessionRestoreErrorDialog =
@@ -369,12 +390,12 @@ async function _handleLoadSessionFailure(e) {
369390
*
370391
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
371392
*/
372-
export async function setLoggedIn(credentials) {
393+
export async function setLoggedIn(credentials: IMatrixClientCreds): Promise<MatrixClient> {
373394
credentials.freshLogin = true;
374395
stopMatrixClient();
375396
const pickleKey = credentials.userId && credentials.deviceId
376-
? await PlatformPeg.get().createPickleKey(credentials.userId, credentials.deviceId)
377-
: null;
397+
? await PlatformPeg.get().createPickleKey(credentials.userId, credentials.deviceId)
398+
: null;
378399

379400
if (pickleKey) {
380401
console.log("Created pickle key");
@@ -400,7 +421,7 @@ export async function setLoggedIn(credentials) {
400421
*
401422
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
402423
*/
403-
export function hydrateSession(credentials) {
424+
export function hydrateSession(credentials: IMatrixClientCreds): Promise<MatrixClient> {
404425
const oldUserId = MatrixClientPeg.get().getUserId();
405426
const oldDeviceId = MatrixClientPeg.get().getDeviceId();
406427

@@ -425,7 +446,10 @@ export function hydrateSession(credentials) {
425446
*
426447
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
427448
*/
428-
async function _doSetLoggedIn(credentials, clearStorage) {
449+
async function _doSetLoggedIn(
450+
credentials: IMatrixClientCreds,
451+
clearStorage: boolean,
452+
): Promise<MatrixClient> {
429453
credentials.guest = Boolean(credentials.guest);
430454

431455
const softLogout = isSoftLogout();
@@ -514,7 +538,7 @@ async function _doSetLoggedIn(credentials, clearStorage) {
514538
return client;
515539
}
516540

517-
function _showStorageEvictedDialog() {
541+
function _showStorageEvictedDialog(): Promise<boolean> {
518542
const StorageEvictedDialog = sdk.getComponent('views.dialogs.StorageEvictedDialog');
519543
return new Promise(resolve => {
520544
Modal.createTrackedDialog('Storage evicted', '', StorageEvictedDialog, {
@@ -527,7 +551,7 @@ function _showStorageEvictedDialog() {
527551
// `instanceof`. Babel 7 supports this natively in their class handling.
528552
class AbortLoginAndRebuildStorage extends Error { }
529553

530-
function _persistCredentialsToLocalStorage(credentials) {
554+
function _persistCredentialsToLocalStorage(credentials: IMatrixClientCreds): void {
531555
localStorage.setItem(HOMESERVER_URL_KEY, credentials.homeserverUrl);
532556
if (credentials.identityServerUrl) {
533557
localStorage.setItem(ID_SERVER_URL_KEY, credentials.identityServerUrl);
@@ -537,7 +561,7 @@ function _persistCredentialsToLocalStorage(credentials) {
537561
localStorage.setItem("mx_is_guest", JSON.stringify(credentials.guest));
538562

539563
if (credentials.pickleKey) {
540-
localStorage.setItem("mx_has_pickle_key", true);
564+
localStorage.setItem("mx_has_pickle_key", String(true));
541565
} else {
542566
if (localStorage.getItem("mx_has_pickle_key")) {
543567
console.error("Expected a pickle key, but none provided. Encryption may not work.");
@@ -561,7 +585,7 @@ let _isLoggingOut = false;
561585
/**
562586
* Logs the current session out and transitions to the logged-out state
563587
*/
564-
export function logout() {
588+
export function logout(): void {
565589
if (!MatrixClientPeg.get()) return;
566590

567591
if (MatrixClientPeg.get().isGuest()) {
@@ -590,7 +614,7 @@ export function logout() {
590614
);
591615
}
592616

593-
export function softLogout() {
617+
export function softLogout(): void {
594618
if (!MatrixClientPeg.get()) return;
595619

596620
// Track that we've detected and trapped a soft logout. This helps prevent other
@@ -611,11 +635,11 @@ export function softLogout() {
611635
// DO NOT CALL LOGOUT. A soft logout preserves data, logout does not.
612636
}
613637

614-
export function isSoftLogout() {
638+
export function isSoftLogout(): boolean {
615639
return localStorage.getItem("mx_soft_logout") === "true";
616640
}
617641

618-
export function isLoggingOut() {
642+
export function isLoggingOut(): boolean {
619643
return _isLoggingOut;
620644
}
621645

@@ -625,7 +649,7 @@ export function isLoggingOut() {
625649
* @param {boolean} startSyncing True (default) to actually start
626650
* syncing the client.
627651
*/
628-
async function startMatrixClient(startSyncing=true) {
652+
async function startMatrixClient(startSyncing = true): Promise<void> {
629653
console.log(`Lifecycle: Starting MatrixClient`);
630654

631655
// dispatch this before starting the matrix client: it's used
@@ -684,7 +708,7 @@ async function startMatrixClient(startSyncing=true) {
684708
* Stops a running client and all related services, and clears persistent
685709
* storage. Used after a session has been logged out.
686710
*/
687-
export async function onLoggedOut() {
711+
export async function onLoggedOut(): Promise<void> {
688712
_isLoggingOut = false;
689713
// Ensure that we dispatch a view change **before** stopping the client so
690714
// so that React components unmount first. This avoids React soft crashes
@@ -698,7 +722,7 @@ export async function onLoggedOut() {
698722
* @param {object} opts Options for how to clear storage.
699723
* @returns {Promise} promise which resolves once the stores have been cleared
700724
*/
701-
async function _clearStorage(opts: {deleteEverything: boolean}) {
725+
async function _clearStorage(opts?: { deleteEverything?: boolean }): Promise<void> {
702726
Analytics.disable();
703727

704728
if (window.localStorage) {
@@ -736,7 +760,7 @@ async function _clearStorage(opts: {deleteEverything: boolean}) {
736760
* @param {boolean} unsetClient True (default) to abandon the client
737761
* on MatrixClientPeg after stopping.
738762
*/
739-
export function stopMatrixClient(unsetClient=true) {
763+
export function stopMatrixClient(unsetClient = true): void {
740764
Notifier.stop();
741765
UserActivity.sharedInstance().stop();
742766
TypingStore.sharedInstance().reset();

src/MatrixClientPeg.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface IMatrixClientCreds {
3838
homeserverUrl: string;
3939
identityServerUrl: string;
4040
userId: string;
41-
deviceId: string;
41+
deviceId?: string;
4242
accessToken: string;
4343
guest?: boolean;
4444
pickleKey?: string;

src/components/structures/MatrixChat.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import 'what-input';
3030

3131
import Analytics from "../../Analytics";
3232
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
33-
import { MatrixClientPeg } from "../../MatrixClientPeg";
33+
import { MatrixClientPeg, IMatrixClientCreds } from "../../MatrixClientPeg";
3434
import PlatformPeg from "../../PlatformPeg";
3535
import SdkConfig from "../../SdkConfig";
3636
import * as RoomListSorter from "../../RoomListSorter";
@@ -290,7 +290,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
290290
// When the session loads it'll be detected as soft logged out and a dispatch
291291
// will be sent out to say that, triggering this MatrixChat to show the soft
292292
// logout page.
293-
Lifecycle.loadSession({});
293+
Lifecycle.loadSession();
294294
}
295295

296296
this.accountPassword = null;
@@ -1814,12 +1814,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
18141814
this.showScreen("forgot_password");
18151815
};
18161816

1817-
onRegisterFlowComplete = (credentials: object, password: string) => {
1817+
onRegisterFlowComplete = (credentials: IMatrixClientCreds, password: string) => {
18181818
return this.onUserCompletedLoginFlow(credentials, password);
18191819
};
18201820

18211821
// returns a promise which resolves to the new MatrixClient
1822-
onRegistered(credentials: object) {
1822+
onRegistered(credentials: IMatrixClientCreds) {
18231823
return Lifecycle.setLoggedIn(credentials);
18241824
}
18251825

@@ -1905,7 +1905,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
19051905
* Note: SSO users (and any others using token login) currently do not pass through
19061906
* this, as they instead jump straight into the app after `attemptTokenLogin`.
19071907
*/
1908-
onUserCompletedLoginFlow = async (credentials: object, password: string) => {
1908+
onUserCompletedLoginFlow = async (credentials: IMatrixClientCreds, password: string) => {
19091909
this.accountPassword = password;
19101910
// self-destruct the password after 5mins
19111911
if (this.accountPasswordTimer !== null) clearTimeout(this.accountPasswordTimer);

0 commit comments

Comments
 (0)