package com.sidaddressverification import android.util.Log import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.Promise import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableMap import com.facebook.react.module.annotations.ReactModule import com.facebook.react.modules.core.DeviceEventManagerModule import kotlinx.coroutines.* import tech.sourceid.sid_address_verification.AddressVerification import tech.sourceid.sid_address_verification.services.LocationTracking @ReactModule(name = SIDAddressVerificationModule.NAME) class SIDAddressVerificationModule(reactContext: ReactApplicationContext) : NativeSIDAddressVerificationSpec(reactContext) { private val addressVerification: AddressVerification by lazy { AddressVerification(reactContext) } override fun getName(): String { return NAME } // Example method // See https://reactnative.dev/docs/native-modules-android override fun multiply(a: Double, b: Double): Double { return a * b } // Start location tracking with API credentials override fun startTrackingWithConfig( apiKey: String, customerID: String, verificationGroupID: String, // token: String, // refreshToken: String, promise: Promise ) { Log.d("startTrackingWithConfig", "apiKey: $apiKey, customerID: $customerID, verificationGroupID: $verificationGroupID") CoroutineScope(Dispatchers.IO).launch { try { addressVerification.startLocationTracking(apiKey, customerID, verificationGroupID) { lat, lng -> sendLocationUpdate(lat, lng) } withContext(Dispatchers.Main) { promise.resolve(true) } } catch (e: Exception) { withContext(Dispatchers.Main) { promise.reject("TRACKING_ERROR", e.message, e) } } } } override fun pickLocation(promise: Promise) { Log.d("pickLocation", "Picking location manually") addressVerification.pickLocation { resolvedAddress -> try { val result = Arguments.createMap().apply { putDouble("latitude", resolvedAddress.latitude) putDouble("longitude", resolvedAddress.longitude) putString("fullAddress", resolvedAddress.fullAddress) putString("country", resolvedAddress.country) putString("state", resolvedAddress.state) putString("city", resolvedAddress.city) putString("postalCode", resolvedAddress.postalCode) putString("street", resolvedAddress.street) } promise.resolve(result) } catch (e: Exception) { promise.reject("PICK_LOCATION_ERROR", e.message, e) } } } // Stop tracking override fun stopTracking() { addressVerification.stopLocationTracking() } // Fetch remote configuration override fun fetchConfiguration(apiKey: String, customerID: String, token: String, refreshToken: String, promise: Promise) { CoroutineScope(Dispatchers.IO).launch { try { val config = addressVerification.fetchConfig() val result = Arguments.createMap().apply { putDouble("pollingInterval", config.geotaggingPollingInterval.toDouble()) putDouble("sessionTimeout", config.geotaggingSessionTimeout.toDouble()) } withContext(Dispatchers.Main) { promise.resolve(result) } } catch (e: Exception) { withContext(Dispatchers.Main) { promise.reject("CONFIG_ERROR", e.message, e) } } } } // Send location updates to JS private fun sendLocationUpdate(latitude: Double, longitude: Double) { Log.d("LocationUpdate", "Lat: $latitude, Lng: $longitude") val params = Arguments.createMap().apply { putDouble("latitude", latitude) putDouble("longitude", longitude) } reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit("onLocationUpdate", params) } // RN event compliance override fun addListener(eventName: String) { // Required for RN 65+ } override fun removeListeners(count: Double) { // Required for RN 65+ } companion object { const val NAME = "SIDAddressVerification" } }