Skip to content

Commit f6f58a2

Browse files
committed
Extract ResetIdentityBody into a separate object to allow re-using it
1 parent c929eed commit f6f58a2

File tree

3 files changed

+135
-93
lines changed

3 files changed

+135
-93
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright 2024-2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
import { Button, InlineSpinner, VisualList, VisualListItem } from "@vector-im/compound-web";
9+
import CheckIcon from "@vector-im/compound-design-tokens/assets/web/icons/check";
10+
import InfoIcon from "@vector-im/compound-design-tokens/assets/web/icons/info";
11+
import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
12+
import React, { type JSX, useState, type MouseEventHandler } from "react";
13+
14+
import { _t } from "../../../../languageHandler";
15+
import { EncryptionCard } from "./EncryptionCard";
16+
import { uiAuthCallback } from "../../../../CreateCrossSigning";
17+
import { EncryptionCardButtons } from "./EncryptionCardButtons";
18+
import { EncryptionCardEmphasisedContent } from "./EncryptionCardEmphasisedContent";
19+
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext";
20+
21+
interface ResetIdentityBodyProps {
22+
/**
23+
* Called when the identity is reset.
24+
*/
25+
onFinish: MouseEventHandler<HTMLButtonElement>;
26+
/**
27+
* Called when the cancel button is clicked.
28+
*/
29+
onCancelClick: () => void;
30+
31+
/**
32+
* The variant of the panel to show. We show more warnings in the 'compromised' variant (no use in showing a user
33+
* this warning if they have to reset because they no longer have their key)
34+
*/
35+
variant: ResetIdentityBodyVariant;
36+
}
37+
38+
/**
39+
* "compromised" is shown when the user chooses 'reset' explicitly in settings, usually because they believe their
40+
* identity has been compromised.
41+
*
42+
* "sync_failed" is shown when the user tried to recover their identity but the process failed, probably because
43+
* the required information is missing from recovery.
44+
*
45+
* "forgot" is shown when the user has just forgotten their passphrase.
46+
*/
47+
export type ResetIdentityBodyVariant = "compromised" | "forgot" | "sync_failed";
48+
49+
/**
50+
* User interface component allowing the user to reset their cryptographic identity.
51+
*
52+
* Used by {@link ResetIdentityPanel}.
53+
*/
54+
export function ResetIdentityBody({ onCancelClick, onFinish, variant }: ResetIdentityBodyProps): JSX.Element {
55+
const matrixClient = useMatrixClientContext();
56+
57+
// After the user clicks "Continue", we disable the button so it can't be
58+
// clicked again, and warn the user not to close the window.
59+
const [inProgress, setInProgress] = useState(false);
60+
61+
return (
62+
<EncryptionCard Icon={ErrorIcon} destructive={true} title={titleForVariant(variant)}>
63+
<EncryptionCardEmphasisedContent>
64+
<VisualList>
65+
<VisualListItem Icon={CheckIcon} success={true}>
66+
{_t("settings|encryption|advanced|breadcrumb_first_description")}
67+
</VisualListItem>
68+
<VisualListItem Icon={InfoIcon}>
69+
{_t("settings|encryption|advanced|breadcrumb_second_description")}
70+
</VisualListItem>
71+
<VisualListItem Icon={InfoIcon}>
72+
{_t("settings|encryption|advanced|breadcrumb_third_description")}
73+
</VisualListItem>
74+
</VisualList>
75+
{variant === "compromised" && <span>{_t("settings|encryption|advanced|breadcrumb_warning")}</span>}
76+
</EncryptionCardEmphasisedContent>
77+
<EncryptionCardButtons>
78+
<Button
79+
destructive={true}
80+
disabled={inProgress}
81+
onClick={async (evt) => {
82+
setInProgress(true);
83+
await matrixClient
84+
.getCrypto()
85+
?.resetEncryption((makeRequest) => uiAuthCallback(matrixClient, makeRequest));
86+
onFinish(evt);
87+
}}
88+
>
89+
{inProgress ? (
90+
<>
91+
<InlineSpinner /> {_t("settings|encryption|advanced|reset_in_progress")}
92+
</>
93+
) : (
94+
_t("action|continue")
95+
)}
96+
</Button>
97+
{inProgress ? (
98+
<EncryptionCardEmphasisedContent>
99+
<span className="mx_ResetIdentityPanel_warning">
100+
{_t("settings|encryption|advanced|do_not_close_warning")}
101+
</span>
102+
</EncryptionCardEmphasisedContent>
103+
) : (
104+
<Button kind="tertiary" onClick={onCancelClick}>
105+
{_t("action|cancel")}
106+
</Button>
107+
)}
108+
</EncryptionCardButtons>
109+
</EncryptionCard>
110+
);
111+
}
112+
113+
function titleForVariant(variant: ResetIdentityBodyVariant): string {
114+
switch (variant) {
115+
case "compromised":
116+
return _t("settings|encryption|advanced|breadcrumb_title");
117+
case "sync_failed":
118+
return _t("settings|encryption|advanced|breadcrumb_title_sync_failed");
119+
120+
default:
121+
case "forgot":
122+
return _t("settings|encryption|advanced|breadcrumb_title_forgot");
123+
}
124+
}

