@trustchex/react-native-sdk 1.495.12 → 1.497.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/camera/TrustchexCameraView.kt +4 -1
- package/android/src/main/java/com/trustchex/reactnativesdk/mlkit/MLKitModule.kt +5 -1
- package/ios/Camera/TrustchexCameraView.swift +3 -0
- package/ios/MLKit/MLKitModule.swift +1 -1
- package/lib/module/Shared/Components/EIDScanner.js +35 -4
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +30 -8
- package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +9 -1
- package/lib/module/Shared/EIDReader/eidReader.js +11 -1
- package/lib/module/Translation/Resources/en.js +3 -0
- package/lib/module/Translation/Resources/tr.js +3 -0
- package/lib/module/version.js +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.utils.d.ts +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +3 -0
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +3 -0
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/lib/typescript/src/version.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Shared/Components/EIDScanner.tsx +49 -2
- package/src/Shared/Components/IdentityDocumentCamera.tsx +29 -2
- package/src/Shared/Components/IdentityDocumentCamera.utils.ts +9 -0
- package/src/Shared/EIDReader/eidReader.ts +11 -1
- package/src/Translation/Resources/en.ts +5 -0
- package/src/Translation/Resources/tr.ts +5 -0
- 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(
|
|
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 <
|
|
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 &&
|
|
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
|
|
@@ -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;
|
|
@@ -1370,6 +1383,15 @@ const IdentityDocumentCamera = ({
|
|
|
1370
1383
|
setIsBrightnessLow(!isRegionBright);
|
|
1371
1384
|
if (!isRegionBright) diagStats.current.hadLowBrightness = true;
|
|
1372
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
|
+
|
|
1373
1395
|
// Check blur only in center region (area of interest) to avoid false positives
|
|
1374
1396
|
// from iOS depth-of-field background blur
|
|
1375
1397
|
let isNotBlurry = true;
|
|
@@ -1854,12 +1876,12 @@ const IdentityDocumentCamera = ({
|
|
|
1854
1876
|
opacity: errorFlashAnim
|
|
1855
1877
|
},
|
|
1856
1878
|
// 3. Warning (yellow) - quality issues
|
|
1857
|
-
(isBrightnessLow || isFrameBlurry) && styles.topZoneTextWarning,
|
|
1879
|
+
(isBrightnessLow || isFrameBlurry || isGlareDetected) && styles.topZoneTextWarning,
|
|
1858
1880
|
// 4. Scanning (green) - all elements detected AND inside scan area
|
|
1859
|
-
status === 'SCANNING' && allElementsDetected && elementsOutsideScanArea.length === 0 && !isBrightnessLow && !isFrameBlurry && styles.topZoneTextScanning
|
|
1881
|
+
status === 'SCANNING' && allElementsDetected && elementsOutsideScanArea.length === 0 && !isBrightnessLow && !isFrameBlurry && !isGlareDetected && styles.topZoneTextScanning
|
|
1860
1882
|
// 5. Default (white) - aligning (not all detected OR elements outside scan area)
|
|
1861
1883
|
],
|
|
1862
|
-
children: getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, allElementsDetected, elementsOutsideScanArea, t)
|
|
1884
|
+
children: getStatusMessage(nextStep, status, detectedDocumentType, isBrightnessLow, isFrameBlurry, isGlareDetected, allElementsDetected, elementsOutsideScanArea, t)
|
|
1863
1885
|
})]
|
|
1864
1886
|
}), /*#__PURE__*/_jsx(View, {
|
|
1865
1887
|
style: styles.leftZone
|
|
@@ -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
|
}
|
|
@@ -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 *
|
|
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ı',
|
package/lib/module/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EIDScanner.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/EIDScanner.tsx"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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"}
|
|
@@ -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":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,IAAI,EACL,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQpD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG7E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,OAAO,CAGT;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAEvE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM;;;;;EAmBpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;;;;;sBAW9C,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM;EAIjE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC/D,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM;;;;;EAQhB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,UAAU,EAClB,oBAAoB,EAAE,YAAY,EAClC,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,OAAO,EACtB,mBAAmB,EAAE,OAAO,EAC5B,uBAAuB,EAAE,MAAM,EAAE,EACjC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GAC3D,MAAM,
|
|
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,
|
|
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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../../../src/Translation/Resources/en.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../../../src/Translation/Resources/en.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wBAyRE"}
|
|
@@ -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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tr.d.ts","sourceRoot":"","sources":["../../../../../src/Translation/Resources/tr.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tr.d.ts","sourceRoot":"","sources":["../../../../../src/Translation/Resources/tr.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wBA4RE"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "1.
|
|
1
|
+
export declare const SDK_VERSION = "1.497.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,YAAY,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback, useRef } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Alert,
|
|
4
|
+
View,
|
|
5
|
+
Text,
|
|
6
|
+
Image,
|
|
7
|
+
StyleSheet,
|
|
8
|
+
Animated,
|
|
9
|
+
Vibration,
|
|
10
|
+
} from 'react-native';
|
|
3
11
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
12
|
import NFCManager from 'react-native-nfc-manager';
|
|
5
13
|
import DeviceInfo from 'react-native-device-info';
|
|
@@ -254,19 +262,31 @@ const EIDScanner = ({
|
|
|
254
262
|
// "reading document" spinner never clears and the user is stuck with no
|
|
255
263
|
// error. Cap the whole read; on timeout we throw a categorized error so
|
|
256
264
|
// the catch below surfaces a retry prompt and finally resets the UI.
|
|
265
|
+
// Fire a "chip detected" haptic exactly once, the moment progress first
|
|
266
|
+
// moves off 0 (the chip connected and the read began). Confirms contact
|
|
267
|
+
// to a user who can't see the screen while holding the phone to the doc.
|
|
268
|
+
let chipDetectedHapticFired = false;
|
|
257
269
|
const readPromise = eidReader(
|
|
258
270
|
documentNumber,
|
|
259
271
|
dateOfBirth,
|
|
260
272
|
dateOfExpiry,
|
|
261
273
|
(progressValue) => {
|
|
274
|
+
if (progressValue > 0 && !chipDetectedHapticFired) {
|
|
275
|
+
chipDetectedHapticFired = true;
|
|
276
|
+
Vibration.vibrate(40);
|
|
277
|
+
}
|
|
262
278
|
setProgress(progressValue);
|
|
263
279
|
// Update stage message based on progress
|
|
264
280
|
if (progressValue <= 20) {
|
|
265
281
|
setProgressStage(t('eidScannerScreen.connecting'));
|
|
266
282
|
} else if (progressValue <= 30) {
|
|
267
283
|
setProgressStage(t('eidScannerScreen.readingMRZ'));
|
|
268
|
-
} else if (progressValue <
|
|
284
|
+
} else if (progressValue < 95) {
|
|
269
285
|
setProgressStage(t('eidScannerScreen.readingFaceImage'));
|
|
286
|
+
} else if (progressValue < 100) {
|
|
287
|
+
// 95→100 is the (possibly slow) photo decode — give it its own
|
|
288
|
+
// stage so the bar doesn't look frozen at "Finalizing".
|
|
289
|
+
setProgressStage(t('eidScannerScreen.decodingFaceImage'));
|
|
270
290
|
} else {
|
|
271
291
|
setProgressStage(t('eidScannerScreen.completing'));
|
|
272
292
|
}
|
|
@@ -292,6 +312,11 @@ const EIDScanner = ({
|
|
|
292
312
|
}
|
|
293
313
|
}
|
|
294
314
|
if (passportData) {
|
|
315
|
+
// Success haptic: the phone is pressed against the document, so the
|
|
316
|
+
// user often can't see the screen — a buzz confirms the chip read
|
|
317
|
+
// finished. (The NFC step previously had no haptics at all, unlike the
|
|
318
|
+
// camera/liveness screens.)
|
|
319
|
+
Vibration.vibrate(120);
|
|
295
320
|
const scanDuration = Date.now() - startTime;
|
|
296
321
|
const documentData = normalizeFromMRZInfo(passportData.mrz);
|
|
297
322
|
const builtName = buildDocumentName(
|
|
@@ -429,6 +454,10 @@ const EIDScanner = ({
|
|
|
429
454
|
tag_lost: 'eidScannerScreen.nfcTagLost',
|
|
430
455
|
timeout: 'eidScannerScreen.nfcTimeout',
|
|
431
456
|
not_enabled: 'eidScannerScreen.nfcNotEnabled',
|
|
457
|
+
// The default/most-common "chip just wouldn't read" bucket. Show the
|
|
458
|
+
// actionable hold-flat-and-retry guidance rather than the generic
|
|
459
|
+
// "contact support" message — re-placing the phone usually fixes it.
|
|
460
|
+
reading_error: 'eidScannerScreen.nfcReadFailed',
|
|
432
461
|
};
|
|
433
462
|
|
|
434
463
|
if (category !== 'user_cancelled') {
|
|
@@ -831,6 +860,17 @@ const EIDScanner = ({
|
|
|
831
860
|
</Text>
|
|
832
861
|
)))}
|
|
833
862
|
|
|
863
|
+
{/* The connect/auth phase (progress still 0) is the most fragile part
|
|
864
|
+
of the read — the many PACE/BAC round-trips drop if the phone
|
|
865
|
+
moves. Tell the user to hold still here, not only once the bar
|
|
866
|
+
starts moving (the progress UI's "Hold steady" is gated on
|
|
867
|
+
progress > 0). */}
|
|
868
|
+
{hasNfc && isEnabled && isScanning && progress === 0 && (
|
|
869
|
+
<Text style={styles.keepStillHint}>
|
|
870
|
+
{t('eidScannerScreen.keepStill')}
|
|
871
|
+
</Text>
|
|
872
|
+
)}
|
|
873
|
+
|
|
834
874
|
{hasNfc && isEnabled && !isScanning && !isScanned && (
|
|
835
875
|
<View style={styles.buttonsContainer}>
|
|
836
876
|
<StyledButton mode="contained" onPress={readNFC}>
|
|
@@ -938,6 +978,13 @@ const styles = StyleSheet.create({
|
|
|
938
978
|
color: 'black',
|
|
939
979
|
textAlign: 'center',
|
|
940
980
|
},
|
|
981
|
+
keepStillHint: {
|
|
982
|
+
fontSize: 15,
|
|
983
|
+
color: '#666',
|
|
984
|
+
textAlign: 'center',
|
|
985
|
+
marginTop: 12,
|
|
986
|
+
paddingHorizontal: 24,
|
|
987
|
+
},
|
|
941
988
|
// ── ID Card result layout ──────────────────────────────────────────────
|
|
942
989
|
idCardWrapper: {
|
|
943
990
|
gap: 10,
|
|
@@ -137,6 +137,11 @@ const IdentityDocumentCamera = ({
|
|
|
137
137
|
>(undefined);
|
|
138
138
|
const [isBrightnessLow, setIsBrightnessLow] = useState(false);
|
|
139
139
|
const [isFrameBlurry, setIsFrameBlurry] = useState(false);
|
|
140
|
+
// Glare was being silently rejected (frames dropped with no user feedback), so
|
|
141
|
+
// a user fighting reflections just saw the scan hang. Surface it so we can show
|
|
142
|
+
// an actionable "move away from glare" hint. Set at each glare rejection;
|
|
143
|
+
// cleared when a frame passes the brightness check (a fresh, glare-free frame).
|
|
144
|
+
const [isGlareDetected, setIsGlareDetected] = useState(false);
|
|
140
145
|
const [hasGuideShown, setHasGuideShown] = useState(false);
|
|
141
146
|
const [status, setStatus] = useState<
|
|
142
147
|
'SEARCHING' | 'SCANNING' | 'SCANNED' | 'INCORRECT'
|
|
@@ -234,6 +239,7 @@ const IdentityDocumentCamera = ({
|
|
|
234
239
|
frameH: 0,
|
|
235
240
|
hadLowBrightness: false,
|
|
236
241
|
hadBlurryFrames: false,
|
|
242
|
+
hadGlare: false,
|
|
237
243
|
});
|
|
238
244
|
const [faceDetectionEnabled, setFaceDetectionEnabled] = useState(true);
|
|
239
245
|
const faceImages = useRef<string[]>([]);
|
|
@@ -348,6 +354,7 @@ const IdentityDocumentCamera = ({
|
|
|
348
354
|
frameH: 0,
|
|
349
355
|
hadLowBrightness: false,
|
|
350
356
|
hadBlurryFrames: false,
|
|
357
|
+
hadGlare: false,
|
|
351
358
|
};
|
|
352
359
|
cachedBarcode.current = null;
|
|
353
360
|
isCompletionCallbackInvoked.current = false;
|
|
@@ -396,6 +403,7 @@ const IdentityDocumentCamera = ({
|
|
|
396
403
|
detectedDocumentType,
|
|
397
404
|
isBrightnessLow,
|
|
398
405
|
isFrameBlurry,
|
|
406
|
+
isGlareDetected,
|
|
399
407
|
allElementsDetected,
|
|
400
408
|
elementsOutsideScanArea,
|
|
401
409
|
t
|
|
@@ -418,6 +426,7 @@ const IdentityDocumentCamera = ({
|
|
|
418
426
|
hasGuideShown,
|
|
419
427
|
isBrightnessLow,
|
|
420
428
|
isFrameBlurry,
|
|
429
|
+
isGlareDetected,
|
|
421
430
|
nextStep,
|
|
422
431
|
status,
|
|
423
432
|
detectedDocumentType,
|
|
@@ -566,7 +575,9 @@ const IdentityDocumentCamera = ({
|
|
|
566
575
|
}
|
|
567
576
|
};
|
|
568
577
|
|
|
569
|
-
// Check if face image has glare (brightness exceeds threshold)
|
|
578
|
+
// Check if face image has glare (brightness exceeds threshold). Also surfaces
|
|
579
|
+
// the result to `isGlareDetected` so the user gets an actionable hint instead
|
|
580
|
+
// of a silently-stalled scan.
|
|
570
581
|
const checkFaceGlare = async (faceImage: string): Promise<boolean> => {
|
|
571
582
|
try {
|
|
572
583
|
// Check entire face region for glare
|
|
@@ -578,6 +589,8 @@ const IdentityDocumentCamera = ({
|
|
|
578
589
|
100, // Full face height
|
|
579
590
|
MAX_BRIGHTNESS_THRESHOLD
|
|
580
591
|
);
|
|
592
|
+
setIsGlareDetected(hasGlare);
|
|
593
|
+
if (hasGlare) diagStats.current.hadGlare = true;
|
|
581
594
|
return hasGlare;
|
|
582
595
|
} catch (error) {
|
|
583
596
|
return false; // Assume no glare on error
|
|
@@ -616,6 +629,8 @@ const IdentityDocumentCamera = ({
|
|
|
616
629
|
Math.round(height * 0.8),
|
|
617
630
|
MAX_BRIGHTNESS_THRESHOLD
|
|
618
631
|
);
|
|
632
|
+
setIsGlareDetected(hasGlare);
|
|
633
|
+
if (hasGlare) diagStats.current.hadGlare = true;
|
|
619
634
|
return hasGlare;
|
|
620
635
|
} catch (error) {
|
|
621
636
|
return false;
|
|
@@ -2041,6 +2056,15 @@ const IdentityDocumentCamera = ({
|
|
|
2041
2056
|
setIsBrightnessLow(!isRegionBright);
|
|
2042
2057
|
if (!isRegionBright) diagStats.current.hadLowBrightness = true;
|
|
2043
2058
|
|
|
2059
|
+
// Reset glare to false at the start of every frame. The glare helpers
|
|
2060
|
+
// (checkDocumentGlare/checkFaceGlare) only run at accept-time and set it
|
|
2061
|
+
// true when they find glare; without this per-frame clear the flag would
|
|
2062
|
+
// latch — a "Glare detected" warning would stick over a now-clean view
|
|
2063
|
+
// (and, once a face is locked, the face-glare site never runs again so it
|
|
2064
|
+
// could never clear at all). The accept-time checks run later in this same
|
|
2065
|
+
// frame's handlers and re-assert true if glare is still present.
|
|
2066
|
+
setIsGlareDetected(false);
|
|
2067
|
+
|
|
2044
2068
|
// Check blur only in center region (area of interest) to avoid false positives
|
|
2045
2069
|
// from iOS depth-of-field background blur
|
|
2046
2070
|
let isNotBlurry = true;
|
|
@@ -2666,13 +2690,15 @@ const IdentityDocumentCamera = ({
|
|
|
2666
2690
|
opacity: errorFlashAnim,
|
|
2667
2691
|
},
|
|
2668
2692
|
// 3. Warning (yellow) - quality issues
|
|
2669
|
-
(isBrightnessLow || isFrameBlurry) &&
|
|
2693
|
+
(isBrightnessLow || isFrameBlurry || isGlareDetected) &&
|
|
2694
|
+
styles.topZoneTextWarning,
|
|
2670
2695
|
// 4. Scanning (green) - all elements detected AND inside scan area
|
|
2671
2696
|
status === 'SCANNING' &&
|
|
2672
2697
|
allElementsDetected &&
|
|
2673
2698
|
elementsOutsideScanArea.length === 0 &&
|
|
2674
2699
|
!isBrightnessLow &&
|
|
2675
2700
|
!isFrameBlurry &&
|
|
2701
|
+
!isGlareDetected &&
|
|
2676
2702
|
styles.topZoneTextScanning,
|
|
2677
2703
|
// 5. Default (white) - aligning (not all detected OR elements outside scan area)
|
|
2678
2704
|
]}
|
|
@@ -2683,6 +2709,7 @@ const IdentityDocumentCamera = ({
|
|
|
2683
2709
|
detectedDocumentType,
|
|
2684
2710
|
isBrightnessLow,
|
|
2685
2711
|
isFrameBlurry,
|
|
2712
|
+
isGlareDetected,
|
|
2686
2713
|
allElementsDetected,
|
|
2687
2714
|
elementsOutsideScanArea,
|
|
2688
2715
|
t
|
|
@@ -119,6 +119,7 @@ export function getStatusMessage(
|
|
|
119
119
|
detectedDocumentType: DocumentType,
|
|
120
120
|
isBrightnessLow: boolean,
|
|
121
121
|
isFrameBlurry: boolean,
|
|
122
|
+
isGlareDetected: boolean,
|
|
122
123
|
allElementsDetected: boolean,
|
|
123
124
|
elementsOutsideScanArea: string[],
|
|
124
125
|
t: (key: string, params?: Record<string, unknown>) => string
|
|
@@ -150,6 +151,14 @@ export function getStatusMessage(
|
|
|
150
151
|
return t('identityDocumentCamera.lowBrightness');
|
|
151
152
|
}
|
|
152
153
|
|
|
154
|
+
// Glare is a primary failure mode (reflections off the laminate/photo). It was
|
|
155
|
+
// previously detected but never communicated, so the scan just appeared to
|
|
156
|
+
// hang. Tell the user how to fix it. Ranked above blur because a glare hotspot
|
|
157
|
+
// both blocks acceptance and often reads as a "sharp" (non-blurry) frame.
|
|
158
|
+
if (isGlareDetected) {
|
|
159
|
+
return t('identityDocumentCamera.reduceGlare');
|
|
160
|
+
}
|
|
161
|
+
|
|
153
162
|
if (isFrameBlurry) {
|
|
154
163
|
return t('identityDocumentCamera.avoidBlur');
|
|
155
164
|
}
|
|
@@ -732,8 +732,12 @@ const eidReader = async (
|
|
|
732
732
|
// step (it was previously outside, so an early DG2 failure went unlabelled).
|
|
733
733
|
const dg2InputStream = passportService.getInputStream(EIDService.EF_DG2);
|
|
734
734
|
await dg2InputStream.init();
|
|
735
|
+
// Map the DG2 byte stream to 30→95 (not →100): the JPEG2000 decode that
|
|
736
|
+
// follows can take a noticeable beat (esp. large passport portraits), and
|
|
737
|
+
// jumping to 100 before it made the UI sit at "100% Finalizing" looking
|
|
738
|
+
// frozen during the decode. We reserve 95→100 for the decode step below.
|
|
735
739
|
InputStream.onRead((totalBytesRead, fileLength) => {
|
|
736
|
-
progress = 30 + (totalBytesRead / fileLength) *
|
|
740
|
+
progress = 30 + (totalBytesRead / fileLength) * 65;
|
|
737
741
|
if (progressCallback) {
|
|
738
742
|
progressCallback(progress);
|
|
739
743
|
}
|
|
@@ -756,6 +760,12 @@ const eidReader = async (
|
|
|
756
760
|
const buffer = Buffer.alloc(imageLength);
|
|
757
761
|
await imageInputStream.readBytesWithOffset(buffer, 0, imageLength);
|
|
758
762
|
const rawMimeType = faceImageInfo.getMimeType();
|
|
763
|
+
// Signal the (potentially slow) photo decode so the UI shows a distinct
|
|
764
|
+
// "decoding photo" stage at 95% rather than appearing frozen at 100%.
|
|
765
|
+
progress = 95;
|
|
766
|
+
if (progressCallback) {
|
|
767
|
+
progressCallback(progress);
|
|
768
|
+
}
|
|
759
769
|
const converted = await convertJP2IfNeeded(buffer, rawMimeType);
|
|
760
770
|
imageAsBase64 = converted.base64;
|
|
761
771
|
mimeType = converted.mimeType;
|
|
@@ -143,11 +143,14 @@ export default {
|
|
|
143
143
|
'eidScannerScreen.placeDocumentOnNFC':
|
|
144
144
|
'Place your document near the NFC reader',
|
|
145
145
|
'eidScannerScreen.readingDocument': 'Hold steady - Reading document',
|
|
146
|
+
'eidScannerScreen.keepStill':
|
|
147
|
+
'Keep the document and phone still until the read completes.',
|
|
146
148
|
'eidScannerScreen.checkYourInformation': 'Review your information carefully',
|
|
147
149
|
'eidScannerScreen.approveAndContinue': 'Approve and Continue',
|
|
148
150
|
'eidScannerScreen.connecting': 'Establishing secure connection...',
|
|
149
151
|
'eidScannerScreen.readingMRZ': 'Reading document information...',
|
|
150
152
|
'eidScannerScreen.readingFaceImage': 'Reading photo data...',
|
|
153
|
+
'eidScannerScreen.decodingFaceImage': 'Decoding photo...',
|
|
151
154
|
'eidScannerScreen.completing': 'Finalizing verification...',
|
|
152
155
|
'eidScannerScreen.progress': 'Progress',
|
|
153
156
|
'identityDocumentCamera.guideHeader': 'Document Scan',
|
|
@@ -178,6 +181,8 @@ export default {
|
|
|
178
181
|
'identityDocumentCamera.hologramCheck': 'Hologram',
|
|
179
182
|
'identityDocumentCamera.keepSteady': 'Keep device steady',
|
|
180
183
|
'identityDocumentCamera.avoidBlur': 'Keep device steady',
|
|
184
|
+
'identityDocumentCamera.reduceGlare':
|
|
185
|
+
'Glare detected. Tilt the document or move away from direct light.',
|
|
181
186
|
'identityDocumentCamera.wrongSideFront':
|
|
182
187
|
'Show the front side of your document',
|
|
183
188
|
'identityDocumentCamera.wrongSideBack': 'Show the back side of your document',
|
|
@@ -143,12 +143,15 @@ export default {
|
|
|
143
143
|
'Pasaportunuzu NFC okuyucuya yaklaştırın',
|
|
144
144
|
'eidScannerScreen.placeDocumentOnNFC': 'Belgenizi NFC okuyucuya yaklaştırın',
|
|
145
145
|
'eidScannerScreen.readingDocument': 'Sabit tutun - Belge okunuyor',
|
|
146
|
+
'eidScannerScreen.keepStill':
|
|
147
|
+
'Okuma tamamlanana kadar belgeyi ve telefonu sabit tutun.',
|
|
146
148
|
'eidScannerScreen.checkYourInformation':
|
|
147
149
|
'Bilgilerinizi dikkatle kontrol edin',
|
|
148
150
|
'eidScannerScreen.approveAndContinue': 'Onayla ve Devam Et',
|
|
149
151
|
'eidScannerScreen.connecting': 'Güvenli bağlantı kuruluyor...',
|
|
150
152
|
'eidScannerScreen.readingMRZ': 'Belge bilgileri okunuyor...',
|
|
151
153
|
'eidScannerScreen.readingFaceImage': 'Fotoğraf verisi okunuyor...',
|
|
154
|
+
'eidScannerScreen.decodingFaceImage': 'Fotoğraf çözümleniyor...',
|
|
152
155
|
'eidScannerScreen.completing': 'Doğrulama tamamlanıyor...',
|
|
153
156
|
'eidScannerScreen.progress': 'İlerleme',
|
|
154
157
|
'identityDocumentCamera.guideHeader': 'Belge Taraması',
|
|
@@ -179,6 +182,8 @@ export default {
|
|
|
179
182
|
'identityDocumentCamera.hologramCheck': 'Hologram',
|
|
180
183
|
'identityDocumentCamera.keepSteady': 'Cihazı sabit tutun',
|
|
181
184
|
'identityDocumentCamera.avoidBlur': 'Cihazı sabit tutun',
|
|
185
|
+
'identityDocumentCamera.reduceGlare':
|
|
186
|
+
'Parlama algılandı. Belgeyi hafifçe eğin veya doğrudan ışıktan uzaklaşın.',
|
|
182
187
|
'identityDocumentCamera.wrongSideFront': 'Belgenizin ön yüzünü gösterin',
|
|
183
188
|
'identityDocumentCamera.wrongSideBack': 'Belgenizin arka yüzünü gösterin',
|
|
184
189
|
'identityDocumentCamera.idCardDetected': 'Kimlik kartı algılandı',
|
package/src/version.ts
CHANGED