Skip to content

Commit a92dd3b

Browse files
committed
wip
1 parent 12399c7 commit a92dd3b

2 files changed

Lines changed: 75 additions & 82 deletions

File tree

src/components/structures/MatrixChat.tsx

Lines changed: 67 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ import Markdown from "../../Markdown";
141141
import { sanitizeHtmlParams } from "../../Linkify";
142142
import { isOnlyAdmin } from "../../utils/membership";
143143
import { ModuleApi } from "../../modules/Api.ts";
144+
import { logErrorAndShowErrorDialog } from "../../utils/ErrorUtils.tsx";
144145

145146
// legacy export
146147
export { default as Views } from "../../Views";
@@ -408,61 +409,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
408409
*
409410
* {@link onWillStartClient} and {@link onClientStarted} will already have been called (but not necessarily
410411
* completed).
411-
*
412-
* This method either calls {@link onLiggedIn} directly, or switches to {@link Views.E2E_SETUP} or
413-
* {@link Views.COMPLETE_SECURITY}, which will later call {@link onCompleteSecurityE2eSetupFinished}.
414412
*/
415413
private async postLoginSetup(): Promise<void> {
416-
const cli = MatrixClientPeg.safeGet();
417-
const cryptoEnabled = Boolean(cli.getCrypto());
418-
if (!cryptoEnabled) {
419-
this.onLoggedIn();
420-
}
421-
422-
const promisesList: Promise<any>[] = [this.firstSyncPromise.promise];
423-
let crossSigningIsSetUp = false;
424-
if (cryptoEnabled) {
425-
// check if the user has previously published public cross-signing keys,
426-
// as a proxy to figure out if it's worth prompting the user to verify
427-
// from another device.
428-
promisesList.push(
429-
(async (): Promise<void> => {
430-
crossSigningIsSetUp = Boolean(await cli.getCrypto()?.userHasCrossSigningKeys());
431-
})(),
432-
);
433-
}
434-
414+
// TODO: move to onUserCompletedLoginFlow?
435415
// Now update the state to say we're waiting for the first sync to complete rather
436416
// than for the login to finish.
437417
this.setState({ pendingInitialSync: true });
438-
439-
await Promise.all(promisesList);
440-
441-
if (!cryptoEnabled) {
442-
this.setState({ pendingInitialSync: false });
443-
return;
444-
}
445-
446-
if (crossSigningIsSetUp) {
447-
// if the user has previously set up cross-signing, verify this device so we can fetch the
448-
// private keys.
449-
450-
const cryptoExtension = ModuleRunner.instance.extensions.cryptoSetup;
451-
if (cryptoExtension.SHOW_ENCRYPTION_SETUP_UI == false) {
452-
this.onLoggedIn();
453-
} else {
454-
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
455-
}
456-
} else if (!(await shouldSkipSetupEncryption(cli))) {
457-
// if cross-signing is not yet set up, do so now if possible.
458-
InitialCryptoSetupStore.sharedInstance().startInitialCryptoSetup(
459-
cli,
460-
this.onCompleteSecurityE2eSetupFinished,
461-
);
462-
this.setStateForNewView({ view: Views.E2E_SETUP });
463-
} else {
464-
this.onLoggedIn();
465-
}
418+
await this.firstSyncPromise.promise;
466419
this.setState({ pendingInitialSync: false });
467420
}
468421

