signal-desktop/ts/components/installScreen/InstallScreenBackupImportStep.tsx

207 lines
5.9 KiB
TypeScript
Raw Normal View History

2024-08-27 21:00:41 +00:00
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
2024-09-11 18:03:18 +00:00
import React, { useState, useCallback } from 'react';
2024-08-27 21:00:41 +00:00
2024-09-04 02:56:13 +00:00
import type { LocalizerType } from '../../types/Util';
import { InstallScreenBackupStep } from '../../types/InstallScreen';
2024-09-04 02:56:13 +00:00
import { formatFileSize } from '../../util/formatFileSize';
import { TitlebarDragArea } from '../TitlebarDragArea';
import { ProgressBar } from '../ProgressBar';
2024-09-11 18:03:18 +00:00
import { ConfirmationDialog } from '../ConfirmationDialog';
2024-09-04 02:56:13 +00:00
import { InstallScreenSignalLogo } from './InstallScreenSignalLogo';
import { roundFractionForProgressBar } from '../../util/numbers';
import { missingCaseError } from '../../util/missingCaseError';
2024-08-27 21:00:41 +00:00
// We can't always use destructuring assignment because of the complexity of this props
// type.
export type PropsType = Readonly<{
i18n: LocalizerType;
backupStep: InstallScreenBackupStep;
2024-08-27 21:00:41 +00:00
currentBytes?: number;
totalBytes?: number;
hasError?: boolean;
2024-09-11 18:03:18 +00:00
onCancel: () => void;
onRetry: () => void;
2024-08-27 21:00:41 +00:00
}>;
2024-09-04 02:56:13 +00:00
export function InstallScreenBackupImportStep({
2024-08-27 21:00:41 +00:00
i18n,
backupStep,
2024-08-27 21:00:41 +00:00
currentBytes,
totalBytes,
hasError,
2024-09-11 18:03:18 +00:00
onCancel,
onRetry,
2024-08-27 21:00:41 +00:00
}: PropsType): JSX.Element {
2024-09-11 18:03:18 +00:00
const [isConfirmingCancel, setIsConfirmingCancel] = useState(false);
const [isConfirmingSkip, setIsConfirmingSkip] = useState(false);
2024-09-11 18:03:18 +00:00
const confirmCancel = useCallback(() => {
setIsConfirmingCancel(true);
}, []);
const abortCancel = useCallback(() => {
setIsConfirmingCancel(false);
}, []);
const onCancelWrap = useCallback(() => {
onCancel();
setIsConfirmingCancel(false);
}, [onCancel]);
const confirmSkip = useCallback(() => {
setIsConfirmingSkip(true);
}, []);
const abortSkip = useCallback(() => {
setIsConfirmingSkip(false);
}, []);
const onSkipWrap = useCallback(() => {
onCancel();
setIsConfirmingSkip(false);
}, [onCancel]);
const onRetryWrap = useCallback(() => {
onRetry();
setIsConfirmingSkip(false);
}, [onRetry]);
2024-08-27 21:00:41 +00:00
let progress: JSX.Element;
if (currentBytes != null && totalBytes != null) {
const fractionComplete = roundFractionForProgressBar(
currentBytes / totalBytes
);
2024-08-27 21:00:41 +00:00
let hint: string;
if (backupStep === InstallScreenBackupStep.Download) {
hint = i18n('icu:BackupImportScreen__progressbar-hint', {
currentSize: formatFileSize(currentBytes),
totalSize: formatFileSize(totalBytes),
fractionComplete,
});
} else if (backupStep === InstallScreenBackupStep.Process) {
hint = i18n('icu:BackupImportScreen__progressbar-hint--processing');
} else {
throw missingCaseError(backupStep);
}
2024-08-27 21:00:41 +00:00
progress = (
<>
<ProgressBar
key={backupStep}
fractionComplete={fractionComplete}
isRTL={i18n.getLocaleDirection() === 'rtl'}
/>
2024-09-11 18:03:18 +00:00
<div className="InstallScreenBackupImportStep__progressbar-hint">
{hint}
2024-08-27 21:00:41 +00:00
</div>
</>
);
} else {
progress = (
<>
<ProgressBar
key={backupStep}
fractionComplete={0}
isRTL={i18n.getLocaleDirection() === 'rtl'}
/>
2024-09-11 18:03:18 +00:00
<div className="InstallScreenBackupImportStep__progressbar-hint">
{i18n('icu:BackupImportScreen__progressbar-hint--preparing')}
2024-08-27 21:00:41 +00:00
</div>
</>
);
}
2024-08-27 21:00:41 +00:00
return (
2024-09-11 18:03:18 +00:00
<div className="InstallScreenBackupImportStep">
2024-08-27 21:00:41 +00:00
<TitlebarDragArea />
<InstallScreenSignalLogo />
2024-09-11 18:03:18 +00:00
<div className="InstallScreenBackupImportStep__content">
<h3 className="InstallScreenBackupImportStep__title">
2024-08-27 21:00:41 +00:00
{i18n('icu:BackupImportScreen__title')}
</h3>
{progress}
2024-09-11 18:03:18 +00:00
<div className="InstallScreenBackupImportStep__description">
2024-08-27 21:00:41 +00:00
{i18n('icu:BackupImportScreen__description')}
</div>
</div>
2024-09-11 18:03:18 +00:00
{backupStep === InstallScreenBackupStep.Download && (
2024-09-11 18:03:18 +00:00
<button
className="InstallScreenBackupImportStep__cancel"
type="button"
onClick={confirmCancel}
>
{i18n('icu:BackupImportScreen__cancel')}
</button>
)}
{isConfirmingCancel && (
<ConfirmationDialog
dialogName="InstallScreenBackupImportStep.confirmCancel"
title={i18n('icu:BackupImportScreen__cancel-confirmation__title')}
cancelText={i18n(
'icu:BackupImportScreen__cancel-confirmation__cancel'
)}
actions={[
{
action: onCancelWrap,
style: 'negative',
text: i18n(
'icu:BackupImportScreen__cancel-confirmation__confirm'
),
},
]}
i18n={i18n}
onClose={abortCancel}
>
{i18n('icu:BackupImportScreen__cancel-confirmation__body')}
</ConfirmationDialog>
)}
{isConfirmingSkip && (
<ConfirmationDialog
dialogName="InstallScreenBackupImportStep.confirmSkip"
title={i18n('icu:BackupImportScreen__skip-confirmation__title')}
cancelText={i18n('icu:BackupImportScreen__skip-confirmation__cancel')}
actions={[
{
action: onSkipWrap,
style: 'affirmative',
text: i18n('icu:BackupImportScreen__skip'),
},
]}
i18n={i18n}
onClose={abortSkip}
>
{i18n('icu:BackupImportScreen__skip-confirmation__body')}
</ConfirmationDialog>
)}
{hasError && !isConfirmingSkip && (
<ConfirmationDialog
dialogName="InstallScreenBackupImportStep.error"
title={i18n('icu:BackupImportScreen__error__title')}
cancelText={i18n('icu:BackupImportScreen__skip')}
actions={[
{
action: onRetryWrap,
style: 'affirmative',
text: i18n('icu:BackupImportScreen__error__confirm'),
},
]}
i18n={i18n}
onClose={confirmSkip}
>
{i18n('icu:BackupImportScreen__error__body')}
</ConfirmationDialog>
)}
2024-08-27 21:00:41 +00:00
</div>
);
}