@trustchex/react-native-sdk 1.214.0 → 1.245.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 +2 -2
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +2 -2
- package/lib/module/Screens/Static/ResultScreen.js +2 -2
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +148 -99
- package/lib/module/Shared/Components/EIDScanner.js +4 -4
- package/lib/module/Shared/Components/FaceCamera.js +4 -3
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +4 -3
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +2 -2
- package/lib/module/Shared/Components/StyledButton.js +30 -0
- package/lib/module/Shared/Constants/index.js +3 -0
- package/lib/module/Shared/Constants/validation.constants.js +24 -0
- package/lib/module/Shared/Libs/demo.utils.js +5 -3
- package/lib/module/Translation/Resources/en.js +50 -52
- package/lib/module/Translation/Resources/tr.js +48 -53
- package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.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/StyledButton.d.ts +6 -0
- package/lib/typescript/src/Shared/Components/StyledButton.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Constants/index.d.ts +2 -0
- package/lib/typescript/src/Shared/Constants/index.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Constants/validation.constants.d.ts +20 -0
- package/lib/typescript/src/Shared/Constants/validation.constants.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/demo.utils.d.ts +2 -2
- package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +1 -3
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +1 -6
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +3 -3
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +3 -3
- package/src/Screens/Static/ResultScreen.tsx +3 -3
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +179 -123
- package/src/Shared/Components/EIDScanner.tsx +7 -7
- package/src/Shared/Components/FaceCamera.tsx +6 -5
- package/src/Shared/Components/IdentityDocumentCamera.tsx +6 -5
- package/src/Shared/Components/QrCodeScannerCamera.tsx +3 -3
- package/src/Shared/Components/StyledButton.tsx +35 -0
- package/src/Shared/Constants/index.ts +1 -0
- package/src/Shared/Constants/validation.constants.ts +24 -0
- package/src/Shared/Libs/demo.utils.ts +5 -4
- package/src/Translation/Resources/en.ts +51 -54
- package/src/Translation/Resources/tr.ts +50 -55
- package/lib/module/Shared/Components/OTPCodeInput.js +0 -74
- package/lib/typescript/src/Shared/Components/OTPCodeInput.d.ts +0 -10
- package/lib/typescript/src/Shared/Components/OTPCodeInput.d.ts.map +0 -1
- package/src/Shared/Components/OTPCodeInput.tsx +0 -93
|
@@ -20,25 +20,28 @@ import {
|
|
|
20
20
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
21
21
|
import AppContext from '../../Shared/Contexts/AppContext';
|
|
22
22
|
import httpClient, { NotFoundError } from '../../Shared/Libs/http-client';
|
|
23
|
-
import OTPCodeInput from '../../Shared/Components/OTPCodeInput';
|
|
24
23
|
import { useTranslation } from 'react-i18next';
|
|
25
24
|
import LanguageSelector from '../../Shared/Components/LanguageSelector';
|
|
26
25
|
import NavigationManager, {
|
|
27
26
|
type NavigationManagerRef,
|
|
28
27
|
} from '../../Shared/Components/NavigationManager';
|
|
29
28
|
import type { VerificationSession } from '../../Shared/Types/verificationSession';
|
|
30
|
-
import {
|
|
29
|
+
import { TextInput, useTheme } from 'react-native-paper';
|
|
30
|
+
import StyledButton from '../../Shared/Components/StyledButton';
|
|
31
31
|
import LottieView from 'lottie-react-native';
|
|
32
32
|
import {
|
|
33
33
|
getSimulatedDemoData,
|
|
34
34
|
isDemoSession,
|
|
35
35
|
} from '../../Shared/Libs/demo.utils';
|
|
36
36
|
import { useNavigation } from '@react-navigation/native';
|
|
37
|
+
import {
|
|
38
|
+
SESSION_CODE_CHARSET_PATTERN,
|
|
39
|
+
SESSION_CODE_VALIDATION_PATTERN,
|
|
40
|
+
} from '../../Shared/Constants/validation.constants';
|
|
37
41
|
|
|
38
42
|
const VerificationSessionCheckScreen = () => {
|
|
39
|
-
const [
|
|
43
|
+
const [sessionCode, setSessionCode] = useState('');
|
|
40
44
|
const [code, setCode] = useState('');
|
|
41
|
-
const [isEnabled, setIsEnabled] = useState(false);
|
|
42
45
|
const [isCheckingSession, setIsCheckingSession] = useState(false);
|
|
43
46
|
const [isSendAgainEnabled, setIsSendAgainEnabled] = useState(false);
|
|
44
47
|
const [isCodeSent, setIsCodeSent] = useState(false);
|
|
@@ -60,14 +63,8 @@ const VerificationSessionCheckScreen = () => {
|
|
|
60
63
|
}
|
|
61
64
|
}, [appContext.baseUrl]);
|
|
62
65
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
return re.test(value);
|
|
66
|
-
}, []);
|
|
67
|
-
|
|
68
|
-
const validatePhoneNumber = useCallback((value: string) => {
|
|
69
|
-
const re = /^(5(\d{9}))/;
|
|
70
|
-
return re.test(value);
|
|
66
|
+
const validateSessionCode = useCallback((value: string) => {
|
|
67
|
+
return SESSION_CODE_VALIDATION_PATTERN.test(value.toUpperCase());
|
|
71
68
|
}, []);
|
|
72
69
|
|
|
73
70
|
const getSession = useCallback(
|
|
@@ -94,29 +91,20 @@ const VerificationSessionCheckScreen = () => {
|
|
|
94
91
|
[apiUrl, appContext.isDemoSession, t]
|
|
95
92
|
);
|
|
96
93
|
|
|
97
|
-
const
|
|
98
|
-
async (
|
|
94
|
+
const getSessionByCode = useCallback(
|
|
95
|
+
async (inputCode: string) => {
|
|
99
96
|
try {
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
'VERIFICATION_SESSIONS'
|
|
110
|
-
)
|
|
111
|
-
: undefined
|
|
112
|
-
);
|
|
113
|
-
} else if (isPhoneNumber) {
|
|
114
|
-
response = await httpClient.get<VerificationSession[]>(
|
|
115
|
-
`${apiUrl}/verification-sessions?phoneNumber=${value}`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
97
|
+
appContext.isDemoSession = isDemoSession(inputCode);
|
|
98
|
+
const response = await httpClient.get<{ id: string }>(
|
|
99
|
+
`${apiUrl}/verification-sessions?sessionCode=${inputCode.toUpperCase()}`,
|
|
100
|
+
appContext.isDemoSession
|
|
101
|
+
? getSimulatedDemoData<{ id: string } | undefined, void>(
|
|
102
|
+
'GET_SESSION_BY_CODE'
|
|
103
|
+
)
|
|
104
|
+
: undefined
|
|
105
|
+
);
|
|
118
106
|
|
|
119
|
-
if (!response || response.
|
|
107
|
+
if (!response || !response.id) {
|
|
120
108
|
throw new NotFoundError();
|
|
121
109
|
}
|
|
122
110
|
|
|
@@ -130,7 +118,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
130
118
|
}
|
|
131
119
|
}
|
|
132
120
|
},
|
|
133
|
-
[apiUrl, appContext, t
|
|
121
|
+
[apiUrl, appContext, t]
|
|
134
122
|
);
|
|
135
123
|
|
|
136
124
|
const sendVerificationCode = useCallback(
|
|
@@ -194,7 +182,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
194
182
|
[apiUrl, appContext.isDemoSession, t]
|
|
195
183
|
);
|
|
196
184
|
|
|
197
|
-
const
|
|
185
|
+
const sendOTPCode = useCallback(
|
|
198
186
|
async (sessionId: string) => {
|
|
199
187
|
if (!sessionId) {
|
|
200
188
|
return false;
|
|
@@ -237,7 +225,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
237
225
|
}
|
|
238
226
|
|
|
239
227
|
if (session?.sendOTP) {
|
|
240
|
-
return
|
|
228
|
+
return sendOTPCode(session.id);
|
|
241
229
|
} else if (session?.identificationId) {
|
|
242
230
|
appContext.identificationInfo.identificationId =
|
|
243
231
|
session?.identificationId;
|
|
@@ -254,7 +242,7 @@ const VerificationSessionCheckScreen = () => {
|
|
|
254
242
|
appContext,
|
|
255
243
|
appContext.identificationInfo.sessionId,
|
|
256
244
|
getSession,
|
|
257
|
-
|
|
245
|
+
sendOTPCode,
|
|
258
246
|
theme.colors,
|
|
259
247
|
theme.colors.primary,
|
|
260
248
|
theme.colors.secondary,
|
|
@@ -302,107 +290,138 @@ const VerificationSessionCheckScreen = () => {
|
|
|
302
290
|
<Text style={styles.mainText}>
|
|
303
291
|
{t('verificationSessionCheckScreen.mainText')}
|
|
304
292
|
</Text>
|
|
305
|
-
<
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
293
|
+
<View style={styles.inputContainer}>
|
|
294
|
+
<TextInput
|
|
295
|
+
mode="outlined"
|
|
296
|
+
autoCapitalize="characters"
|
|
297
|
+
placeholder=""
|
|
298
|
+
outlineColor={theme.colors.primary}
|
|
299
|
+
activeOutlineColor={theme.colors.primary}
|
|
300
|
+
style={styles.sessionCodeTextInput}
|
|
301
|
+
contentStyle={styles.sessionCodeInputWithText}
|
|
302
|
+
onChangeText={async (text) => {
|
|
303
|
+
const alphanumericText = text
|
|
304
|
+
.toUpperCase()
|
|
305
|
+
.replace(SESSION_CODE_CHARSET_PATTERN, '');
|
|
306
|
+
if (alphanumericText.length <= 8) {
|
|
307
|
+
setSessionCode(alphanumericText);
|
|
308
|
+
if (
|
|
309
|
+
validateSessionCode(alphanumericText) &&
|
|
310
|
+
alphanumericText.length === 8
|
|
311
|
+
) {
|
|
312
|
+
try {
|
|
313
|
+
setIsCheckingSession(true);
|
|
314
|
+
const session =
|
|
315
|
+
await getSessionByCode(alphanumericText);
|
|
316
|
+
if (session?.id) {
|
|
317
|
+
appContext.identificationInfo.sessionId =
|
|
318
|
+
session.id;
|
|
319
|
+
} else {
|
|
320
|
+
setSessionCode('');
|
|
321
|
+
}
|
|
322
|
+
} catch {
|
|
323
|
+
setSessionCode('');
|
|
324
|
+
} finally {
|
|
325
|
+
setTimeout(() => {
|
|
326
|
+
setIsCheckingSession(false);
|
|
327
|
+
}, 1000);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}}
|
|
332
|
+
value={sessionCode.toUpperCase()}
|
|
333
|
+
maxLength={8}
|
|
334
|
+
/>
|
|
335
|
+
{!sessionCode && (
|
|
336
|
+
<Text style={styles.placeholderText}>
|
|
337
|
+
{t('verificationSessionCheckScreen.enterSessionCode')}
|
|
338
|
+
</Text>
|
|
310
339
|
)}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
340
|
+
</View>
|
|
341
|
+
<View style={styles.horizontalLineContainer}>
|
|
342
|
+
<View
|
|
343
|
+
style={[
|
|
344
|
+
styles.horizontalLine,
|
|
345
|
+
{ backgroundColor: theme.colors.primary },
|
|
346
|
+
]}
|
|
347
|
+
/>
|
|
348
|
+
<Text style={styles.mainText}>
|
|
349
|
+
{t('verificationSessionCheckScreen.or')}
|
|
350
|
+
</Text>
|
|
351
|
+
<View
|
|
352
|
+
style={[
|
|
353
|
+
styles.horizontalLine,
|
|
354
|
+
{ backgroundColor: theme.colors.primary },
|
|
355
|
+
]}
|
|
356
|
+
/>
|
|
357
|
+
</View>
|
|
358
|
+
<StyledButton
|
|
321
359
|
mode="contained"
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
try {
|
|
325
|
-
setIsCheckingSession(true);
|
|
326
|
-
const sessions = await getSessions(emailOrPhone);
|
|
327
|
-
if (sessions && sessions.length > 0) {
|
|
328
|
-
appContext.identificationInfo.sessionId =
|
|
329
|
-
sessions[0].id;
|
|
330
|
-
}
|
|
331
|
-
} catch {
|
|
332
|
-
// Do nothing
|
|
333
|
-
} finally {
|
|
334
|
-
setTimeout(() => {
|
|
335
|
-
setIsCheckingSession(false);
|
|
336
|
-
setIsEnabled(false);
|
|
337
|
-
}, 1000);
|
|
338
|
-
}
|
|
360
|
+
onPress={() => {
|
|
361
|
+
navigation.navigate('QrCodeScanningScreen' as never);
|
|
339
362
|
}}
|
|
340
363
|
>
|
|
341
|
-
{t('verificationSessionCheckScreen.
|
|
342
|
-
</
|
|
343
|
-
{!isEnabled && (
|
|
344
|
-
<>
|
|
345
|
-
<View style={styles.horizontalLineContainer}>
|
|
346
|
-
<View style={styles.horizontalLine} />
|
|
347
|
-
<Text style={styles.mainText}>
|
|
348
|
-
{t('verificationSessionCheckScreen.or')}
|
|
349
|
-
</Text>
|
|
350
|
-
<View style={styles.horizontalLine} />
|
|
351
|
-
</View>
|
|
352
|
-
<Button
|
|
353
|
-
mode="contained"
|
|
354
|
-
onPress={() => {
|
|
355
|
-
navigation.navigate('QrCodeScanningScreen' as never);
|
|
356
|
-
}}
|
|
357
|
-
>
|
|
358
|
-
{t('verificationSessionCheckScreen.scanQRCode')}
|
|
359
|
-
</Button>
|
|
360
|
-
</>
|
|
361
|
-
)}
|
|
364
|
+
{t('verificationSessionCheckScreen.scanQRCode')}
|
|
365
|
+
</StyledButton>
|
|
362
366
|
</>
|
|
363
367
|
) : (
|
|
364
368
|
<>
|
|
365
369
|
<Text style={styles.mainText}>
|
|
366
370
|
{t('verificationSessionCheckScreen.codeText')}
|
|
367
371
|
</Text>
|
|
368
|
-
<
|
|
369
|
-
|
|
372
|
+
<TextInput
|
|
373
|
+
mode="outlined"
|
|
374
|
+
autoFocus={true}
|
|
375
|
+
placeholder=""
|
|
376
|
+
outlineColor={theme.colors.primary}
|
|
377
|
+
activeOutlineColor={theme.colors.primary}
|
|
378
|
+
style={styles.otpCodeTextInput}
|
|
379
|
+
contentStyle={styles.otpCodeInputWithText}
|
|
380
|
+
keyboardType="number-pad"
|
|
381
|
+
textContentType="oneTimeCode"
|
|
382
|
+
autoComplete="sms-otp"
|
|
383
|
+
maxLength={6}
|
|
370
384
|
onChangeText={(text) => {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
385
|
+
const numericText = text.replace(/[^0-9]/g, '');
|
|
386
|
+
if (numericText.length <= 6) {
|
|
387
|
+
setCode(numericText);
|
|
388
|
+
if (numericText.length === 6) {
|
|
389
|
+
(async () => {
|
|
390
|
+
setIsCodeGettingVerified(true);
|
|
391
|
+
const verifiedSession = await getVerifiedSession(
|
|
392
|
+
appContext.identificationInfo.sessionId,
|
|
393
|
+
numericText
|
|
394
|
+
);
|
|
395
|
+
if (verifiedSession?.identificationId) {
|
|
396
|
+
appContext.identificationInfo.identificationId =
|
|
397
|
+
verifiedSession?.identificationId;
|
|
398
|
+
setCode('');
|
|
399
|
+
setIsCodeSent(false);
|
|
400
|
+
navigationManagerRef.current?.navigateToNextStep();
|
|
401
|
+
} else {
|
|
402
|
+
appContext.onError?.('Invalid OTP code');
|
|
403
|
+
Alert.alert(
|
|
404
|
+
t('general.error'),
|
|
405
|
+
t('verificationSessionCheckScreen.codeError')
|
|
406
|
+
);
|
|
407
|
+
setCode('');
|
|
408
|
+
setIsCodeGettingVerified(false);
|
|
409
|
+
}
|
|
410
|
+
})();
|
|
411
|
+
}
|
|
394
412
|
}
|
|
395
413
|
}}
|
|
414
|
+
value={code}
|
|
396
415
|
/>
|
|
397
|
-
<
|
|
416
|
+
<StyledButton
|
|
398
417
|
mode="contained"
|
|
399
418
|
disabled={!isSendAgainEnabled}
|
|
400
419
|
onPress={() => {
|
|
401
|
-
|
|
420
|
+
sendOTPCode(appContext.identificationInfo.sessionId);
|
|
402
421
|
}}
|
|
403
422
|
>
|
|
404
423
|
{t('verificationSessionCheckScreen.sendCodeAgain')}
|
|
405
|
-
</
|
|
424
|
+
</StyledButton>
|
|
406
425
|
</>
|
|
407
426
|
)}
|
|
408
427
|
</View>
|
|
@@ -440,17 +459,15 @@ const styles = StyleSheet.create({
|
|
|
440
459
|
justifyContent: 'center',
|
|
441
460
|
},
|
|
442
461
|
horizontalLineContainer: {
|
|
443
|
-
display: 'flex',
|
|
444
462
|
flexDirection: 'row',
|
|
445
463
|
alignItems: 'center',
|
|
446
|
-
justifyContent: '
|
|
464
|
+
justifyContent: 'space-between',
|
|
447
465
|
gap: 10,
|
|
448
|
-
|
|
466
|
+
paddingVertical: 10,
|
|
449
467
|
},
|
|
450
468
|
horizontalLine: {
|
|
451
469
|
flex: 1,
|
|
452
|
-
height:
|
|
453
|
-
backgroundColor: '#aaa',
|
|
470
|
+
height: 2,
|
|
454
471
|
},
|
|
455
472
|
loadingAnimation: {
|
|
456
473
|
width: '100%',
|
|
@@ -519,6 +536,45 @@ const styles = StyleSheet.create({
|
|
|
519
536
|
alignItems: 'center',
|
|
520
537
|
position: 'absolute',
|
|
521
538
|
},
|
|
539
|
+
inputContainer: {
|
|
540
|
+
position: 'relative',
|
|
541
|
+
width: '100%',
|
|
542
|
+
},
|
|
543
|
+
sessionCodeTextInput: {
|
|
544
|
+
backgroundColor: 'white',
|
|
545
|
+
},
|
|
546
|
+
sessionCodeInputWithText: {
|
|
547
|
+
textTransform: 'uppercase',
|
|
548
|
+
fontWeight: '800',
|
|
549
|
+
fontSize: 28,
|
|
550
|
+
textAlign: 'center',
|
|
551
|
+
letterSpacing: 8,
|
|
552
|
+
},
|
|
553
|
+
placeholderText: {
|
|
554
|
+
position: 'absolute',
|
|
555
|
+
top: 0,
|
|
556
|
+
left: 0,
|
|
557
|
+
right: 0,
|
|
558
|
+
height: '100%',
|
|
559
|
+
lineHeight: 56,
|
|
560
|
+
fontSize: 16,
|
|
561
|
+
color: '#666',
|
|
562
|
+
textAlign: 'center',
|
|
563
|
+
pointerEvents: 'none',
|
|
564
|
+
},
|
|
565
|
+
sessionCodeInputPlaceholder: {
|
|
566
|
+
fontSize: 16,
|
|
567
|
+
textAlign: 'center',
|
|
568
|
+
},
|
|
569
|
+
otpCodeTextInput: {
|
|
570
|
+
backgroundColor: 'white',
|
|
571
|
+
},
|
|
572
|
+
otpCodeInputWithText: {
|
|
573
|
+
fontWeight: '800',
|
|
574
|
+
fontSize: 28,
|
|
575
|
+
textAlign: 'center',
|
|
576
|
+
letterSpacing: 8,
|
|
577
|
+
},
|
|
522
578
|
});
|
|
523
579
|
|
|
524
580
|
export default VerificationSessionCheckScreen;
|
|
@@ -7,7 +7,7 @@ import NativeProgressBar from './NativeProgressBar';
|
|
|
7
7
|
import type { FieldRecords } from 'mrz';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
import AppContext from '../Contexts/AppContext';
|
|
10
|
-
import
|
|
10
|
+
import StyledButton from './StyledButton';
|
|
11
11
|
import LottieView from 'lottie-react-native';
|
|
12
12
|
import { useKeepAwake } from '../Libs/native-keep-awake.utils';
|
|
13
13
|
import { speakWithDebounce } from '../Libs/tts.utils';
|
|
@@ -183,7 +183,7 @@ const EIDScanner = ({
|
|
|
183
183
|
{t('eidScannerScreen.guideText')}
|
|
184
184
|
</Text>
|
|
185
185
|
</View>
|
|
186
|
-
<
|
|
186
|
+
<StyledButton
|
|
187
187
|
mode="contained"
|
|
188
188
|
onPress={() => {
|
|
189
189
|
setHasGuideShown(true);
|
|
@@ -191,7 +191,7 @@ const EIDScanner = ({
|
|
|
191
191
|
}}
|
|
192
192
|
>
|
|
193
193
|
{t('eidScannerScreen.startScanning')}
|
|
194
|
-
</
|
|
194
|
+
</StyledButton>
|
|
195
195
|
</View>
|
|
196
196
|
) : (
|
|
197
197
|
<>
|
|
@@ -309,7 +309,7 @@ const EIDScanner = ({
|
|
|
309
309
|
<Text style={styles.mainText}>
|
|
310
310
|
{t('eidScannerScreen.nfcNotEnabled')}
|
|
311
311
|
</Text>
|
|
312
|
-
<
|
|
312
|
+
<StyledButton
|
|
313
313
|
mode="contained"
|
|
314
314
|
onPress={async () => {
|
|
315
315
|
await NFCManager.goToNfcSetting();
|
|
@@ -317,7 +317,7 @@ const EIDScanner = ({
|
|
|
317
317
|
}}
|
|
318
318
|
>
|
|
319
319
|
{t('eidScannerScreen.enableNFC')}
|
|
320
|
-
</
|
|
320
|
+
</StyledButton>
|
|
321
321
|
</View>
|
|
322
322
|
)}
|
|
323
323
|
|
|
@@ -368,7 +368,7 @@ const EIDScanner = ({
|
|
|
368
368
|
|
|
369
369
|
{hasNfc && isEnabled && isScanned && (
|
|
370
370
|
<View style={styles.buttonsContainer}>
|
|
371
|
-
<
|
|
371
|
+
<StyledButton
|
|
372
372
|
mode="contained"
|
|
373
373
|
disabled={!documentFaceImage || !documentMRZInfo}
|
|
374
374
|
onPress={() => {
|
|
@@ -387,7 +387,7 @@ const EIDScanner = ({
|
|
|
387
387
|
}}
|
|
388
388
|
>
|
|
389
389
|
{t('eidScannerScreen.approveAndContinue')}
|
|
390
|
-
</
|
|
390
|
+
</StyledButton>
|
|
391
391
|
</View>
|
|
392
392
|
)}
|
|
393
393
|
</>
|
|
@@ -28,7 +28,8 @@ import { Worklets, useSharedValue } from 'react-native-worklets-core';
|
|
|
28
28
|
import { crop } from '../VisionCameraPlugins/Cropper';
|
|
29
29
|
import { isFrameBright } from '../Libs/camera.utils';
|
|
30
30
|
import { useTranslation } from 'react-i18next';
|
|
31
|
-
import { ActivityIndicator
|
|
31
|
+
import { ActivityIndicator } from 'react-native-paper';
|
|
32
|
+
import StyledButton from './StyledButton';
|
|
32
33
|
|
|
33
34
|
export type FaceCameraProps = {
|
|
34
35
|
onFacesDetected: (
|
|
@@ -174,14 +175,14 @@ const FaceCamera = ({
|
|
|
174
175
|
<Text style={styles.permissionText}>
|
|
175
176
|
{t('general.noCameraPermissionGiven')}
|
|
176
177
|
</Text>
|
|
177
|
-
<
|
|
178
|
+
<StyledButton
|
|
178
179
|
mode="contained"
|
|
179
180
|
onPress={() => {
|
|
180
181
|
Linking.openSettings();
|
|
181
182
|
}}
|
|
182
183
|
>
|
|
183
184
|
{t('general.openSettings')}
|
|
184
|
-
</
|
|
185
|
+
</StyledButton>
|
|
185
186
|
</View>
|
|
186
187
|
);
|
|
187
188
|
}
|
|
@@ -192,14 +193,14 @@ const FaceCamera = ({
|
|
|
192
193
|
<Text style={styles.permissionText}>
|
|
193
194
|
{t('general.noMicrophonePermissionGiven')}
|
|
194
195
|
</Text>
|
|
195
|
-
<
|
|
196
|
+
<StyledButton
|
|
196
197
|
mode="contained"
|
|
197
198
|
onPress={() => {
|
|
198
199
|
Linking.openSettings();
|
|
199
200
|
}}
|
|
200
201
|
>
|
|
201
202
|
{t('general.openSettings')}
|
|
202
|
-
</
|
|
203
|
+
</StyledButton>
|
|
203
204
|
</View>
|
|
204
205
|
);
|
|
205
206
|
}
|
|
@@ -46,7 +46,8 @@ import {
|
|
|
46
46
|
import { getAverageBrightness } from '../Libs/camera.utils';
|
|
47
47
|
import { useTranslation } from 'react-i18next';
|
|
48
48
|
import LottieView from 'lottie-react-native';
|
|
49
|
-
import { ActivityIndicator
|
|
49
|
+
import { ActivityIndicator } from 'react-native-paper';
|
|
50
|
+
import StyledButton from './StyledButton';
|
|
50
51
|
import { type Barcode, scanCodes } from '../VisionCameraPlugins/BarcodeScanner';
|
|
51
52
|
import { speakWithDebounce } from '../Libs/tts.utils';
|
|
52
53
|
import AppContext from '../Contexts/AppContext';
|
|
@@ -981,14 +982,14 @@ const IdentityDocumentCamera = ({
|
|
|
981
982
|
<Text style={styles.permissionText}>
|
|
982
983
|
{t('general.noCameraPermissionGiven')}
|
|
983
984
|
</Text>
|
|
984
|
-
<
|
|
985
|
+
<StyledButton
|
|
985
986
|
mode="contained"
|
|
986
987
|
onPress={() => {
|
|
987
988
|
Linking.openSettings();
|
|
988
989
|
}}
|
|
989
990
|
>
|
|
990
991
|
{t('general.openSettings')}
|
|
991
|
-
</
|
|
992
|
+
</StyledButton>
|
|
992
993
|
</View>
|
|
993
994
|
);
|
|
994
995
|
}
|
|
@@ -1044,14 +1045,14 @@ const IdentityDocumentCamera = ({
|
|
|
1044
1045
|
• {t('identityDocumentCamera.guidePoint3')}
|
|
1045
1046
|
</TextView>
|
|
1046
1047
|
</View>
|
|
1047
|
-
<
|
|
1048
|
+
<StyledButton
|
|
1048
1049
|
mode="contained"
|
|
1049
1050
|
onPress={() => {
|
|
1050
1051
|
setHasGuideShown(true);
|
|
1051
1052
|
}}
|
|
1052
1053
|
>
|
|
1053
1054
|
{t('general.letsGo')}
|
|
1054
|
-
</
|
|
1055
|
+
</StyledButton>
|
|
1055
1056
|
</View>
|
|
1056
1057
|
) : (
|
|
1057
1058
|
<>
|
|
@@ -22,7 +22,7 @@ import { useIsFocused } from '@react-navigation/native';
|
|
|
22
22
|
import { useTranslation } from 'react-i18next';
|
|
23
23
|
import LottieView from 'lottie-react-native';
|
|
24
24
|
import { type Barcode, scanCodes } from '../VisionCameraPlugins/BarcodeScanner';
|
|
25
|
-
import
|
|
25
|
+
import StyledButton from './StyledButton';
|
|
26
26
|
|
|
27
27
|
export interface QrCodeScannerCameraProps {
|
|
28
28
|
onQrCodeScanned: (data: string) => void;
|
|
@@ -175,14 +175,14 @@ const QrCodeScannerCamera = ({ onQrCodeScanned }: QrCodeScannerCameraProps) => {
|
|
|
175
175
|
<Text style={styles.permissionText}>
|
|
176
176
|
{t('general.noCameraPermissionGiven')}
|
|
177
177
|
</Text>
|
|
178
|
-
<
|
|
178
|
+
<StyledButton
|
|
179
179
|
mode="contained"
|
|
180
180
|
onPress={() => {
|
|
181
181
|
Linking.openSettings();
|
|
182
182
|
}}
|
|
183
183
|
>
|
|
184
184
|
{t('general.openSettings')}
|
|
185
|
-
</
|
|
185
|
+
</StyledButton>
|
|
186
186
|
</View>
|
|
187
187
|
);
|
|
188
188
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
import { Button } from 'react-native-paper';
|
|
4
|
+
import type { ButtonProps } from 'react-native-paper';
|
|
5
|
+
|
|
6
|
+
type StyledButtonProps = ButtonProps;
|
|
7
|
+
|
|
8
|
+
const StyledButton: React.FC<StyledButtonProps> = ({
|
|
9
|
+
style,
|
|
10
|
+
labelStyle,
|
|
11
|
+
...props
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<Button
|
|
15
|
+
{...props}
|
|
16
|
+
style={[styles.button, style]}
|
|
17
|
+
labelStyle={[styles.label, labelStyle]}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const styles = StyleSheet.create({
|
|
23
|
+
button: {
|
|
24
|
+
borderRadius: 8,
|
|
25
|
+
height: 56,
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
elevation: 2,
|
|
28
|
+
},
|
|
29
|
+
label: {
|
|
30
|
+
fontWeight: 'bold',
|
|
31
|
+
fontSize: 16,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default StyledButton;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './validation.constants';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation constants used throughout the SDK.
|
|
3
|
+
* These constants ensure consistency between frontend and backend validation.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Character set for session codes.
|
|
8
|
+
* Excludes ambiguous characters (0, 1, I, O) to prevent confusion.
|
|
9
|
+
*/
|
|
10
|
+
export const SESSION_CODE_CHARSET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Regular expression pattern for validating session code characters.
|
|
14
|
+
* Matches only characters from SESSION_CODE_CHARSET.
|
|
15
|
+
*/
|
|
16
|
+
export const SESSION_CODE_CHARSET_PATTERN =
|
|
17
|
+
/[^ABCDEFGHJKLMNPQRSTUVWXYZ23456789]/g;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Regular expression for validating complete session codes.
|
|
21
|
+
* Session codes must be exactly 8 characters from SESSION_CODE_CHARSET.
|
|
22
|
+
*/
|
|
23
|
+
export const SESSION_CODE_VALIDATION_PATTERN =
|
|
24
|
+
/^[ABCDEFGHJKLMNPQRSTUVWXYZ23456789]{8}$/;
|