@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
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from 'react-native';
|
|
21
21
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
22
22
|
import AppContext from '../../Shared/Contexts/AppContext';
|
|
23
|
-
import httpClient, {
|
|
23
|
+
import httpClient, { NotFoundError } from '../../Shared/Libs/http-client';
|
|
24
24
|
import { useTranslation } from 'react-i18next';
|
|
25
25
|
import LanguageSelector from '../../Shared/Components/LanguageSelector';
|
|
26
26
|
import NavigationManager, {
|
|
@@ -49,11 +49,8 @@ import {
|
|
|
49
49
|
|
|
50
50
|
const VerificationSessionCheckScreen = () => {
|
|
51
51
|
const [sessionCode, setSessionCode] = useState('');
|
|
52
|
-
const [code, setCode] = useState('');
|
|
53
52
|
const [isCheckingSession, setIsCheckingSession] = useState(false);
|
|
54
|
-
const
|
|
55
|
-
const [isCodeSent, setIsCodeSent] = useState(false);
|
|
56
|
-
const [isCodeGettingVerified, setIsCodeGettingVerified] = useState(false);
|
|
53
|
+
const isCheckingSessionRef = useRef(false);
|
|
57
54
|
const appContext = useContext(AppContext);
|
|
58
55
|
const { t } = useTranslation();
|
|
59
56
|
const navigationManagerRef = React.useRef<NavigationManagerRef>(null);
|
|
@@ -76,11 +73,12 @@ const VerificationSessionCheckScreen = () => {
|
|
|
76
73
|
}, []);
|
|
77
74
|
|
|
78
75
|
const getSession = useCallback(
|
|
79
|
-
async (id: string) => {
|
|
76
|
+
async (id: string, isDemoMode?: boolean) => {
|
|
77
|
+
const isDemo = isDemoMode ?? appContext.isDemoSession;
|
|
80
78
|
try {
|
|
81
79
|
const response = await httpClient.get<VerificationSession>(
|
|
82
80
|
`${apiUrl}/verification-sessions/${id}`,
|
|
83
|
-
|
|
81
|
+
isDemo
|
|
84
82
|
? getSimulatedDemoData<VerificationSession | undefined, void>(
|
|
85
83
|
'GET_SESSION'
|
|
86
84
|
)
|
|
@@ -111,11 +109,12 @@ const VerificationSessionCheckScreen = () => {
|
|
|
111
109
|
const getSessionByCode = useCallback(
|
|
112
110
|
async (inputCode: string) => {
|
|
113
111
|
try {
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
const isDemoMode = isDemoSession(inputCode);
|
|
113
|
+
appContext.setIsDemoSession?.(isDemoMode);
|
|
114
|
+
analyticsService.setDemoSession(isDemoMode);
|
|
116
115
|
const response = await httpClient.get<{ id: string }>(
|
|
117
116
|
`${apiUrl}/verification-sessions?sessionCode=${inputCode.toUpperCase()}`,
|
|
118
|
-
|
|
117
|
+
isDemoMode
|
|
119
118
|
? getSimulatedDemoData<{ id: string } | undefined, void>(
|
|
120
119
|
'GET_SESSION_BY_CODE'
|
|
121
120
|
)
|
|
@@ -151,121 +150,19 @@ const VerificationSessionCheckScreen = () => {
|
|
|
151
150
|
[apiUrl, appContext, t]
|
|
152
151
|
);
|
|
153
152
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
await httpClient.post(
|
|
158
|
-
`${apiUrl}/verification-sessions/${sessionId}`,
|
|
159
|
-
{},
|
|
160
|
-
appContext.isDemoSession
|
|
161
|
-
? getSimulatedDemoData('SEND_VERIFICATION_CODE')
|
|
162
|
-
: undefined
|
|
163
|
-
);
|
|
164
|
-
return true;
|
|
165
|
-
} catch (error) {
|
|
166
|
-
if (error instanceof NotFoundError) {
|
|
167
|
-
// Session expired or invalid - expected behavior, not actionable
|
|
168
|
-
Alert.alert(
|
|
169
|
-
t('general.error'),
|
|
170
|
-
t('verificationSessionCheckScreen.noVerificationSessionFound')
|
|
171
|
-
);
|
|
172
|
-
} else if (error instanceof TooManyRequestsError) {
|
|
173
|
-
// Code was already sent recently - this is expected behavior
|
|
174
|
-
// Return true since the code was already sent
|
|
175
|
-
return true;
|
|
176
|
-
} else {
|
|
177
|
-
trackError(
|
|
178
|
-
'VERIFICATION_CODE_SEND_FAILED',
|
|
179
|
-
'Failed to send verification code',
|
|
180
|
-
'verification_session_check',
|
|
181
|
-
'high',
|
|
182
|
-
{ recoverable: true, userAction: 'send_verification_code' }
|
|
183
|
-
);
|
|
184
|
-
Alert.alert(
|
|
185
|
-
t('general.error'),
|
|
186
|
-
t('verificationSessionCheckScreen.cannotSendVerificationCode')
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return false;
|
|
153
|
+
const navigateToOTPScreen = useCallback(
|
|
154
|
+
(sessionId: string) => {
|
|
155
|
+
(navigation as any).navigate('OTPVerificationScreen', { sessionId });
|
|
191
156
|
},
|
|
192
|
-
[
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
const getVerifiedSession = useCallback(
|
|
196
|
-
async (sessionId: string, verificationCode: string) => {
|
|
197
|
-
try {
|
|
198
|
-
const response = await httpClient.post<
|
|
199
|
-
VerificationSession,
|
|
200
|
-
{ code: string }
|
|
201
|
-
>(
|
|
202
|
-
`${apiUrl}/verification-sessions/${sessionId}`,
|
|
203
|
-
{
|
|
204
|
-
code: verificationCode,
|
|
205
|
-
},
|
|
206
|
-
appContext.isDemoSession
|
|
207
|
-
? getSimulatedDemoData<
|
|
208
|
-
VerificationSession | undefined,
|
|
209
|
-
{ code: string }
|
|
210
|
-
>('GET_VERIFIED_SESSION', { code: verificationCode })
|
|
211
|
-
: undefined
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
return response;
|
|
215
|
-
} catch (error) {
|
|
216
|
-
if (error instanceof NotFoundError) {
|
|
217
|
-
// Session expired or invalid - expected behavior, not actionable
|
|
218
|
-
Alert.alert(
|
|
219
|
-
t('general.error'),
|
|
220
|
-
t('verificationSessionCheckScreen.noVerificationSessionFound')
|
|
221
|
-
);
|
|
222
|
-
} else if (error instanceof BadRequestError) {
|
|
223
|
-
// Wrong OTP code - expected user behavior, not actionable
|
|
224
|
-
} else {
|
|
225
|
-
trackError(
|
|
226
|
-
'VERIFIED_SESSION_CHECK_ERROR',
|
|
227
|
-
error instanceof Error ? error.message : 'Unknown error',
|
|
228
|
-
'verification_session_check',
|
|
229
|
-
'high',
|
|
230
|
-
{ recoverable: false, userAction: 'check_verified_session' }
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
[apiUrl, appContext.isDemoSession, t]
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
const sendOTPCode = useCallback(
|
|
239
|
-
async (sessionId: string) => {
|
|
240
|
-
if (!sessionId) {
|
|
241
|
-
return false;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const isSent = await sendVerificationCode(sessionId);
|
|
245
|
-
|
|
246
|
-
if (!isSent) {
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
setIsSendAgainEnabled(false);
|
|
251
|
-
|
|
252
|
-
setTimeout(
|
|
253
|
-
() => {
|
|
254
|
-
setIsSendAgainEnabled(true);
|
|
255
|
-
},
|
|
256
|
-
3 * 60 * 1000
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
setIsCodeSent(true);
|
|
260
|
-
|
|
261
|
-
return true;
|
|
262
|
-
},
|
|
263
|
-
[sendVerificationCode]
|
|
157
|
+
[navigation]
|
|
264
158
|
);
|
|
265
159
|
|
|
266
160
|
useEffect(() => {
|
|
267
|
-
|
|
161
|
+
// Only run this effect if sessionId exists AND we're not currently checking a session
|
|
162
|
+
// This prevents race condition when session code is entered
|
|
163
|
+
if (!initialized.current && appContext.identificationInfo.sessionId && !isCheckingSessionRef.current) {
|
|
268
164
|
initialized.current = true;
|
|
165
|
+
isCheckingSessionRef.current = true;
|
|
269
166
|
setIsCheckingSession(true);
|
|
270
167
|
getSession(appContext.identificationInfo.sessionId)
|
|
271
168
|
.then((session) => {
|
|
@@ -275,15 +172,18 @@ const VerificationSessionCheckScreen = () => {
|
|
|
275
172
|
}
|
|
276
173
|
|
|
277
174
|
if (session?.sendOTP) {
|
|
278
|
-
|
|
279
|
-
} else
|
|
280
|
-
|
|
281
|
-
|
|
175
|
+
navigateToOTPScreen(session.id);
|
|
176
|
+
} else {
|
|
177
|
+
if (session?.identificationId) {
|
|
178
|
+
appContext.identificationInfo.identificationId =
|
|
179
|
+
session?.identificationId;
|
|
180
|
+
}
|
|
282
181
|
navigationManagerRef.current?.navigateToNextStep();
|
|
283
182
|
}
|
|
284
183
|
})
|
|
285
184
|
.finally(() => {
|
|
286
185
|
setTimeout(() => {
|
|
186
|
+
isCheckingSessionRef.current = false;
|
|
287
187
|
setIsCheckingSession(false);
|
|
288
188
|
}, 1000);
|
|
289
189
|
});
|
|
@@ -292,7 +192,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
292
192
|
appContext,
|
|
293
193
|
appContext.identificationInfo.sessionId,
|
|
294
194
|
getSession,
|
|
295
|
-
|
|
195
|
+
navigateToOTPScreen,
|
|
296
196
|
]);
|
|
297
197
|
|
|
298
198
|
return (
|
|
@@ -323,7 +223,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
323
223
|
/>
|
|
324
224
|
)}
|
|
325
225
|
</View>
|
|
326
|
-
{isCheckingSession
|
|
226
|
+
{isCheckingSession ? (
|
|
327
227
|
<LottieView
|
|
328
228
|
source={require('../../Shared/Animations/loading.json')}
|
|
329
229
|
style={styles.loadingAnimation}
|
|
@@ -331,7 +231,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
331
231
|
loop={true}
|
|
332
232
|
resizeMode="cover"
|
|
333
233
|
/>
|
|
334
|
-
) :
|
|
234
|
+
) : (
|
|
335
235
|
<>
|
|
336
236
|
<Text style={styles.mainText}>
|
|
337
237
|
{t('verificationSessionCheckScreen.mainText')}
|
|
@@ -357,23 +257,42 @@ const VerificationSessionCheckScreen = () => {
|
|
|
357
257
|
alphanumericText.length === 8
|
|
358
258
|
) {
|
|
359
259
|
try {
|
|
260
|
+
isCheckingSessionRef.current = true;
|
|
360
261
|
setIsCheckingSession(true);
|
|
361
|
-
const
|
|
262
|
+
const isDemoMode = isDemoSession(alphanumericText);
|
|
263
|
+
const sessionResponse =
|
|
362
264
|
await getSessionByCode(alphanumericText);
|
|
363
|
-
if (
|
|
265
|
+
if (sessionResponse?.id) {
|
|
364
266
|
if (appContext.setSessionId) {
|
|
365
|
-
appContext.setSessionId(
|
|
267
|
+
appContext.setSessionId(sessionResponse.id);
|
|
366
268
|
} else {
|
|
367
269
|
appContext.identificationInfo.sessionId =
|
|
368
|
-
|
|
270
|
+
sessionResponse.id;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const session = await getSession(sessionResponse.id, isDemoMode);
|
|
274
|
+
appContext.workflowSteps = session?.workflowSteps;
|
|
275
|
+
if (session?.branding) {
|
|
276
|
+
appContext.branding = appContext.branding || session.branding;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (session?.sendOTP) {
|
|
280
|
+
navigateToOTPScreen(sessionResponse.id);
|
|
281
|
+
} else {
|
|
282
|
+
if (session?.identificationId) {
|
|
283
|
+
appContext.identificationInfo.identificationId =
|
|
284
|
+
session?.identificationId;
|
|
285
|
+
}
|
|
286
|
+
navigationManagerRef.current?.navigateToNextStep();
|
|
369
287
|
}
|
|
370
288
|
} else {
|
|
371
289
|
setSessionCode('');
|
|
372
290
|
}
|
|
373
|
-
} catch {
|
|
291
|
+
} catch (error) {
|
|
374
292
|
setSessionCode('');
|
|
375
293
|
} finally {
|
|
376
294
|
setTimeout(() => {
|
|
295
|
+
isCheckingSessionRef.current = false;
|
|
377
296
|
setIsCheckingSession(false);
|
|
378
297
|
}, 1000);
|
|
379
298
|
}
|
|
@@ -408,64 +327,6 @@ const VerificationSessionCheckScreen = () => {
|
|
|
408
327
|
{t('verificationSessionCheckScreen.scanQRCode')}
|
|
409
328
|
</StyledButton>
|
|
410
329
|
</>
|
|
411
|
-
) : (
|
|
412
|
-
<>
|
|
413
|
-
<Text style={styles.mainText}>
|
|
414
|
-
{t('verificationSessionCheckScreen.codeText')}
|
|
415
|
-
</Text>
|
|
416
|
-
<StyledTextInput
|
|
417
|
-
autoFocus={true}
|
|
418
|
-
placeholder=""
|
|
419
|
-
borderColor={primaryColor}
|
|
420
|
-
focusedBorderColor={primaryColor}
|
|
421
|
-
inputStyle={styles.otpCodeTextInput}
|
|
422
|
-
keyboardType="number-pad"
|
|
423
|
-
textContentType="oneTimeCode"
|
|
424
|
-
autoComplete="sms-otp"
|
|
425
|
-
maxLength={6}
|
|
426
|
-
onChangeText={(text) => {
|
|
427
|
-
const numericText = text.replace(/[^0-9]/g, '');
|
|
428
|
-
if (numericText.length <= 6) {
|
|
429
|
-
setCode(numericText);
|
|
430
|
-
if (numericText.length === 6) {
|
|
431
|
-
(async () => {
|
|
432
|
-
setIsCodeGettingVerified(true);
|
|
433
|
-
const verifiedSession = await getVerifiedSession(
|
|
434
|
-
appContext.identificationInfo.sessionId,
|
|
435
|
-
numericText
|
|
436
|
-
);
|
|
437
|
-
if (verifiedSession?.identificationId) {
|
|
438
|
-
appContext.identificationInfo.identificationId =
|
|
439
|
-
verifiedSession?.identificationId;
|
|
440
|
-
setCode('');
|
|
441
|
-
setIsCodeSent(false);
|
|
442
|
-
navigationManagerRef.current?.navigateToNextStep();
|
|
443
|
-
} else {
|
|
444
|
-
// User entered wrong OTP code - expected behavior, not actionable
|
|
445
|
-
appContext.onError?.('Invalid OTP code');
|
|
446
|
-
Alert.alert(
|
|
447
|
-
t('general.error'),
|
|
448
|
-
t('verificationSessionCheckScreen.codeError')
|
|
449
|
-
);
|
|
450
|
-
setCode('');
|
|
451
|
-
setIsCodeGettingVerified(false);
|
|
452
|
-
}
|
|
453
|
-
})();
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}}
|
|
457
|
-
value={code}
|
|
458
|
-
/>
|
|
459
|
-
<StyledButton
|
|
460
|
-
mode="contained"
|
|
461
|
-
disabled={!isSendAgainEnabled}
|
|
462
|
-
onPress={() => {
|
|
463
|
-
sendOTPCode(appContext.identificationInfo.sessionId);
|
|
464
|
-
}}
|
|
465
|
-
>
|
|
466
|
-
{t('verificationSessionCheckScreen.sendCodeAgain')}
|
|
467
|
-
</StyledButton>
|
|
468
|
-
</>
|
|
469
330
|
)}
|
|
470
331
|
</View>
|
|
471
332
|
{appContext.branding.logoUrl && (
|
|
@@ -593,12 +454,6 @@ const styles = StyleSheet.create({
|
|
|
593
454
|
textAlign: 'center',
|
|
594
455
|
textTransform: 'none',
|
|
595
456
|
},
|
|
596
|
-
otpCodeTextInput: {
|
|
597
|
-
fontWeight: '800',
|
|
598
|
-
fontSize: 28,
|
|
599
|
-
textAlign: 'center',
|
|
600
|
-
letterSpacing: 8,
|
|
601
|
-
},
|
|
602
457
|
});
|
|
603
458
|
|
|
604
459
|
export default VerificationSessionCheckScreen;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import React, { useCallback, useContext, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
TouchableOpacity,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
Platform,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { useNavigation } from '@react-navigation/native';
|
|
10
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
11
|
+
import AppContext from '../Contexts/AppContext';
|
|
12
|
+
import { getSimulatedDemoData } from '../Libs/demo.utils';
|
|
13
|
+
import type { VerificationSession } from '../Types/verificationSession';
|
|
14
|
+
|
|
15
|
+
type ScreenOption = {
|
|
16
|
+
screen: string;
|
|
17
|
+
label: string;
|
|
18
|
+
icon: string;
|
|
19
|
+
setupDemo?: () => void;
|
|
20
|
+
params?: Record<string, unknown>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Icon mapping matching Flutter SDK Material Icons
|
|
24
|
+
const ICONS = {
|
|
25
|
+
LOGIN: '🔑', // Icons.login
|
|
26
|
+
HANDSHAKE: '🤝', // Icons.handshake
|
|
27
|
+
CREDIT_CARD: '💳', // Icons.credit_card
|
|
28
|
+
NFC: '📡', // Icons.nfc
|
|
29
|
+
FACE: '👤', // Icons.face
|
|
30
|
+
CHECK_CIRCLE: '✅', // Icons.check_circle
|
|
31
|
+
BUG_REPORT: '🔧', // Icons.bug_report (using wrench for debug)
|
|
32
|
+
PHONE: '📱', // Icons.phone
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
const DebugNavigationPanel = () => {
|
|
36
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
37
|
+
const navigation = useNavigation();
|
|
38
|
+
const appContext = useContext(AppContext);
|
|
39
|
+
const insets = useSafeAreaInsets();
|
|
40
|
+
|
|
41
|
+
const setupDemoSession = useCallback((setDebugFlag: boolean = false) => {
|
|
42
|
+
appContext.setIsDemoSession?.(true);
|
|
43
|
+
appContext.identificationInfo.sessionId = 'demo-verification-id';
|
|
44
|
+
appContext.identificationInfo.identificationId = 'demo-identification-id';
|
|
45
|
+
appContext.isDebugNavigated = setDebugFlag;
|
|
46
|
+
|
|
47
|
+
// Populate workflow steps with demo data (including contract URLs)
|
|
48
|
+
const demoSession = getSimulatedDemoData<VerificationSession, never>('GET_SESSION');
|
|
49
|
+
appContext.workflowSteps = demoSession.workflowSteps;
|
|
50
|
+
}, [appContext]);
|
|
51
|
+
|
|
52
|
+
const screens: ScreenOption[] = [
|
|
53
|
+
{
|
|
54
|
+
screen: 'VerificationSessionCheckScreen',
|
|
55
|
+
label: 'Session Check',
|
|
56
|
+
icon: ICONS.LOGIN,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
screen: 'OTPVerificationScreen',
|
|
60
|
+
label: 'OTP',
|
|
61
|
+
icon: ICONS.PHONE,
|
|
62
|
+
setupDemo: () => {
|
|
63
|
+
setupDemoSession(true);
|
|
64
|
+
},
|
|
65
|
+
params: { sessionId: 'demo-verification-id' },
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
screen: 'ContractAcceptanceScreen',
|
|
69
|
+
label: 'Consent',
|
|
70
|
+
icon: ICONS.HANDSHAKE,
|
|
71
|
+
setupDemo: () => {
|
|
72
|
+
setupDemoSession(true);
|
|
73
|
+
// Set current workflow step to contract acceptance so demo contract URLs are loaded
|
|
74
|
+
const contractStep = appContext.workflowSteps?.find(
|
|
75
|
+
(step) => step.type === 'CONTRACT_ACCEPTANCE'
|
|
76
|
+
);
|
|
77
|
+
if (contractStep) {
|
|
78
|
+
appContext.currentWorkflowStep = contractStep;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
screen: 'IdentityDocumentScanningScreen',
|
|
84
|
+
label: 'ID Scan',
|
|
85
|
+
icon: ICONS.CREDIT_CARD,
|
|
86
|
+
setupDemo: () => {
|
|
87
|
+
setupDemoSession(true);
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
screen: 'IdentityDocumentEIDScanningScreen',
|
|
92
|
+
label: 'eID Scan',
|
|
93
|
+
icon: ICONS.NFC,
|
|
94
|
+
setupDemo: () => {
|
|
95
|
+
setupDemoSession(true);
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
screen: 'LivenessDetectionScreen',
|
|
100
|
+
label: 'Liveness',
|
|
101
|
+
icon: ICONS.FACE,
|
|
102
|
+
setupDemo: () => {
|
|
103
|
+
setupDemoSession(true);
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
screen: 'ResultScreen',
|
|
108
|
+
label: 'Result',
|
|
109
|
+
icon: ICONS.CHECK_CIRCLE,
|
|
110
|
+
setupDemo: () => {
|
|
111
|
+
setupDemoSession();
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
const jumpToScreen = useCallback(
|
|
117
|
+
(screen: ScreenOption) => {
|
|
118
|
+
if (screen.setupDemo) {
|
|
119
|
+
screen.setupDemo();
|
|
120
|
+
}
|
|
121
|
+
(navigation as any).navigate(screen.screen, screen.params);
|
|
122
|
+
setIsExpanded(false);
|
|
123
|
+
},
|
|
124
|
+
[navigation]
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Only show in development mode
|
|
128
|
+
if (!__DEV__) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<View style={[styles.container, { bottom: 20 + insets.bottom }]}>
|
|
134
|
+
{isExpanded && (
|
|
135
|
+
<View style={styles.panel}>
|
|
136
|
+
<Text style={styles.title}>SDK JUMP TO SCREEN:</Text>
|
|
137
|
+
{screens.map((screen) => (
|
|
138
|
+
<TouchableOpacity
|
|
139
|
+
key={screen.screen}
|
|
140
|
+
style={styles.screenButton}
|
|
141
|
+
onPress={() => jumpToScreen(screen)}
|
|
142
|
+
>
|
|
143
|
+
<Text style={styles.screenIcon}>{screen.icon}</Text>
|
|
144
|
+
<Text style={styles.screenLabel}>{screen.label}</Text>
|
|
145
|
+
</TouchableOpacity>
|
|
146
|
+
))}
|
|
147
|
+
</View>
|
|
148
|
+
)}
|
|
149
|
+
<TouchableOpacity
|
|
150
|
+
style={styles.toggleButton}
|
|
151
|
+
onPress={() => setIsExpanded(!isExpanded)}
|
|
152
|
+
>
|
|
153
|
+
<Text style={styles.bugIcon}>{ICONS.BUG_REPORT}</Text>
|
|
154
|
+
{isExpanded && (
|
|
155
|
+
<>
|
|
156
|
+
<View style={styles.spacing} />
|
|
157
|
+
<Text style={styles.toggleText}>DEBUG NAV</Text>
|
|
158
|
+
</>
|
|
159
|
+
)}
|
|
160
|
+
<View style={styles.spacing} />
|
|
161
|
+
<Text style={styles.arrow}>{isExpanded ? '▼' : '▲'}</Text>
|
|
162
|
+
</TouchableOpacity>
|
|
163
|
+
</View>
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const styles = StyleSheet.create({
|
|
168
|
+
container: {
|
|
169
|
+
position: 'absolute',
|
|
170
|
+
right: 20,
|
|
171
|
+
alignItems: 'flex-end',
|
|
172
|
+
zIndex: 9999,
|
|
173
|
+
},
|
|
174
|
+
toggleButton: {
|
|
175
|
+
flexDirection: 'row',
|
|
176
|
+
alignItems: 'center',
|
|
177
|
+
backgroundColor: '#FF5252',
|
|
178
|
+
paddingHorizontal: 12,
|
|
179
|
+
paddingVertical: 10,
|
|
180
|
+
borderRadius: 10,
|
|
181
|
+
borderWidth: 2,
|
|
182
|
+
borderColor: 'white',
|
|
183
|
+
...Platform.select({
|
|
184
|
+
ios: {
|
|
185
|
+
shadowColor: '#000',
|
|
186
|
+
shadowOffset: { width: 0, height: 4 },
|
|
187
|
+
shadowOpacity: 0.3,
|
|
188
|
+
shadowRadius: 8,
|
|
189
|
+
},
|
|
190
|
+
android: {
|
|
191
|
+
elevation: 8,
|
|
192
|
+
},
|
|
193
|
+
}),
|
|
194
|
+
},
|
|
195
|
+
bugIcon: {
|
|
196
|
+
fontSize: 24,
|
|
197
|
+
},
|
|
198
|
+
spacing: {
|
|
199
|
+
width: 8,
|
|
200
|
+
},
|
|
201
|
+
toggleText: {
|
|
202
|
+
color: 'white',
|
|
203
|
+
fontSize: 14,
|
|
204
|
+
fontWeight: 'bold',
|
|
205
|
+
},
|
|
206
|
+
arrow: {
|
|
207
|
+
color: 'white',
|
|
208
|
+
fontSize: 20,
|
|
209
|
+
},
|
|
210
|
+
panel: {
|
|
211
|
+
backgroundColor: 'rgba(0, 0, 0, 0.9)',
|
|
212
|
+
borderRadius: 12,
|
|
213
|
+
padding: 12,
|
|
214
|
+
marginBottom: 10,
|
|
215
|
+
borderWidth: 1,
|
|
216
|
+
borderColor: 'rgba(255, 82, 82, 0.5)',
|
|
217
|
+
minWidth: 180,
|
|
218
|
+
...Platform.select({
|
|
219
|
+
ios: {
|
|
220
|
+
shadowColor: '#000',
|
|
221
|
+
shadowOffset: { width: 0, height: 4 },
|
|
222
|
+
shadowOpacity: 0.5,
|
|
223
|
+
shadowRadius: 15,
|
|
224
|
+
},
|
|
225
|
+
android: {
|
|
226
|
+
elevation: 15,
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
},
|
|
230
|
+
title: {
|
|
231
|
+
color: 'rgba(255, 255, 255, 0.7)',
|
|
232
|
+
fontSize: 11,
|
|
233
|
+
fontWeight: 'bold',
|
|
234
|
+
letterSpacing: 1.2,
|
|
235
|
+
marginBottom: 12,
|
|
236
|
+
textAlign: 'right',
|
|
237
|
+
},
|
|
238
|
+
screenButton: {
|
|
239
|
+
flexDirection: 'row',
|
|
240
|
+
alignItems: 'center',
|
|
241
|
+
justifyContent: 'flex-start',
|
|
242
|
+
backgroundColor: '#616161',
|
|
243
|
+
paddingHorizontal: 12,
|
|
244
|
+
paddingVertical: 8,
|
|
245
|
+
borderRadius: 4,
|
|
246
|
+
marginBottom: 6,
|
|
247
|
+
},
|
|
248
|
+
screenIcon: {
|
|
249
|
+
fontSize: 16,
|
|
250
|
+
marginRight: 8,
|
|
251
|
+
width: 20,
|
|
252
|
+
textAlign: 'center',
|
|
253
|
+
},
|
|
254
|
+
screenLabel: {
|
|
255
|
+
color: 'white',
|
|
256
|
+
fontSize: 12,
|
|
257
|
+
fontWeight: '500',
|
|
258
|
+
flex: 1,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
export default DebugNavigationPanel;
|