src/components/views/settings/encryption/ResetIdentityPanel.tsx

Lines changed: 8 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,11 @@
55
* Please see LICENSE files in the repository root for full details.
66
*/
77

8-
import { Breadcrumb, Button, InlineSpinner, VisualList, VisualListItem } from "@vector-im/compound-web";
9-
import CheckIcon from "@vector-im/compound-design-tokens/assets/web/icons/check";
10-
import InfoIcon from "@vector-im/compound-design-tokens/assets/web/icons/info";
11-
import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
12-
import React, { type JSX, useState, type MouseEventHandler } from "react";
8+
import { Breadcrumb } from "@vector-im/compound-web";
9+
import React, { type JSX, type MouseEventHandler } from "react";
1310

1411
import { _t } from "../../../../languageHandler";
15-
import { EncryptionCard } from "./EncryptionCard";
16-
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext";
17-
import { uiAuthCallback } from "../../../../CreateCrossSigning";
18-
import { EncryptionCardButtons } from "./EncryptionCardButtons";
19-
import { EncryptionCardEmphasisedContent } from "./EncryptionCardEmphasisedContent";
12+
import { ResetIdentityBody, type ResetIdentityBodyVariant } from "./ResetIdentityBody";
2013

2114
interface ResetIdentityPanelProps {
2215
/**
@@ -29,33 +22,17 @@ interface ResetIdentityPanelProps {
2922
onCancelClick: () => void;
3023

3124
/**
32-
* The variant of the panel to show. We show more warnings in the 'compromised' variant (no use in showing a user
33-
* this warning if they have to reset because they no longer have their key)
25+
* Which variant of this panel to show.
3426
*/
35-
variant: ResetIdentityPanelVariant;
27+
variant: ResetIdentityBodyVariant;
3628
}
3729

