@trustchex/react-native-sdk 1.215.0 → 1.248.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.
Files changed (49) hide show
  1. package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +2 -2
  2. package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +2 -2
  3. package/lib/module/Screens/Static/ResultScreen.js +4 -9
  4. package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +150 -106
  5. package/lib/module/Shared/Components/EIDScanner.js +4 -4
  6. package/lib/module/Shared/Components/FaceCamera.js +4 -3
  7. package/lib/module/Shared/Components/IdentityDocumentCamera.js +4 -3
  8. package/lib/module/Shared/Components/QrCodeScannerCamera.js +2 -2
  9. package/lib/module/Shared/Components/StyledButton.js +30 -0
  10. package/lib/module/Shared/Constants/index.js +3 -0
  11. package/lib/module/Shared/Constants/validation.constants.js +24 -0
  12. package/lib/module/Shared/Libs/demo.utils.js +5 -3
  13. package/lib/module/Translation/Resources/en.js +50 -52
  14. package/lib/module/Translation/Resources/tr.js +48 -53
  15. package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
  16. package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
  17. package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
  18. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  19. package/lib/typescript/src/Shared/Components/StyledButton.d.ts +6 -0
  20. package/lib/typescript/src/Shared/Components/StyledButton.d.ts.map +1 -0
  21. package/lib/typescript/src/Shared/Constants/index.d.ts +2 -0
  22. package/lib/typescript/src/Shared/Constants/index.d.ts.map +1 -0
  23. package/lib/typescript/src/Shared/Constants/validation.constants.d.ts +20 -0
  24. package/lib/typescript/src/Shared/Constants/validation.constants.d.ts.map +1 -0
  25. package/lib/typescript/src/Shared/Libs/demo.utils.d.ts +2 -2
  26. package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
  27. package/lib/typescript/src/Translation/Resources/en.d.ts +1 -3
  28. package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
  29. package/lib/typescript/src/Translation/Resources/tr.d.ts +1 -6
  30. package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +3 -3
  33. package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +3 -3
  34. package/src/Screens/Static/ResultScreen.tsx +14 -12
  35. package/src/Screens/Static/VerificationSessionCheckScreen.tsx +184 -131
  36. package/src/Shared/Components/EIDScanner.tsx +7 -7
  37. package/src/Shared/Components/FaceCamera.tsx +6 -5
  38. package/src/Shared/Components/IdentityDocumentCamera.tsx +6 -5
  39. package/src/Shared/Components/QrCodeScannerCamera.tsx +3 -3
  40. package/src/Shared/Components/StyledButton.tsx +35 -0
  41. package/src/Shared/Constants/index.ts +1 -0
  42. package/src/Shared/Constants/validation.constants.ts +24 -0
  43. package/src/Shared/Libs/demo.utils.ts +5 -4
  44. package/src/Translation/Resources/en.ts +51 -54
  45. package/src/Translation/Resources/tr.ts +50 -55
  46. package/lib/module/Shared/Components/OTPCodeInput.js +0 -74
  47. package/lib/typescript/src/Shared/Components/OTPCodeInput.d.ts +0 -10
  48. package/lib/typescript/src/Shared/Components/OTPCodeInput.d.ts.map +0 -1
  49. package/src/Shared/Components/OTPCodeInput.tsx +0 -93
@@ -6,7 +6,7 @@ import WebView from 'react-native-webview';
6
6
  import NavigationManager from "../../Shared/Components/NavigationManager.js";
7
7
  import AppContext from "../../Shared/Contexts/AppContext.js";
8
8
  import { getI18n, useTranslation } from 'react-i18next';
9
- import { Button } from 'react-native-paper';
9
+ import StyledButton from "../../Shared/Components/StyledButton.js";
10
10
  import NativeDeviceInfo from "../../Shared/Libs/native-device-info.utils.js";
