@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.
Files changed (54) hide show
  1. package/TrustchexSDK.podspec +3 -1
  2. package/android/src/main/AndroidManifest.xml +1 -0
  3. package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKPackage.kt +0 -13
  4. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraManager.kt +0 -8
  5. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +60 -39
  6. package/android/src/main/java/com/trustchex/reactnativesdk/opencv/OpenCVModule.kt +94 -13
  7. package/ios/Camera/TrustchexCameraManager.m +0 -2
  8. package/ios/Camera/TrustchexCameraManager.swift +0 -7
  9. package/ios/Camera/TrustchexCameraView.swift +16 -47
  10. package/ios/OpenCV/OpenCVHelper.h +17 -0
  11. package/ios/OpenCV/OpenCVHelper.mm +128 -0
  12. package/ios/OpenCV/OpenCVModule.h +6 -0
  13. package/ios/OpenCV/OpenCVModule.mm +141 -0
  14. package/ios/TrustchexSDK-Bridging-Header.h +8 -0
  15. package/lib/module/Screens/Debug/MRZTestScreen.js +175 -0
  16. package/lib/module/Shared/Components/DebugNavigationPanel.js +4 -0
  17. package/lib/module/Shared/Components/EIDScanner.js +0 -78
  18. package/lib/module/Shared/Components/IdentityDocumentCamera.js +188 -150
  19. package/lib/module/Shared/Components/QrCodeScannerCamera.js +0 -3
  20. package/lib/module/Shared/Libs/mrz.utils.js +265 -0
  21. package/lib/module/Trustchex.js +4 -0
  22. package/lib/module/index.js +1 -0
  23. package/lib/module/version.js +1 -1
  24. package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts +3 -0
  25. package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -0
  26. package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -1
  27. package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
  28. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts +3 -1
  29. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  30. package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
  31. package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts +0 -19
  32. package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts.map +1 -1
  33. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +18 -1
  34. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
  35. package/lib/typescript/src/Trustchex.d.ts.map +1 -1
  36. package/lib/typescript/src/index.d.ts +3 -0
  37. package/lib/typescript/src/index.d.ts.map +1 -1
  38. package/lib/typescript/src/version.d.ts +1 -1
  39. package/package.json +2 -1
  40. package/src/Screens/Debug/MRZTestScreen.tsx +209 -0
  41. package/src/Shared/Components/DebugNavigationPanel.tsx +5 -0
  42. package/src/Shared/Components/EIDScanner.tsx +0 -53
  43. package/src/Shared/Components/IdentityDocumentCamera.tsx +228 -146
  44. package/src/Shared/Components/QrCodeScannerCamera.tsx +0 -9
  45. package/src/Shared/Components/TrustchexCamera.tsx +0 -20
  46. package/src/Shared/Libs/mrz.utils.ts +289 -1
  47. package/src/Trustchex.tsx +5 -0
  48. package/src/index.tsx +3 -0
  49. package/src/version.ts +1 -1
  50. package/android/src/main/java/com/trustchex/reactnativesdk/mrz/MRZValidationModule.kt +0 -785
  51. package/android/src/main/java/com/trustchex/reactnativesdk/mrz/MRZValidator.kt +0 -419
  52. package/ios/MRZValidation.m +0 -39
  53. package/ios/MRZValidation.swift +0 -802
  54. 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
