Add warning dialog when copying recovery key
This commit is contained in:
parent
4eddde9922
commit
2f772e96ab
@ -8540,10 +8540,30 @@
|
||||
"messageformat": "Record your recovery key",
|
||||
"description": "Title for viewing the recovery (backup) key for local message backups."
|
||||
},
|
||||
"icu:Preferences--local-backups-recovery-key--title": {
|
||||
"messageformat": "Your recovery key",
|
||||
"description": "Title for viewing the recovery (backup) key for local message backups."
|
||||
},
|
||||
"icu:Preferences--local-backups-record-backup-key-description": {
|
||||
"messageformat": "This key is required to recover your account and data. Store this key somewhere safe. If you lose it, you won’t be able to recover your account. <learnMoreLink>Learn more.</learnMoreLink>",
|
||||
"description": "Description for viewing the recovery (backup) key for local message backups."
|
||||
},
|
||||
"icu:Preferences--local-backups-recovery-key--description": {
|
||||
"messageformat": "This key is required to recover your account and data. Store it somewhere safe and never share it with anyone. Signal will never message you for your recovery key. <learnMoreLink>Learn more.</learnMoreLink>",
|
||||
"description": "Description for viewing the recovery (backup) key for local message backups."
|
||||
},
|
||||
"icu:Preferences__recovery-key__do-not-share-title": {
|
||||
"messageformat": "Do not share recovery key",
|
||||
"description": "Title of the dialog warning the user not to share their recovery key, shown after copying the recovery key."
|
||||
},
|
||||
"icu:Preferences__recovery-key__do-not-share-description": {
|
||||
"messageformat": "<strong>Signal will never message you</strong> for your recovery key. Never respond to a chat pretending to be Signal. Store your recovery key somewhere safe and never share it with anyone. <learnMoreLink>Learn more.</learnMoreLink>",
|
||||
"description": "Body of the dialog warning the user not to share their recovery key, shown after copying the recovery key."
|
||||
},
|
||||
"icu:Preferences__recovery-key__do-not-share-confirm": {
|
||||
"messageformat": "Got it",
|
||||
"description": "Button to dismiss the dialog warning the user not to share their recovery key."
|
||||
},
|
||||
"icu:Preferences--local-backups-confirm-recovery-key": {
|
||||
"messageformat": "Confirm your recovery key",
|
||||
"description": "Title for confirming the recovery (backup) key for local message backups by re-entering it into a text box."
|
||||
|
||||
7
images/warning-circle.svg
Normal file
7
images/warning-circle.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="32" cy="32" r="32" fill="#F8E0D9"/>
|
||||
<path d="M18 39.6L30.8 19.2H33.6L46.8 39.6L43.6 43.6H20.8L18 42.8V39.6Z" fill="#FDEEEB"/>
|
||||
<path d="M31.9998 24.2806C31.0232 24.2806 30.2533 25.112 30.3282 26.0857L30.9223 33.8091C30.9657 34.3722 31.4351 34.8069 31.9998 34.8069C32.5645 34.8069 33.034 34.3722 33.0773 33.8091L33.6714 26.0857C33.7463 25.112 32.9764 24.2806 31.9998 24.2806Z" fill="#C34922"/>
|
||||
<path d="M30.2454 38.3157C30.2454 37.3468 31.0309 36.5613 31.9998 36.5613C32.9687 36.5613 33.7542 37.3468 33.7542 38.3157C33.7542 39.2846 32.9687 40.0701 31.9998 40.0701C31.0309 40.0701 30.2454 39.2846 30.2454 38.3157Z" fill="#C34922"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.9118 19.0087C29.7412 15.8835 34.2584 15.8835 36.0878 19.0087L46.8102 37.3263C48.6587 40.4841 46.3813 44.456 42.7223 44.456H21.2773C17.6183 44.456 15.3409 40.4841 17.1894 37.3262L27.9118 19.0087ZM33.9681 20.2495C33.0873 18.7448 30.9123 18.7448 30.0315 20.2495L19.309 38.567C18.419 40.0875 19.5156 41.9999 21.2773 41.9999H42.7223C44.484 41.9999 45.5806 40.0875 44.6906 38.567L33.9681 20.2495Z" fill="#C34922"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -1,7 +1,7 @@
|
||||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ChangeEvent, JSX, MouseEvent } from 'react';
|
||||
import type { ChangeEvent, JSX } from 'react';
|
||||
import { useCallback, useMemo, useState, useRef } from 'react';
|
||||
import lodash from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
@ -37,6 +37,9 @@ import { AxoSymbol } from '../axo/AxoSymbol.dom.tsx';
|
||||
const { noop } = lodash;
|
||||
const log = createLogger('PreferencesLocalBackups');
|
||||
|
||||
const SIGNAL_USER_SAFETY_LINK =
|
||||
'https://support.signal.org/hc/articles/9932566320410-Staying-Safe-from-Phishing-Scams-and-Impersonation';
|
||||
|
||||
export function PreferencesLocalBackups({
|
||||
backupKey,
|
||||
backupKeyHash,
|
||||
@ -553,6 +556,10 @@ function LocalBackupsSetupFolderPicker({
|
||||
|
||||
type BackupKeyStep = 'view' | 'confirm' | 'caution' | 'reference';
|
||||
|
||||
function Strong(parts: Array<string | JSX.Element>) {
|
||||
return <strong>{parts}</strong>;
|
||||
}
|
||||
|
||||
function LocalBackupsBackupKeyViewer({
|
||||
backupKey,
|
||||
i18n,
|
||||
@ -568,6 +575,8 @@ function LocalBackupsBackupKeyViewer({
|
||||
}): JSX.Element {
|
||||
const [isBackupKeyConfirmed, setIsBackupKeyConfirmed] =
|
||||
useState<boolean>(false);
|
||||
const [isShowingDoNotShareModal, setIsShowingDoNotShareModal] =
|
||||
useState<boolean>(false);
|
||||
const [step, setStep] = useState<BackupKeyStep>(
|
||||
isReferencing ? 'reference' : 'view'
|
||||
);
|
||||
@ -577,20 +586,21 @@ function LocalBackupsBackupKeyViewer({
|
||||
() => formatBackupKeyForDisplay(backupKey, { convertAmbiguousChars: true }),
|
||||
[backupKey]
|
||||
);
|
||||
const onCopyBackupKey = useCallback(
|
||||
async function handleCopyBackupKey(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
window.SignalClipboard.copyTextTemporarily(
|
||||
backupKeyForDisplay,
|
||||
45 * SECOND
|
||||
);
|
||||
showToast({ toastType: ToastType.CopiedBackupKey });
|
||||
},
|
||||
[backupKeyForDisplay, showToast]
|
||||
);
|
||||
const onCopyBackupKey = useCallback(() => {
|
||||
window.SignalClipboard.copyTextTemporarily(
|
||||
backupKeyForDisplay,
|
||||
45 * SECOND
|
||||
);
|
||||
showToast({ toastType: ToastType.CopiedBackupKey });
|
||||
}, [backupKeyForDisplay, showToast]);
|
||||
|
||||
const learnMoreLink = (parts: Array<string | JSX.Element>) => (
|
||||
<a href={SIGNAL_BACKUPS_LEARN_MORE_URL} rel="noreferrer" target="_blank">
|
||||
const learnMorePhishingLink = (parts: Array<string | JSX.Element>) => (
|
||||
<a
|
||||
className={tw('text-color-label-primary')}
|
||||
href={SIGNAL_USER_SAFETY_LINK}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{parts}
|
||||
</a>
|
||||
);
|
||||
@ -600,13 +610,13 @@ function LocalBackupsBackupKeyViewer({
|
||||
let footerLeft: JSX.Element | undefined;
|
||||
let footerRight: JSX.Element;
|
||||
if (isStepViewOrReference) {
|
||||
title = i18n('icu:Preferences--local-backups-record-recovery-key');
|
||||
title = i18n('icu:Preferences--local-backups-recovery-key--title');
|
||||
description = (
|
||||
<I18n
|
||||
id="icu:Preferences--local-backups-record-backup-key-description"
|
||||
id="icu:Preferences--local-backups-recovery-key--description"
|
||||
i18n={i18n}
|
||||
components={{
|
||||
learnMoreLink,
|
||||
learnMoreLink: learnMorePhishingLink,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@ -655,6 +665,51 @@ function LocalBackupsBackupKeyViewer({
|
||||
|
||||
return (
|
||||
<div className="Preferences--LocalBackupsSetupScreen Preferences__settings-pane-content--with-footer Preferences__padding">
|
||||
{isShowingDoNotShareModal ? (
|
||||
<AxoAlertDialog.Root
|
||||
open
|
||||
onOpenChange={() => setIsShowingDoNotShareModal(false)}
|
||||
>
|
||||
<AxoAlertDialog.Content escape="cancel-is-noop">
|
||||
<AxoAlertDialog.Body>
|
||||
<div className={tw('mt-3 mb-2 flex flex-col items-center')}>
|
||||
<img
|
||||
role="presentation"
|
||||
alt=""
|
||||
className={tw('mt-1 mb-3 size-16 shrink-0')}
|
||||
src="images/warning-circle.svg"
|
||||
/>
|
||||
<AxoAlertDialog.Title>
|
||||
{i18n('icu:Preferences__recovery-key__do-not-share-title')}
|
||||
</AxoAlertDialog.Title>
|
||||
</div>
|
||||
<AxoAlertDialog.Description>
|
||||
<div className={tw('mb-3 text-center type-body-medium')}>
|
||||
<I18n
|
||||
id="icu:Preferences__recovery-key__do-not-share-description"
|
||||
i18n={i18n}
|
||||
components={{
|
||||
strong: Strong,
|
||||
learnMoreLink: learnMorePhishingLink,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</AxoAlertDialog.Description>
|
||||
</AxoAlertDialog.Body>
|
||||
<AxoAlertDialog.Footer>
|
||||
<AxoAlertDialog.Action
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
onCopyBackupKey();
|
||||
setIsShowingDoNotShareModal(false);
|
||||
}}
|
||||
>
|
||||
{i18n('icu:Preferences__recovery-key__do-not-share-confirm')}
|
||||
</AxoAlertDialog.Action>
|
||||
</AxoAlertDialog.Footer>
|
||||
</AxoAlertDialog.Content>
|
||||
</AxoAlertDialog.Root>
|
||||
) : null}
|
||||
{step === 'caution' && (
|
||||
<Modal
|
||||
i18n={i18n}
|
||||
@ -712,7 +767,7 @@ function LocalBackupsBackupKeyViewer({
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
symbol="copy"
|
||||
onClick={onCopyBackupKey}
|
||||
onClick={() => setIsShowingDoNotShareModal(true)}
|
||||
>
|
||||
{i18n('icu:Preferences__local-backups-copy-key')}
|
||||
</AxoButton.Root>
|
||||
|
||||
@ -321,7 +321,11 @@ function renderToast({
|
||||
if (toastType === ToastType.CopiedBackupKey) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={3 * SECOND}>
|
||||
{i18n('icu:Preferences__local-backups-copied-recovery-key')}
|
||||
<div className={tw('flex items-center')}>
|
||||
<AxoSymbol.InlineGlyph symbol="copy" label={null} />
|
||||
|
||||
{i18n('icu:Preferences__local-backups-copied-recovery-key')}
|
||||
</div>
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user