Documentation for initialisation/login code (#31297)

* Documentation in MatrixChat and Lifecycle

* State transition diagram for `View`
This commit is contained in:
Richard van der Hoff 2025-11-21 14:58:03 +00:00 committed by GitHub
parent fbb43d5e61
commit b679693702
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 130 additions and 3 deletions

View file

@ -599,6 +599,9 @@ async function abortLogin(): Promise<void> {
}
/** Attempt to restore the session from localStorage or indexeddb.
*
* If the credentials are found, and the session is successfully restored,
* emits {@link Action.OnLoggedIn}, {@link Action.WillStartClient} and {@link Action.StartedClient}.
*
* @returns true if a session was found; false if no existing session was found.
*
@ -787,6 +790,8 @@ async function createOidcTokenRefresher(credentials: IMatrixClientCreds): Promis
* optionally clears localstorage, persists new credentials
* to localstorage, starts the new client.
*
* Emits {@link Action.OnLoggedIn}, {@link Action.WillStartClient} and {@link Action.StartedClient}.
*
* @param {IMatrixClientCreds} credentials The credentials to use
* @param {Boolean} clearStorageEnabled True to clear storage before starting the new client
* @param {Boolean} isFreshLogin True if this is a fresh login, false if it is previous session being restored
@ -1019,6 +1024,12 @@ export function isLoggingOut(): boolean {
* Starts the matrix client and all other react-sdk services that
* listen for events while a session is logged in.
*
* By the time this method is called, we have successfully logged in if necessary, and the client has been set up with
* the access token.
*
* Emits {@link Acction.WillStartClient} before starting the client, and {@link Action.ClientStarted} when the client has
* been started.
*
* @param client the matrix client to start
* @param startSyncing - `true` to actually start syncing the client.
* @param clientPegOpts - Options to pass through to {@link MatrixClientPeg.start}.

View file

@ -6,7 +6,76 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
/** constants for MatrixChat.state.view */
/**
* Constants for MatrixChat.state.view.
*
* The `View` is the primary state machine of the application: it has different states for the various setup flows
* that the user may find themselves in. Once we have a functioning client, we can transition to the `LOGGED_IN` state
* which is the "normal" state of the application.
*
* An incomplete state transition diagram follows.
*
* (initial state)
* Lock held by other instance
* LOADING CONFIRM_LOCK_
* THEFT
* Lock theft confirmed
* Session recovered
*
* No previous session
* Token/OIDC login succeeded
*
*
* WELCOME (from all other states
* except LOCK_STOLEN)
*
* "Create Account" "Sign in" Client logged out
*
*
*
* "Create an ▼ ▼ "Forgot
* account" ┌─────────────────┐ password"
* REGISTER LOGIN FORGOT_PASSWORD
*
* "Sign in here" Complete /
* "Sign in instead"
*
*
*
*
* (postLoginSetup)
*
*
* E2EE not enabled
* Account has Account lacks
* cross-signing cross-signing
* keys keys
* Client started and
* force_verification
* pending COMPLETE_ E2E_SETUP
* SECURITY
* "Forgotten
* your
* password?"
*
* (from all other states
* except LOCK_STOLEN)
*
* Soft logout error
*
* LOGGED_IN Re-authentication succeeded SOFT_LOGOUT
*
*
*
* (from all other states)
*
* Session lock stolen
*
*
* LOCK_STOLEN
*
*
*/
enum Views {
// a special initial state which is only used at startup, while we are
// trying to re-animate a matrix client or register as a guest.

View file

@ -202,7 +202,10 @@ interface IState {
hideToSRUsers: boolean;
syncError: Error | null;
serverConfig?: ValidatedServerConfig;
/** Has our MatrixClient started? */
ready: boolean;
threepidInvite?: IThreepidInvite;
roomOobData?: object;
pendingInitialSync?: boolean;
@ -225,7 +228,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
private firstSyncPromise: PromiseWithResolvers<void>;
private screenAfterLogin?: IScreen;
/** True if we have successfully completed an OIDC or token login.
*
* XXX it's unclear if this is ever cleared, so what happens if the user logs out and then logs back in?
*/
private tokenLogin?: boolean;
// What to focus on next component update, if anything
private focusNext: FocusNextType;
private subTitleStatus: string;
@ -386,6 +395,26 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
await Lifecycle.onSessionLockStolen();
}
/**
* Perform actions that are specific to a user that has just logged in (compare {@link onLoggedIn}, which, despite
* its name, is called when an already-logged-in client is restored at session startup).
*
* Called when:
*
* - We successfully completed an OIDC or token login, via {@link initSession}.
* - The {@link Login} or {@link Register} components notify us that we successfully completed a non-OIDC login or
* registration.
*
* In both cases, {@link Action.OnLoggedIn} will already have been emitted, but the call to {@link onLoggedIn} will
* have been suppressed (by either {@link tokenLogin} being set, or the view being set to {@link Views.LOGIN} or
* {@link Views.REGISTER}).
*
* {@link onWillStartClient} and {@link onClientStarted} will already have been called (but not necessarily
* completed).
*
* This method either calls {@link onLiggedIn} directly, or switches to {@link Views.E2E_SETUP} or
* {@link Views.COMPLETE_SECURITY}, which will later call {@link onCompleteSecurityE2eSetupFinished}.
*/
private async postLoginSetup(): Promise<void> {
const cli = MatrixClientPeg.safeGet();
const cryptoEnabled = Boolean(cli.getCrypto());
@ -1369,7 +1398,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}
/**
* Called when a new logged in session has started
* Called when a new logged in session has started.
*
* Called:
*
* - on {@link Action.OnLoggedIn}, but only when we don't expect a separate call to {@link postLoginSetup}.
* - from {@link postLoginSetup}, when we don't have crypto setup tasks to perform after the login.
*
* It's never actually called if we have crypto setup tasks to perform after login (which we normally do, unless
* crypto is disabled.) XXX: is this a bug or a feature?
*/
private async onLoggedIn(): Promise<void> {
ThemeController.isLogin = false;
@ -1379,6 +1416,16 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
await this.onShowPostLoginScreen();
}
/**
* Show the first screen after the application is successfully loaded in a logged-in state.
*
* Called:
*
* - by {@link onLoggedIn}
* - by {@link onCompleteSecurityE2eSetupFinished}
*
* In other words, whenever we think we have completed the login and E2E setup tasks.
*/
private async onShowPostLoginScreen(): Promise<void> {
this.setStateForNewView({ view: Views.LOGGED_IN });
// If a specific screen is set to be shown after login, show that above
@ -2043,7 +2090,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
PerformanceMonitor.instance.stop(PerformanceEntryNames.REGISTER);
};
// complete security / e2e setup has finished
/** Called when {@link Views.E2E_SETUP} or {@link Views.COMPLETE_SECURITY} have completed. */
private onCompleteSecurityE2eSetupFinished = async (): Promise<void> => {
const forceVerify = await this.shouldForceVerification();
if (forceVerify) {