@trustchex/react-native-sdk 1.361.0 → 1.362.1
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/AndroidManifest.xml +1 -0
- 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 +60 -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
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ActivityIndicator,
|
|
13
13
|
PermissionsAndroid,
|
|
14
14
|
Dimensions,
|
|
15
|
+
ScrollView,
|
|
15
16
|
type NativeSyntheticEvent,
|
|
16
17
|
type ViewStyle,
|
|
17
18
|
} from 'react-native';
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
} from './TrustchexCamera';
|
|
24
25
|
import { NativeModules } from 'react-native';
|
|
25
26
|
import type { MRZFields } from '../Types/mrzFields';
|
|
27
|
+
import mrzUtils from '../Libs/mrz.utils';
|
|
26
28
|
import { useKeepAwake } from '../Libs/native-keep-awake.utils';
|
|
27
29
|
import { useIsFocused } from '@react-navigation/native';
|
|
28
30
|
import { useTranslation } from 'react-i18next';
|
|
@@ -50,6 +52,7 @@ export type DocumentScannedData = {
|
|
|
50
52
|
export type BlockText = {
|
|
51
53
|
blocks: BlocksData[];
|
|
52
54
|
resultText: string;
|
|
55
|
+
mrzOnlyText?: string; // MRZ-specific text from detected MRZ blocks only
|
|
53
56
|
};
|
|
54
57
|
|
|
55
58
|
type BlocksData = {
|
|
@@ -97,6 +100,7 @@ export type PhotoOptions = {
|
|
|
97
100
|
export interface IdentityDocumentCameraProps {
|
|
98
101
|
onlyMRZScan: boolean;
|
|
99
102
|
onIdentityDocumentScanned: (scannedData: DocumentScannedData) => void;
|
|
103
|
+
testMode?: boolean;
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
interface Face {
|
|
@@ -128,6 +132,7 @@ const MAX_CONSECUTIVE_QUALITY_FAILURES = 30;
|
|
|
128
132
|
const IdentityDocumentCamera = ({
|
|
129
133
|
onlyMRZScan,
|
|
130
134
|
onIdentityDocumentScanned,
|
|
135
|
+
testMode = false,
|
|
131
136
|
}: IdentityDocumentCameraProps) => {
|
|
132
137
|
useKeepAwake();
|
|
133
138
|
const theme = useTheme();
|
|
@@ -201,6 +206,12 @@ const IdentityDocumentCamera = ({
|
|
|
201
206
|
// Barcode caching - persist detected barcode across frames for reliability
|
|
202
207
|
const cachedBarcode = useRef<Barcode | null>(null);
|
|
203
208
|
|
|
209
|
+
// Test mode tracking
|
|
210
|
+
const [testModeData, setTestModeData] = useState<{
|
|
211
|
+
mrzText: string;
|
|
212
|
+
timestamp: number;
|
|
213
|
+
} | null>(null);
|
|
214
|
+
|
|
204
215
|
// Helper to compare MRZ field values (ignore raw text variations)
|
|
205
216
|
const areMRZFieldsEqual = useCallback(
|
|
206
217
|
(fields1: any, fields2: any): boolean => {
|
|
@@ -699,7 +710,7 @@ const IdentityDocumentCamera = ({
|
|
|
699
710
|
barcode?: Barcode,
|
|
700
711
|
image?: string,
|
|
701
712
|
elementsOutside?: boolean,
|
|
702
|
-
|
|
713
|
+
scannedText?: BlockText
|
|
703
714
|
) => {
|
|
704
715
|
const detectDocumentType = (
|
|
705
716
|
facesParam: Face[],
|
|
@@ -970,13 +981,49 @@ const IdentityDocumentCamera = ({
|
|
|
970
981
|
return;
|
|
971
982
|
}
|
|
972
983
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
const
|
|
984
|
+
// Use JavaScript MRZ validation with corrections
|
|
985
|
+
// Prefer MRZ-only text if available (from detected MRZ blocks),
|
|
986
|
+
// otherwise fall back to all text (for backward compatibility)
|
|
987
|
+
const textForValidation = scannedText?.mrzOnlyText || text;
|
|
988
|
+
const mrzValidationResult =
|
|
989
|
+
mrzUtils.validateMRZWithCorrections(textForValidation);
|
|
990
|
+
const parsedMRZData = {
|
|
991
|
+
valid: mrzValidationResult.valid,
|
|
992
|
+
fields: mrzValidationResult.fields || null,
|
|
993
|
+
};
|
|
994
|
+
|
|
995
|
+
// Capture test mode data
|
|
996
|
+
if (testMode && text && text.includes('<')) {
|
|
997
|
+
const mrzOnlyText = scannedText?.mrzOnlyText || text;
|
|
998
|
+
setTestModeData({
|
|
999
|
+
mrzText: mrzOnlyText,
|
|
1000
|
+
timestamp: Date.now(),
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// Log MRZ validation details for debugging
|
|
1005
|
+
if (isDebugEnabled() && text && text.includes('<')) {
|
|
1006
|
+
const mrzLines = text
|
|
1007
|
+
.split('\n')
|
|
1008
|
+
.filter((line) => line.includes('<') && line.length > 20);
|
|
1009
|
+
if (mrzLines.length >= 2) {
|
|
1010
|
+
console.log(
|
|
1011
|
+
'[MRZ Debug] Raw OCR text lines:',
|
|
1012
|
+
mrzLines.map((l) => `"${l}"`)
|
|
1013
|
+
);
|
|
1014
|
+
console.log('[MRZ Debug] Validation result:', {
|
|
1015
|
+
valid: mrzValidationResult.valid,
|
|
1016
|
+
format: mrzValidationResult.format,
|
|
1017
|
+
documentCode: mrzValidationResult.fields?.documentCode,
|
|
1018
|
+
documentNumber: mrzValidationResult.fields?.documentNumber,
|
|
1019
|
+
optional1: mrzValidationResult.fields?.optional1,
|
|
1020
|
+
error: mrzValidationResult.error,
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// Extract raw MRZ lines from text if validation succeeded
|
|
1026
|
+
const mrzText = parsedMRZData.valid ? mrzUtils.fixMRZ(text) : null;
|
|
980
1027
|
|
|
981
1028
|
// MRZ stability check - require consistent valid reads to avoid OCR noise
|
|
982
1029
|
// Compare parsed field values instead of raw text to handle OCR variations in filler characters
|
|
@@ -1071,11 +1118,28 @@ const IdentityDocumentCamera = ({
|
|
|
1071
1118
|
parsedMRZData?.valid === true &&
|
|
1072
1119
|
hasRequiredFields &&
|
|
1073
1120
|
mrzStableAndValid;
|
|
1121
|
+
|
|
1122
|
+
// For Turkish ID cards, barcode should match MRZ optional1 (serial number)
|
|
1123
|
+
// But some cards have encoding differences, so be lenient
|
|
1074
1124
|
const barcodeMatchesMRZ =
|
|
1075
1125
|
barcodeToUse?.rawValue?.trim() ===
|
|
1076
1126
|
parsedMRZData?.fields?.optional1?.trim();
|
|
1127
|
+
|
|
1128
|
+
// If barcode doesn't match exactly, check if it contains the optional1 value
|
|
1129
|
+
const barcodeContainsMRZ =
|
|
1130
|
+
barcodeToUse?.rawValue?.includes(
|
|
1131
|
+
parsedMRZData?.fields?.optional1?.trim() || ''
|
|
1132
|
+
) ||
|
|
1133
|
+
parsedMRZData?.fields?.optional1?.includes(
|
|
1134
|
+
barcodeToUse?.rawValue?.trim() || ''
|
|
1135
|
+
);
|
|
1136
|
+
|
|
1077
1137
|
// Require barcode for all documents (no special card fallback)
|
|
1078
|
-
|
|
1138
|
+
// Accept if exact match OR if one contains the other (handles encoding differences)
|
|
1139
|
+
const barcodeAccepted =
|
|
1140
|
+
onlyMRZScan ||
|
|
1141
|
+
barcodeMatchesMRZ ||
|
|
1142
|
+
(!!barcodeToUse?.rawValue && barcodeContainsMRZ);
|
|
1079
1143
|
|
|
1080
1144
|
// CRITICAL: Require all document elements to be in frame before accepting
|
|
1081
1145
|
// For ID_BACK: MRZ + barcode (check directly, not via state to avoid timing issues)
|
|
@@ -1140,8 +1204,11 @@ const IdentityDocumentCamera = ({
|
|
|
1140
1204
|
onlyMRZScan,
|
|
1141
1205
|
hasBarcodeValue: !!barcodeToUse?.rawValue,
|
|
1142
1206
|
barcodeMatchesMRZ,
|
|
1207
|
+
barcodeContainsMRZ,
|
|
1143
1208
|
mrzOptional1: parsedMRZData?.fields?.optional1,
|
|
1144
1209
|
barcodeValue: barcodeToUse?.rawValue,
|
|
1210
|
+
barcodeValueTrimmed: barcodeToUse?.rawValue?.trim(),
|
|
1211
|
+
optional1Trimmed: parsedMRZData?.fields?.optional1?.trim(),
|
|
1145
1212
|
barcodeSource:
|
|
1146
1213
|
barcodeToUse === cachedBarcode.current
|
|
1147
1214
|
? 'cached'
|
|
@@ -1864,6 +1931,7 @@ const IdentityDocumentCamera = ({
|
|
|
1864
1931
|
logMRZValidationFailure,
|
|
1865
1932
|
currentSecondaryFaceImage,
|
|
1866
1933
|
detectHologramNative,
|
|
1934
|
+
mrzUtils,
|
|
1867
1935
|
]
|
|
1868
1936
|
);
|
|
1869
1937
|
|
|
@@ -1982,6 +2050,7 @@ const IdentityDocumentCamera = ({
|
|
|
1982
2050
|
const resultText = textBlocks.map((b) => b.text).join('\n');
|
|
1983
2051
|
const scannedText: BlockText = {
|
|
1984
2052
|
resultText,
|
|
2053
|
+
mrzOnlyText: undefined, // Will be set below if MRZ blocks detected
|
|
1985
2054
|
blocks: textBlocks.map((block) => ({
|
|
1986
2055
|
blockText: block.text || '',
|
|
1987
2056
|
blockFrame: block.blockFrame ?? {
|
|
@@ -2186,6 +2255,20 @@ const IdentityDocumentCamera = ({
|
|
|
2186
2255
|
|
|
2187
2256
|
console.log('[Debug] MRZ blocks found:', mrzBlocks.length);
|
|
2188
2257
|
if (mrzBlocks.length > 0) {
|
|
2258
|
+
// Extract MRZ-only text from detected blocks (sorted by Y position for correct line order)
|
|
2259
|
+
const sortedMrzBlocks = [...mrzBlocks].sort(
|
|
2260
|
+
(a, b) => (a.blockFrame?.y || 0) - (b.blockFrame?.y || 0)
|
|
2261
|
+
);
|
|
2262
|
+
scannedText.mrzOnlyText = sortedMrzBlocks
|
|
2263
|
+
.map((b) => b.text)
|
|
2264
|
+
.join('\n');
|
|
2265
|
+
if (isDebugEnabled()) {
|
|
2266
|
+
console.log(
|
|
2267
|
+
'[MRZ Extraction] Using only MRZ blocks:',
|
|
2268
|
+
scannedText.mrzOnlyText.substring(0, 100)
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2189
2272
|
const minX = Math.min(...mrzBlocks.map((b) => b.blockFrame!.x));
|
|
2190
2273
|
const minY = Math.min(...mrzBlocks.map((b) => b.blockFrame!.y));
|
|
2191
2274
|
const maxX = Math.max(
|
|
@@ -2520,7 +2603,7 @@ const IdentityDocumentCamera = ({
|
|
|
2520
2603
|
barcodes.length ? barcodes[0] : undefined,
|
|
2521
2604
|
base64Image,
|
|
2522
2605
|
outsideElements.length > 0,
|
|
2523
|
-
|
|
2606
|
+
scannedText
|
|
2524
2607
|
);
|
|
2525
2608
|
} catch (error: any) {
|
|
2526
2609
|
console.warn('Frame processing error:', error?.message);
|
|
@@ -2626,7 +2709,6 @@ const IdentityDocumentCamera = ({
|
|
|
2626
2709
|
enableFrameProcessing={isActive}
|
|
2627
2710
|
enableFaceDetection={isActive && faceDetectionEnabled}
|
|
2628
2711
|
enableTextRecognition={isActive}
|
|
2629
|
-
enableMrzValidation={isActive}
|
|
2630
2712
|
enableBarcodeScanning={isActive && nextStep === 'SCAN_ID_BACK'}
|
|
2631
2713
|
includeBase64={isActive}
|
|
2632
2714
|
targetFps={10}
|
|
@@ -3272,43 +3354,6 @@ const IdentityDocumentCamera = ({
|
|
|
3272
3354
|
</TextView>
|
|
3273
3355
|
</View>
|
|
3274
3356
|
)}
|
|
3275
|
-
{isDebugEnabled() && (
|
|
3276
|
-
<View style={styles.imageContainer}>
|
|
3277
|
-
{_currentHologramMaskImage ? (
|
|
3278
|
-
<Image
|
|
3279
|
-
source={{
|
|
3280
|
-
uri: `data:image/jpeg;base64,${_currentHologramMaskImage}`,
|
|
3281
|
-
}}
|
|
3282
|
-
style={styles.faceImage}
|
|
3283
|
-
/>
|
|
3284
|
-
) : (
|
|
3285
|
-
<View
|
|
3286
|
-
style={[
|
|
3287
|
-
styles.faceImage,
|
|
3288
|
-
{ backgroundColor: '#333', justifyContent: 'center' },
|
|
3289
|
-
]}
|
|
3290
|
-
>
|
|
3291
|
-
<TextView
|
|
3292
|
-
style={{
|
|
3293
|
-
color: '#666',
|
|
3294
|
-
fontSize: 10,
|
|
3295
|
-
textAlign: 'center',
|
|
3296
|
-
}}
|
|
3297
|
-
>
|
|
3298
|
-
Waiting...
|
|
3299
|
-
</TextView>
|
|
3300
|
-
</View>
|
|
3301
|
-
)}
|
|
3302
|
-
<TextView
|
|
3303
|
-
style={[
|
|
3304
|
-
styles.imageContainerText,
|
|
3305
|
-
_currentHologramMaskImage && { color: '#4CAF50' },
|
|
3306
|
-
]}
|
|
3307
|
-
>
|
|
3308
|
-
{`${_currentHologramMaskImage ? '✓ ' : ''}Mask`}
|
|
3309
|
-
</TextView>
|
|
3310
|
-
</View>
|
|
3311
|
-
)}
|
|
3312
3357
|
{isDebugEnabled() && (
|
|
3313
3358
|
<View style={styles.imageContainer}>
|
|
3314
3359
|
{currentHologramImage ? (
|
|
@@ -3379,30 +3424,39 @@ const IdentityDocumentCamera = ({
|
|
|
3379
3424
|
</View>
|
|
3380
3425
|
)}
|
|
3381
3426
|
{isDebugEnabled() && (
|
|
3382
|
-
<View style={styles.
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3427
|
+
<View style={styles.imageContainer}>
|
|
3428
|
+
{_currentHologramMaskImage ? (
|
|
3429
|
+
<Image
|
|
3430
|
+
source={{
|
|
3431
|
+
uri: `data:image/jpeg;base64,${_currentHologramMaskImage}`,
|
|
3432
|
+
}}
|
|
3433
|
+
style={styles.faceImage}
|
|
3434
|
+
/>
|
|
3435
|
+
) : (
|
|
3436
|
+
<View
|
|
3437
|
+
style={[
|
|
3438
|
+
styles.faceImage,
|
|
3439
|
+
{ backgroundColor: '#333', justifyContent: 'center' },
|
|
3440
|
+
]}
|
|
3441
|
+
>
|
|
3442
|
+
<TextView
|
|
3443
|
+
style={{
|
|
3444
|
+
color: '#666',
|
|
3445
|
+
fontSize: 10,
|
|
3446
|
+
textAlign: 'center',
|
|
3447
|
+
}}
|
|
3448
|
+
>
|
|
3449
|
+
Waiting...
|
|
3450
|
+
</TextView>
|
|
3451
|
+
</View>
|
|
3452
|
+
)}
|
|
3453
|
+
<TextView
|
|
3454
|
+
style={[
|
|
3455
|
+
styles.imageContainerText,
|
|
3456
|
+
_currentHologramMaskImage && { color: '#4CAF50' },
|
|
3457
|
+
]}
|
|
3458
|
+
>
|
|
3459
|
+
{`${_currentHologramMaskImage ? '✓ ' : ''}Mask`}
|
|
3406
3460
|
</TextView>
|
|
3407
3461
|
</View>
|
|
3408
3462
|
)}
|
|
@@ -3457,82 +3511,120 @@ const IdentityDocumentCamera = ({
|
|
|
3457
3511
|
) : null}
|
|
3458
3512
|
</View>
|
|
3459
3513
|
{isDebugEnabled() && (
|
|
3460
|
-
<
|
|
3514
|
+
<SafeAreaView
|
|
3461
3515
|
style={{
|
|
3462
3516
|
position: 'absolute',
|
|
3463
|
-
top:
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
borderWidth: 1,
|
|
3469
|
-
borderColor: '#FF6B6B',
|
|
3470
|
-
maxWidth: 200,
|
|
3517
|
+
top: 0,
|
|
3518
|
+
left: 0,
|
|
3519
|
+
right: 0,
|
|
3520
|
+
alignItems: 'center',
|
|
3521
|
+
pointerEvents: 'none',
|
|
3471
3522
|
}}
|
|
3472
3523
|
>
|
|
3473
|
-
<
|
|
3524
|
+
<View
|
|
3474
3525
|
style={{
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3526
|
+
marginTop: 10,
|
|
3527
|
+
backgroundColor: 'rgba(0, 0, 0, 0.85)',
|
|
3528
|
+
padding: 10,
|
|
3529
|
+
borderRadius: 8,
|
|
3530
|
+
borderWidth: 1,
|
|
3531
|
+
borderColor: '#FF6B6B',
|
|
3532
|
+
minWidth: 200,
|
|
3479
3533
|
}}
|
|
3480
3534
|
>
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3535
|
+
<TextView
|
|
3536
|
+
style={{
|
|
3537
|
+
color: '#FF6B6B',
|
|
3538
|
+
fontSize: 11,
|
|
3539
|
+
fontWeight: 'bold',
|
|
3540
|
+
marginBottom: 6,
|
|
3541
|
+
textAlign: 'center',
|
|
3542
|
+
}}
|
|
3543
|
+
>
|
|
3544
|
+
DEBUG MODE
|
|
3545
|
+
</TextView>
|
|
3546
|
+
<TextView
|
|
3547
|
+
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3548
|
+
>
|
|
3549
|
+
{`Step: ${nextStep}`}
|
|
3550
|
+
</TextView>
|
|
3551
|
+
<TextView
|
|
3552
|
+
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3553
|
+
>
|
|
3554
|
+
{`Status: ${status}`}
|
|
3555
|
+
</TextView>
|
|
3556
|
+
<TextView
|
|
3557
|
+
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3558
|
+
>
|
|
3559
|
+
{`Doc Type: ${detectedDocumentType}`}
|
|
3560
|
+
</TextView>
|
|
3561
|
+
<TextView
|
|
3562
|
+
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3563
|
+
>
|
|
3564
|
+
{`Brightness: ${isBrightnessLow ? '⚠️ LOW' : '✓'}`}
|
|
3565
|
+
</TextView>
|
|
3566
|
+
<TextView
|
|
3567
|
+
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3568
|
+
>
|
|
3569
|
+
{`Blur: ${isFrameBlurry ? '⚠️' : '✓'}`}
|
|
3570
|
+
</TextView>
|
|
3571
|
+
<TextView
|
|
3572
|
+
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3573
|
+
>
|
|
3574
|
+
{`Flash: ${isTorchOn ? '🔦' : '○'}`}
|
|
3575
|
+
</TextView>
|
|
3576
|
+
<TextView style={{ color: '#88D8B0', fontSize: 9 }}>
|
|
3577
|
+
{`Face Detection: ${faceDetectionEnabled ? '✓' : '✗'}`}
|
|
3578
|
+
</TextView>
|
|
3579
|
+
</View>
|
|
3580
|
+
</SafeAreaView>
|
|
3581
|
+
)}
|
|
3582
|
+
{testMode && testModeData && (
|
|
3583
|
+
<SafeAreaView
|
|
3584
|
+
style={{
|
|
3585
|
+
position: 'absolute',
|
|
3586
|
+
bottom: 0,
|
|
3587
|
+
left: 0,
|
|
3588
|
+
right: 0,
|
|
3589
|
+
maxHeight: '40%',
|
|
3590
|
+
backgroundColor: 'rgba(0, 0, 0, 0.95)',
|
|
3591
|
+
borderTopWidth: 2,
|
|
3592
|
+
borderTopColor: '#FFA500',
|
|
3593
|
+
}}
|
|
3594
|
+
>
|
|
3595
|
+
<ScrollView style={{ flex: 1 }}>
|
|
3596
|
+
<View style={{ padding: 10 }}>
|
|
3505
3597
|
<TextView
|
|
3506
|
-
style={{
|
|
3598
|
+
style={{
|
|
3599
|
+
color: '#FFA500',
|
|
3600
|
+
fontSize: 12,
|
|
3601
|
+
fontWeight: 'bold',
|
|
3602
|
+
marginBottom: 8,
|
|
3603
|
+
textAlign: 'center',
|
|
3604
|
+
}}
|
|
3507
3605
|
>
|
|
3508
|
-
|
|
3606
|
+
MRZ Text Read
|
|
3509
3607
|
</TextView>
|
|
3608
|
+
|
|
3510
3609
|
<TextView
|
|
3511
|
-
style={{
|
|
3610
|
+
style={{
|
|
3611
|
+
color: '#FFFFFF',
|
|
3612
|
+
fontSize: 9,
|
|
3613
|
+
fontFamily: 'monospace',
|
|
3614
|
+
lineHeight: 16,
|
|
3615
|
+
}}
|
|
3512
3616
|
>
|
|
3513
|
-
{
|
|
3617
|
+
{testModeData.mrzText
|
|
3618
|
+
.split('\n')
|
|
3619
|
+
.map(
|
|
3620
|
+
(line, i) =>
|
|
3621
|
+
`Line ${i + 1}: ${line} (${line.length} chars)`
|
|
3622
|
+
)
|
|
3623
|
+
.join('\n')}
|
|
3514
3624
|
</TextView>
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3519
|
-
>
|
|
3520
|
-
{`Brightness: ${isBrightnessLow ? '⚠️ LOW' : '✓'}`}
|
|
3521
|
-
</TextView>
|
|
3522
|
-
<TextView
|
|
3523
|
-
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3524
|
-
>
|
|
3525
|
-
{`Blur: ${isFrameBlurry ? '⚠️' : '✓'}`}
|
|
3526
|
-
</TextView>
|
|
3527
|
-
<TextView
|
|
3528
|
-
style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
|
|
3529
|
-
>
|
|
3530
|
-
{`Flash: ${isTorchOn ? '🔦' : '○'}`}
|
|
3531
|
-
</TextView>
|
|
3532
|
-
<TextView style={{ color: '#88D8B0', fontSize: 9 }}>
|
|
3533
|
-
{`Face Detection: ${faceDetectionEnabled ? '✓' : '✗'}`}
|
|
3534
|
-
</TextView>
|
|
3535
|
-
</View>
|
|
3625
|
+
</View>
|
|
3626
|
+
</ScrollView>
|
|
3627
|
+
</SafeAreaView>
|
|
3536
3628
|
)}
|
|
3537
3629
|
</>
|
|
3538
3630
|
)}
|
|
@@ -3644,7 +3736,7 @@ const styles = StyleSheet.create({
|
|
|
3644
3736
|
display: 'flex',
|
|
3645
3737
|
flexDirection: 'row',
|
|
3646
3738
|
gap: 10,
|
|
3647
|
-
justifyContent: '
|
|
3739
|
+
justifyContent: 'center',
|
|
3648
3740
|
flexWrap: 'wrap',
|
|
3649
3741
|
},
|
|
3650
3742
|
cardDetectionRow: {
|
|
@@ -3684,16 +3776,6 @@ const styles = StyleSheet.create({
|
|
|
3684
3776
|
flexDirection: 'column',
|
|
3685
3777
|
alignItems: 'center',
|
|
3686
3778
|
},
|
|
3687
|
-
debugInfoContainer: {
|
|
3688
|
-
flex: 1,
|
|
3689
|
-
paddingLeft: 10,
|
|
3690
|
-
},
|
|
3691
|
-
debugInfoText: {
|
|
3692
|
-
color: 'white',
|
|
3693
|
-
fontSize: 8,
|
|
3694
|
-
fontWeight: 'bold',
|
|
3695
|
-
marginBottom: 2,
|
|
3696
|
-
},
|
|
3697
3779
|
guide: {
|
|
3698
3780
|
flex: 1,
|
|
3699
3781
|
display: 'flex',
|
|
@@ -61,13 +61,6 @@ const QrCodeScannerCamera = ({
|
|
|
61
61
|
bottom: height * (0.65 - marginBuffer),
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
console.log(
|
|
65
|
-
`[QR Frame Check] Frame: ${width}x${height}, Scanning: left=${scanningFrame.left}, top=${scanningFrame.top}, right=${scanningFrame.right}, bottom=${scanningFrame.bottom}`
|
|
66
|
-
);
|
|
67
|
-
console.log(
|
|
68
|
-
`[QR Frame Check] Code bbox: left=${boundingBox.left}, top=${boundingBox.top}, right=${boundingBox.right}, bottom=${boundingBox.bottom}`
|
|
69
|
-
);
|
|
70
|
-
|
|
71
64
|
// Check if entire bounding box is within scanning frame (with margin buffer)
|
|
72
65
|
const isInFrame =
|
|
73
66
|
boundingBox.left >= scanningFrame.left &&
|
|
@@ -75,8 +68,6 @@ const QrCodeScannerCamera = ({
|
|
|
75
68
|
boundingBox.right <= scanningFrame.right &&
|
|
76
69
|
boundingBox.bottom <= scanningFrame.bottom;
|
|
77
70
|
|
|
78
|
-
console.log(`[QR Frame Check] Is in frame: ${isInFrame}`);
|
|
79
|
-
|
|
80
71
|
return isInFrame;
|
|
81
72
|
};
|
|
82
73
|
|
|
@@ -63,7 +63,6 @@ export interface Frame {
|
|
|
63
63
|
textBlocks?: NativeTextBlock[];
|
|
64
64
|
resultText?: string;
|
|
65
65
|
barcodes?: NativeBarcode[];
|
|
66
|
-
mrzResult?: NativeMRZResult;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
export interface NativeFace {
|
|
@@ -97,24 +96,6 @@ export interface NativeBarcode {
|
|
|
97
96
|
cornerPoints?: Array<{ x: number; y: number }>;
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
export interface NativeMRZResult {
|
|
101
|
-
valid: boolean;
|
|
102
|
-
format: string;
|
|
103
|
-
error?: string;
|
|
104
|
-
documentCode?: string;
|
|
105
|
-
issuingState?: string;
|
|
106
|
-
documentNumber?: string;
|
|
107
|
-
lastName?: string;
|
|
108
|
-
firstName?: string;
|
|
109
|
-
birthDate?: string;
|
|
110
|
-
sex?: string;
|
|
111
|
-
expirationDate?: string;
|
|
112
|
-
nationality?: string;
|
|
113
|
-
optional1?: string;
|
|
114
|
-
optional2?: string;
|
|
115
|
-
rawLines?: string;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
99
|
interface TrustchexCameraProps {
|
|
119
100
|
style?: StyleProp<ViewStyle>;
|
|
120
101
|
cameraType?: 'front' | 'back';
|
|
@@ -125,7 +106,6 @@ interface TrustchexCameraProps {
|
|
|
125
106
|
enableFaceDetection?: boolean;
|
|
126
107
|
enableTextRecognition?: boolean;
|
|
127
108
|
enableBarcodeScanning?: boolean;
|
|
128
|
-
enableMrzValidation?: boolean;
|
|
129
109
|
includeBase64?: boolean;
|
|
130
110
|
onFrameAvailable?: (event: NativeSyntheticEvent<{ frame: Frame }>) => void;
|
|
131
111
|
onCameraReady?: (
|