1058d2dd0SWill Schurman // Copyright 2015-present 650 Industries. All rights reserved. 2058d2dd0SWill Schurman package host.exp.exponent.modules 3058d2dd0SWill Schurman 4058d2dd0SWill Schurman import com.facebook.react.bridge.* 5058d2dd0SWill Schurman import com.facebook.react.modules.core.DeviceEventManagerModule 6058d2dd0SWill Schurman import host.exp.exponent.Constants 7058d2dd0SWill Schurman import host.exp.exponent.analytics.EXL 8058d2dd0SWill Schurman import host.exp.exponent.di.NativeModuleDepsProvider 9058d2dd0SWill Schurman import host.exp.exponent.experience.ErrorActivity 10058d2dd0SWill Schurman import host.exp.exponent.kernel.DevMenuManager 11058d2dd0SWill Schurman import host.exp.exponent.kernel.ExponentKernelModuleInterface 12058d2dd0SWill Schurman import host.exp.exponent.kernel.ExponentKernelModuleProvider 13058d2dd0SWill Schurman import host.exp.exponent.kernel.ExponentKernelModuleProvider.KernelEvent 14058d2dd0SWill Schurman import host.exp.exponent.kernel.ExponentKernelModuleProvider.KernelEventCallback 15058d2dd0SWill Schurman import host.exp.exponent.kernel.Kernel 16058d2dd0SWill Schurman import host.exp.exponent.storage.ExponentSharedPreferences 17*3ba32fe9SKudo Chien import host.exp.exponent.utils.BundleJSONConverter 18058d2dd0SWill Schurman import org.json.JSONObject 19058d2dd0SWill Schurman import java.util.* 20058d2dd0SWill Schurman import javax.inject.Inject 21058d2dd0SWill Schurman 22058d2dd0SWill Schurman class ExponentKernelModule(reactContext: ReactApplicationContext?) : 23058d2dd0SWill Schurman ReactContextBaseJavaModule(reactContext), ExponentKernelModuleInterface { 24058d2dd0SWill Schurman 25058d2dd0SWill Schurman @Inject 26058d2dd0SWill Schurman lateinit var kernel: Kernel 27058d2dd0SWill Schurman 28058d2dd0SWill Schurman @Inject 29058d2dd0SWill Schurman lateinit var exponentSharedPreferences: ExponentSharedPreferences 30058d2dd0SWill Schurman 31058d2dd0SWill Schurman @Inject 32058d2dd0SWill Schurman lateinit var devMenuManager: DevMenuManager 33058d2dd0SWill Schurman getConstantsnull34058d2dd0SWill Schurman override fun getConstants(): Map<String, Any> { 35058d2dd0SWill Schurman return mapOf( 36058d2dd0SWill Schurman "sdkVersions" to Constants.SDK_VERSIONS 37058d2dd0SWill Schurman ) 38058d2dd0SWill Schurman } 39058d2dd0SWill Schurman getNamenull40058d2dd0SWill Schurman override fun getName(): String { 41058d2dd0SWill Schurman return "ExponentKernel" 42058d2dd0SWill Schurman } 43058d2dd0SWill Schurman consumeEventQueuenull44058d2dd0SWill Schurman override fun consumeEventQueue() { 45058d2dd0SWill Schurman if (ExponentKernelModuleProvider.eventQueue.size == 0) { 46058d2dd0SWill Schurman return 47058d2dd0SWill Schurman } 48058d2dd0SWill Schurman 49058d2dd0SWill Schurman val (name, data, callback) = ExponentKernelModuleProvider.eventQueue.remove() 50058d2dd0SWill Schurman 51058d2dd0SWill Schurman val eventId = UUID.randomUUID().toString() 52058d2dd0SWill Schurman data.putString("eventId", eventId) 53058d2dd0SWill Schurman 54058d2dd0SWill Schurman kernelEventCallbacks[eventId] = callback 55058d2dd0SWill Schurman 56058d2dd0SWill Schurman try { 57058d2dd0SWill Schurman reactApplicationContext 58058d2dd0SWill Schurman .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) 59058d2dd0SWill Schurman .emit(name, data) 60058d2dd0SWill Schurman } catch (e: Exception) { 61058d2dd0SWill Schurman onEventFailure(eventId, e.message) 62058d2dd0SWill Schurman } 63058d2dd0SWill Schurman 64058d2dd0SWill Schurman consumeEventQueue() 65058d2dd0SWill Schurman } 66058d2dd0SWill Schurman 67058d2dd0SWill Schurman //region Exported methods 68058d2dd0SWill Schurman @ReactMethod getSessionAsyncnull69058d2dd0SWill Schurman fun getSessionAsync(promise: Promise) { 70058d2dd0SWill Schurman val sessionString = exponentSharedPreferences.getString(ExponentSharedPreferences.ExponentSharedPreferencesKey.EXPO_AUTH_SESSION) 71058d2dd0SWill Schurman if (sessionString == null) { 72058d2dd0SWill Schurman promise.resolve(null) 73058d2dd0SWill Schurman return 74058d2dd0SWill Schurman } 75058d2dd0SWill Schurman 76058d2dd0SWill Schurman try { 77058d2dd0SWill Schurman val sessionJsonObject = JSONObject(sessionString) 78058d2dd0SWill Schurman val session = Arguments.fromBundle(BundleJSONConverter.convertToBundle(sessionJsonObject)) 79058d2dd0SWill Schurman promise.resolve(session) 80058d2dd0SWill Schurman } catch (e: Exception) { 81058d2dd0SWill Schurman promise.resolve(null) 82058d2dd0SWill Schurman EXL.e(TAG, e) 83058d2dd0SWill Schurman } 84058d2dd0SWill Schurman } 85058d2dd0SWill Schurman 86058d2dd0SWill Schurman @ReactMethod setSessionAsyncnull87058d2dd0SWill Schurman fun setSessionAsync(session: ReadableMap, promise: Promise) { 88058d2dd0SWill Schurman try { 89058d2dd0SWill Schurman val sessionJsonObject = JSONObject(session.toHashMap()) 90058d2dd0SWill Schurman exponentSharedPreferences.updateSession(sessionJsonObject) 91058d2dd0SWill Schurman promise.resolve(null) 92058d2dd0SWill Schurman } catch (e: Exception) { 93058d2dd0SWill Schurman promise.reject("ERR_SESSION_NOT_SAVED", "Could not save session secret", e) 94058d2dd0SWill Schurman EXL.e(TAG, e) 95058d2dd0SWill Schurman } 96058d2dd0SWill Schurman } 97058d2dd0SWill Schurman 98058d2dd0SWill Schurman @ReactMethod removeSessionAsyncnull99058d2dd0SWill Schurman fun removeSessionAsync(promise: Promise) { 100058d2dd0SWill Schurman try { 101058d2dd0SWill Schurman exponentSharedPreferences.removeSession() 102058d2dd0SWill Schurman promise.resolve(null) 103058d2dd0SWill Schurman } catch (e: Exception) { 104058d2dd0SWill Schurman promise.reject("ERR_SESSION_NOT_REMOVED", "Could not remove session secret", e) 105058d2dd0SWill Schurman EXL.e(TAG, e) 106058d2dd0SWill Schurman } 107058d2dd0SWill Schurman } 108058d2dd0SWill Schurman 109058d2dd0SWill Schurman @ReactMethod goToHomeFromErrorScreennull110058d2dd0SWill Schurman fun goToHomeFromErrorScreen() { 111058d2dd0SWill Schurman if (ErrorActivity.visibleActivity == null) { 112058d2dd0SWill Schurman // shouldn't ever get here 113058d2dd0SWill Schurman EXL.e(TAG, "visibleActivity was null in goToHomeFromErrorScreen") 114058d2dd0SWill Schurman return 115058d2dd0SWill Schurman } 116058d2dd0SWill Schurman ErrorActivity.visibleActivity!!.onClickHome() 117058d2dd0SWill Schurman } 118058d2dd0SWill Schurman 119058d2dd0SWill Schurman @ReactMethod reloadFromErrorScreennull120058d2dd0SWill Schurman fun reloadFromErrorScreen() { 121058d2dd0SWill Schurman if (ErrorActivity.visibleActivity == null) { 122058d2dd0SWill Schurman // shouldn't ever get here 123058d2dd0SWill Schurman EXL.e(TAG, "visibleActivity was null in reloadFromErrorScreen") 124058d2dd0SWill Schurman return 125058d2dd0SWill Schurman } 126058d2dd0SWill Schurman ErrorActivity.visibleActivity!!.onClickReload() 127058d2dd0SWill Schurman } 128058d2dd0SWill Schurman 129058d2dd0SWill Schurman @ReactMethod onEventSuccessnull130058d2dd0SWill Schurman fun onEventSuccess(eventId: String, result: ReadableMap) { 131058d2dd0SWill Schurman kernelEventCallbacks.remove(eventId)?.onEventSuccess(result) 132058d2dd0SWill Schurman } 133058d2dd0SWill Schurman 134058d2dd0SWill Schurman @ReactMethod onEventFailurenull135058d2dd0SWill Schurman fun onEventFailure(eventId: String, errorMessage: String?) { 136058d2dd0SWill Schurman kernelEventCallbacks.remove(eventId)?.onEventFailure(errorMessage) 137058d2dd0SWill Schurman } 138058d2dd0SWill Schurman 139058d2dd0SWill Schurman //region DevMenu 140058d2dd0SWill Schurman @ReactMethod doesCurrentTaskEnableDevtoolsAsyncnull141058d2dd0SWill Schurman fun doesCurrentTaskEnableDevtoolsAsync(promise: Promise) { 142058d2dd0SWill Schurman promise.resolve(devMenuManager.isDevSupportEnabledByCurrentActivity()) 143058d2dd0SWill Schurman } 144058d2dd0SWill Schurman 145058d2dd0SWill Schurman @ReactMethod getIsOnboardingFinishedAsyncnull146058d2dd0SWill Schurman fun getIsOnboardingFinishedAsync(promise: Promise) { 147058d2dd0SWill Schurman promise.resolve(devMenuManager.isOnboardingFinished()) 148058d2dd0SWill Schurman } 149058d2dd0SWill Schurman 150058d2dd0SWill Schurman @ReactMethod setIsOnboardingFinishedAsyncnull151058d2dd0SWill Schurman fun setIsOnboardingFinishedAsync(isOnboardingFinished: Boolean, promise: Promise) { 152058d2dd0SWill Schurman devMenuManager.setIsOnboardingFinished(isOnboardingFinished) 153058d2dd0SWill Schurman promise.resolve(null) 154058d2dd0SWill Schurman } 155058d2dd0SWill Schurman 156058d2dd0SWill Schurman @ReactMethod closeDevMenuAsyncnull157058d2dd0SWill Schurman fun closeDevMenuAsync(promise: Promise) { 158058d2dd0SWill Schurman devMenuManager.hideInCurrentActivity() 159058d2dd0SWill Schurman promise.resolve(true) 160058d2dd0SWill Schurman } 161058d2dd0SWill Schurman 162058d2dd0SWill Schurman @ReactMethod getDevMenuItemsToShowAsyncnull163058d2dd0SWill Schurman fun getDevMenuItemsToShowAsync(promise: Promise) { 164058d2dd0SWill Schurman val devMenuItems = devMenuManager.getMenuItems() 165058d2dd0SWill Schurman promise.resolve(devMenuItems) 166058d2dd0SWill Schurman } 167058d2dd0SWill Schurman 168058d2dd0SWill Schurman @ReactMethod selectDevMenuItemWithKeyAsyncnull169058d2dd0SWill Schurman fun selectDevMenuItemWithKeyAsync(itemKey: String?, promise: Promise) { 170058d2dd0SWill Schurman devMenuManager.selectItemWithKey(itemKey!!) 171058d2dd0SWill Schurman devMenuManager.requestToClose() 172058d2dd0SWill Schurman promise.resolve(true) 173058d2dd0SWill Schurman } 174058d2dd0SWill Schurman 175058d2dd0SWill Schurman @ReactMethod reloadAppAsyncnull176058d2dd0SWill Schurman fun reloadAppAsync(promise: Promise) { 177058d2dd0SWill Schurman devMenuManager.reloadApp() 178058d2dd0SWill Schurman devMenuManager.requestToClose() 179058d2dd0SWill Schurman promise.resolve(true) 180058d2dd0SWill Schurman } 181058d2dd0SWill Schurman 182058d2dd0SWill Schurman @ReactMethod goToHomeAsyncnull183058d2dd0SWill Schurman fun goToHomeAsync(promise: Promise) { 184058d2dd0SWill Schurman kernel.openHomeActivity() 185058d2dd0SWill Schurman devMenuManager.requestToClose() 186058d2dd0SWill Schurman promise.resolve(true) 187058d2dd0SWill Schurman } //endregion DevMenu 188058d2dd0SWill Schurman 189058d2dd0SWill Schurman //endregion Exported methods 190058d2dd0SWill Schurman companion object { 191058d2dd0SWill Schurman private val TAG = ExponentKernelModule::class.java.simpleName 192058d2dd0SWill Schurman 193058d2dd0SWill Schurman private var instance: ExponentKernelModule? = null 194058d2dd0SWill Schurman 195058d2dd0SWill Schurman private val kernelEventCallbacks = mutableMapOf<String, KernelEventCallback>() 196058d2dd0SWill Schurman queueEventnull197058d2dd0SWill Schurman fun queueEvent(name: String, data: WritableMap, callback: KernelEventCallback) { 198058d2dd0SWill Schurman queueEvent(KernelEvent(name, data, callback)) 199058d2dd0SWill Schurman } 200058d2dd0SWill Schurman queueEventnull201058d2dd0SWill Schurman fun queueEvent(event: KernelEvent) { 202058d2dd0SWill Schurman ExponentKernelModuleProvider.eventQueue.add(event) 203058d2dd0SWill Schurman instance?.consumeEventQueue() 204058d2dd0SWill Schurman } 205058d2dd0SWill Schurman } 206058d2dd0SWill Schurman 207058d2dd0SWill Schurman init { 208058d2dd0SWill Schurman NativeModuleDepsProvider.instance.inject(ExponentKernelModule::class.java, this) 209058d2dd0SWill Schurman instance = this 210058d2dd0SWill Schurman } 211058d2dd0SWill Schurman } 212