// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { type ReactNode } from 'react';
import {
LocalExportErrors,
LocalBackupExportSteps,
} from '../types/LocalExport.std.js';
import { AxoDialog } from '../axo/AxoDialog.dom.js';
import { AxoAlertDialog } from '../axo/AxoAlertDialog.dom.js';
import type { LocalBackupExportWorkflowType } from '../types/LocalExport.std.js';
import type { LocalizerType } from '../types/I18N.std.js';
import { formatFileSize } from '../util/formatFileSize.std.js';
import { ProgressBar } from './ProgressBar.dom.js';
import { missingCaseError } from '../util/missingCaseError.std.js';
import { tw } from '../axo/tw.dom.js';
import { AxoSymbol } from '../axo/AxoSymbol.dom.js';
import type { AxoSymbolIconName } from '../axo/_internal/AxoSymbolDefs.generated.std.js';
export type PropsType = {
cancelWorkflow: () => void;
clearWorkflow: () => void;
i18n: LocalizerType;
openFileInFolder: (path: string) => void;
osName: 'linux' | 'macos' | 'windows' | undefined;
workflow: LocalBackupExportWorkflowType;
};
export function LocalBackupExportWorkflow({
cancelWorkflow,
clearWorkflow,
i18n,
openFileInFolder,
osName,
workflow,
}: PropsType): React.JSX.Element {
const { step } = workflow;
if (
step === LocalBackupExportSteps.ExportingMessages ||
step === LocalBackupExportSteps.ExportingAttachments
) {
const progress =
step === LocalBackupExportSteps.ExportingAttachments
? workflow.progress
: undefined;
let progressElements;
if (progress) {
const fractionComplete =
progress.totalBytes > 0
? progress.currentBytes / progress.totalBytes
: 0;
progressElements = (
<>
{i18n('icu:PlaintextExport--ProgressDialog--Progress', {
currentBytes: formatFileSize(progress.currentBytes),
totalBytes: formatFileSize(progress.totalBytes),
percentage: fractionComplete,
})}
>
);
} else {
progressElements = (
);
}
return (
{i18n('icu:LocalBackupExport--ProgressDialog--Header')}
{progressElements}
{i18n('icu:PlaintextExport--ProgressDialog--TimeWarning')}
);
}
if (step === LocalBackupExportSteps.Complete) {
let showInFolderText = i18n(
'icu:PlaintextExport--CompleteDialog--ShowFiles--Windows'
);
if (osName === 'macos') {
showInFolderText = i18n(
'icu:PlaintextExport--CompleteDialog--ShowFiles--Mac'
);
} else if (osName === 'linux') {
showInFolderText = i18n(
'icu:PlaintextExport--CompleteDialog--ShowFiles--Linux'
);
}
return (
{i18n('icu:LocalBackupExport--CompleteDialog--Header')}
{i18n(
'icu:LocalBackupExport--CompleteDialog--RestoreInstructionsHeader'
)}
{
openFileInFolder(workflow.localBackupFolder);
clearWorkflow();
}}
>
{showInFolderText}
{i18n('icu:ok')}
);
}
if (step === LocalBackupExportSteps.Error) {
const { type } = workflow.errorDetails;
let title;
let detail;
if (type === LocalExportErrors.General) {
title = i18n('icu:PlaintextExport--Error--General--Title');
detail = i18n('icu:PlaintextExport--Error--General--Description');
} else if (type === LocalExportErrors.NotEnoughStorage) {
title = i18n('icu:PlaintextExport--Error--NotEnoughStorage--Title');
detail = i18n('icu:PlaintextExport--Error--NotEnoughStorage--Detail', {
bytes: formatFileSize(workflow.errorDetails.bytesNeeded),
});
} else if (type === LocalExportErrors.RanOutOfStorage) {
title = i18n('icu:PlaintextExport--Error--RanOutOfStorage--Title');
detail = i18n('icu:PlaintextExport--Error--RanOutOfStorage--Detail', {
bytes: formatFileSize(workflow.errorDetails.bytesNeeded),
});
} else if (type === LocalExportErrors.StoragePermissions) {
title = i18n('icu:PlaintextExport--Error--DiskPermssions--Title');
detail = i18n('icu:PlaintextExport--Error--DiskPermssions--Detail');
} else {
throw missingCaseError(type);
}
return (
{title}
{detail}
{i18n('icu:ok')}
);
}
throw missingCaseError(step);
}
function ListItemWithIcon({
iconName,
content,
}: {
iconName: AxoSymbolIconName;
content: ReactNode;
}): ReactNode {
return (
{content}
);
}