@@ -141,6 +141,7 @@ import Markdown from "../../Markdown";
141141import { sanitizeHtmlParams } from "../../Linkify" ;
142142import { isOnlyAdmin } from "../../utils/membership" ;
143143import { ModuleApi } from "../../modules/Api.ts" ;
144+ import { logErrorAndShowErrorDialog } from "../../utils/ErrorUtils.tsx" ;
144145
145146// legacy export
146147export { 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 = "" ;
0 commit comments