expo-modules-core 0.6.4 → 0.8.0

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 (217) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +1 -1
  3. package/android/ExpoModulesCorePlugin.gradle +15 -0
  4. package/android/build.gradle +46 -32
  5. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
  6. package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
  7. package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
  8. package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +19 -0
  11. package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
  12. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
  13. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
  14. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
  15. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
  16. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
  17. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
  18. package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
  19. package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
  20. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
  21. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
  22. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
  23. package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
  24. package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
  25. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
  26. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
  27. package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
  28. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
  29. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +61 -0
  30. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
  31. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
  32. package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
  33. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
  34. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +219 -30
  35. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
  36. package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
  37. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
  38. package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
  39. package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
  40. package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
  41. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
  42. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
  45. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
  46. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
  47. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
  48. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
  49. package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
  50. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
  51. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
  52. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +64 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
  55. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +42 -1
  56. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
  57. package/build/EventEmitter.d.ts +1 -0
  58. package/build/EventEmitter.d.ts.map +1 -0
  59. package/build/NativeModulesProxy.d.ts +1 -0
  60. package/build/NativeModulesProxy.d.ts.map +1 -0
  61. package/build/NativeModulesProxy.native.d.ts +1 -4
  62. package/build/NativeModulesProxy.native.d.ts.map +1 -0
  63. package/build/NativeModulesProxy.native.js +1 -14
  64. package/build/NativeModulesProxy.native.js.map +1 -1
  65. package/build/NativeModulesProxy.types.d.ts +1 -3
  66. package/build/NativeModulesProxy.types.d.ts.map +1 -0
  67. package/build/NativeModulesProxy.types.js.map +1 -1
  68. package/build/NativeViewManagerAdapter.d.ts +1 -0
  69. package/build/NativeViewManagerAdapter.d.ts.map +1 -0
  70. package/build/NativeViewManagerAdapter.native.d.ts +1 -0
  71. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
  72. package/build/NativeViewManagerAdapter.native.js +9 -33
  73. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  74. package/build/PermissionsHook.d.ts +1 -0
  75. package/build/PermissionsHook.d.ts.map +1 -0
  76. package/build/PermissionsInterface.d.ts +1 -0
  77. package/build/PermissionsInterface.d.ts.map +1 -0
  78. package/build/Platform.d.ts +1 -0
  79. package/build/Platform.d.ts.map +1 -0
  80. package/build/SyntheticPlatformEmitter.d.ts +1 -0
  81. package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
  82. package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
  83. package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
  84. package/build/deprecate.d.ts +1 -0
  85. package/build/deprecate.d.ts.map +1 -0
  86. package/build/environment/browser.d.ts +1 -0
  87. package/build/environment/browser.d.ts.map +1 -0
  88. package/build/environment/browser.web.d.ts +1 -0
  89. package/build/environment/browser.web.d.ts.map +1 -0
  90. package/build/errors/CodedError.d.ts +1 -0
  91. package/build/errors/CodedError.d.ts.map +1 -0
  92. package/build/errors/UnavailabilityError.d.ts +1 -0
  93. package/build/errors/UnavailabilityError.d.ts.map +1 -0
  94. package/build/index.d.ts +3 -0
  95. package/build/index.d.ts.map +1 -0
  96. package/build/index.js +2 -0
  97. package/build/index.js.map +1 -1
  98. package/build/requireNativeModule.d.ts +16 -0
  99. package/build/requireNativeModule.d.ts.map +1 -0
  100. package/build/requireNativeModule.js +18 -0
  101. package/build/requireNativeModule.js.map +1 -0
  102. package/build/sweet/NativeErrorManager.d.ts +3 -0
  103. package/build/sweet/NativeErrorManager.d.ts.map +1 -0
  104. package/build/sweet/NativeErrorManager.js +3 -0
  105. package/build/sweet/NativeErrorManager.js.map +1 -0
  106. package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
  107. package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
  108. package/build/sweet/setUpErrorManager.fx.js +11 -0
  109. package/build/sweet/setUpErrorManager.fx.js.map +1 -0
  110. package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
  111. package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
  112. package/ios/EXAppDefines.h +1 -0
  113. package/ios/EXAppDefines.m +6 -0
  114. package/ios/EXUtilities.h +2 -0
  115. package/ios/EXUtilities.m +12 -0
  116. package/ios/ExpoModulesCore.h +4 -0
  117. package/ios/ExpoModulesCore.podspec +4 -2
  118. package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
  119. package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
  120. package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
  121. package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
  122. package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
  123. package/ios/JSI/EXJSIInstaller.mm +17 -0
  124. package/ios/JSI/EXJSIUtils.h +19 -0
  125. package/ios/JSI/EXJSIUtils.mm +89 -0
  126. package/ios/JSI/EXJavaScriptObject.h +97 -0
  127. package/ios/JSI/EXJavaScriptObject.mm +121 -0
  128. package/ios/JSI/EXJavaScriptRuntime.h +73 -0
  129. package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
  130. package/ios/JSI/EXJavaScriptValue.h +57 -0
  131. package/ios/JSI/EXJavaScriptValue.mm +166 -0
  132. package/ios/JSI/ExpoModulesHostObject.h +33 -0
  133. package/ios/JSI/ExpoModulesHostObject.mm +41 -0
  134. package/ios/JSI/JavaScriptRuntime.swift +32 -0
  135. package/ios/JSI/JavaScriptValue.swift +94 -0
  136. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
  137. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
  138. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
  139. package/ios/RCTComponentData+Privates.h +12 -0
  140. package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
  141. package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
  142. package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
  143. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
  144. package/ios/ReactDelegates/ModulePriorities.swift +1 -1
  145. package/ios/Swift/AppContext.swift +64 -4
  146. package/ios/Swift/Arguments/ArgumentType.swift +4 -0
  147. package/ios/Swift/Arguments/Convertibles.swift +13 -13
  148. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
  149. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
  150. package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
  151. package/ios/Swift/Conversions.swift +51 -56
  152. package/ios/Swift/EventListener.swift +8 -10
  153. package/ios/Swift/Events/Callback.swift +66 -0
  154. package/ios/Swift/Events/Event.swift +43 -0
  155. package/ios/Swift/Exceptions/ChainableException.swift +51 -0
  156. package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
  157. package/ios/Swift/Exceptions/Exception.swift +62 -0
  158. package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
  159. package/ios/Swift/Exceptions/GenericException.swift +20 -0
  160. package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
  161. package/ios/Swift/Functions/AnyFunction.swift +11 -1
  162. package/ios/Swift/Functions/AsyncFunction.swift +17 -0
  163. package/ios/Swift/Functions/ConcreteFunction.swift +43 -17
  164. package/ios/Swift/JavaScriptUtils.swift +54 -0
  165. package/ios/Swift/ModuleHolder.swift +66 -16
  166. package/ios/Swift/ModuleRegistry.swift +4 -1
  167. package/ios/Swift/Modules/AnyModule.swift +0 -1
  168. package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
  169. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
  170. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +0 -188
  171. package/ios/Swift/ModulesProvider.swift +3 -11
  172. package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
  173. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +384 -0
  174. package/ios/Swift/Promise.swift +8 -3
  175. package/ios/Swift/Records/AnyField.swift +7 -0
  176. package/ios/Swift/Records/Field.swift +24 -19
  177. package/ios/Swift/Records/FieldOption.swift +1 -1
  178. package/ios/Swift/Records/Record.swift +12 -4
  179. package/ios/Swift/SwiftInteropBridge.swift +53 -15
  180. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  181. package/ios/Swift/Views/ComponentData.swift +96 -0
  182. package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
  183. package/ios/Swift/Views/ExpoView.swift +8 -0
  184. package/ios/Swift/Views/ViewFactory.swift +1 -1
  185. package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
  186. package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
  187. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +26 -0
  188. package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
  189. package/ios/Swift.h +5 -0
  190. package/ios/Tests/ArgumentTypeSpec.swift +5 -7
  191. package/ios/Tests/ConstantsSpec.swift +6 -7
  192. package/ios/Tests/ConvertiblesSpec.swift +35 -36
  193. package/ios/Tests/ExceptionsSpec.swift +111 -0
  194. package/ios/Tests/ExpoModulesSpec.swift +76 -0
  195. package/ios/Tests/FunctionSpec.swift +22 -25
  196. package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
  197. package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
  198. package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
  199. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  200. package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
  201. package/ios/Tests/ModuleEventListenersSpec.swift +3 -4
  202. package/ios/Tests/ModuleRegistrySpec.swift +2 -3
  203. package/ios/Tests/RecordSpec.swift +9 -20
  204. package/package.json +3 -3
  205. package/src/NativeModulesProxy.native.ts +2 -22
  206. package/src/NativeModulesProxy.types.ts +0 -8
  207. package/src/NativeViewManagerAdapter.native.tsx +12 -28
  208. package/src/index.ts +4 -0
  209. package/src/requireNativeModule.ts +29 -0
  210. package/src/sweet/NativeErrorManager.ts +2 -0
  211. package/src/sweet/setUpErrorManager.fx.ts +12 -0
  212. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
  213. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
  214. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
  215. package/ios/JSI/ExpoModulesProxySpec.h +0 -24
  216. package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
  217. package/ios/JSI/JSIInstaller.mm +0 -22
