expo-modules-core 0.4.8 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/android/build.gradle +30 -2
  3. package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +42 -5
  4. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +49 -5
  5. package/android/src/main/java/expo/modules/core/BasePackage.java +6 -0
  6. package/android/src/main/java/expo/modules/core/ModulePriorities.kt +25 -0
  7. package/android/src/main/java/expo/modules/core/interfaces/ActivityEventListener.java +3 -1
  8. package/android/src/main/java/expo/modules/core/interfaces/ApplicationLifecycleListener.java +10 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/Package.java +4 -0
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +21 -0
  11. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityLifecycleListener.java +14 -0
  12. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +70 -0
  13. package/android/src/main/java/expo/modules/core/utilities/KotlinUtilities.kt +23 -0
  14. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +166 -0
  15. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +9 -0
  16. package/android/src/main/java/expo/modules/kotlin/ExpoModulesHelper.kt +18 -0
  17. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +24 -0
  18. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +98 -0
  19. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +41 -0
  20. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +56 -0
  21. package/android/src/main/java/expo/modules/kotlin/ModulesProvider.kt +7 -0
  22. package/android/src/main/java/expo/modules/kotlin/Promise.kt +13 -0
  23. package/android/src/main/java/expo/modules/kotlin/ReactLifecycleDelegate.kt +39 -0
  24. package/android/src/main/java/expo/modules/kotlin/ReadableArrayIterator.kt +14 -0
  25. package/android/src/main/java/expo/modules/kotlin/ReadableTypeExtensions.kt +18 -0
  26. package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructor.kt +5 -0
  27. package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructorFactory.kt +31 -0
  28. package/android/src/main/java/expo/modules/kotlin/allocators/UnsafeAllocator.kt +49 -0
  29. package/android/src/main/java/expo/modules/kotlin/events/EventListener.kt +39 -0
  30. package/android/src/main/java/expo/modules/kotlin/events/EventName.kt +31 -0
  31. package/android/src/main/java/expo/modules/kotlin/events/EventsDefinition.kt +3 -0
  32. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +26 -0
  33. package/android/src/main/java/expo/modules/kotlin/events/OnActivityResultPayload.kt +8 -0
  34. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +70 -0
  35. package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +50 -0
  36. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +14 -0
  37. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +15 -0
  38. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +24 -0
  39. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +227 -0
  40. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +16 -0
  41. package/android/src/main/java/expo/modules/kotlin/records/Field.kt +5 -0
  42. package/android/src/main/java/expo/modules/kotlin/records/Record.kt +3 -0
  43. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +55 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +14 -0
  45. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +44 -0
  46. package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +60 -0
  47. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +84 -0
  48. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +25 -0
  49. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +39 -0
  50. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +28 -0
  51. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +19 -0
  52. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +107 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +10 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +17 -0
  55. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
  56. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +21 -0
  57. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +41 -0
  58. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +40 -0
  59. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +21 -0
  60. package/android/src/main/java/expo/modules/kotlin/views/ViewWrapperDelegateHolder.kt +5 -0
  61. package/build/NativeModulesProxy.native.d.ts +4 -0
  62. package/build/NativeModulesProxy.native.js +14 -1
  63. package/build/NativeModulesProxy.native.js.map +1 -1
  64. package/build/NativeModulesProxy.types.d.ts +3 -0
  65. package/build/NativeModulesProxy.types.js.map +1 -1
  66. package/build/NativeViewManagerAdapter.native.js +1 -1
  67. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  68. package/ios/AppDelegates/EXAppDelegateWrapper.h +19 -0
  69. package/ios/AppDelegates/EXAppDelegateWrapper.m +45 -0
  70. package/ios/AppDelegates/EXAppDelegatesLoader.h +15 -0
  71. package/ios/AppDelegates/EXAppDelegatesLoader.m +30 -0
  72. package/ios/AppDelegates/EXLegacyAppDelegateWrapper.h +16 -0
  73. package/ios/{EXAppDelegateWrapper.m → AppDelegates/EXLegacyAppDelegateWrapper.m} +2 -2
  74. package/ios/AppDelegates/ExpoAppDelegate.swift +282 -0
  75. package/ios/AppDelegates/ExpoAppDelegateSubscriber.swift +24 -0
  76. package/ios/EXAppDefines.h +26 -0
  77. package/ios/EXAppDefines.m +61 -0
  78. package/ios/ExpoModulesCore.podspec +8 -3
  79. package/ios/JSI/ExpoModulesProxySpec.h +24 -0
  80. package/ios/JSI/ExpoModulesProxySpec.mm +135 -0
  81. package/ios/JSI/JSIConversions.h +42 -0
  82. package/ios/JSI/JSIConversions.mm +164 -0
  83. package/ios/JSI/JSIInstaller.h +19 -0
  84. package/ios/JSI/JSIInstaller.mm +22 -0
  85. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -6
  86. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +6 -0
  87. package/ios/NativeModulesProxy/{EXNativeModulesProxy.m → EXNativeModulesProxy.mm} +63 -17
  88. package/ios/ReactDelegates/EXRCTBridgeDelegateInterceptor.h +16 -0
  89. package/ios/ReactDelegates/EXRCTBridgeDelegateInterceptor.m +49 -0
  90. package/ios/ReactDelegates/EXReactDelegateWrapper+Private.h +18 -0
  91. package/ios/ReactDelegates/EXReactDelegateWrapper.h +25 -0
  92. package/ios/ReactDelegates/EXReactDelegateWrapper.m +40 -0
  93. package/ios/ReactDelegates/ExpoReactDelegate.swift +37 -0
  94. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +52 -0
  95. package/ios/ReactDelegates/ModulePriorities.swift +20 -0
  96. package/ios/Services/EXReactNativeEventEmitter.h +6 -0
  97. package/ios/Services/EXReactNativeEventEmitter.m +15 -0
  98. package/ios/Swift/AppContext.swift +14 -1
  99. package/ios/Swift/Arguments/AnyArgument.swift +14 -0
  100. package/ios/Swift/Arguments/AnyArgumentType.swift +13 -0
  101. package/ios/Swift/Arguments/ArgumentType.swift +24 -0
  102. package/ios/Swift/Arguments/ConvertibleArgument.swift +15 -0
  103. package/ios/Swift/Arguments/Convertibles.swift +107 -0
  104. package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +42 -0
  105. package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +16 -0
  106. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +105 -0
  107. package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +49 -0
  108. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +15 -0
  109. package/ios/Swift/Arguments/Types/RawArgumentType.swift +25 -0
  110. package/ios/Swift/Conversions.swift +199 -7
  111. package/ios/Swift/EventListener.swift +37 -5
  112. package/ios/Swift/Functions/AnyFunction.swift +42 -0
  113. package/ios/Swift/{Methods/ConcreteMethod.swift → Functions/ConcreteFunction.swift} +32 -34
  114. package/ios/Swift/ModuleHolder.swift +86 -20
  115. package/ios/Swift/ModuleRegistry.swift +19 -8
  116. package/ios/Swift/Modules/AnyModule.swift +8 -8
  117. package/ios/Swift/Modules/Module.swift +11 -0
  118. package/ios/Swift/Modules/ModuleDefinition.swift +55 -15
  119. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +1 -1
  120. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +149 -54
  121. package/ios/Swift/ModulesProvider.swift +19 -0
  122. package/ios/Swift/Promise.swift +1 -1
  123. package/ios/Swift/Records/Field.swift +1 -1
  124. package/ios/Swift/Records/Record.swift +8 -1
  125. package/ios/Swift/SwiftInteropBridge.swift +46 -17
  126. package/ios/Swift/Views/AnyViewProp.swift +2 -2
  127. package/ios/Swift/Views/ConcreteViewProp.swift +37 -10
  128. package/ios/Swift/Views/ViewModuleWrapper.swift +9 -4
  129. package/ios/Swift.h +9 -0
  130. package/ios/Tests/ArgumentTypeSpec.swift +145 -0
  131. package/ios/Tests/ConstantsSpec.swift +36 -0
  132. package/ios/Tests/ConvertiblesSpec.swift +265 -0
  133. package/ios/Tests/EXAppDefinesTest.m +99 -0
  134. package/ios/Tests/{MethodSpec.swift → FunctionSpec.swift} +69 -54
  135. package/ios/Tests/FunctionWithConvertiblesSpec.swift +66 -0
  136. package/ios/Tests/Mocks/ModuleMocks.swift +21 -7
  137. package/ios/Tests/ModuleEventListenersSpec.swift +17 -16
  138. package/ios/Tests/ModuleRegistrySpec.swift +4 -7
  139. package/package.json +3 -3
  140. package/src/NativeModulesProxy.native.ts +22 -2
  141. package/src/NativeModulesProxy.types.ts +8 -0
  142. package/src/NativeViewManagerAdapter.native.tsx +1 -1
  143. package/android/src/main/java/expo/modules/core/interfaces/ApplicationLifecycleListener.kt +0 -9
  144. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityLifecycleListener.kt +0 -11
  145. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.kt +0 -51
  146. package/ios/EXAppDelegateWrapper.h +0 -13
  147. package/ios/Swift/Methods/AnyArgumentType.swift +0 -48
  148. package/ios/Swift/Methods/AnyMethod.swift +0 -31
  149. package/ios/Swift/Methods/AnyMethodArgument.swift +0 -13