3830
/**
39-
* "compromised" is shown when the user chooses 'reset' explicitly in settings, usually because they believe their
40-
* identity has been compromised.
31+
* The Encryption Settings panel for resetting the identity of the current user.
4132
*
42-
* "sync_failed" is shown when the user tried to recover their identity but the process failed, probably because
43-
* the required information is missing from recovery.
44-
*
45-
* "forgot" is shown when the user has just forgotten their passphrase.
46-
*/
47-
export type ResetIdentityPanelVariant = "compromised" | "forgot" | "sync_failed";
48-
49-
/**
50-
* The panel for resetting the identity of the current user.
33+
* A thin wrapper around {@link ResetIdentityBody}, just adding breadcrumbs.
5134
*/
5235
export function ResetIdentityPanel({ onCancelClick, onFinish, variant }: ResetIdentityPanelProps): JSX.Element {
53-
const matrixClient = useMatrixClientContext();
54-
55-
// After the user clicks "Continue", we disable the button so it can't be
56-
// clicked again, and warn the user not to close the window.
57-
const [inProgress, setInProgress] = useState(false);
58-
5936
return (
6037
<>
6138
<Breadcrumb
@@ -64,67 +41,7 @@ export function ResetIdentityPanel({ onCancelClick, onFinish, variant }: ResetId
6441
pages={[_t("settings|encryption|title"), _t("settings|encryption|advanced|breadcrumb_page")]}
6542
onPageClick={onCancelClick}
6643
/>
67-
<EncryptionCard Icon={ErrorIcon} destructive={true} title={titleForVariant(variant)}>
68-
<EncryptionCardEmphasisedContent>
69-
<VisualList>
70-
<VisualListItem Icon={CheckIcon} success={true}>
71-
{_t("settings|encryption|advanced|breadcrumb_first_description")}
72-
</VisualListItem>
73-
<VisualListItem Icon={InfoIcon}>
74-
{_t("settings|encryption|advanced|breadcrumb_second_description")}
75-
</VisualListItem>
76-
<VisualListItem Icon={InfoIcon}>
77-
{_t("settings|encryption|advanced|breadcrumb_third_description")}
78-
</VisualListItem>
79-
</VisualList>
80-
{variant === "compromised" && <span>{_t("settings|encryption|advanced|breadcrumb_warning")}</span>}
81-
</EncryptionCardEmphasisedContent>
82-
<EncryptionCardButtons>
83-
<Button
84-
destructive={true}
85-
disabled={inProgress}
86-
onClick={async (evt) => {
87-
setInProgress(true);
88-
await matrixClient
89-
.getCrypto()
90-
?.resetEncryption((makeRequest) => uiAuthCallback(matrixClient, makeRequest));
91-
onFinish(evt);
92-
}}
93-
>
94-
{inProgress ? (
95-
<>
96-
<InlineSpinner /> {_t("settings|encryption|advanced|reset_in_progress")}
97-
</>
98-
) : (
99-
_t("action|continue")
100-
)}
101-
</Button>
102-
{inProgress ? (
103-
<EncryptionCardEmphasisedContent>
104-
<span className="mx_ResetIdentityPanel_warning">
105-
{_t("settings|encryption|advanced|do_not_close_warning")}
106-
</span>
107-
</EncryptionCardEmphasisedContent>
108-
) : (
109-
<Button kind="tertiary" onClick={onCancelClick}>
110-
{_t("action|cancel")}
111-
</Button>
112-
)}
113-
</EncryptionCardButtons>
114-
</EncryptionCard>
44+
<ResetIdentityBody onFinish={onFinish} onCancelClick={onCancelClick} variant={variant} />
11545
</>
11646
);
11747
}
118-
119-
function titleForVariant(variant: ResetIdentityPanelVariant): string {
120-
switch (variant) {
121-
case "compromised":
122-
return _t("settings|encryption|advanced|breadcrumb_title");
123-
case "sync_failed":
124-
return _t("settings|encryption|advanced|breadcrumb_title_sync_failed");
125-
126-
default:
127-
case "forgot":
128-
return _t("settings|encryption|advanced|breadcrumb_title_forgot");
129-
}
130-
}

src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import SetupEncryptionDialog from "../../../dialogs/security/SetupEncryptionDial
2020
import { SettingsSection } from "../../shared/SettingsSection";
2121
import { SettingsSubheader } from "../../SettingsSubheader";
2222
import { AdvancedPanel } from "../../encryption/AdvancedPanel";
23-
import { ResetIdentityPanel, type ResetIdentityPanelVariant } from "../../encryption/ResetIdentityPanel";
23+
import { ResetIdentityPanel } from "../../encryption/ResetIdentityPanel";
24+
import { type ResetIdentityBodyVariant } from "../../encryption/ResetIdentityBody";
2425
import { RecoveryPanelOutOfSync } from "../../encryption/RecoveryPanelOutOfSync";
2526
import { useTypedEventEmitter } from "../../../../../hooks/useEventEmitter";
2627
import { KeyStoragePanel } from "../../encryption/KeyStoragePanel";
@@ -147,7 +148,7 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Props):
147148
* Given what state we want the tab to be in, what variant of the
148149
* ResetIdentityPanel do we need?
149150
*/
150-
function findResetVariant(state: State): ResetIdentityPanelVariant {
151+
function findResetVariant(state: State): ResetIdentityBodyVariant {
151152
switch (state) {
152153
case "reset_identity_compromised":
153154
return "compromised";

0 commit comments

Comments
 (0)