@trustchex/react-native-sdk 1.409.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.
Files changed (156) hide show
  1. package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKModule.kt +2 -8
  2. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +59 -1
  3. package/ios/Camera/TrustchexCameraView.swift +9 -1
  4. package/lib/module/Screens/Debug/NFCScanTestScreen.js +635 -0
  5. package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +1 -4
  6. package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +17 -4
  7. package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +102 -23
  8. package/lib/module/Screens/Dynamic/VerbalConsentScreen.js +1079 -0
  9. package/lib/module/Screens/Dynamic/VideoCallScreen.js +3 -1
  10. package/lib/module/Screens/Static/ResultScreen.js +128 -22
  11. package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +8 -0
  12. package/lib/module/Shared/Animations/recording.json +1 -0
  13. package/lib/module/Shared/Components/DebugNavigationPanel.js +69 -71
  14. package/lib/module/Shared/Components/EIDScanner.js +212 -108
  15. package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +5 -3
  16. package/lib/module/Shared/Components/IdentityDocumentCamera.js +53 -36
  17. package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +13 -4
  18. package/lib/module/Shared/Components/NavigationManager.js +24 -16
  19. package/lib/module/Shared/EIDReader/aesSecureMessagingWrapper.js +51 -0
  20. package/lib/module/Shared/EIDReader/apduLevelPACECapable.js +3 -0
  21. package/lib/module/Shared/EIDReader/bacKey.js +16 -2
  22. package/lib/module/Shared/EIDReader/eidReader.js +354 -13
  23. package/lib/module/Shared/EIDReader/eidService.js +25 -1
  24. package/lib/module/Shared/EIDReader/nfcManagerCardService.js +4 -7
  25. package/lib/module/Shared/EIDReader/paceInfo.js +85 -0
  26. package/lib/module/Shared/EIDReader/paceKeySpec.js +51 -0
  27. package/lib/module/Shared/EIDReader/protocol/paceAPDUSender.js +100 -0
  28. package/lib/module/Shared/EIDReader/protocol/paceProtocol.js +655 -0
  29. package/lib/module/Shared/EIDReader/protocol/paceResult.js +37 -0
  30. package/lib/module/Shared/EIDReader/secureMessagingWrapper.js +27 -4
  31. package/lib/module/Shared/EIDReader/smartcards/commandAPDU.js +2 -1
  32. package/lib/module/Shared/EIDReader/tlv/tlv.helpers.js +1 -1
  33. package/lib/module/Shared/EIDReader/tlv/tlv.utils.js +6 -3
  34. package/lib/module/Shared/EIDReader/utils/aesCrypto.utils.js +189 -0
  35. package/lib/module/Shared/Libs/analytics.utils.js +4 -0
  36. package/lib/module/Shared/Libs/contains.js +1 -40
  37. package/lib/module/Shared/Libs/country-display.utils.js +34 -0
  38. package/lib/module/Shared/Libs/demo.utils.js +8 -0
  39. package/lib/module/Shared/Libs/mrz.utils.js +3 -2
  40. package/lib/module/Shared/Libs/status-bar.utils.js +4 -2
  41. package/lib/module/Shared/Types/analytics.types.js +2 -0
  42. package/lib/module/Translation/Resources/en.js +41 -2
  43. package/lib/module/Translation/Resources/tr.js +41 -2
  44. package/lib/module/Trustchex.js +54 -20
  45. package/lib/module/version.js +1 -1
  46. package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts +3 -0
  47. package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts.map +1 -0
  48. package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
  49. package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
  50. package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
  51. package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts +3 -0
  52. package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts.map +1 -0
  53. package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts.map +1 -1
  54. package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
  55. package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
  56. package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -1
  57. package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
  58. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  59. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +1 -1
  60. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -1
  61. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +5 -0
  62. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
  63. package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
  64. package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts +18 -0
  65. package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts.map +1 -0
  66. package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts +23 -0
  67. package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts.map +1 -0
  68. package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts +6 -0
  69. package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts.map +1 -1
  70. package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
  71. package/lib/typescript/src/Shared/EIDReader/eidService.d.ts +9 -0
  72. package/lib/typescript/src/Shared/EIDReader/eidService.d.ts.map +1 -1
  73. package/lib/typescript/src/Shared/EIDReader/nfcManagerCardService.d.ts.map +1 -1
  74. package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts +50 -0
  75. package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts.map +1 -0
  76. package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts +30 -0
  77. package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts.map +1 -0
  78. package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts +17 -0
  79. package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts.map +1 -0
  80. package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts +105 -0
  81. package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts.map +1 -0
  82. package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts +24 -0
  83. package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts.map +1 -0
  84. package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts +15 -0
  85. package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts.map +1 -1
  86. package/lib/typescript/src/Shared/EIDReader/smartcards/commandAPDU.d.ts.map +1 -1
  87. package/lib/typescript/src/Shared/EIDReader/tlv/tlv.utils.d.ts.map +1 -1
  88. package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts +39 -0
  89. package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts.map +1 -0
  90. package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -1
  91. package/lib/typescript/src/Shared/Libs/contains.d.ts +0 -7
  92. package/lib/typescript/src/Shared/Libs/contains.d.ts.map +1 -1
  93. package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts +2 -0
  94. package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts.map +1 -0
  95. package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
  96. package/lib/typescript/src/Shared/Libs/http-client.d.ts +1 -1
  97. package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
  98. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
  99. package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts.map +1 -1
  100. package/lib/typescript/src/Shared/Types/analytics.types.d.ts +2 -0
  101. package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -1
  102. package/lib/typescript/src/Shared/Types/identificationInfo.d.ts +10 -1
  103. package/lib/typescript/src/Shared/Types/identificationInfo.d.ts.map +1 -1
  104. package/lib/typescript/src/Translation/Resources/en.d.ts +40 -1
  105. package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
  106. package/lib/typescript/src/Translation/Resources/tr.d.ts +40 -1
  107. package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
  108. package/lib/typescript/src/Trustchex.d.ts.map +1 -1
  109. package/lib/typescript/src/version.d.ts +1 -1
  110. package/package.json +7 -4
  111. package/src/Screens/Debug/NFCScanTestScreen.tsx +692 -0
  112. package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +1 -4
  113. package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +21 -4
  114. package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +124 -23
  115. package/src/Screens/Dynamic/VerbalConsentScreen.tsx +1401 -0
  116. package/src/Screens/Dynamic/VideoCallScreen.tsx +3 -1
  117. package/src/Screens/Static/ResultScreen.tsx +183 -31
  118. package/src/Screens/Static/VerificationSessionCheckScreen.tsx +9 -0
  119. package/src/Shared/Animations/recording.json +1 -0
  120. package/src/Shared/Components/DebugNavigationPanel.tsx +73 -48
  121. package/src/Shared/Components/EIDScanner.tsx +222 -111
  122. package/src/Shared/Components/IdentityDocumentCamera.flows.ts +7 -4
  123. package/src/Shared/Components/IdentityDocumentCamera.tsx +199 -184
  124. package/src/Shared/Components/IdentityDocumentCamera.utils.ts +13 -4
  125. package/src/Shared/Components/NavigationManager.tsx +27 -18
  126. package/src/Shared/EIDReader/aesSecureMessagingWrapper.ts +69 -0
  127. package/src/Shared/EIDReader/apduLevelPACECapable.ts +34 -0
  128. package/src/Shared/EIDReader/bacKey.ts +24 -8
  129. package/src/Shared/EIDReader/eidReader.ts +398 -12
  130. package/src/Shared/EIDReader/eidService.ts +49 -1
  131. package/src/Shared/EIDReader/nfcManagerCardService.ts +4 -6
  132. package/src/Shared/EIDReader/paceInfo.ts +159 -0
  133. package/src/Shared/EIDReader/paceKeySpec.ts +56 -0
  134. package/src/Shared/EIDReader/protocol/paceAPDUSender.ts +163 -0
  135. package/src/Shared/EIDReader/protocol/paceProtocol.ts +946 -0
  136. package/src/Shared/EIDReader/protocol/paceResult.ts +62 -0
  137. package/src/Shared/EIDReader/secureMessagingWrapper.ts +28 -10
  138. package/src/Shared/EIDReader/smartcards/commandAPDU.ts +2 -1
  139. package/src/Shared/EIDReader/tlv/tlv.helpers.ts +1 -1
  140. package/src/Shared/EIDReader/tlv/tlv.utils.ts +8 -5
  141. package/src/Shared/EIDReader/utils/aesCrypto.utils.ts +217 -0
  142. package/src/Shared/Libs/analytics.utils.ts +4 -0
  143. package/src/Shared/Libs/contains.ts +0 -53
  144. package/src/Shared/Libs/country-display.utils.ts +55 -0
  145. package/src/Shared/Libs/crypto.utils.ts +2 -2
  146. package/src/Shared/Libs/demo.utils.ts +10 -0
  147. package/src/Shared/Libs/http-client.ts +12 -4
  148. package/src/Shared/Libs/mrz.utils.ts +3 -2
  149. package/src/Shared/Libs/status-bar.utils.ts +4 -2
  150. package/src/Shared/Services/VideoSessionService.ts +1 -1
  151. package/src/Shared/Types/analytics.types.ts +2 -0
  152. package/src/Shared/Types/identificationInfo.ts +11 -0
  153. package/src/Translation/Resources/en.ts +63 -3
  154. package/src/Translation/Resources/tr.ts +62 -3
  155. package/src/Trustchex.tsx +53 -17
  156. 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,9 +69,32 @@ 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