- nativeMrzResult?: Frame['mrzResult']
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
- const parsedMRZData =
974
- nativeMrzResult?.valid && nativeMrzResult.documentCode
975
- ? { valid: true, fields: nativeMrzResult as MRZFields }
976
- : nativeMrzResult?.documentCode
977
- ? { valid: false, fields: nativeMrzResult as MRZFields }
978
- : { valid: false, fields: null };
979
- const mrzText = parsedMRZData.valid ? nativeMrzResult?.rawLines : null;
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
- const barcodeAccepted = onlyMRZScan || barcodeMatchesMRZ;
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
- frame.mrzResult
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.debugInfoContainer}>
3383
- <TextView style={styles.debugInfoText}>
3384
- {`Step: ${nextStep}`}
3385
- </TextView>
3386
- <TextView style={styles.debugInfoText}>
3387
- {`Status: ${status}`}
3388
- </TextView>
3389
- <TextView style={styles.debugInfoText}>
3390
- {`Face: ${currentFaceImage ? '✓ CAPTURED' : '✗ WAITING'} ${!faceDetectionEnabled ? '(DISABLED)' : ''}`}
3391
- </TextView>
3392
- <TextView style={styles.debugInfoText}>
3393
- {`Hologram: ${currentHologramImage ? '✓ CAPTURED' : `${hologramImageCount}/${HOLOGRAM_IMAGE_COUNT} imgs`} (retry ${hologramDetectionCurrentRetryCount.current}/${HOLOGRAM_DETECTION_RETRY_COUNT})`}
3394
- </TextView>
3395
- <TextView style={styles.debugInfoText}>
3396
- {`2nd Face: ${currentSecondaryFaceImage ? '✓ CAPTURED' : '✗ WAITING'} (retry ${secondaryFaceDetectionCurrentRetryCount.current}/${SECOND_FACE_DETECTION_RETRY_COUNT})`}
3397
- </TextView>
3398
- <TextView style={styles.debugInfoText}>
3399
- {`Flash: ${isTorchOn ? '🔦 ON' : '🔦 OFF'}`}
3400
- </TextView>
3401
- <TextView style={styles.debugInfoText}>
3402
- {`Brightness: ${isBrightnessLow ? '⚠️ LOW' : '✓ OK'}`}
3403
- </TextView>
3404
- <TextView style={styles.debugInfoText}>
3405
- {`Blur: ${isFrameBlurry ? '⚠️ BLURRY' : '✓ OK'}`}
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
- <View
3514
+ <SafeAreaView
3461
3515
  style={{
3462
3516
  position: 'absolute',
3463
- top: 10,
3464
- right: 10,
3465
- backgroundColor: 'rgba(0, 0, 0, 0.85)',
3466
- padding: 10,
3467
- borderRadius: 8,
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
- <TextView
3524
+ <View
3474
3525
  style={{
3475
- color: '#FF6B6B',
3476
- fontSize: 11,
3477
- fontWeight: 'bold',
3478
- marginBottom: 6,
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
- 🐛 DEBUG MODE
3482
- </TextView>
3483
- <TextView
3484
- style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
3485
- >
3486
- {`Step: ${nextStep}`}
3487
- </TextView>
3488
- <TextView
3489
- style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
3490
- >
3491
- {`Status: ${status}`}
3492
- </TextView>
3493
- <TextView
3494
- style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
3495
- >
3496
- {`Doc Type: ${detectedDocumentType}`}
3497
- </TextView>
3498
- <TextView
3499
- style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
3500
- >
3501
- {`Face: ${currentFaceImage ? '✓' : '✗'}`}
3502
- </TextView>
3503
- {!onlyMRZScan && (
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={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
3598
+ style={{
3599
+ color: '#FFA500',
3600
+ fontSize: 12,
3601
+ fontWeight: 'bold',
3602
+ marginBottom: 8,
3603
+ textAlign: 'center',
3604
+ }}
3507
3605
  >
3508
- {`2nd Face: ${currentSecondaryFaceImage ? '✓' : '✗'}`}
3606
+ MRZ Text Read
3509
3607
  </TextView>
3608
+
3510
3609
  <TextView
3511
- style={{ color: '#88D8B0', fontSize: 9, marginBottom: 2 }}
3610
+ style={{
3611
+ color: '#FFFFFF',
3612
+ fontSize: 9,
3613
+ fontFamily: 'monospace',
3614
+ lineHeight: 16,
3615
+ }}
3512
3616
  >
3513
- {`Hologram: ${hologramImageCount}/${HOLOGRAM_IMAGE_COUNT}`}
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
- <TextView
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: 'flex-start',
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?: (