1 package host.exp.exponent.experience
2 
3 import com.facebook.react.bridge.NativeModule
4 import com.facebook.react.bridge.ReactApplicationContext
5 import expo.modules.adapters.react.ReactModuleRegistryProvider
6 import expo.modules.core.ModuleRegistry
7 import expo.modules.core.interfaces.RegistryLifecycleListener
8 import expo.modules.notifications.notifications.categories.ExpoNotificationCategoriesModule
9 import expo.modules.notifications.notifications.handling.NotificationsHandler
10 import expo.modules.notifications.notifications.scheduling.NotificationScheduler
11 import host.exp.exponent.utils.ScopedContext
12 import host.exp.exponent.kernel.ExperienceKey
13 import expo.modules.manifests.core.Manifest
14 import versioned.host.exp.exponent.modules.universal.*
15 import versioned.host.exp.exponent.modules.universal.notifications.ScopedServerRegistrationModule
16 
17 open class DetachedModuleRegistryAdapter(moduleRegistryProvider: ReactModuleRegistryProvider) :
18   ExpoModuleRegistryAdapter(moduleRegistryProvider) {
19 
20   override fun createNativeModules(
21     scopedContext: ScopedContext,
22     experienceKey: ExperienceKey,
23     experienceProperties: Map<String, Any?>,
24     manifest: Manifest,
25     experienceStableLegacyId: String,
26     otherModules: List<NativeModule>
27   ): List<NativeModule> {
28     val reactApplicationContext = scopedContext.context as ReactApplicationContext
29 
30     // We only use React application context, because we're detached -- no scopes
31     val moduleRegistry = mModuleRegistryProvider[scopedContext]
32 
33     moduleRegistry.registerInternalModule(
34       ConstantsBinding(
35         scopedContext,
36         experienceProperties,
37         manifest
38       )
39     )
40 
41     // Overriding expo-updates UpdatesService
42     moduleRegistry.registerInternalModule(UpdatesBinding(scopedContext, experienceProperties))
43 
44     // ReactAdapterPackage requires ReactContext
45     val reactContext = scopedContext.context as ReactApplicationContext
46     for (internalModule in mReactAdapterPackage.createInternalModules(reactContext)) {
47       moduleRegistry.registerInternalModule(internalModule)
48     }
49 
50     // Overriding ScopedUIManagerModuleWrapper from ReactAdapterPackage
51     moduleRegistry.registerInternalModule(ScopedUIManagerModuleWrapper(reactContext))
52 
53     // Overriding expo-file-system FileSystemModule
54     moduleRegistry.registerExportedModule(ScopedFileSystemModule(scopedContext))
55 
56     // Overriding expo-secure-store
57     moduleRegistry.registerExportedModule(ScopedSecureStoreModule(scopedContext))
58 
59     // Certain notifications classes should share `SharedPreferences` object with the notifications services, so we don't want to use scoped context.
60     moduleRegistry.registerExportedModule(NotificationScheduler(scopedContext.baseContext))
61     moduleRegistry.registerExportedModule(ExpoNotificationCategoriesModule(scopedContext.baseContext))
62     moduleRegistry.registerExportedModule(NotificationsHandler(scopedContext.baseContext))
63     // We consciously pass scoped context to ScopedServerRegistrationModule
64     // so it can access legacy scoped backed-up storage and migrates
65     // the legacy UUID to scoped non-backed-up storage.
66     moduleRegistry.registerExportedModule(ScopedServerRegistrationModule(scopedContext))
67 
68     // Adding other modules (not universal) to module registry as consumers.
69     // It allows these modules to refer to universal modules.
70     for (otherModule in otherModules) {
71       if (otherModule is RegistryLifecycleListener) {
72         moduleRegistry.registerExtraListener(otherModule as RegistryLifecycleListener)
73       }
74     }
75     configureModuleRegistry(moduleRegistry, reactApplicationContext)
76     return getNativeModulesFromModuleRegistry(reactApplicationContext, moduleRegistry)
77   }
78 
79   protected open fun configureModuleRegistry(
80     moduleRegistry: ModuleRegistry,
81     reactContext: ReactApplicationContext
82   ) {
83     // Subclasses may add more modules here.
84   }
85 }
86