From ea99eebb7bfbca43b6726742f8ae4ef7e5f4cf41 Mon Sep 17 00:00:00 2001 From: Zoe Date: Tue, 17 Mar 2020 10:20:58 +0000 Subject: [PATCH] Report to the user when a key signature upload fails --- src/components/structures/MatrixChat.js | 10 ++ .../dialogs/KeySignatureUploadFailedDialog.js | 108 ++++++++++++++++++ src/i18n/strings/en_EN.json | 10 ++ 3 files changed, 128 insertions(+) create mode 100644 src/components/views/dialogs/KeySignatureUploadFailedDialog.js diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index f1a5a372be..e3a239663e 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1495,6 +1495,16 @@ export default createReactClass({ } }); + cli.on("crypto.keySignatureUploadFailure", (failures, source, continuation) => { + const KeySignatureUploadFailedDialog = + sdk.getComponent('views.dialogs.KeySignatureUploadFailedDialog'); + Modal.createTrackedDialog( + 'Failed to upload key signatures', + 'Failed to upload key signatures', + KeySignatureUploadFailedDialog, + { failures, source, continuation }); + }); + cli.on("crypto.verification.request", request => { const isFlagOn = SettingsStore.isFeatureEnabled("feature_cross_signing"); diff --git a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js b/src/components/views/dialogs/KeySignatureUploadFailedDialog.js new file mode 100644 index 0000000000..a04c4a389f --- /dev/null +++ b/src/components/views/dialogs/KeySignatureUploadFailedDialog.js @@ -0,0 +1,108 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, {useState, useCallback, useRef} from 'react'; +import * as sdk from '../../../index'; +import { _t } from '../../../languageHandler'; + +export default function KeySignatureUploadFailedDialog({ + failures, + source, + continuation, + onFinished, + }) { + const RETRIES = 2; + const BaseDialog = sdk.getComponent('dialogs.BaseDialog'); + const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); + const Spinner = sdk.getComponent('elements.Spinner'); + const [retry, setRetry] = useState(RETRIES); + const [cancelled, setCancelled] = useState(false); + const [retrying, setRetrying] = useState(false); + const [success, setSuccess] = useState(false); + const onCancel = useRef(onFinished); + + const causes = new Map([ + ["_afterCrossSigningLocalKeyChange", _t("a new master key signature")], + ["checkOwnCrossSigningTrust", _t("a new cross-signing key signature")], + ["setDeviceVerification", _t("a device cross-signing signature")], + ]); + const defaultCause = _t("a key signature"); + + const onRetry = useCallback(async () => { + try { + setRetrying(true); + const cancel = new Promise((resolve, reject) => { + onCancel.current = reject; + }).finally(() => { + setCancelled(true); + }); + await Promise.race([ + continuation(), + cancel, + ]); + setSuccess(true); + } catch (e) { + setRetry(r => r-1); + } finally { + onCancel.current = onFinished; + setRetrying(false); + } + }, [continuation, onFinished]); + + let body; + if (!success && !cancelled && continuation && retry > 0) { + const reason = causes.get(source) || defaultCause; + + body = (
+

{_t("Riot encountered an error during upload of:")}

+

{reason}

+ {retrying && } +
{JSON.stringify(failures, null, 2)}
+ +
); + } else { + body = (
+ {success ? + {_t("Upload completed")} : + cancelled ? + {_t("Cancelled signature upload")} : + {_t("Unabled to upload")}} + +
); + } + + return ( + {}} + > + {body} + + ); +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5f3ead1490..971e6037e4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1577,6 +1577,16 @@ "Ignore request": "Ignore request", "Loading session info...": "Loading session info...", "Encryption key request": "Encryption key request", + "a new master key signature": "a new master key signature", + "a new cross-signing key signature": "a new cross-signing key signature", + "a device cross-signing signature": "a device cross-signing signature", + "a key signature": "a key signature", + "Riot encountered an error during upload of:": "Riot encountered an error during upload of:", + "Upload completed": "Upload completed", + "Cancelled signature upload": "Cancelled signature upload", + "Unabled to upload": "Unabled to upload", + "Signature upload success": "Signature upload success", + "Signature upload failed": "Signature upload failed", "You've previously used Riot on %(host)s with lazy loading of members enabled. In this version lazy loading is disabled. As the local cache is not compatible between these two settings, Riot needs to resync your account.": "You've previously used Riot on %(host)s with lazy loading of members enabled. In this version lazy loading is disabled. As the local cache is not compatible between these two settings, Riot needs to resync your account.", "If the other version of Riot is still open in another tab, please close it as using Riot on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "If the other version of Riot is still open in another tab, please close it as using Riot on the same host with both lazy loading enabled and disabled simultaneously will cause issues.", "Incompatible local cache": "Incompatible local cache",