@trustchex/react-native-sdk 1.361.0 → 1.362.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/TrustchexSDK.podspec +3 -1
- package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKPackage.kt +0 -13
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraManager.kt +0 -8
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +59 -39
- package/android/src/main/java/com/trustchex/reactnativesdk/opencv/OpenCVModule.kt +94 -13
- package/ios/Camera/TrustchexCameraManager.m +0 -2
- package/ios/Camera/TrustchexCameraManager.swift +0 -7
- package/ios/Camera/TrustchexCameraView.swift +16 -47
- package/ios/OpenCV/OpenCVHelper.h +17 -0
- package/ios/OpenCV/OpenCVHelper.mm +128 -0
- package/ios/OpenCV/OpenCVModule.h +6 -0
- package/ios/OpenCV/OpenCVModule.mm +141 -0
- package/ios/TrustchexSDK-Bridging-Header.h +8 -0
- package/lib/module/Screens/Debug/MRZTestScreen.js +175 -0
- package/lib/module/Shared/Components/DebugNavigationPanel.js +4 -0
- package/lib/module/Shared/Components/EIDScanner.js +0 -78
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +188 -150
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +0 -3
- package/lib/module/Shared/Libs/mrz.utils.js +265 -0
- package/lib/module/Trustchex.js +4 -0
- package/lib/module/index.js +1 -0
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts +3 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts +0 -19
- package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +18 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +2 -1
- package/src/Screens/Debug/MRZTestScreen.tsx +209 -0
- package/src/Shared/Components/DebugNavigationPanel.tsx +5 -0
- package/src/Shared/Components/EIDScanner.tsx +0 -53
- package/src/Shared/Components/IdentityDocumentCamera.tsx +228 -146
- package/src/Shared/Components/QrCodeScannerCamera.tsx +0 -9
- package/src/Shared/Components/TrustchexCamera.tsx +0 -20
- package/src/Shared/Libs/mrz.utils.ts +289 -1
- package/src/Trustchex.tsx +5 -0
- package/src/index.tsx +3 -0
- package/src/version.ts +1 -1
- package/android/src/main/java/com/trustchex/reactnativesdk/mrz/MRZValidationModule.kt +0 -785
- package/android/src/main/java/com/trustchex/reactnativesdk/mrz/MRZValidator.kt +0 -419
- package/ios/MRZValidation.m +0 -39
- package/ios/MRZValidation.swift +0 -802
- package/ios/MRZValidator.swift +0 -466
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
/* eslint-disable react-native/no-inline-styles */
|
|
4
4
|
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
|
5
|
-
import { View, StyleSheet, Text as TextView, Platform, StatusBar, Vibration, Linking, Image, ActivityIndicator, PermissionsAndroid, Dimensions } from 'react-native';
|
|
5
|
+
import { View, StyleSheet, Text as TextView, Platform, StatusBar, Vibration, Linking, Image, ActivityIndicator, PermissionsAndroid, Dimensions, ScrollView } from 'react-native';
|
|
6
6
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
7
7
|
import { TrustchexCamera } from "./TrustchexCamera.js";
|
|
8
8
|
import { NativeModules } from 'react-native';
|
|
9
|
+
import mrzUtils from "../Libs/mrz.utils.js";
|
|
9
10
|
import { useKeepAwake } from "../Libs/native-keep-awake.utils.js";
|
|
10
11
|
import { useIsFocused } from '@react-navigation/native';
|
|
11
12
|
import { useTranslation } from 'react-i18next';
|
|
@@ -28,7 +29,8 @@ const MIN_BRIGHTNESS_THRESHOLD = 45;
|
|
|
28
29
|
const MAX_CONSECUTIVE_QUALITY_FAILURES = 30;
|
|
29
30
|
const IdentityDocumentCamera = ({
|
|
30
31
|
onlyMRZScan,
|
|
31
|
-
onIdentityDocumentScanned
|
|
32
|
+
onIdentityDocumentScanned,
|
|
33
|
+
testMode = false
|
|
32
34
|
}) => {
|
|
33
35
|
useKeepAwake();
|
|
34
36
|
const theme = useTheme();
|
|
@@ -84,6 +86,9 @@ const IdentityDocumentCamera = ({
|
|
|
84
86
|
// Barcode caching - persist detected barcode across frames for reliability
|
|
85
87
|
const cachedBarcode = useRef(null);
|
|
86
88
|
|
|
89
|
+
// Test mode tracking
|
|
90
|
+
const [testModeData, setTestModeData] = useState(null);
|
|
91
|
+
|
|
87
92
|
// Helper to compare MRZ field values (ignore raw text variations)
|
|
88
93
|
const areMRZFieldsEqual = useCallback((fields1, fields2) => {
|
|
89
94
|
if (!fields1 || !fields2) return false;
|
|
@@ -355,7 +360,7 @@ const IdentityDocumentCamera = ({
|
|
|
355
360
|
}, 1000);
|
|
356
361
|
}
|
|
357
362
|
}, [setIsTorchOn]);
|
|
358
|
-
const handleFaceAndText = useCallback(async (text, faces, frameWidth, frameHeight, barcode, image, elementsOutside,
|
|
363
|
+
const handleFaceAndText = useCallback(async (text, faces, frameWidth, frameHeight, barcode, image, elementsOutside, scannedText) => {
|
|
359
364
|
const detectDocumentType = (facesParam, ocrText, mrzFields, frameWidthParam, mrzTextParam) => {
|
|
360
365
|
// Relaxed signature detection: matches signature/imza variants and OCR errors
|
|
361
366
|
const hasSignatureMatch = /s[gi]g?n[au]?t[u]?r|imz[a]s?/i.test(ocrText);
|
|
@@ -530,17 +535,44 @@ const IdentityDocumentCamera = ({
|
|
|
530
535
|
setStatus('SEARCHING');
|
|
531
536
|
return;
|
|
532
537
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
valid:
|
|
541
|
-
fields: null
|
|
538
|
+
|
|
539
|
+
// Use JavaScript MRZ validation with corrections
|
|
540
|
+
// Prefer MRZ-only text if available (from detected MRZ blocks),
|
|
541
|
+
// otherwise fall back to all text (for backward compatibility)
|
|
542
|
+
const textForValidation = scannedText?.mrzOnlyText || text;
|
|
543
|
+
const mrzValidationResult = mrzUtils.validateMRZWithCorrections(textForValidation);
|
|
544
|
+
const parsedMRZData = {
|
|
545
|
+
valid: mrzValidationResult.valid,
|
|
546
|
+
fields: mrzValidationResult.fields || null
|
|
542
547
|
};
|
|
543
|
-
|
|
548
|
+
|
|
549
|
+
// Capture test mode data
|
|
550
|
+
if (testMode && text && text.includes('<')) {
|
|
551
|
+
const mrzOnlyText = scannedText?.mrzOnlyText || text;
|
|
552
|
+
setTestModeData({
|
|
553
|
+
mrzText: mrzOnlyText,
|
|
554
|
+
timestamp: Date.now()
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Log MRZ validation details for debugging
|
|
559
|
+
if (isDebugEnabled() && text && text.includes('<')) {
|
|
560
|
+
const mrzLines = text.split('\n').filter(line => line.includes('<') && line.length > 20);
|
|
561
|
+
if (mrzLines.length >= 2) {
|
|
562
|
+
console.log('[MRZ Debug] Raw OCR text lines:', mrzLines.map(l => `"${l}"`));
|
|
563
|
+
console.log('[MRZ Debug] Validation result:', {
|
|
564
|
+
valid: mrzValidationResult.valid,
|
|
565
|
+
format: mrzValidationResult.format,
|
|
566
|
+
documentCode: mrzValidationResult.fields?.documentCode,
|
|
567
|
+
documentNumber: mrzValidationResult.fields?.documentNumber,
|
|
568
|
+
optional1: mrzValidationResult.fields?.optional1,
|
|
569
|
+
error: mrzValidationResult.error
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Extract raw MRZ lines from text if validation succeeded
|
|
575
|
+
const mrzText = parsedMRZData.valid ? mrzUtils.fixMRZ(text) : null;
|
|
544
576
|
|
|
545
577
|
// MRZ stability check - require consistent valid reads to avoid OCR noise
|
|
546
578
|
// Compare parsed field values instead of raw text to handle OCR variations in filler characters
|
|
@@ -609,9 +641,17 @@ const IdentityDocumentCamera = ({
|
|
|
609
641
|
// CRITICAL: Only accept MRZ with valid checksums AND consistent reads
|
|
610
642
|
// AND ensure all required fields are present
|
|
611
643
|
const mrzAccepted = parsedMRZData?.valid === true && hasRequiredFields && mrzStableAndValid;
|
|
644
|
+
|
|
645
|
+
// For Turkish ID cards, barcode should match MRZ optional1 (serial number)
|
|
646
|
+
// But some cards have encoding differences, so be lenient
|
|
612
647
|
const barcodeMatchesMRZ = barcodeToUse?.rawValue?.trim() === parsedMRZData?.fields?.optional1?.trim();
|
|
648
|
+
|
|
649
|
+
// If barcode doesn't match exactly, check if it contains the optional1 value
|
|
650
|
+
const barcodeContainsMRZ = barcodeToUse?.rawValue?.includes(parsedMRZData?.fields?.optional1?.trim() || '') || parsedMRZData?.fields?.optional1?.includes(barcodeToUse?.rawValue?.trim() || '');
|
|
651
|
+
|
|
613
652
|
// Require barcode for all documents (no special card fallback)
|
|
614
|
-
|
|
653
|
+
// Accept if exact match OR if one contains the other (handles encoding differences)
|
|
654
|
+
const barcodeAccepted = onlyMRZScan || barcodeMatchesMRZ || !!barcodeToUse?.rawValue && barcodeContainsMRZ;
|
|
615
655
|
|
|
616
656
|
// CRITICAL: Require all document elements to be in frame before accepting
|
|
617
657
|
// For ID_BACK: MRZ + barcode (check directly, not via state to avoid timing issues)
|
|
@@ -652,8 +692,11 @@ const IdentityDocumentCamera = ({
|
|
|
652
692
|
onlyMRZScan,
|
|
653
693
|
hasBarcodeValue: !!barcodeToUse?.rawValue,
|
|
654
694
|
barcodeMatchesMRZ,
|
|
695
|
+
barcodeContainsMRZ,
|
|
655
696
|
mrzOptional1: parsedMRZData?.fields?.optional1,
|
|
656
697
|
barcodeValue: barcodeToUse?.rawValue,
|
|
698
|
+
barcodeValueTrimmed: barcodeToUse?.rawValue?.trim(),
|
|
699
|
+
optional1Trimmed: parsedMRZData?.fields?.optional1?.trim(),
|
|
657
700
|
barcodeSource: barcodeToUse === cachedBarcode.current ? 'cached' : 'current'
|
|
658
701
|
});
|
|
659
702
|
}
|
|
@@ -1158,7 +1201,7 @@ const IdentityDocumentCamera = ({
|
|
|
1158
1201
|
}
|
|
1159
1202
|
setStatus('SCANNING');
|
|
1160
1203
|
}
|
|
1161
|
-
}, [nextStep, frameDimensions, currentHologramImage, currentFaceImage, hasRequiredMRZFields, areMRZFieldsEqual, detectedDocumentType, onlyMRZScan, isTorchOn, setIsTorchOn, setNextStepAndVibrate, onIdentityDocumentScanned, logMRZDetails, logMRZValidationFailure, currentSecondaryFaceImage, detectHologramNative]);
|
|
1204
|
+
}, [nextStep, frameDimensions, currentHologramImage, currentFaceImage, hasRequiredMRZFields, areMRZFieldsEqual, detectedDocumentType, onlyMRZScan, isTorchOn, setIsTorchOn, setNextStepAndVibrate, onIdentityDocumentScanned, logMRZDetails, logMRZValidationFailure, currentSecondaryFaceImage, detectHologramNative, mrzUtils]);
|
|
1162
1205
|
const handleFrame = useCallback(async event => {
|
|
1163
1206
|
if (!isCameraInitialized.current) {
|
|
1164
1207
|
return;
|
|
@@ -1253,6 +1296,8 @@ const IdentityDocumentCamera = ({
|
|
|
1253
1296
|
const resultText = textBlocks.map(b => b.text).join('\n');
|
|
1254
1297
|
const scannedText = {
|
|
1255
1298
|
resultText,
|
|
1299
|
+
mrzOnlyText: undefined,
|
|
1300
|
+
// Will be set below if MRZ blocks detected
|
|
1256
1301
|
blocks: textBlocks.map(block => ({
|
|
1257
1302
|
blockText: block.text || '',
|
|
1258
1303
|
blockFrame: block.blockFrame ?? {
|
|
@@ -1423,6 +1468,12 @@ const IdentityDocumentCamera = ({
|
|
|
1423
1468
|
const mrzBlocks = textBlocks.filter(block => block.blockFrame && block.blockFrame.y > bottomHalf && mrzPattern.test(block.text));
|
|
1424
1469
|
console.log('[Debug] MRZ blocks found:', mrzBlocks.length);
|
|
1425
1470
|
if (mrzBlocks.length > 0) {
|
|
1471
|
+
// Extract MRZ-only text from detected blocks (sorted by Y position for correct line order)
|
|
1472
|
+
const sortedMrzBlocks = [...mrzBlocks].sort((a, b) => (a.blockFrame?.y || 0) - (b.blockFrame?.y || 0));
|
|
1473
|
+
scannedText.mrzOnlyText = sortedMrzBlocks.map(b => b.text).join('\n');
|
|
1474
|
+
if (isDebugEnabled()) {
|
|
1475
|
+
console.log('[MRZ Extraction] Using only MRZ blocks:', scannedText.mrzOnlyText.substring(0, 100));
|
|
1476
|
+
}
|
|
1426
1477
|
const minX = Math.min(...mrzBlocks.map(b => b.blockFrame.x));
|
|
1427
1478
|
const minY = Math.min(...mrzBlocks.map(b => b.blockFrame.y));
|
|
1428
1479
|
const maxX = Math.max(...mrzBlocks.map(b => b.blockFrame.x + b.blockFrame.width));
|
|
@@ -1660,7 +1711,7 @@ const IdentityDocumentCamera = ({
|
|
|
1660
1711
|
}
|
|
1661
1712
|
}
|
|
1662
1713
|
setElementsOutsideScanArea(outsideElements);
|
|
1663
|
-
handleFaceAndText(scannedText.resultText ?? '', detectedFaces, frame.width, frame.height, barcodes.length ? barcodes[0] : undefined, base64Image, outsideElements.length > 0,
|
|
1714
|
+
handleFaceAndText(scannedText.resultText ?? '', detectedFaces, frame.width, frame.height, barcodes.length ? barcodes[0] : undefined, base64Image, outsideElements.length > 0, scannedText);
|
|
1664
1715
|
} catch (error) {
|
|
1665
1716
|
console.warn('Frame processing error:', error?.message);
|
|
1666
1717
|
}
|
|
@@ -1745,7 +1796,6 @@ const IdentityDocumentCamera = ({
|
|
|
1745
1796
|
enableFrameProcessing: isActive,
|
|
1746
1797
|
enableFaceDetection: isActive && faceDetectionEnabled,
|
|
1747
1798
|
enableTextRecognition: isActive,
|
|
1748
|
-
enableMrzValidation: isActive,
|
|
1749
1799
|
enableBarcodeScanning: isActive && nextStep === 'SCAN_ID_BACK',
|
|
1750
1800
|
includeBase64: isActive,
|
|
1751
1801
|
targetFps: 10,
|
|
@@ -2184,32 +2234,6 @@ const IdentityDocumentCamera = ({
|
|
|
2184
2234
|
}],
|
|
2185
2235
|
children: `${currentSecondaryFaceImage ? '✓ ' : ''}2nd Face`
|
|
2186
2236
|
})]
|
|
2187
|
-
}), isDebugEnabled() && /*#__PURE__*/_jsxs(View, {
|
|
2188
|
-
style: styles.imageContainer,
|
|
2189
|
-
children: [_currentHologramMaskImage ? /*#__PURE__*/_jsx(Image, {
|
|
2190
|
-
source: {
|
|
2191
|
-
uri: `data:image/jpeg;base64,${_currentHologramMaskImage}`
|
|
2192
|
-
},
|
|
2193
|
-
style: styles.faceImage
|
|
2194
|
-
}) : /*#__PURE__*/_jsx(View, {
|
|
2195
|
-
style: [styles.faceImage, {
|
|
2196
|
-
backgroundColor: '#333',
|
|
2197
|
-
justifyContent: 'center'
|
|
2198
|
-
}],
|
|
2199
|
-
children: /*#__PURE__*/_jsx(TextView, {
|
|
2200
|
-
style: {
|
|
2201
|
-
color: '#666',
|
|
2202
|
-
fontSize: 10,
|
|
2203
|
-
textAlign: 'center'
|
|
2204
|
-
},
|
|
2205
|
-
children: "Waiting..."
|
|
2206
|
-
})
|
|
2207
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2208
|
-
style: [styles.imageContainerText, _currentHologramMaskImage && {
|
|
2209
|
-
color: '#4CAF50'
|
|
2210
|
-
}],
|
|
2211
|
-
children: `${_currentHologramMaskImage ? '✓ ' : ''}Mask`
|
|
2212
|
-
})]
|
|
2213
2237
|
}), isDebugEnabled() && /*#__PURE__*/_jsxs(View, {
|
|
2214
2238
|
style: styles.imageContainer,
|
|
2215
2239
|
children: [currentHologramImage ? /*#__PURE__*/_jsx(Image, {
|
|
@@ -2269,31 +2293,30 @@ const IdentityDocumentCamera = ({
|
|
|
2269
2293
|
children: `${currentHologramImage ? '✓ ' : latestHologramFaceImage ? '⏳ ' : ''}Hologram`
|
|
2270
2294
|
})]
|
|
2271
2295
|
}), isDebugEnabled() && /*#__PURE__*/_jsxs(View, {
|
|
2272
|
-
style: styles.
|
|
2273
|
-
children: [/*#__PURE__*/_jsx(
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
style: styles.
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2292
|
-
style: styles.debugInfoText,
|
|
2293
|
-
children: `Brightness: ${isBrightnessLow ? '⚠️ LOW' : '✓ OK'}`
|
|
2296
|
+
style: styles.imageContainer,
|
|
2297
|
+
children: [_currentHologramMaskImage ? /*#__PURE__*/_jsx(Image, {
|
|
2298
|
+
source: {
|
|
2299
|
+
uri: `data:image/jpeg;base64,${_currentHologramMaskImage}`
|
|
2300
|
+
},
|
|
2301
|
+
style: styles.faceImage
|
|
2302
|
+
}) : /*#__PURE__*/_jsx(View, {
|
|
2303
|
+
style: [styles.faceImage, {
|
|
2304
|
+
backgroundColor: '#333',
|
|
2305
|
+
justifyContent: 'center'
|
|
2306
|
+
}],
|
|
2307
|
+
children: /*#__PURE__*/_jsx(TextView, {
|
|
2308
|
+
style: {
|
|
2309
|
+
color: '#666',
|
|
2310
|
+
fontSize: 10,
|
|
2311
|
+
textAlign: 'center'
|
|
2312
|
+
},
|
|
2313
|
+
children: "Waiting..."
|
|
2314
|
+
})
|
|
2294
2315
|
}), /*#__PURE__*/_jsx(TextView, {
|
|
2295
|
-
style: styles.
|
|
2296
|
-
|
|
2316
|
+
style: [styles.imageContainerText, _currentHologramMaskImage && {
|
|
2317
|
+
color: '#4CAF50'
|
|
2318
|
+
}],
|
|
2319
|
+
children: `${_currentHologramMaskImage ? '✓ ' : ''}Mask`
|
|
2297
2320
|
})]
|
|
2298
2321
|
})]
|
|
2299
2322
|
})
|
|
@@ -2323,98 +2346,123 @@ const IdentityDocumentCamera = ({
|
|
|
2323
2346
|
loop: true,
|
|
2324
2347
|
autoPlay: true
|
|
2325
2348
|
}) : null
|
|
2326
|
-
}), isDebugEnabled() && /*#__PURE__*/
|
|
2349
|
+
}), isDebugEnabled() && /*#__PURE__*/_jsx(SafeAreaView, {
|
|
2327
2350
|
style: {
|
|
2328
2351
|
position: 'absolute',
|
|
2329
|
-
top:
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
borderWidth: 1,
|
|
2335
|
-
borderColor: '#FF6B6B',
|
|
2336
|
-
maxWidth: 200
|
|
2352
|
+
top: 0,
|
|
2353
|
+
left: 0,
|
|
2354
|
+
right: 0,
|
|
2355
|
+
alignItems: 'center',
|
|
2356
|
+
pointerEvents: 'none'
|
|
2337
2357
|
},
|
|
2338
|
-
children:
|
|
2339
|
-
style: {
|
|
2340
|
-
color: '#FF6B6B',
|
|
2341
|
-
fontSize: 11,
|
|
2342
|
-
fontWeight: 'bold',
|
|
2343
|
-
marginBottom: 6
|
|
2344
|
-
},
|
|
2345
|
-
children: "\uD83D\uDC1B DEBUG MODE"
|
|
2346
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2347
|
-
style: {
|
|
2348
|
-
color: '#88D8B0',
|
|
2349
|
-
fontSize: 9,
|
|
2350
|
-
marginBottom: 2
|
|
2351
|
-
},
|
|
2352
|
-
children: `Step: ${nextStep}`
|
|
2353
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2354
|
-
style: {
|
|
2355
|
-
color: '#88D8B0',
|
|
2356
|
-
fontSize: 9,
|
|
2357
|
-
marginBottom: 2
|
|
2358
|
-
},
|
|
2359
|
-
children: `Status: ${status}`
|
|
2360
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2361
|
-
style: {
|
|
2362
|
-
color: '#88D8B0',
|
|
2363
|
-
fontSize: 9,
|
|
2364
|
-
marginBottom: 2
|
|
2365
|
-
},
|
|
2366
|
-
children: `Doc Type: ${detectedDocumentType}`
|
|
2367
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2358
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
2368
2359
|
style: {
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2360
|
+
marginTop: 10,
|
|
2361
|
+
backgroundColor: 'rgba(0, 0, 0, 0.85)',
|
|
2362
|
+
padding: 10,
|
|
2363
|
+
borderRadius: 8,
|
|
2364
|
+
borderWidth: 1,
|
|
2365
|
+
borderColor: '#FF6B6B',
|
|
2366
|
+
minWidth: 200
|
|
2372
2367
|
},
|
|
2373
|
-
children: `Face: ${currentFaceImage ? '✓' : '✗'}`
|
|
2374
|
-
}), !onlyMRZScan && /*#__PURE__*/_jsxs(_Fragment, {
|
|
2375
2368
|
children: [/*#__PURE__*/_jsx(TextView, {
|
|
2369
|
+
style: {
|
|
2370
|
+
color: '#FF6B6B',
|
|
2371
|
+
fontSize: 11,
|
|
2372
|
+
fontWeight: 'bold',
|
|
2373
|
+
marginBottom: 6,
|
|
2374
|
+
textAlign: 'center'
|
|
2375
|
+
},
|
|
2376
|
+
children: "DEBUG MODE"
|
|
2377
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2378
|
+
style: {
|
|
2379
|
+
color: '#88D8B0',
|
|
2380
|
+
fontSize: 9,
|
|
2381
|
+
marginBottom: 2
|
|
2382
|
+
},
|
|
2383
|
+
children: `Step: ${nextStep}`
|
|
2384
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2385
|
+
style: {
|
|
2386
|
+
color: '#88D8B0',
|
|
2387
|
+
fontSize: 9,
|
|
2388
|
+
marginBottom: 2
|
|
2389
|
+
},
|
|
2390
|
+
children: `Status: ${status}`
|
|
2391
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2392
|
+
style: {
|
|
2393
|
+
color: '#88D8B0',
|
|
2394
|
+
fontSize: 9,
|
|
2395
|
+
marginBottom: 2
|
|
2396
|
+
},
|
|
2397
|
+
children: `Doc Type: ${detectedDocumentType}`
|
|
2398
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2399
|
+
style: {
|
|
2400
|
+
color: '#88D8B0',
|
|
2401
|
+
fontSize: 9,
|
|
2402
|
+
marginBottom: 2
|
|
2403
|
+
},
|
|
2404
|
+
children: `Brightness: ${isBrightnessLow ? '⚠️ LOW' : '✓'}`
|
|
2405
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2376
2406
|
style: {
|
|
2377
2407
|
color: '#88D8B0',
|
|
2378
2408
|
fontSize: 9,
|
|
2379
2409
|
marginBottom: 2
|
|
2380
2410
|
},
|
|
2381
|
-
children: `
|
|
2411
|
+
children: `Blur: ${isFrameBlurry ? '⚠️' : '✓'}`
|
|
2382
2412
|
}), /*#__PURE__*/_jsx(TextView, {
|
|
2383
2413
|
style: {
|
|
2384
2414
|
color: '#88D8B0',
|
|
2385
2415
|
fontSize: 9,
|
|
2386
2416
|
marginBottom: 2
|
|
2387
2417
|
},
|
|
2388
|
-
children: `
|
|
2418
|
+
children: `Flash: ${isTorchOn ? '🔦' : '○'}`
|
|
2419
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2420
|
+
style: {
|
|
2421
|
+
color: '#88D8B0',
|
|
2422
|
+
fontSize: 9
|
|
2423
|
+
},
|
|
2424
|
+
children: `Face Detection: ${faceDetectionEnabled ? '✓' : '✗'}`
|
|
2389
2425
|
})]
|
|
2390
|
-
})
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
children: `Blur: ${isFrameBlurry ? '⚠️' : '✓'}`
|
|
2404
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2405
|
-
style: {
|
|
2406
|
-
color: '#88D8B0',
|
|
2407
|
-
fontSize: 9,
|
|
2408
|
-
marginBottom: 2
|
|
2409
|
-
},
|
|
2410
|
-
children: `Flash: ${isTorchOn ? '🔦' : '○'}`
|
|
2411
|
-
}), /*#__PURE__*/_jsx(TextView, {
|
|
2426
|
+
})
|
|
2427
|
+
}), testMode && testModeData && /*#__PURE__*/_jsx(SafeAreaView, {
|
|
2428
|
+
style: {
|
|
2429
|
+
position: 'absolute',
|
|
2430
|
+
bottom: 0,
|
|
2431
|
+
left: 0,
|
|
2432
|
+
right: 0,
|
|
2433
|
+
maxHeight: '40%',
|
|
2434
|
+
backgroundColor: 'rgba(0, 0, 0, 0.95)',
|
|
2435
|
+
borderTopWidth: 2,
|
|
2436
|
+
borderTopColor: '#FFA500'
|
|
2437
|
+
},
|
|
2438
|
+
children: /*#__PURE__*/_jsx(ScrollView, {
|
|
2412
2439
|
style: {
|
|
2413
|
-
|
|
2414
|
-
fontSize: 9
|
|
2440
|
+
flex: 1
|
|
2415
2441
|
},
|
|
2416
|
-
children:
|
|
2417
|
-
|
|
2442
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
2443
|
+
style: {
|
|
2444
|
+
padding: 10
|
|
2445
|
+
},
|
|
2446
|
+
children: [/*#__PURE__*/_jsx(TextView, {
|
|
2447
|
+
style: {
|
|
2448
|
+
color: '#FFA500',
|
|
2449
|
+
fontSize: 12,
|
|
2450
|
+
fontWeight: 'bold',
|
|
2451
|
+
marginBottom: 8,
|
|
2452
|
+
textAlign: 'center'
|
|
2453
|
+
},
|
|
2454
|
+
children: "MRZ Text Read"
|
|
2455
|
+
}), /*#__PURE__*/_jsx(TextView, {
|
|
2456
|
+
style: {
|
|
2457
|
+
color: '#FFFFFF',
|
|
2458
|
+
fontSize: 9,
|
|
2459
|
+
fontFamily: 'monospace',
|
|
2460
|
+
lineHeight: 16
|
|
2461
|
+
},
|
|
2462
|
+
children: testModeData.mrzText.split('\n').map((line, i) => `Line ${i + 1}: ${line} (${line.length} chars)`).join('\n')
|
|
2463
|
+
})]
|
|
2464
|
+
})
|
|
2465
|
+
})
|
|
2418
2466
|
})]
|
|
2419
2467
|
})]
|
|
2420
2468
|
});
|
|
@@ -2523,7 +2571,7 @@ const styles = StyleSheet.create({
|
|
|
2523
2571
|
display: 'flex',
|
|
2524
2572
|
flexDirection: 'row',
|
|
2525
2573
|
gap: 10,
|
|
2526
|
-
justifyContent: '
|
|
2574
|
+
justifyContent: 'center',
|
|
2527
2575
|
flexWrap: 'wrap'
|
|
2528
2576
|
},
|
|
2529
2577
|
cardDetectionRow: {
|
|
@@ -2563,16 +2611,6 @@ const styles = StyleSheet.create({
|
|
|
2563
2611
|
flexDirection: 'column',
|
|
2564
2612
|
alignItems: 'center'
|
|
2565
2613
|
},
|
|
2566
|
-
debugInfoContainer: {
|
|
2567
|
-
flex: 1,
|
|
2568
|
-
paddingLeft: 10
|
|
2569
|
-
},
|
|
2570
|
-
debugInfoText: {
|
|
2571
|
-
color: 'white',
|
|
2572
|
-
fontSize: 8,
|
|
2573
|
-
fontWeight: 'bold',
|
|
2574
|
-
marginBottom: 2
|
|
2575
|
-
},
|
|
2576
2614
|
guide: {
|
|
2577
2615
|
flex: 1,
|
|
2578
2616
|
display: 'flex',
|
|
@@ -39,12 +39,9 @@ const QrCodeScannerCamera = ({
|
|
|
39
39
|
right: width * (0.97 - marginBuffer),
|
|
40
40
|
bottom: height * (0.65 - marginBuffer)
|
|
41
41
|
};
|
|
42
|
-
console.log(`[QR Frame Check] Frame: ${width}x${height}, Scanning: left=${scanningFrame.left}, top=${scanningFrame.top}, right=${scanningFrame.right}, bottom=${scanningFrame.bottom}`);
|
|
43
|
-
console.log(`[QR Frame Check] Code bbox: left=${boundingBox.left}, top=${boundingBox.top}, right=${boundingBox.right}, bottom=${boundingBox.bottom}`);
|
|
44
42
|
|
|
45
43
|
// Check if entire bounding box is within scanning frame (with margin buffer)
|
|
46
44
|
const isInFrame = boundingBox.left >= scanningFrame.left && boundingBox.top >= scanningFrame.top && boundingBox.right <= scanningFrame.right && boundingBox.bottom <= scanningFrame.bottom;
|
|
47
|
-
console.log(`[QR Frame Check] Is in frame: ${isInFrame}`);
|
|
48
45
|
return isInFrame;
|
|
49
46
|
};
|
|
50
47
|
const handleFrame = useCallback(async event => {
|