@trustchex/react-native-sdk 1.362.6 → 1.381.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/TrustchexSDK.podspec +3 -3
  2. package/android/build.gradle +3 -3
  3. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +64 -19
  4. package/android/src/main/java/com/trustchex/reactnativesdk/opencv/OpenCVModule.kt +636 -301
  5. package/ios/Camera/TrustchexCameraView.swift +166 -119
  6. package/ios/OpenCV/OpenCVHelper.h +0 -7
  7. package/ios/OpenCV/OpenCVHelper.mm +0 -60
  8. package/ios/OpenCV/OpenCVModule.h +0 -4
  9. package/ios/OpenCV/OpenCVModule.mm +440 -358
  10. package/lib/module/Shared/Components/DebugOverlay.js +541 -0
  11. package/lib/module/Shared/Components/FaceCamera.js +1 -0
  12. package/lib/module/Shared/Components/IdentityDocumentCamera.constants.js +44 -0
  13. package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +270 -0
  14. package/lib/module/Shared/Components/IdentityDocumentCamera.js +708 -1593
  15. package/lib/module/Shared/Components/IdentityDocumentCamera.types.js +3 -0
  16. package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +273 -0
  17. package/lib/module/Shared/Components/QrCodeScannerCamera.js +1 -8
  18. package/lib/module/Shared/Libs/mrz.utils.js +202 -9
  19. package/lib/module/Translation/Resources/en.js +0 -4
  20. package/lib/module/Translation/Resources/tr.js +0 -4
  21. package/lib/module/version.js +1 -1
  22. package/lib/typescript/src/Shared/Components/DebugOverlay.d.ts +30 -0
  23. package/lib/typescript/src/Shared/Components/DebugOverlay.d.ts.map +1 -0
  24. package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
  25. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.constants.d.ts +35 -0
  26. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.constants.d.ts.map +1 -0
  27. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts +3 -56
  28. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  29. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +88 -0
  30. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -0
  31. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.types.d.ts +116 -0
  32. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.types.d.ts.map +1 -0
  33. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +93 -0
  34. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -0
  35. package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
  36. package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts +1 -0
  37. package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts.map +1 -1
  38. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +8 -0
  39. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
  40. package/lib/typescript/src/Translation/Resources/en.d.ts +0 -4
  41. package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
  42. package/lib/typescript/src/Translation/Resources/tr.d.ts +0 -4
  43. package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
  44. package/lib/typescript/src/version.d.ts +1 -1
  45. package/package.json +1 -1
  46. package/src/Shared/Components/DebugOverlay.tsx +656 -0
  47. package/src/Shared/Components/FaceCamera.tsx +1 -0
  48. package/src/Shared/Components/IdentityDocumentCamera.constants.ts +44 -0
  49. package/src/Shared/Components/IdentityDocumentCamera.flows.ts +342 -0
  50. package/src/Shared/Components/IdentityDocumentCamera.tsx +1105 -2324
  51. package/src/Shared/Components/IdentityDocumentCamera.types.ts +136 -0
  52. package/src/Shared/Components/IdentityDocumentCamera.utils.ts +364 -0
  53. package/src/Shared/Components/QrCodeScannerCamera.tsx +1 -9
  54. package/src/Shared/Components/TrustchexCamera.tsx +1 -0
  55. package/src/Shared/Libs/mrz.utils.ts +238 -26
  56. package/src/Translation/Resources/en.ts +0 -4
  57. package/src/Translation/Resources/tr.ts +0 -4
  58. package/src/version.ts +1 -1
@@ -19,9 +19,9 @@ Pod::Spec.new do |s|
19
19
  s.public_header_files = "ios/OpenCV/OpenCVHelper.h"
20
20
 
21
21
  # ML Kit dependencies
22
- s.dependency "GoogleMLKit/TextRecognition"
23
- s.dependency "GoogleMLKit/FaceDetection"
24
- s.dependency "GoogleMLKit/BarcodeScanning"
22
+ s.dependency "GoogleMLKit/TextRecognition", "~> 9.0"
23
+ s.dependency "GoogleMLKit/FaceDetection", "~> 9.0"
24
+ s.dependency "GoogleMLKit/BarcodeScanning", "~> 9.0"
25
25
 
26
26
  # OpenCV dependency
27
27
  s.dependency "OpenCV", "~> 4.3.0"
