@trustchex/react-native-sdk 1.334.0 → 1.354.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +8 -2
- package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +5 -1
- package/lib/module/Screens/Dynamic/IdentityDocumentScanningScreen.js +5 -1
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +29 -15
- package/lib/module/Screens/Static/OTPVerificationScreen.js +285 -0
- package/lib/module/Screens/Static/ResultScreen.js +90 -26
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +48 -134
- package/lib/module/Shared/Components/DebugNavigationPanel.js +252 -0
- package/lib/module/Shared/Components/EIDScanner.js +142 -17
- package/lib/module/Shared/Components/FaceCamera.js +23 -11
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +295 -44
- package/lib/module/Shared/Components/NavigationManager.js +19 -3
- package/lib/module/Shared/Config/camera-enhancement.config.js +58 -0
- package/lib/module/Shared/Contexts/AppContext.js +1 -0
- package/lib/module/Shared/Libs/camera.utils.js +221 -1
- package/lib/module/Shared/Libs/frame-enhancement.utils.js +133 -0
- package/lib/module/Shared/Libs/mrz.utils.js +98 -1
- package/lib/module/Translation/Resources/en.js +30 -0
- package/lib/module/Translation/Resources/tr.js +30 -0
- package/lib/module/Trustchex.js +49 -39
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/OTPVerificationScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Static/OTPVerificationScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts +3 -0
- package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Config/camera-enhancement.config.d.ts +54 -0
- package/lib/typescript/src/Shared/Config/camera-enhancement.config.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts +2 -0
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/camera.utils.d.ts +65 -1
- package/lib/typescript/src/Shared/Libs/camera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/frame-enhancement.utils.d.ts +25 -0
- package/lib/typescript/src/Shared/Libs/frame-enhancement.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +30 -0
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +30 -0
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +3 -3
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +6 -2
- package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +3 -1
- package/src/Screens/Dynamic/IdentityDocumentScanningScreen.tsx +3 -1
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +27 -17
- package/src/Screens/Static/OTPVerificationScreen.tsx +379 -0
- package/src/Screens/Static/ResultScreen.tsx +160 -101
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +51 -196
- package/src/Shared/Components/DebugNavigationPanel.tsx +262 -0
- package/src/Shared/Components/EIDScanner.tsx +144 -19
- package/src/Shared/Components/FaceCamera.tsx +38 -21
- package/src/Shared/Components/IdentityDocumentCamera.tsx +399 -101
- package/src/Shared/Components/NavigationManager.tsx +19 -3
- package/src/Shared/Config/camera-enhancement.config.ts +46 -0
- package/src/Shared/Contexts/AppContext.ts +3 -0
- package/src/Shared/Libs/camera.utils.ts +240 -1
- package/src/Shared/Libs/frame-enhancement.utils.ts +217 -0
- package/src/Shared/Libs/mrz.utils.ts +78 -1
- package/src/Translation/Resources/en.ts +30 -0
- package/src/Translation/Resources/tr.ts +30 -0
- package/src/Trustchex.tsx +58 -46
- package/src/version.ts +1 -1
|
@@ -2,6 +2,7 @@ import React, { useContext, useEffect, useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import type { FieldRecords } from 'mrz';
|
|
4
4
|
import { Alert, SafeAreaView, StyleSheet, View } from 'react-native';
|
|
5
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
6
|
import IdentityDocumentCamera, {
|
|
6
7
|
type DocumentScannedData,
|
|
7
8
|
} from '../../Shared/Components/IdentityDocumentCamera';
|
|
@@ -27,6 +28,7 @@ const IdentityDocumentScanningScreen = () => {
|
|
|
27
28
|
const navigationManagerRef = React.useRef<NavigationManagerRef>(null);
|
|
28
29
|
const appContext = useContext(AppContext);
|
|
29
30
|
const { t } = useTranslation();
|
|
31
|
+
const insets = useSafeAreaInsets();
|
|
30
32
|
const [allowedDocumentTypes, setAllowedDocumentTypes] = useState<
|
|
31
33
|
('I' | 'P')[] | null
|
|
32
34
|
>(null);
|
|
@@ -158,7 +160,7 @@ const IdentityDocumentScanningScreen = () => {
|
|
|
158
160
|
}}
|
|
159
161
|
showDebugImages={false}
|
|
160
162
|
/>
|
|
161
|
-
<View style={styles.footer}>
|
|
163
|
+
<View style={[styles.footer, { bottom: insets.bottom }]}>
|
|
162
164
|
<NavigationManager ref={navigationManagerRef} />
|
|
163
165
|
</View>
|
|
164
166
|
</SafeAreaView>
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
Platform,
|
|
16
16
|
Vibration,
|
|
17
17
|
} from 'react-native';
|
|
18
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
19
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
18
20
|
import NativeCircularProgress from '../../Shared/Components/NativeCircularProgress';
|
|
19
21
|
import { Camera } from 'react-native-vision-camera';
|
|
20
22
|
import type { Face } from '../../Shared/VisionCameraPlugins/FaceDetector';
|
|
@@ -86,6 +88,7 @@ const LivenessDetectionScreen = () => {
|
|
|
86
88
|
const navigationManagerRef = React.useRef<NavigationManagerRef>(null);
|
|
87
89
|
const { t } = useTranslation();
|
|
88
90
|
const [isRecording, setIsRecording] = useState(false);
|
|
91
|
+
const insets = useSafeAreaInsets();
|
|
89
92
|
|
|
90
93
|
// Track screen view and exit
|
|
91
94
|
useScreenTracking('liveness_detection');
|
|
@@ -512,7 +515,7 @@ const LivenessDetectionScreen = () => {
|
|
|
512
515
|
return (
|
|
513
516
|
<>
|
|
514
517
|
{!hasGuideShown ? (
|
|
515
|
-
<
|
|
518
|
+
<SafeAreaView style={styles.guide}>
|
|
516
519
|
<LottieView
|
|
517
520
|
source={require('../../Shared/Animations/face-scan.json')}
|
|
518
521
|
style={styles.guideAnimation}
|
|
@@ -539,15 +542,17 @@ const LivenessDetectionScreen = () => {
|
|
|
539
542
|
• {t('livenessDetectionScreen.guidePoint4')}
|
|
540
543
|
</Text>
|
|
541
544
|
</View>
|
|
542
|
-
<
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
545
|
+
<View style={{ paddingBottom: insets.bottom }}>
|
|
546
|
+
<StyledButton
|
|
547
|
+
mode="contained"
|
|
548
|
+
onPress={() => {
|
|
549
|
+
setHasGuideShown(true);
|
|
550
|
+
}}
|
|
551
|
+
>
|
|
552
|
+
{t('general.letsGo')}
|
|
553
|
+
</StyledButton>
|
|
554
|
+
</View>
|
|
555
|
+
</SafeAreaView>
|
|
551
556
|
) : (
|
|
552
557
|
<>
|
|
553
558
|
<FaceCamera
|
|
@@ -558,11 +563,11 @@ const LivenessDetectionScreen = () => {
|
|
|
558
563
|
<NativeCircularProgress
|
|
559
564
|
style={styles.circularProgress}
|
|
560
565
|
size={PREVIEW_SIZE}
|
|
561
|
-
width={
|
|
562
|
-
backgroundWidth={
|
|
566
|
+
width={8}
|
|
567
|
+
backgroundWidth={8}
|
|
563
568
|
fill={state.progressFill}
|
|
564
569
|
tintColor={appContext.branding.primaryColor}
|
|
565
|
-
backgroundColor="
|
|
570
|
+
backgroundColor="rgba(255, 255, 255, 0.3)"
|
|
566
571
|
/>
|
|
567
572
|
{state.brightnessLow && (
|
|
568
573
|
<LottieView
|
|
@@ -575,7 +580,12 @@ const LivenessDetectionScreen = () => {
|
|
|
575
580
|
<Svg style={styles.svgMask}>
|
|
576
581
|
<Mask id="hole-mask">
|
|
577
582
|
<SvgRect width="100%" height="100%" fill="white" />
|
|
578
|
-
<Circle
|
|
583
|
+
<Circle
|
|
584
|
+
cx={windowWidth / 2}
|
|
585
|
+
cy={windowHeight / 2}
|
|
586
|
+
r={PREVIEW_SIZE / 2}
|
|
587
|
+
fill="black"
|
|
588
|
+
/>
|
|
579
589
|
</Mask>
|
|
580
590
|
|
|
581
591
|
<SvgRect
|
|
@@ -585,7 +595,7 @@ const LivenessDetectionScreen = () => {
|
|
|
585
595
|
mask="url(#hole-mask)"
|
|
586
596
|
/>
|
|
587
597
|
</Svg>
|
|
588
|
-
<View style={styles.instructionsContainerTop}>
|
|
598
|
+
<View style={[styles.instructionsContainerTop, { paddingTop: insets.top }]}>
|
|
589
599
|
<Text style={styles.instructions}>
|
|
590
600
|
{(() => {
|
|
591
601
|
if (state.brightnessLow) {
|
|
@@ -602,7 +612,7 @@ const LivenessDetectionScreen = () => {
|
|
|
602
612
|
})()}
|
|
603
613
|
</Text>
|
|
604
614
|
</View>
|
|
605
|
-
<View style={styles.instructionsContainerBottom}>
|
|
615
|
+
<View style={[styles.instructionsContainerBottom, { paddingBottom: insets.bottom }]}>
|
|
606
616
|
<Text style={styles.action}>
|
|
607
617
|
{state.faceDetected &&
|
|
608
618
|
!state.faceTooBig &&
|
|
@@ -613,7 +623,7 @@ const LivenessDetectionScreen = () => {
|
|
|
613
623
|
</View>
|
|
614
624
|
</>
|
|
615
625
|
)}
|
|
616
|
-
<View style={styles.footer}>
|
|
626
|
+
<View style={[styles.footer, { bottom: insets.bottom }]}>
|
|
617
627
|
<NavigationManager ref={navigationManagerRef} />
|
|
618
628
|
</View>
|
|
619
629
|
</>
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useContext,
|
|
4
|
+
useEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import {
|
|
9
|
+
SafeAreaView,
|
|
10
|
+
Text,
|
|
11
|
+
StyleSheet,
|
|
12
|
+
Alert,
|
|
13
|
+
View,
|
|
14
|
+
Image,
|
|
15
|
+
Dimensions,
|
|
16
|
+
KeyboardAvoidingView,
|
|
17
|
+
Platform,
|
|
18
|
+
ScrollView,
|
|
19
|
+
} from 'react-native';
|
|
20
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
21
|
+
import { useRoute, type RouteProp } from '@react-navigation/native';
|
|
22
|
+
import AppContext from '../../Shared/Contexts/AppContext';
|
|
23
|
+
import httpClient, { BadRequestError, NotFoundError, TooManyRequestsError } from '../../Shared/Libs/http-client';
|
|
24
|
+
import { useTranslation } from 'react-i18next';
|
|
25
|
+
import LanguageSelector from '../../Shared/Components/LanguageSelector';
|
|
26
|
+
import NavigationManager, {
|
|
27
|
+
type NavigationManagerRef,
|
|
28
|
+
} from '../../Shared/Components/NavigationManager';
|
|
29
|
+
import type { VerificationSession } from '../../Shared/Types/verificationSession';
|
|
30
|
+
import StyledButton from '../../Shared/Components/StyledButton';
|
|
31
|
+
import StyledTextInput from '../../Shared/Components/StyledTextInput';
|
|
32
|
+
import { useTheme } from '../../Shared/Contexts/ThemeContext';
|
|
33
|
+
import LottieView from 'lottie-react-native';
|
|
34
|
+
import {
|
|
35
|
+
getSimulatedDemoData,
|
|
36
|
+
} from '../../Shared/Libs/demo.utils';
|
|
37
|
+
import {
|
|
38
|
+
trackError,
|
|
39
|
+
useScreenTracking,
|
|
40
|
+
} from '../../Shared/Libs/analytics.utils';
|
|
41
|
+
|
|
42
|
+
type OTPVerificationScreenParams = {
|
|
43
|
+
sessionId: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const OTPVerificationScreen = () => {
|
|
47
|
+
const route = useRoute<RouteProp<{ params: OTPVerificationScreenParams }, 'params'>>();
|
|
48
|
+
const sessionId = route.params?.sessionId;
|
|
49
|
+
const [code, setCode] = useState('');
|
|
50
|
+
const [isSendAgainEnabled, setIsSendAgainEnabled] = useState(false);
|
|
51
|
+
const [isCodeGettingVerified, setIsCodeGettingVerified] = useState(false);
|
|
52
|
+
const appContext = useContext(AppContext);
|
|
53
|
+
const { t } = useTranslation();
|
|
54
|
+
const navigationManagerRef = useRef<NavigationManagerRef>(null);
|
|
55
|
+
const initialized = useRef(false);
|
|
56
|
+
const insets = useSafeAreaInsets();
|
|
57
|
+
const theme = useTheme();
|
|
58
|
+
const primaryColor = theme.colors.primary;
|
|
59
|
+
|
|
60
|
+
useScreenTracking('otp_verification');
|
|
61
|
+
|
|
62
|
+
// Guard: If sessionId is not provided, show error
|
|
63
|
+
if (!sessionId) {
|
|
64
|
+
return (
|
|
65
|
+
<SafeAreaView style={[styles.container, { backgroundColor: theme.colors.background }]}>
|
|
66
|
+
<Text style={[styles.errorText, { color: theme.colors.error }]}>
|
|
67
|
+
{t('general.sessionNotFound')}
|
|
68
|
+
</Text>
|
|
69
|
+
</SafeAreaView>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const apiUrl = `${appContext.baseUrl}/api/app/mobile`;
|
|
74
|
+
|
|
75
|
+
const sendVerificationCode = useCallback(
|
|
76
|
+
async (sessionId: string) => {
|
|
77
|
+
try {
|
|
78
|
+
await httpClient.post(
|
|
79
|
+
`${apiUrl}/verification-sessions/${sessionId}`,
|
|
80
|
+
{},
|
|
81
|
+
appContext.isDemoSession
|
|
82
|
+
? getSimulatedDemoData('SEND_VERIFICATION_CODE')
|
|
83
|
+
: undefined
|
|
84
|
+
);
|
|
85
|
+
return true;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error instanceof NotFoundError) {
|
|
88
|
+
Alert.alert(
|
|
89
|
+
t('general.error'),
|
|
90
|
+
t('verificationSessionCheckScreen.noVerificationSessionFound')
|
|
91
|
+
);
|
|
92
|
+
} else if (error instanceof TooManyRequestsError) {
|
|
93
|
+
return true;
|
|
94
|
+
} else {
|
|
95
|
+
trackError(
|
|
96
|
+
'VERIFICATION_CODE_SEND_FAILED',
|
|
97
|
+
'Failed to send verification code',
|
|
98
|
+
'otp_verification',
|
|
99
|
+
'high',
|
|
100
|
+
{ recoverable: true, userAction: 'send_verification_code' }
|
|
101
|
+
);
|
|
102
|
+
Alert.alert(
|
|
103
|
+
t('general.error'),
|
|
104
|
+
t('verificationSessionCheckScreen.cannotSendVerificationCode')
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
},
|
|
110
|
+
[apiUrl, appContext.isDemoSession, t]
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const getVerifiedSession = useCallback(
|
|
114
|
+
async (sessionId: string, verificationCode: string) => {
|
|
115
|
+
try {
|
|
116
|
+
const response = await httpClient.post<
|
|
117
|
+
VerificationSession,
|
|
118
|
+
{ code: string }
|
|
119
|
+
>(
|
|
120
|
+
`${apiUrl}/verification-sessions/${sessionId}`,
|
|
121
|
+
{
|
|
122
|
+
code: verificationCode,
|
|
123
|
+
},
|
|
124
|
+
appContext.isDemoSession
|
|
125
|
+
? getSimulatedDemoData<
|
|
126
|
+
VerificationSession | undefined,
|
|
127
|
+
{ code: string }
|
|
128
|
+
>('GET_VERIFIED_SESSION', { code: verificationCode })
|
|
129
|
+
: undefined
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
return response;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error instanceof NotFoundError) {
|
|
135
|
+
Alert.alert(
|
|
136
|
+
t('general.error'),
|
|
137
|
+
t('verificationSessionCheckScreen.noVerificationSessionFound')
|
|
138
|
+
);
|
|
139
|
+
} else if (error instanceof BadRequestError) {
|
|
140
|
+
// Wrong OTP code - expected user behavior, not actionable
|
|
141
|
+
} else {
|
|
142
|
+
trackError(
|
|
143
|
+
'VERIFIED_SESSION_CHECK_ERROR',
|
|
144
|
+
error instanceof Error ? error.message : 'Unknown error',
|
|
145
|
+
'otp_verification',
|
|
146
|
+
'high',
|
|
147
|
+
{ recoverable: false, userAction: 'check_verified_session' }
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
[apiUrl, appContext.isDemoSession, t]
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const sendOTPCode = useCallback(
|
|
156
|
+
async (sessionId: string) => {
|
|
157
|
+
if (!sessionId) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const isSent = await sendVerificationCode(sessionId);
|
|
162
|
+
|
|
163
|
+
if (!isSent) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
setIsSendAgainEnabled(false);
|
|
168
|
+
|
|
169
|
+
setTimeout(
|
|
170
|
+
() => {
|
|
171
|
+
setIsSendAgainEnabled(true);
|
|
172
|
+
},
|
|
173
|
+
3 * 60 * 1000
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
return true;
|
|
177
|
+
},
|
|
178
|
+
[sendVerificationCode]
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (!initialized.current && sessionId) {
|
|
183
|
+
initialized.current = true;
|
|
184
|
+
sendOTPCode(sessionId);
|
|
185
|
+
}
|
|
186
|
+
}, [sessionId, sendOTPCode]);
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<SafeAreaView style={styles.safeAreaContainer}>
|
|
190
|
+
<KeyboardAvoidingView
|
|
191
|
+
style={styles.keyboardAvoidingView}
|
|
192
|
+
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
193
|
+
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
|
|
194
|
+
>
|
|
195
|
+
<ScrollView
|
|
196
|
+
style={styles.container}
|
|
197
|
+
contentContainerStyle={styles.scrollContainer}
|
|
198
|
+
keyboardShouldPersistTaps="handled"
|
|
199
|
+
showsVerticalScrollIndicator={false}
|
|
200
|
+
>
|
|
201
|
+
<View style={styles.mainContent}>
|
|
202
|
+
<LanguageSelector />
|
|
203
|
+
<View style={styles.mainHeader}>
|
|
204
|
+
{appContext.branding.logoUrl ? (
|
|
205
|
+
<Image
|
|
206
|
+
source={{ uri: appContext.branding.logoUrl }}
|
|
207
|
+
style={styles.mainLogo}
|
|
208
|
+
/>
|
|
209
|
+
) : (
|
|
210
|
+
<Image
|
|
211
|
+
source={require('../../Shared/Assets/trustchex-logo-black.png')}
|
|
212
|
+
style={styles.trustchexLogo}
|
|
213
|
+
/>
|
|
214
|
+
)}
|
|
215
|
+
</View>
|
|
216
|
+
{isCodeGettingVerified ? (
|
|
217
|
+
<LottieView
|
|
218
|
+
source={require('../../Shared/Animations/loading.json')}
|
|
219
|
+
style={styles.loadingAnimation}
|
|
220
|
+
autoPlay
|
|
221
|
+
loop={true}
|
|
222
|
+
resizeMode="cover"
|
|
223
|
+
/>
|
|
224
|
+
) : (
|
|
225
|
+
<>
|
|
226
|
+
<Text style={styles.mainText}>
|
|
227
|
+
{t('verificationSessionCheckScreen.codeText')}
|
|
228
|
+
</Text>
|
|
229
|
+
<StyledTextInput
|
|
230
|
+
autoFocus={true}
|
|
231
|
+
placeholder=""
|
|
232
|
+
borderColor={primaryColor}
|
|
233
|
+
focusedBorderColor={primaryColor}
|
|
234
|
+
inputStyle={styles.otpCodeTextInput}
|
|
235
|
+
keyboardType="number-pad"
|
|
236
|
+
textContentType="oneTimeCode"
|
|
237
|
+
autoComplete="sms-otp"
|
|
238
|
+
maxLength={6}
|
|
239
|
+
onChangeText={(text) => {
|
|
240
|
+
const numericText = text.replace(/[^0-9]/g, '');
|
|
241
|
+
if (numericText.length <= 6) {
|
|
242
|
+
setCode(numericText);
|
|
243
|
+
if (numericText.length === 6) {
|
|
244
|
+
(async () => {
|
|
245
|
+
setIsCodeGettingVerified(true);
|
|
246
|
+
const verifiedSession = await getVerifiedSession(
|
|
247
|
+
sessionId,
|
|
248
|
+
numericText
|
|
249
|
+
);
|
|
250
|
+
if (verifiedSession?.identificationId) {
|
|
251
|
+
appContext.identificationInfo.identificationId =
|
|
252
|
+
verifiedSession?.identificationId;
|
|
253
|
+
// Update workflow steps from verified session if available
|
|
254
|
+
if (verifiedSession.workflowSteps) {
|
|
255
|
+
appContext.workflowSteps = verifiedSession.workflowSteps;
|
|
256
|
+
}
|
|
257
|
+
setCode('');
|
|
258
|
+
navigationManagerRef.current?.navigateToNextStep();
|
|
259
|
+
} else {
|
|
260
|
+
appContext.onError?.('Invalid OTP code');
|
|
261
|
+
Alert.alert(
|
|
262
|
+
t('general.error'),
|
|
263
|
+
t('verificationSessionCheckScreen.codeError')
|
|
264
|
+
);
|
|
265
|
+
setCode('');
|
|
266
|
+
setIsCodeGettingVerified(false);
|
|
267
|
+
}
|
|
268
|
+
})();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}}
|
|
272
|
+
value={code}
|
|
273
|
+
/>
|
|
274
|
+
<StyledButton
|
|
275
|
+
mode="contained"
|
|
276
|
+
disabled={!isSendAgainEnabled}
|
|
277
|
+
onPress={() => {
|
|
278
|
+
sendOTPCode(sessionId);
|
|
279
|
+
}}
|
|
280
|
+
>
|
|
281
|
+
{t('verificationSessionCheckScreen.sendCodeAgain')}
|
|
282
|
+
</StyledButton>
|
|
283
|
+
</>
|
|
284
|
+
)}
|
|
285
|
+
</View>
|
|
286
|
+
{appContext.branding.logoUrl && (
|
|
287
|
+
<View style={[styles.footer, { bottom: insets.bottom + 15 }]}>
|
|
288
|
+
<Text style={styles.mainText}>Powered By</Text>
|
|
289
|
+
<Image
|
|
290
|
+
source={require('../../Shared/Assets/trustchex-logo-black.png')}
|
|
291
|
+
style={styles.poweredByLogo}
|
|
292
|
+
/>
|
|
293
|
+
</View>
|
|
294
|
+
)}
|
|
295
|
+
<NavigationManager ref={navigationManagerRef} />
|
|
296
|
+
</ScrollView>
|
|
297
|
+
</KeyboardAvoidingView>
|
|
298
|
+
</SafeAreaView>
|
|
299
|
+
);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const styles = StyleSheet.create({
|
|
303
|
+
safeAreaContainer: {
|
|
304
|
+
flex: 1,
|
|
305
|
+
backgroundColor: 'white',
|
|
306
|
+
},
|
|
307
|
+
keyboardAvoidingView: {
|
|
308
|
+
flex: 1,
|
|
309
|
+
},
|
|
310
|
+
container: {
|
|
311
|
+
flex: 1,
|
|
312
|
+
},
|
|
313
|
+
scrollContainer: {
|
|
314
|
+
flexGrow: 1,
|
|
315
|
+
padding: 20,
|
|
316
|
+
alignItems: 'center',
|
|
317
|
+
justifyContent: 'center',
|
|
318
|
+
},
|
|
319
|
+
loadingAnimation: {
|
|
320
|
+
width: '100%',
|
|
321
|
+
height: '100%',
|
|
322
|
+
maxHeight: 200,
|
|
323
|
+
},
|
|
324
|
+
mainHeader: {
|
|
325
|
+
display: 'flex',
|
|
326
|
+
flexDirection: 'column',
|
|
327
|
+
alignItems: 'center',
|
|
328
|
+
justifyContent: 'center',
|
|
329
|
+
},
|
|
330
|
+
mainContent: {
|
|
331
|
+
flex: 1,
|
|
332
|
+
display: 'flex',
|
|
333
|
+
gap: 20,
|
|
334
|
+
justifyContent: 'center',
|
|
335
|
+
width: '100%',
|
|
336
|
+
maxWidth: 400,
|
|
337
|
+
},
|
|
338
|
+
mainText: {
|
|
339
|
+
color: 'black',
|
|
340
|
+
textAlign: 'center',
|
|
341
|
+
},
|
|
342
|
+
mainLogo: {
|
|
343
|
+
width: Dimensions.get('window').width - 40,
|
|
344
|
+
height: Dimensions.get('window').width / 4,
|
|
345
|
+
maxWidth: 300,
|
|
346
|
+
maxHeight: 300,
|
|
347
|
+
resizeMode: 'contain',
|
|
348
|
+
},
|
|
349
|
+
trustchexLogo: {
|
|
350
|
+
width: 300,
|
|
351
|
+
height: 75,
|
|
352
|
+
resizeMode: 'contain',
|
|
353
|
+
},
|
|
354
|
+
poweredByLogo: {
|
|
355
|
+
width: 120,
|
|
356
|
+
height: 30,
|
|
357
|
+
resizeMode: 'contain',
|
|
358
|
+
},
|
|
359
|
+
footer: {
|
|
360
|
+
display: 'flex',
|
|
361
|
+
flexDirection: 'column',
|
|
362
|
+
justifyContent: 'center',
|
|
363
|
+
alignItems: 'center',
|
|
364
|
+
position: 'absolute',
|
|
365
|
+
},
|
|
366
|
+
otpCodeTextInput: {
|
|
367
|
+
fontWeight: '800',
|
|
368
|
+
fontSize: 28,
|
|
369
|
+
textAlign: 'center',
|
|
370
|
+
letterSpacing: 8,
|
|
371
|
+
},
|
|
372
|
+
errorText: {
|
|
373
|
+
fontSize: 16,
|
|
374
|
+
textAlign: 'center',
|
|
375
|
+
padding: 20,
|
|
376
|
+
},
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
export default OTPVerificationScreen;
|