@trustchex/react-native-sdk 1.495.11 → 1.496.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 (38) hide show
  1. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +4 -1
  2. package/android/src/main/java/com/trustchex/reactnativesdk/mlkit/MLKitModule.kt +5 -1
  3. package/ios/Camera/TrustchexCameraView.swift +3 -0
  4. package/ios/MLKit/MLKitModule.swift +1 -1
  5. package/lib/module/Shared/Components/EIDScanner.js +35 -4
  6. package/lib/module/Shared/Components/IdentityDocumentCamera.constants.js +9 -0
  7. package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +38 -3
  8. package/lib/module/Shared/Components/IdentityDocumentCamera.js +56 -18
  9. package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +20 -5
  10. package/lib/module/Shared/EIDReader/eidReader.js +11 -1
  11. package/lib/module/Translation/Resources/en.js +3 -0
  12. package/lib/module/Translation/Resources/tr.js +3 -0
  13. package/lib/module/version.js +1 -1
  14. package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
  15. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.constants.d.ts +1 -0
  16. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.constants.d.ts.map +1 -1
  17. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  18. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +1 -1
  19. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -1
  20. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +1 -1
  21. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
  22. package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
  23. package/lib/typescript/src/Translation/Resources/en.d.ts +3 -0
  24. package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
  25. package/lib/typescript/src/Translation/Resources/tr.d.ts +3 -0
  26. package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
  27. package/lib/typescript/src/version.d.ts +1 -1
  28. package/lib/typescript/src/version.d.ts.map +1 -1
  29. package/package.json +1 -1
  30. package/src/Shared/Components/EIDScanner.tsx +49 -2
  31. package/src/Shared/Components/IdentityDocumentCamera.constants.ts +9 -0
  32. package/src/Shared/Components/IdentityDocumentCamera.flows.ts +49 -3
  33. package/src/Shared/Components/IdentityDocumentCamera.tsx +64 -26
  34. package/src/Shared/Components/IdentityDocumentCamera.utils.ts +21 -3
  35. package/src/Shared/EIDReader/eidReader.ts +11 -1
  36. package/src/Translation/Resources/en.ts +5 -0
  37. package/src/Translation/Resources/tr.ts +5 -0
  38. package/src/version.ts +1 -1
@@ -106,9 +106,12 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
106
106
  private val barcodeScanner by lazy {
107
107
  BarcodeScanning.getClient(
108
108
  BarcodeScannerOptions.Builder()
109
+ // CODE_128 (Turkish e-ID), QR, and PDF417 (US/EU driver-licenses
110
+ // and many national IDs carry the back-side data as PDF417).
109
111
  .setBarcodeFormats(
110
112
  Barcode.FORMAT_CODE_128,
111
- Barcode.FORMAT_QR_CODE
113
+ Barcode.FORMAT_QR_CODE,
114
+ Barcode.FORMAT_PDF417
112
115
  )
113
116
  .build()
114
117
  )
@@ -30,7 +30,11 @@ class MLKitModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaM
30
30
  )
31
31
  private val barcodeScanner = BarcodeScanning.getClient(
32
32
  BarcodeScannerOptions.Builder()
33
- .setBarcodeFormats(Barcode.FORMAT_CODE_128, Barcode.FORMAT_QR_CODE)
33
+ .setBarcodeFormats(
34
+ Barcode.FORMAT_CODE_128,
35
+ Barcode.FORMAT_QR_CODE,
36
+ Barcode.FORMAT_PDF417
37
+ )
34
38
  .build()
35
39
  )
36
40
 
@@ -220,6 +220,9 @@ class TrustchexCameraView: UIView {
220
220
 
221
221
  if supportedTypes.contains(.code128) { typesToEnable.append(.code128) }
222
222
  if supportedTypes.contains(.qr) { typesToEnable.append(.qr) }
223
+ // PDF417: US/EU driver-licenses and many national IDs carry the
224
+ // back-side data as PDF417 (already mapped to BarcodeFormat below).
225
+ if supportedTypes.contains(.pdf417) { typesToEnable.append(.pdf417) }
223
226
 
224
227
  metadataOutput.metadataObjectTypes = typesToEnable
225
228
  }
@@ -19,7 +19,7 @@ class MLKitModule: NSObject {
19
19
  return FaceDetector.faceDetector(options: options)
20
20
  }()
21
21
  private lazy var barcodeScanner: BarcodeScanner = {
22
- let formats: BarcodeFormat = [.code128, .qrCode]
22
+ let formats: BarcodeFormat = [.code128, .qrCode, .PDF417]
23
23
  let options = BarcodeScannerOptions(formats: formats)
24
24
  return BarcodeScanner.barcodeScanner(options: options)
25
25
  }()
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import React, { useState, useEffect, useCallback, useRef } from 'react';
4
- import { Alert, View, Text, Image, StyleSheet, Animated } from 'react-native';
4
+ import { Alert, View, Text, Image, StyleSheet, Animated, Vibration } from 'react-native';
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
6
  import NFCManager from 'react-native-nfc-manager';
7
7
  import DeviceInfo from 'react-native-device-info';