@@ -83,9 +83,9 @@ dependencies {
83
83
  implementation "androidx.camera:camera-video:1.4.0"
84
84
 
85
85
  // Google ML Kit dependencies
86
- implementation 'com.google.mlkit:text-recognition:16.0.1'
87
- implementation 'com.google.mlkit:face-detection:16.1.7'
88
- implementation 'com.google.mlkit:barcode-scanning:17.3.0'
86
+ implementation 'com.google.mlkit:text-recognition:16.0.0'
87
+ implementation 'com.google.mlkit:face-detection:16.1.5'
88
+ implementation 'com.google.mlkit:barcode-scanning:17.1.0'
89
89
 
90
90
  // Google Play Services dependency for Tasks
91
91
  implementation 'com.google.android.gms:play-services-tasks:18.2.0'
@@ -44,10 +44,10 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
44
44
  // ==================================================================================
45
45
  // PORTRAIT-ONLY CAMERA VIEW
46
46
  // All camera use cases are locked to ROTATION_0 (portrait) orientation.
47
- // Preview: 720x1280 (Portrait HD)
48
- // ImageAnalysis: 720x1280 (Portrait HD for ML Kit)
49
- // ImageCapture: 720x1280 (Portrait HD for frame capture during recording)
50
- // VideoCapture: Quality.HD (CameraX auto-selects portrait HD resolution)
47
+ // Supports two resolutions:
48
+ // - HD: 720x1280 (portrait HD) - lower bandwidth, faster processing
49
+ // - Full HD: 1080x1920 (portrait Full HD, default) - sharp text/document capture
50
+ // Selection criteria: use Full HD for document scanning, HD for real-time detection
51
51
  // Activity must be locked to portrait in AndroidManifest.xml
52
52
  // ==================================================================================
53
53
 
@@ -69,6 +69,7 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
69
69
  private var torchEnabled = false
70
70
  private var frameProcessingEnabled = false
71
71
  private var targetFps = 10
72
+ private var resolution = "fullhd" // "hd" (720x1280) or "fullhd" (1080x1920, default)
72
73
  private var isCameraInitialized = false
73
74
  private var isStoppingRecording = false // Track if stopRecording was called to prevent cancelRecording from deleting the file
74
75
 
@@ -80,6 +81,8 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
80
81
 
81
82
  // ML Kit detector instances (lazy, created once)
82
83
  private val textRecognizer by lazy {
84
+ // Use DEFAULT_OPTIONS for best accuracy with Latin scripts (including MRZ)
85
+ // ML Kit Text Recognition v2 provides superior accuracy for document scanning
83
86
  TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)
84
87
  }
85
88
  private val faceDetector by lazy {
@@ -202,6 +205,14 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
202
205
  targetFps = fps.coerceIn(1, 30)
203
206
  }
204
207
 
208
+ fun setResolution(res: String) {
209
+ // Accept "hd" or "fullhd" (default "fullhd" for 1080x1920)
210
+ resolution = if (res.lowercase() == "hd") "hd" else "fullhd"
211
+ if (isCameraInitialized) {
212
+ initializeCamera()
213
+ }
214
+ }
215
+
205
216
  fun setFaceDetectionEnabled(enabled: Boolean) {
206
217
  faceDetectionEnabled = enabled
207
218
  }
@@ -238,14 +249,12 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
238
249
  provider.unbindAll()
239
250
 
