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