package io.scanbot.barcodesdk.plugin.reactnative import android.app.Activity import android.app.Application import android.content.Intent import com.facebook.react.bridge.ActivityEventListener import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap import com.facebook.react.modules.core.DeviceEventManagerModule import io.scanbot.barcodesdk.plugin.reactnative.extensions.toJSON import io.scanbot.barcodesdk.plugin.reactnative.extensions.toWritableMap import io.scanbot.sdk_wrapper.barcode.operations.detection.SBBDetectBarcodes import io.scanbot.sdk_wrapper.barcode.operations.image_operations.SBBImageOperations import io.scanbot.sdk_wrapper.barcode.operations.license.SBBLicenseOperations import io.scanbot.sdk_wrapper.barcode.operations.pdf_extraction.SBBExtractFromPdf import io.scanbot.sdk_wrapper.barcode.operations.setup.SBBSetupOperations import io.scanbot.sdk_wrapper.barcode.rtuui.SBBRtuUi import org.json.JSONException import org.json.JSONObject class ScanbotBarcodeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), ActivityEventListener { companion object { const val NAME = "ScanbotBarcodeSdk" const val BARCODE_ITEM_MAPPER_EVENT = "barcodeItemMapperEvent" } override fun getName(): String { return NAME } @ReactMethod fun initializeSdk(configuration: ReadableMap, promise: Promise) = runOperationWithJSONParam( configuration, promise ) { configurationAsJSON -> reactApplicationContextIfActiveOrWarn?.let { SBBSetupOperations.initializeSdk( it.applicationContext as Application, configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) it.addActivityEventListener(this) } ?: run { promise.reject("", "React Native Instance has already disappeared.") } } @ReactMethod fun getLicenseInfo(promise: Promise) { SBBLicenseOperations.getLicenseInfo(ScanbotBarcodeSdkPluginResultDelegate(promise)) } @ReactMethod fun cleanup(promise: Promise) { SBBSetupOperations.cleanup(ScanbotBarcodeSdkPluginResultDelegate(promise)) } @ReactMethod fun startBarcodeScanner( configuration: ReadableMap, promise: Promise ) = runOperationWithJSONParamAndSafeActivity( configuration, promise ) { configurationAsJSON, currentActivity -> SBBRtuUi.startLegacyBarcodeScanner( currentActivity, configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } @ReactMethod fun closeBarcodeScanner(promise: Promise) = runOperationWithSafeActivity(promise) { currentActivity -> SBBRtuUi.closeLegacyBarcodeScanner( currentActivity, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } @ReactMethod fun startBatchBarcodeScanner( configuration: ReadableMap, promise: Promise ) = runOperationWithJSONParamAndSafeActivity( configuration, promise ) { configurationAsJSON, currentActivity -> SBBRtuUi.startLegacyBatchBarcodeScanner( currentActivity, configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } @ReactMethod fun closeBatchBarcodeScanner(promise: Promise) = runOperationWithSafeActivity(promise) { currentActivity -> SBBRtuUi.closeLegacyBatchBarcodeScanner( currentActivity, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } @ReactMethod fun startBarcodeScannerV2( configuration: ReadableMap, barcodeItemMapperImplemented: Boolean, promise: Promise ) = runOperationWithJSONParamAndSafeActivity( configuration, promise ) { configurationAsJSON, currentActivity -> if (barcodeItemMapperImplemented) { SBBRtuUi.startBarcodeScanner( currentActivity, configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) { reactApplicationContextIfActiveOrWarn?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) ?.emit(BARCODE_ITEM_MAPPER_EVENT, it.toWritableMap()) } } else { SBBRtuUi.startBarcodeScanner( currentActivity, configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } } @ReactMethod fun onBarcodeItemMapper(barcodeItemUuid: String, barcodeMappedData: ReadableMap?) { SBBRtuUi.onBarcodeItemMapper(barcodeItemUuid, barcodeMappedData?.toJSON()) } @ReactMethod fun detectBarcodesOnImage(configuration: ReadableMap, promise: Promise) = runOperationWithJSONParam(configuration, promise) { configurationAsJSON -> SBBDetectBarcodes.detectOnImage( configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } @ReactMethod fun extractImagesFromPDF(configuration: ReadableMap, promise: Promise) = runOperationWithJSONParam(configuration, promise) { configurationAsJSON -> SBBExtractFromPdf.extractImages( configurationAsJSON, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } @ReactMethod fun getImageData(imageFileUri: String, promise: Promise) { SBBImageOperations.getImageData( imageFileUri, ScanbotBarcodeSdkPluginResultDelegate(promise) ) } override fun onActivityResult( activity: Activity, requestCode: Int, resultCode: Int, intent: Intent? ) { SBBRtuUi.onActivityResult(requestCode, resultCode, intent) } override fun onNewIntent(intent: Intent?) { // NO-OP } //region Helpers @Suppress("UNUSED_PARAMETER") @ReactMethod fun addListener(type: String?) { // Keep: Required for RN built in Event Emitter Calls, otherwise warnings are thrown in the console log. } @Suppress("UNUSED_PARAMETER") @ReactMethod fun removeListeners(type: Int?) { // Keep: Required for RN built in Event Emitter Calls, otherwise warnings are thrown in the console log. } private fun runOperationWithJSONParam( configuration: ReadableMap, promise: Promise, operation: (configurationAsJSON: JSONObject) -> Unit ) { val configurationAsJSON: JSONObject try { configurationAsJSON = configuration.toJSON() } catch (ex: JSONException) { promise.reject(ex) return } operation(configurationAsJSON) } private fun runOperationWithSafeActivity( promise: Promise, operation: (currentActivity: Activity) -> Unit ) { reactApplicationContext?.currentActivity?.let { operation(it) } ?: run { promise.reject("", "ScanbotBarcodeSdkModule is not attached to activity") } } private fun runOperationWithJSONParamAndSafeActivity( configuration: ReadableMap, promise: Promise, operation: (configurationAsJSON: JSONObject, currentActivity: Activity) -> Unit ) { val configurationAsJSON: JSONObject try { configurationAsJSON = configuration.toJSON() } catch (ex: JSONException) { promise.reject(ex) return } reactApplicationContext?.currentActivity?.let { operation(configurationAsJSON, it) } ?: run { promise.reject("", "ScanbotBarcodeSdkModule is not attached to activity") } } //endregion Helpers }