react-native-rectangle-doc-scanner 3.130.0 → 3.132.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.
- package/android/build.gradle +78 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/CameraController.kt +229 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/DocumentDetector.kt +263 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/DocumentScannerModule.kt +121 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/DocumentScannerPackage.kt +16 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/DocumentScannerView.kt +388 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/DocumentScannerViewManager.kt +102 -0
- package/android/src/main/kotlin/com/reactnativerectangledocscanner/ImageProcessor.kt +220 -0
- package/package.json +5 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.reactnativerectangledocscanner
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class DocumentScannerPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(DocumentScannerModule(reactContext))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
14
|
+
return listOf(DocumentScannerViewManager())
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
package com.reactnativerectangledocscanner
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.BitmapFactory
|
|
5
|
+
import android.graphics.Canvas
|
|
6
|
+
import android.graphics.Color
|
|
7
|
+
import android.graphics.Paint
|
|
8
|
+
import android.graphics.PorterDuff
|
|
9
|
+
import android.graphics.PorterDuffXfermode
|
|
10
|
+
import android.os.Handler
|
|
11
|
+
import android.os.Looper
|
|
12
|
+
import android.util.Base64
|
|
13
|
+
import android.util.Log
|
|
14
|
+
import android.view.View
|
|
15
|
+
import android.widget.FrameLayout
|
|
16
|
+
import androidx.camera.view.PreviewView
|
|
17
|
+
import androidx.lifecycle.LifecycleOwner
|
|
18
|
+
import com.facebook.react.bridge.Arguments
|
|
19
|
+
import com.facebook.react.bridge.WritableMap
|
|
20
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
21
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
22
|
+
import kotlinx.coroutines.*
|
|
23
|
+
import java.io.File
|
|
24
|
+
import kotlin.math.max
|
|
25
|
+
|
|
26
|
+
class DocumentScannerView(context: ThemedReactContext) : FrameLayout(context) {
|
|
27
|
+
private val themedContext = context
|
|
28
|
+
private val previewView: PreviewView
|
|
29
|
+
private val overlayView: OverlayView
|
|
30
|
+
private var cameraController: CameraController? = null
|
|
31
|
+
|
|
32
|
+
// Props (matching iOS)
|
|
33
|
+
var overlayColor: Int = Color.parseColor("#80FFFFFF")
|
|
34
|
+
var enableTorch: Boolean = false
|
|
35
|
+
var useFrontCam: Boolean = false
|
|
36
|
+
var useBase64: Boolean = false
|
|
37
|
+
var saveInAppDocument: Boolean = false
|
|
38
|
+
var captureMultiple: Boolean = false
|
|
39
|
+
var manualOnly: Boolean = false
|
|
40
|
+
var detectionCountBeforeCapture: Int = 15
|
|
41
|
+
var detectionRefreshRateInMS: Int = 100
|
|
42
|
+
var quality: Float = 0.95f
|
|
43
|
+
var brightness: Float = 0f
|
|
44
|
+
var contrast: Float = 1f
|
|
45
|
+
var saturation: Float = 1f
|
|
46
|
+
|
|
47
|
+
// State
|
|
48
|
+
private var stableCounter = 0
|
|
49
|
+
private var lastDetectedRectangle: Rectangle? = null
|
|
50
|
+
private var lastDetectionQuality: RectangleQuality = RectangleQuality.TOO_FAR
|
|
51
|
+
private val detectionHandler = Handler(Looper.getMainLooper())
|
|
52
|
+
private var detectionRunnable: Runnable? = null
|
|
53
|
+
private var isCapturing = false
|
|
54
|
+
|
|
55
|
+
// Coroutine scope for async operations
|
|
56
|
+
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
|
57
|
+
|
|
58
|
+
companion object {
|
|
59
|
+
private const val TAG = "DocumentScannerView"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
init {
|
|
63
|
+
// Create preview view
|
|
64
|
+
previewView = PreviewView(context).apply {
|
|
65
|
+
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
66
|
+
scaleType = PreviewView.ScaleType.FILL_CENTER
|
|
67
|
+
}
|
|
68
|
+
addView(previewView)
|
|
69
|
+
|
|
70
|
+
// Create overlay view for drawing rectangle
|
|
71
|
+
overlayView = OverlayView(context)
|
|
72
|
+
addView(overlayView)
|
|
73
|
+
|
|
74
|
+
// Setup camera
|
|
75
|
+
post {
|
|
76
|
+
setupCamera()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private fun setupCamera() {
|
|
81
|
+
try {
|
|
82
|
+
val lifecycleOwner = context as? LifecycleOwner ?: run {
|
|
83
|
+
Log.e(TAG, "Context is not a LifecycleOwner")
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
cameraController = CameraController(context, lifecycleOwner, previewView)
|
|
88
|
+
cameraController?.startCamera(useFrontCam, !manualOnly)
|
|
89
|
+
|
|
90
|
+
// Start detection loop
|
|
91
|
+
startDetectionLoop()
|
|
92
|
+
|
|
93
|
+
Log.d(TAG, "Camera setup completed")
|
|
94
|
+
} catch (e: Exception) {
|
|
95
|
+
Log.e(TAG, "Failed to setup camera", e)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private fun startDetectionLoop() {
|
|
100
|
+
detectionRunnable?.let { detectionHandler.removeCallbacks(it) }
|
|
101
|
+
|
|
102
|
+
detectionRunnable = object : Runnable {
|
|
103
|
+
override fun run() {
|
|
104
|
+
// Perform detection
|
|
105
|
+
performDetection()
|
|
106
|
+
|
|
107
|
+
// Schedule next detection
|
|
108
|
+
detectionHandler.postDelayed(this, detectionRefreshRateInMS.toLong())
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
detectionHandler.post(detectionRunnable!!)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private fun performDetection() {
|
|
116
|
+
// In a real implementation, we'd analyze the camera frames
|
|
117
|
+
// For now, we'll simulate detection based on capture
|
|
118
|
+
// The actual detection happens during capture in this simplified version
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun onRectangleDetected(rectangle: Rectangle?, quality: RectangleQuality) {
|
|
122
|
+
lastDetectedRectangle = rectangle
|
|
123
|
+
lastDetectionQuality = quality
|
|
124
|
+
|
|
125
|
+
// Update overlay
|
|
126
|
+
overlayView.setRectangle(rectangle, overlayColor)
|
|
127
|
+
|
|
128
|
+
// Update stable counter based on quality
|
|
129
|
+
when (quality) {
|
|
130
|
+
RectangleQuality.GOOD -> {
|
|
131
|
+
if (rectangle != null) {
|
|
132
|
+
stableCounter++
|
|
133
|
+
Log.d(TAG, "Good rectangle detected, stableCounter: $stableCounter/$detectionCountBeforeCapture")
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
RectangleQuality.BAD_ANGLE, RectangleQuality.TOO_FAR -> {
|
|
137
|
+
if (stableCounter > 0) {
|
|
138
|
+
stableCounter--
|
|
139
|
+
}
|
|
140
|
+
Log.d(TAG, "Bad rectangle detected (type: $quality), stableCounter: $stableCounter")
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Send event to JavaScript
|
|
145
|
+
sendRectangleDetectEvent(rectangle, quality)
|
|
146
|
+
|
|
147
|
+
// Auto-capture if threshold reached
|
|
148
|
+
if (!manualOnly && stableCounter >= detectionCountBeforeCapture && rectangle != null) {
|
|
149
|
+
Log.d(TAG, "Auto-capture triggered! stableCounter: $stableCounter >= threshold: $detectionCountBeforeCapture")
|
|
150
|
+
stableCounter = 0
|
|
151
|
+
capture()
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
fun capture() {
|
|
156
|
+
captureWithPromise(null)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Capture image with promise support (matches iOS captureWithResolver:rejecter:)
|
|
161
|
+
* @param promise Optional promise to resolve with capture result
|
|
162
|
+
*/
|
|
163
|
+
fun captureWithPromise(promise: com.facebook.react.bridge.Promise?) {
|
|
164
|
+
if (isCapturing) {
|
|
165
|
+
Log.d(TAG, "Already capturing, ignoring request")
|
|
166
|
+
promise?.reject("CAPTURE_IN_PROGRESS", "Capture already in progress")
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
isCapturing = true
|
|
171
|
+
Log.d(TAG, "Capture initiated with promise: ${promise != null}")
|
|
172
|
+
|
|
173
|
+
val outputDir = if (saveInAppDocument) {
|
|
174
|
+
context.filesDir
|
|
175
|
+
} else {
|
|
176
|
+
context.cacheDir
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
cameraController?.capturePhoto(
|
|
180
|
+
outputDirectory = outputDir,
|
|
181
|
+
onImageCaptured = { file ->
|
|
182
|
+
scope.launch {
|
|
183
|
+
processAndEmitImage(file, promise)
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
onError = { exception ->
|
|
187
|
+
Log.e(TAG, "Capture failed", exception)
|
|
188
|
+
isCapturing = false
|
|
189
|
+
|
|
190
|
+
// Reject promise if provided
|
|
191
|
+
promise?.reject("CAPTURE_FAILED", "Failed to capture image", exception)
|
|
192
|
+
|
|
193
|
+
// Also send event for backwards compatibility
|
|
194
|
+
sendErrorEvent("capture_failed")
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private suspend fun processAndEmitImage(imageFile: File, promise: com.facebook.react.bridge.Promise? = null) = withContext(Dispatchers.IO) {
|
|
200
|
+
try {
|
|
201
|
+
// Detect rectangle in captured image
|
|
202
|
+
val bitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
|
|
203
|
+
val detectedRectangle = DocumentDetector.detectRectangle(bitmap)
|
|
204
|
+
|
|
205
|
+
// Process image with detected rectangle
|
|
206
|
+
val shouldCrop = detectedRectangle != null && stableCounter > 0
|
|
207
|
+
val processed = ImageProcessor.processImage(
|
|
208
|
+
imagePath = imageFile.absolutePath,
|
|
209
|
+
rectangle = detectedRectangle,
|
|
210
|
+
brightness = brightness,
|
|
211
|
+
contrast = contrast,
|
|
212
|
+
saturation = saturation,
|
|
213
|
+
shouldCrop = shouldCrop
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
// Save or encode images
|
|
217
|
+
val result = if (useBase64) {
|
|
218
|
+
Arguments.createMap().apply {
|
|
219
|
+
putString("croppedImage", ImageProcessor.bitmapToBase64(processed.croppedImage, quality))
|
|
220
|
+
putString("initialImage", ImageProcessor.bitmapToBase64(processed.initialImage, quality))
|
|
221
|
+
putMap("rectangleCoordinates", detectedRectangle?.toMap()?.toWritableMap())
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
val timestamp = System.currentTimeMillis()
|
|
225
|
+
val croppedPath = ImageProcessor.saveBitmapToFile(
|
|
226
|
+
processed.croppedImage,
|
|
227
|
+
if (saveInAppDocument) context.filesDir else context.cacheDir,
|
|
228
|
+
"cropped_img_$timestamp.jpeg",
|
|
229
|
+
quality
|
|
230
|
+
)
|
|
231
|
+
val initialPath = ImageProcessor.saveBitmapToFile(
|
|
232
|
+
processed.initialImage,
|
|
233
|
+
if (saveInAppDocument) context.filesDir else context.cacheDir,
|
|
234
|
+
"initial_img_$timestamp.jpeg",
|
|
235
|
+
quality
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
Arguments.createMap().apply {
|
|
239
|
+
putString("croppedImage", croppedPath)
|
|
240
|
+
putString("initialImage", initialPath)
|
|
241
|
+
putMap("rectangleCoordinates", detectedRectangle?.toMap()?.toWritableMap())
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
withContext(Dispatchers.Main) {
|
|
246
|
+
Log.d(TAG, "Processing completed, resolving promise: ${promise != null}")
|
|
247
|
+
|
|
248
|
+
// Resolve promise first (if provided) - matches iOS behavior
|
|
249
|
+
promise?.resolve(result)
|
|
250
|
+
|
|
251
|
+
// Then send event for backwards compatibility
|
|
252
|
+
sendPictureTakenEvent(result)
|
|
253
|
+
|
|
254
|
+
isCapturing = false
|
|
255
|
+
|
|
256
|
+
if (!captureMultiple) {
|
|
257
|
+
stopCamera()
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
} catch (e: Exception) {
|
|
261
|
+
Log.e(TAG, "Failed to process image", e)
|
|
262
|
+
withContext(Dispatchers.Main) {
|
|
263
|
+
// Reject promise if provided
|
|
264
|
+
promise?.reject("PROCESSING_FAILED", "Failed to process image: ${e.message}", e)
|
|
265
|
+
|
|
266
|
+
// Also send error event for backwards compatibility
|
|
267
|
+
sendErrorEvent("processing_failed")
|
|
268
|
+
isCapturing = false
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private fun sendPictureTakenEvent(data: WritableMap) {
|
|
274
|
+
val event = Arguments.createMap().apply {
|
|
275
|
+
merge(data)
|
|
276
|
+
}
|
|
277
|
+
themedContext.getJSModule(RCTEventEmitter::class.java)
|
|
278
|
+
.receiveEvent(id, "onPictureTaken", event)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private fun sendRectangleDetectEvent(rectangle: Rectangle?, quality: RectangleQuality) {
|
|
282
|
+
val event = Arguments.createMap().apply {
|
|
283
|
+
putInt("stableCounter", stableCounter)
|
|
284
|
+
putInt("lastDetectionType", quality.ordinal)
|
|
285
|
+
putMap("rectangleCoordinates", rectangle?.toMap()?.toWritableMap())
|
|
286
|
+
putMap("previewSize", Arguments.createMap().apply {
|
|
287
|
+
putInt("width", width)
|
|
288
|
+
putInt("height", height)
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
themedContext.getJSModule(RCTEventEmitter::class.java)
|
|
292
|
+
.receiveEvent(id, "onRectangleDetect", event)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private fun sendErrorEvent(error: String) {
|
|
296
|
+
val event = Arguments.createMap().apply {
|
|
297
|
+
putString("error", error)
|
|
298
|
+
}
|
|
299
|
+
themedContext.getJSModule(RCTEventEmitter::class.java)
|
|
300
|
+
.receiveEvent(id, "onPictureTaken", event)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
fun setEnableTorch(enabled: Boolean) {
|
|
304
|
+
this.enableTorch = enabled
|
|
305
|
+
cameraController?.setTorchEnabled(enabled)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
fun setUseFrontCam(enabled: Boolean) {
|
|
309
|
+
if (this.useFrontCam != enabled) {
|
|
310
|
+
this.useFrontCam = enabled
|
|
311
|
+
cameraController?.stopCamera()
|
|
312
|
+
setupCamera()
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
fun startCamera() {
|
|
317
|
+
cameraController?.startCamera(useFrontCam, !manualOnly)
|
|
318
|
+
startDetectionLoop()
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fun stopCamera() {
|
|
322
|
+
detectionRunnable?.let { detectionHandler.removeCallbacks(it) }
|
|
323
|
+
cameraController?.stopCamera()
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
override fun onDetachedFromWindow() {
|
|
327
|
+
super.onDetachedFromWindow()
|
|
328
|
+
stopCamera()
|
|
329
|
+
cameraController?.shutdown()
|
|
330
|
+
scope.cancel()
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Overlay view for drawing detected rectangle
|
|
335
|
+
*/
|
|
336
|
+
private class OverlayView(context: Context) : View(context) {
|
|
337
|
+
private var rectangle: Rectangle? = null
|
|
338
|
+
private var overlayColor: Int = Color.parseColor("#80FFFFFF")
|
|
339
|
+
private val paint = Paint().apply {
|
|
340
|
+
style = Paint.Style.FILL
|
|
341
|
+
xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
fun setRectangle(rect: Rectangle?, color: Int) {
|
|
345
|
+
this.rectangle = rect
|
|
346
|
+
this.overlayColor = color
|
|
347
|
+
invalidate()
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
override fun onDraw(canvas: Canvas) {
|
|
351
|
+
super.onDraw(canvas)
|
|
352
|
+
|
|
353
|
+
rectangle?.let { rect ->
|
|
354
|
+
paint.color = overlayColor
|
|
355
|
+
|
|
356
|
+
// Draw the rectangle overlay (simplified - just a filled polygon)
|
|
357
|
+
val path = android.graphics.Path().apply {
|
|
358
|
+
moveTo(rect.topLeft.x.toFloat(), rect.topLeft.y.toFloat())
|
|
359
|
+
lineTo(rect.topRight.x.toFloat(), rect.topRight.y.toFloat())
|
|
360
|
+
lineTo(rect.bottomRight.x.toFloat(), rect.bottomRight.y.toFloat())
|
|
361
|
+
lineTo(rect.bottomLeft.x.toFloat(), rect.bottomLeft.y.toFloat())
|
|
362
|
+
close()
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
canvas.drawPath(path, paint)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Extension function to convert Map to WritableMap
|
|
373
|
+
*/
|
|
374
|
+
private fun Map<String, Any?>.toWritableMap(): WritableMap {
|
|
375
|
+
val map = Arguments.createMap()
|
|
376
|
+
forEach { (key, value) ->
|
|
377
|
+
when (value) {
|
|
378
|
+
null -> map.putNull(key)
|
|
379
|
+
is Boolean -> map.putBoolean(key, value)
|
|
380
|
+
is Double -> map.putDouble(key, value)
|
|
381
|
+
is Int -> map.putInt(key, value)
|
|
382
|
+
is String -> map.putString(key, value)
|
|
383
|
+
is Map<*, *> -> map.putMap(key, (value as Map<String, Any?>).toWritableMap())
|
|
384
|
+
else -> Log.w("DocumentScannerView", "Unknown type for key $key: ${value::class.java}")
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return map
|
|
388
|
+
}
|
package/android/src/main/kotlin/com/reactnativerectangledocscanner/DocumentScannerViewManager.kt
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
package com.reactnativerectangledocscanner
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import com.facebook.react.bridge.ReadableArray
|
|
5
|
+
import com.facebook.react.common.MapBuilder
|
|
6
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
9
|
+
|
|
10
|
+
class DocumentScannerViewManager : SimpleViewManager<DocumentScannerView>() {
|
|
11
|
+
|
|
12
|
+
companion object {
|
|
13
|
+
const val REACT_CLASS = "RNPdfScannerManager"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override fun getName() = REACT_CLASS
|
|
17
|
+
|
|
18
|
+
override fun createViewInstance(reactContext: ThemedReactContext): DocumentScannerView {
|
|
19
|
+
return DocumentScannerView(reactContext)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@ReactProp(name = "overlayColor", customType = "Color")
|
|
23
|
+
fun setOverlayColor(view: DocumentScannerView, color: Int?) {
|
|
24
|
+
color?.let {
|
|
25
|
+
view.overlayColor = it
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@ReactProp(name = "enableTorch")
|
|
30
|
+
fun setEnableTorch(view: DocumentScannerView, enabled: Boolean) {
|
|
31
|
+
view.setEnableTorch(enabled)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@ReactProp(name = "useFrontCam")
|
|
35
|
+
fun setUseFrontCam(view: DocumentScannerView, enabled: Boolean) {
|
|
36
|
+
view.setUseFrontCam(enabled)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@ReactProp(name = "useBase64")
|
|
40
|
+
fun setUseBase64(view: DocumentScannerView, enabled: Boolean) {
|
|
41
|
+
view.useBase64 = enabled
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@ReactProp(name = "saveInAppDocument")
|
|
45
|
+
fun setSaveInAppDocument(view: DocumentScannerView, enabled: Boolean) {
|
|
46
|
+
view.saveInAppDocument = enabled
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@ReactProp(name = "captureMultiple")
|
|
50
|
+
fun setCaptureMultiple(view: DocumentScannerView, enabled: Boolean) {
|
|
51
|
+
view.captureMultiple = enabled
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@ReactProp(name = "manualOnly")
|
|
55
|
+
fun setManualOnly(view: DocumentScannerView, enabled: Boolean) {
|
|
56
|
+
view.manualOnly = enabled
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@ReactProp(name = "detectionCountBeforeCapture")
|
|
60
|
+
fun setDetectionCountBeforeCapture(view: DocumentScannerView, count: Int) {
|
|
61
|
+
view.detectionCountBeforeCapture = count
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@ReactProp(name = "detectionRefreshRateInMS")
|
|
65
|
+
fun setDetectionRefreshRateInMS(view: DocumentScannerView, rate: Int) {
|
|
66
|
+
view.detectionRefreshRateInMS = rate
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@ReactProp(name = "quality")
|
|
70
|
+
fun setQuality(view: DocumentScannerView, quality: Float) {
|
|
71
|
+
view.quality = quality
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@ReactProp(name = "brightness")
|
|
75
|
+
fun setBrightness(view: DocumentScannerView, brightness: Float) {
|
|
76
|
+
view.brightness = brightness
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@ReactProp(name = "contrast")
|
|
80
|
+
fun setContrast(view: DocumentScannerView, contrast: Float) {
|
|
81
|
+
view.contrast = contrast
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@ReactProp(name = "saturation")
|
|
85
|
+
fun setSaturation(view: DocumentScannerView, saturation: Float) {
|
|
86
|
+
view.saturation = saturation
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
|
|
90
|
+
return MapBuilder.of(
|
|
91
|
+
"onPictureTaken",
|
|
92
|
+
MapBuilder.of("registrationName", "onPictureTaken"),
|
|
93
|
+
"onRectangleDetect",
|
|
94
|
+
MapBuilder.of("registrationName", "onRectangleDetect")
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
override fun onDropViewInstance(view: DocumentScannerView) {
|
|
99
|
+
super.onDropViewInstance(view)
|
|
100
|
+
view.stopCamera()
|
|
101
|
+
}
|
|
102
|
+
}
|