11
11
  import { speakWithDebounce } from "../../Shared/Libs/tts.utils.js";
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -84,7 +84,7 @@ const ContractAcceptanceScreen = () => {
84
84
  children: [/*#__PURE__*/_jsx(Text, {
85
85
  style: styles.footerText,
86
86
  children: t('termsOfUseAndDataPrivacyScreen.footerText')
87
- }), /*#__PURE__*/_jsx(Button, {
87
+ }), /*#__PURE__*/_jsx(StyledButton, {
88
88
  mode: "contained",
89
89
  disabled: !isEnabled,
90
90
  onPress: async () => {
@@ -10,7 +10,7 @@ import NavigationManager from "../../Shared/Components/NavigationManager.js";
10
10
  import AppContext from "../../Shared/Contexts/AppContext.js";
11
11
  import { contains } from "../../Shared/Libs/contains.js";
12
12
  import { useTranslation } from 'react-i18next';
13
- import { Button } from 'react-native-paper';
13
+ import StyledButton from "../../Shared/Components/StyledButton.js";
14
14
  import LottieView from 'lottie-react-native';
15
15
  import { speakWithDebounce } from "../../Shared/Libs/tts.utils.js";
16
16
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
@@ -415,7 +415,7 @@ const LivenessDetectionScreen = () => {
415
415
  style: styles.guideText,
416
416
  children: ["\u2022 ", t('livenessDetectionScreen.guidePoint4')]
417
417
  })]
418
- }), /*#__PURE__*/_jsx(Button, {
418
+ }), /*#__PURE__*/_jsx(StyledButton, {
419
419
  mode: "contained",
420
420
  onPress: () => {
421
421
  setHasGuideShown(true);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import React, { useCallback, useContext, useEffect, useState } from 'react';
3
+ import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
4
4
  import { Alert, Image, Platform, SafeAreaView, ScrollView, StyleSheet, Text, View } from 'react-native';
5
5
  import AppContext from "../../Shared/Contexts/AppContext.js";
6
6
  import httpClient from "../../Shared/Libs/http-client.js";
@@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next';
14
14
  import { Video as VideoCompressor } from 'react-native-compressor';
15
15
  import { encryptWithAes, getSessionKey } from "../../Shared/Libs/crypto.utils.js";
16
16
  import Video from 'react-native-video';
17
- import { Button } from 'react-native-paper';
17
+ import StyledButton from "../../Shared/Components/StyledButton.js";
18
18
  import NativeDeviceInfo from "../../Shared/Libs/native-device-info.utils.js";
19
19
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
20
20
  const ResultScreen = () => {
@@ -22,17 +22,12 @@ const ResultScreen = () => {
22
22
  const [isSubmitting, setIsSubmitting] = useState(false);
23
23
  const [progress, setProgress] = useState(0);
24
24
  const navigationManagerRef = React.useRef(null);
25
- const [apiUrl, setApiUrl] = useState(`${appContext.baseUrl}/api/app/mobile`);
26
25
  const [shouldShowDemoData, setShouldShowDemoData] = useState(false);
27
26
  const [deviceIdentifier, setDeviceIdentifier] = useState('');
28
27
  const {
29
28
  t
30
29
  } = useTranslation();
31
- useEffect(() => {
32
- if (appContext.baseUrl) {
33
- setApiUrl(`${appContext.baseUrl}/api/app/mobile`);
34
- }
35
- }, [appContext.baseUrl]);
30
+ const apiUrl = useMemo(() => `${appContext.baseUrl}/api/app/mobile`, [appContext.baseUrl]);
36
31
  useEffect(() => {
37
32
  if (appContext.isDemoSession) {
38
33
  setShouldShowDemoData(true);
@@ -503,7 +498,7 @@ const ResultScreen = () => {
503
498
  })]
504
499
  })]
505
500
  })
506
- }), /*#__PURE__*/_jsx(Button, {
501
+ }), /*#__PURE__*/_jsx(StyledButton, {
507
502
  mode: "contained",
508
503
  onPress: () => {
509
504
  appContext.onCompleted?.();
@@ -1,23 +1,23 @@
1
1
  "use strict";
2
2
 
3
- import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
3
+ import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
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
7
  import httpClient, { NotFoundError } from "../../Shared/Libs/http-client.js";
8
- import OTPCodeInput from "../../Shared/Components/OTPCodeInput.js";
9
8
  import { useTranslation } from 'react-i18next';
10
9
  import LanguageSelector from "../../Shared/Components/LanguageSelector.js";
11
10
  import NavigationManager from "../../Shared/Components/NavigationManager.js";
12
- import { Button, TextInput, useTheme } from 'react-native-paper';
11
+ import { TextInput, useTheme } from 'react-native-paper';
12
+ import StyledButton from "../../Shared/Components/StyledButton.js";
13
13
  import LottieView from 'lottie-react-native';
14
14
  import { getSimulatedDemoData, isDemoSession } from "../../Shared/Libs/demo.utils.js";
15
15
  import { useNavigation } from '@react-navigation/native';
16
+ import { SESSION_CODE_CHARSET_PATTERN, SESSION_CODE_VALIDATION_PATTERN } from "../../Shared/Constants/validation.constants.js";
16
17
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
17
18
  const VerificationSessionCheckScreen = () => {
18
- const [emailOrPhone, setEmailOrPhone] = useState('');
19
+ const [sessionCode, setSessionCode] = useState('');
19
20
  const [code, setCode] = useState('');
20
- const [isEnabled, setIsEnabled] = useState(false);
21
21
  const [isCheckingSession, setIsCheckingSession] = useState(false);
22
22
  const [isSendAgainEnabled, setIsSendAgainEnabled] = useState(false);
23
23
  const [isCodeSent, setIsCodeSent] = useState(false);
@@ -28,22 +28,12 @@ const VerificationSessionCheckScreen = () => {
28
28
  } = useTranslation();
29
29
  const navigationManagerRef = React.useRef(null);
30
30
  const navigation = useNavigation();
31
- const [apiUrl, setApiUrl] = useState(`${appContext.baseUrl}/api/app/mobile`);
32
31
  const theme = useTheme();
33
32
  const initialized = useRef(false);
34
33
  const insets = useSafeAreaInsets();
35
- useEffect(() => {
36
- if (appContext.baseUrl) {
37
- setApiUrl(`${appContext.baseUrl}/api/app/mobile`);
38
- }
39
- }, [appContext.baseUrl]);
40
- const validateEmail = useCallback(value => {
41
- const re = /\S+@\S+\.\S+/;
42
- return re.test(value);
43
- }, []);
44
- const validatePhoneNumber = useCallback(value => {
45
- const re = /^(5(\d{9}))/;
46
- return re.test(value);
34
+ const apiUrl = useMemo(() => `${appContext.baseUrl}/api/app/mobile`, [appContext.baseUrl]);
35
+ const validateSessionCode = useCallback(value => {
36
+ return SESSION_CODE_VALIDATION_PATTERN.test(value.toUpperCase());
47
37
  }, []);
48
38
  const getSession = useCallback(async id => {
49
39
  try {
@@ -55,18 +45,11 @@ const VerificationSessionCheckScreen = () => {
55
45
  }
56
46
  }
57
47
  }, [apiUrl, appContext.isDemoSession, t]);
58
- const getSessions = useCallback(async value => {
48
+ const getSessionByCode = useCallback(async inputCode => {
59
49
  try {
60
- const isEmail = validateEmail(value);
61
- const isPhoneNumber = validatePhoneNumber(value);
62
- let response = [];
63
- if (isEmail) {
64
- appContext.isDemoSession = isDemoSession(value);
65
- response = await httpClient.get(`${apiUrl}/verification-sessions?email=${value}`, appContext.isDemoSession ? getSimulatedDemoData('VERIFICATION_SESSIONS') : undefined);
66
- } else if (isPhoneNumber) {
67
- response = await httpClient.get(`${apiUrl}/verification-sessions?phoneNumber=${value}`);
68
- }
69
- if (!response || response.length === 0) {
50
+ appContext.isDemoSession = isDemoSession(inputCode);
51
+ const response = await httpClient.get(`${apiUrl}/verification-sessions?sessionCode=${inputCode.toUpperCase()}`, appContext.isDemoSession ? getSimulatedDemoData('GET_SESSION_BY_CODE') : undefined);
52
+ if (!response || !response.id) {
70
53
  throw new NotFoundError();
71
54
  }
72
55
  return response;
@@ -75,7 +58,7 @@ const VerificationSessionCheckScreen = () => {
75
58
  Alert.alert(t('general.error'), t('verificationSessionCheckScreen.noVerificationSessionFound'));
76
59
  }
77
60
  }
78
- }, [apiUrl, appContext, t, validateEmail, validatePhoneNumber]);
61
+ }, [apiUrl, appContext, t]);
79
62
  const sendVerificationCode = useCallback(async sessionId => {
80
63
  try {
81
64
  await httpClient.post(`${apiUrl}/verification-sessions/${sessionId}`, {}, appContext.isDemoSession ? getSimulatedDemoData('SEND_VERIFICATION_CODE') : undefined);
@@ -103,7 +86,7 @@ const VerificationSessionCheckScreen = () => {
103
86
  }
104
87
  }
105
88
  }, [apiUrl, appContext.isDemoSession, t]);
106
- const sendCode = useCallback(async sessionId => {
89
+ const sendOTPCode = useCallback(async sessionId => {
107
90
  if (!sessionId) {
108
91
  return false;
109
92
  }
@@ -131,7 +114,7 @@ const VerificationSessionCheckScreen = () => {
131
114
  theme.colors.tertiary = appContext.branding.tertiaryColor;
132
115
  }
133
116
  if (session?.sendOTP) {
134
- return sendCode(session.id);
117
+ return sendOTPCode(session.id);
135
118
  } else if (session?.identificationId) {
136
119
  appContext.identificationInfo.identificationId = session?.identificationId;
137
120
  navigationManagerRef.current?.navigateToNextStep();
@@ -142,7 +125,7 @@ const VerificationSessionCheckScreen = () => {
142
125
  }, 1000);
143
126
  });
144
127
  }
145
- }, [appContext, appContext.identificationInfo.sessionId, getSession, sendCode, theme.colors, theme.colors.primary, theme.colors.secondary, theme.colors.tertiary]);
128
+ }, [appContext, appContext.identificationInfo.sessionId, getSession, sendOTPCode, theme.colors, theme.colors.primary, theme.colors.secondary, theme.colors.tertiary]);
146
129
  return /*#__PURE__*/_jsx(SafeAreaView, {
147
130
  style: styles.safeAreaContainer,
148
131
  children: /*#__PURE__*/_jsx(KeyboardAvoidingView, {
@@ -177,87 +160,111 @@ const VerificationSessionCheckScreen = () => {
177
160
  children: [/*#__PURE__*/_jsx(Text, {
178
161
  style: styles.mainText,
179
162
  children: t('verificationSessionCheckScreen.mainText')
180
- }), /*#__PURE__*/_jsx(TextInput, {
181
- mode: "outlined",
182
- autoCapitalize: "none",
183
- placeholder: t('verificationSessionCheckScreen.inputPlaceholder'),
184
- onChangeText: text => {
185
- setEmailOrPhone(text);
186
- if (validateEmail(text) || validatePhoneNumber(text)) {
187
- setIsEnabled(true);
188
- } else {
189
- setIsEnabled(false);
190
- }
191
- }
192
- }), /*#__PURE__*/_jsx(Button, {
193
- mode: "contained",
194
- disabled: !isEnabled,
195
- onPress: async () => {
196
- try {
197
- setIsCheckingSession(true);
198
- const sessions = await getSessions(emailOrPhone);
199
- if (sessions && sessions.length > 0) {
200
- appContext.identificationInfo.sessionId = sessions[0].id;
163
+ }), /*#__PURE__*/_jsxs(View, {
164
+ style: styles.inputContainer,
165
+ children: [/*#__PURE__*/_jsx(TextInput, {
166
+ mode: "outlined",
167
+ autoCapitalize: "characters",
168
+ placeholder: "",
169
+ outlineColor: theme.colors.primary,
170
+ activeOutlineColor: theme.colors.primary,
171
+ style: styles.sessionCodeTextInput,
172
+ contentStyle: styles.sessionCodeInputWithText,
173
+ onChangeText: async text => {
174
+ const alphanumericText = text.toUpperCase().replace(SESSION_CODE_CHARSET_PATTERN, '');
175
+ if (alphanumericText.length <= 8) {
176
+ setSessionCode(alphanumericText);
177
+ if (validateSessionCode(alphanumericText) && alphanumericText.length === 8) {
178
+ try {
179
+ setIsCheckingSession(true);
180
+ const session = await getSessionByCode(alphanumericText);
181
+ if (session?.id) {
182
+ appContext.identificationInfo.sessionId = session.id;
183
+ } else {
184
+ setSessionCode('');
185
+ }
186
+ } catch {
187
+ setSessionCode('');
188
+ } finally {
189
+ setTimeout(() => {
190
+ setIsCheckingSession(false);
191
+ }, 1000);
192
+ }
193
+ }
201
194
  }
202
- } catch {
203
- // Do nothing
204
- } finally {
205
- setTimeout(() => {
206
- setIsCheckingSession(false);
207
- setIsEnabled(false);
208
- }, 1000);
209
- }
210
- },
211
- children: t('verificationSessionCheckScreen.continue')
212
- }), !isEnabled && /*#__PURE__*/_jsxs(_Fragment, {
213
- children: [/*#__PURE__*/_jsxs(View, {
214
- style: styles.horizontalLineContainer,
215
- children: [/*#__PURE__*/_jsx(View, {
216
- style: styles.horizontalLine
217
- }), /*#__PURE__*/_jsx(Text, {
218
- style: styles.mainText,
219
- children: t('verificationSessionCheckScreen.or')
220
- }), /*#__PURE__*/_jsx(View, {
221
- style: styles.horizontalLine
222
- })]
223
- }), /*#__PURE__*/_jsx(Button, {
224
- mode: "contained",
225
- onPress: () => {
226
- navigation.navigate('QrCodeScanningScreen');
227
195
  },
228
- children: t('verificationSessionCheckScreen.scanQRCode')
196
+ value: sessionCode.toUpperCase(),
197
+ maxLength: 8
198
+ }), !sessionCode && /*#__PURE__*/_jsx(Text, {
199
+ style: styles.placeholderText,
200
+ children: t('verificationSessionCheckScreen.enterSessionCode')
229
201
  })]
202
+ }), /*#__PURE__*/_jsxs(View, {
203
+ style: styles.horizontalLineContainer,
204
+ children: [/*#__PURE__*/_jsx(View, {
205
+ style: [styles.horizontalLine, {
206
+ backgroundColor: theme.colors.primary
207
+ }]
208
+ }), /*#__PURE__*/_jsx(Text, {
209
+ style: styles.mainText,
210
+ children: t('verificationSessionCheckScreen.or')
211
+ }), /*#__PURE__*/_jsx(View, {
212
+ style: [styles.horizontalLine, {
213
+ backgroundColor: theme.colors.primary
214
+ }]
215
+ })]
216
+ }), /*#__PURE__*/_jsx(StyledButton, {
217
+ mode: "contained",
218
+ onPress: () => {
219
+ navigation.navigate('QrCodeScanningScreen');
220
+ },
221
+ children: t('verificationSessionCheckScreen.scanQRCode')
230
222
  })]
231
223
  }) : /*#__PURE__*/_jsxs(_Fragment, {
232
224
  children: [/*#__PURE__*/_jsx(Text, {
233
225
  style: styles.mainText,
234
226
  children: t('verificationSessionCheckScreen.codeText')
235
- }), /*#__PURE__*/_jsx(OTPCodeInput, {
236
- value: code,
227
+ }), /*#__PURE__*/_jsx(TextInput, {
228
+ mode: "outlined",
229
+ autoFocus: true,
230
+ placeholder: "",
231
+ outlineColor: theme.colors.primary,
232
+ activeOutlineColor: theme.colors.primary,
233
+ style: styles.otpCodeTextInput,
234
+ contentStyle: styles.otpCodeInputWithText,
235
+ keyboardType: "number-pad",
236
+ textContentType: "oneTimeCode",
237
+ autoComplete: "sms-otp",
238
+ maxLength: 6,
237
239
  onChangeText: text => {
238
- setCode(text);
239
- },
240
- codeLength: 6,
241
- onCodeFilled: async value => {
242
- setIsCodeGettingVerified(true);
243
- const verifiedSession = await getVerifiedSession(appContext.identificationInfo.sessionId, value);
244
- if (verifiedSession?.identificationId) {
245
- appContext.identificationInfo.identificationId = verifiedSession?.identificationId;
246
- setCode('');
247
- setIsCodeSent(false);
248
- navigationManagerRef.current?.navigateToNextStep();
249
- } else {
250
- appContext.onError?.('Invalid OTP code');
251
- Alert.alert(t('general.error'), t('verificationSessionCheckScreen.codeError'));
252
- setCode('');
253
- setIsCodeGettingVerified(false);
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(appContext.identificationInfo.sessionId, numericText);
247
+ if (verifiedSession?.identificationId) {
248
+ appContext.identificationInfo.identificationId = verifiedSession?.identificationId;
249
+ setCode('');
250
+ setIsCodeSent(false);
251
+ navigationManagerRef.current?.navigateToNextStep();
252
+ } else {
253
+ appContext.onError?.('Invalid OTP code');
254
+ Alert.alert(t('general.error'), t('verificationSessionCheckScreen.codeError'));
255
+ setCode('');
256
+ setIsCodeGettingVerified(false);
257
+ }
258
+ })();
259
+ }
254
260
  }
255
- }
256
- }), /*#__PURE__*/_jsx(Button, {
261
+ },
262
+ value: code
263
+ }), /*#__PURE__*/_jsx(StyledButton, {
257
264
  mode: "contained",
258
265
  disabled: !isSendAgainEnabled,
259
266
  onPress: () => {
260
- sendCode(appContext.identificationInfo.sessionId);
267
+ sendOTPCode(appContext.identificationInfo.sessionId);
261
268
  },
262
269
  children: t('verificationSessionCheckScreen.sendCodeAgain')
263
270
  })]
@@ -298,17 +305,15 @@ const styles = StyleSheet.create({
298
305
  justifyContent: 'center'
299
306
  },
300
307
  horizontalLineContainer: {
301
- display: 'flex',
302
308
  flexDirection: 'row',
303
309
  alignItems: 'center',
304
- justifyContent: 'center',
310
+ justifyContent: 'space-between',
305
311
  gap: 10,
306
- padding: 10
312
+ paddingVertical: 10
307
313
  },
308
314
  horizontalLine: {
309
315
  flex: 1,
310
- height: 1,
311
- backgroundColor: '#aaa'
316
+ height: 2
312
317
  },
313
318
  loadingAnimation: {
314
319
  width: '100%',
@@ -376,6 +381,45 @@ const styles = StyleSheet.create({
376
381
  justifyContent: 'center',
377
382
  alignItems: 'center',
378
383
  position: 'absolute'
384
+ },
385
+ inputContainer: {
386
+ position: 'relative',
387
+ width: '100%'
388
+ },
389
+ sessionCodeTextInput: {
390
+ backgroundColor: 'white'
391
+ },
392
+ sessionCodeInputWithText: {
393
+ textTransform: 'uppercase',
394
+ fontWeight: '800',
395
+ fontSize: 28,
396
+ textAlign: 'center',
397
+ letterSpacing: 8
398
+ },
399
+ placeholderText: {
400
+ position: 'absolute',
401
+ top: 0,
402
+ left: 0,
403
+ right: 0,
404
+ height: '100%',
405
+ lineHeight: 56,
406
+ fontSize: 16,
407
+ color: '#666',
408
+ textAlign: 'center',
409
+ pointerEvents: 'none'
410
+ },
411
+ sessionCodeInputPlaceholder: {
412
+ fontSize: 16,
413
+ textAlign: 'center'
414
+ },
415
+ otpCodeTextInput: {
416
+ backgroundColor: 'white'
417
+ },
418
+ otpCodeInputWithText: {
419
+ fontWeight: '800',
420
+ fontSize: 28,
421
+ textAlign: 'center',
422
+ letterSpacing: 8
379
423
  }
380
424
  });
381
425
  export default VerificationSessionCheckScreen;
@@ -7,7 +7,7 @@ import { eidReader } from "../EIDReader/eidReader.js";
7
7
  import NativeProgressBar from "./NativeProgressBar.js";
8
8
  import { useTranslation } from 'react-i18next';
9
9
  import AppContext from "../Contexts/AppContext.js";
10
- import { Button } from 'react-native-paper';
10
+ import StyledButton from "./StyledButton.js";
11
11
  import LottieView from 'lottie-react-native';
12
12
  import { useKeepAwake } from "../Libs/native-keep-awake.utils.js";
13
13
  import { speakWithDebounce } from "../Libs/tts.utils.js";
@@ -136,7 +136,7 @@ const EIDScanner = ({
136
136
  style: styles.guideText,
137
137
  children: t('eidScannerScreen.guideText')
138
138
  })
139
- }), /*#__PURE__*/_jsx(Button, {
139
+ }), /*#__PURE__*/_jsx(StyledButton, {
140
140
  mode: "contained",
141
141
  onPress: () => {
142
142
  setHasGuideShown(true);
@@ -250,7 +250,7 @@ const EIDScanner = ({
250
250
  children: [/*#__PURE__*/_jsx(Text, {
251
251
  style: styles.mainText,
252
252
  children: t('eidScannerScreen.nfcNotEnabled')
253
- }), /*#__PURE__*/_jsx(Button, {
253
+ }), /*#__PURE__*/_jsx(StyledButton, {
254
254
  mode: "contained",
255
255
  onPress: async () => {
256
256
  await NFCManager.goToNfcSetting();
@@ -283,7 +283,7 @@ const EIDScanner = ({
283
283
  color: appContext.branding.primaryColor
284
284
  }), hasNfc && isEnabled && isScanned && /*#__PURE__*/_jsx(View, {
285
285
  style: styles.buttonsContainer,
286
- children: /*#__PURE__*/_jsx(Button, {
286
+ children: /*#__PURE__*/_jsx(StyledButton, {
287
287
  mode: "contained",
288
288
  disabled: !documentFaceImage || !documentMRZInfo,
289
289
  onPress: () => {
@@ -11,7 +11,8 @@ import { Worklets, useSharedValue } from 'react-native-worklets-core';
11
11
  import { crop } from "../VisionCameraPlugins/Cropper/index.js";
12
12
  import { isFrameBright } from "../Libs/camera.utils.js";
13
13
  import { useTranslation } from 'react-i18next';
14
- import { ActivityIndicator, Button } from 'react-native-paper';
14
+ import { ActivityIndicator } from 'react-native-paper';
15
+ import StyledButton from "./StyledButton.js";
15
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
17
  const VIDEO_WIDTH = 1280;
17
18
  const VIDEO_HEIGHT = 720;
@@ -141,7 +142,7 @@ const FaceCamera = ({
141
142
  children: [/*#__PURE__*/_jsx(Text, {
142
143
  style: styles.permissionText,
143
144
  children: t('general.noCameraPermissionGiven')
144
- }), /*#__PURE__*/_jsx(Button, {
145
+ }), /*#__PURE__*/_jsx(StyledButton, {
145
146
  mode: "contained",
146
147
  onPress: () => {
147
148
  Linking.openSettings();
@@ -156,7 +157,7 @@ const FaceCamera = ({
156
157
  children: [/*#__PURE__*/_jsx(Text, {
157
158
  style: styles.permissionText,
158
159
  children: t('general.noMicrophonePermissionGiven')
159
- }), /*#__PURE__*/_jsx(Button, {
160
+ }), /*#__PURE__*/_jsx(StyledButton, {
160
161
  mode: "contained",
161
162
  onPress: () => {
162
163
  Linking.openSettings();
@@ -17,7 +17,8 @@ import { AdaptiveThresholdTypes, ColorConversionCodes, DataTypes, ObjectType, Op
17
17
  import { getAverageBrightness } from "../Libs/camera.utils.js";
18
18
  import { useTranslation } from 'react-i18next';
19
19
  import LottieView from 'lottie-react-native';
20
- import { ActivityIndicator, Button } from 'react-native-paper';
20
+ import { ActivityIndicator } from 'react-native-paper';
21
+ import StyledButton from "./StyledButton.js";
21
22
  import { scanCodes } from "../VisionCameraPlugins/BarcodeScanner/index.js";
22
23
  import { speakWithDebounce } from "../Libs/tts.utils.js";
23
24
  import AppContext from "../Contexts/AppContext.js";
@@ -631,7 +632,7 @@ const IdentityDocumentCamera = ({
631
632
  children: [/*#__PURE__*/_jsx(Text, {
632
633
  style: styles.permissionText,
633
634
  children: t('general.noCameraPermissionGiven')
634
- }), /*#__PURE__*/_jsx(Button, {
635
+ }), /*#__PURE__*/_jsx(StyledButton, {
635
636
  mode: "contained",
636
637
  onPress: () => {
637
638
  Linking.openSettings();
@@ -692,7 +693,7 @@ const IdentityDocumentCamera = ({
692
693
  style: styles.guideText,
693
694
  children: ["\u2022 ", t('identityDocumentCamera.guidePoint3')]
694
695
  })]
695
- }), /*#__PURE__*/_jsx(Button, {
696
+ }), /*#__PURE__*/_jsx(StyledButton, {
696
697
  mode: "contained",
697
698
  onPress: () => {
698
699
  setHasGuideShown(true);
@@ -9,7 +9,7 @@ import { useIsFocused } from '@react-navigation/native';
9
9
  import { useTranslation } from 'react-i18next';
10
10
  import LottieView from 'lottie-react-native';
11
11
  import { scanCodes } from "../VisionCameraPlugins/BarcodeScanner/index.js";
12
- import { Button } from 'react-native-paper';
12
+ import StyledButton from "./StyledButton.js";
13
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  const QrCodeScannerCamera = ({
15
15
  onQrCodeScanned
@@ -133,7 +133,7 @@ const QrCodeScannerCamera = ({
133
133
  children: [/*#__PURE__*/_jsx(Text, {
134
134
  style: styles.permissionText,
135
135
  children: t('general.noCameraPermissionGiven')
136
- }), /*#__PURE__*/_jsx(Button, {
136
+ }), /*#__PURE__*/_jsx(StyledButton, {
137
137
  mode: "contained",
138
138
  onPress: () => {
139
139
  Linking.openSettings();
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { StyleSheet } from 'react-native';
5
+ import { Button } from 'react-native-paper';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const StyledButton = ({
8
+ style,
9
+ labelStyle,
10
+ ...props
11
+ }) => {
12
+ return /*#__PURE__*/_jsx(Button, {
13
+ ...props,
14
+ style: [styles.button, style],
15
+ labelStyle: [styles.label, labelStyle]
16
+ });
17
+ };
18
+ const styles = StyleSheet.create({
19
+ button: {
20
+ borderRadius: 8,
21
+ height: 56,
22
+ justifyContent: 'center',
23
+ elevation: 2
24
+ },
25
+ label: {
26
+ fontWeight: 'bold',
27
+ fontSize: 16
28
+ }
29
+ });
30
+ export default StyledButton;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ export * from "./validation.constants.js";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Validation constants used throughout the SDK.
5
+ * These constants ensure consistency between frontend and backend validation.
6
+ */
7
+
8
+ /**
9
+ * Character set for session codes.
10
+ * Excludes ambiguous characters (0, 1, I, O) to prevent confusion.
11
+ */
12
+ export const SESSION_CODE_CHARSET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
13
+
14
+ /**
15
+ * Regular expression pattern for validating session code characters.
16
+ * Matches only characters from SESSION_CODE_CHARSET.
17
+ */
18
+ export const SESSION_CODE_CHARSET_PATTERN = /[^ABCDEFGHJKLMNPQRSTUVWXYZ23456789]/g;
19
+
20
+ /**
21
+ * Regular expression for validating complete session codes.
22
+ * Session codes must be exactly 8 characters from SESSION_CODE_CHARSET.
23
+ */
24
+ export const SESSION_CODE_VALIDATION_PATTERN = /^[ABCDEFGHJKLMNPQRSTUVWXYZ23456789]{8}$/;
@@ -38,11 +38,13 @@ const demoSession = {
38
38
  required: false
39
39
  }]
40
40
  };
41
- const isDemoSession = email => email === 'demo@trustchex.com';
41
+ const isDemoSession = sessionCode => sessionCode.toUpperCase() === 'DEMXCXDE';
42
42
  const getSimulatedDemoData = (dataType, body) => {
43
43
  switch (dataType) {
44
- case 'VERIFICATION_SESSIONS':
45
- return [demoSession];
44
+ case 'GET_SESSION_BY_CODE':
45
+ return {
46
+ id: demoSession.id
47
+ };
46
48
  case 'GET_SESSION':
47
49
  return demoSession;
48
50
  case 'SEND_VERIFICATION_CODE':