@@ -65,7 +64,11 @@ export function InstallScreenQrCodeNotScannedStep({
)}
-
+
{i18n('icu:Install__scan-this-code')}
@@ -110,7 +113,7 @@ export function InstallScreenQrCodeNotScannedStep({
}
function InstallScreenQrCode(
- props: Loadable & { i18n: LocalizerType }
+ props: Loadable & { i18n: LocalizerType; retryGetQrCode: () => void }
): ReactElement {
const { i18n } = props;
@@ -124,11 +127,24 @@ function InstallScreenQrCode(
(
- {children}
+ retry: children => (
+
),
}}
/>
diff --git a/ts/state/smart/InstallScreen.tsx b/ts/state/smart/InstallScreen.tsx
index 9991e00b007b..5d6c8524968a 100644
--- a/ts/state/smart/InstallScreen.tsx
+++ b/ts/state/smart/InstallScreen.tsx
@@ -4,6 +4,7 @@
import type { ComponentProps, ReactElement } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
+import pTimeout, { TimeoutError } from 'p-timeout';
import { getIntl } from '../selectors/user';
import { getUpdatesState } from '../selectors/updates';
@@ -28,6 +29,9 @@ import { isRecord } from '../../util/isRecord';
import * as Errors from '../../types/errors';
import { normalizeDeviceName } from '../../util/normalizeDeviceName';
import OS from '../../util/os/osMain';
+import { SECOND } from '../../util/durations';
+import { BackOff } from '../../util/BackOff';
+import { drop } from '../../util/drop';
type PropsType = ComponentProps;
@@ -53,6 +57,13 @@ const INITIAL_STATE: StateType = {
provisioningUrl: { loadingState: LoadingState.Loading },
};
+const qrCodeBackOff = new BackOff([
+ 10 * SECOND,
+ 20 * SECOND,
+ 30 * SECOND,
+ 60 * SECOND,
+]);
+
function getInstallError(err: unknown): InstallError {
if (err instanceof HTTPError) {
switch (err.code) {
@@ -83,6 +94,7 @@ export function SmartInstallScreen(): ReactElement {
const chooseDeviceNamePromiseWrapperRef = useRef(explodePromise());
const [state, setState] = useState(INITIAL_STATE);
+ const [retryCounter, setRetryCounter] = useState(0);
const setProvisioningUrl = useCallback(
(value: string) => {
@@ -206,12 +218,16 @@ export function SmartInstallScreen(): ReactElement {
return result;
};
- void (async () => {
+ async function getQRCode(): Promise {
+ const sleepError = new TimeoutError();
try {
- await accountManager.registerSecondDevice(
+ const qrCodePromise = accountManager.registerSecondDevice(
updateProvisioningUrl,
confirmNumber
);
+ const sleepMs = qrCodeBackOff.getAndIncrement();
+ log.info(`InstallScreen/getQRCode: race to ${sleepMs}ms`);
+ await pTimeout(qrCodePromise, sleepMs, sleepError);
window.IPC.removeSetupMenuItems();
} catch (error) {
@@ -222,17 +238,36 @@ export function SmartInstallScreen(): ReactElement {
if (hasCleanedUp) {
return;
}
- setState({
- step: InstallScreenStep.Error,
- error: getInstallError(error),
- });
+
+ if (qrCodeBackOff.isFull()) {
+ log.error('InstallScreen/getQRCode: too many tries');
+ setState({
+ step: InstallScreenStep.Error,
+ error: InstallError.QRCodeFailed,
+ });
+ return;
+ }
+
+ if (error === sleepError) {
+ setState({
+ step: InstallScreenStep.QrCodeNotScanned,
+ provisioningUrl: { loadingState: LoadingState.LoadFailed, error },
+ });
+ } else {
+ setState({
+ step: InstallScreenStep.Error,
+ error: getInstallError(error),
+ });
+ }
}
- })();
+ }
+
+ drop(getQRCode());
return () => {
hasCleanedUp = true;
};
- }, [setProvisioningUrl, onQrCodeScanned]);
+ }, [setProvisioningUrl, retryCounter, onQrCodeScanned]);
let props: PropsType;
@@ -258,6 +293,10 @@ export function SmartInstallScreen(): ReactElement {
updates,
currentVersion: window.getVersion(),
startUpdate,
+ retryGetQrCode: () => {
+ setRetryCounter(count => count + 1);
+ setState(INITIAL_STATE);
+ },
OS: OS.getName(),
},
};
diff --git a/ts/types/support.ts b/ts/types/support.ts
index 8e2fa41ca127..251fb37f7a5a 100644
--- a/ts/types/support.ts
+++ b/ts/types/support.ts
@@ -5,3 +5,5 @@ export const PRODUCTION_DOWNLOAD_URL = 'https://signal.org/download/';
export const BETA_DOWNLOAD_URL = 'https://support.signal.org/beta';
export const UNSUPPORTED_OS_URL =
'https://support.signal.org/hc/articles/5109141421850';
+export const LINK_SIGNAL_DESKTOP =
+ 'https://support.signal.org/hc/articles/360007320451#desktop_multiple_device';