1 package expo.modules.devmenu
2 
3 import android.app.Activity
4 import android.content.Context
5 import android.os.Bundle
6 import android.view.KeyEvent
7 import android.view.View
8 import android.view.ViewGroup
9 import com.facebook.react.ReactApplication
10 import com.facebook.react.ReactPackage
11 import com.facebook.react.bridge.NativeModule
12 import com.facebook.react.bridge.ReactApplicationContext
13 import com.facebook.react.uimanager.ReactShadowNode
14 import com.facebook.react.uimanager.ViewManager
15 import expo.modules.core.interfaces.Package
16 import expo.modules.core.interfaces.ReactActivityHandler
17 import expo.modules.core.interfaces.ReactActivityLifecycleListener
18 import expo.modules.devmenu.extensions.DevMenuExtension
19 import expo.modules.devmenu.react.DevMenuAwareReactActivity
20 
21 object DevMenuPackageDelegate {
22   @JvmField
23   var enableAutoSetup: Boolean? = null
24 
shouldEnableAutoSetupnull25   internal fun shouldEnableAutoSetup(activityContext: Context?): Boolean {
26     if (enableAutoSetup != null) {
27       // if someone else has set this explicitly, use that value
28       return enableAutoSetup!!
29     }
30     if (activityContext != null && activityContext is DevMenuAwareReactActivity) {
31       // Backwards compatibility -- if the MainActivity is already an instance of
32       // DevMenuAwareReactActivity, we skip auto-setup.
33       return false
34     }
35     return true
36   }
37 }
38 
39 class DevMenuPackage : Package, ReactPackage {
createNativeModulesnull40   override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
41     return listOf(
42       DevMenuExtension(reactContext),
43     )
44   }
45 
createViewManagersnull46   override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<View, ReactShadowNode<*>>> {
47     return emptyList()
48   }
49 
createReactActivityLifecycleListenersnull50   override fun createReactActivityLifecycleListeners(activityContext: Context?): List<ReactActivityLifecycleListener> {
51     if (!DevMenuPackageDelegate.shouldEnableAutoSetup(activityContext) || !BuildConfig.DEBUG) {
52       return emptyList()
53     }
54 
55     return listOf(
56       object : ReactActivityLifecycleListener {
57         override fun onCreate(activity: Activity, savedInstanceState: Bundle?) {
58           if (!DevMenuManager.isInitialized()) {
59             DevMenuManager.initializeWithReactNativeHost((activity.application as ReactApplication).reactNativeHost)
60           } else {
61             DevMenuManager.synchronizeDelegate()
62           }
63         }
64       }
65     )
66   }
67 
createReactActivityHandlersnull68   override fun createReactActivityHandlers(activityContext: Context?): List<ReactActivityHandler> {
69     if (!DevMenuPackageDelegate.shouldEnableAutoSetup(activityContext) || !BuildConfig.DEBUG) {
70       return emptyList()
71     }
72 
73     return listOf(
74       object : ReactActivityHandler {
75         override fun createReactRootViewContainer(activity: Activity): ViewGroup {
76           return DevMenuReactRootViewContainer(activity as Context)
77         }
78 
79         override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
80           return DevMenuManager.onKeyEvent(keyCode, event)
81         }
82       }
83     )
84   }
85 }
86