@@ -35,6 +35,7 @@ fun convert(value: Dynamic, type: KType): Any? {
35
35
 
36
36
  object TypeConverterProviderImpl : TypeConverterProvider {
37
37
  private val cachedConverters = createCashedConverters(false) + createCashedConverters(true)
38
+ private val cachedRecordConverters = mutableMapOf<KClass<*>, TypeConverter<*>>()
38
39
 
39
40
  override fun obtainTypeConverter(type: KType): TypeConverter<*> {
40
41
  cachedConverters[type]?.let {
@@ -68,8 +69,15 @@ object TypeConverterProviderImpl : TypeConverterProvider {
68
69
  return EnumTypeConverter(kClass as KClass<Enum<*>>, type.isMarkedNullable)
69
70
  }
70
71
 
72
+ val cachedConverter = cachedRecordConverters[kClass]
73
+ if (cachedConverter != null) {
74
+ return cachedConverter
75
+ }
76
+
71
77
  if (kClass.isSubclassOf(Record::class)) {
72
- return RecordTypeConverter<Record>(this, type)
78
+ val converter = RecordTypeConverter<Record>(this, type)
79
+ cachedRecordConverters[kClass] = converter
80
+ return converter
73
81
  }
74
82
 
75
83
  throw MissingTypeConverter(type)
@@ -0,0 +1,3 @@
1
+ package expo.modules.kotlin.views
2
+
3
+ class CallbacksDefinition(val names: Array<out String>)
@@ -3,9 +3,11 @@ package expo.modules.kotlin.views
3
3
  import android.view.View
4
4
  import android.view.ViewGroup
5
5
  import com.facebook.react.bridge.ReadableMap
6
+ import com.facebook.react.common.MapBuilder
6
7
  import com.facebook.react.uimanager.ThemedReactContext
7
8
  import com.facebook.react.uimanager.ViewGroupManager
8
9
  import com.facebook.react.uimanager.annotations.ReactProp
10
+ import expo.modules.core.utilities.ifNull
9
11
 
10
12
  class GroupViewManagerWrapper(
11
13
  override val viewWrapperDelegate: ViewManagerWrapperDelegate
@@ -19,4 +21,73 @@ class GroupViewManagerWrapper(
19
21
  fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
20
22
  viewWrapperDelegate.setProxiedProperties(view, proxiedProperties)
21
23
  }
24
+
25
+ override fun onDropViewInstance(view: ViewGroup) {
26
+ super.onDropViewInstance(view)
27
+ viewWrapperDelegate.onDestroy(view)
28
+ }
29
+
30
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
31
+ viewWrapperDelegate.getExportedCustomDirectEventTypeConstants()?.let {
32
+ val directEvents = super.getExportedCustomDirectEventTypeConstants() ?: emptyMap()
33
+ val builder = MapBuilder.builder<String, Any>()
34
+ directEvents.forEach { event ->
35
+ builder.put(event.key, event.value)
36
+ }
37
+ it.forEach { event ->
38
+ builder.put(event.key, event.value)
39
+ }
40
+ return builder.build()
41
+ }
42
+
43
+ return super.getExportedCustomDirectEventTypeConstants()
44
+ }
45
+
46
+ override fun addView(parent: ViewGroup, child: View, index: Int) {
47
+ viewWrapperDelegate
48
+ .viewGroupDefinition
49
+ ?.addViewAction
50
+ ?.invoke(parent, child, index)
51
+ .ifNull {
52
+ super.addView(parent, child, index)
53
+ }
54
+ }
55
+
56
+ override fun getChildCount(parent: ViewGroup): Int {
57
+ return viewWrapperDelegate.viewGroupDefinition
58
+ ?.getChildCountAction
59
+ ?.invoke(parent)
60
+ .ifNull {
61
+ super.getChildCount(parent)
62
+ }
63
+ }
64
+
65
+ override fun getChildAt(parent: ViewGroup, index: Int): View? {
66
+ viewWrapperDelegate.viewGroupDefinition
67
+ ?.getChildAtAction
68
+ ?.let {
69
+ return it.invoke(parent, index)
70
+ }
71
+ .ifNull {
72
+ return super.getChildAt(parent, index)
73
+ }
74
+ }
75
+
76
+ override fun removeViewAt(parent: ViewGroup, index: Int) {
77
+ viewWrapperDelegate.viewGroupDefinition
78
+ ?.removeViewAtAction
79
+ ?.invoke(parent, index)
80
+ .ifNull {
81
+ super.removeViewAt(parent, index)
82
+ }
83
+ }
84
+
85
+ override fun removeView(parent: ViewGroup, view: View) {
86
+ viewWrapperDelegate.viewGroupDefinition
87
+ ?.removeViewAction
88
+ ?.invoke(parent, view)
89
+ .ifNull {
90
+ super.removeView(parent, view)
91
+ }
92
+ }
22
93
  }
@@ -2,6 +2,7 @@ package expo.modules.kotlin.views
2
2
 
3
3
  import android.view.View
4
4
  import com.facebook.react.bridge.ReadableMap
5
+ import com.facebook.react.common.MapBuilder
5
6
  import com.facebook.react.uimanager.SimpleViewManager
6
7
  import com.facebook.react.uimanager.ThemedReactContext
7
8
  import com.facebook.react.uimanager.annotations.ReactProp
@@ -18,4 +19,25 @@ class SimpleViewManagerWrapper(
18
19
  fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
19
20
  viewWrapperDelegate.setProxiedProperties(view, proxiedProperties)
20
21
  }
22
+
23
+ override fun onDropViewInstance(view: View) {
24
+ super.onDropViewInstance(view)
25
+ viewWrapperDelegate.onDestroy(view)
26
+ }
27
+
28
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
29
+ viewWrapperDelegate.getExportedCustomDirectEventTypeConstants()?.let {
30
+ val directEvents = super.getExportedCustomDirectEventTypeConstants() ?: emptyMap()
31
+ val builder = MapBuilder.builder<String, Any>()
32
+ directEvents.forEach { event ->
33
+ builder.put(event.key, event.value)
34
+ }
35
+ it.forEach { event ->
36
+ builder.put(event.key, event.value)
37
+ }
38
+ return builder.build()
39
+ }
40
+
41
+ return super.getExportedCustomDirectEventTypeConstants()
42
+ }
21
43
  }
@@ -0,0 +1,18 @@
1
+ package expo.modules.kotlin.views
2
+
3
+ import android.view.View
4
+ import android.view.ViewGroup
5
+
6
+ class ViewGroupDefinition(
7
+ val addViewAction: AddViewAction?,
8
+ val getChildAtAction: GetChildAtAction?,
9
+ val getChildCountAction: GetChildCountAction?,
10
+ val removeViewAction: RemoveViewAction?,
11
+ val removeViewAtAction: RemoveViewAtAction?
12
+ )
13
+
14
+ internal typealias AddViewAction = (parent: ViewGroup, child: View, index: Int) -> Unit
15
+ internal typealias GetChildAtAction = (parent: ViewGroup, index: Int) -> View?
16
+ internal typealias GetChildCountAction = (parent: ViewGroup) -> Int
17
+ internal typealias RemoveViewAction = (parent: ViewGroup, childToRemove: View) -> Unit
18
+ internal typealias RemoveViewAtAction = (parent: ViewGroup, index: Int) -> Unit
@@ -0,0 +1,64 @@
1
+ @file:OptIn(ExperimentalStdlibApi::class)
2
+
3
+ package expo.modules.kotlin.views
4
+
5
+ import android.view.View
6
+ import android.view.ViewGroup
7
+ import expo.modules.kotlin.modules.DefinitionMarker
8
+
9
+ @DefinitionMarker
10
+ class ViewGroupDefinitionBuilder {
11
+ @PublishedApi internal var addViewAction: AddViewAction? = null
12
+ @PublishedApi internal var getChildAtAction: GetChildAtAction? = null
13
+ @PublishedApi internal var getChildCountAction: GetChildCountAction? = null
14
+ @PublishedApi internal var removeViewAction: RemoveViewAction? = null
15
+ @PublishedApi internal var removeViewAtAction: RemoveViewAtAction? = null
16
+
17
+ fun build() = ViewGroupDefinition(
18
+ addViewAction,
19
+ getChildAtAction,
20
+ getChildCountAction,
21
+ removeViewAction,
22
+ removeViewAtAction
23
+ )
24
+
25
+ inline fun <reified ParentViewType : ViewGroup, reified ChildViewType : View> addChildView(
26
+ noinline body: (parent: ParentViewType, child: ChildViewType, index: Int) -> Unit
27
+ ) {
28
+ addViewAction = { parent, child, index ->
29
+ body(parent as ParentViewType, child as ChildViewType, index)
30
+ }
31
+ }
32
+
33
+ inline fun <reified ParentViewType : ViewGroup> getChildCount(
34
+ noinline body: (view: ParentViewType) -> Int
35
+ ) {
36
+ getChildCountAction = { view ->
37
+ body(view as ParentViewType)
38
+ }
39
+ }
40
+
41
+ inline fun <reified ParentViewType : ViewGroup, reified ChildViewType : View> getChildViewAt(
42
+ noinline body: (view: ParentViewType, index: Int) -> ChildViewType?
43
+ ) {
44
+ getChildAtAction = { view, index ->
45
+ body(view as ParentViewType, index)
46
+ }
47
+ }
48
+
49
+ inline fun <reified ParentViewType : ViewGroup> removeChildViewAt(
50
+ noinline body: (view: ParentViewType, index: Int) -> Unit
51
+ ) {
52
+ removeViewAtAction = { view, index ->
53
+ body(view as ParentViewType, index)
54
+ }
55
+ }
56
+
57
+ inline fun <reified ParentViewType : ViewGroup, reified ChildViewType : View> removeChildView(
58
+ noinline body: (parent: ParentViewType, child: ChildViewType) -> Unit
59
+ ) {
60
+ removeViewAction = { view, child ->
61
+ body(view as ParentViewType, child as ChildViewType)
62
+ }
63
+ }
64
+ }
@@ -4,18 +4,27 @@ import android.content.Context
4
4
  import android.util.Log
5
5
  import android.view.View
6
6
  import android.view.ViewGroup
7
+ import com.facebook.react.bridge.ReactContext
7
8
  import com.facebook.react.bridge.ReadableMap
9
+ import expo.modules.adapters.react.NativeModulesProxy
8
10
  import expo.modules.core.ViewManager
11
+ import expo.modules.kotlin.exception.CodedException
12
+ import expo.modules.kotlin.exception.UnexpectedException
9
13
  import expo.modules.kotlin.recycle
10
14
 
11
15
  class ViewManagerDefinition(
12
16
  private val viewFactory: (Context) -> View,
13
17
  private val viewType: Class<out View>,
14
- private val props: Map<String, AnyViewProp>
18
+ private val props: Map<String, AnyViewProp>,
19
+ val onViewDestroys: ((View) -> Unit)? = null,
20
+ val callbacksDefinition: CallbacksDefinition? = null,
21
+ val viewGroupDefinition: ViewGroupDefinition? = null
15
22
  ) {
16
23
 
17
24
  fun createView(context: Context): View = viewFactory(context)
18
25
 
26
+ val propsNames: List<String> = props.keys.toList()
27
+
19
28
  fun getViewManagerType(): ViewManager.ViewManagerType {
20
29
  return if (ViewGroup::class.java.isAssignableFrom(viewType)) {
21
30
  ViewManager.ViewManagerType.GROUP
@@ -33,9 +42,28 @@ class ViewManagerDefinition(
33
42
  try {
34
43
  propDelegate.set(this, onView)
35
44
  } catch (exception: Throwable) {
36
- Log.e("ExpoModulesCore", "Cannot set the $key prop on the ${viewType.simpleName}.", exception)
45
+ Log.e("ExpoModulesCore", "Cannot set the '$key' prop on the '${viewType.simpleName}'.", exception)
46
+
47
+ handleException(
48
+ onView,
49
+ when (exception) {
50
+ is CodedException -> exception
51
+ else -> UnexpectedException(exception)
52
+ }
53
+ )
37
54
  }
38
55
  }
39
56
  }
40
57
  }
58
+
59
+ fun handleException(view: View, exception: CodedException) {
60
+ val reactContext = (view.context as? ReactContext) ?: return
61
+ val nativeModulesProxy = reactContext
62
+ .catalystInstance
63
+ ?.getNativeModule("NativeUnimoduleProxy") as? NativeModulesProxy
64
+ ?: return
65
+ val appContext = nativeModulesProxy.kotlinInteropModuleRegistry.appContext
66
+
67
+ appContext.errorManager?.reportExceptionToLogBox(exception)
68
+ }
41
69
  }
@@ -4,9 +4,11 @@ package expo.modules.kotlin.views
4
4
 
5
5
  import android.content.Context
6
6
  import android.view.View
7
+ import expo.modules.kotlin.modules.DefinitionMarker
7
8
  import expo.modules.kotlin.types.toAnyType
8
9
  import kotlin.reflect.typeOf
9
10
 
11
+ @DefinitionMarker
10
12
  class ViewManagerDefinitionBuilder {
11
13
  @PublishedApi
12
14
  internal var viewFactory: ((Context) -> View)? = null
@@ -14,19 +16,40 @@ class ViewManagerDefinitionBuilder {
14
16
  internal var viewType: Class<out View>? = null
15
17
  @PublishedApi
16
18
  internal var props = mutableMapOf<String, AnyViewProp>()
19
+ @PublishedApi
20
+ internal var onViewDestroys: ((View) -> Unit)? = null
21
+ @PublishedApi
22
+ internal var viewGroupDefinition: ViewGroupDefinition? = null
23
+ private var callbacksDefinition: CallbacksDefinition? = null
17
24
 
18
25
  fun build(): ViewManagerDefinition =
19
26
  ViewManagerDefinition(
20
27
  requireNotNull(viewFactory),
21
28
  requireNotNull(viewType),
22
- props
29
+ props,
30
+ onViewDestroys,
31
+ callbacksDefinition,
32
+ viewGroupDefinition
23
33
  )
24
34
 
35
+ /**
36
+ * Defines the factory creating a native view when the module is used as a view.
37
+ */
25
38
  inline fun <reified ViewType : View> view(noinline body: (Context) -> ViewType) {
26
39
  viewType = ViewType::class.java
27
40
  viewFactory = body
28
41
  }
29
42
 
43
+ /**
44
+ * Creates view's lifecycle listener that is called right after the view isn't longer used by React Native.
45
+ */
46
+ inline fun <reified ViewType : View> onViewDestroys(noinline body: (view: ViewType) -> Unit) {
47
+ onViewDestroys = { body(it as ViewType) }
48
+ }
49
+
50
+ /**
51
+ * Creates a view prop that defines its name and setter.
52
+ */
30
53
  inline fun <reified ViewType : View, reified PropType> prop(
31
54
  name: String,
32
55
  noinline body: (view: ViewType, prop: PropType) -> Unit
@@ -37,4 +60,22 @@ class ViewManagerDefinitionBuilder {
37
60
  body
38
61
  )
39
62
  }
63
+
64
+ /**
65
+ * Defines prop names that should be treated as callbacks.
66
+ */
67
+ fun events(vararg callbacks: String) {
68
+ callbacksDefinition = CallbacksDefinition(callbacks)
69
+ }
70
+
71
+ /**
72
+ * Creates the group view definition that scopes group view-related definitions.
73
+ */
74
+ inline fun groupView(body: ViewGroupDefinitionBuilder.() -> Unit) {
75
+ require(viewGroupDefinition == null) { "The viewManager definition may have exported only one groupView definition." }
76
+
77
+ val groupViewDefinitionBuilder = ViewGroupDefinitionBuilder()
78
+ body.invoke(groupViewDefinitionBuilder)
79
+ viewGroupDefinition = groupViewDefinitionBuilder.build()
80
+ }
40
81
  }
@@ -1,21 +1,81 @@
1
1
  package expo.modules.kotlin.views
2
2
 
3
3
  import android.content.Context
4
+ import android.util.Log
4
5
  import android.view.View
5
6
  import com.facebook.react.bridge.ReadableMap
7
+ import com.facebook.react.common.MapBuilder
8
+ import expo.modules.core.utilities.ifNull
6
9
  import expo.modules.kotlin.ModuleHolder
10
+ import expo.modules.kotlin.callbacks.ViewCallbackDelegate
11
+ import kotlin.reflect.full.declaredMemberProperties
12
+ import kotlin.reflect.jvm.isAccessible
7
13
 
8
14
  class ViewManagerWrapperDelegate(internal var moduleHolder: ModuleHolder) {
9
15
  private val definition: ViewManagerDefinition
10
16
  get() = requireNotNull(moduleHolder.definition.viewManagerDefinition)
11
17
 
18
+ internal val viewGroupDefinition: ViewGroupDefinition?
19
+ get() = definition.viewGroupDefinition
20
+
12
21
  val name: String
13
22
  get() = moduleHolder.name
14
23
 
15
- fun createView(context: Context): View =
16
- definition.createView(context)
24
+ fun createView(context: Context): View {
25
+ return definition
26
+ .createView(context)
27
+ .also {
28
+ configureView(it)
29
+ }
30
+ }
17
31
 
18
32
  fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
19
33
  definition.setProps(proxiedProperties, view)
20
34
  }
35
+
36
+ fun onDestroy(view: View) =
37
+ definition.onViewDestroys?.invoke(view)
38
+
39
+ fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
40
+ val builder = MapBuilder.builder<String, Any>()
41
+ definition
42
+ .callbacksDefinition
43
+ ?.names
44
+ ?.forEach {
45
+ builder.put(
46
+ it, MapBuilder.of<String, Any>("registrationName", it)
47
+ )
48
+ }
49
+ return builder.build()
50
+ }
51
+
52
+ private fun configureView(view: View) {
53
+ val callbacks = definition.callbacksDefinition?.names ?: return
54
+
55
+ val kClass = view.javaClass.kotlin
56
+ val propertiesMap = kClass
57
+ .declaredMemberProperties
58
+ .map { it.name to it }
59
+ .toMap()
60
+
61
+ callbacks.forEach {
62
+ val property = propertiesMap[it].ifNull {
63
+ Log.w("ExpoModuleCore", "Property `$it` does not exist in ${kClass.simpleName}.")
64
+ return@forEach
65
+ }
66
+ property.isAccessible = true
67
+
68
+ val delegate = property.getDelegate(view).ifNull {
69
+ Log.w("ExpoModulesCore", "Property delegate for `$it` in ${kClass.simpleName} does not exist.")
70
+ return@forEach
71
+ }
72
+
73
+ val viewDelegate = (delegate as? ViewCallbackDelegate<*>).ifNull {
74
+ Log.w("ExpoModulesCore", "Property delegate for `$it` cannot be cased to `ViewCallbackDelegate`.")
75
+ return@forEach
76
+ }
77
+
78
+ viewDelegate.isValidated = true
79
+ }
80
+ }
21
81
  }
