Skip to content
Merged
2 changes: 1 addition & 1 deletion app/src/components/navbar/HomeNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const HomeNavBar = (props: NativeStackHeaderProps) => {
try {
Clipboard.setString('');
} catch {}
props.navigation.navigate('Prove');
props.navigation.navigate('DocumentSelectorForProving');
} catch (error) {
console.error('Error consuming token:', error);
if (
Expand Down
2 changes: 1 addition & 1 deletion app/src/hooks/useEarnPointsFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const useEarnPointsFlow = ({

// Use setTimeout to ensure modal dismisses before navigating
setTimeout(() => {
navigation.navigate('Prove');
navigation.navigate('DocumentSelectorForProving');
}, 100);
}, [selfClient, navigation]);

Expand Down
13 changes: 13 additions & 0 deletions app/src/navigation/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import AccountRecoveryScreen from '@/screens/account/recovery/AccountRecoveryScr
import DocumentDataNotFoundScreen from '@/screens/account/recovery/DocumentDataNotFoundScreen';
import RecoverWithPhraseScreen from '@/screens/account/recovery/RecoverWithPhraseScreen';
import CloudBackupScreen from '@/screens/account/settings/CloudBackupScreen';
import { ProofSettingsScreen } from '@/screens/account/settings/ProofSettingsScreen';
import SettingsScreen from '@/screens/account/settings/SettingsScreen';
import ShowRecoveryPhraseScreen from '@/screens/account/settings/ShowRecoveryPhraseScreen';
import { IS_EUCLID_ENABLED } from '@/utils/devUtils';
Expand Down Expand Up @@ -65,6 +66,18 @@ const accountScreens = {
},
} as NativeStackNavigationOptions,
},
ProofSettings: {
screen: ProofSettingsScreen,
options: {
title: 'Proof Settings',
headerStyle: {
backgroundColor: white,
},
headerTitleStyle: {
color: black,
},
} as NativeStackNavigationOptions,
},
Settings: {
screen: SettingsScreen,
options: {
Expand Down
10 changes: 8 additions & 2 deletions app/src/navigation/deeplinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ export const handleUrl = (selfClient: SelfClient, uri: string) => {
selfClient.getSelfAppState().startAppListener(selfAppJson.sessionId);

navigationRef.reset(
createDeeplinkNavigationState('Prove', correctParentScreen),
createDeeplinkNavigationState(
'DocumentSelectorForProving',
correctParentScreen,
),
);

return;
Expand All @@ -143,7 +146,10 @@ export const handleUrl = (selfClient: SelfClient, uri: string) => {
selfClient.getSelfAppState().startAppListener(sessionId);

navigationRef.reset(
createDeeplinkNavigationState('Prove', correctParentScreen),
createDeeplinkNavigationState(
'DocumentSelectorForProving',
correctParentScreen,
),
);
} else if (mock_passport) {
try {
Expand Down
3 changes: 3 additions & 0 deletions app/src/navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export type RootStackParamList = Omit<
| 'Disclaimer'
| 'DocumentNFCScan'
| 'DocumentOnboarding'
| 'DocumentSelectorForProving'
| 'Gratification'
| 'Home'
| 'IDPicker'
Expand Down Expand Up @@ -142,13 +143,15 @@ export type RootStackParamList = Omit<
returnToScreen?: 'Points';
}
| undefined;
ProofSettings: undefined;
AccountVerifiedSuccess: undefined;

// Proof/Verification screens
ProofHistoryDetail: {
data: ProofHistory;
};
Prove: undefined;
DocumentSelectorForProving: undefined;

// App screens
Loading: {
Expand Down
14 changes: 14 additions & 0 deletions app/src/navigation/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { NativeStackNavigationOptions } from '@react-navigation/native-stac

import { black, white } from '@selfxyz/mobile-sdk-alpha/constants/colors';

import { DocumentSelectorForProvingScreen } from '@/screens/verification/DocumentSelectorForProvingScreen';
import ProofRequestStatusScreen from '@/screens/verification/ProofRequestStatusScreen';
import ProveScreen from '@/screens/verification/ProveScreen';
import QRCodeTroubleScreen from '@/screens/verification/QRCodeTroubleScreen';
Expand All @@ -20,6 +21,19 @@ const verificationScreens = {
gestureEnabled: false,
} as NativeStackNavigationOptions,
},
DocumentSelectorForProving: {
screen: DocumentSelectorForProvingScreen,
options: {
title: 'Select ID',
headerStyle: {
backgroundColor: black,
},
headerTitleStyle: {
color: white,
},
gestureEnabled: false,
} as NativeStackNavigationOptions,
},
Prove: {
screen: ProveScreen,
options: {
Expand Down
130 changes: 130 additions & 0 deletions app/src/screens/account/settings/ProofSettingsScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// 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 React from 'react';
import { StyleSheet, Switch, Text, View } from 'react-native';
import { ScrollView, YStack } from 'tamagui';

import {
black,
blue600,
slate200,
slate500,
white,
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';

import { useSettingStore } from '@/stores/settingStore';

const ProofSettingsScreen: React.FC = () => {
const {
skipDocumentSelector,
setSkipDocumentSelector,
skipDocumentSelectorIfSingle,
setSkipDocumentSelectorIfSingle,
} = useSettingStore();

return (
<YStack flex={1} backgroundColor={white}>
<ScrollView>
<YStack padding={20} gap={20}>
<Text style={styles.sectionTitle}>Document Selection</Text>

<View style={styles.settingRow}>
<View style={styles.settingTextContainer}>
<Text style={styles.settingLabel}>
Always skip document selection
</Text>
<Text style={styles.settingDescription}>
Go directly to proof generation using your previously selected
or first available document
</Text>
</View>
<Switch
value={skipDocumentSelector}
onValueChange={setSkipDocumentSelector}
trackColor={{ false: slate200, true: blue600 }}
thumbColor={white}
testID="skip-document-selector-toggle"
/>
</View>

<View style={styles.divider} />

<View style={styles.settingRow}>
<View style={styles.settingTextContainer}>
<Text style={styles.settingLabel}>
Skip when only one document
</Text>
<Text style={styles.settingDescription}>
Automatically select your document when you only have one valid
ID available
</Text>
</View>
<Switch
value={skipDocumentSelectorIfSingle}
onValueChange={setSkipDocumentSelectorIfSingle}
trackColor={{ false: slate200, true: blue600 }}
thumbColor={white}
disabled={skipDocumentSelector}
testID="skip-document-selector-if-single-toggle"
/>
</View>

{skipDocumentSelector && (
<Text style={styles.infoText}>
Document selection is always skipped. The &quot;Skip when only one
document&quot; setting has no effect.
</Text>
)}
</YStack>
</ScrollView>
</YStack>
);
};

const styles = StyleSheet.create({
sectionTitle: {
fontSize: 14,
fontFamily: dinot,
fontWeight: '600',
color: slate500,
textTransform: 'uppercase',
letterSpacing: 1,
},
settingRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
gap: 16,
},
settingTextContainer: {
flex: 1,
gap: 4,
},
settingLabel: {
fontSize: 16,
fontFamily: dinot,
fontWeight: '500',
color: black,
},
settingDescription: {
fontSize: 14,
fontFamily: dinot,
color: slate500,
},
divider: {
height: 1,
backgroundColor: slate200,
},
infoText: {
fontSize: 13,
fontFamily: dinot,
fontStyle: 'italic',
color: slate500,
paddingHorizontal: 4,
},
});

export { ProofSettingsScreen };
4 changes: 3 additions & 1 deletion app/src/screens/account/settings/SettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { SvgProps } from 'react-native-svg';
import { Button, ScrollView, View, XStack, YStack } from 'tamagui';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { Bug, FileText } from '@tamagui/lucide-icons';
import { Bug, FileText, Settings2 } from '@tamagui/lucide-icons';

import { BodyText, pressedStyle } from '@selfxyz/mobile-sdk-alpha/components';
import {
Expand Down Expand Up @@ -78,6 +78,7 @@ const routes =
[Data, 'View document info', 'DocumentDataInfo'],
[Lock, 'Reveal recovery phrase', 'ShowRecoveryPhrase'],
[Cloud, 'Cloud backup', 'CloudBackupSettings'],
[Settings2 as React.FC<SvgProps>, 'Proof settings', 'ProofSettings'],
[Feedback, 'Send feedback', 'email_feedback'],
[ShareIcon, 'Share Self app', 'share'],
[
Expand All @@ -88,6 +89,7 @@ const routes =
] satisfies [React.FC<SvgProps>, string, RouteOption][])
: ([
[Data, 'View document info', 'DocumentDataInfo'],
[Settings2 as React.FC<SvgProps>, 'Proof settings', 'ProofSettings'],
[Feedback, 'Send feeback', 'email_feedback'],
[
FileText as React.FC<SvgProps>,
Expand Down
Loading
Loading