1 package expo.modules.devmenu.websockets 2 3 import android.util.Log 4 import com.facebook.react.ReactInstanceManager 5 import com.facebook.react.bridge.UiThreadUtil 6 import com.facebook.react.modules.core.RCTNativeAppEventEmitter 7 import com.facebook.react.packagerconnection.NotificationOnlyHandler 8 import expo.interfaces.devmenu.DevMenuManagerInterface 9 import expo.modules.devmenu.devtools.DevMenuDevToolsDelegate 10 import org.json.JSONObject 11 import java.lang.ref.WeakReference 12 13 class DevMenuCommandHandlersProvider( 14 private val manager: DevMenuManagerInterface, 15 reactInstanceManager: ReactInstanceManager 16 ) { 17 private val _instanceManager = WeakReference(reactInstanceManager) 18 private val instanceManager 19 get() = _instanceManager.get() 20 21 private val onReload = object : NotificationOnlyHandler() { onNotificationnull22 override fun onNotification(params: Any?) { 23 manager.closeMenu() 24 UiThreadUtil.runOnUiThread { 25 instanceManager?.devSupportManager?.handleReloadJS() 26 } 27 } 28 } 29 30 private val onDevMenu = object : NotificationOnlyHandler() { onNotificationnull31 override fun onNotification(params: Any?) { 32 val activity = instanceManager?.currentReactContext?.currentActivity ?: return 33 manager.toggleMenu(activity) 34 } 35 } 36 37 private val onDevCommand = object : NotificationOnlyHandler() { onNotificationnull38 override fun onNotification(params: Any?) { 39 val instanceManager = instanceManager ?: return 40 val devDelegate = DevMenuDevToolsDelegate(manager, instanceManager) 41 42 if (params is JSONObject) { 43 val command = params.optString("name") ?: return 44 45 when (command) { 46 "reload" -> devDelegate.reload() 47 "toggleDevMenu" -> { 48 val activity = instanceManager.currentReactContext?.currentActivity ?: return 49 manager.toggleMenu(activity) 50 } 51 "toggleRemoteDebugging" -> devDelegate.toggleRemoteDebugging() 52 "toggleElementInspector" -> devDelegate.toggleElementInspector() 53 "togglePerformanceMonitor" -> { 54 val activity = instanceManager.currentReactContext?.currentActivity ?: return 55 devDelegate.togglePerformanceMonitor(activity) 56 } 57 "openJSInspector" -> devDelegate.openJSInspector() 58 "reconnectReactDevTools" -> { 59 // Emit the `RCTDevMenuShown` for the app to reconnect react-devtools 60 // https://github.com/facebook/react-native/blob/22ba1e45c52edcc345552339c238c1f5ef6dfc65/Libraries/Core/setUpReactDevTools.js#L80 61 instanceManager.currentReactContext?.getJSModule(RCTNativeAppEventEmitter::class.java)?.emit("RCTDevMenuShown", null) 62 } 63 else -> Log.w("DevMenu", "Unknown command: $command") 64 } 65 } 66 } 67 } 68 createCommandHandlersnull69 fun createCommandHandlers(): Map<String, NotificationOnlyHandler> { 70 return mapOf( 71 "reload" to onReload, 72 "devMenu" to onDevMenu, 73 "sendDevCommand" to onDevCommand 74 ) 75 } 76 } 77