@@ -22,3 +22,4 @@ export declare class EventEmitter {
22
22
  emit(eventName: string, ...params: any[]): void;
23
23
  }
24
24
  export {};
25
+ //# sourceMappingURL=EventEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../src/EventEmitter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAY,MAAM,cAAc,CAAC;AAI5D,aAAK,YAAY,GAAG;IAClB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AAGF,oBAAY,YAAY,GAAG;IACzB;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,qBAAa,YAAY;IACvB,cAAc,SAAK;IACnB,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,kBAAkB,CAAC;gBAEtB,YAAY,EAAE,YAAY;IAKtC,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,YAAY;IAgB7E,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmB3C,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IA0BpD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI;CAGhD"}
@@ -3,3 +3,4 @@ declare const _default: {
3
3
  [moduleName: string]: ProxyNativeModule;
4
4
  };
5
5
  export default _default;
6
+ //# sourceMappingURL=NativeModulesProxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeModulesProxy.d.ts","sourceRoot":"","sources":["../src/NativeModulesProxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;;;;AAG/D,wBAAiE"}
@@ -2,8 +2,5 @@ import { ProxyNativeModule } from './NativeModulesProxy.types';
2
2
  declare const NativeModulesProxy: {
3
3
  [moduleName: string]: ProxyNativeModule;
4
4
  };
