signal-desktop/ts/state/smart/InstallScreen.tsx

145 lines
4.6 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2021 Signal Messenger, LLC
2021-12-16 15:02:22 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import type { ComponentProps } from 'react';
2024-09-04 02:56:13 +00:00
import React, { memo, useCallback, useState, useEffect } from 'react';
2021-12-16 15:02:22 +00:00
import { useSelector } from 'react-redux';
2024-09-04 02:56:13 +00:00
2021-12-16 15:02:22 +00:00
import { getIntl } from '../selectors/user';
2023-03-20 20:42:00 +00:00
import { getUpdatesState } from '../selectors/updates';
2024-09-04 02:56:13 +00:00
import { getInstallerState } from '../selectors/installer';
2024-09-11 18:03:18 +00:00
import { useAppActions } from '../ducks/app';
2024-09-04 02:56:13 +00:00
import { useInstallerActions } from '../ducks/installer';
2023-03-20 20:42:00 +00:00
import { useUpdatesActions } from '../ducks/updates';
import { hasExpired as hasExpiredSelector } from '../selectors/expiration';
2021-12-16 15:02:22 +00:00
import { missingCaseError } from '../../util/missingCaseError';
2024-09-11 18:03:18 +00:00
import { backupsService } from '../../services/backups';
2024-09-04 02:56:13 +00:00
import { InstallScreen } from '../../components/InstallScreen';
import { WidthBreakpoint } from '../../components/_util';
2024-09-04 02:56:13 +00:00
import { InstallScreenStep } from '../../types/InstallScreen';
import OS from '../../util/os/osMain';
2024-03-15 14:20:33 +00:00
import { fileToBytes } from '../../util/fileToBytes';
2024-09-04 18:12:45 +00:00
import { isStagingServer } from '../../util/isStagingServer';
2024-09-04 02:56:13 +00:00
import * as log from '../../logging/log';
import { SmartToastManager } from './ToastManager';
2021-12-16 15:02:22 +00:00
type PropsType = ComponentProps<typeof InstallScreen>;
export const SmartInstallScreen = memo(function SmartInstallScreen() {
2021-12-16 15:02:22 +00:00
const i18n = useSelector(getIntl);
2024-09-04 02:56:13 +00:00
const installerState = useSelector(getInstallerState);
2023-03-20 20:42:00 +00:00
const updates = useSelector(getUpdatesState);
2024-09-11 18:03:18 +00:00
const { openInbox } = useAppActions();
const { startInstaller, finishInstall, retryBackupImport } =
useInstallerActions();
2023-03-20 20:42:00 +00:00
const { startUpdate } = useUpdatesActions();
const hasExpired = useSelector(hasExpiredSelector);
2021-12-16 15:02:22 +00:00
2024-09-04 02:56:13 +00:00
const [deviceName, setDeviceName] = useState<string>('');
const [backupFile, setBackupFile] = useState<File | undefined>();
2021-12-16 15:02:22 +00:00
2024-09-04 02:56:13 +00:00
const onSubmitDeviceName = useCallback(async () => {
if (backupFile != null) {
// This is only for testing so don't bother catching errors
finishInstall({ deviceName, backupFile: await fileToBytes(backupFile) });
} else {
finishInstall({ deviceName, backupFile: undefined });
2021-12-16 15:02:22 +00:00
}
2024-09-04 02:56:13 +00:00
}, [backupFile, deviceName, finishInstall]);
2021-12-16 15:02:22 +00:00
2024-09-11 18:03:18 +00:00
const onCancelBackupImport = useCallback((): void => {
backupsService.cancelDownload();
if (installerState.step === InstallScreenStep.BackupImport) {
openInbox();
}
}, [installerState.step, openInbox]);
2024-09-04 02:56:13 +00:00
const suggestedDeviceName =
installerState.step === InstallScreenStep.ChoosingDeviceName
? installerState.deviceName
: undefined;
2021-12-16 15:02:22 +00:00
useEffect(() => {
2024-09-04 02:56:13 +00:00
setDeviceName(suggestedDeviceName ?? '');
}, [suggestedDeviceName]);
2021-12-16 15:02:22 +00:00
let props: PropsType;
2024-09-04 02:56:13 +00:00
switch (installerState.step) {
case InstallScreenStep.NotStarted:
log.error('InstallScreen: Installer not started');
return null;
2021-12-16 15:02:22 +00:00
case InstallScreenStep.QrCodeNotScanned:
props = {
step: InstallScreenStep.QrCodeNotScanned,
screenSpecificProps: {
i18n,
2024-09-04 02:56:13 +00:00
provisioningUrl: installerState.provisioningUrl,
2023-03-20 20:42:00 +00:00
hasExpired,
updates,
currentVersion: window.getVersion(),
startUpdate,
2024-09-04 02:56:13 +00:00
retryGetQrCode: startInstaller,
OS: OS.getName(),
2024-09-04 18:12:45 +00:00
isStaging: isStagingServer(),
2021-12-16 15:02:22 +00:00
},
};
break;
case InstallScreenStep.ChoosingDeviceName:
props = {
step: InstallScreenStep.ChoosingDeviceName,
screenSpecificProps: {
i18n,
2024-09-04 02:56:13 +00:00
deviceName,
2021-12-16 15:02:22 +00:00
setDeviceName,
2024-03-15 14:20:33 +00:00
setBackupFile,
2021-12-16 15:02:22 +00:00
onSubmit: onSubmitDeviceName,
},
};
break;
case InstallScreenStep.LinkInProgress:
props = {
step: InstallScreenStep.LinkInProgress,
screenSpecificProps: { i18n },
};
break;
2024-09-04 02:56:13 +00:00
case InstallScreenStep.BackupImport:
props = {
step: InstallScreenStep.BackupImport,
screenSpecificProps: {
i18n,
currentBytes: installerState.currentBytes,
totalBytes: installerState.totalBytes,
hasError: installerState.hasError,
2024-09-11 18:03:18 +00:00
onCancel: onCancelBackupImport,
onRetry: retryBackupImport,
2024-09-04 02:56:13 +00:00
},
};
break;
case InstallScreenStep.Error:
props = {
step: InstallScreenStep.Error,
screenSpecificProps: {
i18n,
error: installerState.error,
quit: () => window.IPC.shutdown(),
tryAgain: startInstaller,
},
};
break;
2021-12-16 15:02:22 +00:00
default:
2024-09-04 02:56:13 +00:00
throw missingCaseError(installerState);
2021-12-16 15:02:22 +00:00
}
return (
<>
<InstallScreen {...props} />
<SmartToastManager
disableMegaphone
containerWidthBreakpoint={WidthBreakpoint.Narrow}
/>
</>
);
});