diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 1e4346d473..ca2b901102 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -11022,6 +11022,50 @@
"messageformat": "Slide",
"description": "aria-label for a slide within a carousel UI layout"
},
+ "icu:MaybeTransferModal__title": {
+ "messageformat": "Transfer your phone’s message history to this desktop?",
+ "description": "Title for dialog shown when user is unlinked and clicks to relink"
+ },
+ "icu:MaybeTransferModal__description": {
+ "messageformat": "When you re-link this desktop, you can transfer your phone’s message history to this device.",
+ "description": "Description for dialog shown when user is unlinked and clicks to relink"
+ },
+ "icu:MaybeTransferModal__learnMore": {
+ "messageformat": "Learn more",
+ "description": "Text for link to a support article about relinking a linked device"
+ },
+ "icu:MaybeTransferModal__replaceHistory": {
+ "messageformat": "This will replace the message history on this desktop.",
+ "description": "Bullet point in relink dialog for what will happen if you link & sync"
+ },
+ "icu:MaybeTransferModal__scanQrCode": {
+ "messageformat": "You’ll need to relink by scanning a QR code.",
+ "description": "Bullet point in relink dialog for what will happen if you link & sync"
+ },
+ "icu:MaybeTransferModal__media": {
+ "messageformat": "If you have paid Signal Secure Backups, all of your media will be transferred. Otherwise, your last 45 days of media will be included.",
+ "description": "Bullet point in relink dialog for what will happen if you link & sync"
+ },
+ "icu:MaybeTransferModal__transfer": {
+ "messageformat": "Transfer",
+ "description": "Button text when user wants to transfer data from their phone"
+ },
+ "icu:MaybeTransferModal__dontTransfer": {
+ "messageformat": "Don't transfer",
+ "description": "Button text when user does not want to transfer data from their phone"
+ },
+ "icu:DeleteDataAndRelinkConfirmationDialog__title": {
+ "messageformat": "Delete all data?",
+ "description": "Title in confirmation dialog shown when user is unlinked and chose to delete data and relink"
+ },
+ "icu:DeleteDataAndRelinkConfirmationDialog__pending": {
+ "messageformat": "Deleting all data",
+ "description": "Accessiblity label for button when data is in progress of being deleted"
+ },
+ "icu:DeleteDataAndRelinkConfirmationDialog__body": {
+ "messageformat": "All current data in Signal Desktop will be deleted. You can then scan a QR code and transfer your message history from your phone.",
+ "description": "Description in confirmation dialog shown when user is unlinked and chose to delete data and relink"
+ },
"icu:WhatsNew__bugfixes": {
"messageformat": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes",
diff --git a/ts/components/DialogRelink.dom.stories.tsx b/ts/components/DialogRelink.dom.stories.tsx
index c5812ad54c..9fe54906aa 100644
--- a/ts/components/DialogRelink.dom.stories.tsx
+++ b/ts/components/DialogRelink.dom.stories.tsx
@@ -16,6 +16,7 @@ const defaultProps = {
containerWidthBreakpoint: WidthBreakpoint.Wide,
i18n,
relinkDevice: action('relink-device'),
+ renderClearingDataView: action('render-clearing-data-view'),
reregister: action('reregister'),
weArePrimaryDevice: false,
};
diff --git a/ts/components/DialogRelink.dom.tsx b/ts/components/DialogRelink.dom.tsx
index 945b82fd45..aaedae97ef 100644
--- a/ts/components/DialogRelink.dom.tsx
+++ b/ts/components/DialogRelink.dom.tsx
@@ -1,17 +1,22 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import type { JSX } from 'react';
+import { useState, type JSX } from 'react';
import type { LocalizerType } from '../types/Util.std.ts';
import type { WidthBreakpoint } from './_util.std.ts';
import { LeftPaneDialog } from './LeftPaneDialog.dom.tsx';
+import {
+ DeleteDataAndRelinkConfirmationDialog,
+ MaybeTransferModal,
+} from './MaybeTransferModal.dom.tsx';
export type PropsType = {
containerWidthBreakpoint: WidthBreakpoint;
i18n: LocalizerType;
relinkDevice: () => void;
+ renderClearingDataView: () => void;
reregister: () => void;
weArePrimaryDevice: boolean;
};
@@ -20,9 +25,14 @@ export function DialogRelink({
containerWidthBreakpoint,
i18n,
relinkDevice,
+ renderClearingDataView,
reregister,
weArePrimaryDevice,
}: PropsType): JSX.Element | null {
+ const [relinkDialogStep, setRelinkDialogStep] = useState<
+ 'maybe-transfer' | 'confirm-deletion' | null
+ >(null);
+
if (weArePrimaryDevice) {
return (
+ <>
+ setRelinkDialogStep('maybe-transfer')}
+ title={i18n('icu:unlinked')}
+ hasAction
+ />
+ setRelinkDialogStep('confirm-deletion')}
+ onDontTransfer={relinkDevice}
+ onCancel={() => setRelinkDialogStep(null)}
+ />
+ {relinkDialogStep === 'confirm-deletion' ? (
+ setRelinkDialogStep('maybe-transfer')}
+ onConfirm={() => {
+ renderClearingDataView();
+ setRelinkDialogStep(null);
+ }}
+ />
+ ) : null}
+ >
);
}
diff --git a/ts/components/LeftPane.dom.stories.tsx b/ts/components/LeftPane.dom.stories.tsx
index 19efa14a20..04b6065b1f 100644
--- a/ts/components/LeftPane.dom.stories.tsx
+++ b/ts/components/LeftPane.dom.stories.tsx
@@ -260,6 +260,7 @@ const useProps = (overrideProps: OverridePropsType = {}): PropsType => {
+ );
+}
+
+export function DeleteDataConfirmationDialog(): JSX.Element {
+ return (
+ action('onConfirm')()}
+ i18n={i18n}
+ />
+ );
+}
diff --git a/ts/components/MaybeTransferModal.dom.tsx b/ts/components/MaybeTransferModal.dom.tsx
new file mode 100644
index 0000000000..badd8e08a9
--- /dev/null
+++ b/ts/components/MaybeTransferModal.dom.tsx
@@ -0,0 +1,181 @@
+// Copyright 2026 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import { type JSX, type ReactNode } from 'react';
+
+import type { LocalizerType } from '../types/Util.std.ts';
+import { AxoDialog } from '../axo/AxoDialog.dom.tsx';
+import { tw } from '../axo/tw.dom.tsx';
+import { type AxoSymbolIconName } from '../axo/_internal/AxoSymbolDefs.generated.std.ts';
+import { AxoSymbol } from '../axo/AxoSymbol.dom.tsx';
+import { I18n } from './I18n.dom.tsx';
+import { AxoAlertDialog } from '../axo/AxoAlertDialog.dom.tsx';
+import { AxoButton } from '../axo/AxoButton.dom.tsx';
+
+const LEARN_MORE_LINK =
+ 'https://support.signal.org/hc/articles/360007320551-Linked-Devices';
+
+export function MaybeTransferModal({
+ i18n,
+ onCancel,
+ onDontTransfer,
+ onTransfer,
+ open,
+}: {
+ i18n: LocalizerType;
+ onCancel: () => void;
+ onDontTransfer: () => void;
+ onTransfer: () => void;
+ open: boolean;
+}): JSX.Element {
+ return (
+ {
+ if (!isOpen) {
+ onCancel();
+ }
+ }}
+ >
+
+
+