@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.
- 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 +4 -9
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +150 -106
- 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/ResultScreen.d.ts.map +1 -1
- 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 +14 -12
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +184 -131
- 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
|
@@ -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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
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(
|
|
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 {
|
|
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 [
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
48
|
+
const getSessionByCode = useCallback(async inputCode => {
|
|
59
49
|
try {
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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__*/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
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(
|
|
236
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
|
|
261
|
+
},
|
|
262
|
+
value: code
|
|
263
|
+
}), /*#__PURE__*/_jsx(StyledButton, {
|
|
257
264
|
mode: "contained",
|
|
258
265
|
disabled: !isSendAgainEnabled,
|
|
259
266
|
onPress: () => {
|
|
260
|
-
|
|
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: '
|
|
310
|
+
justifyContent: 'space-between',
|
|
305
311
|
gap: 10,
|
|
306
|
-
|
|
312
|
+
paddingVertical: 10
|
|
307
313
|
},
|
|
308
314
|
horizontalLine: {
|
|
309
315
|
flex: 1,
|
|
310
|
-
height:
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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,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 =
|
|
41
|
+
const isDemoSession = sessionCode => sessionCode.toUpperCase() === 'DEMXCXDE';
|
|
42
42
|
const getSimulatedDemoData = (dataType, body) => {
|
|
43
43
|
switch (dataType) {
|
|
44
|
-
case '
|
|
45
|
-
return
|
|
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':
|