package com.barcodescanner import android.Manifest import android.graphics.Color import android.util.Log import androidx.appcompat.app.AppCompatActivity import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.annotations.ReactModule import com.facebook.react.modules.core.PermissionAwareActivity import com.facebook.react.modules.core.PermissionListener import com.facebook.react.uimanager.SimpleViewManager import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ViewManagerDelegate import com.facebook.react.uimanager.annotations.ReactProp import com.facebook.react.viewmanagers.BarcodeScannerViewManagerDelegate import com.facebook.react.viewmanagers.BarcodeScannerViewManagerInterface import com.facebook.react.uimanager.events.EventDispatcher import com.facebook.react.uimanager.UIManagerHelper import com.facebook.react.common.MapBuilder import com.google.zxing.BarcodeFormat import com.facebook.react.bridge.ReadableMap @ReactModule(name = BarcodeScannerViewManager.NAME) class BarcodeScannerViewManager(private val appContext: ReactApplicationContext) : SimpleViewManager(),PermissionListener, BarcodeScannerViewManagerInterface { private val mDelegate: ViewManagerDelegate private var barCodeListener : BarcodeScannerListener? = null init { mDelegate = BarcodeScannerViewManagerDelegate(this) } override fun getDelegate(): ViewManagerDelegate? { return mDelegate } override fun getName(): String { return NAME } override fun createViewInstance(context: ThemedReactContext): BarcodeScannerView { val currentActivity = appContext.getCurrentActivity() if(currentActivity != null && !currentActivity.isPermissionAlreadyPermit(Manifest.permission.CAMERA)){ if (currentActivity is PermissionAwareActivity) { currentActivity.requestPermissions( arrayOf( Manifest.permission.CAMERA ), CAMERA_PERMISSION_REQUEST_CODE, this ) } } return BarcodeScannerView(context).apply { setOnResultListener { result-> val eventDispatcher:EventDispatcher? = UIManagerHelper.getEventDispatcherForReactTag(context,id) eventDispatcher?.dispatchEvent(ScanResultEvent(id,result)) } barCodeListener = BarcodeScannerListener(this).also { if(currentActivity != null && currentActivity is AppCompatActivity){ currentActivity.lifecycle.addObserver(it) } } } } @ReactProp(name = "frameWidth") override fun setFrameWidth(view: BarcodeScannerView?, frameWidth: Int) { view?.setFrameWidth(frameWidth) } @ReactProp(name = "frameBorderColor") override fun setFrameBorderColor(view: BarcodeScannerView?, value: String?) { if(value!=null){ view?.setBorderColor( Color.parseColor(value)) } } @ReactProp(name = "frameHeight") override fun setFrameHeight(view: BarcodeScannerView?, frameHeight: Int) { view?.setFrameHeight(frameHeight) } @ReactProp(name = "autoFocusEnabled") override fun setAutoFocusEnabled(view: BarcodeScannerView, enabled: Boolean) { view.setAutoFocusEnabled(enabled) } @ReactProp(name = "acceptFormats") override fun setAcceptFormats(view: BarcodeScannerView, acceptFormats: ReadableMap?) { if(acceptFormats!= null){ val formats = parseAcceptFormats(acceptFormats) if(formats.isNotEmpty()){ view.setFormats(formats) }else{ view.setFormats(BarcodeFormat.values().toMutableList()) } } } private fun parseAcceptFormats(acceptFormats: ReadableMap): List { val availableFormats = BarcodeFormat.values().fold(mutableMapOf()){ current, item -> current[item.name] = item current } return kotlin.runCatching { val acceptedFormats = acceptFormats.getArray("acceptedFormats") ?: return@runCatching emptyList() val totalItems = acceptedFormats.size() (0 until totalItems).mapNotNull { itemIndex -> val format = acceptedFormats.getString(itemIndex) availableFormats[format] } }.getOrNull() ?: emptyList() } @ReactProp(name = "flashModeEnabled") override fun setFlashModeEnabled(view: BarcodeScannerView, enabled: Boolean) { view.setFlashModeEnabled(enabled) } override fun onDropViewInstance(view: BarcodeScannerView){ view.stopCamera() barCodeListener?.run { val currentActivity = appContext.getCurrentActivity() if(currentActivity != null && currentActivity is AppCompatActivity){ currentActivity.lifecycle.removeObserver(this) } } super.onDropViewInstance(view) } override fun getExportedCustomDirectEventTypeConstants(): MutableMap { return MapBuilder.of( ScanResultEvent.EVENT_NAME, MapBuilder.of("registrationName", "onScanResultListener"), ) } override fun onRequestPermissionsResult( requestCode: Int, permission: Array, grantResults: IntArray ): Boolean { //todo handle permission denied return true } companion object { const val NAME = "BarcodeScannerView" private const val CAMERA_PERMISSION_REQUEST_CODE = 10 } }