240
251
  try {
241
- // Determine resolution based on camera type
242
- // Front camera (liveness): HD (720x1280) for optimal performance
243
- // Back camera (documents): Full HD (1080x1920) for sharp document capture
244
- val isFrontCamera = cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA
245
- val targetResolution = if (isFrontCamera) {
246
- Size(720, 1280) // Portrait HD for front camera
247
- } else {
248
- Size(1080, 1920) // Portrait Full HD for back camera
252
+ // Determine resolution based on configured resolution setting
253
+ // "hd": 720x1280 (lower bandwidth, faster processing)
254
+ // "fullhd": 1080x1920 (default - sharp text/document capture)
255
+ val targetResolution = when (resolution.lowercase()) {
256
+ "hd" -> Size(720, 1280) // Portrait HD
257
+ else -> Size(1080, 1920) // Portrait Full HD (default)
249
258
  }
250
259
 
251
260
  // Preview use case
@@ -273,9 +282,13 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
273
282
  // Removing it allows us to bind VideoCapture + Analyzer + Preview simultaneously
274
283
  // within the 3-use-case limit of many Android devices.
275
284
 
276
- // Video capture use case — PORTRAIT HD
285
+ // Video capture use case — select quality based on resolution setting
286
+ val videoQuality = when (resolution.lowercase()) {
287
+ "hd" -> Quality.HD // 720x1280
288
+ else -> Quality.FHD // 1080x1920 (Full HD, default)
289
+ }
277
290
  val recorder = Recorder.Builder()
278
- .setQualitySelector(QualitySelector.from(Quality.HD))
291
+ .setQualitySelector(QualitySelector.from(videoQuality))
279
292
  .build()
280
293
  videoCapture = VideoCapture.withOutput(recorder)
281
294
 
@@ -351,6 +364,12 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
351
364
  return
352
365
  }
353
366
 
367
+ // ML Kit Performance Optimization Tips Applied:
368
+ // 1. Throttle detector calls using STRATEGY_KEEP_ONLY_LATEST backpressure
369
+ // 2. Drop frames if detector is still busy (prevents queue buildup)
370
+ // 3. Process at lower resolution (720x1280 portrait) for real-time detection
371
+ // 4. Use ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST for frame dropping
372
+ // 5. Close ImageProxy immediately after ML Kit processing completes
354
373
  val hasAnyDetection = frameProcessingEnabled && (faceDetectionEnabled || textRecognitionEnabled || barcodeScanningEnabled)
355
374
  if (!hasAnyDetection) {
356
375
  isProcessing.set(false)
@@ -363,9 +382,6 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
363
382
 
364
383
  // Create InputImage directly from camera frame — zero-copy, no base64 for ML Kit
365
384
  val inputImage = InputImage.fromMediaImage(mediaImage, rotationDegrees)
366
-
367
- // Use original image for text recognition
368
- val textInputImage = inputImage
369
385
 
370
386
  // Calculate portrait-oriented dimensions early (JPEG is already rotated)
371
387
  val isRotated = rotationDegrees == 90 || rotationDegrees == 270
@@ -376,6 +392,10 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
376
392
  // Brightness calculation restricted to scanning frame area (between 36% from top and 36% from bottom, 5% margins on sides)
377
393
  val averageBrightness = computeYPlaneBrightness(imageProxy, reportedWidth, reportedHeight)
378
394
 
395
+ // Use original inputImage directly for text recognition
396
+ // ML Kit works best with native camera frames, not processed bitmaps
397
+ val textInputImage = inputImage
398
+
379
399
  // Generate JPEG base64 only when JS side explicitly needs the image
380
400
  // NOTE: Do NOT auto-generate for face detection - too expensive, causes frame drops
381
401
  val jpegBase64: String? = if (includeBase64) {
@@ -398,6 +418,7 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
398
418
  } else null
399
419
 
400
420
  // Wait for all detectors, then build + send a single event to JS
421
+ // ML Kit resource cleanup: InputImage is automatically cleaned after task completion
401
422
  Tasks.whenAllComplete(tasks).addOnCompleteListener { _ ->
402
423
  try {
403
424
  val frameData = Arguments.createMap()
@@ -476,8 +497,6 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
476
497
  }
477
498
  }
478
499
 
479
- // MRZ validation moved to JavaScript - native implementation removed
480
-
481
500
  // Barcode scanning results
482
501
  if (barcodeTask != null) {
483
502
  val barcodesArray = Arguments.createArray()
@@ -581,6 +600,32 @@ class TrustchexCameraView(context: ThemedReactContext) : FrameLayout(context) {
581
600
  return if (count > 0) sum.toDouble() / count else 0.0
582
601
  }
583
602
 
603
+ /**
604
+ * Validates if the image dimensions are suitable for ML Kit text recognition.
605
+ *
606
+ * ML Kit text recognition requirements:
607
+ * - Minimum 16x16 pixels per character for acceptable accuracy
608
+ * - Ideal: 16-24 pixels per character for optimal performance
609
+ * - At 720x1280 (portrait HD), assuming ~30px average character width:
610
+ * - Can fit ~24 characters per line (720/30)
611
+ * - Can fit ~42 lines (1280/30)
612
+ *
613
+ * @return quality score (0.0-1.0) where 1.0 is optimal
614
+ */
615
+ private fun calculateTextRecognitionQuality(width: Int, height: Int): Double {
616
+ // For text at typical font sizes, we want at least 720px width
617
+ // Quality decreases significantly below 640px
618
+ val pixelScore = when {
619
+ width >= 720 && height >= 1280 -> 1.0 // Optimal
620
+ width >= 640 && height >= 960 -> 0.85 // Good
621
+ width >= 480 && height >= 640 -> 0.65 // Acceptable
622
+ else -> 0.4 // Poor
623
+ }
624
+ return pixelScore
625
+ }
626
+
627
+
628
+
584
629
  private fun yuvImageProxyToJpegBase64(imageProxy: ImageProxy, rotationDegrees: Int): String? {
585
630
  try {
586
631
  val width = imageProxy.width