From 7ef3b446f4fcb587ef071f6de8ad8aba14ad3d05 Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 27 Apr 2020 16:58:24 +0100 Subject: [PATCH 1/5] Show progress when loading keys --- .../keybackup/RestoreKeyBackupDialog.js | 25 ++++++++++++++++++- src/i18n/strings/en_EN.json | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index dc82a71713..92d23f9e65 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, @@ -273,7 +284,19 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let title; if (this.state.loading) { title = _t("Loading..."); - content = ; + let details; + if (this.state.progress.stage === "fetch") { + details = _t("Downloading from server..."); + } else if (this.state.progress.stage === "load_keys") { + const { total, successes, failures } = this.state.progress; + details = _t("Loaded %(completed)s of %(total)s", { total, completed: successes + failures }); + } else if (this.state.progress.stage === "prefetch") { + details = _t("Requesting from server..."); + } + content =
+
{details}
+ +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5544e3a8b1..992ace1e92 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1794,6 +1794,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 .", + "Downloading from server": "Downloading from server", + "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", + "Requesting from server...": "Requesting from server...", "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.", From b7bcf25cfab8539c172f36b6ee331eaa06488426 Mon Sep 17 00:00:00 2001 From: Zoe Date: Tue, 28 Apr 2020 11:36:28 +0100 Subject: [PATCH 2/5] i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 992ace1e92..3fd9951cfe 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1794,7 +1794,7 @@ "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 .", - "Downloading from server": "Downloading from server", + "Downloading from server...": "Downloading from server...", "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", "Requesting from server...": "Requesting from server...", "Unable to load backup status": "Unable to load backup status", From 3dbcc9fe9957289eb7f0d78ff75545885078f9a2 Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 14:14:39 +0100 Subject: [PATCH 3/5] copy changes --- .../dialogs/keybackup/RestoreKeyBackupDialog.js | 12 ++++++------ src/i18n/strings/en_EN.json | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 92d23f9e65..da67fb9777 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -283,15 +283,15 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let content; let title; if (this.state.loading) { - title = _t("Loading..."); + title = _t("Restoring keys from backup"); let details; if (this.state.progress.stage === "fetch") { - details = _t("Downloading from server..."); + details = _t("Fetching keys from server..."); } else if (this.state.progress.stage === "load_keys") { const { total, successes, failures } = this.state.progress; - details = _t("Loaded %(completed)s of %(total)s", { total, completed: successes + failures }); + details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures }); } else if (this.state.progress.stage === "prefetch") { - details = _t("Requesting from server..."); + details = _t("Fetching keys from server..."); } content =
{details}
@@ -328,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( @@ -337,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} set up new recovery options.": "If you've forgotten your recovery key you can .", - "Downloading from server...": "Downloading from server...", - "Loaded %(completed)s of %(total)s": "Loaded %(completed)s of %(total)s", - "Requesting from server...": "Requesting from server...", + "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 +1804,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", From 1afb09d2574dfced61baa3aeafe7881329b712ea Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 14:29:36 +0100 Subject: [PATCH 4/5] Fixed the dialog height --- .../keybackup/_RestoreKeyBackupDialog.scss | 6 +++++ .../keybackup/RestoreKeyBackupDialog.js | 26 +++++++++---------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index 9cba8e0da9..d74224c94d 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 { + 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 da67fb9777..9829f7af8e 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -293,10 +293,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { } else if (this.state.progress.stage === "prefetch") { details = _t("Fetching keys from server..."); } - content =
+ content = <>
{details}
-
; + ; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -304,20 +304,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { title = _t("Recovery key mismatch"); - content =
+ content = <>

{_t( "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

-
; + ; } else { title = _t("Incorrect recovery passphrase"); - content =
+ content = <>

{_t( "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

-
; + ; } } else { title = _t("Error"); @@ -336,7 +336,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, )}

; } - content =
+ content = <>

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

{failedToDecrypt} -
; + ; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); title = _t("Enter recovery passphrase"); - content =
+ content = <>

{_t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, @@ -394,7 +394,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} -

; + ; } else { title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -413,7 +413,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
; } - content =
+ content = <>

{_t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, @@ -450,7 +450,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} -

; + ; } return ( @@ -458,7 +458,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { onFinished={this.props.onFinished} title={title} > -
+
{content}
From 64c70b2de09ca3cb3c7124f44a1c94f812243418 Mon Sep 17 00:00:00 2001 From: Zoe Date: Wed, 29 Apr 2020 15:10:23 +0100 Subject: [PATCH 5/5] fragments and i18n don't play nice together --- .../keybackup/_RestoreKeyBackupDialog.scss | 2 +- .../keybackup/RestoreKeyBackupDialog.js | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss index d74224c94d..5689d84bc5 100644 --- a/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss +++ b/res/css/views/dialogs/keybackup/_RestoreKeyBackupDialog.scss @@ -32,7 +32,7 @@ limitations under the License. padding: 10px; } -.mx_RestoreKeyBackupDialog_content { +.mx_RestoreKeyBackupDialog_content > div { display: flex; flex-direction: column; justify-content: space-between; diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 9829f7af8e..f1008dfcb0 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -293,10 +293,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { } else if (this.state.progress.stage === "prefetch") { details = _t("Fetching keys from server..."); } - content = <> + content =
{details}
- ; +
; } else if (this.state.loadError) { title = _t("Error"); content = _t("Unable to load backup status"); @@ -304,20 +304,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { title = _t("Recovery key mismatch"); - content = <> + content =

{_t( "Backup could not be decrypted with this recovery key: " + "please verify that you entered the correct recovery key.", )}

- ; +
; } else { title = _t("Incorrect recovery passphrase"); - content = <> + content =

{_t( "Backup could not be decrypted with this recovery passphrase: " + "please verify that you entered the correct recovery passphrase.", )}

- ; +
; } } else { title = _t("Error"); @@ -336,7 +336,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, )}

; } - content = <> + content =

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

{failedToDecrypt} - ; +
; } else if (backupHasPassphrase && !this.state.forceRecoveryKey) { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); title = _t("Enter recovery passphrase"); - content = <> + content =

{_t( "Warning: you should only set up key backup " + "from a trusted computer.", {}, @@ -394,7 +394,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} - ; +

; } else { title = _t("Enter recovery key"); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -413,7 +413,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
; } - content = <> + content =

{_t( "Warning: You should only set up key backup " + "from a trusted computer.", {}, @@ -450,7 +450,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {s} , })} - ; +

; } return (