Add key storage delete confirm screen

This commit is contained in:
David Baker
2025-02-05 14:20:29 +01:00
parent b7b2ea3448
commit e408715335
4 changed files with 103 additions and 8 deletions

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import { Breadcrumb, Button, VisualList, VisualListItem } from "@vector-im/compound-web";
import CrossIcon from "@vector-im/compound-design-tokens/assets/web/icons/close";
import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error";
import React, { useCallback, useState } from "react";
import { _t } from "../../../../languageHandler";
import { EncryptionCard } from "./EncryptionCard";
import { useKeyStoragePanelViewModel } from "../../../viewmodels/settings/encryption/KeyStoragePanelViewModel";
interface ResetIdentityPanelProps {
onFinish: () => void;
}
/**
* Confirms that the user really wants to turn off and delete their key storage
*/
export function DeleteKeyStoragePanel({ onFinish }: ResetIdentityPanelProps): JSX.Element {
const { setEnabled } = useKeyStoragePanelViewModel();
const [busy, setBusy] = useState(false);
const onDeleteClick = useCallback(async () => {
setBusy(true);
try {
await setEnabled(false);
} finally {
setBusy(false);
}
onFinish();
}, [setEnabled, onFinish]);
return (
<>
<Breadcrumb
backLabel={_t("action|back")}
onBackClick={onFinish}
pages={[_t("settings|encryption|title"), _t("settings|encryption|delete_key_storage|breadcrumb_page")]}
onPageClick={onFinish}
/>
<EncryptionCard
Icon={ErrorIcon}
destructive={true}
title={_t("settings|encryption|delete_key_storage|title")}
className="mx_ResetIdentityPanel"
>
<div className="mx_ResetIdentityPanel_content">
{_t("settings|encryption|delete_key_storage|description")}
<VisualList>
<VisualListItem Icon={CrossIcon} destructive={true}>
{_t("settings|encryption|delete_key_storage|list_first")}
</VisualListItem>
<VisualListItem Icon={CrossIcon} destructive={true}>
{_t("settings|encryption|delete_key_storage|list_second")}
</VisualListItem>
</VisualList>
</div>
<div className="mx_ResetIdentityPanel_footer">
<Button destructive={true} onClick={onDeleteClick} disabled={busy}>
{_t("settings|encryption|delete_key_storage|confirm")}
</Button>
<Button kind="tertiary" onClick={onFinish}>
{_t("action|cancel")}
</Button>
</div>
</EncryptionCard>
</>
);
}

View File

@@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
import React, { FormEvent, JSX, useCallback } from "react";
import React, { FormEvent, useCallback } from "react";
import { InlineField, InlineSpinner, Label, Root, ToggleControl } from "@vector-im/compound-web";
import { SettingsSection } from "../shared/SettingsSection";
@@ -13,17 +13,25 @@ import { _t } from "../../../../languageHandler";
import { SettingsHeader } from "../SettingsHeader";
import { useKeyStoragePanelViewModel } from "../../../viewmodels/settings/encryption/KeyStoragePanelViewModel";
interface Props {
onKeyStorageDisableClick: () => void;
}
/**
* This component allows the user to set up or change their recovery key.
*/
export function KeyBackupPanel(): JSX.Element {
export const KeyStoragePanel: React.FC<Props> = ({ onKeyStorageDisableClick }) => {
const { isEnabled, setEnabled, loading, busy } = useKeyStoragePanelViewModel();
const onKeyBackupChange = useCallback(
(e: FormEvent<HTMLInputElement>) => {
setEnabled(e.currentTarget.checked);
if (e.currentTarget.checked) {
setEnabled(true);
} else {
onKeyStorageDisableClick();
}
},
[setEnabled],
[setEnabled, onKeyStorageDisableClick],
);
if (loading) {
@@ -58,4 +66,4 @@ export function KeyBackupPanel(): JSX.Element {
</Root>
</SettingsSection>
);
}
};

View File

@@ -24,7 +24,8 @@ import { ResetIdentityPanel } from "../../encryption/ResetIdentityPanel";
import { RecoveryPanelOutOfSync } from "../../encryption/RecoveryPanelOutOfSync";
import Spinner from "../../../elements/Spinner";
import { useEventEmitter } from "../../../../../hooks/useEventEmitter";
import { KeyBackupPanel } from "../../encryption/KeyStoragePanel";
import { KeyStoragePanel } from "../../encryption/KeyStoragePanel";
import { DeleteKeyStoragePanel } from "../../encryption/DeleteKeyStoragePanel";
/**
* The state in the encryption settings tab.
@@ -49,7 +50,8 @@ export type State =
| "set_recovery_key"
| "reset_identity_compromised"
| "reset_identity_forgot"
| "secrets_not_cached";
| "secrets_not_cached"
| "key_storage_delete";
interface EncryptionUserSettingsTabProps {
/**
@@ -113,7 +115,7 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti
case "main":
content = (
<>
<KeyBackupPanel />
<KeyStoragePanel onKeyStorageDisableClick={() => setState("key_storage_delete")} />
{keyBackupIsEnabled && (
<>
<RecoveryPanel
@@ -158,6 +160,9 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti
/>
);
break;
case "key_storage_delete":
content = <DeleteKeyStoragePanel onFinish={() => setState("main")} />;
break;
}
}

View File

@@ -2482,6 +2482,14 @@
"session_key": "Session key:",
"title": "Advanced"
},
"delete_key_storage": {
"breadcrumb_page": "Delete key storage",
"confirm": "Delete key storage",
"description": "Deleting key storage will remove your cryptographic identity and message keys from the server and turn off the following security features:",
"list_first": "You will not have encrypted message history on new devices",
"list_second": "You will lose access to your encrypted messages if you are signed out of Element everywhere",
"title": "Are you sure you want to turn off key storage and delete it?"
},
"device_not_verified_button": "Verify this device",
"device_not_verified_description": "You need to verify this device in order to view your encryption settings.",
"device_not_verified_title": "Device not verified",