react-native-rectangle-doc-scanner 3.191.0 → 3.192.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.
@@ -28,6 +28,8 @@ class CameraController(
28
28
 
29
29
  private var useFrontCamera = false
30
30
  private var torchEnabled = false
31
+ private var detectionEnabled = true
32
+ private var isCaptureSession = false
31
33
 
32
34
  var onFrameAnalyzed: ((Rectangle?, Int, Int) -> Unit)? = null
33
35
 
@@ -51,6 +53,7 @@ class CameraController(
51
53
  Log.d(TAG, "========================================")
52
54
 
53
55
  this.useFrontCamera = useFrontCam
56
+ this.detectionEnabled = enableDetection
54
57
 
55
58
  Log.d(TAG, "[CAMERA_CONTROLLER] Getting ProcessCameraProvider instance...")
56
59
  val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
@@ -61,7 +64,9 @@ class CameraController(
61
64
  cameraProvider = cameraProviderFuture.get()
62
65
  Log.d(TAG, "[CAMERA_CONTROLLER] Got cameraProvider: $cameraProvider")
63
66
  Log.d(TAG, "[CAMERA_CONTROLLER] Calling bindCameraUseCases...")
64
- bindCameraUseCases(enableDetection)
67
+ // Bind preview + analysis only. ImageCapture is bound lazily during capture
68
+ // to avoid stream configuration timeouts on some devices.
69
+ bindCameraUseCases(enableDetection, useImageCapture = false)
65
70
  } catch (e: Exception) {
66
71
  Log.e(TAG, "[CAMERA_CONTROLLER] Failed to start camera", e)
67
72
  e.printStackTrace()
@@ -80,9 +85,10 @@ class CameraController(
80
85
  /**
81
86
  * Bind camera use cases (preview, capture, analysis)
82
87
  */
83
- private fun bindCameraUseCases(enableDetection: Boolean) {
88
+ private fun bindCameraUseCases(enableDetection: Boolean, useImageCapture: Boolean) {
84
89
  Log.d(TAG, "[BIND] bindCameraUseCases called")
85
90
  Log.d(TAG, "[BIND] enableDetection: $enableDetection")
91
+ Log.d(TAG, "[BIND] useImageCapture: $useImageCapture")
86
92
 
87
93
  val cameraProvider = cameraProvider
88
94
  if (cameraProvider == null) {
@@ -117,16 +123,20 @@ class CameraController(
117
123
  .build()
118
124
  Log.d(TAG, "[BIND] Preview created: $preview")
119
125
 
120
- // Image capture use case (high resolution for document scanning)
121
- Log.d(TAG, "[BIND] Creating ImageCapture use case...")
122
- imageCapture = ImageCapture.Builder()
123
- .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
124
- // Cap resolution to avoid camera session timeouts on lower-end devices.
125
- .setTargetResolution(Size(960, 720))
126
- .setTargetRotation(targetRotation)
127
- .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
128
- .build()
129
- Log.d(TAG, "[BIND] ImageCapture created: $imageCapture")
126
+ // Image capture use case (bound only when capture is requested)
127
+ if (useImageCapture) {
128
+ Log.d(TAG, "[BIND] Creating ImageCapture use case...")
129
+ imageCapture = ImageCapture.Builder()
130
+ .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
131
+ // Cap resolution to avoid camera session timeouts on lower-end devices.
132
+ .setTargetResolution(Size(960, 720))
133
+ .setTargetRotation(targetRotation)
134
+ .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
135
+ .build()
136
+ Log.d(TAG, "[BIND] ImageCapture created: $imageCapture")
137
+ } else {
138
+ imageCapture = null
139
+ }
130
140
 
131
141
  // Image analysis use case for rectangle detection
132
142
  imageAnalysis = if (enableDetection) {
@@ -166,7 +176,10 @@ class CameraController(
166
176
  cameraProvider.unbindAll()
167
177
 
168
178
  // Bind use cases to camera
169
- val useCases = mutableListOf<UseCase>(preview, imageCapture!!)
179
+ val useCases = mutableListOf<UseCase>(preview)
180
+ if (imageCapture != null) {
181
+ useCases.add(imageCapture!!)
182
+ }
170
183
  if (imageAnalysis != null) {
171
184
  useCases.add(imageAnalysis!!)
172
185
  }
@@ -190,6 +203,7 @@ class CameraController(
190
203
  Log.d(TAG, "[BIND] Camera started successfully!")
191
204
  Log.d(TAG, "[BIND] hasFlashUnit: ${camera?.cameraInfo?.hasFlashUnit()}")
192
205
  Log.d(TAG, "[BIND] ========================================")
206
+ isCaptureSession = useImageCapture
193
207
  } catch (e: Exception) {
194
208
  Log.e(TAG, "[BIND] Failed to bind camera use cases", e)
195
209
  e.printStackTrace()
@@ -301,6 +315,24 @@ class CameraController(
301
315
  onImageCaptured: (File) -> Unit,
302
316
  onError: (Exception) -> Unit
303
317
  ) {
318
+ if (!isCaptureSession) {
319
+ val provider = cameraProvider ?: run {
320
+ onError(Exception("Camera provider not initialized"))
321
+ return
322
+ }
323
+ ContextCompat.getMainExecutor(context).execute {
324
+ try {
325
+ // Rebind with ImageCapture only for the capture to avoid stream timeouts.
326
+ provider.unbindAll()
327
+ bindCameraUseCases(enableDetection = false, useImageCapture = true)
328
+ capturePhoto(outputDirectory, onImageCaptured, onError)
329
+ } catch (e: Exception) {
330
+ onError(e)
331
+ }
332
+ }
333
+ return
334
+ }
335
+
304
336
  val imageCapture = imageCapture ?: run {
305
337
  onError(Exception("Image capture not initialized"))
306
338
  return
@@ -320,6 +352,11 @@ class CameraController(
320
352
  override fun onImageSaved(output: ImageCapture.OutputFileResults) {
321
353
  Log.d(TAG, "Photo capture succeeded: ${photoFile.absolutePath}")
322
354
  onImageCaptured(photoFile)
355
+ if (detectionEnabled) {
356
+ ContextCompat.getMainExecutor(context).execute {
357
+ bindCameraUseCases(enableDetection = true, useImageCapture = false)
358
+ }
359
+ }
323
360
  }
324
361
 
325
362
  override fun onError(exception: ImageCaptureException) {
@@ -327,7 +364,12 @@ class CameraController(
327
364
  if (exception.imageCaptureError == ImageCapture.ERROR_CAMERA_CLOSED) {
328
365
  Log.w(TAG, "Camera was closed during capture, attempting restart")
329
366
  stopCamera()
330
- startCamera(useFrontCamera, true)
367
+ startCamera(useFrontCamera, detectionEnabled)
368
+ }
369
+ if (detectionEnabled) {
370
+ ContextCompat.getMainExecutor(context).execute {
371
+ bindCameraUseCases(enableDetection = true, useImageCapture = false)
372
+ }
331
373
  }
332
374
  onError(exception)
333
375
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.191.0",
3
+ "version": "3.192.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",