diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 80d0683bf9..cf7f4d4126 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -26,14 +26,15 @@ import Modal from '../../../../Modal'; import { promptForBackupPassphrase } from '../../../../CrossSigningManager'; const PHASE_LOADING = 0; -const PHASE_MIGRATE = 1; -const PHASE_PASSPHRASE = 2; -const PHASE_PASSPHRASE_CONFIRM = 3; -const PHASE_SHOWKEY = 4; -const PHASE_KEEPITSAFE = 5; -const PHASE_STORING = 6; -const PHASE_DONE = 7; -const PHASE_CONFIRM_SKIP = 8; +const PHASE_LOADERROR = 1; +const PHASE_MIGRATE = 2; +const PHASE_PASSPHRASE = 3; +const PHASE_PASSPHRASE_CONFIRM = 4; +const PHASE_SHOWKEY = 5; +const PHASE_KEEPITSAFE = 6; +const PHASE_STORING = 7; +const PHASE_DONE = 8; +const PHASE_CONFIRM_SKIP = 9; const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc. const PASSPHRASE_FEEDBACK_DELAY = 500; // How long after keystroke to offer passphrase feedback, ms. @@ -104,25 +105,29 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } async _fetchBackupInfo() { - const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); - const backupSigStatus = ( - // we may not have started crypto yet, in which case we definitely don't trust the backup - MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) - ); + try { + const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); + const backupSigStatus = ( + // we may not have started crypto yet, in which case we definitely don't trust the backup + MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) + ); - const { force } = this.props; - const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_PASSPHRASE; + const { force } = this.props; + const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_PASSPHRASE; - this.setState({ - phase, - backupInfo, - backupSigStatus, - }); + this.setState({ + phase, + backupInfo, + backupSigStatus, + }); - return { - backupInfo, - backupSigStatus, - }; + return { + backupInfo, + backupSigStatus, + }; + } catch (e) { + this.setState({phase: PHASE_LOADERROR}); + } } async _queryKeyUploadAuth() { @@ -133,8 +138,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { // no keys which would be a no-op. console.log("uploadDeviceSigningKeys unexpectedly succeeded without UI auth!"); } catch (error) { - if (!error.data.flows) { + if (!error.data || !error.data.flows) { console.log("uploadDeviceSigningKeys advertised no flows!"); + return; } const canUploadKeysWithPasswordOnly = error.data.flows.some(f => { return f.stages.length === 1 && f.stages[0] === 'm.login.password'; @@ -306,6 +312,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } } + _onLoadRetryClick = () => { + this.setState({phase: PHASE_LOADING}); + this._fetchBackupInfo(); + } + _onSkipSetupClick = () => { this.setState({phase: PHASE_CONFIRM_SKIP}); } @@ -676,6 +687,20 @@ export default class CreateSecretStorageDialog extends React.PureComponent { ; } + _renderPhaseLoadError() { + const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); + return
+

{_t("Unable to query secret storage status")}

+
+ +
+
; + } + _renderPhaseDone() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return
@@ -749,6 +774,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { case PHASE_LOADING: content = this._renderBusyPhase(); break; + case PHASE_LOADERROR: + content = this._renderPhaseLoadError(); + break; case PHASE_MIGRATE: content = this._renderPhaseMigrate(); break; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index be8f1a7a4a..8ba838d313 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2200,13 +2200,14 @@ "Print it and store it somewhere safe": "Print it and store it somewhere safe", "Save it on a USB key or backup drive": "Save it on a USB key or backup drive", "Copy it to your personal cloud storage": "Copy it to your personal cloud storage", + "Unable to query secret storage status": "Unable to query secret storage status", + "Retry": "Retry", "You can now verify your other devices, and other users to keep your chats safe.": "You can now verify your other devices, and other users to keep your chats safe.", "Upgrade your encryption": "Upgrade your encryption", "Confirm recovery passphrase": "Confirm recovery passphrase", "Make a copy of your recovery key": "Make a copy of your recovery key", "You're done!": "You're done!", "Unable to set up secret storage": "Unable to set up secret storage", - "Retry": "Retry", "We'll store an encrypted copy of your keys on our server. Secure your backup with a recovery passphrase.": "We'll store an encrypted copy of your keys on our server. Secure your backup with a recovery passphrase.", "For maximum security, this should be different from your account password.": "For maximum security, this should be different from your account password.", "Enter a recovery passphrase...": "Enter a recovery passphrase...",