diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index 9cba8e0da9..5689d84bc5 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,3 +32,9 @@ limitations under the License. padding: 10px; } +.mx_RestoreKeyBackupDialog_content > div { + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 110px; /* Empirically measured */ +} diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index dc82a71713..f1008dfcb0 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -59,6 +59,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { forceRecoveryKey: false, passPhrase: '', restoreType: null, + progress: { stage: "prefetch" }, }; } @@ -80,6 +81,12 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { }); } + _progressCallback = (data) => { + this.setState({ + progress: data, + }); + } + _onResetRecoveryClick = () => { this.props.onFinished(false); Modal.createTrackedDialogAsync('Key Backup', 'Key Backup', @@ -110,6 +117,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { // is the right one and restoring it is currently the only way we can do this. const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword( this.state.passPhrase, undefined, undefined, this.state.backupInfo, + { progressCallback: this._progressCallback }, ); if (this.props.keyCallback) { const key = await MatrixClientPeg.get().keyBackupKeyFromPassword( @@ -146,6 +154,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { try { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey( this.state.recoveryKey, undefined, undefined, this.state.backupInfo, + { progressCallback: this._progressCallback }, ); if (this.props.keyCallback) { const key = MatrixClientPeg.get().keyBackupKeyFromRecoveryKey(this.state.recoveryKey); @@ -185,6 +194,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { const recoverInfo = await accessSecretStorage(async () => { return MatrixClientPeg.get().restoreKeyBackupWithSecretStorage( this.state.backupInfo, + { progressCallback: this._progressCallback }, ); }); this.setState({ @@ -207,6 +217,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { undefined, /* targetRoomId */ undefined, /* targetSessionId */ backupInfo, + { progressCallback: this._progressCallback }, ); this.setState({ recoverInfo, @@ -272,8 +283,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let content; let title; if (this.state.loading) { - title = _t("Loading..."); - content = ; + title = _t("Restoring keys from backup"); + let details; + if (this.state.progress.stage === "fetch") { + details = _t("Fetching keys from server..."); + } else if (this.state.progress.stage === "load_keys") { + const { total, successes, failures } = this.state.progress; + details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures }); + } else if (this.state.progress.stage === "prefetch") { + details = _t("Fetching keys from server..."); + } + content =
+
{details}
+ +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -305,7 +328,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { content = _t("No backup found!"); } else if (this.state.recoverInfo) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); - title = _t("Backup restored"); + title = _t("Keys restored"); let failedToDecrypt; if (this.state.recoverInfo.total > this.state.recoverInfo.imported) { failedToDecrypt =

{_t( @@ -314,7 +337,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { )}

; } content =
-

{_t("Restored %(sessionCount)s session keys", {sessionCount: this.state.recoverInfo.imported})}

+

{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

{failedToDecrypt} -
+
{content}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b1ec616d67..4be143c523 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1797,6 +1797,9 @@ "Not a valid recovery key": "Not a valid recovery key", "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.", "If you've forgotten your recovery key you can .": "If you've forgotten your recovery key you can .", + "Restoring keys from backup": "Restoring keys from backup", + "Fetching keys from server...": "Fetching keys from server...", + "%(completed)s of %(total)s keys restored": "%(completed)s of %(total)s keys restored", "Unable to load backup status": "Unable to load backup status", "Recovery key mismatch": "Recovery key mismatch", "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.", @@ -1804,9 +1807,9 @@ "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.", "Unable to restore backup": "Unable to restore backup", "No backup found!": "No backup found!", - "Backup restored": "Backup restored", + "Keys restored": "Keys restored", "Failed to decrypt %(failedCount)s sessions!": "Failed to decrypt %(failedCount)s sessions!", - "Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys", + "Successfully restored %(sessionCount)s keys": "Successfully restored %(sessionCount)s keys", "Warning: you should only set up key backup from a trusted computer.": "Warning: you should only set up key backup from a trusted computer.", "Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Access your secure message history and set up secure messaging by entering your recovery passphrase.", "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options",