@trustchex/react-native-sdk 1.381.0 → 1.464.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/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKModule.kt +2 -8
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +60 -13
- package/android/src/main/java/com/trustchex/reactnativesdk/mlkit/MLKitModule.kt +1 -1
- package/ios/Camera/TrustchexCameraView.swift +10 -13
- package/ios/MLKit/MLKitModule.swift +1 -1
- package/lib/module/Screens/Debug/BarcodeTestScreen.js +308 -0
- package/lib/module/Screens/Debug/MRZTestScreen.js +105 -13
- package/lib/module/Screens/Debug/NFCScanTestScreen.js +635 -0
- package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +49 -32
- package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +22 -4
- package/lib/module/Screens/Dynamic/IdentityDocumentScanningScreen.js +5 -0
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +126 -27
- package/lib/module/Screens/Dynamic/VerbalConsentScreen.js +1079 -0
- package/lib/module/Screens/Dynamic/VideoCallScreen.js +678 -0
- package/lib/module/Screens/Static/OTPVerificationScreen.js +6 -0
- package/lib/module/Screens/Static/QrCodeScanningScreen.js +7 -1
- package/lib/module/Screens/Static/ResultScreen.js +154 -34
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +59 -51
- package/lib/module/Shared/Animations/recording.json +1 -0
- package/lib/module/Shared/Animations/video-call.json +1 -0
- package/lib/module/Shared/Components/DebugNavigationPanel.js +231 -67
- package/lib/module/Shared/Components/EIDScanner.js +213 -112
- package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +5 -3
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +77 -39
- package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +13 -4
- package/lib/module/Shared/Components/NavigationManager.js +39 -19
- package/lib/module/Shared/Contexts/AppContext.js +1 -0
- package/lib/module/Shared/EIDReader/aesSecureMessagingWrapper.js +51 -0
- package/lib/module/Shared/EIDReader/apduLevelPACECapable.js +3 -0
- package/lib/module/Shared/EIDReader/bacKey.js +16 -2
- package/lib/module/Shared/EIDReader/eidReader.js +354 -13
- package/lib/module/Shared/EIDReader/eidService.js +25 -1
- package/lib/module/Shared/EIDReader/nfcManagerCardService.js +4 -7
- package/lib/module/Shared/EIDReader/paceInfo.js +85 -0
- package/lib/module/Shared/EIDReader/paceKeySpec.js +51 -0
- package/lib/module/Shared/EIDReader/protocol/paceAPDUSender.js +100 -0
- package/lib/module/Shared/EIDReader/protocol/paceProtocol.js +655 -0
- package/lib/module/Shared/EIDReader/protocol/paceResult.js +37 -0
- package/lib/module/Shared/EIDReader/secureMessagingWrapper.js +27 -4
- package/lib/module/Shared/EIDReader/smartcards/commandAPDU.js +2 -1
- package/lib/module/Shared/EIDReader/tlv/tlv.helpers.js +1 -1
- package/lib/module/Shared/EIDReader/tlv/tlv.utils.js +6 -3
- package/lib/module/Shared/EIDReader/utils/aesCrypto.utils.js +189 -0
- package/lib/module/Shared/Libs/SignalingClient.js +128 -0
- package/lib/module/Shared/Libs/analytics.utils.js +8 -0
- package/lib/module/Shared/Libs/contains.js +1 -40
- package/lib/module/Shared/Libs/country-display.utils.js +34 -0
- package/lib/module/Shared/Libs/deeplink.utils.js +9 -1
- package/lib/module/Shared/Libs/demo.utils.js +8 -0
- package/lib/module/Shared/Libs/http-client.js +9 -0
- package/lib/module/Shared/Libs/mrz.utils.js +3 -2
- package/lib/module/Shared/Libs/promise.utils.js +16 -2
- package/lib/module/Shared/Libs/status-bar.utils.js +23 -0
- package/lib/module/Shared/Services/DataUploadService.js +294 -0
- package/lib/module/Shared/Services/VideoSessionService.js +156 -0
- package/lib/module/Shared/Services/WebRTCService.js +510 -0
- package/lib/module/Shared/Types/analytics.types.js +4 -0
- package/lib/module/Translation/Resources/en.js +61 -2
- package/lib/module/Translation/Resources/tr.js +61 -2
- package/lib/module/Trustchex.js +64 -20
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Debug/BarcodeTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/BarcodeTestScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts.map +1 -0
- 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/Dynamic/VerbalConsentScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Static/OTPVerificationScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/QrCodeScanningScreen.d.ts.map +1 -1
- 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.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +5 -0
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts +1 -0
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts +18 -0
- package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts +23 -0
- package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts +6 -0
- package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts +9 -0
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/nfcManagerCardService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts +50 -0
- package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts +30 -0
- package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts +17 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts +105 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts +24 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts +15 -0
- package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/smartcards/commandAPDU.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/tlv/tlv.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts +39 -0
- package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/SignalingClient.d.ts +24 -0
- package/lib/typescript/src/Shared/Libs/SignalingClient.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/contains.d.ts +0 -7
- package/lib/typescript/src/Shared/Libs/contains.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts +2 -0
- package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/deeplink.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/promise.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts +9 -0
- package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Services/DataUploadService.d.ts +25 -0
- package/lib/typescript/src/Shared/Services/DataUploadService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Services/VideoSessionService.d.ts +33 -0
- package/lib/typescript/src/Shared/Services/VideoSessionService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Services/WebRTCService.d.ts +58 -0
- package/lib/typescript/src/Shared/Services/WebRTCService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts +4 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Types/identificationInfo.d.ts +13 -1
- package/lib/typescript/src/Shared/Types/identificationInfo.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +60 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +60 -1
- 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 +35 -5
- package/src/Screens/Debug/BarcodeTestScreen.tsx +317 -0
- package/src/Screens/Debug/MRZTestScreen.tsx +107 -13
- package/src/Screens/Debug/NFCScanTestScreen.tsx +692 -0
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +58 -35
- package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +27 -4
- package/src/Screens/Dynamic/IdentityDocumentScanningScreen.tsx +6 -0
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +156 -27
- package/src/Screens/Dynamic/VerbalConsentScreen.tsx +1401 -0
- package/src/Screens/Dynamic/VideoCallScreen.tsx +766 -0
- package/src/Screens/Static/OTPVerificationScreen.tsx +6 -0
- package/src/Screens/Static/QrCodeScanningScreen.tsx +7 -1
- package/src/Screens/Static/ResultScreen.tsx +235 -48
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +67 -72
- package/src/Shared/Animations/recording.json +1 -0
- package/src/Shared/Animations/video-call.json +1 -0
- package/src/Shared/Components/DebugNavigationPanel.tsx +252 -51
- package/src/Shared/Components/EIDScanner.tsx +223 -116
- package/src/Shared/Components/IdentityDocumentCamera.flows.ts +7 -4
- package/src/Shared/Components/IdentityDocumentCamera.tsx +224 -188
- package/src/Shared/Components/IdentityDocumentCamera.utils.ts +13 -4
- package/src/Shared/Components/NavigationManager.tsx +41 -19
- package/src/Shared/Contexts/AppContext.ts +2 -0
- package/src/Shared/EIDReader/aesSecureMessagingWrapper.ts +69 -0
- package/src/Shared/EIDReader/apduLevelPACECapable.ts +34 -0
- package/src/Shared/EIDReader/bacKey.ts +24 -8
- package/src/Shared/EIDReader/eidReader.ts +398 -12
- package/src/Shared/EIDReader/eidService.ts +49 -1
- package/src/Shared/EIDReader/nfcManagerCardService.ts +4 -6
- package/src/Shared/EIDReader/paceInfo.ts +159 -0
- package/src/Shared/EIDReader/paceKeySpec.ts +56 -0
- package/src/Shared/EIDReader/protocol/paceAPDUSender.ts +163 -0
- package/src/Shared/EIDReader/protocol/paceProtocol.ts +946 -0
- package/src/Shared/EIDReader/protocol/paceResult.ts +62 -0
- package/src/Shared/EIDReader/secureMessagingWrapper.ts +28 -10
- package/src/Shared/EIDReader/smartcards/commandAPDU.ts +2 -1
- package/src/Shared/EIDReader/tlv/tlv.helpers.ts +1 -1
- package/src/Shared/EIDReader/tlv/tlv.utils.ts +8 -5
- package/src/Shared/EIDReader/utils/aesCrypto.utils.ts +217 -0
- package/src/Shared/Libs/SignalingClient.ts +189 -0
- package/src/Shared/Libs/analytics.utils.ts +8 -0
- package/src/Shared/Libs/contains.ts +0 -53
- package/src/Shared/Libs/country-display.utils.ts +55 -0
- package/src/Shared/Libs/crypto.utils.ts +2 -2
- package/src/Shared/Libs/deeplink.utils.ts +12 -1
- package/src/Shared/Libs/demo.utils.ts +10 -0
- package/src/Shared/Libs/http-client.ts +19 -1
- package/src/Shared/Libs/mrz.utils.ts +3 -2
- package/src/Shared/Libs/promise.utils.ts +16 -2
- package/src/Shared/Libs/status-bar.utils.ts +21 -0
- package/src/Shared/Services/DataUploadService.ts +395 -0
- package/src/Shared/Services/VideoSessionService.ts +190 -0
- package/src/Shared/Services/WebRTCService.ts +636 -0
- package/src/Shared/Types/analytics.types.ts +4 -0
- package/src/Shared/Types/identificationInfo.ts +16 -1
- package/src/Translation/Resources/en.ts +88 -3
- package/src/Translation/Resources/tr.ts +89 -3
- package/src/Trustchex.tsx +65 -19
- package/src/version.ts +1 -1
|
@@ -11,6 +11,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
11
11
|
import AppContext from "../Contexts/AppContext.js";
|
|
12
12
|
import StyledButton from "./StyledButton.js";
|
|
13
13
|
import LottieView from 'lottie-react-native';
|
|
14
|
+
import { getLocalizedCountryName } from "../Libs/country-display.utils.js";
|
|
14
15
|
import { useKeepAwake } from "../Libs/native-keep-awake.utils.js";
|
|
15
16
|
import { speak, resetLastMessage } from "../Libs/tts.utils.js";
|
|
16
17
|
import { trackEIDScanStart, trackEIDScanComplete, trackEIDScanFailed } from "../Libs/analytics.utils.js";
|
|
@@ -68,12 +69,34 @@ const EIDScanner = ({
|
|
|
68
69
|
const [isScanned, setIsScanned] = React.useState(false);
|
|
69
70
|
const [hasGuideShown, setHasGuideShown] = React.useState(false);
|
|
70
71
|
const {
|
|
71
|
-
t
|
|
72
|
+
t,
|
|
73
|
+
i18n
|
|
72
74
|
} = useTranslation();
|
|
73
75
|
const appContext = React.useContext(AppContext);
|
|
76
|
+
const formatGender = useCallback(code => {
|
|
77
|
+
switch (code?.toUpperCase()) {
|
|
78
|
+
case 'M':
|
|
79
|
+
return t('eidScannerScreen.genderMale', 'Male');
|
|
80
|
+
case 'F':
|
|
81
|
+
return t('eidScannerScreen.genderFemale', 'Female');
|
|
82
|
+
default:
|
|
83
|
+
return t('eidScannerScreen.genderUnspecified', 'Unspecified');
|
|
84
|
+
}
|
|
85
|
+
}, [t]);
|
|
86
|
+
const formatDocumentType = useCallback(code => {
|
|
87
|
+
if (!code) return '';
|
|
88
|
+
const upper = code.toUpperCase();
|
|
89
|
+
if (upper.startsWith('P')) return t('eidScannerScreen.docTypePassport', 'Passport');
|
|
90
|
+
if (upper.startsWith('I')) return t('eidScannerScreen.docTypeID', 'ID Card');
|
|
91
|
+
if (upper.startsWith('A')) return t('eidScannerScreen.docTypeResidence', 'Residence Permit');
|
|
92
|
+
if (upper.startsWith('V')) return t('eidScannerScreen.docTypeVisa', 'Visa');
|
|
93
|
+
return code;
|
|
94
|
+
}, [t]);
|
|
95
|
+
const formatNationality = useCallback(code => {
|
|
96
|
+
return getLocalizedCountryName(code, i18n.language);
|
|
97
|
+
}, [i18n.language]);
|
|
74
98
|
const [voiceGuidanceMessage, setVoiceGuidanceMessage] = useState();
|
|
75
99
|
const [attemptNumber, setAttemptNumber] = useState(0);
|
|
76
|
-
const lastVoiceGuidanceMessage = useRef('');
|
|
77
100
|
const readNFC = useCallback(async () => {
|
|
78
101
|
const startTime = Date.now();
|
|
79
102
|
const currentAttempt = attemptNumber + 1;
|
|
@@ -82,7 +105,6 @@ const EIDScanner = ({
|
|
|
82
105
|
setIsScanned(false);
|
|
83
106
|
setProgress(0);
|
|
84
107
|
setProgressStage('');
|
|
85
|
-
lastVoiceGuidanceMessage.current = '';
|
|
86
108
|
resetLastMessage();
|
|
87
109
|
|
|
88
110
|
// Track EID scan start using analytics helper
|
|
@@ -241,8 +263,7 @@ const EIDScanner = ({
|
|
|
241
263
|
}
|
|
242
264
|
}, [isScanning, progress, pulseAnim]);
|
|
243
265
|
useEffect(() => {
|
|
244
|
-
if (voiceGuidanceMessage && appContext.currentWorkflowStep?.data?.voiceGuidanceActive
|
|
245
|
-
lastVoiceGuidanceMessage.current = voiceGuidanceMessage;
|
|
266
|
+
if (voiceGuidanceMessage && appContext.currentWorkflowStep?.data?.voiceGuidanceActive) {
|
|
246
267
|
speak(voiceGuidanceMessage, true);
|
|
247
268
|
}
|
|
248
269
|
}, [voiceGuidanceMessage, appContext.currentWorkflowStep?.data?.voiceGuidanceActive]);
|
|
@@ -299,101 +320,119 @@ const EIDScanner = ({
|
|
|
299
320
|
children: t('eidScannerScreen.startScanning')
|
|
300
321
|
})]
|
|
301
322
|
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
302
|
-
children: [isScanned &&
|
|
303
|
-
|
|
304
|
-
uri: `data:${documentFaceImageMimeType};base64,${documentFaceImage}`
|
|
305
|
-
},
|
|
306
|
-
style: styles.faceImage
|
|
307
|
-
}), isScanned && documentFaceImage &&
|
|
308
|
-
// TODO Add support for jp2 images
|
|
309
|
-
documentFaceImageMimeType === 'image/jp2' && /*#__PURE__*/_jsx(Text, {
|
|
310
|
-
style: styles.mainText,
|
|
311
|
-
children: t('eidScannerScreen.imageCannotBeShown')
|
|
312
|
-
}), isScanned && !documentFaceImage && /*#__PURE__*/_jsx(Text, {
|
|
313
|
-
style: styles.mainText,
|
|
314
|
-
children: t('eidScannerScreen.faceImageNotFound')
|
|
315
|
-
}), isScanned && documentMRZInfo && /*#__PURE__*/_jsxs(View, {
|
|
316
|
-
style: styles.mrzInfo,
|
|
323
|
+
children: [isScanned && /*#__PURE__*/_jsxs(View, {
|
|
324
|
+
style: styles.resultCard,
|
|
317
325
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
318
|
-
style: styles.
|
|
319
|
-
children: [/*#__PURE__*/
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
style: styles.
|
|
324
|
-
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}), /*#__PURE__*/
|
|
332
|
-
style: styles.
|
|
333
|
-
children:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
345
|
-
style: styles.mrzInfoItem,
|
|
346
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
347
|
-
style: styles.mrzInfoLabel,
|
|
348
|
-
children: [t('eidScannerScreen.documentNumber'), ":"]
|
|
349
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
350
|
-
style: styles.mrzInfoText,
|
|
351
|
-
children: documentMRZInfo.getDocumentNumber()
|
|
352
|
-
})]
|
|
353
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
354
|
-
style: styles.mrzInfoItem,
|
|
355
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
356
|
-
style: styles.mrzInfoLabel,
|
|
357
|
-
children: [t('eidScannerScreen.name'), ":"]
|
|
358
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
359
|
-
style: styles.mrzInfoText,
|
|
360
|
-
children: documentMRZInfo.getSecondaryIdentifier()
|
|
361
|
-
})]
|
|
362
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
363
|
-
style: styles.mrzInfoItem,
|
|
364
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
365
|
-
style: styles.mrzInfoLabel,
|
|
366
|
-
children: [t('eidScannerScreen.surname'), ":"]
|
|
367
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
368
|
-
style: styles.mrzInfoText,
|
|
369
|
-
children: documentMRZInfo.getPrimaryIdentifier()
|
|
326
|
+
style: styles.resultHeader,
|
|
327
|
+
children: [documentFaceImage && (documentFaceImageMimeType === 'image/jpeg' || documentFaceImageMimeType === 'image/png') ? /*#__PURE__*/_jsx(Image, {
|
|
328
|
+
source: {
|
|
329
|
+
uri: `data:${documentFaceImageMimeType};base64,${documentFaceImage}`
|
|
330
|
+
},
|
|
331
|
+
style: styles.faceImage,
|
|
332
|
+
resizeMode: "cover"
|
|
333
|
+
}) : /*#__PURE__*/_jsx(View, {
|
|
334
|
+
style: styles.faceImagePlaceholder,
|
|
335
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
336
|
+
style: styles.faceImagePlaceholderText,
|
|
337
|
+
children: "?"
|
|
338
|
+
})
|
|
339
|
+
}), documentMRZInfo && /*#__PURE__*/_jsxs(View, {
|
|
340
|
+
style: styles.resultHeaderInfo,
|
|
341
|
+
children: [/*#__PURE__*/_jsxs(Text, {
|
|
342
|
+
style: styles.fullName,
|
|
343
|
+
numberOfLines: 2,
|
|
344
|
+
children: [documentMRZInfo.getSecondaryIdentifier(), ' ', documentMRZInfo.getPrimaryIdentifier()]
|
|
345
|
+
}), /*#__PURE__*/_jsxs(Text, {
|
|
346
|
+
style: styles.subInfo,
|
|
347
|
+
children: [formatNationality(documentMRZInfo.getNationality()), " \xB7", ' ', formatDocumentType(documentMRZInfo.getDocumentCode())]
|
|
348
|
+
}), /*#__PURE__*/_jsxs(Text, {
|
|
349
|
+
style: styles.subInfo,
|
|
350
|
+
children: [formatGender(documentMRZInfo.getGender().getStrCode()), " \xB7", ' ', formatDate(documentMRZInfo.getDateOfBirth())]
|
|
351
|
+
})]
|
|
370
352
|
})]
|
|
371
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
372
|
-
style: styles.
|
|
373
|
-
children: [/*#__PURE__*/_jsxs(
|
|
374
|
-
style: styles.
|
|
375
|
-
children: [
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
style: styles.
|
|
384
|
-
children: [
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
style: styles.
|
|
393
|
-
children: [
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
353
|
+
}), documentMRZInfo && /*#__PURE__*/_jsxs(View, {
|
|
354
|
+
style: styles.mrzInfo,
|
|
355
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
356
|
+
style: styles.mrzInfoItem,
|
|
357
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
358
|
+
style: styles.mrzInfoLabel,
|
|
359
|
+
children: t('eidScannerScreen.name')
|
|
360
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
361
|
+
style: styles.mrzInfoText,
|
|
362
|
+
children: documentMRZInfo.getSecondaryIdentifier()
|
|
363
|
+
})]
|
|
364
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
365
|
+
style: styles.mrzInfoItem,
|
|
366
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
367
|
+
style: styles.mrzInfoLabel,
|
|
368
|
+
children: t('eidScannerScreen.surname')
|
|
369
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
370
|
+
style: styles.mrzInfoText,
|
|
371
|
+
children: documentMRZInfo.getPrimaryIdentifier()
|
|
372
|
+
})]
|
|
373
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
374
|
+
style: styles.mrzInfoItem,
|
|
375
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
376
|
+
style: styles.mrzInfoLabel,
|
|
377
|
+
children: t('eidScannerScreen.documentCode')
|
|
378
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
379
|
+
style: styles.mrzInfoText,
|
|
380
|
+
children: formatDocumentType(documentMRZInfo.getDocumentCode())
|
|
381
|
+
})]
|
|
382
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
383
|
+
style: styles.mrzInfoItem,
|
|
384
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
385
|
+
style: styles.mrzInfoLabel,
|
|
386
|
+
children: t('eidScannerScreen.documentNumber')
|
|
387
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
388
|
+
style: styles.mrzInfoText,
|
|
389
|
+
children: documentMRZInfo.getDocumentNumber()
|
|
390
|
+
})]
|
|
391
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
392
|
+
style: styles.mrzInfoItem,
|
|
393
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
394
|
+
style: styles.mrzInfoLabel,
|
|
395
|
+
children: t('eidScannerScreen.personalNumber')
|
|
396
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
397
|
+
style: styles.mrzInfoText,
|
|
398
|
+
children: documentMRZInfo.getOptionalData1()
|
|
399
|
+
})]
|
|
400
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
401
|
+
style: styles.mrzInfoItem,
|
|
402
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
403
|
+
style: styles.mrzInfoLabel,
|
|
404
|
+
children: t('eidScannerScreen.nationality')
|
|
405
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
406
|
+
style: styles.mrzInfoText,
|
|
407
|
+
children: formatNationality(documentMRZInfo.getNationality())
|
|
408
|
+
})]
|
|
409
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
410
|
+
style: styles.mrzInfoItem,
|
|
411
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
412
|
+
style: styles.mrzInfoLabel,
|
|
413
|
+
children: t('eidScannerScreen.gender')
|
|
414
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
415
|
+
style: styles.mrzInfoText,
|
|
416
|
+
children: formatGender(documentMRZInfo.getGender().getStrCode())
|
|
417
|
+
})]
|
|
418
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
419
|
+
style: styles.mrzInfoItem,
|
|
420
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
421
|
+
style: styles.mrzInfoLabel,
|
|
422
|
+
children: t('eidScannerScreen.birthDate')
|
|
423
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
424
|
+
style: styles.mrzInfoText,
|
|
425
|
+
children: formatDate(documentMRZInfo.getDateOfBirth())
|
|
426
|
+
})]
|
|
427
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
428
|
+
style: styles.mrzInfoItem,
|
|
429
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
430
|
+
style: styles.mrzInfoLabel,
|
|
431
|
+
children: t('eidScannerScreen.expirationDate')
|
|
432
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
433
|
+
style: styles.mrzInfoText,
|
|
434
|
+
children: formatDate(documentMRZInfo.getDateOfExpiry())
|
|
435
|
+
})]
|
|
397
436
|
})]
|
|
398
437
|
})]
|
|
399
438
|
}), !hasNfc && /*#__PURE__*/_jsx(Text, {
|
|
@@ -426,7 +465,14 @@ const EIDScanner = ({
|
|
|
426
465
|
}) || documentType === 'UNKNOWN' && /*#__PURE__*/_jsx(Text, {
|
|
427
466
|
style: styles.mainText,
|
|
428
467
|
children: t('eidScannerScreen.placeDocumentOnNFC')
|
|
429
|
-
})), hasNfc && isEnabled && isScanned && /*#__PURE__*/_jsx(View, {
|
|
468
|
+
})), hasNfc && isEnabled && !isScanning && !isScanned && /*#__PURE__*/_jsx(View, {
|
|
469
|
+
style: styles.buttonsContainer,
|
|
470
|
+
children: /*#__PURE__*/_jsx(StyledButton, {
|
|
471
|
+
mode: "contained",
|
|
472
|
+
onPress: readNFC,
|
|
473
|
+
children: t('eidScannerScreen.startScanning')
|
|
474
|
+
})
|
|
475
|
+
}), hasNfc && isEnabled && isScanned && /*#__PURE__*/_jsx(View, {
|
|
430
476
|
style: styles.buttonsContainer,
|
|
431
477
|
children: /*#__PURE__*/_jsx(StyledButton, {
|
|
432
478
|
mode: "contained",
|
|
@@ -511,31 +557,86 @@ const styles = StyleSheet.create({
|
|
|
511
557
|
color: 'black',
|
|
512
558
|
textAlign: 'center'
|
|
513
559
|
},
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
560
|
+
resultCard: {
|
|
561
|
+
backgroundColor: '#fff',
|
|
562
|
+
borderRadius: 16,
|
|
563
|
+
padding: 16,
|
|
564
|
+
gap: 16,
|
|
565
|
+
shadowColor: '#000',
|
|
566
|
+
shadowOffset: {
|
|
567
|
+
width: 0,
|
|
568
|
+
height: 2
|
|
569
|
+
},
|
|
570
|
+
shadowOpacity: 0.08,
|
|
571
|
+
shadowRadius: 8,
|
|
572
|
+
elevation: 3,
|
|
519
573
|
borderWidth: 1,
|
|
520
|
-
|
|
574
|
+
borderColor: '#f0f0f0'
|
|
575
|
+
},
|
|
576
|
+
resultHeader: {
|
|
577
|
+
flexDirection: 'row',
|
|
578
|
+
gap: 14,
|
|
579
|
+
alignItems: 'flex-start'
|
|
580
|
+
},
|
|
581
|
+
resultHeaderInfo: {
|
|
582
|
+
flex: 1,
|
|
583
|
+
gap: 4,
|
|
584
|
+
justifyContent: 'center'
|
|
585
|
+
},
|
|
586
|
+
fullName: {
|
|
587
|
+
fontSize: 17,
|
|
588
|
+
fontWeight: '700',
|
|
589
|
+
color: '#111',
|
|
590
|
+
letterSpacing: 0.2
|
|
591
|
+
},
|
|
592
|
+
subInfo: {
|
|
593
|
+
fontSize: 13,
|
|
594
|
+
color: '#666',
|
|
595
|
+
fontWeight: '500'
|
|
596
|
+
},
|
|
597
|
+
faceImage: {
|
|
598
|
+
width: 90,
|
|
599
|
+
height: 115,
|
|
600
|
+
borderRadius: 10,
|
|
601
|
+
overflow: 'hidden'
|
|
602
|
+
},
|
|
603
|
+
faceImagePlaceholder: {
|
|
604
|
+
width: 90,
|
|
605
|
+
height: 115,
|
|
606
|
+
borderRadius: 10,
|
|
607
|
+
backgroundColor: '#f5f5f5',
|
|
608
|
+
alignItems: 'center',
|
|
609
|
+
justifyContent: 'center'
|
|
610
|
+
},
|
|
611
|
+
faceImagePlaceholderText: {
|
|
612
|
+
fontSize: 32,
|
|
613
|
+
color: '#ccc'
|
|
521
614
|
},
|
|
522
615
|
mrzInfo: {
|
|
523
616
|
flexDirection: 'column',
|
|
524
|
-
width: '100%'
|
|
617
|
+
width: '100%',
|
|
618
|
+
gap: 2
|
|
525
619
|
},
|
|
526
620
|
mrzInfoItem: {
|
|
527
621
|
flexDirection: 'row',
|
|
528
622
|
justifyContent: 'space-between',
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
623
|
+
alignItems: 'center',
|
|
624
|
+
paddingVertical: 8,
|
|
625
|
+
borderBottomColor: '#f0f0f0',
|
|
626
|
+
borderBottomWidth: 1
|
|
532
627
|
},
|
|
533
628
|
mrzInfoLabel: {
|
|
534
|
-
color: '
|
|
535
|
-
|
|
629
|
+
color: '#888',
|
|
630
|
+
fontSize: 13,
|
|
631
|
+
fontWeight: '500'
|
|
536
632
|
},
|
|
537
633
|
mrzInfoText: {
|
|
538
|
-
color: '
|
|
634
|
+
color: '#111',
|
|
635
|
+
fontSize: 13,
|
|
636
|
+
fontWeight: '600',
|
|
637
|
+
textAlign: 'right',
|
|
638
|
+
flexShrink: 1,
|
|
639
|
+
marginLeft: 8
|
|
539
640
|
},
|
|
540
641
|
guide: {
|
|
541
642
|
flex: 1,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* KEY DISTINGUISHING FEATURES:
|
|
9
9
|
* =============================
|
|
10
10
|
* PASSPORT: Has MRZ on FRONT with pattern P<XXX (e.g., P<TUR, P<USA)
|
|
11
|
-
* ID CARD: Has NO MRZ on front; MRZ only on BACK with code
|
|
11
|
+
* ID CARD: Has NO MRZ on front; MRZ only on BACK with code starting with I, A, or C
|
|
12
12
|
*
|
|
13
13
|
* IMPORTANT: Both passports and ID cards have signature sections!
|
|
14
14
|
* Signature presence is NOT a distinguishing feature between document types.
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
import { PASSPORT_MRZ_PATTERN } from "./IdentityDocumentCamera.constants.js";
|
|
34
|
+
import { isIDCardDocumentCode } from "./IdentityDocumentCamera.utils.js";
|
|
35
|
+
|
|
34
36
|
/**
|
|
35
37
|
* After this many retry attempts for ID_FRONT flow, proceed with face detection alone
|
|
36
38
|
* even if signature text OCR fails. This prevents blocking users due to OCR limitations.
|
|
@@ -178,10 +180,10 @@ export function handleIDFrontFlow(faces, text, mrzText, mrzFields, retryCount) {
|
|
|
178
180
|
}
|
|
179
181
|
|
|
180
182
|
// ============================================================================
|
|
181
|
-
// STEP 4: Final MRZ code check (if present, must be
|
|
183
|
+
// STEP 4: Final MRZ code check (if present, must be an ID card code, not P)
|
|
182
184
|
// ============================================================================
|
|
183
185
|
// ID cards should NOT have MRZ on front, but if detected, verify it's not passport
|
|
184
|
-
if (mrzFields?.documentCode && mrzFields.documentCode
|
|
186
|
+
if (mrzFields?.documentCode && !isIDCardDocumentCode(mrzFields.documentCode)) {
|
|
185
187
|
return {
|
|
186
188
|
shouldProceed: false,
|
|
187
189
|
reason: `MRZ shows unexpected document code: ${mrzFields.documentCode}`,
|
|
@@ -94,6 +94,7 @@ const IdentityDocumentCamera = ({
|
|
|
94
94
|
const isHologramDetectionInProgress = useRef(false); // Prevent concurrent hologram detection calls
|
|
95
95
|
const isCompletionCallbackInvoked = useRef(false); // Prevent multiple callback invocations when COMPLETED
|
|
96
96
|
const isStepTransitionInProgress = useRef(false); // Prevent duplicate step transitions from rapid frames
|
|
97
|
+
const isCompletionAnnouncementSpoken = useRef(false); // Prevent duplicate "scan completed" voice guidance
|
|
97
98
|
|
|
98
99
|
const faceDetectionErrorCount = useRef(0);
|
|
99
100
|
const brightnessHistory = useRef([]);
|
|
@@ -101,7 +102,6 @@ const IdentityDocumentCamera = ({
|
|
|
101
102
|
const faceImages = useRef([]);
|
|
102
103
|
const hologramImageCountRef = useRef(0);
|
|
103
104
|
const [hologramImageCount, setHologramImageCount] = useState(0);
|
|
104
|
-
const lastVoiceGuidanceMessage = useRef('');
|
|
105
105
|
const [latestHologramFaceImage, setLatestHologramFaceImage] = useState(undefined);
|
|
106
106
|
const lastFacePosition = useRef(null);
|
|
107
107
|
const [documentPlaneBounds, setDocumentPlaneBounds] = useState(null);
|
|
@@ -135,6 +135,7 @@ const IdentityDocumentCamera = ({
|
|
|
135
135
|
setIsActive(true);
|
|
136
136
|
isCompletionCallbackInvoked.current = false; // Reset callback flag when starting new scan
|
|
137
137
|
isStepTransitionInProgress.current = false;
|
|
138
|
+
isCompletionAnnouncementSpoken.current = false;
|
|
138
139
|
} else {
|
|
139
140
|
setIsActive(false);
|
|
140
141
|
faceImages.current = [];
|
|
@@ -148,9 +149,9 @@ const IdentityDocumentCamera = ({
|
|
|
148
149
|
lastValidMRZFields.current = null;
|
|
149
150
|
validMRZConsecutiveCount.current = 0;
|
|
150
151
|
cachedBarcode.current = null;
|
|
151
|
-
lastVoiceGuidanceMessage.current = '';
|
|
152
152
|
isCompletionCallbackInvoked.current = false;
|
|
153
153
|
isStepTransitionInProgress.current = false;
|
|
154
|
+
isCompletionAnnouncementSpoken.current = false;
|
|
154
155
|
// Clear all captured image states from previous scan
|
|
155
156
|
setCurrentFaceImage(undefined);
|
|
156
157
|
setCurrentHologramImage(undefined);
|
|
@@ -163,9 +164,9 @@ const IdentityDocumentCamera = ({
|
|
|
163
164
|
hologramImageCountRef.current = 0;
|
|
164
165
|
setHologramImageCount(0);
|
|
165
166
|
setLatestHologramFaceImage(undefined);
|
|
166
|
-
lastVoiceGuidanceMessage.current = '';
|
|
167
167
|
isCompletionCallbackInvoked.current = false; // Reset callback flag on unmount
|
|
168
168
|
isStepTransitionInProgress.current = false;
|
|
169
|
+
isCompletionAnnouncementSpoken.current = false;
|
|
169
170
|
// Clear all captured image states on unmount
|
|
170
171
|
setCurrentFaceImage(undefined);
|
|
171
172
|
setCurrentHologramImage(undefined);
|
|
@@ -176,9 +177,17 @@ const IdentityDocumentCamera = ({
|
|
|
176
177
|
useEffect(() => {
|
|
177
178
|
if (!hasGuideShown || !appContext.currentWorkflowStep?.data?.voiceGuidanceActive) return;
|
|
178
179
|
const message = getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, allElementsDetected, elementsOutsideScanArea, t);
|
|
179
|
-
if (message
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
if (message) {
|
|
181
|
+
if (nextStep === 'COMPLETED') {
|
|
182
|
+
if (isCompletionAnnouncementSpoken.current) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
isCompletionAnnouncementSpoken.current = true;
|
|
186
|
+
} else {
|
|
187
|
+
isCompletionAnnouncementSpoken.current = false;
|
|
188
|
+
}
|
|
189
|
+
const shouldBypassInterval = nextStep !== 'COMPLETED';
|
|
190
|
+
speak(message, shouldBypassInterval);
|
|
182
191
|
}
|
|
183
192
|
}, [appContext.currentWorkflowStep?.data?.voiceGuidanceActive, hasGuideShown, isBrightnessLow, isFrameBlurry, nextStep, status, detectedDocumentType, allElementsDetected, elementsOutsideScanArea, t]);
|
|
184
193
|
useEffect(() => {
|
|
@@ -207,6 +216,20 @@ const IdentityDocumentCamera = ({
|
|
|
207
216
|
isStepTransitionInProgress.current = false;
|
|
208
217
|
}, [nextStep]);
|
|
209
218
|
|
|
219
|
+
// Update status bar based on guide visibility
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
if (hasGuideShown) {
|
|
222
|
+
// Scanning camera view - use light icons on dark background
|
|
223
|
+
StatusBar.setBarStyle('light-content', true);
|
|
224
|
+
} else {
|
|
225
|
+
// Guide screen with white background - use dark icons
|
|
226
|
+
StatusBar.setBarStyle('dark-content', true);
|
|
227
|
+
if (Platform.OS === 'android') {
|
|
228
|
+
StatusBar.setBackgroundColor('#ffffff', true);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}, [hasGuideShown]);
|
|
232
|
+
|
|
210
233
|
// Error flash animation - flash red text when wrong side detected
|
|
211
234
|
useEffect(() => {
|
|
212
235
|
if (status === 'INCORRECT') {
|
|
@@ -1462,6 +1485,53 @@ const IdentityDocumentCamera = ({
|
|
|
1462
1485
|
const handleCameraError = useCallback(event => {
|
|
1463
1486
|
console.error('Camera error:', event.nativeEvent.error);
|
|
1464
1487
|
}, []);
|
|
1488
|
+
|
|
1489
|
+
// Show the guide immediately — the guide is pure UI and does not need
|
|
1490
|
+
// camera access. Permission is requested in the background (useEffect) so
|
|
1491
|
+
// it will usually be resolved by the time the user taps "Let's Go".
|
|
1492
|
+
// This avoids a white/blank screen while the async permission check runs.
|
|
1493
|
+
if (!hasGuideShown) {
|
|
1494
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
1495
|
+
style: StyleSheet.absoluteFill,
|
|
1496
|
+
children: [/*#__PURE__*/_jsx(StatusBar, {
|
|
1497
|
+
barStyle: "dark-content",
|
|
1498
|
+
backgroundColor: "#ffffff",
|
|
1499
|
+
translucent: true
|
|
1500
|
+
}), /*#__PURE__*/_jsxs(SafeAreaView, {
|
|
1501
|
+
style: styles.guide,
|
|
1502
|
+
children: [/*#__PURE__*/_jsx(LottieView, {
|
|
1503
|
+
source: require('../../Shared/Animations/id-or-passport.json'),
|
|
1504
|
+
style: styles.guideAnimation,
|
|
1505
|
+
loop: true,
|
|
1506
|
+
autoPlay: true
|
|
1507
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
1508
|
+
style: styles.guideHeader,
|
|
1509
|
+
children: t('identityDocumentCamera.guideHeader')
|
|
1510
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
1511
|
+
style: styles.guidePoints,
|
|
1512
|
+
children: [/*#__PURE__*/_jsx(TextView, {
|
|
1513
|
+
style: styles.guideText,
|
|
1514
|
+
children: t('identityDocumentCamera.guideText')
|
|
1515
|
+
}), /*#__PURE__*/_jsxs(TextView, {
|
|
1516
|
+
style: styles.guideText,
|
|
1517
|
+
children: ["\u2022 ", t('identityDocumentCamera.guidePoint1')]
|
|
1518
|
+
}), /*#__PURE__*/_jsxs(TextView, {
|
|
1519
|
+
style: styles.guideText,
|
|
1520
|
+
children: ["\u2022 ", t('identityDocumentCamera.guidePoint2')]
|
|
1521
|
+
}), /*#__PURE__*/_jsxs(TextView, {
|
|
1522
|
+
style: styles.guideText,
|
|
1523
|
+
children: ["\u2022 ", t('identityDocumentCamera.guidePoint3')]
|
|
1524
|
+
})]
|
|
1525
|
+
}), /*#__PURE__*/_jsx(StyledButton, {
|
|
1526
|
+
mode: "contained",
|
|
1527
|
+
onPress: () => {
|
|
1528
|
+
setHasGuideShown(true);
|
|
1529
|
+
},
|
|
1530
|
+
children: t('general.letsGo')
|
|
1531
|
+
})]
|
|
1532
|
+
})]
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1465
1535
|
if (!permissionsRequested) {
|
|
1466
1536
|
return /*#__PURE__*/_jsxs(SafeAreaView, {
|
|
1467
1537
|
style: styles.permissionContainer,
|
|
@@ -1496,39 +1566,7 @@ const IdentityDocumentCamera = ({
|
|
|
1496
1566
|
barStyle: "light-content",
|
|
1497
1567
|
backgroundColor: "transparent",
|
|
1498
1568
|
translucent: true
|
|
1499
|
-
}),
|
|
1500
|
-
style: styles.guide,
|
|
1501
|
-
children: [/*#__PURE__*/_jsx(LottieView, {
|
|
1502
|
-
source: require('../../Shared/Animations/id-or-passport.json'),
|
|
1503
|
-
style: styles.guideAnimation,
|
|
1504
|
-
loop: true,
|
|
1505
|
-
autoPlay: true
|
|
1506
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
1507
|
-
style: styles.guideHeader,
|
|
1508
|
-
children: t('identityDocumentCamera.guideHeader')
|
|
1509
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
1510
|
-
style: styles.guidePoints,
|
|
1511
|
-
children: [/*#__PURE__*/_jsx(TextView, {
|
|
1512
|
-
style: styles.guideText,
|
|
1513
|
-
children: t('identityDocumentCamera.guideText')
|
|
1514
|
-
}), /*#__PURE__*/_jsxs(TextView, {
|
|
1515
|
-
style: styles.guideText,
|
|
1516
|
-
children: ["\u2022 ", t('identityDocumentCamera.guidePoint1')]
|
|
1517
|
-
}), /*#__PURE__*/_jsxs(TextView, {
|
|
1518
|
-
style: styles.guideText,
|
|
1519
|
-
children: ["\u2022 ", t('identityDocumentCamera.guidePoint2')]
|
|
1520
|
-
}), /*#__PURE__*/_jsxs(TextView, {
|
|
1521
|
-
style: styles.guideText,
|
|
1522
|
-
children: ["\u2022 ", t('identityDocumentCamera.guidePoint3')]
|
|
1523
|
-
})]
|
|
1524
|
-
}), /*#__PURE__*/_jsx(StyledButton, {
|
|
1525
|
-
mode: "contained",
|
|
1526
|
-
onPress: () => {
|
|
1527
|
-
setHasGuideShown(true);
|
|
1528
|
-
},
|
|
1529
|
-
children: t('general.letsGo')
|
|
1530
|
-
})]
|
|
1531
|
-
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
1569
|
+
}), /*#__PURE__*/_jsxs(_Fragment, {
|
|
1532
1570
|
children: [/*#__PURE__*/_jsx(TrustchexCamera, {
|
|
1533
1571
|
ref: cameraRef,
|
|
1534
1572
|
style: StyleSheet.absoluteFill,
|
|
@@ -4,6 +4,15 @@ import { Dimensions } from 'react-native';
|
|
|
4
4
|
import { SIGNATURE_REGEX, PASSPORT_MRZ_PATTERN } from "./IdentityDocumentCamera.constants.js";
|
|
5
5
|
import { debugLog, isDebugEnabled } from "../Libs/debug.utils.js";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Checks if a document code represents an ID card (TD1/TD2).
|
|
9
|
+
* Per ICAO 9303, valid ID card codes start with 'I', 'A', or 'C'.
|
|
10
|
+
*/
|
|
11
|
+
export function isIDCardDocumentCode(code) {
|
|
12
|
+
if (!code) return false;
|
|
13
|
+
return code.startsWith('I') || code.startsWith('A') || code.startsWith('C');
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
/**
|
|
8
17
|
* Frame-to-screen coordinate transform using FILL_CENTER scaling
|
|
9
18
|
*/
|
|
@@ -175,8 +184,8 @@ export function detectDocumentType(faces, ocrText, mrzFields, frameWidth, mrzTex
|
|
|
175
184
|
});
|
|
176
185
|
}
|
|
177
186
|
|
|
178
|
-
// ID Back: no face + ID MRZ
|
|
179
|
-
if (faces.length === 0 && mrzFields?.documentCode
|
|
187
|
+
// ID Back: no face + ID MRZ (codes starting with I, A, or C per ICAO 9303)
|
|
188
|
+
if (faces.length === 0 && isIDCardDocumentCode(mrzFields?.documentCode)) {
|
|
180
189
|
return 'ID_BACK';
|
|
181
190
|
}
|
|
182
191
|
|
|
@@ -205,8 +214,8 @@ export function detectDocumentType(faces, ocrText, mrzFields, frameWidth, mrzTex
|
|
|
205
214
|
// Filter to card-sized faces only (min 5% of frame width to exclude tiny background faces)
|
|
206
215
|
const cardSizedFaces = frameWidth ? faces.filter(face => face.bounds.width >= frameWidth * 0.05 && face.bounds.height >= frameWidth * 0.05) : faces;
|
|
207
216
|
if (cardSizedFaces.length > 0) {
|
|
208
|
-
// If we have MRZ code
|
|
209
|
-
if (mrzFields?.documentCode
|
|
217
|
+
// If we have an ID card MRZ code (I, A, or C), it's definitely an ID card
|
|
218
|
+
if (isIDCardDocumentCode(mrzFields?.documentCode)) {
|
|
210
219
|
return 'ID_FRONT';
|
|
211
220
|
}
|
|
212
221
|
|