package/CHANGELOG.md CHANGED
@@ -10,7 +10,38 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
- ## 0.4.8 — 2021-11-11
13
+ ## 0.6.1 — 2021-12-08
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
17
+ ## 0.6.0 — 2021-12-03
18
+
19
+ ### 🎉 New features
20
+
21
+ - Made `Foundation.URL` a convertible type to consistently normalize file paths to file URLs. ([#15278](https://github.com/expo/expo/pull/15278) by [@tsapeta](https://github.com/tsapeta))
22
+ - Improve external Android handlers or listeners backward compatibility by Java 8 interface default method. ([#15421](https://github.com/expo/expo/pull/15421) by [@kudo](https://github.com/kudo))
23
+
24
+ ### 💡 Others
25
+
26
+ - Add parameter to `ReactNativeHostHandler.onDidCreateReactInstanceManager` on Android. ([#15221](https://github.com/expo/expo/pull/15221) by [@esamelson](https://github.com/esamelson))
27
+ - Make the no-argument module initializer unavailable — `onCreate` definition component should be used instead. ([#15262](https://github.com/expo/expo/pull/15262) by [@tsapeta](https://github.com/tsapeta))
28
+
29
+ ## 0.5.0 — 2021-11-17
30
+
31
+ ### 🎉 New features
32
+
33
+ - Method calls on iOS now can go through the JSI instead of the bridge (opt-in feature). ([#14626](https://github.com/expo/expo/pull/14626) by [@tsapeta](https://github.com/tsapeta))
34
+ - `AppDelegateWrapper` is now written in Swift and is independent of the singleton modules. ([#14867](https://github.com/expo/expo/pull/14867) by [@tsapeta](https://github.com/tsapeta))
35
+ - Implemented sending native events to JavaScript in Sweet API on iOS. ([#14958](https://github.com/expo/expo/pull/14958) by [@tsapeta](https://github.com/tsapeta))
36
+ - [Sweet API] Introduced Convertibles on iOS — a way to use custom types as method arguments if they can be converted from JavaScript values. Provided implementation for some common CoreGraphics types. ([#14988](https://github.com/expo/expo/pull/14988) by [@tsapeta](https://github.com/tsapeta))
37
+ - Introduce `ReactActivityHandler` and support `createReactRootView` hook. ([#14883](https://github.com/expo/expo/pull/14883) by [@kudo](https://github.com/kudo))
38
+ - [Sweet API] Added support for array types in method arguments on iOS. ([#15042](https://github.com/expo/expo/pull/15042) by [@tsapeta](https://github.com/tsapeta))
39
+ - [Sweet API] Added support for optional types in method arguments on iOS. ([#15068](https://github.com/expo/expo/pull/15068) by [@tsapeta](https://github.com/tsapeta))
40
+ - [Sweet API] Added support for enums in method arguments on iOS. ([#15129](https://github.com/expo/expo/pull/15129) by [@tsapeta](https://github.com/tsapeta))
41
+ - [Sweet API] Automatic conversion is now available for view props setters. ([#15132](https://github.com/expo/expo/pull/15132) by [@tsapeta](https://github.com/tsapeta))
42
+ - [Sweet API] Added experimental implementation of the new API in Kotlin. (by [@lukmccall](https://github.com/lukmccall))
43
+ - Introduce EXAppDefines to get app building configurations. ([#14428](https://github.com/expo/expo/pull/14428) by [@kudo](https://github.com/kudo))
44
+ - Introduce React Native bridge delegate handlers on iOS. ([#15138](https://github.com/expo/expo/pull/15138) by [@kudo](https://github.com/kudo))
14
45
 
15
46
  ### 🐛 Bug fixes
16
47
 
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.4.8'
6
+ version = '0.6.1'
7
7
 
8
8
  buildscript {
9
9
  // Simple helper that allows the root project to override versions declared by this library.
@@ -58,7 +58,7 @@ android {
58
58
  targetSdkVersion safeExtGet("targetSdkVersion", 30)
59
59
  consumerProguardFiles 'proguard-rules.pro'
60
60
  versionCode 1
61
- versionName "0.4.8"
61
+ versionName "0.6.1"
62
62
  }
63
63
  lintOptions {
64
64
  abortOnError false
@@ -66,10 +66,23 @@ android {
66
66
  kotlinOptions {
67
67
  jvmTarget = JavaVersion.VERSION_1_8
68
68
  }
69
+
70
+ testOptions {
71
+ unitTests.all {
72
+ testLogging {
73
+ outputs.upToDateWhen { false }
74
+ events "passed", "failed", "skipped", "standardError"
75
+ showCauses true
76
+ showExceptions true
77
+ showStandardStreams true
78
+ }
79
+ }
80
+ }
69
81
  }
70
82
 
71
83
  dependencies {
72
84
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '1.4.21')}"
85
+ implementation "org.jetbrains.kotlin:kotlin-reflect:${safeExtGet('kotlinVersion', '1.4.21')}"
73
86
  implementation 'androidx.annotation:annotation:1.2.0'
74
87
 
75
88
  // used only in `expo.modules.core.errors.ModuleDestroyedException` for API export
@@ -77,4 +90,19 @@ dependencies {
77
90
 
78
91
  //noinspection GradleDynamicVersion
79
92
  implementation 'com.facebook.react:react-native:+'
93
+
94
+ testImplementation 'androidx.test:core:1.4.0'
95
+ testImplementation 'junit:junit:4.13.1'
96
+ testImplementation 'io.mockk:mockk:1.10.6'
97
+ testImplementation "com.google.truth:truth:1.1.2"
98
+ }
99
+
100
+ /**
101
+ * To make the users of annotations @OptIn and @RequiresOptIn aware of their experimental status,
102
+ * the compiler raises warnings when compiling the code with these annotations:
103
+ * This class can only be used with the compiler argument '-Xopt-in=kotlin.RequiresOptIn'
104
+ * To remove the warnings, we add the compiler argument -Xopt-in=kotlin.RequiresOptIn.
105
+ */
106
+ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
107
+ kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
80
108
  }
@@ -5,14 +5,18 @@ import com.facebook.react.bridge.NativeModule;
5
5
  import com.facebook.react.bridge.ReactApplicationContext;
6
6
  import com.facebook.react.uimanager.ViewManager;
7
7
 
8
+ import java.util.ArrayList;
9
+ import java.util.List;
10
+ import java.util.Objects;
11
+
8
12
  import expo.modules.adapters.react.views.SimpleViewManagerAdapter;
9
13
  import expo.modules.adapters.react.views.ViewGroupManagerAdapter;
10
14
  import expo.modules.core.ModuleRegistry;
11
15
  import expo.modules.core.interfaces.InternalModule;
12
16
  import expo.modules.core.interfaces.Package;
13
-
14
- import java.util.ArrayList;
15
- import java.util.List;
17
+ import expo.modules.kotlin.KotlinInteropModuleRegistry;
18
+ import expo.modules.kotlin.ModulesProvider;
19
+ import expo.modules.kotlin.views.ViewWrapperDelegateHolder;
16
20
 
17
21
  /**
18
22
  * An adapter over {@link ModuleRegistry}, compatible with React (implementing {@link ReactPackage}).
@@ -21,7 +25,11 @@ import java.util.List;
21
25
  */
22
26
  public class ModuleRegistryAdapter implements ReactPackage {
23
27
  protected ReactModuleRegistryProvider mModuleRegistryProvider;
28
+ protected ModulesProvider mModulesProvider;
24
29
  protected ReactAdapterPackage mReactAdapterPackage = new ReactAdapterPackage();
30
+ private NativeModulesProxy mModulesProxy;
31
+ // We need to save all view holders to update them when the new kotlin module registry will be created.
32
+ private List<ViewWrapperDelegateHolder> mWrapperDelegateHolders = null;
25
33
 
26
34
  public ModuleRegistryAdapter(List<Package> packageList) {
27
35
  mModuleRegistryProvider = new ReactModuleRegistryProvider(packageList, null);
@@ -31,6 +39,11 @@ public class ModuleRegistryAdapter implements ReactPackage {
31
39
  mModuleRegistryProvider = moduleRegistryProvider;
32
40
  }
33
41
 
42
+ public ModuleRegistryAdapter(ReactModuleRegistryProvider moduleRegistryProvider, ModulesProvider modulesProvider) {
43
+ mModuleRegistryProvider = moduleRegistryProvider;
44
+ mModulesProvider = modulesProvider;
45
+ }
46
+
34
47
  @Override
35
48
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
36
49
  ModuleRegistry moduleRegistry = mModuleRegistryProvider.get(reactContext);
@@ -39,13 +52,20 @@ public class ModuleRegistryAdapter implements ReactPackage {
39
52
  moduleRegistry.registerInternalModule(internalModule);
40
53
  }
41
54
 
42
- return getNativeModulesFromModuleRegistry(reactContext, moduleRegistry);
55
+ List<NativeModule> nativeModules = getNativeModulesFromModuleRegistry(reactContext, moduleRegistry);
56
+ if (mWrapperDelegateHolders != null) {
57
+ KotlinInteropModuleRegistry kotlinInteropModuleRegistry = mModulesProxy.getKotlinInteropModuleRegistry();
58
+ kotlinInteropModuleRegistry.updateModuleHoldersInViewManagers(mWrapperDelegateHolders);
59
+ }
60
+
61
+ return nativeModules;
43
62
  }
44
63
 
45
64
  protected List<NativeModule> getNativeModulesFromModuleRegistry(ReactApplicationContext reactContext, ModuleRegistry moduleRegistry) {
46
65
  List<NativeModule> nativeModulesList = new ArrayList<>(2);
47
66
 
48
- nativeModulesList.add(new NativeModulesProxy(reactContext, moduleRegistry));
67
+ mModulesProxy = createNativeModulesProxy(reactContext, moduleRegistry);
68
+ nativeModulesList.add(mModulesProxy);
49
69
 
50
70
  // Add listener that will notify expo.modules.core.ModuleRegistry when all modules are ready
51
71
  nativeModulesList.add(new ModuleRegistryReadyNotifier(moduleRegistry));
@@ -73,6 +93,23 @@ public class ModuleRegistryAdapter implements ReactPackage {
73
93
  break;
74
94
  }
75
95
  }
96
+
97
+ // We assume that `createNativeModules` was called first.
98
+ NativeModulesProxy modulesProxy = Objects.requireNonNull(mModulesProxy);
99
+ KotlinInteropModuleRegistry kotlinInteropModuleRegistry = modulesProxy.getKotlinInteropModuleRegistry();
100
+ List<ViewManager<?, ?>> kViewManager = kotlinInteropModuleRegistry.exportViewManagers();
101
+ // Saves all holders that needs to be in sync with module registry
102
+ mWrapperDelegateHolders = kotlinInteropModuleRegistry.extractViewManagersDelegateHolders(kViewManager);
103
+ viewManagerList.addAll(kViewManager);
104
+
76
105
  return viewManagerList;
77
106
  }
107
+
108
+ private NativeModulesProxy createNativeModulesProxy(ReactApplicationContext reactContext, ModuleRegistry moduleRegistry) {
109
+ if (mModulesProvider != null) {
110
+ return new NativeModulesProxy(reactContext, moduleRegistry, mModulesProvider);
111
+ } else {
112
+ return new NativeModulesProxy(reactContext, moduleRegistry);
113
+ }
114
+ }
78
115
  }
@@ -14,13 +14,19 @@ import expo.modules.core.ExportedModule;
14
14
  import expo.modules.core.ModuleRegistry;
15
15
  import expo.modules.core.ViewManager;
16
16
  import expo.modules.core.interfaces.ExpoMethod;
17
+ import expo.modules.kotlin.ExpoModulesHelper;
18
+ import expo.modules.kotlin.KotlinInteropModuleRegistry;
19
+ import expo.modules.kotlin.KPromiseWrapper;
20
+ import expo.modules.kotlin.ModulesProvider;
17
21
 
22
+ import java.lang.ref.WeakReference;
18
23
  import java.lang.reflect.Method;
19
24
  import java.util.ArrayList;
20
25
  import java.util.Collection;
21
26
  import java.util.HashMap;
22
27
  import java.util.List;
23
28
  import java.util.Map;
29
+ import java.util.Objects;
24
30
 
25
31
  import javax.annotation.Nullable;
26
32
 
@@ -45,12 +51,36 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
45
51
  private ModuleRegistry mModuleRegistry;
46
52
  private Map<String, Map<String, Integer>> mExportedMethodsKeys;
47
53
  private Map<String, SparseArray<String>> mExportedMethodsReverseKeys;
54
+ private KotlinInteropModuleRegistry mKotlinInteropModuleRegistry;
48
55
 
49
56
  public NativeModulesProxy(ReactApplicationContext context, ModuleRegistry moduleRegistry) {
50
57
  super(context);
51
58
  mModuleRegistry = moduleRegistry;
52
59
  mExportedMethodsKeys = new HashMap<>();
53
60
  mExportedMethodsReverseKeys = new HashMap<>();
61
+
62
+ mKotlinInteropModuleRegistry = new KotlinInteropModuleRegistry(
63
+ Objects.requireNonNull(ExpoModulesHelper.Companion.getModulesProvider()),
64
+ moduleRegistry,
65
+ new WeakReference<>(context)
66
+ );
67
+ }
68
+
69
+ public NativeModulesProxy(ReactApplicationContext context, ModuleRegistry moduleRegistry, ModulesProvider modulesProvider) {
70
+ super(context);
71
+ mModuleRegistry = moduleRegistry;
72
+ mExportedMethodsKeys = new HashMap<>();
73
+ mExportedMethodsReverseKeys = new HashMap<>();
74
+
75
+ mKotlinInteropModuleRegistry = new KotlinInteropModuleRegistry(
76
+ Objects.requireNonNull(modulesProvider),
77
+ moduleRegistry,
78
+ new WeakReference<>(context)
79
+ );
80
+ }
81
+
82
+ public KotlinInteropModuleRegistry getKotlinInteropModuleRegistry() {
83
+ return mKotlinInteropModuleRegistry;
54
84
  }
55
85
 
56
86
  @Override
@@ -79,11 +109,19 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
79
109
  exportedMethodsMap.put(moduleName, exportedMethods);
80
110
  }
81
111
 
112
+ modulesConstants.putAll(mKotlinInteropModuleRegistry.exportedModulesConstants());
113
+ exportedMethodsMap.putAll(mKotlinInteropModuleRegistry.exportMethods((name, info) -> {
114
+ assignExportedMethodsKeys(name, (List<Map<String, Object>>) info);
115
+ return null;
116
+ }));
117
+
82
118
  for (ViewManager viewManager : viewManagers) {
83
119
  viewManagersNames.add(viewManager.getName());
84
120
  }
85
121
 
86
- Map<String, Object> constants = new HashMap<>(2);
122
+ viewManagersNames.addAll(mKotlinInteropModuleRegistry.exportedViewManagersNames());
123
+
124
+ Map<String, Object> constants = new HashMap<>(3);
87
125
  constants.put(MODULES_CONSTANTS_KEY, modulesConstants);
88
126
  constants.put(EXPORTED_METHODS_KEY, exportedMethodsMap);
89
127
  constants.put(VIEW_MANAGERS_NAMES_KEY, viewManagersNames);
@@ -110,6 +148,11 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
110
148
  return;
111
149
  }
112
150
 
151
+ if (mKotlinInteropModuleRegistry.hasModule(moduleName)) {
152
+ mKotlinInteropModuleRegistry.callMethod(moduleName, methodName, arguments, new KPromiseWrapper(promise));
153
+ return;
154
+ }
155
+
113
156
  try {
114
157
  List<Object> nativeArguments = getNativeArgumentsForMethod(arguments, mModuleRegistry.getExportedModule(moduleName).getExportedMethodInfos().get(methodName));
115
158
  nativeArguments.add(new PromiseWrapper(promise));
@@ -121,9 +164,9 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
121
164
  promise.reject(UNEXPECTED_ERROR, "Encountered an exception while calling native method: " + e.getMessage(), e);
122
165
  } catch (NoSuchMethodException e) {
123
166
  promise.reject(
124
- UNDEFINED_METHOD_ERROR,
125
- "Method " + methodName + " of Java module " + moduleName + " is undefined.",
126
- e
167
+ UNDEFINED_METHOD_ERROR,
168
+ "Method " + methodName + " of Java module " + moduleName + " is undefined.",
169
+ e
127
170
  );
128
171
  }
129
172
  }
@@ -157,7 +200,7 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
157
200
  * Returns methodInfo Map (a Map containing a value for key argumentsCount).
158
201
  */
159
202
  private Map<String, Object> getMethodInfo(String name, Method method) {
160
- Map<String, Object> info = new HashMap<>(1);
203
+ Map<String, Object> info = new HashMap<>(2);
161
204
  info.put(METHOD_INFO_NAME, name);
162
205
  info.put(METHOD_INFO_ARGUMENTS_COUNT, method.getParameterTypes().length - 1); // - 1 is for the Promise
163
206
  return info;
@@ -200,5 +243,6 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
200
243
  @Override
201
244
  public void onCatalystInstanceDestroy() {
202
245
  mModuleRegistry.onDestroy();
246
+ mKotlinInteropModuleRegistry.onDestroy();
203
247
  }
204
248
  }
@@ -5,6 +5,7 @@ import android.content.Context;
5
5
  import expo.modules.core.interfaces.ApplicationLifecycleListener;
6
6
  import expo.modules.core.interfaces.InternalModule;
7
7
  import expo.modules.core.interfaces.Package;
8
+ import expo.modules.core.interfaces.ReactActivityHandler;
8
9
  import expo.modules.core.interfaces.ReactActivityLifecycleListener;
9
10
  import expo.modules.core.interfaces.ReactNativeHostHandler;
10
11
  import expo.modules.core.interfaces.SingletonModule;
@@ -49,4 +50,9 @@ public class BasePackage implements Package {
49
50
  public List<ReactActivityLifecycleListener> createReactActivityLifecycleListeners(Context activityContext) {
50
51
  return Collections.emptyList();
51
52
  }
53
+
54
+ @Override
55
+ public List<ReactActivityHandler> createReactActivityHandlers(Context activityContext) {
56
+ return Collections.emptyList();
57
+ }
52
58
  }
@@ -0,0 +1,25 @@
1
+ package expo.modules.core
2
+
3
+ /**
4
+ * This class determines the order of the following handlers/listeners
5
+ * - {@link ReactNativeHostHandler}
6
+ * - {@link ApplicationLifecycleListener}
7
+ * - {@link ReactActivityLifecycleListener}
8
+ * - {@link ReactActivityHandler}
9
+ *
10
+ * The priority is only for internal use and we maintain a pre-defined {@link SUPPORTED_MODULES} map.
11
+ */
12
+ object ModulePriorities {
13
+ fun get(packageName: String?): Int {
14
+ return packageName?.let {
15
+ return SUPPORTED_MODULES[it] ?: 0
16
+ } ?: 0
17
+ }
18
+
19
+ private val SUPPORTED_MODULES = mapOf(
20
+ // {key} to {value}
21
+ // key: full qualified class name
22
+ // value: priority value, the higher value takes precedence
23
+ "expo.modules.updates.UpdatesPackage" to 10,
24
+ )
25
+ }
@@ -3,8 +3,10 @@ package expo.modules.core.interfaces;
3
3
  import android.app.Activity;
4
4
  import android.content.Intent;
5
5
 
6
+ import androidx.annotation.Nullable;
7
+
6
8
  public interface ActivityEventListener {
7
- public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data);
9
+ public void onActivityResult(Activity activity, int requestCode, int resultCode, @Nullable Intent data);
8
10
 
9
11
  // Called when a new intent is passed to the activity
10
12
  public void onNewIntent(Intent intent);
@@ -0,0 +1,10 @@
1
+ package expo.modules.core.interfaces;
2
+
3
+ import android.app.Application;
4
+ import android.content.res.Configuration;
5
+
6
+ public interface ApplicationLifecycleListener {
7
+ default void onCreate(Application application) {}
8
+
9
+ default void onConfigurationChanged(Configuration newConfig) {}
10
+ }
@@ -43,4 +43,8 @@ public interface Package {
43
43
  default List<? extends ReactActivityLifecycleListener> createReactActivityLifecycleListeners(Context activityContext) {
44
44
  return Collections.emptyList();
45
45
  }
46
+
47
+ default List<? extends ReactActivityHandler> createReactActivityHandlers(Context activityContext) {
48
+ return Collections.emptyList();
49
+ }
46
50
  }
@@ -0,0 +1,21 @@
1
+ package expo.modules.core.interfaces;
2
+
3
+ import android.app.Activity;
4
+ import com.facebook.react.ReactRootView;
5
+
6
+ import androidx.annotation.Nullable;
7
+
8
+ /**
9
+ * A handler API for modules to override default ReactActivity behaviors.
10
+ * Used by {@link ReactActivityDelegateWrapper}
11
+ */
12
+ public interface ReactActivityHandler {
13
+ /**
14
+ * Given modules a chance to override the default {@link ReactRootView}
15
+ * @return the override ReactRootView instance or null if not to override
16
+ */
17
+ @Nullable
18
+ default ReactRootView createReactRootView(Activity activity) {
19
+ return null;
20
+ }
21
+ }
@@ -0,0 +1,14 @@
1
+ package expo.modules.core.interfaces;
2
+
3
+ import android.app.Activity;
4
+ import android.os.Bundle;
5
+
6
+ public interface ReactActivityLifecycleListener {
7
+ default void onCreate(Activity activity, Bundle savedInstanceState) {}
8
+
9
+ default void onResume(Activity activity) {}
10
+
11
+ default void onPause(Activity activity) {}
12
+
13
+ default void onDestroy(Activity activity) {}
14
+ }
@@ -0,0 +1,70 @@
1
+ package expo.modules.core.interfaces;
2
+
3
+ import com.facebook.react.ReactInstanceManager;
4
+ import com.facebook.react.bridge.JavaScriptContextHolder;
5
+ import com.facebook.react.bridge.ReactApplicationContext;
6
+
7
+ import androidx.annotation.Nullable;
8
+
9
+ public interface ReactNativeHostHandler {
10
+ /**
11
+ * Given chance for modules to customize {@link ReactInstanceManager}
12
+ *
13
+ * @param useDeveloperSupport true if {@link ReactNativeHost} enabled developer support
14
+ * @return instance of {@link ReactInstanceManager}, or null if not to override
15
+ */
16
+ @Nullable
17
+ default ReactInstanceManager createReactInstanceManager(boolean useDeveloperSupport) {
18
+ return null;
19
+ }
20
+
21
+ /**
22
+ * Given chance for modules to override react bundle file.
23
+ * e.g. for expo-updates
24
+ *
25
+ * @param useDeveloperSupport true if {@link ReactNativeHost} enabled developer support
26
+ * @return custom path to bundle file, or null if not to override
27
+ */
28
+ @Nullable
29
+ default String getJSBundleFile(boolean useDeveloperSupport) {
30
+ return null;
31
+ }
32
+
33
+ /**
34
+ * Given chance for modules to override react bundle asset name.
35
+ * e.g. for expo-updates
36
+ *
37
+ * @param useDeveloperSupport true if {@link ReactNativeHost} enabled developer support
38
+ * @return custom bundle asset name, or null if not to override
39
+ */
40
+ @Nullable
41
+ default String getBundleAssetName(boolean useDeveloperSupport) {
42
+ return null;
43
+ }
44
+
45
+ //region event listeners
46
+
47
+ /**
48
+ * Given chance for JSI modules to register, e.g. for react-native-reanimated
49
+ *
50
+ * @param useDeveloperSupport true if {@link ReactNativeHost} enabled developer support
51
+ */
52
+ default void onRegisterJSIModules(
53
+ ReactApplicationContext reactApplicationContext,
54
+ JavaScriptContextHolder jsContext,
55
+ boolean useDeveloperSupport
56
+ ) {
57
+ }
58
+
59
+ /**
60
+ * Callback before {@link ReactInstanceManager} creation
61
+ */
62
+ default void onWillCreateReactInstanceManager(boolean useDeveloperSupport) {}
63
+
64
+ /**
65
+ * Callback after {@link ReactInstanceManager} creation
66
+ */
67
+ default void onDidCreateReactInstanceManager(ReactInstanceManager reactInstanceManager, boolean useDeveloperSupport) {}
68
+
69
+ //endregion
70
+ }
@@ -0,0 +1,23 @@
1
+ package expo.modules.core.utilities
2
+
3
+ /**
4
+ * Returns receiver, or block result if the receiver is `null`
5
+ *
6
+ * A more semantic equivalent to: `nullable ?: run { ... }`:
7
+ * ```
8
+ * val nonNullable1 = sthNullable.ifNull { ... }
9
+ * val nonNullable2 = sthNullable ?: run { ... }
10
+ * ```
11
+ */
12
+ inline fun <T> T?.ifNull(block: () -> T): T = this ?: block()
13
+
14
+ /**
15
+ * If the receiver is instance of `T`, returns the receiver, otherwise returns `null`
16
+ *
17
+ * Works the same as the `as?` operator, but allows method chaining without parentheses:
18
+ * ```
19
+ * val x = a.b.takeIfInstanceOf<Number>?.someMethod()
20
+ * val y = (a.b as? Number)?.someMethod() // same, but needs parenthesis
21
+ * ```
22
+ */
23
+ inline fun <reified T> Any?.takeIfInstanceOf(): T? = if (this is T) this else null