diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 113322786..e8c51935e 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -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. Learn more.", "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. Learn more.", + "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": "Signal will never message you 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. Learn more.", + "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." diff --git a/images/warning-circle.svg b/images/warning-circle.svg new file mode 100644 index 000000000..2080ea470 --- /dev/null +++ b/images/warning-circle.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ts/components/PreferencesLocalBackups.dom.tsx b/ts/components/PreferencesLocalBackups.dom.tsx index bc1422c56..978fd44a3 100644 --- a/ts/components/PreferencesLocalBackups.dom.tsx +++ b/ts/components/PreferencesLocalBackups.dom.tsx @@ -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) { + return {parts}; +} + function LocalBackupsBackupKeyViewer({ backupKey, i18n, @@ -568,6 +575,8 @@ function LocalBackupsBackupKeyViewer({ }): JSX.Element { const [isBackupKeyConfirmed, setIsBackupKeyConfirmed] = useState(false); + const [isShowingDoNotShareModal, setIsShowingDoNotShareModal] = + useState(false); const [step, setStep] = useState( 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) => ( - + const learnMorePhishingLink = (parts: Array) => ( + {parts} ); @@ -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 = ( ); @@ -655,6 +665,51 @@ function LocalBackupsBackupKeyViewer({ return (
+ {isShowingDoNotShareModal ? ( + setIsShowingDoNotShareModal(false)} + > + + +
+ + + {i18n('icu:Preferences__recovery-key__do-not-share-title')} + +
+ +
+ +
+
+
+ + { + onCopyBackupKey(); + setIsShowingDoNotShareModal(false); + }} + > + {i18n('icu:Preferences__recovery-key__do-not-share-confirm')} + + +
+
+ ) : null} {step === 'caution' && ( setIsShowingDoNotShareModal(true)} > {i18n('icu:Preferences__local-backups-copy-key')} diff --git a/ts/components/ToastManager.dom.tsx b/ts/components/ToastManager.dom.tsx index 2d3419a53..37ba2fc71 100644 --- a/ts/components/ToastManager.dom.tsx +++ b/ts/components/ToastManager.dom.tsx @@ -321,7 +321,11 @@ function renderToast({ if (toastType === ToastType.CopiedBackupKey) { return ( - {i18n('icu:Preferences__local-backups-copied-recovery-key')} +
+ +    + {i18n('icu:Preferences__local-backups-copied-recovery-key')} +
); }