100
  const readNFC = useCallback(async () => {
@@ -296,101 +320,119 @@ const EIDScanner = ({
296
320
  children: t('eidScannerScreen.startScanning')
297
321
  })]
298
322
  }) : /*#__PURE__*/_jsxs(_Fragment, {
299
- children: [isScanned && documentFaceImage && documentFaceImageMimeType === 'image/jpeg' && /*#__PURE__*/_jsx(Image, {
300
- source: {
301
- uri: `data:${documentFaceImageMimeType};base64,${documentFaceImage}`
302
- },
303
- style: styles.faceImage
304
- }), isScanned && documentFaceImage &&
305
- // TODO Add support for jp2 images
306
- documentFaceImageMimeType === 'image/jp2' && /*#__PURE__*/_jsx(Text, {
307
- style: styles.mainText,
308
- children: t('eidScannerScreen.imageCannotBeShown')
309
- }), isScanned && !documentFaceImage && /*#__PURE__*/_jsx(Text, {
310
- style: styles.mainText,
311
- children: t('eidScannerScreen.faceImageNotFound')
312
- }), isScanned && documentMRZInfo && /*#__PURE__*/_jsxs(View, {
313
- style: styles.mrzInfo,
323
+ children: [isScanned && /*#__PURE__*/_jsxs(View, {
324
+ style: styles.resultCard,
314
325
  children: [/*#__PURE__*/_jsxs(View, {
315
- style: styles.mrzInfoItem,
316
- children: [/*#__PURE__*/_jsxs(Text, {
317
- style: styles.mrzInfoLabel,
318
- children: [t('eidScannerScreen.documentCode'), ":"]
319
- }), /*#__PURE__*/_jsx(Text, {
320
- style: styles.mrzInfoText,
321
- children: documentMRZInfo.getDocumentCode()
322
- })]
323
- }), /*#__PURE__*/_jsxs(View, {
324
- style: styles.mrzInfoItem,
325
- children: [/*#__PURE__*/_jsxs(Text, {
326
- style: styles.mrzInfoLabel,
327
- children: [t('eidScannerScreen.nationality'), ":"]
328
- }), /*#__PURE__*/_jsx(Text, {
329
- style: styles.mrzInfoText,
330
- children: documentMRZInfo.getNationality()
331
- })]
332
- }), /*#__PURE__*/_jsxs(View, {
333
- style: styles.mrzInfoItem,
334
- children: [/*#__PURE__*/_jsxs(Text, {
335
- style: styles.mrzInfoLabel,
336
- children: [t('eidScannerScreen.personalNumber'), ":"]
337
- }), /*#__PURE__*/_jsx(Text, {
338
- style: styles.mrzInfoText,
339
- children: documentMRZInfo.getOptionalData1()
340
- })]
341
- }), /*#__PURE__*/_jsxs(View, {
342
- style: styles.mrzInfoItem,
343
- children: [/*#__PURE__*/_jsxs(Text, {
344
- style: styles.mrzInfoLabel,
345
- children: [t('eidScannerScreen.documentNumber'), ":"]
346
- }), /*#__PURE__*/_jsx(Text, {
347
- style: styles.mrzInfoText,
348
- children: documentMRZInfo.getDocumentNumber()
349
- })]
350
- }), /*#__PURE__*/_jsxs(View, {
351
- style: styles.mrzInfoItem,
352
- children: [/*#__PURE__*/_jsxs(Text, {
353
- style: styles.mrzInfoLabel,
354
- children: [t('eidScannerScreen.name'), ":"]
355
- }), /*#__PURE__*/_jsx(Text, {
356
- style: styles.mrzInfoText,
357
- children: documentMRZInfo.getSecondaryIdentifier()
358
- })]
359
- }), /*#__PURE__*/_jsxs(View, {
360
- style: styles.mrzInfoItem,
361
- children: [/*#__PURE__*/_jsxs(Text, {
362
- style: styles.mrzInfoLabel,
363
- children: [t('eidScannerScreen.surname'), ":"]
364
- }), /*#__PURE__*/_jsx(Text, {
365
- style: styles.mrzInfoText,
366
- 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
+ })]
367
352
  })]
368
- }), /*#__PURE__*/_jsxs(View, {
369
- style: styles.mrzInfoItem,
370
- children: [/*#__PURE__*/_jsxs(Text, {
371
- style: styles.mrzInfoLabel,
372
- children: [t('eidScannerScreen.birthDate'), ":"]
373
- }), /*#__PURE__*/_jsx(Text, {
374
- style: styles.mrzInfoText,
375
- children: formatDate(documentMRZInfo.getDateOfBirth())
376
- })]
377
- }), /*#__PURE__*/_jsxs(View, {
378
- style: styles.mrzInfoItem,
379
- children: [/*#__PURE__*/_jsxs(Text, {
380
- style: styles.mrzInfoLabel,
381
- children: [t('eidScannerScreen.gender'), ":"]
382
- }), /*#__PURE__*/_jsx(Text, {
383
- style: styles.mrzInfoText,
384
- children: documentMRZInfo.getGender().getStrCode()
385
- })]
386
- }), /*#__PURE__*/_jsxs(View, {
387
- style: styles.mrzInfoItem,
388
- children: [/*#__PURE__*/_jsxs(Text, {
389
- style: styles.mrzInfoLabel,
390
- children: [t('eidScannerScreen.expirationDate'), ":"]
391
- }), /*#__PURE__*/_jsx(Text, {
392
- style: styles.mrzInfoText,
393
- children: formatDate(documentMRZInfo.getDateOfExpiry())
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
+ })]
394
436
  })]
395
437
  })]
396
438
  }), !hasNfc && /*#__PURE__*/_jsx(Text, {
@@ -423,7 +465,14 @@ const EIDScanner = ({
423
465
  }) || documentType === 'UNKNOWN' && /*#__PURE__*/_jsx(Text, {
424
466
  style: styles.mainText,
425
467
  children: t('eidScannerScreen.placeDocumentOnNFC')
426
- })), 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, {
427
476
  style: styles.buttonsContainer,
428
477
  children: /*#__PURE__*/_jsx(StyledButton, {
429
478
  mode: "contained",
@@ -508,31 +557,86 @@ const styles = StyleSheet.create({
508
557
  color: 'black',
509
558
  textAlign: 'center'
510
559
  },
511
- faceImage: {
512
- width: 150,
513
- height: 150,
514
- borderRadius: 150,
515
- borderColor: 'lightgray',
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,
516
573
  borderWidth: 1,
517
- alignSelf: 'center'
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'
518
614
  },
519
615
  mrzInfo: {
520
616
  flexDirection: 'column',
521
- width: '100%'
617
+ width: '100%',
618
+ gap: 2
522
619
  },
523
620
  mrzInfoItem: {
524
621
  flexDirection: 'row',
525
622
  justifyContent: 'space-between',
526
- borderBottomColor: 'lightgray',
527
- borderBottomWidth: 1,
528
- paddingVertical: 5
623
+ alignItems: 'center',
624
+ paddingVertical: 8,
625
+ borderBottomColor: '#f0f0f0',
626
+ borderBottomWidth: 1
529
627
  },
530
628
  mrzInfoLabel: {
531
- color: 'black',
532
- fontWeight: 'bold'
629
+ color: '#888',
630
+ fontSize: 13,
631
+ fontWeight: '500'
533
632
  },
534
633
  mrzInfoText: {
535
- color: 'black'
634
+ color: '#111',
635
+ fontSize: 13,
636
+ fontWeight: '600',
637
+ textAlign: 'right',
638
+ flexShrink: 1,
639
+ marginLeft: 8
536
640
  },
537
641
  guide: {
538
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 'I'
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 'I' not 'P')
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 !== 'I') {
186
+ if (mrzFields?.documentCode && !isIDCardDocumentCode(mrzFields.documentCode)) {
185
187
  return {
186
188
  shouldProceed: false,
187
189
  reason: `MRZ shows unexpected document code: ${mrzFields.documentCode}`,
@@ -224,7 +224,9 @@ const IdentityDocumentCamera = ({
224
224
  } else {
225
225
  // Guide screen with white background - use dark icons
226
226
  StatusBar.setBarStyle('dark-content', true);
227
- StatusBar.setBackgroundColor('#ffffff', true);
227
+ if (Platform.OS === 'android') {
228
+ StatusBar.setBackgroundColor('#ffffff', true);
229
+ }
228
230
  }
229
231
  }, [hasGuideShown]);
230
232
 
@@ -1483,6 +1485,53 @@ const IdentityDocumentCamera = ({
1483
1485
  const handleCameraError = useCallback(event => {
1484
1486
  console.error('Camera error:', event.nativeEvent.error);
1485
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
+ }
1486
1535
  if (!permissionsRequested) {
1487
1536
  return /*#__PURE__*/_jsxs(SafeAreaView, {
1488
1537
  style: styles.permissionContainer,
@@ -1514,42 +1563,10 @@ const IdentityDocumentCamera = ({
1514
1563
  return /*#__PURE__*/_jsxs(View, {
1515
1564
  style: StyleSheet.absoluteFill,
1516
1565
  children: [/*#__PURE__*/_jsx(StatusBar, {
1517
- barStyle: hasGuideShown ? 'light-content' : 'dark-content',
1518
- backgroundColor: hasGuideShown ? 'transparent' : '#ffffff',
1566
+ barStyle: "light-content",
1567
+ backgroundColor: "transparent",
1519
1568
  translucent: true
1520
- }), !hasGuideShown ? /*#__PURE__*/_jsxs(SafeAreaView, {
1521
- style: styles.guide,
1522
- children: [/*#__PURE__*/_jsx(LottieView, {
1523
- source: require('../../Shared/Animations/id-or-passport.json'),
1524
- style: styles.guideAnimation,
1525
- loop: true,
1526
- autoPlay: true
1527
- }), /*#__PURE__*/_jsx(TextView, {
1528
- style: styles.guideHeader,
1529
- children: t('identityDocumentCamera.guideHeader')
1530
- }), /*#__PURE__*/_jsxs(View, {
1531
- style: styles.guidePoints,
1532
- children: [/*#__PURE__*/_jsx(TextView, {
1533
- style: styles.guideText,
1534
- children: t('identityDocumentCamera.guideText')
1535
- }), /*#__PURE__*/_jsxs(TextView, {
1536
- style: styles.guideText,
1537
- children: ["\u2022 ", t('identityDocumentCamera.guidePoint1')]
1538
- }), /*#__PURE__*/_jsxs(TextView, {
1539
- style: styles.guideText,
1540
- children: ["\u2022 ", t('identityDocumentCamera.guidePoint2')]
1541
- }), /*#__PURE__*/_jsxs(TextView, {
1542
- style: styles.guideText,
1543
- children: ["\u2022 ", t('identityDocumentCamera.guidePoint3')]
1544
- })]
1545
- }), /*#__PURE__*/_jsx(StyledButton, {
1546
- mode: "contained",
1547
- onPress: () => {
1548
- setHasGuideShown(true);
1549
- },
1550
- children: t('general.letsGo')
1551
- })]
1552
- }) : /*#__PURE__*/_jsxs(_Fragment, {
1569
+ }), /*#__PURE__*/_jsxs(_Fragment, {
1553
1570
  children: [/*#__PURE__*/_jsx(TrustchexCamera, {
1554
1571
  ref: cameraRef,
1555
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 === 'I') {
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 'I', it's definitely an ID card
209
- if (mrzFields?.documentCode === 'I') {
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
 
@@ -10,10 +10,14 @@ import i18n from "../../Translation/index.js";
10
10
  import StyledButton from "./StyledButton.js";
11
11
  import { analyticsService } from "../Services/AnalyticsService.js";
12
12
 
13
- // Simple global navigation lock
13
+ // Navigation lock - use a ref-like pattern so unmounting resets state.
14
+ // The module-level object is shared across all instances but the
15
+ // cleanup effect in the component resets it on unmount.
14
16
  import { jsx as _jsx } from "react/jsx-runtime";
15
- let isNavigating = false;
16
- let lastNavigationTime = 0;
17
+ const navigationLock = {
18
+ isNavigating: false,
19
+ lastNavigationTime: 0
20
+ };
17
21
  const NavigationManager = /*#__PURE__*/forwardRef(({
18
22
  canSkipStep
19
23
  }, ref) => {
@@ -30,18 +34,19 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
30
34
  IDENTITY_DOCUMENT_SCAN: 'IdentityDocumentScanningScreen',
31
35
  IDENTITY_DOCUMENT_EID_SCAN: 'IdentityDocumentEIDScanningScreen',
32
36
  LIVENESS_CHECK: 'LivenessDetectionScreen',
37
+ VERBAL_CONSENT: 'VerbalConsentScreen',
33
38
  VIDEO_CALL: 'VideoCallScreen'
34
39
  },
35
40
  RESULT: 'ResultScreen'
36
41
  };
37
42
  React.useEffect(() => {
38
43
  const handleFocus = () => {
39
- isNavigating = false;
44
+ navigationLock.isNavigating = false;
40
45
  };
41
46
  navigation.addListener('focus', handleFocus);
42
47
  return () => {
43
48
  navigation.removeListener('focus', handleFocus);
44
- isNavigating = false;
49
+ navigationLock.isNavigating = false;
45
50
  };
46
51
  }, [navigation]);
47
52
  const getNextRoute = useCallback((workflowSteps, currentWorkFlowStep) => {
@@ -73,16 +78,19 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
73
78
  if (nextStep.type === 'VIDEO_CALL') {
74
79
  return routes.DYNAMIC_ROUTES.VIDEO_CALL;
75
80
  }
81
+ if (nextStep.type === 'VERBAL_CONSENT') {
82
+ return routes.DYNAMIC_ROUTES.VERBAL_CONSENT;
83
+ }
76
84
  return routes.VERIFICATION_SESSION_CHECK;
77
- }, [appContext, routes.VERIFICATION_SESSION_CHECK, routes.DYNAMIC_ROUTES.CONTRACT_ACCEPTANCE, routes.DYNAMIC_ROUTES.IDENTITY_DOCUMENT_EID_SCAN, routes.DYNAMIC_ROUTES.IDENTITY_DOCUMENT_SCAN, routes.DYNAMIC_ROUTES.LIVENESS_CHECK, routes.RESULT]);
85
+ }, [appContext, routes.VERIFICATION_SESSION_CHECK, routes.RESULT, routes.DYNAMIC_ROUTES.CONTRACT_ACCEPTANCE, routes.DYNAMIC_ROUTES.IDENTITY_DOCUMENT_SCAN, routes.DYNAMIC_ROUTES.IDENTITY_DOCUMENT_EID_SCAN, routes.DYNAMIC_ROUTES.LIVENESS_CHECK, routes.DYNAMIC_ROUTES.VIDEO_CALL, routes.DYNAMIC_ROUTES.VERBAL_CONSENT]);
78
86
  const goToNextRoute = useCallback(() => {
79
87
  const currentTime = Date.now();
80
88
  const minTimeBetweenNavigation = 1000;
81
- if (isNavigating || currentTime - lastNavigationTime < minTimeBetweenNavigation) {
89
+ if (navigationLock.isNavigating || currentTime - navigationLock.lastNavigationTime < minTimeBetweenNavigation) {
82
90
  return;
83
91
  }
84
- isNavigating = true;
85
- lastNavigationTime = currentTime;
92
+ navigationLock.isNavigating = true;
93
+ navigationLock.lastNavigationTime = currentTime;
86
94
  try {
87
95
  const nextRoute = getNextRoute(appContext.workflowSteps, appContext.currentWorkflowStep);
88
96
  navigation.dispatch(CommonActions.navigate({
@@ -92,15 +100,15 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
92
100
  }
93
101
  }));
94
102
  } catch (error) {
95
- isNavigating = false;
103
+ navigationLock.isNavigating = false;
96
104
  throw error;
97
105
  }
98
106
  setTimeout(() => {
99
- isNavigating = false;
107
+ navigationLock.isNavigating = false;
100
108
  }, 1000);
101
109
  }, [getNextRoute, appContext.workflowSteps, appContext.currentWorkflowStep, navigation]);
102
110
  const goToNextRouteWithAlert = useCallback(() => {
103
- if (isNavigating) {
111
+ if (navigationLock.isNavigating) {
104
112
  return;
105
113
  }
106
114
  Alert.alert(t('general.warning'), t('navigationManager.skipStepWarning'), [{
@@ -112,10 +120,10 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
112
120
  }]);
113
121
  }, [goToNextRoute, t]);
114
122
  const reset = useCallback(() => {
115
- if (isNavigating) {
123
+ if (navigationLock.isNavigating) {
116
124
  return;
117
125
  }
118
- isNavigating = true;
126
+ navigationLock.isNavigating = true;
119
127
  try {
120
128
  // Preserve demo session state when resetting
121
129
  const wasDemoSession = appContext.isDemoSession;
@@ -157,11 +165,11 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
157
165
  }]
158
166
  }));
159
167
  } catch (error) {
160
- isNavigating = false;
168
+ navigationLock.isNavigating = false;
161
169
  throw error;
162
170
  }
163
171
  setTimeout(() => {
164
- isNavigating = false;
172
+ navigationLock.isNavigating = false;
165
173
  }, 1000);
166
174
  }, [appContext, navigation, routes.VERIFICATION_SESSION_CHECK]);
167
175
  usePreventRemove(true, ({