@@ -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" ;
@@ -411,61 +412,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
411412 *
412413 * {@link onWillStartClient} and {@link onClientStarted} will already have been called (but not necessarily
413414 * completed).
414- *
415- * This method either calls {@link onLiggedIn} directly, or switches to {@link Views.E2E_SETUP} or
416- * {@link Views.COMPLETE_SECURITY}, which will later call {@link onCompleteSecurityE2eSetupFinished}.
417415 */
418416 private async postLoginSetup ( ) : Promise < void > {
419- const cli = MatrixClientPeg . safeGet ( ) ;
420- const cryptoEnabled = Boolean ( cli . getCrypto ( ) ) ;
421- if ( ! cryptoEnabled ) {
422- this . onLoggedIn ( ) ;
423- }
424-
425- const promisesList : Promise < any > [ ] = [ this . firstSyncPromise . promise ] ;
426- let crossSigningIsSetUp = false ;
427- if ( cryptoEnabled ) {
428- // check if the user has previously published public cross-signing keys,
429- // as a proxy to figure out if it's worth prompting the user to verify
430- // from another device.
431- promisesList . push (
432- ( async ( ) : Promise < void > => {
433- crossSigningIsSetUp = Boolean ( await cli . getCrypto ( ) ?. userHasCrossSigningKeys ( ) ) ;
434- } ) ( ) ,
435- ) ;
436- }
437-
417+ // TODO: move to onUserCompletedLoginFlow?
438418 // Now update the state to say we're waiting for the first sync to complete rather
439419 // than for the login to finish.
440420 this . setState ( { pendingInitialSync : true } ) ;
441-
442- await Promise . all ( promisesList ) ;
443-
444- if ( ! cryptoEnabled ) {
445- this . setState ( { pendingInitialSync : false } ) ;
446- return ;
447- }
448-
449- if ( crossSigningIsSetUp ) {
450- // if the user has previously set up cross-signing, verify this device so we can fetch the
451- // private keys.
452-
453- const cryptoExtension = ModuleRunner . instance . extensions . cryptoSetup ;
454- if ( cryptoExtension . SHOW_ENCRYPTION_SETUP_UI == false ) {
455- this . onLoggedIn ( ) ;
456- } else {
457- this . setStateForNewView ( { view : Views . COMPLETE_SECURITY } ) ;
458- }
459- } else if ( ! ( await shouldSkipSetupEncryption ( cli ) ) ) {
460- // if cross-signing is not yet set up, do so now if possible.
461- InitialCryptoSetupStore . sharedInstance ( ) . startInitialCryptoSetup (
462- cli ,
463- this . onCompleteSecurityE2eSetupFinished ,
464- ) ;
465- this . setStateForNewView ( { view : Views . E2E_SETUP } ) ;
466- } else {
467- this . onLoggedIn ( ) ;
468- }
421+ await this . firstSyncPromise . promise ;
469422 this . setState ( { pendingInitialSync : false } ) ;
470423 }
471424
@@ -1385,10 +1338,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
13851338 /**
13861339 * Returns true if the user must go through the device verification process before they
13871340 * can use the app.
1388- * @returns true if the user must verify
1341+ *
1342+ * @returns true if the device is unverified, but crypto is enabled.
13891343 */
1390- private async shouldForceVerification ( ) : Promise < boolean > {
1391- if ( ! SdkConfig . get ( "force_verification" ) ) return false ;
1344+ private async deviceNeedsVerification ( ) : Promise < boolean > {
13921345 const mustVerifyFlag = localStorage . getItem ( "must_verify_device" ) ;
13931346 if ( ! mustVerifyFlag ) return false ;
13941347
@@ -1416,8 +1369,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14161369 ThemeController . isLogin = false ;
14171370 this . themeWatcher ?. recheck ( ) ;
14181371 StorageManager . tryPersistStorage ( ) ;
1419-
1420- await this . onShowPostLoginScreen ( ) ;
14211372 }
14221373
14231374 /**
@@ -1429,15 +1380,55 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14291380 * - by {@link onCompleteSecurityE2eSetupFinished}
14301381 *
14311382 * In other words, whenever we think we have completed the login and E2E setup tasks.
1383+ *
1384+ * TODO: fix docs
14321385 */
1433- private async onShowPostLoginScreen ( ) : Promise < void > {
1434- logger . debug ( "onShowPostLoginScreen: Transitioning to logged in view." ) ;
1386+ private async showNextView ( ) : Promise < void > {
1387+ const cli = MatrixClientPeg . safeGet ( ) ;
1388+
1389+ const forceVerification = SdkConfig . get ( "force_verification" ) ;
1390+ logger . debug ( `showNextView: current view=${ this . state . view } ; force_verification=${ forceVerification } ` ) ;
1391+
1392+ // First of all, figure out if we need to do some cross-signing setup.
1393+ // Traditionally, we would only do that just after logging in, but with the advent of `force_verification`,
1394+ // we may need to do it on every restart.
1395+ if (
1396+ ( this . state . view == Views . LOGIN || this . state . view == Views . REGISTER || forceVerification ) &&
1397+ ! ( await shouldSkipSetupEncryption ( cli ) )
1398+ ) {
1399+ const crypto = cli . getCrypto ( ) ! ;
1400+
1401+ // Check if we need to create cross-signing keys for this user.
1402+ if ( ! ( await crypto ! . userHasCrossSigningKeys ( ) ) ) {
1403+ logger . debug ( "showNextView: user lacks cross-signing keys, starting setup" ) ;
1404+ InitialCryptoSetupStore . sharedInstance ( ) . startInitialCryptoSetup (
1405+ cli ,
1406+ this . onCompleteSecurityE2eSetupFinished ,
1407+ ) ;
1408+ this . setStateForNewView ( { view : Views . E2E_SETUP } ) ;
1409+ return ;
1410+ }
1411+
1412+ // We have cross-signing keys, so see if we need to verify this device.
1413+ if (
1414+ ModuleRunner . instance . extensions . cryptoSetup . SHOW_ENCRYPTION_SETUP_UI &&
1415+ ( await this . deviceNeedsVerification ( ) )
1416+ ) {
1417+ logger . debug ( "showNextView: user must verify device, starting verification" ) ;
1418+ this . setStateForNewView ( { view : Views . COMPLETE_SECURITY } ) ;
1419+ return ;
1420+ }
1421+ }
1422+
1423+ // We've done the E2E setup stuff, so we can transition to the regular application, with
1424+ // an appropriate screen.
1425+ logger . debug ( "showNextView: E2E setup done, transitioning to logged in view." ) ;
14351426
14361427 this . setStateForNewView ( { view : Views . LOGGED_IN } ) ;
14371428 // If a specific screen is set to be shown after login, show that above
14381429 // all else, as it probably means the user clicked on something already.
14391430 if ( this . screenAfterLogin ?. screen ) {
1440- logger . debug ( `onShowPostLoginScreen : showing screen ${ this . screenAfterLogin . screen } ` ) ;
1431+ logger . debug ( `showNextView : showing screen ${ this . screenAfterLogin . screen } ` ) ;
14411432 this . showScreen ( this . screenAfterLogin . screen , this . screenAfterLogin . params ) ;
14421433 this . screenAfterLogin = undefined ;
14431434 } else if ( MatrixClientPeg . currentUserIsJustRegistered ( ) ) {
@@ -1446,7 +1437,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14461437 if ( ThreepidInviteStore . instance . pickBestInvite ( ) ) {
14471438 // The user has a 3pid invite pending - show them that
14481439 const threepidInvite = ThreepidInviteStore . instance . pickBestInvite ( ) ;
1449- logger . debug ( `onShowPostLoginScreen : showing room ${ threepidInvite . roomId } after registration` ) ;
1440+ logger . debug ( `showNextView : showing room ${ threepidInvite . roomId } after registration` ) ;
14501441
14511442 // HACK: This is a pretty brutal way of threading the invite back through
14521443 // our systems, but it's the safest we have for now.
@@ -1455,11 +1446,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
14551446 } else {
14561447 // The user has just logged in after registering,
14571448 // so show the homepage.
1458- logger . debug ( "onShowPostLoginScreen : Showing home page after registration" ) ;
1449+ logger . debug ( "showNextView : Showing home page after registration" ) ;
14591450 dis . dispatch < ViewHomePagePayload > ( { action : Action . ViewHomePage , justRegistered : true } ) ;
14601451 }
14611452 } else {
1462- logger . debug ( "onShowPostLoginScreen : showScreenAfterLogin" ) ;
1453+ logger . debug ( "showNextView : showScreenAfterLogin" ) ;
14631454 this . showScreenAfterLogin ( ) ;
14641455 }
14651456
@@ -1776,18 +1767,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
17761767 */
17771768 private async onClientStarted ( ) : Promise < void > {
17781769 const cli = MatrixClientPeg . safeGet ( ) ;
1779-
1780- const shouldForceVerification = await this . shouldForceVerification ( ) ;
1781- // XXX: Don't replace the screen if it's already one of these: postLoginSetup
1782- // changes to these screens in certain circumstances so we shouldn't clobber it.
1783- // We should probably have one place where we decide what the next screen is after
1784- // login.
1785- if ( ! [ Views . COMPLETE_SECURITY , Views . E2E_SETUP ] . includes ( this . state . view ) ) {
1786- if ( shouldForceVerification ) {
1787- this . setStateForNewView ( { view : Views . COMPLETE_SECURITY } ) ;
1788- }
1789- }
1790-
17911770 const crypto = cli . getCrypto ( ) ;
17921771 if ( crypto ) {
17931772 const blacklistEnabled = SettingsStore . getValueAt ( SettingLevel . DEVICE , "blacklistUnverifiedDevices" ) ;
@@ -1803,6 +1782,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
18031782 this . setState ( {
18041783 ready : true ,
18051784 } ) ;
1785+
1786+ await this . showNextView ( ) ;
18061787 }
18071788
18081789 public showScreen ( screen : string , params ?: { [ key : string ] : any } ) : void {
@@ -2110,18 +2091,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
21102091 } ;
21112092
21122093 /** Called when {@link Views.E2E_SETUP} or {@link Views.COMPLETE_SECURITY} have completed. */
2113- private onCompleteSecurityE2eSetupFinished = async ( ) : Promise < void > => {
2114- const forceVerify = await this . shouldForceVerification ( ) ;
2115- if ( forceVerify ) {
2116- const isVerified = await MatrixClientPeg . safeGet ( ) . getCrypto ( ) ?. isCrossSigningReady ( ) ;
2117- if ( ! isVerified ) {
2118- // We must verify but we haven't yet verified - don't continue logging in
2119- return ;
2120- }
2121- }
2122-
2123- await this . onShowPostLoginScreen ( ) . catch ( ( e ) => {
2124- logger . error ( "Exception showing post-login screen" , e ) ;
2094+ private onCompleteSecurityE2eSetupFinished = ( ) : void => {
2095+ this . showNextView ( ) . catch ( ( e ) => {
2096+ logErrorAndShowErrorDialog ( "Exception showing post-login screen" , e ) ;
21252097 } ) ;
21262098 } ;
21272099
0 commit comments