5
- /**
6
- * Sets whether to use a TurboModule version of the proxy.
7
- */
8
- export declare function useExpoTurboModules(state?: boolean): void;
9
5
  export default NativeModulesProxy;
6
+ //# sourceMappingURL=NativeModulesProxy.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeModulesProxy.native.d.ts","sourceRoot":"","sources":["../src/NativeModulesProxy.native.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAM/D,QAAA,MAAM,kBAAkB,EAAE;IAAE,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,CAAA;CAAO,CAAC;AAkD3E,eAAe,kBAAkB,CAAC"}
@@ -3,14 +3,6 @@ const NativeProxy = NativeModules.NativeUnimoduleProxy;
3
3
  const modulesConstantsKey = 'modulesConstants';
4
4
  const exportedMethodsKey = 'exportedMethods';
5
5
  const NativeModulesProxy = {};
6
- // Keep it opt-in for now. It's too risky without proper and thorough testing.
7
- let canUseExpoTurboModules = false;
8
- /**
9
- * Sets whether to use a TurboModule version of the proxy.
10
- */
11
- export function useExpoTurboModules(state = true) {
12
- canUseExpoTurboModules = state;
13
- }
14
6
  if (NativeProxy) {
15
7
  Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {
16
8
  NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};
@@ -20,12 +12,7 @@ if (NativeProxy) {
20
12
  if (argumentsCount !== args.length) {
21
13
  return Promise.reject(new Error(`Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${argumentsCount === 1 ? 'argument' : 'arguments'} but received ${args.length}`));
22
14
  }
23
- if (canUseExpoTurboModules && global.ExpoModulesProxy) {
24
- return global.ExpoModulesProxy.callMethodAsync(moduleName, methodInfo.name, args);
25
- }
26
- else {
27
- return NativeProxy.callMethod(moduleName, key, args);
28
- }
15
+ return NativeProxy.callMethod(moduleName, key, args);
29
16
  };
30
17
  });