@@ -472,6 +425,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
472425
| (Pick<IState, K> | IState | null),
473426
callback?: () => void,
474427
): void {
428+
if (state && "view" in state) {
429+
logger.log("Changing view from", this.state.view, "to", state.view);
430+
}
475431
if (this.shouldTrackPageChange(this.state, { ...this.state, ...state })) {
476432
this.startPageChangeTimer();
477433
}
@@ -643,6 +599,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
643599
private onAction = (payload: ActionPayload): void => {
644600
// once the session lock has been stolen, don't try to do anything.
645601
if (this.state.view === Views.LOCK_STOLEN) {
602+
logger.warn("Ignoring action as session lock has been stolen");
646603
return;
647604
}
648605

@@ -1378,10 +1335,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
13781335
/**
13791336
* Returns true if the user must go through the device verification process before they
13801337
* can use the app.
1381-
* @returns true if the user must verify
1338+
*
1339+
* @returns true if the device is unverified, but crypto is enabled.
13821340
*/
1383-
private async shouldForceVerification(): Promise<boolean> {
1384-
if (!SdkConfig.get("force_verification")) return false;
1341+
private async deviceNeedsVerification(): Promise<boolean> {
13851342
const mustVerifyFlag = localStorage.getItem("must_verify_device");
13861343
if (!mustVerifyFlag) return false;
13871344

@@ -1409,8 +1366,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14091366
ThemeController.isLogin = false;
14101367
this.themeWatcher?.recheck();
14111368
StorageManager.tryPersistStorage();
1412-
1413-
await this.onShowPostLoginScreen();
14141369
}
14151370

14161371
/**
@@ -1422,12 +1377,54 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14221377
* - by {@link onCompleteSecurityE2eSetupFinished}
14231378
*
14241379
* In other words, whenever we think we have completed the login and E2E setup tasks.
1380+
*
1381+
* TODO: fix docs
14251382
*/
1426-
private async onShowPostLoginScreen(): Promise<void> {
1383+
private async showNextPostLoginView(): Promise<void> {
1384+
const cli = MatrixClientPeg.safeGet();
1385+
1386+
// First of all, figure out if we need to do some cross-signing setup.
1387+
// Traditionally, we would only do that just after logging in, but with the advent of `force_verification`,
1388+
// we may need to do it on every restart.
1389+
if (
1390+
(this.state.view == Views.LOGIN ||
1391+
this.state.view == Views.REGISTER ||
1392+
SdkConfig.get("force_verification")) &&
1393+
!(await shouldSkipSetupEncryption(cli))
1394+
) {
1395+
const crypto = cli.getCrypto()!;
1396+
1397+
// Check if we need to create cross-signing keys for this user.
1398+
if (!(await crypto!.userHasCrossSigningKeys())) {
1399+
logger.info("showNextPostLoginScreen: user lacks cross-signing keys, starting setup");
1400+
InitialCryptoSetupStore.sharedInstance().startInitialCryptoSetup(
1401+
cli,
1402+
this.onCompleteSecurityE2eSetupFinished,
1403+
);
1404+
this.setStateForNewView({ view: Views.E2E_SETUP });
1405+
return;
1406+
}
1407+
1408+
// We have cross-signing keys, so see if we need to verify this device.
1409+
if (
1410+
ModuleRunner.instance.extensions.cryptoSetup.SHOW_ENCRYPTION_SETUP_UI &&
1411+
(await this.deviceNeedsVerification())
1412+
) {
1413+
logger.info("showNextPostLoginScreen: user must verify device, starting verification");
1414+
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
1415+
return;
1416+
}
1417+
}
1418+
1419+
// We've done the E2E setup stuff, so we can transition to the regular application, with
1420+
// an appropriate screen.
1421+
logger.info("showNextPostLoginScreen: E2E setup done, transitioning to logged in view.");
1422+
14271423
this.setStateForNewView({ view: Views.LOGGED_IN });
14281424
// If a specific screen is set to be shown after login, show that above
14291425
// all else, as it probably means the user clicked on something already.
14301426
if (this.screenAfterLogin?.screen) {
1427+
logger.info(`showNextPostLoginView: showing screen ${this.screenAfterLogin.screen}`);
14311428
this.showScreen(this.screenAfterLogin.screen, this.screenAfterLogin.params);
14321429
this.screenAfterLogin = undefined;
14331430
} else if (MatrixClientPeg.currentUserIsJustRegistered()) {
@@ -1436,6 +1433,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14361433
if (ThreepidInviteStore.instance.pickBestInvite()) {
14371434
// The user has a 3pid invite pending - show them that
14381435
const threepidInvite = ThreepidInviteStore.instance.pickBestInvite();
1436+
logger.info(`showNextPostLoginView: showing room ${threepidInvite.roomId} after registration`);
14391437

14401438
// HACK: This is a pretty brutal way of threading the invite back through
14411439
// our systems, but it's the safest we have for now.
@@ -1444,9 +1442,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14441442
} else {
14451443
// The user has just logged in after registering,
14461444
// so show the homepage.
1445+
logger.info("showNextPostLoginView: Showing home page after registration");
14471446
dis.dispatch<ViewHomePagePayload>({ action: Action.ViewHomePage, justRegistered: true });
14481447
}
14491448
} else {
1449+
logger.info("showNextPostLoginView: showScreenAfterLogin");
14501450
this.showScreenAfterLogin();
14511451
}
14521452

@@ -1510,15 +1510,19 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
15101510
// If screenAfterLogin is set, use that, then null it so that a second login will
15111511
// result in view_home_page, _user_settings or _room_directory
15121512
if (this.screenAfterLogin && this.screenAfterLogin.screen) {
1513+
logger.info(`showScreenAfterLogin: showing screen ${this.screenAfterLogin.screen}`);
15131514
this.showScreen(this.screenAfterLogin.screen, this.screenAfterLogin.params);
15141515
this.screenAfterLogin = undefined;
15151516
} else if (localStorage && localStorage.getItem("mx_last_room_id")) {
15161517
// Before defaulting to directory, show the last viewed room
1518+
logger.info(`showScreenAfterLogin: showing last room`);
15171519
this.viewLastRoom();
15181520
} else {
15191521
if (MatrixClientPeg.safeGet().isGuest()) {
1522+
logger.info(`showScreenAfterLogin: showing guest welcome page`);
15201523
dis.dispatch({ action: "view_welcome_page" });
15211524
} else {
1525+
logger.info(`showScreenAfterLogin: showing home page`);
15221526
dis.dispatch({ action: Action.ViewHomePage });
15231527
}
15241528
}
@@ -1759,18 +1763,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
17591763
*/
17601764
private async onClientStarted(): Promise<void> {
17611765
const cli = MatrixClientPeg.safeGet();
1762-
1763-
const shouldForceVerification = await this.shouldForceVerification();
1764-
// XXX: Don't replace the screen if it's already one of these: postLoginSetup
1765-
// changes to these screens in certain circumstances so we shouldn't clobber it.
1766-
// We should probably have one place where we decide what the next screen is after
1767-
// login.
1768-
if (![Views.COMPLETE_SECURITY, Views.E2E_SETUP].includes(this.state.view)) {
1769-
if (shouldForceVerification) {
1770-
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
1771-
}
1772-
}
1773-
17741766
const crypto = cli.getCrypto();
17751767
if (crypto) {
17761768
const blacklistEnabled = SettingsStore.getValueAt(SettingLevel.DEVICE, "blacklistUnverifiedDevices");
@@ -1786,6 +1778,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
17861778
this.setState({
17871779
ready: true,
17881780
});
1781+
1782+
await this.showNextPostLoginView();
17891783
}
17901784

17911785
public showScreen(screen: string, params?: { [key: string]: any }): void {
@@ -1796,6 +1790,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
17961790
dis.dispatch({ action: Action.ViewHomePage });
17971791
return;
17981792
}
1793+
logger.info(`showScreen ${screen}`);
17991794

18001795
if (screen === "register") {
18011796
dis.dispatch({
@@ -2088,20 +2083,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
20882083
};
20892084

20902085
/** Called when {@link Views.E2E_SETUP} or {@link Views.COMPLETE_SECURITY} have completed. */
2091-
private onCompleteSecurityE2eSetupFinished = async (): Promise<void> => {
2092-
const forceVerify = await this.shouldForceVerification();
2093-
if (forceVerify) {
2094-
const isVerified = await MatrixClientPeg.safeGet().getCrypto()?.isCrossSigningReady();
2095-
if (!isVerified) {
2096-
// We must verify but we haven't yet verified - don't continue logging in
2097-
return;
2098-
}
2099-
}
2100-
2101-
await this.onShowPostLoginScreen().catch((e) => {
2102-
logger.error("Exception showing post-login screen", e);
2086+
private onCompleteSecurityE2eSetupFinished(): void {
2087+
this.showNextPostLoginView().catch((e) => {
2088+
logErrorAndShowErrorDialog("Exception showing post-login screen", e);
21032089
});
2104-
};
2090+
}
21052091

21062092
private getFragmentAfterLogin(): string {
21072093
let fragmentAfterLogin = "";

src/dispatcher/dispatcher.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
88
Please see LICENSE files in the repository root for full details.
99
*/
1010

11-
import { type Action } from "./actions";
11+
import { Action } from "./actions";
1212
import { type ActionPayload, AsyncActionPayload } from "./payloads";
13+
import { logger } from "matrix-js-sdk/src/logger";
1314

1415
type DispatchToken = string;
1516

@@ -82,6 +83,12 @@ export class MatrixDispatcher {
8283
*/
8384
// eslint-disable-next-line @typescript-eslint/naming-convention
8485
private _dispatch = (payload: ActionPayload): void => {
86+
// Log all actions, except a few spammy ones
87+
if (payload.action !== Action.UserActivity) {
88+
// XXX fixme too much data
89+
logger.info(`Dispatch action ${payload.action}`, payload);
90+
}
91+
8592
invariant(!this.isDispatching(), "Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.");
8693
this.startDispatching(payload);
8794
try {

0 commit comments

Comments
 (0)