@@ -186,15 +186,27 @@ const EIDScanner = ({
186
186
  // "reading document" spinner never clears and the user is stuck with no
187
187
  // error. Cap the whole read; on timeout we throw a categorized error so
188
188
  // the catch below surfaces a retry prompt and finally resets the UI.
189
+ // Fire a "chip detected" haptic exactly once, the moment progress first
190
+ // moves off 0 (the chip connected and the read began). Confirms contact
191
+ // to a user who can't see the screen while holding the phone to the doc.
192
+ let chipDetectedHapticFired = false;
189
193
  const readPromise = eidReader(documentNumber, dateOfBirth, dateOfExpiry, progressValue => {
194
+ if (progressValue > 0 && !chipDetectedHapticFired) {
195
+ chipDetectedHapticFired = true;
196
+ Vibration.vibrate(40);
197
+ }
190
198
  setProgress(progressValue);
191
199
  // Update stage message based on progress
192
200
  if (progressValue <= 20) {
193
201
  setProgressStage(t('eidScannerScreen.connecting'));
194
202
  } else if (progressValue <= 30) {
195
203
  setProgressStage(t('eidScannerScreen.readingMRZ'));
196
- } else if (progressValue < 100) {
204
+ } else if (progressValue < 95) {
197
205
  setProgressStage(t('eidScannerScreen.readingFaceImage'));
206
+ } else if (progressValue < 100) {
207
+ // 95→100 is the (possibly slow) photo decode — give it its own
208
+ // stage so the bar doesn't look frozen at "Finalizing".
209
+ setProgressStage(t('eidScannerScreen.decodingFaceImage'));
198
210
  } else {
199
211
  setProgressStage(t('eidScannerScreen.completing'));
200
212
  }
@@ -217,6 +229,11 @@ const EIDScanner = ({
217
229
  }
218
230
  }
219
231
  if (passportData) {
232
+ // Success haptic: the phone is pressed against the document, so the
233
+ // user often can't see the screen — a buzz confirms the chip read
234
+ // finished. (The NFC step previously had no haptics at all, unlike the
235
+ // camera/liveness screens.)
236
+ Vibration.vibrate(120);
220
237
  const scanDuration = Date.now() - startTime;
221
238
  const documentData = normalizeFromMRZInfo(passportData.mrz);
222
239
  const builtName = buildDocumentName(documentData.firstName, documentData.lastName, documentData.issuingCountry, passportData.dg11FirstName, passportData.dg11LastName);
@@ -299,7 +316,11 @@ const EIDScanner = ({
299
316
  auth_failed: 'eidScannerScreen.nfcAuthFailed',
300
317
  tag_lost: 'eidScannerScreen.nfcTagLost',
301
318
  timeout: 'eidScannerScreen.nfcTimeout',
302
- not_enabled: 'eidScannerScreen.nfcNotEnabled'
319
+ not_enabled: 'eidScannerScreen.nfcNotEnabled',
320
+ // The default/most-common "chip just wouldn't read" bucket. Show the
321
+ // actionable hold-flat-and-retry guidance rather than the generic
322
+ // "contact support" message — re-placing the phone usually fixes it.
323
+ reading_error: 'eidScannerScreen.nfcReadFailed'
303
324
  };
304
325
  if (category !== 'user_cancelled') {
305
326
  const actionableKey = ACTIONABLE[category];
@@ -569,7 +590,10 @@ const EIDScanner = ({
569
590
  }) || documentType === 'UNKNOWN' && /*#__PURE__*/_jsx(Text, {
570
591
  style: styles.mainText,
571
592
  children: t('eidScannerScreen.placeDocumentOnNFC')
572
- })), hasNfc && isEnabled && !isScanning && !isScanned && /*#__PURE__*/_jsx(View, {
593
+ })), hasNfc && isEnabled && isScanning && progress === 0 && /*#__PURE__*/_jsx(Text, {
594
+ style: styles.keepStillHint,
595
+ children: t('eidScannerScreen.keepStill')
596
+ }), hasNfc && isEnabled && !isScanning && !isScanned && /*#__PURE__*/_jsx(View, {
573
597
  style: styles.buttonsContainer,
574
598
  children: /*#__PURE__*/_jsx(StyledButton, {
575
599
  mode: "contained",
@@ -661,6 +685,13 @@ const styles = StyleSheet.create({
661
685
  color: 'black',
662
686
  textAlign: 'center'
663
687
  },
688
+ keepStillHint: {
689
+ fontSize: 15,
690
+ color: '#666',
691
+ textAlign: 'center',
692
+ marginTop: 12,
693
+ paddingHorizontal: 24
694
+ },
664
695
  // ── ID Card result layout ──────────────────────────────────────────────
665
696
  idCardWrapper: {
666
697
  gap: 10
@@ -17,6 +17,15 @@ export const REQUIRED_CONSISTENT_DOCTYPE_DETECTIONS = 3;
17
17
  export const SIGNATURE_REGEX = /s[gi]g?n[au]?t[u]?r|imz[a]s?/i;
18
18
  export const SIGNATURE_TEXT_REGEX = /signature|imza|İmza/i;
19
19
  export const MRZ_BLOCK_PATTERN = /[A-Z0-9<]{8,}.*</i;
20
+ // A DENSE MRZ run — a contiguous block of MRZ characters that contains a chevron
21
+ // FILLER pair (`<<`). Real machine-readable zones are padded with `<<…`; a card
22
+ // FACE (ID front) has no MRZ, and the occasional stray single `<` OCR'd from a
23
+ // guilloche/chevron glyph will NOT contain a `<<` filler run. Used to decide
24
+ // "is a real MRZ visible on this front?" without the false positives of
25
+ // MRZ_BLOCK_PATTERN (whose `.*<` lets a lone detached `<` anywhere in the frame
26
+ // match) — that looseness could otherwise wedge a legitimate ID front that
27
+ // happens to OCR a stray `<`.
28
+ export const MRZ_DENSE_PATTERN = /[A-Z0-9<]{6,}<<[A-Z0-9<]*/i;
20
29
  // Matches the line-1 start of ANY ICAO TD3 passport MRZ, so the camera routes
21
30
  // every passport variant into the passport flow (not the ID-card back-side
22
31
  // flow). Per ICAO 9303 Part 4: `P` + a type char (filler `<` or a subtype
@@ -30,7 +30,7 @@
30
30
  * - No face, has MRZ with code 'I'
31
31
  */
32
32
 
33
- import { PASSPORT_MRZ_PATTERN } from "./IdentityDocumentCamera.constants.js";
33
+ import { PASSPORT_MRZ_PATTERN, MRZ_DENSE_PATTERN } from "./IdentityDocumentCamera.constants.js";
34
34
  import { isIDCardDocumentCode, isPassportDocumentCode, documentHasBackSide } from "./IdentityDocumentCamera.utils.js";
35
35
 
36
36
  /**
@@ -142,8 +142,15 @@ export function handleIDFrontFlow(faces, text, mrzText, mrzFields, retryCount) {
142
142
  nextAction: 'REJECT_AS_PASSPORT'
143
143
  };
144
144
  }
145
- if (mrzText && PASSPORT_MRZ_PATTERN.test(mrzText)) {
146
- // Passport MRZ pattern visible even if not fully parsed
145
+
146
+ // Passport MRZ pattern visible even if not fully parsed. Check BOTH the
147
+ // parsed `mrzText` (null until the MRZ validates) AND the raw OCR `text` — a
148
+ // passport's MRZ is dense and frequently OCRs a few frames after its face +
149
+ // signature, so on the accepting frame `mrzText` is often still null while the
150
+ // raw `P<XXX...` run is already visible. Testing only `mrzText` (the old bug)
151
+ // let such a passport pass as an ID front and get routed to a back side that
152
+ // does not exist.
153
+ if (mrzText && PASSPORT_MRZ_PATTERN.test(mrzText) || PASSPORT_MRZ_PATTERN.test(text)) {
147
154
  return {
148
155
  shouldProceed: false,
149
156
  reason: 'Passport MRZ pattern visible - not an ID card',
@@ -163,6 +170,34 @@ export function handleIDFrontFlow(faces, text, mrzText, mrzFields, retryCount) {
163
170
  };
164
171
  }
165
172
 
173
+ // ============================================================================
174
+ // STEP 2b: An ID-card FRONT has NO MRZ (the MRZ is on the back). So if a real
175
+ // MRZ is currently visible on this "front", it is almost certainly a passport
176
+ // data page whose 'P' code we just haven't parsed yet — do NOT accept it as an
177
+ // ID front; wait for the MRZ to resolve (→ a 'P' code routes it to the
178
+ // passport flow). This is the guard that stops a passport (face + signature +
179
+ // not-yet-parsed MRZ) being accepted as ID_FRONT and then getting stuck at
180
+ // SCAN_ID_BACK, which rejects the passport's photo page because it has a face.
181
+ //
182
+ // We use MRZ_DENSE_PATTERN (requires a `<<` filler run), NOT the loose
183
+ // MRZ_BLOCK_PATTERN — a card face has no MRZ, but a stray single `<` OCR'd
184
+ // from a guilloche could match the loose pattern and wedge a real ID front.
185
+ // We ALSO honor the signature retry threshold: a real ID front genuinely has
186
+ // no MRZ, so if a "dense MRZ" keeps matching frame after frame past the
187
+ // threshold it is OCR noise, not a passport — fall through and let STEP 3's
188
+ // face-only acceptance proceed rather than waiting forever.
189
+ const mrzVisibleOnFront = !!mrzText || MRZ_DENSE_PATTERN.test(text);
190
+ const stillWaitingForMrz = retryCount <= SIGNATURE_RETRY_THRESHOLD;
191
+ if (mrzVisibleOnFront && stillWaitingForMrz && !isIDCardDocumentCode(mrzFields?.documentCode)) {
192
+ // An ID-card MRZ code (I/A/C) is allowed to proceed (handled in STEP 4); any
193
+ // other visible MRZ → keep waiting for it to parse and reveal a 'P' code.
194
+ return {
195
+ shouldProceed: false,
196
+ reason: 'MRZ block visible on front - waiting to confirm it is not a passport',
197
+ nextAction: 'WAIT_FOR_MRZ'
198
+ };
199
+ }
200
+
166
201
  // ============================================================================
167
202
  // STEP 3: Check for signature (optional front side confirmation)
168
203
  // ============================================================================
@@ -23,7 +23,7 @@ import { useTheme } from "../Contexts/ThemeContext.js";
23
23
  import DebugOverlay, { TestModePanel } from "./DebugOverlay.js";
24
24
  import { getStatusMessage, getFrameToScreenTransform, transformBoundsToScreen, getScanAreaBounds, angleBetweenPoints, detectDocumentType, determineDocumentTypeToSet, areMRZFieldsEqual, hasRequiredMRZFields, validateFacePosition, isPassportDocumentCode } from "./IdentityDocumentCamera.utils.js";
25
25
  import { handlePassportFlow, handleIDFrontFlow, handleIDBackFlow, getNextStepAfterHologram } from "./IdentityDocumentCamera.flows.js";
26
- import { HOLOGRAM_IMAGE_COUNT, HOLOGRAM_DETECTION_THRESHOLD, HOLOGRAM_DETECTION_RETRY_COUNT, HOLOGRAM_CAPTURE_INTERVAL, HOLOGRAM_MAX_FRAMES_WITHOUT_FACE, MIN_BRIGHTNESS_THRESHOLD, MAX_BRIGHTNESS_THRESHOLD, FACE_EDGE_MARGIN_PERCENT, MAX_CONSECUTIVE_QUALITY_FAILURES, REQUIRED_CONSISTENT_DOCTYPE_DETECTIONS, SIGNATURE_TEXT_REGEX, MRZ_BLOCK_PATTERN, PASSPORT_MRZ_PATTERN, MIN_CARD_FACE_SIZE_PERCENT } from "./IdentityDocumentCamera.constants.js";
26
+ import { HOLOGRAM_IMAGE_COUNT, HOLOGRAM_DETECTION_THRESHOLD, HOLOGRAM_DETECTION_RETRY_COUNT, HOLOGRAM_CAPTURE_INTERVAL, HOLOGRAM_MAX_FRAMES_WITHOUT_FACE, MIN_BRIGHTNESS_THRESHOLD, MAX_BRIGHTNESS_THRESHOLD, FACE_EDGE_MARGIN_PERCENT, MAX_CONSECUTIVE_QUALITY_FAILURES, REQUIRED_CONSISTENT_DOCTYPE_DETECTIONS, SIGNATURE_TEXT_REGEX, MRZ_BLOCK_PATTERN, MIN_CARD_FACE_SIZE_PERCENT } from "./IdentityDocumentCamera.constants.js";
27
27
 
28
28
  // Re-export types for backward compatibility
29
29
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
@@ -71,6 +71,11 @@ const IdentityDocumentCamera = ({
71
71
  const [currentSecondaryFaceImage, setCurrentSecondaryFaceImage] = useState(undefined);
72
72
  const [isBrightnessLow, setIsBrightnessLow] = useState(false);
73
73
  const [isFrameBlurry, setIsFrameBlurry] = useState(false);
74
+ // Glare was being silently rejected (frames dropped with no user feedback), so
75
+ // a user fighting reflections just saw the scan hang. Surface it so we can show
76
+ // an actionable "move away from glare" hint. Set at each glare rejection;
77
+ // cleared when a frame passes the brightness check (a fresh, glare-free frame).
78
+ const [isGlareDetected, setIsGlareDetected] = useState(false);
74
79
  const [hasGuideShown, setHasGuideShown] = useState(false);
75
80
  const [status, setStatus] = useState('SEARCHING');
76
81
  // True once the multi-frame voted MRZ consensus is STABLE + valid (the same
@@ -153,7 +158,8 @@ const IdentityDocumentCamera = ({
153
158
  frameW: 0,
154
159
  frameH: 0,
155
160
  hadLowBrightness: false,
156
- hadBlurryFrames: false
161
+ hadBlurryFrames: false,
162
+ hadGlare: false
157
163
  });
158
164
  const [faceDetectionEnabled, setFaceDetectionEnabled] = useState(true);
159
165
  const faceImages = useRef([]);
@@ -219,7 +225,8 @@ const IdentityDocumentCamera = ({
219
225
  frameW: 0,
220
226
  frameH: 0,
221
227
  hadLowBrightness: false,
222
- hadBlurryFrames: false
228
+ hadBlurryFrames: false,
229
+ hadGlare: false
223
230
  };
224
231
  cachedBarcode.current = null;
225
232
  isCompletionCallbackInvoked.current = false;
@@ -255,7 +262,7 @@ const IdentityDocumentCamera = ({
255
262
  }, [isFocused, hasPermission, hasGuideShown]);
256
263
  useEffect(() => {
257
264
  if (!hasGuideShown || !appContext.currentWorkflowStep?.data?.voiceGuidanceActive) return;
258
- const message = getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, allElementsDetected, elementsOutsideScanArea, t);
265
+ const message = getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, isGlareDetected, allElementsDetected, elementsOutsideScanArea, t);
259
266
  if (message) {
260
267
  if (nextStep === 'COMPLETED') {
261
268
  if (isCompletionAnnouncementSpoken.current) {
@@ -268,7 +275,7 @@ const IdentityDocumentCamera = ({
268
275
  const shouldBypassInterval = nextStep !== 'COMPLETED';
269
276
  speak(message, shouldBypassInterval);
270
277
  }
271
- }, [appContext.currentWorkflowStep?.data?.voiceGuidanceActive, hasGuideShown, isBrightnessLow, isFrameBlurry, nextStep, status, detectedDocumentType, allElementsDetected, elementsOutsideScanArea, t]);
278
+ }, [appContext.currentWorkflowStep?.data?.voiceGuidanceActive, hasGuideShown, isBrightnessLow, isFrameBlurry, isGlareDetected, nextStep, status, detectedDocumentType, allElementsDetected, elementsOutsideScanArea, t]);
272
279
  useEffect(() => {
273
280
  if (status === 'INCORRECT') {
274
281
  const timeout = setTimeout(() => {
@@ -377,7 +384,9 @@ const IdentityDocumentCamera = ({
377
384
  }
378
385
  };
379
386
 
380
- // Check if face image has glare (brightness exceeds threshold)
387
+ // Check if face image has glare (brightness exceeds threshold). Also surfaces
388
+ // the result to `isGlareDetected` so the user gets an actionable hint instead
389
+ // of a silently-stalled scan.
381
390
  const checkFaceGlare = async faceImage => {
382
391
  try {
383
392
  // Check entire face region for glare
@@ -386,6 +395,8 @@ const IdentityDocumentCamera = ({
386
395
  100,
387
396
  // Full face height
388
397
  MAX_BRIGHTNESS_THRESHOLD);
398
+ setIsGlareDetected(hasGlare);
399
+ if (hasGlare) diagStats.current.hadGlare = true;
389
400
  return hasGlare;
390
401
  } catch (error) {
391
402
  return false; // Assume no glare on error
@@ -404,6 +415,8 @@ const IdentityDocumentCamera = ({
404
415
  try {
405
416
  // Check center 80% region for glare (document area)
406
417
  const hasGlare = await OpenCVModule.isRectangularRegionBright(image, Math.round(width * 0.1), Math.round(height * 0.1), Math.round(width * 0.8), Math.round(height * 0.8), MAX_BRIGHTNESS_THRESHOLD);
418
+ setIsGlareDetected(hasGlare);
419
+ if (hasGlare) diagStats.current.hadGlare = true;
407
420
  return hasGlare;
408
421
  } catch (error) {
409
422
  return false;
@@ -817,22 +830,38 @@ const IdentityDocumentCamera = ({
817
830
  const hasFaces = primaryFaces.length > 0;
818
831
  const hasSignature = /signature|imza|İmza/i.test(text);
819
832
  const hasPassportMRZ = parsedMRZData?.fields?.documentCode === 'P';
820
- const hasPassportMRZPattern = mrzText && PASSPORT_MRZ_PATTERN.test(mrzText);
821
- if (hasFaces || hasSignature || hasPassportMRZ || hasPassportMRZPattern) {
822
- setStatus('INCORRECT');
823
- return;
824
- }
825
833
 
826
- // Safety: passport somehow reached ID_BACK step
827
- if (detectedDocumentType === 'PASSPORT') {
834
+ // RECOVERY (must run BEFORE the wrong-side guard below): a passport was
835
+ // misrouted to SCAN_ID_BACK. A passport has only its data page, which
836
+ // carries a face + MRZ — exactly what the wrong-side guard treats as
837
+ // "wrong side", so without this it would loop on INCORRECT forever
838
+ // (the reported "stuck asking for ID back" case). If we have positive
839
+ // passport evidence here, the front was already captured, so complete
840
+ // as a passport instead of waiting for a back that does not exist.
841
+ //
842
+ // We deliberately gate ONLY on authoritative signals: a locked PASSPORT
843
+ // classification, or a PARSED MRZ document code of 'P'. We do NOT test
844
+ // the raw OCR `text` against PASSPORT_MRZ_PATTERN here — an ID card's
845
+ // BACK legitimately carries an MRZ whose name line ("PAPPAS<<MARIA…",
846
+ // "…<<PHILIPP…") can false-match the unanchored pattern and would then
847
+ // wrongly complete a real ID card as a passport, skipping the back-side
848
+ // MRZ + barcode validation entirely.
849
+ if (detectedDocumentType === 'PASSPORT' || hasPassportMRZ) {
828
850
  transitionStepWithCallback('COMPLETED', 'SCAN_ID_BACK', {
829
851
  image,
830
852
  documentType: 'PASSPORT',
831
- mrzText: mrzText ?? undefined,
832
- mrzFields: parsedMRZData?.fields
853
+ mrzText: mrzText ?? lastValidMRZText.current ?? undefined,
854
+ mrzFields: parsedMRZData?.fields ?? lastValidMRZFields.current ?? undefined
833
855
  });
834
856
  return;
835
857
  }
858
+
859
+ // Wrong-side detection: a face or signature means we're looking at a
860
+ // front, not an ID-card back (which has neither).
861
+ if (hasFaces || hasSignature) {
862
+ setStatus('INCORRECT');
863
+ return;
864
+ }
836
865
  setElementsOutsideScanArea([]);
837
866
  const flowResult = handleIDBackFlow(mrzText, parsedMRZData?.fields, parsedMRZData?.valid === true, mrzStableAndValid, hasRequiredMRZFields(parsedMRZData?.fields), barcodeToUse?.rawValue, onlyMRZScan);
838
867
  if (!flowResult.shouldProceed) {
@@ -1354,6 +1383,15 @@ const IdentityDocumentCamera = ({
1354
1383
  setIsBrightnessLow(!isRegionBright);
1355
1384
  if (!isRegionBright) diagStats.current.hadLowBrightness = true;
1356
1385
 
1386
+ // Reset glare to false at the start of every frame. The glare helpers
1387
+ // (checkDocumentGlare/checkFaceGlare) only run at accept-time and set it
1388
+ // true when they find glare; without this per-frame clear the flag would
1389
+ // latch — a "Glare detected" warning would stick over a now-clean view
1390
+ // (and, once a face is locked, the face-glare site never runs again so it
1391
+ // could never clear at all). The accept-time checks run later in this same
1392
+ // frame's handlers and re-assert true if glare is still present.
1393
+ setIsGlareDetected(false);
1394
+
1357
1395
  // Check blur only in center region (area of interest) to avoid false positives
1358
1396
  // from iOS depth-of-field background blur
1359
1397
  let isNotBlurry = true;
@@ -1838,12 +1876,12 @@ const IdentityDocumentCamera = ({
1838
1876
  opacity: errorFlashAnim
1839
1877
  },
1840
1878
  // 3. Warning (yellow) - quality issues
1841
- (isBrightnessLow || isFrameBlurry) && styles.topZoneTextWarning,
1879
+ (isBrightnessLow || isFrameBlurry || isGlareDetected) && styles.topZoneTextWarning,
1842
1880
  // 4. Scanning (green) - all elements detected AND inside scan area
1843
- status === 'SCANNING' && allElementsDetected && elementsOutsideScanArea.length === 0 && !isBrightnessLow && !isFrameBlurry && styles.topZoneTextScanning
1881
+ status === 'SCANNING' && allElementsDetected && elementsOutsideScanArea.length === 0 && !isBrightnessLow && !isFrameBlurry && !isGlareDetected && styles.topZoneTextScanning
1844
1882
  // 5. Default (white) - aligning (not all detected OR elements outside scan area)
1845
1883
  ],
1846
- children: getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, allElementsDetected, elementsOutsideScanArea, t)
1884
+ children: getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, isGlareDetected, allElementsDetected, elementsOutsideScanArea, t)
1847
1885
  })]
1848
1886
  }), /*#__PURE__*/_jsx(View, {
1849
1887
  style: styles.leftZone
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import { Dimensions } from 'react-native';
4
- import { SIGNATURE_REGEX, PASSPORT_MRZ_PATTERN } from "./IdentityDocumentCamera.constants.js";
4
+ import { SIGNATURE_REGEX, PASSPORT_MRZ_PATTERN, MRZ_DENSE_PATTERN } from "./IdentityDocumentCamera.constants.js";
5
5
  import { debugLog, isDebugEnabled } from "../Libs/debug.utils.js";
6
6
 
7
7
  /**
@@ -100,7 +100,7 @@ export function transformBoundsToScreen(bounds, scale, offsetX, offsetY) {
100
100
  * Unified status message logic used by both voice guidance and render text.
101
101
  * Returns the appropriate i18n key arguments for the current scan state.
102
102
  */
103
- export function getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, allElementsDetected, elementsOutsideScanArea, t) {
103
+ export function getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, isGlareDetected, allElementsDetected, elementsOutsideScanArea, t) {
104
104
  if (nextStep === 'COMPLETED') {
105
105
  return t('identityDocumentCamera.scanCompleted');
106
106
  }
@@ -126,6 +126,14 @@ export function getStatusMessage(nextStep, status, detectedDocumentType, isBrigh
126
126
  if (isBrightnessLow) {
127
127
  return t('identityDocumentCamera.lowBrightness');
128
128
  }
129
+
130
+ // Glare is a primary failure mode (reflections off the laminate/photo). It was
131
+ // previously detected but never communicated, so the scan just appeared to
132
+ // hang. Tell the user how to fix it. Ranked above blur because a glare hotspot
133
+ // both blocks acceptance and often reads as a "sharp" (non-blurry) frame.
134
+ if (isGlareDetected) {
135
+ return t('identityDocumentCamera.reduceGlare');
136
+ }
129
137
  if (isFrameBlurry) {
130
138
  return t('identityDocumentCamera.avoidBlur');
131
139
  }
@@ -248,10 +256,17 @@ export function detectDocumentType(faces, ocrText, mrzFields, frameWidth, mrzTex
248
256
  return 'ID_FRONT';
249
257
  }
250
258
 
251
- // If signature present and NO passport MRZ pattern, likely ID_FRONT
252
- // But we can't be 100% sure yet - passport MRZ might appear in next frames
259
+ // If signature present and NO passport MRZ pattern, likely ID_FRONT
260
+ // BUT an ID-card front has no MRZ, so if a real (dense) MRZ is visible here
261
+ // (and it is not a confirmed ID code — that returned above) this is almost
262
+ // certainly a passport data page whose 'P' code just hasn't OCR'd yet.
263
+ // Stay UNKNOWN and let later frames resolve it, rather than locking
264
+ // ID_FRONT and routing a passport to a back side it does not have. We use
265
+ // MRZ_DENSE_PATTERN (needs a `<<` filler run) so a stray single `<` OCR'd
266
+ // from a card-face guilloche cannot wedge a genuine ID front at UNKNOWN.
267
+ const hasUnresolvedMrzBlock = !!mrzText || MRZ_DENSE_PATTERN.test(ocrText);
253
268
  const hasSignature = hasSignatureMatch;
254
- if (hasSignature && !hasPassportMRZPattern) {
269
+ if (hasSignature && !hasPassportMRZPattern && !hasUnresolvedMrzBlock) {
255
270
  return 'ID_FRONT';
256
271
  }
257
272
  }
@@ -633,8 +633,12 @@ const eidReader = async (documentNumber, dateOfBirth, dateOfExpiry, progressCall
633
633
  // step (it was previously outside, so an early DG2 failure went unlabelled).
634
634
  const dg2InputStream = passportService.getInputStream(EIDService.EF_DG2);
635
635
  await dg2InputStream.init();
636
+ // Map the DG2 byte stream to 30→95 (not →100): the JPEG2000 decode that
637
+ // follows can take a noticeable beat (esp. large passport portraits), and
638
+ // jumping to 100 before it made the UI sit at "100% Finalizing" looking
639
+ // frozen during the decode. We reserve 95→100 for the decode step below.
636
640
  InputStream.onRead((totalBytesRead, fileLength) => {
637
- progress = 30 + totalBytesRead / fileLength * 70;
641
+ progress = 30 + totalBytesRead / fileLength * 65;
638
642
  if (progressCallback) {
639
643
  progressCallback(progress);
640
644
  }
@@ -656,6 +660,12 @@ const eidReader = async (documentNumber, dateOfBirth, dateOfExpiry, progressCall
656
660
  const buffer = Buffer.alloc(imageLength);
657
661
  await imageInputStream.readBytesWithOffset(buffer, 0, imageLength);
658
662
  const rawMimeType = faceImageInfo.getMimeType();
663
+ // Signal the (potentially slow) photo decode so the UI shows a distinct
664
+ // "decoding photo" stage at 95% rather than appearing frozen at 100%.
665
+ progress = 95;
666
+ if (progressCallback) {
667
+ progressCallback(progress);
668
+ }
659
669
  const converted = await convertJP2IfNeeded(buffer, rawMimeType);
660
670
  imageAsBase64 = converted.base64;
661
671
  mimeType = converted.mimeType;
@@ -113,11 +113,13 @@ export default {
113
113
  'eidScannerScreen.placePassportOnNFC': 'Place your passport near the NFC reader',
114
114
  'eidScannerScreen.placeDocumentOnNFC': 'Place your document near the NFC reader',
115
115
  'eidScannerScreen.readingDocument': 'Hold steady - Reading document',
116
+ 'eidScannerScreen.keepStill': 'Keep the document and phone still until the read completes.',
116
117
  'eidScannerScreen.checkYourInformation': 'Review your information carefully',
117
118
  'eidScannerScreen.approveAndContinue': 'Approve and Continue',
118
119
  'eidScannerScreen.connecting': 'Establishing secure connection...',
119
120
  'eidScannerScreen.readingMRZ': 'Reading document information...',
120
121
  'eidScannerScreen.readingFaceImage': 'Reading photo data...',
122
+ 'eidScannerScreen.decodingFaceImage': 'Decoding photo...',
121
123
  'eidScannerScreen.completing': 'Finalizing verification...',
122
124
  'eidScannerScreen.progress': 'Progress',
123
125
  'identityDocumentCamera.guideHeader': 'Document Scan',
@@ -142,6 +144,7 @@ export default {
142
144
  'identityDocumentCamera.hologramCheck': 'Hologram',
143
145
  'identityDocumentCamera.keepSteady': 'Keep device steady',
144
146
  'identityDocumentCamera.avoidBlur': 'Keep device steady',
147
+ 'identityDocumentCamera.reduceGlare': 'Glare detected. Tilt the document or move away from direct light.',
145
148
  'identityDocumentCamera.wrongSideFront': 'Show the front side of your document',
146
149
  'identityDocumentCamera.wrongSideBack': 'Show the back side of your document',
147
150
  'identityDocumentCamera.idCardDetected': 'ID detected',
@@ -113,11 +113,13 @@ export default {
113
113
  'eidScannerScreen.placePassportOnNFC': 'Pasaportunuzu NFC okuyucuya yaklaştırın',
114
114
  'eidScannerScreen.placeDocumentOnNFC': 'Belgenizi NFC okuyucuya yaklaştırın',
115
115
  'eidScannerScreen.readingDocument': 'Sabit tutun - Belge okunuyor',
116
+ 'eidScannerScreen.keepStill': 'Okuma tamamlanana kadar belgeyi ve telefonu sabit tutun.',
116
117
  'eidScannerScreen.checkYourInformation': 'Bilgilerinizi dikkatle kontrol edin',
117
118
  'eidScannerScreen.approveAndContinue': 'Onayla ve Devam Et',
118
119
  'eidScannerScreen.connecting': 'Güvenli bağlantı kuruluyor...',
119
120
  'eidScannerScreen.readingMRZ': 'Belge bilgileri okunuyor...',
120
121
  'eidScannerScreen.readingFaceImage': 'Fotoğraf verisi okunuyor...',
122
+ 'eidScannerScreen.decodingFaceImage': 'Fotoğraf çözümleniyor...',
121
123
  'eidScannerScreen.completing': 'Doğrulama tamamlanıyor...',
122
124
  'eidScannerScreen.progress': 'İlerleme',
123
125
  'identityDocumentCamera.guideHeader': 'Belge Taraması',
@@ -142,6 +144,7 @@ export default {
142
144
  'identityDocumentCamera.hologramCheck': 'Hologram',
143
145
  'identityDocumentCamera.keepSteady': 'Cihazı sabit tutun',
144
146
  'identityDocumentCamera.avoidBlur': 'Cihazı sabit tutun',
147
+ 'identityDocumentCamera.reduceGlare': 'Parlama algılandı. Belgeyi hafifçe eğin veya doğrudan ışıktan uzaklaşın.',
145
148
  'identityDocumentCamera.wrongSideFront': 'Belgenizin ön yüzünü gösterin',
146
149
  'identityDocumentCamera.wrongSideBack': 'Belgenizin arka yüzünü gösterin',
147
150
  'identityDocumentCamera.idCardDetected': 'Kimlik kartı algılandı',
@@ -2,4 +2,4 @@
2
2
 
3
3
  // This file is auto-generated. Do not edit manually.
4
4
  // Version is synced from package.json during build.
5
- export const SDK_VERSION = '1.495.11';
5
+ export const SDK_VERSION = '1.496.0';
@@ -1 +1 @@
1
- {"version":3,"file":"EIDScanner.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/EIDScanner.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAwBpD,UAAU,eAAe;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CACd,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,KACtB,IAAI,CAAC;IACV,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED,QAAA,MAAM,UAAU,GAAI,6FAOjB,eAAe,4CA8yBjB,CAAC;AA4NF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"EIDScanner.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/EIDScanner.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAwBpD,UAAU,eAAe;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CACd,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,KACtB,IAAI,CAAC;IACV,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED,QAAA,MAAM,UAAU,GAAI,6FAOjB,eAAe,4CA80BjB,CAAC;AAmOF,eAAe,UAAU,CAAC"}
@@ -14,6 +14,7 @@ export declare const REQUIRED_CONSISTENT_DOCTYPE_DETECTIONS = 3;
14
14
  export declare const SIGNATURE_REGEX: RegExp;
15
15
  export declare const SIGNATURE_TEXT_REGEX: RegExp;
16
16
  export declare const MRZ_BLOCK_PATTERN: RegExp;
17
+ export declare const MRZ_DENSE_PATTERN: RegExp;
17
18
  export declare const PASSPORT_MRZ_PATTERN: RegExp;
18
19
  export declare const MIN_SECURITY_FEATURES_REQUIRED = 4;
19
20
  export declare const SECURITY_FEATURE_NAMES: {
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityDocumentCamera.constants.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,4BAA4B,OAAO,CAAC;AACjD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAEnD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AACnD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAC/C,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,eAAO,MAAM,sCAAsC,IAAI,CAAC;AAExD,eAAO,MAAM,eAAe,QAAkC,CAAC;AAC/D,eAAO,MAAM,oBAAoB,QAAyB,CAAC;AAC3D,eAAO,MAAM,iBAAiB,QAAsB,CAAC;AASrD,eAAO,MAAM,oBAAoB,QAAyC,CAAC;AAI3E,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,sBAAsB;;;;;;;;;;CAUzB,CAAC;AAKX,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,mBAAmB,MAAM,CAAC"}
1
+ {"version":3,"file":"IdentityDocumentCamera.constants.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,4BAA4B,OAAO,CAAC;AACjD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAEnD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AACnD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAC/C,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,eAAO,MAAM,sCAAsC,IAAI,CAAC;AAExD,eAAO,MAAM,eAAe,QAAkC,CAAC;AAC/D,eAAO,MAAM,oBAAoB,QAAyB,CAAC;AAC3D,eAAO,MAAM,iBAAiB,QAAsB,CAAC;AASrD,eAAO,MAAM,iBAAiB,QAA+B,CAAC;AAS9D,eAAO,MAAM,oBAAoB,QAAyC,CAAC;AAI3E,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,sBAAsB;;;;;;;;;;CAUzB,CAAC;AAKX,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,mBAAmB,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityDocumentCamera.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.tsx"],"names":[],"mappings":"AA0EA,OAAO,KAAK,EACV,mBAAmB,EACnB,SAAS,EACT,2BAA2B,EAK5B,MAAM,gCAAgC,CAAC;AAGxC,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,2BAA2B,EAAE,CAAC;AAC5E,YAAY,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAMnE,QAAA,MAAM,sBAAsB,GAAI,uDAI7B,2BAA2B,4CAmmF7B,CAAC;AAiIF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"IdentityDocumentCamera.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.tsx"],"names":[],"mappings":"AAyEA,OAAO,KAAK,EACV,mBAAmB,EACnB,SAAS,EACT,2BAA2B,EAK5B,MAAM,gCAAgC,CAAC;AAGxC,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,2BAA2B,EAAE,CAAC;AAC5E,YAAY,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAMnE,QAAA,MAAM,sBAAsB,GAAI,uDAI7B,2BAA2B,4CA0oF7B,CAAC;AAiIF,eAAe,sBAAsB,CAAC"}
@@ -37,7 +37,7 @@ export interface PassportFlowResult {
37
37
  export interface IDFrontFlowResult {
38
38
  shouldProceed: boolean;
39
39
  reason?: string;
40
- nextAction?: 'WAIT_FOR_ELEMENTS' | 'REJECT_AS_PASSPORT' | 'PROCEED_TO_HOLOGRAM';
40
+ nextAction?: 'WAIT_FOR_ELEMENTS' | 'WAIT_FOR_MRZ' | 'REJECT_AS_PASSPORT' | 'PROCEED_TO_HOLOGRAM';
41
41
  }
42
42
  export interface IDBackFlowResult {
43
43
  shouldProceed: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityDocumentCamera.flows.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.flows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAgB,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAcpD,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EACP,mBAAmB,GACnB,cAAc,GACd,qBAAqB,GACrB,sBAAsB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EACP,mBAAmB,GACnB,oBAAoB,GACpB,qBAAqB,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,cAAc,GAAG,kBAAkB,GAAG,sBAAsB,CAAC;CAC3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,iBAAiB,EAAE,OAAO,EAC1B,WAAW,EAAE,OAAO,EACpB,iBAAiB,EAAE,OAAO,EAC1B,YAAY,EAAE,OAAO,GACpB,kBAAkB,CAgEpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,UAAU,EAAE,MAAM,GACjB,iBAAiB,CA0EnB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,QAAQ,EAAE,OAAO,EACjB,iBAAiB,EAAE,OAAO,EAC1B,iBAAiB,EAAE,OAAO,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,WAAW,EAAE,OAAO,GACnB,gBAAgB,CA2DlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,wBAAwB,CACtC,oBAAoB,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,EACrE,mBAAmB,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,EACpE,UAAU,EAAE,MAAM,GAAG,SAAS,EAM9B,iBAAiB,GAAE,OAAe,GACjC,WAAW,GAAG,cAAc,CAuB9B"}
1
+ {"version":3,"file":"IdentityDocumentCamera.flows.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.flows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAgB,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAiBpD,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EACP,mBAAmB,GACnB,cAAc,GACd,qBAAqB,GACrB,sBAAsB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EACP,mBAAmB,GACnB,cAAc,GACd,oBAAoB,GACpB,qBAAqB,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,cAAc,GAAG,kBAAkB,GAAG,sBAAsB,CAAC;CAC3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,iBAAiB,EAAE,OAAO,EAC1B,WAAW,EAAE,OAAO,EACpB,iBAAiB,EAAE,OAAO,EAC1B,YAAY,EAAE,OAAO,GACpB,kBAAkB,CAgEpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAoHnB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,QAAQ,EAAE,OAAO,EACjB,iBAAiB,EAAE,OAAO,EAC1B,iBAAiB,EAAE,OAAO,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,WAAW,EAAE,OAAO,GACnB,gBAAgB,CA2DlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,wBAAwB,CACtC,oBAAoB,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,EACrE,mBAAmB,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,EACpE,UAAU,EAAE,MAAM,GAAG,SAAS,EAM9B,iBAAiB,GAAE,OAAe,GACjC,WAAW,GAAG,cAAc,CAuB9B"}
@@ -57,7 +57,7 @@ export declare function transformBoundsToScreen(bounds: {
57
57
  * Unified status message logic used by both voice guidance and render text.
58
58
  * Returns the appropriate i18n key arguments for the current scan state.
59
59
  */
60
- export declare function getStatusMessage(nextStep: ScanStep, status: ScanStatus, detectedDocumentType: DocumentType, isBrightnessLow: boolean, isFrameBlurry: boolean, allElementsDetected: boolean, elementsOutsideScanArea: string[], t: (key: string, params?: Record<string, unknown>) => string): string;
60
+ export declare function getStatusMessage(nextStep: ScanStep, status: ScanStatus, detectedDocumentType: DocumentType, isBrightnessLow: boolean, isFrameBlurry: boolean, isGlareDetected: boolean, allElementsDetected: boolean, elementsOutsideScanArea: string[], t: (key: string, params?: Record<string, unknown>) => string): string;
61
61
  /**
62
62
  * Calculate angle from two points in degrees
63
63
  */
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityDocumentCamera.utils.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IdentityDocumentCamera.utils.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/IdentityDocumentCamera.utils.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"eidReader.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/EIDReader/eidReader.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AA2Y7C,QAAA,MAAM,SAAS,GACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,EACnB,cAAc,MAAM,EACpB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAC5C,OAAO,CACN;IACE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GACD,SAAS,CA+XZ,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"eidReader.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/EIDReader/eidReader.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AA2Y7C,QAAA,MAAM,SAAS,GACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,EACnB,cAAc,MAAM,EACpB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAC5C,OAAO,CACN;IACE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GACD,SAAS,CAyYZ,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -111,11 +111,13 @@ declare const _default: {
111
111
  'eidScannerScreen.placePassportOnNFC': string;
112
112
  'eidScannerScreen.placeDocumentOnNFC': string;
113
113
  'eidScannerScreen.readingDocument': string;
114
+ 'eidScannerScreen.keepStill': string;
114
115
  'eidScannerScreen.checkYourInformation': string;
115
116
  'eidScannerScreen.approveAndContinue': string;
116
117
  'eidScannerScreen.connecting': string;
117
118
  'eidScannerScreen.readingMRZ': string;
118
119
  'eidScannerScreen.readingFaceImage': string;
120
+ 'eidScannerScreen.decodingFaceImage': string;
119
121
  'eidScannerScreen.completing': string;
120
122
  'eidScannerScreen.progress': string;
121
123
  'identityDocumentCamera.guideHeader': string;
@@ -140,6 +142,7 @@ declare const _default: {
140
142
  'identityDocumentCamera.hologramCheck': string;
141
143
  'identityDocumentCamera.keepSteady': string;
142
144
  'identityDocumentCamera.avoidBlur': string;
145
+ 'identityDocumentCamera.reduceGlare': string;
143
146
  'identityDocumentCamera.wrongSideFront': string;
144
147
  'identityDocumentCamera.wrongSideBack': string;
145
148
  'identityDocumentCamera.idCardDetected': string;