diff --git a/native/account/registration/auth-navigator.react.js b/native/account/registration/auth-navigator.react.js
--- a/native/account/registration/auth-navigator.react.js
+++ b/native/account/registration/auth-navigator.react.js
@@ -57,9 +57,11 @@
RestorePromptScreenRouteName,
RestorePasswordAccountScreenRouteName,
RestoreBackupScreenRouteName,
+ RestoreBackupErrorScreenRouteName,
RestoreSIWEBackupRouteName,
} from '../../navigation/route-names.js';
import QRCodeScreen from '../qr-code-screen.react.js';
+import RestoreBackupErrorScreen from '../restore-backup-error-screen.react.js';
import RestoreBackupScreen from '../restore-backup-screen.react.js';
import RestorePasswordAccountScreen from '../restore-password-account-screen.react.js';
import RestorePromptScreen from '../restore-prompt-screen.react.js';
@@ -223,6 +225,11 @@
component={RestoreBackupScreen}
options={disableGesturesScreenOptions}
/>
+
,
+ +route: NavigationRoute<'RestoreBackupErrorScreen'>,
+};
+
+export type RestoreBackupErrorScreenParams = {
+ +deviceType: 'primary' | 'secondary',
+ +errorDetails?: ?string,
+};
+
+function RestoreBackupErrorScreen(props: Props): React.Node {
+ const styles = useStyles(unboundStyles);
+ const { deviceType, errorDetails: errorDetailsProp } = props.route.params;
+
+ const storedError = useSelector(state =>
+ state.restoreBackupState.status === 'user_data_restore_failed'
+ ? state.restoreBackupState.payload.error
+ : null,
+ );
+ const errorDetails = React.useMemo(() => {
+ if (errorDetailsProp) {
+ return errorDetailsProp;
+ } else if (storedError) {
+ const messageForException = getMessageForException(storedError);
+ return messageForException ?? 'unknown_error';
+ }
+
+ console.warn('Restore error screen shown but no error details provided');
+ return 'unknown_error';
+ }, [errorDetailsProp, storedError]);
+
+ const dispatch = useDispatch();
+
+ const ignoreErrorAndLogIn = React.useCallback(() => {
+ dispatch({
+ type: markBackupAsRestoredActionType,
+ });
+ }, [dispatch]);
+
+ const onPressIgnore = React.useCallback(() => {
+ Alert.alert(
+ 'Continue without full restoration?',
+ 'Some of your data could not be restored from backup. You can still use the app, but recent messages and settings may be missing.',
+ [
+ { text: 'Cancel', style: 'cancel' },
+ {
+ text: 'Continue',
+ onPress: ignoreErrorAndLogIn,
+ style: 'destructive',
+ },
+ ],
+ { cancelable: true },
+ );
+ }, [ignoreErrorAndLogIn]);
+
+ const onPressTryAgain = React.useCallback(() => {
+ dispatch({
+ type: resetBackupRestoreStateActionType,
+ });
+
+ props.navigation.popToTop();
+ }, [props.navigation, dispatch]);
+
+ let deviceTypeWarning;
+ if (deviceType === 'secondary') {
+ deviceTypeWarning = (
+
+ Your backup appears to be corrupt. Be careful with your primary device,
+ as you may lose data if you log out of it at this time.
+
+ );
+ } else {
+ deviceTypeWarning = (
+
+ Failed to restore your data from backup.
+
+ );
+ }
+
+ return (
+
+
+ Restoration failed
+ {deviceTypeWarning}
+
+ Error message:
+
+ {errorDetails} Long long long long long long long long long long
+ long long text
+
+
+
+ For help recovering your data, email support@comm.app or message
+ Ashoat on the app.
+
+
+
+
+
+
+
+ );
+}
+
+const unboundStyles = {
+ header: {
+ fontSize: 24,
+ color: 'panelForegroundLabel',
+ paddingBottom: 16,
+ },
+ section: {
+ fontFamily: 'Arial',
+ fontSize: 15,
+ lineHeight: 20,
+ color: 'panelForegroundSecondaryLabel',
+ paddingBottom: 16,
+ },
+ errorDetailsContainer: {
+ backgroundColor: 'codeBackground',
+ padding: 12,
+ marginBottom: 16,
+ borderRadius: 8,
+ },
+ errorDetailsHeader: {
+ fontFamily: 'Arial',
+ fontSize: 14,
+ fontWeight: 'bold',
+ color: 'panelForegroundLabel',
+ marginBottom: 8,
+ },
+ errorDetails: {
+ fontFamily: 'Menlo',
+ fontSize: 12,
+ color: 'panelForegroundSecondaryLabel',
+ lineHeight: 16,
+ },
+ scrollViewContentContainer: {
+ flexGrow: 1,
+ },
+};
+
+export default RestoreBackupErrorScreen;
diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js
--- a/native/navigation/route-names.js
+++ b/native/navigation/route-names.js
@@ -3,7 +3,7 @@
import type { RouteProp } from '@react-navigation/core';
import type { ActionResultModalParams } from './action-result-modal.react.js';
-import type { InviteLinkModalParams } from './invite-link-modal.react';
+import type { InviteLinkModalParams } from './invite-link-modal.react.js';
import type { NUXTipsOverlayBackdropParams } from './nux-tip-overlay-backdrop.react.js';
import type { ConnectSecondaryDeviceParams } from '../account/qr-auth/connect-secondary-device.react.js';
import type { AvatarSelectionParams } from '../account/registration/avatar-selection.react.js';
@@ -16,7 +16,8 @@
import type { RegistrationTermsParams } from '../account/registration/registration-terms.react.js';
import type { CreateSIWEBackupMessageParams } from '../account/registration/siwe-backup-message-creation.react.js';
import type { UsernameSelectionParams } from '../account/registration/username-selection.react.js';
-import type { RestoreBackupScreenParams } from '../account/restore-backup-screen.react';
+import type { RestoreBackupErrorScreenParams } from '../account/restore-backup-error-screen.react.js';
+import type { RestoreBackupScreenParams } from '../account/restore-backup-screen.react.js';
import type { TermsAndPrivacyModalParams } from '../account/terms-and-privacy-modal.react.js';
import type { RestoreSIWEBackupParams } from '../backup/restore-siwe-backup.react.js';
import type { ThreadPickerModalParams } from '../calendar/thread-picker-modal.react.js';
@@ -159,6 +160,7 @@
export const RestorePasswordAccountScreenRouteName =
'RestorePasswordAccountScreen';
export const RestoreBackupScreenRouteName = 'RestoreBackupScreen';
+export const RestoreBackupErrorScreenRouteName = 'RestoreBackupErrorScreen';
export const UserProfileBottomSheetNavigatorRouteName =
'UserProfileBottomSheetNavigator';
export const UserProfileBottomSheetRouteName = 'UserProfileBottomSheet';
@@ -337,6 +339,7 @@
+RestorePromptScreen: void,
+RestorePasswordAccountScreen: void,
+RestoreBackupScreen: RestoreBackupScreenParams,
+ +RestoreBackupErrorScreen: RestoreBackupErrorScreenParams,
+RestoreSIWEBackup: RestoreSIWEBackupParams,
};