mirror of
https://github.com/selfxyz/self.git
synced 2026-01-10 07:08:10 -05:00
SELF-1262:Hotfix/hide unregistered document (#1423)
* hide unregistered documents
* redirect to 'Home' instead of 'Launch'
* RecoverWithPhraseScreen: wrap restoreAccount in try-catch
* Revert "RecoverWithPhraseScreen: wrap restoreAccount in try-catch"
This reverts commit e53b5630ca.
* RecoverWithPhraseScreen: wrap restoreAccount in try-catch
* update lock
* fix types
* bump version
* remove launch screen
* update bundle version
* add new events
* fix nested react requires
* fix heavy tests
* address fake mocks
* fix test
* address codex and coderabbit logic conceners
* fix linting
* remove last borked react test
---------
Co-authored-by: Justin Hernandez <justin.hernandez@self.xyz>
This commit is contained in:
@@ -22,7 +22,7 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1183.0)
|
||||
aws-partitions (1.1184.0)
|
||||
aws-sdk-core (3.237.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
|
||||
@@ -10,19 +10,12 @@ import type { DocumentCategory } from '@selfxyz/common/utils/types';
|
||||
|
||||
import DeferredLinkingInfoScreen from '@/screens/app/DeferredLinkingInfoScreen';
|
||||
import GratificationScreen from '@/screens/app/GratificationScreen';
|
||||
import LaunchScreen from '@/screens/app/LaunchScreen';
|
||||
import LoadingScreen from '@/screens/app/LoadingScreen';
|
||||
import type { ModalNavigationParams } from '@/screens/app/ModalScreen';
|
||||
import ModalScreen from '@/screens/app/ModalScreen';
|
||||
import SplashScreen from '@/screens/app/SplashScreen';
|
||||
|
||||
const appScreens = {
|
||||
Launch: {
|
||||
screen: LaunchScreen,
|
||||
options: {
|
||||
header: () => <SystemBars style="light" />,
|
||||
},
|
||||
},
|
||||
Loading: {
|
||||
screen: LoadingScreen,
|
||||
options: {
|
||||
|
||||
@@ -156,14 +156,10 @@ export const SelfClientProvider = ({ children }: PropsWithChildren) => {
|
||||
|
||||
addListener(
|
||||
SdkEvents.PROVING_REGISTER_ERROR_OR_FAILURE,
|
||||
async ({ hasValidDocument }) => {
|
||||
async ({ hasValidDocument: _hasValidDocument }) => {
|
||||
setTimeout(() => {
|
||||
if (navigationRef.isReady()) {
|
||||
if (hasValidDocument) {
|
||||
navigationRef.navigate({ name: 'Home', params: {} });
|
||||
} else {
|
||||
navigationRef.navigate({ name: 'Launch', params: undefined });
|
||||
}
|
||||
navigationRef.navigate({ name: 'Home', params: {} });
|
||||
}
|
||||
}, 3000);
|
||||
},
|
||||
|
||||
@@ -79,7 +79,7 @@ const AccountRecoveryChoiceScreen: React.FC = () => {
|
||||
if (!result) {
|
||||
console.warn('Failed to restore account');
|
||||
trackEvent(BackupEvents.CLOUD_RESTORE_FAILED_UNKNOWN);
|
||||
navigation.navigate('Launch');
|
||||
navigation.navigate({ name: 'Home', params: {} });
|
||||
setRestoring(false);
|
||||
return false;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ const AccountRecoveryChoiceScreen: React.FC = () => {
|
||||
'Secret provided did not match a registered ID. Please try again.',
|
||||
);
|
||||
trackEvent(BackupEvents.CLOUD_RESTORE_FAILED_PASSPORT_NOT_REGISTERED);
|
||||
navigation.navigate('Launch');
|
||||
navigation.navigate({ name: 'Home', params: {} });
|
||||
setRestoring(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const { flush: flushAnalytics } = analytics();
|
||||
|
||||
const DocumentDataNotFoundScreen: React.FC = () => {
|
||||
const selfClient = useSelfClient();
|
||||
const navigateToLaunch = useHapticNavigation('Launch');
|
||||
const navigateToCountryPicker = useHapticNavigation('CountryPicker');
|
||||
const navigateToHome = useHapticNavigation('Home');
|
||||
|
||||
const onPress = async () => {
|
||||
@@ -31,7 +31,7 @@ const DocumentDataNotFoundScreen: React.FC = () => {
|
||||
if (hasValidDocument) {
|
||||
navigateToHome();
|
||||
} else {
|
||||
navigateToLaunch();
|
||||
navigateToCountryPicker();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -55,57 +55,88 @@ const RecoverWithPhraseScreen: React.FC = () => {
|
||||
}, []);
|
||||
|
||||
const restoreAccount = useCallback(async () => {
|
||||
setRestoring(true);
|
||||
const slimMnemonic = mnemonic?.trim();
|
||||
if (!slimMnemonic || !ethers.Mnemonic.isValidMnemonic(slimMnemonic)) {
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
const result = await restoreAccountFromMnemonic(slimMnemonic);
|
||||
try {
|
||||
setRestoring(true);
|
||||
const slimMnemonic = mnemonic?.trim();
|
||||
if (!slimMnemonic || !ethers.Mnemonic.isValidMnemonic(slimMnemonic)) {
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
const result = await restoreAccountFromMnemonic(slimMnemonic);
|
||||
|
||||
if (!result) {
|
||||
console.warn('Failed to restore account');
|
||||
navigation.navigate('Launch');
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
if (!result) {
|
||||
console.warn('Failed to restore account');
|
||||
trackEvent(BackupEvents.CLOUD_RESTORE_FAILED_AUTH, {
|
||||
mnemonicLength: slimMnemonic.split(' ').length,
|
||||
});
|
||||
navigation.navigate({ name: 'Home', params: {} });
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const passportDataAndSecret = (await loadPassportDataAndSecret()) as string;
|
||||
const { passportData, secret } = JSON.parse(passportDataAndSecret);
|
||||
const { isRegistered, csca } = await isUserRegisteredWithAlternativeCSCA(
|
||||
passportData,
|
||||
secret as string,
|
||||
{
|
||||
getCommitmentTree(docCategory) {
|
||||
return useProtocolStore.getState()[docCategory].commitment_tree;
|
||||
const passportDataAndSecret = await loadPassportDataAndSecret();
|
||||
if (!passportDataAndSecret) {
|
||||
console.warn(
|
||||
'No passport data found on device. Please scan or import your document.',
|
||||
);
|
||||
trackEvent(BackupEvents.CLOUD_RESTORE_FAILED_AUTH, {
|
||||
reason: 'no_passport_data',
|
||||
});
|
||||
navigation.navigate({ name: 'Home', params: {} });
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
const { passportData, secret } = JSON.parse(passportDataAndSecret);
|
||||
const { isRegistered, csca } = await isUserRegisteredWithAlternativeCSCA(
|
||||
passportData,
|
||||
secret as string,
|
||||
{
|
||||
getCommitmentTree(docCategory) {
|
||||
return useProtocolStore.getState()[docCategory].commitment_tree;
|
||||
},
|
||||
getAltCSCA(docCategory) {
|
||||
if (docCategory === 'aadhaar') {
|
||||
const publicKeys =
|
||||
useProtocolStore.getState().aadhaar.public_keys;
|
||||
// Convert string[] to Record<string, string> format expected by AlternativeCSCA
|
||||
return publicKeys
|
||||
? Object.fromEntries(publicKeys.map(key => [key, key]))
|
||||
: {};
|
||||
}
|
||||
|
||||
return useProtocolStore.getState()[docCategory].alternative_csca;
|
||||
},
|
||||
},
|
||||
getAltCSCA(docCategory) {
|
||||
if (docCategory === 'aadhaar') {
|
||||
const publicKeys = useProtocolStore.getState().aadhaar.public_keys;
|
||||
// Convert string[] to Record<string, string> format expected by AlternativeCSCA
|
||||
return publicKeys
|
||||
? Object.fromEntries(publicKeys.map(key => [key, key]))
|
||||
: {};
|
||||
}
|
||||
|
||||
return useProtocolStore.getState()[docCategory].alternative_csca;
|
||||
},
|
||||
},
|
||||
);
|
||||
if (!isRegistered) {
|
||||
console.warn(
|
||||
'Secret provided did not match a registered passport. Please try again.',
|
||||
);
|
||||
reStorePassportDataWithRightCSCA(passportData, csca as string);
|
||||
navigation.navigate('Launch');
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
if (!isRegistered) {
|
||||
console.warn(
|
||||
'Secret provided did not match a registered passport. Please try again.',
|
||||
);
|
||||
trackEvent(BackupEvents.CLOUD_RESTORE_FAILED_PASSPORT_NOT_REGISTERED, {
|
||||
reason: 'document_not_registered',
|
||||
hasCSCA: !!csca,
|
||||
});
|
||||
navigation.navigate({ name: 'Home', params: {} });
|
||||
setRestoring(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setRestoring(false);
|
||||
await markCurrentDocumentAsRegistered(selfClient);
|
||||
trackEvent(BackupEvents.ACCOUNT_RECOVERY_COMPLETED);
|
||||
navigation.navigate('AccountVerifiedSuccess');
|
||||
if (csca) {
|
||||
await reStorePassportDataWithRightCSCA(passportData, csca);
|
||||
}
|
||||
|
||||
await markCurrentDocumentAsRegistered(selfClient);
|
||||
setRestoring(false);
|
||||
trackEvent(BackupEvents.ACCOUNT_RECOVERY_COMPLETED);
|
||||
navigation.navigate('AccountVerifiedSuccess');
|
||||
} catch (error) {
|
||||
trackEvent(BackupEvents.CLOUD_RESTORE_FAILED_UNKNOWN, {
|
||||
reason: 'unexpected_error',
|
||||
error: error instanceof Error ? error.message : 'unknown',
|
||||
});
|
||||
setRestoring(false);
|
||||
navigation.navigate({ name: 'Home', params: {} });
|
||||
}
|
||||
}, [
|
||||
mnemonic,
|
||||
navigation,
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { Pressable, StyleSheet, View } from 'react-native';
|
||||
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { Anchor, Text, YStack } from 'tamagui';
|
||||
import { useTurnkey } from '@turnkey/react-native-wallet-kit';
|
||||
|
||||
import {
|
||||
AbstractButton,
|
||||
BodyText,
|
||||
Caption,
|
||||
} from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import { AppEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
|
||||
|
||||
import { privacyUrl, termsUrl } from '@/consts/links';
|
||||
import useConnectionModal from '@/hooks/useConnectionModal';
|
||||
import useHapticNavigation from '@/hooks/useHapticNavigation';
|
||||
import { useModal } from '@/hooks/useModal';
|
||||
import IDCardPlaceholder from '@/images/icons/id_card_placeholder.svg';
|
||||
import {
|
||||
black,
|
||||
red500,
|
||||
slate300,
|
||||
slate400,
|
||||
white,
|
||||
zinc800,
|
||||
} from '@/utils/colors';
|
||||
import { advercase, dinot } from '@/utils/fonts';
|
||||
|
||||
const LaunchScreen: React.FC = () => {
|
||||
useConnectionModal();
|
||||
const { handleGoogleOauth, fetchWallets } = useTurnkey();
|
||||
const onPress = useHapticNavigation('CountryPicker');
|
||||
const createMock = useHapticNavigation('CreateMock');
|
||||
const { bottom } = useSafeAreaInsets();
|
||||
|
||||
const { showModal: showNoWalletsModal } = useModal({
|
||||
titleText: 'No wallets found',
|
||||
bodyText: 'No wallets found. Please sign in with Turnkey to continue.',
|
||||
buttonText: 'OK',
|
||||
onButtonPress: () => {},
|
||||
onModalDismiss: () => {},
|
||||
});
|
||||
const onImportWalletPress = async () => {
|
||||
try {
|
||||
await handleGoogleOauth();
|
||||
const fetchedWallets = await fetchWallets();
|
||||
|
||||
if (fetchedWallets.length === 0) {
|
||||
showNoWalletsModal();
|
||||
return;
|
||||
}
|
||||
|
||||
onPress();
|
||||
} catch {
|
||||
console.error('handleGoogleOauth error');
|
||||
}
|
||||
};
|
||||
|
||||
const devModeTap = Gesture.Tap()
|
||||
.numberOfTaps(5)
|
||||
.onStart(() => {
|
||||
createMock();
|
||||
});
|
||||
|
||||
return (
|
||||
<YStack backgroundColor={black} flex={1} alignItems="center">
|
||||
<View style={styles.container}>
|
||||
<YStack flex={1} justifyContent="center" alignItems="center">
|
||||
<GestureDetector gesture={devModeTap}>
|
||||
<YStack
|
||||
backgroundColor={red500}
|
||||
borderRadius={14}
|
||||
overflow="hidden"
|
||||
>
|
||||
<IDCardPlaceholder width={300} height={180} />
|
||||
</YStack>
|
||||
</GestureDetector>
|
||||
</YStack>
|
||||
<Text
|
||||
color={white}
|
||||
fontSize={38}
|
||||
fontFamily={advercase}
|
||||
fontWeight="500"
|
||||
textAlign="center"
|
||||
marginBottom={16}
|
||||
>
|
||||
Take control of your digital identity
|
||||
</Text>
|
||||
<BodyText
|
||||
style={{
|
||||
color: slate300,
|
||||
fontSize: 16,
|
||||
textAlign: 'center',
|
||||
marginHorizontal: 40,
|
||||
marginBottom: 40,
|
||||
}}
|
||||
>
|
||||
Self is the easiest way to verify your identity safely wherever you
|
||||
are.
|
||||
</BodyText>
|
||||
</View>
|
||||
|
||||
<YStack
|
||||
gap="$3"
|
||||
width="100%"
|
||||
alignItems="center"
|
||||
paddingHorizontal={20}
|
||||
paddingBottom={bottom}
|
||||
paddingTop={30}
|
||||
backgroundColor={zinc800}
|
||||
>
|
||||
<AbstractButton
|
||||
trackEvent={AppEvents.GET_STARTED}
|
||||
onPress={onPress}
|
||||
bgColor={white}
|
||||
color={black}
|
||||
testID="launch-get-started-button"
|
||||
>
|
||||
Get Started
|
||||
</AbstractButton>
|
||||
|
||||
<Pressable onPress={onImportWalletPress}>
|
||||
<Text style={styles.disclaimer}>
|
||||
<Text style={styles.haveAnAccount}>{`Have an account? `}</Text>
|
||||
<Text style={styles.restore}>restore</Text>
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
<Caption style={styles.notice}>
|
||||
By continuing, you agree to the
|
||||
<Anchor style={styles.link} href={termsUrl}>
|
||||
User Terms and Conditions
|
||||
</Anchor>
|
||||
and acknowledge the
|
||||
<Anchor style={styles.link} href={privacyUrl}>
|
||||
Privacy notice
|
||||
</Anchor>
|
||||
of Self provided by Self Inc.
|
||||
</Caption>
|
||||
</YStack>
|
||||
</YStack>
|
||||
);
|
||||
};
|
||||
|
||||
export default LaunchScreen;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: '102%',
|
||||
paddingTop: '30%',
|
||||
},
|
||||
card: {
|
||||
width: '100%',
|
||||
marginTop: '20%',
|
||||
borderRadius: 16,
|
||||
paddingVertical: 40,
|
||||
paddingHorizontal: 20,
|
||||
alignItems: 'center',
|
||||
shadowColor: black,
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 12,
|
||||
elevation: 8,
|
||||
marginBottom: 8,
|
||||
},
|
||||
logoSection: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
marginBottom: 24,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
logo: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
},
|
||||
disclaimer: {
|
||||
width: '100%',
|
||||
fontSize: 11,
|
||||
letterSpacing: 0.4,
|
||||
textTransform: 'uppercase',
|
||||
fontWeight: '500',
|
||||
fontFamily: dinot,
|
||||
textAlign: 'center',
|
||||
},
|
||||
haveAnAccount: {
|
||||
color: '#6b7280',
|
||||
},
|
||||
restore: {
|
||||
color: '#fff',
|
||||
},
|
||||
notice: {
|
||||
fontFamily: dinot,
|
||||
marginVertical: 10,
|
||||
paddingBottom: 10,
|
||||
color: slate400,
|
||||
textAlign: 'center',
|
||||
lineHeight: 22,
|
||||
fontSize: 14,
|
||||
},
|
||||
link: {
|
||||
fontFamily: dinot,
|
||||
color: slate400,
|
||||
lineHeight: 22,
|
||||
textDecorationLine: 'underline',
|
||||
},
|
||||
});
|
||||
@@ -95,8 +95,8 @@ const SplashScreen: React.FC = ({}) => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error in SplashScreen data loading: ${error}`);
|
||||
setDeeplinkParentScreen('Launch');
|
||||
setNextScreen('Launch');
|
||||
setDeeplinkParentScreen('Home');
|
||||
setNextScreen('Home');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,11 +7,7 @@ import { StyleSheet } from 'react-native';
|
||||
import { View, XStack, YStack } from 'tamagui';
|
||||
import { useIsFocused } from '@react-navigation/native';
|
||||
|
||||
import {
|
||||
DelayedLottieView,
|
||||
hasAnyValidRegisteredDocument,
|
||||
useSelfClient,
|
||||
} from '@selfxyz/mobile-sdk-alpha';
|
||||
import { DelayedLottieView } from '@selfxyz/mobile-sdk-alpha';
|
||||
import {
|
||||
Additional,
|
||||
Description,
|
||||
@@ -33,27 +29,18 @@ import { black, slate400, slate800, white } from '@/utils/colors';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
|
||||
const DocumentCameraScreen: React.FC = () => {
|
||||
const client = useSelfClient();
|
||||
const isFocused = useIsFocused();
|
||||
|
||||
// Add a ref to track when the camera screen is mounted
|
||||
const scanStartTimeRef = useRef(Date.now());
|
||||
const { onPassportRead } = useReadMRZ(scanStartTimeRef);
|
||||
|
||||
const navigateToLaunch = useHapticNavigation('Launch', {
|
||||
action: 'cancel',
|
||||
});
|
||||
const navigateToHome = useHapticNavigation('Home', {
|
||||
action: 'cancel',
|
||||
});
|
||||
|
||||
const onCancelPress = async () => {
|
||||
const hasValidDocument = await hasAnyValidRegisteredDocument(client);
|
||||
if (hasValidDocument) {
|
||||
navigateToHome();
|
||||
} else {
|
||||
navigateToLaunch();
|
||||
}
|
||||
navigateToHome();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -32,11 +32,7 @@ import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
import { CircleHelp } from '@tamagui/lucide-icons';
|
||||
|
||||
import type { PassportData } from '@selfxyz/common/types';
|
||||
import {
|
||||
hasAnyValidRegisteredDocument,
|
||||
sanitizeErrorMessage,
|
||||
useSelfClient,
|
||||
} from '@selfxyz/mobile-sdk-alpha';
|
||||
import { sanitizeErrorMessage, useSelfClient } from '@selfxyz/mobile-sdk-alpha';
|
||||
import {
|
||||
BodyText,
|
||||
ButtonsContainer,
|
||||
@@ -447,9 +443,6 @@ const DocumentNFCScanScreen: React.FC = () => {
|
||||
trackEvent,
|
||||
]);
|
||||
|
||||
const navigateToLaunch = useHapticNavigation('Launch', {
|
||||
action: 'cancel',
|
||||
});
|
||||
const navigateToHome = useHapticNavigation('Home', {
|
||||
action: 'cancel',
|
||||
});
|
||||
@@ -457,12 +450,7 @@ const DocumentNFCScanScreen: React.FC = () => {
|
||||
const onCancelPress = async () => {
|
||||
flushAllAnalytics();
|
||||
logNFCEvent('info', 'scan_cancelled', { ...baseContext, stage: 'cancel' });
|
||||
const hasValidDocument = await hasAnyValidRegisteredDocument(selfClient);
|
||||
if (hasValidDocument) {
|
||||
navigateToHome();
|
||||
} else {
|
||||
navigateToLaunch();
|
||||
}
|
||||
navigateToHome();
|
||||
};
|
||||
|
||||
useFocusEffect(
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
import React from 'react';
|
||||
import { Image } from 'tamagui';
|
||||
|
||||
import {
|
||||
hasAnyValidRegisteredDocument,
|
||||
useSelfClient,
|
||||
} from '@selfxyz/mobile-sdk-alpha';
|
||||
import {
|
||||
BodyText,
|
||||
ButtonsContainer,
|
||||
@@ -24,21 +20,12 @@ import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout';
|
||||
import { black, slate100, white } from '@/utils/colors';
|
||||
|
||||
const DocumentNFCScanScreen: React.FC = () => {
|
||||
const selfClient = useSelfClient();
|
||||
const navigateToLaunch = useHapticNavigation('Launch', {
|
||||
action: 'cancel',
|
||||
});
|
||||
const navigateToHome = useHapticNavigation('Home', {
|
||||
action: 'cancel',
|
||||
});
|
||||
|
||||
const onCancelPress = async () => {
|
||||
const hasValidDocument = await hasAnyValidRegisteredDocument(selfClient);
|
||||
if (hasValidDocument) {
|
||||
navigateToHome();
|
||||
} else {
|
||||
navigateToLaunch();
|
||||
}
|
||||
navigateToHome();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Dimensions, Image, Pressable } from 'react-native';
|
||||
import { Button, ScrollView, Text, View, XStack, YStack } from 'tamagui';
|
||||
import {
|
||||
@@ -122,6 +128,10 @@ const HomeScreen: React.FC = () => {
|
||||
// Prevents back navigation
|
||||
usePreventRemove(true, () => {});
|
||||
|
||||
const hasValidRegisteredDocument = useMemo(() => {
|
||||
return documentCatalog.documents.some(doc => doc.isRegistered === true);
|
||||
}, [documentCatalog]);
|
||||
|
||||
// Calculate bottom padding to prevent button bleeding into system navigation
|
||||
const bottomPadding = useSafeBottomPadding(20);
|
||||
|
||||
@@ -186,7 +196,7 @@ const HomeScreen: React.FC = () => {
|
||||
paddingBottom: 35, // Add extra bottom padding for shadow
|
||||
}}
|
||||
>
|
||||
{documentCatalog.documents.length === 0 ? (
|
||||
{!hasValidRegisteredDocument ? (
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
navigation.navigate('CountryPicker');
|
||||
@@ -218,7 +228,7 @@ const HomeScreen: React.FC = () => {
|
||||
const isSelected =
|
||||
documentCatalog.selectedDocumentId === metadata.id;
|
||||
|
||||
if (!documentData) {
|
||||
if (!documentData || !documentData.metadata.isRegistered) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,6 @@ import { XStack, YStack } from 'tamagui';
|
||||
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
|
||||
import { countryCodes } from '@selfxyz/common/constants';
|
||||
import {
|
||||
hasAnyValidRegisteredDocument,
|
||||
useSelfClient,
|
||||
} from '@selfxyz/mobile-sdk-alpha';
|
||||
import {
|
||||
BodyText,
|
||||
PrimaryButton,
|
||||
@@ -36,8 +32,6 @@ type ComingSoonScreenProps = NativeStackScreenProps<
|
||||
>;
|
||||
|
||||
const ComingSoonScreen: React.FC<ComingSoonScreenProps> = ({ route }) => {
|
||||
const selfClient = useSelfClient();
|
||||
const navigateToLaunch = useHapticNavigation('Launch');
|
||||
const navigateToHome = useHapticNavigation('Home');
|
||||
|
||||
const { countryName, countryCode, documentTypeText } = useMemo(() => {
|
||||
@@ -82,12 +76,7 @@ const ComingSoonScreen: React.FC<ComingSoonScreenProps> = ({ route }) => {
|
||||
}, [route.params?.documentCategory, route.params?.countryCode]);
|
||||
|
||||
const onDismiss = async () => {
|
||||
const hasValidDocument = await hasAnyValidRegisteredDocument(selfClient);
|
||||
if (hasValidDocument) {
|
||||
navigateToHome();
|
||||
} else {
|
||||
navigateToLaunch();
|
||||
}
|
||||
navigateToHome();
|
||||
};
|
||||
|
||||
const onNotifyMe = async () => {
|
||||
|
||||
@@ -69,6 +69,7 @@ export const BackupEvents = {
|
||||
CLOUD_BACKUP_ENABLED_DONE: 'Backup: Cloud Backup Enabled Done',
|
||||
CLOUD_BACKUP_ENABLE_STARTED: 'Backup: Cloud Backup Enable Started',
|
||||
CLOUD_BACKUP_STARTED: 'Backup: Cloud Backup Started',
|
||||
CLOUD_RESTORE_FAILED_AUTH: 'Backup: Cloud Restore Failed: Authentication Failed',
|
||||
CLOUD_RESTORE_FAILED_PASSPORT_NOT_REGISTERED: 'Backup: Cloud Restore Failed: Passport Not Registered',
|
||||
CLOUD_RESTORE_FAILED_UNKNOWN: 'Backup: Cloud Restore Failed: Unknown Error',
|
||||
CLOUD_RESTORE_SUCCESS: 'Backup: Cloud Restore Success',
|
||||
|
||||
Reference in New Issue
Block a user