react-native-rectangle-doc-scanner 3.149.0 → 3.150.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.
@@ -8,6 +8,7 @@ import androidx.camera.core.*
8
8
  import androidx.camera.lifecycle.ProcessCameraProvider
9
9
  import androidx.camera.view.PreviewView
10
10
  import androidx.core.content.ContextCompat
11
+ import androidx.lifecycle.Lifecycle
11
12
  import androidx.lifecycle.LifecycleOwner
12
13
  import java.io.File
13
14
  import java.util.concurrent.ExecutorService
@@ -68,6 +69,13 @@ class CameraController(
68
69
  private fun bindCameraUseCases(enableDetection: Boolean) {
69
70
  val cameraProvider = cameraProvider ?: return
70
71
 
72
+ // Check lifecycle state
73
+ val lifecycle = lifecycleOwner.lifecycle
74
+ if (lifecycle.currentState == Lifecycle.State.DESTROYED) {
75
+ Log.e(TAG, "Cannot bind camera - lifecycle is destroyed")
76
+ return
77
+ }
78
+
71
79
  // Select camera
72
80
  val cameraSelector = if (useFrontCamera) {
73
81
  CameraSelector.DEFAULT_FRONT_CAMERA
@@ -79,14 +87,12 @@ class CameraController(
79
87
  val preview = Preview.Builder()
80
88
  .setTargetResolution(Size(1080, 1920))
81
89
  .build()
82
- .also {
83
- it.setSurfaceProvider(previewView.surfaceProvider)
84
- }
85
90
 
86
91
  // Image capture use case (high resolution for document scanning)
87
92
  imageCapture = ImageCapture.Builder()
88
93
  .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
89
94
  .setTargetResolution(Size(1920, 2560))
95
+ .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
90
96
  .build()
91
97
 
92
98
  // Image analysis use case for rectangle detection
@@ -121,12 +127,15 @@ class CameraController(
121
127
  *useCases.toTypedArray()
122
128
  )
123
129
 
130
+ // Set surface provider AFTER binding to lifecycle
131
+ preview.setSurfaceProvider(previewView.surfaceProvider)
132
+
124
133
  // Restore torch state if it was enabled
125
134
  if (torchEnabled) {
126
135
  setTorchEnabled(true)
127
136
  }
128
137
 
129
- Log.d(TAG, "Camera started successfully")
138
+ Log.d(TAG, "Camera started successfully, hasFlashUnit: ${camera?.cameraInfo?.hasFlashUnit()}")
130
139
  } catch (e: Exception) {
131
140
  Log.e(TAG, "Failed to bind camera use cases", e)
132
141
  }
@@ -19,6 +19,7 @@ import com.facebook.react.bridge.WritableMap
19
19
  import com.facebook.react.uimanager.ThemedReactContext
20
20
  import com.facebook.react.uimanager.events.RCTEventEmitter
21
21
  import kotlinx.coroutines.*
22
+ import kotlinx.coroutines.delay
22
23
  import java.io.File
23
24
  import kotlin.math.min
24
25
 
@@ -48,6 +49,7 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
48
49
  private var stableCounter = 0
49
50
  private var lastDetectionTimestamp: Long = 0L
50
51
  private var isCapturing = false
52
+ private var isDetaching = false
51
53
 
52
54
  // Coroutine scope for async operations
53
55
  private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
@@ -181,6 +183,12 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
181
183
  return
182
184
  }
183
185
 
186
+ if (isDetaching) {
187
+ Log.d(TAG, "View is detaching, cannot capture")
188
+ promise?.reject("VIEW_DETACHING", "View is being removed")
189
+ return
190
+ }
191
+
184
192
  isCapturing = true
185
193
  Log.d(TAG, "Capture initiated with promise: ${promise != null}")
186
194
 
@@ -193,8 +201,14 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
193
201
  cameraController?.capturePhoto(
194
202
  outputDirectory = outputDir,
195
203
  onImageCaptured = { file ->
196
- scope.launch {
197
- processAndEmitImage(file, promise)
204
+ if (!isDetaching) {
205
+ scope.launch {
206
+ processAndEmitImage(file, promise)
207
+ }
208
+ } else {
209
+ Log.d(TAG, "View detaching, skipping image processing")
210
+ isCapturing = false
211
+ promise?.reject("VIEW_DETACHING", "View was removed during capture")
198
212
  }
199
213
  },
200
214
  onError = { exception ->
@@ -351,17 +365,45 @@ class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context), L
351
365
  }
352
366
 
353
367
  fun stopCamera() {
354
- cameraController?.stopCamera()
355
- overlayView.setRectangle(null, overlayColor)
356
- stableCounter = 0
357
- if (lifecycleRegistry.currentState != Lifecycle.State.DESTROYED) {
358
- lifecycleRegistry.currentState = Lifecycle.State.CREATED
368
+ if (!isCapturing) {
369
+ cameraController?.stopCamera()
370
+ overlayView.setRectangle(null, overlayColor)
371
+ stableCounter = 0
372
+ if (lifecycleRegistry.currentState != Lifecycle.State.DESTROYED) {
373
+ lifecycleRegistry.currentState = Lifecycle.State.CREATED
374
+ }
375
+ } else {
376
+ Log.d(TAG, "Cannot stop camera while capturing")
359
377
  }
360
378
  }
361
379
 
362
380
  override fun onDetachedFromWindow() {
363
381
  super.onDetachedFromWindow()
364
- stopCamera()
382
+ Log.d(TAG, "onDetachedFromWindow called, isCapturing: $isCapturing")
383
+
384
+ // Mark as detaching to prevent new captures
385
+ isDetaching = true
386
+
387
+ // Wait for any ongoing capture to complete before cleaning up
388
+ if (isCapturing) {
389
+ Log.d(TAG, "Waiting for capture to complete before cleanup...")
390
+ // Use a coroutine to wait briefly for capture to complete
391
+ scope.launch {
392
+ var waitCount = 0
393
+ while (isCapturing && waitCount < 20) { // Wait up to 2 seconds
394
+ delay(100)
395
+ waitCount++
396
+ }
397
+ performCleanup()
398
+ }
399
+ } else {
400
+ performCleanup()
401
+ }
402
+ }
403
+
404
+ private fun performCleanup() {
405
+ Log.d(TAG, "Performing cleanup")
406
+ cameraController?.stopCamera()
365
407
  lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
366
408
  cameraController?.shutdown()
367
409
  scope.cancel()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.149.0",
3
+ "version": "3.150.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",