diff --git a/src/components/views/settings/encryption/ChangeRecoveryKey.tsx b/src/components/views/settings/encryption/ChangeRecoveryKey.tsx index 2694539f5a..7f0f61cbfe 100644 --- a/src/components/views/settings/encryption/ChangeRecoveryKey.tsx +++ b/src/components/views/settings/encryption/ChangeRecoveryKey.tsx @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -import React, { type JSX, type MouseEventHandler, useState } from "react"; +import React, { type JSX, type MouseEventHandler, useCallback, useState } from "react"; import { Breadcrumb, Button, @@ -20,6 +20,7 @@ import { } from "@vector-im/compound-web"; import CopyIcon from "@vector-im/compound-design-tokens/assets/web/icons/copy"; import KeyIcon from "@vector-im/compound-design-tokens/assets/web/icons/key-solid"; +import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../../languageHandler"; import { EncryptionCard } from "./EncryptionCard"; @@ -79,6 +80,11 @@ export function ChangeRecoveryKey({ // "recovery" is about. Otherwise, we jump straight to showing the user the new key. const [state, setState] = useState(userHasRecoveryKey ? "save_key_change_flow" : "inform_user"); + const onCancelClickWrapper = useCallback(() => { + logger.debug("ChangeRecoveryKey: user cancelled"); + onCancelClick(); + }, [onCancelClick]); + // We create a new recovery key, the recovery key will be displayed to the user const recoveryKey = useAsyncMemo(() => matrixClient.getCrypto()!.createRecoveryKeyFromPassphrase(), []); // Waiting for the recovery key to be generated @@ -91,7 +97,7 @@ export function ChangeRecoveryKey({ content = ( setState("save_key_setup_flow")} - onCancelClick={onCancelClick} + onCancelClick={onCancelClickWrapper} /> ); break; @@ -109,7 +115,7 @@ export function ChangeRecoveryKey({ : "confirm_key_setup_flow", ) } - onCancelClick={onCancelClick} + onCancelClick={onCancelClickWrapper} /> ); break; @@ -120,7 +126,7 @@ export function ChangeRecoveryKey({ { const crypto = matrixClient.getCrypto(); if (!crypto) return onFinish(); @@ -133,6 +139,9 @@ export function ChangeRecoveryKey({ // keyStorageOutOfSyncNeedsBackupReset won't be able to check // the backup state. const needsBackupReset = await deviceListener.keyStorageOutOfSyncNeedsBackupReset(true); + logger.debug( + `ChangeRecoveryKey: user confirmed recovery key; now doing change. needsBackupReset: ${needsBackupReset}`, + ); await deviceListener.whilePaused(async () => { // We need to enable the cache to avoid to prompt the user to enter the new key // when we will try to access the secret storage during the bootstrap @@ -178,9 +187,9 @@ export function ChangeRecoveryKey({ <> { * @param state The state of the device */ export const showToast = (state: DeviceStateForToast): void => { + const myLogger = logger.getChild(`SetupEncryptionToast[${state}]:`); if ( ModuleRunner.instance.extensions.cryptoSetup.setupEncryptionNeeded({ kind: state as any, @@ -162,6 +164,7 @@ export const showToast = (state: DeviceStateForToast): void => { interactionType: "Pointer", name: state === "set_up_recovery" ? "ToastSetUpRecoveryClick" : "ToastTurnOnKeyStorageClick", }); + myLogger.debug("Primary button clicked: opening encryption settings dialog"); // Open the user settings dialog to the encryption tab const payload: OpenToTabPayload = { action: Action.ViewUserSettings, @@ -171,9 +174,11 @@ export const showToast = (state: DeviceStateForToast): void => { break; } case "verify_this_session": + myLogger.debug("Primary button clicked: opening SetupEncryptionDialog"); Modal.createDialog(SetupEncryptionDialog, {}, undefined, /* priority = */ false, /* static = */ true); break; case "key_storage_out_of_sync": { + myLogger.debug("Primary button clicked: starting recovery process"); const modal = Modal.createDialog( Spinner, undefined, @@ -215,6 +220,7 @@ export const showToast = (state: DeviceStateForToast): void => { break; } case "identity_needs_reset": { + myLogger.debug("Primary button clicked: opening encryption settings dialog"); // Open the user settings dialog to reset identity const payload: OpenToTabPayload = { action: Action.ViewUserSettings, @@ -237,6 +243,7 @@ export const showToast = (state: DeviceStateForToast): void => { interactionType: "Pointer", name: "ToastSetUpRecoveryDismiss", }); + myLogger.debug("Secondary button clicked: disabling recovery"); // Record that the user doesn't want to set up recovery const deviceListener = DeviceListener.sharedInstance(); await deviceListener.recordRecoveryDisabled(); @@ -247,14 +254,14 @@ export const showToast = (state: DeviceStateForToast): void => { // Open the user settings dialog to the encryption tab and start the flow to reset encryption or change the recovery key const deviceListener = DeviceListener.sharedInstance(); const needsCrossSigningReset = await deviceListener.keyStorageOutOfSyncNeedsCrossSigningReset(true); + const props = { + initialEncryptionState: needsCrossSigningReset ? "reset_identity_forgot" : "change_recovery_key", + }; + myLogger.debug(`Secondary button clicked: opening encryption settings dialog with props`, props); const payload: OpenToTabPayload = { action: Action.ViewUserSettings, initialTabId: UserTab.Encryption, - props: { - initialEncryptionState: needsCrossSigningReset - ? "reset_identity_forgot" - : "change_recovery_key", - }, + props, }; defaultDispatcher.dispatch(payload); break; @@ -273,6 +280,7 @@ export const showToast = (state: DeviceStateForToast): void => { ); const [dismissed] = await modal.finished; if (dismissed) { + myLogger.debug("Secondary button clicked and confirmed: recording key storage disabled"); const deviceListener = DeviceListener.sharedInstance(); await deviceListener.recordKeyBackupDisabled(); deviceListener.dismissEncryptionSetup(); @@ -280,6 +288,7 @@ export const showToast = (state: DeviceStateForToast): void => { break; } default: + myLogger.debug("Secondary button clicked: dismissing"); DeviceListener.sharedInstance().dismissEncryptionSetup(); } }; @@ -293,20 +302,24 @@ export const showToast = (state: DeviceStateForToast): void => { */ const onAccessSecretStorageFailed = async (error: Error): Promise => { if (error instanceof AccessCancelledError) { + myLogger.debug("AccessSecretStorage failed: user cancelled"); // The user cancelled the dialog - just allow it to close } else { // A real error happened - jump to the reset identity or change // recovery tab const needsCrossSigningReset = await DeviceListener.sharedInstance().keyStorageOutOfSyncNeedsCrossSigningReset(true); + const props = { + initialEncryptionState: needsCrossSigningReset ? "reset_identity_sync_failed" : "change_recovery_key", + }; + myLogger.debug( + `AccessSecretStorage failed: ${error}. Opening encryption settings dialog with props: `, + props, + ); const payload: OpenToTabPayload = { action: Action.ViewUserSettings, initialTabId: UserTab.Encryption, - props: { - initialEncryptionState: needsCrossSigningReset - ? "reset_identity_sync_failed" - : "change_recovery_key", - }, + props, }; defaultDispatcher.dispatch(payload); }