31
18
  // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)
@@ -1 +1 @@
1
- {"version":3,"file":"NativeModulesProxy.native.js","sourceRoot":"","sources":["../src/NativeModulesProxy.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAS7C,MAAM,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC;AACvD,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C,MAAM,kBAAkB,GAAgD,EAAE,CAAC;AAE3E,8EAA8E;AAC9E,IAAI,sBAAsB,GAAG,KAAK,CAAC;AAEnC;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAiB,IAAI;IACvD,sBAAsB,GAAG,KAAK,CAAC;AACjC,CAAC;AAED,IAAI,WAAW,EAAE;IACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QAClE,kBAAkB,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACpF,WAAW,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAe,EAAgB,EAAE;gBACrF,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;gBAC3C,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE;oBAClC,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,iBAAiB,UAAU,IAAI,UAAU,CAAC,IAAI,YAAY,cAAc,IACtE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WACtC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAC/B,CACF,CAAC;iBACH;gBAED,IAAI,sBAAsB,IAAI,MAAM,CAAC,gBAAgB,EAAE;oBACrD,OAAO,MAAM,CAAC,gBAAgB,CAAC,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;iBACnF;qBAAM;oBACL,OAAO,WAAW,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;iBACtD;YACH,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,kFAAkF;QAClF,EAAE;QACF,wEAAwE;QACxE,gDAAgD;QAChD,EAAE;QACF,6GAA6G;QAC7G,gGAAgG;QAChG,4HAA4H;QAC5H,qCAAqC;QACrC,IAAI,aAAa,CAAC,yBAAyB,EAAE;YAC3C,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CACvD,aAAa,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAClF,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAC3D,aAAa,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;SACvF;aAAM;YACL,oBAAoB;YACpB,kHAAkH;YAClH,sHAAsH;YACtH,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;YACtD,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;SAC3D;IACH,CAAC,CAAC,CAAC;CACJ;KAAM;IACL,OAAO,CAAC,IAAI,CACV,gJAAgJ,CACjJ,CAAC;CACH;AAED,eAAe,kBAAkB,CAAC","sourcesContent":["import { NativeModules } from 'react-native';\n\nimport { ProxyNativeModule, TurboNativeModuleProxy } from './NativeModulesProxy.types';\n\n// `ExpoModulesProxy` is not declared in TypeScript yet. It's installed via JSI.\ndeclare namespace global {\n const ExpoModulesProxy: TurboNativeModuleProxy;\n}\n\nconst NativeProxy = NativeModules.NativeUnimoduleProxy;\nconst modulesConstantsKey = 'modulesConstants';\nconst exportedMethodsKey = 'exportedMethods';\n\nconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};\n\n// Keep it opt-in for now. It's too risky without proper and thorough testing.\nlet canUseExpoTurboModules = false;\n\n/**\n * Sets whether to use a TurboModule version of the proxy.\n */\nexport function useExpoTurboModules(state: boolean = true) {\n canUseExpoTurboModules = state;\n}\n\nif (NativeProxy) {\n Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {\n NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};\n NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {\n NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {\n const { key, argumentsCount } = methodInfo;\n if (argumentsCount !== args.length) {\n return Promise.reject(\n new Error(\n `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${\n argumentsCount === 1 ? 'argument' : 'arguments'\n } but received ${args.length}`\n )\n );\n }\n\n if (canUseExpoTurboModules && global.ExpoModulesProxy) {\n return global.ExpoModulesProxy.callMethodAsync(moduleName, methodInfo.name, args);\n } else {\n return NativeProxy.callMethod(moduleName, key, args);\n }\n };\n });\n\n // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)\n // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.\n //\n // On Android only {start,stop}Observing are called on the native module\n // and these should be exported as Expo methods.\n //\n // Before the RN 65, addListener/removeListeners weren't called on Android. However, it no longer stays true.\n // See https://github.com/facebook/react-native/commit/f5502fbda9fe271ff6e1d0da773a3a8ee206a453.\n // That's why, we check if the `EXReactNativeEventEmitter` exists and only if yes, we use it in the listener implementation.\n // Otherwise, those methods are NOOP.\n if (NativeModules.EXReactNativeEventEmitter) {\n NativeModulesProxy[moduleName].addListener = (...args) =>\n NativeModules.EXReactNativeEventEmitter.addProxiedListener(moduleName, ...args);\n NativeModulesProxy[moduleName].removeListeners = (...args) =>\n NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);\n } else {\n // Fixes on Android:\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.\n NativeModulesProxy[moduleName].addListener = () => {};\n NativeModulesProxy[moduleName].removeListeners = () => {};\n }\n });\n} else {\n console.warn(\n `The \"EXNativeModulesProxy\" native module is not exported through NativeModules; verify that expo-modules-core's native code is linked properly`\n );\n}\n\nexport default NativeModulesProxy;\n"]}
1
+ {"version":3,"file":"NativeModulesProxy.native.js","sourceRoot":"","sources":["../src/NativeModulesProxy.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,MAAM,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC;AACvD,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C,MAAM,kBAAkB,GAAgD,EAAE,CAAC;AAE3E,IAAI,WAAW,EAAE;IACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QAClE,kBAAkB,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACpF,WAAW,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAe,EAAgB,EAAE;gBACrF,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;gBAC3C,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE;oBAClC,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,iBAAiB,UAAU,IAAI,UAAU,CAAC,IAAI,YAAY,cAAc,IACtE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WACtC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAC/B,CACF,CAAC;iBACH;gBACD,OAAO,WAAW,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACvD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,kFAAkF;QAClF,EAAE;QACF,wEAAwE;QACxE,gDAAgD;QAChD,EAAE;QACF,6GAA6G;QAC7G,gGAAgG;QAChG,4HAA4H;QAC5H,qCAAqC;QACrC,IAAI,aAAa,CAAC,yBAAyB,EAAE;YAC3C,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CACvD,aAAa,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAClF,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAC3D,aAAa,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;SACvF;aAAM;YACL,oBAAoB;YACpB,kHAAkH;YAClH,sHAAsH;YACtH,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;YACtD,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;SAC3D;IACH,CAAC,CAAC,CAAC;CACJ;KAAM;IACL,OAAO,CAAC,IAAI,CACV,gJAAgJ,CACjJ,CAAC;CACH;AAED,eAAe,kBAAkB,CAAC","sourcesContent":["import { NativeModules } from 'react-native';\n\nimport { ProxyNativeModule } from './NativeModulesProxy.types';\n\nconst NativeProxy = NativeModules.NativeUnimoduleProxy;\nconst modulesConstantsKey = 'modulesConstants';\nconst exportedMethodsKey = 'exportedMethods';\n\nconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};\n\nif (NativeProxy) {\n Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {\n NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};\n NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {\n NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {\n const { key, argumentsCount } = methodInfo;\n if (argumentsCount !== args.length) {\n return Promise.reject(\n new Error(\n `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${\n argumentsCount === 1 ? 'argument' : 'arguments'\n } but received ${args.length}`\n )\n );\n }\n return NativeProxy.callMethod(moduleName, key, args);\n };\n });\n\n // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)\n // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.\n //\n // On Android only {start,stop}Observing are called on the native module\n // and these should be exported as Expo methods.\n //\n // Before the RN 65, addListener/removeListeners weren't called on Android. However, it no longer stays true.\n // See https://github.com/facebook/react-native/commit/f5502fbda9fe271ff6e1d0da773a3a8ee206a453.\n // That's why, we check if the `EXReactNativeEventEmitter` exists and only if yes, we use it in the listener implementation.\n // Otherwise, those methods are NOOP.\n if (NativeModules.EXReactNativeEventEmitter) {\n NativeModulesProxy[moduleName].addListener = (...args) =>\n NativeModules.EXReactNativeEventEmitter.addProxiedListener(moduleName, ...args);\n NativeModulesProxy[moduleName].removeListeners = (...args) =>\n NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);\n } else {\n // Fixes on Android:\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.\n NativeModulesProxy[moduleName].addListener = () => {};\n NativeModulesProxy[moduleName].removeListeners = () => {};\n }\n });\n} else {\n console.warn(\n `The \"EXNativeModulesProxy\" native module is not exported through NativeModules; verify that expo-modules-core's native code is linked properly`\n );\n}\n\nexport default NativeModulesProxy;\n"]}
@@ -3,6 +3,4 @@ export declare type ProxyNativeModule = {
3
3
  addListener: (eventName: string) => void;
4
4
  removeListeners: (count: number) => void;
5
5
  };
6
- export declare type TurboNativeModuleProxy = {
7
- callMethodAsync: <ReturnType>(moduleName: string, methodName: string, args: any[]) => Promise<ReturnType>;
8
- };
6
+ //# sourceMappingURL=NativeModulesProxy.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeModulesProxy.types.d.ts","sourceRoot":"","sources":["../src/NativeModulesProxy.types.ts"],"names":[],"mappings":"AAAA,oBAAY,iBAAiB,GAAG;IAC9B,CAAC,YAAY,EAAE,MAAM,GAAG,GAAG,CAAC;IAC5B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"NativeModulesProxy.types.js","sourceRoot":"","sources":["../src/NativeModulesProxy.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ProxyNativeModule = {\n [propertyName: string]: any;\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\nexport type TurboNativeModuleProxy = {\n callMethodAsync: <ReturnType>(\n moduleName: string,\n methodName: string,\n args: any[]\n ) => Promise<ReturnType>;\n};\n"]}
1
+ {"version":3,"file":"NativeModulesProxy.types.js","sourceRoot":"","sources":["../src/NativeModulesProxy.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ProxyNativeModule = {\n [propertyName: string]: any;\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n"]}
@@ -1,2 +1,3 @@
1
1
  import React from 'react';
2
2
  export declare function requireNativeViewManager<P = any>(viewName: string): React.ComponentType<P>;
3
+ //# sourceMappingURL=NativeViewManagerAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeViewManagerAdapter.d.ts","sourceRoot":"","sources":["../src/NativeViewManagerAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAE1F"}
@@ -3,3 +3,4 @@ import React from 'react';
3
3
  * A drop-in replacement for `requireNativeComponent`.
4
4
  */
5
5
  export declare function requireNativeViewManager<P = any>(viewName: string): React.ComponentType<P>;
6
+ //# sourceMappingURL=NativeViewManagerAdapter.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeViewManagerAdapter.native.d.ts","sourceRoot":"","sources":["../src/NativeViewManagerAdapter.native.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgB1B;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CA0B1F"}
@@ -1,48 +1,24 @@
1
1
  import React from 'react';
2
- import { NativeModules, UIManager, ViewPropTypes, requireNativeComponent } from 'react-native';
3
- // To make the transition from React Native's `requireNativeComponent` to Expo's
4
- // `requireNativeViewManager` as easy as possible, `requireNativeViewManager` is a drop-in
5
- // replacement for `requireNativeComponent`.
6
- //
7
- // For each view manager, we create a wrapper component that accepts all of the props available to
8
- // the author of the universal module. This wrapper component splits the props into two sets: props
9
- // passed to React Native's View (ex: style, testID) and custom view props, which are passed to the
10
- // adapter view component in a prop called `proxiedProperties`.
11
- // NOTE: React Native is moving away from runtime PropTypes and may remove ViewPropTypes, in which
12
- // case we will need another way to separate standard React Native view props from other props,
13
- // which we proxy through the adapter
14
- const ViewPropTypesKeys = Object.keys(ViewPropTypes);
2
+ import { NativeModules, requireNativeComponent } from 'react-native';
15
3
  /**
16
4
  * A drop-in replacement for `requireNativeComponent`.
17
5
  */
18
6
  export function requireNativeViewManager(viewName) {
19
- if (__DEV__) {
20
- const { NativeUnimoduleProxy } = NativeModules;
21
- if (!NativeUnimoduleProxy.viewManagersNames.includes(viewName)) {
22
- const exportedViewManagerNames = NativeUnimoduleProxy.viewManagersNames.join(', ');
23
- console.warn(`The native view manager required by name (${viewName}) from NativeViewManagerAdapter isn't exported by expo-modules-core. Views of this type may not render correctly. Exported view managers: [${exportedViewManagerNames}].`);
24
- }
7
+ const { viewManagersMetadata } = NativeModules.NativeUnimoduleProxy;
8
+ const viewManagerConfig = viewManagersMetadata?.[viewName];
9
+ if (__DEV__ && !viewManagerConfig) {
10
+ const exportedViewManagerNames = Object.keys(viewManagersMetadata).join(', ');
11
+ console.warn(`The native view manager required by name (${viewName}) from NativeViewManagerAdapter isn't exported by expo-modules-core. Views of this type may not render correctly. Exported view managers: [${exportedViewManagerNames}].`);
25
12
  }
26
13
  // Set up the React Native native component, which is an adapter to the universal module's view
27
14
  // manager
28
15
  const reactNativeViewName = `ViewManagerAdapter_${viewName}`;
29
16
  const ReactNativeComponent = requireNativeComponent(reactNativeViewName);
30
- const reactNativeUIConfiguration = (UIManager.getViewManagerConfig
31
- ? UIManager.getViewManagerConfig(reactNativeViewName)
32
- : UIManager[reactNativeViewName]) || {
33
- NativeProps: {},
34
- directEventTypes: {},
35
- };
36
- const reactNativeComponentPropNames = [
37
- 'children',
38
- ...ViewPropTypesKeys,
39
- ...Object.keys(reactNativeUIConfiguration.NativeProps),
40
- ...Object.keys(reactNativeUIConfiguration.directEventTypes),
41
- ];
17
+ const proxiedPropsNames = viewManagerConfig?.propsNames ?? [];
42
18
  // Define a component for universal-module authors to access their native view manager
43
19
  function NativeComponentAdapter(props, ref) {
44
- const nativeProps = pick(props, reactNativeComponentPropNames);
45
- const proxiedProps = omit(props, reactNativeComponentPropNames);
20
+ const nativeProps = omit(props, proxiedPropsNames);
21
+ const proxiedProps = pick(props, proxiedPropsNames);
46
22
  return React.createElement(ReactNativeComponent, { ...nativeProps, proxiedProperties: proxiedProps, ref: ref });
47
23
  }
48
24
  NativeComponentAdapter.displayName = `Adapter<${viewName}>`;