From 3e8599bba02886acd927d0cfbaa0de3e0098289b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:27:14 +0100 Subject: [PATCH] AccessSecretStorageDialog: various fixes (#30093) * AccessSecretStorageDialog: clear notice when input is empty * AccessSecretStorageDialog: Simplify logic for calculating feedback No functional changes, just simplification * AccessSecretStorageDialog: use the right icon Should be a ! in a circle, not an X. Also requires use of `Flex` to fix the vertical alignment. * AccessSecretStorageDialog: fix resizing when key is correct * AccessSecretStorageDialog: remove confirmation on dialog close Per discussion on https://github.com/element-hq/element-web/issues/30024, we don't want this any more. --- .../security/_AccessSecretStorageDialog.pcss | 2 +- src/SecurityManager.ts | 23 ---------- .../security/AccessSecretStorageDialog.tsx | 44 ++++++++++--------- src/i18n/strings/en_EN.json | 2 - .../AccessSecretStorageDialog-test.tsx | 28 +++++++++--- 5 files changed, 47 insertions(+), 52 deletions(-) diff --git a/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss b/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss index 943ec3a41f..9d81097d60 100644 --- a/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss +++ b/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss @@ -32,7 +32,7 @@ Please see LICENSE files in the repository root for full details. color: $alert; &::before { - mask-image: url("@vector-im/compound-design-tokens/icons/close.svg"); + mask-image: url("@vector-im/compound-design-tokens/icons/error-solid.svg"); background-color: $alert; } } diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index b497c57a10..bfd0eb237d 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -19,7 +19,6 @@ import AccessSecretStorageDialog, { type KeyParams, } from "./components/views/dialogs/security/AccessSecretStorageDialog"; import { ModuleRunner } from "./modules/ModuleRunner"; -import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog"; // This stores the secret storage private keys in memory for the JS SDK. This is @@ -50,17 +49,6 @@ export class AccessCancelledError extends Error { } } -async function confirmToDismiss(): Promise { - const [sure] = await Modal.createDialog(QuestionDialog, { - title: _t("encryption|cancel_entering_passphrase_title"), - description: _t("encryption|cancel_entering_passphrase_description"), - danger: false, - button: _t("action|go_back"), - cancelButton: _t("action|cancel"), - }).finished; - return !sure; -} - function makeInputToKey( keyInfo: SecretStorage.SecretStorageKeyDescription, ): (keyParams: KeyParams) => Promise { @@ -134,17 +122,6 @@ async function getSecretStorageKey( return MatrixClientPeg.safeGet().secretStorage.checkKey(key, keyInfo); }, }, - /* className= */ undefined, - /* isPriorityModal= */ false, - /* isStaticModal= */ false, - /* options= */ { - onBeforeClose: async (reason): Promise => { - if (reason === "backgroundClick") { - return confirmToDismiss(); - } - return true; - }, - }, ); const [keyParams] = await finished; if (!keyParams) { diff --git a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx index b44e456404..10f4788580 100644 --- a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx +++ b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx @@ -14,6 +14,7 @@ import React, { type ChangeEvent, type FormEvent } from "react"; import { type SecretStorage } from "matrix-js-sdk/src/matrix"; import Field from "../../elements/Field"; +import { Flex } from "../../../utils/Flex"; import { _t } from "../../../../languageHandler"; import { EncryptionCard } from "../../settings/encryption/EncryptionCard"; import { EncryptionCardButtons } from "../../settings/encryption/EncryptionCardButtons"; @@ -84,6 +85,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent{validationText}; + // The entered key is not (yet) correct. Tell them so. + validationText = _t("encryption|access_secret_storage_dialog|key_validation_text|wrong_security_key"); + classes = classNames({ + "mx_AccessSecretStorageDialog_recoveryKeyFeedback": true, + "mx_AccessSecretStorageDialog_recoveryKeyFeedback--invalid": true, + }); } + + return ( + + {validationText} + + ); } public render(): React.ReactNode { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 459b4fb188..5567472dd0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -920,8 +920,6 @@ "security_key_title": "Recovery key" }, "bootstrap_title": "Setting up keys", - "cancel_entering_passphrase_description": "Are you sure you want to cancel entering passphrase?", - "cancel_entering_passphrase_title": "Cancel entering passphrase?", "confirm_encryption_setup_body": "Click the button below to confirm setting up encryption.", "confirm_encryption_setup_title": "Confirm encryption setup", "cross_signing_room_normal": "This room is end-to-end encrypted", diff --git a/test/unit-tests/components/views/dialogs/AccessSecretStorageDialog-test.tsx b/test/unit-tests/components/views/dialogs/AccessSecretStorageDialog-test.tsx index 2d597f8e18..23fa06720c 100644 --- a/test/unit-tests/components/views/dialogs/AccessSecretStorageDialog-test.tsx +++ b/test/unit-tests/components/views/dialogs/AccessSecretStorageDialog-test.tsx @@ -29,15 +29,15 @@ describe("AccessSecretStorageDialog", () => { render(); }; - const enterRecoveryKey = (): void => { - act(() => { + const enterRecoveryKey = async (valueToEnter: string = recoveryKey): Promise => { + await act(async () => { fireEvent.change(screen.getByRole("textbox"), { target: { - value: recoveryKey, + value: valueToEnter, }, }); - // wait for debounce - jest.advanceTimersByTime(250); + // wait for debounce, and then give `checkPrivateKey` a chance to complete + await jest.advanceTimersByTimeAsync(250); }); }; @@ -116,4 +116,22 @@ describe("AccessSecretStorageDialog", () => { await expect(screen.findByText("The recovery key you entered is not correct.")).resolves.toBeInTheDocument(); expect(screen.getByText("Continue")).toHaveAttribute("aria-disabled", "true"); }); + + it("Clears the 'invalid recovery key' notice when the input is cleared", async function () { + renderComponent({ onFinished: () => {}, checkPrivateKey: () => false }); + + jest.spyOn(mockClient.secretStorage, "checkKey").mockRejectedValue(new Error("invalid key")); + + // First, enter the wrong recovery key + await enterRecoveryKey(); + expect(screen.getByText("The recovery key you entered is not correct.")).toBeInTheDocument(); + + // Now, clear the input: the notice should be cleared. + await enterRecoveryKey(""); + expect(screen.queryByText("The recovery key you entered is not correct.")).not.toBeInTheDocument(); + expect( + screen.getByText("If you have a security key or security phrase, this will work too."), + ).toBeInTheDocument(); + expect(screen.getByText("Continue")).toHaveAttribute("aria-disabled", "true"); + }); });