expo-modules-core 0.4.6 → 0.6.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.
- package/CHANGELOG.md +39 -0
- package/README.md +6 -6
- package/android/build.gradle +30 -2
- package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +27 -5
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +49 -5
- package/android/src/main/java/expo/modules/core/BasePackage.java +6 -0
- package/android/src/main/java/expo/modules/core/ModulePriorities.kt +25 -0
- package/android/src/main/java/expo/modules/core/interfaces/ActivityEventListener.java +3 -1
- package/android/src/main/java/expo/modules/core/interfaces/ApplicationLifecycleListener.java +10 -0
- package/android/src/main/java/expo/modules/core/interfaces/Package.java +4 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +21 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityLifecycleListener.java +14 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +70 -0
- package/android/src/main/java/expo/modules/core/utilities/KotlinUtilities.kt +23 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +166 -0
- package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +9 -0
- package/android/src/main/java/expo/modules/kotlin/ExpoModulesHelper.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +24 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +98 -0
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +41 -0
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +56 -0
- package/android/src/main/java/expo/modules/kotlin/ModulesProvider.kt +7 -0
- package/android/src/main/java/expo/modules/kotlin/Promise.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/ReactLifecycleDelegate.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/ReadableArrayIterator.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/ReadableTypeExtensions.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructor.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructorFactory.kt +31 -0
- package/android/src/main/java/expo/modules/kotlin/allocators/UnsafeAllocator.kt +49 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventListener.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventName.kt +31 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventsDefinition.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +26 -0
- package/android/src/main/java/expo/modules/kotlin/events/OnActivityResultPayload.kt +8 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +70 -0
- package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +50 -0
- package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +24 -0
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +227 -0
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +16 -0
- package/android/src/main/java/expo/modules/kotlin/records/Field.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/records/Record.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +55 -0
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +44 -0
- package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +60 -0
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +84 -0
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +25 -0
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +28 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +19 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +107 -0
- package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +10 -0
- package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +17 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +41 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +40 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewWrapperDelegateHolder.kt +5 -0
- package/build/NativeModulesProxy.native.d.ts +4 -0
- package/build/NativeModulesProxy.native.js +14 -1
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/build/NativeModulesProxy.types.d.ts +3 -0
- package/build/NativeModulesProxy.types.js.map +1 -1
- package/build/NativeViewManagerAdapter.native.js +1 -1
- package/build/NativeViewManagerAdapter.native.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegateWrapper.h +19 -0
- package/ios/AppDelegates/EXAppDelegateWrapper.m +45 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.h +15 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.m +30 -0
- package/ios/AppDelegates/EXLegacyAppDelegateWrapper.h +16 -0
- package/ios/{EXAppDelegateWrapper.m → AppDelegates/EXLegacyAppDelegateWrapper.m} +2 -2
- package/ios/AppDelegates/ExpoAppDelegate.swift +282 -0
- package/ios/AppDelegates/ExpoAppDelegateSubscriber.swift +24 -0
- package/ios/EXAppDefines.h +26 -0
- package/ios/EXAppDefines.m +61 -0
- package/ios/ExpoModulesCore.podspec +8 -3
- package/ios/JSI/ExpoModulesProxySpec.h +24 -0
- package/ios/JSI/ExpoModulesProxySpec.mm +135 -0
- package/ios/JSI/JSIConversions.h +42 -0
- package/ios/JSI/JSIConversions.mm +164 -0
- package/ios/JSI/JSIInstaller.h +19 -0
- package/ios/JSI/JSIInstaller.mm +22 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -6
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +6 -0
- package/ios/NativeModulesProxy/{EXNativeModulesProxy.m → EXNativeModulesProxy.mm} +91 -18
- package/ios/ReactDelegates/EXRCTBridgeDelegateInterceptor.h +16 -0
- package/ios/ReactDelegates/EXRCTBridgeDelegateInterceptor.m +49 -0
- package/ios/ReactDelegates/EXReactDelegateWrapper+Private.h +18 -0
- package/ios/ReactDelegates/EXReactDelegateWrapper.h +25 -0
- package/ios/ReactDelegates/EXReactDelegateWrapper.m +40 -0
- package/ios/ReactDelegates/ExpoReactDelegate.swift +37 -0
- package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +52 -0
- package/ios/ReactDelegates/ModulePriorities.swift +20 -0
- package/ios/Services/EXReactNativeEventEmitter.h +6 -0
- package/ios/Services/EXReactNativeEventEmitter.m +15 -0
- package/ios/Swift/AppContext.swift +14 -1
- package/ios/Swift/Arguments/AnyArgument.swift +14 -0
- package/ios/Swift/Arguments/AnyArgumentType.swift +13 -0
- package/ios/Swift/Arguments/ArgumentType.swift +24 -0
- package/ios/Swift/Arguments/ConvertibleArgument.swift +15 -0
- package/ios/Swift/Arguments/Convertibles.swift +107 -0
- package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +42 -0
- package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +16 -0
- package/ios/Swift/Arguments/Types/EnumArgumentType.swift +105 -0
- package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +49 -0
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +15 -0
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +25 -0
- package/ios/Swift/Conversions.swift +199 -7
- package/ios/Swift/EventListener.swift +37 -5
- package/ios/Swift/Functions/AnyFunction.swift +42 -0
- package/ios/Swift/{Methods/ConcreteMethod.swift → Functions/ConcreteFunction.swift} +32 -34
- package/ios/Swift/ModuleHolder.swift +86 -20
- package/ios/Swift/ModuleRegistry.swift +19 -8
- package/ios/Swift/Modules/AnyModule.swift +8 -8
- package/ios/Swift/Modules/Module.swift +11 -0
- package/ios/Swift/Modules/ModuleDefinition.swift +55 -15
- package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +1 -1
- package/ios/Swift/Modules/ModuleDefinitionComponents.swift +149 -54
- package/ios/Swift/ModulesProvider.swift +19 -0
- package/ios/Swift/Promise.swift +1 -1
- package/ios/Swift/Records/Field.swift +1 -1
- package/ios/Swift/Records/Record.swift +8 -1
- package/ios/Swift/SwiftInteropBridge.swift +46 -17
- package/ios/Swift/Views/AnyViewProp.swift +2 -2
- package/ios/Swift/Views/ConcreteViewProp.swift +37 -10
- package/ios/Swift/Views/ViewModuleWrapper.swift +9 -4
- package/ios/Swift.h +9 -0
- package/ios/Tests/ArgumentTypeSpec.swift +145 -0
- package/ios/Tests/ConstantsSpec.swift +36 -0
- package/ios/Tests/ConvertiblesSpec.swift +265 -0
- package/ios/Tests/EXAppDefinesTest.m +99 -0
- package/ios/Tests/{MethodSpec.swift → FunctionSpec.swift} +69 -54
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +66 -0
- package/ios/Tests/Mocks/ModuleMocks.swift +21 -7
- package/ios/Tests/ModuleEventListenersSpec.swift +17 -16
- package/ios/Tests/ModuleRegistrySpec.swift +4 -7
- package/package.json +3 -3
- package/src/NativeModulesProxy.native.ts +22 -2
- package/src/NativeModulesProxy.types.ts +8 -0
- package/src/NativeViewManagerAdapter.native.tsx +1 -1
- package/android/src/main/java/expo/modules/core/interfaces/ApplicationLifecycleListener.kt +0 -9
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityLifecycleListener.kt +0 -11
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.kt +0 -51
- package/ios/EXAppDelegateWrapper.h +0 -13
- package/ios/Swift/Methods/AnyArgumentType.swift +0 -48
- package/ios/Swift/Methods/AnyMethod.swift +0 -31
- package/ios/Swift/Methods/AnyMethodArgument.swift +0 -13
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
package expo.modules.kotlin.types
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Dynamic
|
|
4
|
+
import expo.modules.kotlin.exception.IncompatibleArgTypeException
|
|
5
|
+
import expo.modules.kotlin.toKType
|
|
6
|
+
import kotlin.reflect.KClass
|
|
7
|
+
import kotlin.reflect.full.createType
|
|
8
|
+
import kotlin.reflect.full.declaredMemberProperties
|
|
9
|
+
import kotlin.reflect.full.primaryConstructor
|
|
10
|
+
|
|
11
|
+
class EnumTypeConverter(
|
|
12
|
+
private val enumClass: KClass<Enum<*>>,
|
|
13
|
+
isOptional: Boolean
|
|
14
|
+
) : TypeConverter<Enum<*>>(isOptional) {
|
|
15
|
+
override fun convertNonOptional(value: Dynamic): Enum<*> {
|
|
16
|
+
@Suppress("UNCHECKED_CAST")
|
|
17
|
+
val enumConstants = requireNotNull(enumClass.java.enumConstants) {
|
|
18
|
+
"Passed type is not an enum type."
|
|
19
|
+
}
|
|
20
|
+
require(enumConstants.isNotEmpty()) {
|
|
21
|
+
"Passed enum type is empty."
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
val primaryConstructor = requireNotNull(enumClass.primaryConstructor) {
|
|
25
|
+
"Cannot convert js value to enum without the primary constructor."
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (primaryConstructor.parameters.isEmpty()) {
|
|
29
|
+
return convertEnumWithoutParameter(value, enumConstants)
|
|
30
|
+
} else if (primaryConstructor.parameters.size == 1) {
|
|
31
|
+
return convertEnumWithParameter(
|
|
32
|
+
value,
|
|
33
|
+
enumConstants,
|
|
34
|
+
primaryConstructor.parameters.first().name!!
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
throw IncompatibleArgTypeException(value.type.toKType(), enumClass.createType())
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* If the primary constructor doesn't take any parameters, we treat the name of each enum as a value.
|
|
43
|
+
* So the jsValue has to contain string.
|
|
44
|
+
*/
|
|
45
|
+
private fun convertEnumWithoutParameter(
|
|
46
|
+
jsValue: Dynamic,
|
|
47
|
+
enumConstants: Array<out Enum<*>>
|
|
48
|
+
): Enum<*> {
|
|
49
|
+
val unwrappedJsValue = jsValue.asString()
|
|
50
|
+
return requireNotNull(
|
|
51
|
+
enumConstants.find { it.name == unwrappedJsValue }
|
|
52
|
+
) { "Couldn't convert ${jsValue.asString()} to ${enumClass.simpleName}." }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* If the primary constructor take one parameter, we treat this parameter as a enum value.
|
|
57
|
+
* In that case, we handles two different types: Int and String.
|
|
58
|
+
*/
|
|
59
|
+
private fun convertEnumWithParameter(
|
|
60
|
+
jsValue: Dynamic,
|
|
61
|
+
enumConstants: Array<out Enum<*>>,
|
|
62
|
+
parameterName: String
|
|
63
|
+
): Enum<*> {
|
|
64
|
+
// To obtain the value of parameter, we have to find a property that is connected with this parameter.
|
|
65
|
+
@Suppress("UNCHECKED_CAST")
|
|
66
|
+
val parameterProperty = enumClass
|
|
67
|
+
.declaredMemberProperties
|
|
68
|
+
.find { it.name == parameterName }
|
|
69
|
+
requireNotNull(parameterProperty) { "Cannot find a property for $parameterName parameter." }
|
|
70
|
+
|
|
71
|
+
val parameterType = parameterProperty.returnType.classifier
|
|
72
|
+
val jsUnwrapValue = if (parameterType == String::class) {
|
|
73
|
+
jsValue.asString()
|
|
74
|
+
} else {
|
|
75
|
+
jsValue.asInt()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return requireNotNull(
|
|
79
|
+
enumConstants.find {
|
|
80
|
+
parameterProperty.get(it) == jsUnwrapValue
|
|
81
|
+
}
|
|
82
|
+
) { "Couldn't convert ${jsValue.asString()} to ${enumClass.simpleName} where $parameterName is the enum parameter. " }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package expo.modules.kotlin.types
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Dynamic
|
|
4
|
+
import expo.modules.kotlin.recycle
|
|
5
|
+
import kotlin.reflect.KType
|
|
6
|
+
|
|
7
|
+
class ListTypeConverter(
|
|
8
|
+
converterProvider: TypeConverterProvider,
|
|
9
|
+
type: KType,
|
|
10
|
+
) : TypeConverter<List<*>>(type.isMarkedNullable) {
|
|
11
|
+
private val elementConverter = converterProvider.obtainTypeConverter(
|
|
12
|
+
requireNotNull(type.arguments.first().type) {
|
|
13
|
+
"The list type should contain the type of elements."
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
override fun convertNonOptional(value: Dynamic): List<*> {
|
|
18
|
+
val jsArray = value.asArray()
|
|
19
|
+
return List(jsArray.size()) { index ->
|
|
20
|
+
jsArray.getDynamic(index).recycle {
|
|
21
|
+
elementConverter.convert(this)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalStdlibApi::class)
|
|
2
|
+
|
|
3
|
+
package expo.modules.kotlin.types
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.Dynamic
|
|
6
|
+
import com.facebook.react.bridge.DynamicFromObject
|
|
7
|
+
import expo.modules.kotlin.recycle
|
|
8
|
+
import kotlin.reflect.KType
|
|
9
|
+
import kotlin.reflect.typeOf
|
|
10
|
+
|
|
11
|
+
class MapTypeConverter(
|
|
12
|
+
converterProvider: TypeConverterProvider,
|
|
13
|
+
type: KType
|
|
14
|
+
) : TypeConverter<Map<*, *>>(type.isMarkedNullable) {
|
|
15
|
+
init {
|
|
16
|
+
require(type.arguments.first().type == typeOf<String>()) {
|
|
17
|
+
"The map key type should be String, but received ${type.arguments.first()}."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private val valueConverter = converterProvider.obtainTypeConverter(
|
|
22
|
+
requireNotNull(type.arguments.getOrNull(1)?.type) {
|
|
23
|
+
"The map type should contain the key type."
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
override fun convertNonOptional(value: Dynamic): Map<*, *> {
|
|
28
|
+
val jsMap = value.asMap()
|
|
29
|
+
val result = mutableMapOf<String, Any?>()
|
|
30
|
+
|
|
31
|
+
jsMap.entryIterator.forEach { (key, value) ->
|
|
32
|
+
DynamicFromObject(value).recycle {
|
|
33
|
+
result[key] = valueConverter.convert(this)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return result
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package expo.modules.kotlin.types
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Dynamic
|
|
4
|
+
import kotlin.reflect.KType
|
|
5
|
+
|
|
6
|
+
class PairTypeConverter(
|
|
7
|
+
converterProvider: TypeConverterProvider,
|
|
8
|
+
type: KType,
|
|
9
|
+
) : TypeConverter<Pair<*, *>>(type.isMarkedNullable) {
|
|
10
|
+
private val firstConverter = converterProvider.obtainTypeConverter(
|
|
11
|
+
requireNotNull(type.arguments.getOrNull(0)?.type) {
|
|
12
|
+
"The pair type should contain the type of the first parameter."
|
|
13
|
+
}
|
|
14
|
+
)
|
|
15
|
+
private val secondConverter = converterProvider.obtainTypeConverter(
|
|
16
|
+
requireNotNull(type.arguments.getOrNull(1)?.type) {
|
|
17
|
+
"The pair type should contain the type of the second parameter."
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
override fun convertNonOptional(value: Dynamic): Pair<*, *> {
|
|
22
|
+
val jsArray = value.asArray()
|
|
23
|
+
return Pair(
|
|
24
|
+
firstConverter.convert(jsArray.getDynamic(0)),
|
|
25
|
+
secondConverter.convert(jsArray.getDynamic(1)),
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package expo.modules.kotlin.types
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Dynamic
|
|
4
|
+
|
|
5
|
+
abstract class TypeConverter<Type : Any>(
|
|
6
|
+
private val isOptional: Boolean
|
|
7
|
+
) {
|
|
8
|
+
open fun convert(value: Dynamic): Type? {
|
|
9
|
+
if (value.isNull) {
|
|
10
|
+
if (isOptional) {
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
throw IllegalArgumentException()
|
|
14
|
+
}
|
|
15
|
+
return convertNonOptional(value)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
abstract fun convertNonOptional(value: Dynamic): Type
|
|
19
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalStdlibApi::class)
|
|
2
|
+
|
|
3
|
+
package expo.modules.kotlin.types
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.Dynamic
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import expo.modules.kotlin.exception.MissingTypeConverter
|
|
9
|
+
import expo.modules.kotlin.records.Record
|
|
10
|
+
import expo.modules.kotlin.records.RecordTypeConverter
|
|
11
|
+
import kotlin.reflect.KClass
|
|
12
|
+
import kotlin.reflect.KType
|
|
13
|
+
import kotlin.reflect.full.createType
|
|
14
|
+
import kotlin.reflect.full.isSubclassOf
|
|
15
|
+
import kotlin.reflect.typeOf
|
|
16
|
+
|
|
17
|
+
interface TypeConverterProvider {
|
|
18
|
+
fun obtainTypeConverter(type: KType): TypeConverter<*>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
inline fun <reified T : Any> obtainTypeConverter(): TypeConverter<T> {
|
|
22
|
+
@Suppress("UNCHECKED_CAST")
|
|
23
|
+
return TypeConverterProviderImpl.obtainTypeConverter(typeOf<T>()) as TypeConverter<T>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
inline fun <reified T> convert(value: Dynamic): T {
|
|
27
|
+
val converter = TypeConverterProviderImpl.obtainTypeConverter(typeOf<T>())
|
|
28
|
+
return converter.convert(value) as T
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun convert(value: Dynamic, type: KType): Any? {
|
|
32
|
+
val converter = TypeConverterProviderImpl.obtainTypeConverter(type)
|
|
33
|
+
return converter.convert(value)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
object TypeConverterProviderImpl : TypeConverterProvider {
|
|
37
|
+
private val cachedConverters = createCashedConverters(false) + createCashedConverters(true)
|
|
38
|
+
|
|
39
|
+
override fun obtainTypeConverter(type: KType): TypeConverter<*> {
|
|
40
|
+
cachedConverters[type]?.let {
|
|
41
|
+
return it
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
val kClass = type.classifier as? KClass<*> ?: throw MissingTypeConverter(type)
|
|
45
|
+
|
|
46
|
+
if (kClass.java.isArray) {
|
|
47
|
+
return ArrayTypeConverter(this, type)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (kClass.isSubclassOf(List::class)) {
|
|
51
|
+
return ListTypeConverter(this, type)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (kClass.isSubclassOf(Map::class)) {
|
|
55
|
+
return MapTypeConverter(this, type)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (kClass.isSubclassOf(Pair::class)) {
|
|
59
|
+
return PairTypeConverter(this, type)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (kClass.isSubclassOf(Array::class)) {
|
|
63
|
+
return ArrayTypeConverter(this, type)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (kClass.java.isEnum) {
|
|
67
|
+
@Suppress("UNCHECKED_CAST")
|
|
68
|
+
return EnumTypeConverter(kClass as KClass<Enum<*>>, type.isMarkedNullable)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (kClass.isSubclassOf(Record::class)) {
|
|
72
|
+
return RecordTypeConverter<Record>(this, type)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw MissingTypeConverter(type)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private fun createCashedConverters(isOptional: Boolean): Map<KType, TypeConverter<*>> {
|
|
79
|
+
val intTypeConverter = IntTypeConverter(isOptional)
|
|
80
|
+
val doubleTypeConverter = DoubleTypeConverter(isOptional)
|
|
81
|
+
val floatTypeConverter = FloatTypeConverter(isOptional)
|
|
82
|
+
val boolTypeConverter = BoolTypeConverter(isOptional)
|
|
83
|
+
|
|
84
|
+
return mapOf(
|
|
85
|
+
Int::class.createType(nullable = isOptional) to intTypeConverter,
|
|
86
|
+
java.lang.Integer::class.createType(nullable = isOptional) to intTypeConverter,
|
|
87
|
+
|
|
88
|
+
Double::class.createType(nullable = isOptional) to doubleTypeConverter,
|
|
89
|
+
java.lang.Double::class.createType(nullable = isOptional) to doubleTypeConverter,
|
|
90
|
+
|
|
91
|
+
Float::class.createType(nullable = isOptional) to floatTypeConverter,
|
|
92
|
+
java.lang.Float::class.createType(nullable = isOptional) to floatTypeConverter,
|
|
93
|
+
|
|
94
|
+
Boolean::class.createType(nullable = isOptional) to boolTypeConverter,
|
|
95
|
+
java.lang.Boolean::class.createType(nullable = isOptional) to boolTypeConverter,
|
|
96
|
+
|
|
97
|
+
String::class.createType(nullable = isOptional) to StringTypeConverter(isOptional),
|
|
98
|
+
|
|
99
|
+
ReadableArray::class.createType(nullable = isOptional) to ReadableArrayTypeConverter(isOptional),
|
|
100
|
+
ReadableMap::class.createType(nullable = isOptional) to ReadableMapTypeConverter(isOptional),
|
|
101
|
+
|
|
102
|
+
IntArray::class.createType(nullable = isOptional) to PrimitiveIntArrayTypeConverter(isOptional),
|
|
103
|
+
DoubleArray::class.createType(nullable = isOptional) to PrimitiveDoubleArrayTypeConverter(isOptional),
|
|
104
|
+
FloatArray::class.createType(nullable = isOptional) to PrimitiveFloatArrayTypeConverter(isOptional),
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package expo.modules.kotlin.views
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.Dynamic
|
|
5
|
+
import expo.modules.kotlin.types.AnyType
|
|
6
|
+
|
|
7
|
+
class ConcreteViewProp<ViewType : View, PropType>(
|
|
8
|
+
name: String,
|
|
9
|
+
private val propType: AnyType,
|
|
10
|
+
private val setter: (view: ViewType, prop: PropType) -> Unit,
|
|
11
|
+
) : AnyViewProp(name) {
|
|
12
|
+
|
|
13
|
+
@Suppress("UNCHECKED_CAST")
|
|
14
|
+
override fun set(prop: Dynamic, onView: View) {
|
|
15
|
+
setter(onView as ViewType, propType.convert(prop) as PropType)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package expo.modules.kotlin.views
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import android.view.ViewGroup
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
+
import com.facebook.react.uimanager.ViewGroupManager
|
|
8
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
9
|
+
|
|
10
|
+
class GroupViewManagerWrapper(
|
|
11
|
+
override val viewWrapperDelegate: ViewManagerWrapperDelegate
|
|
12
|
+
) : ViewGroupManager<ViewGroup>(), ViewWrapperDelegateHolder {
|
|
13
|
+
override fun getName(): String = "ViewManagerAdapter_${viewWrapperDelegate.name}"
|
|
14
|
+
|
|
15
|
+
override fun createViewInstance(reactContext: ThemedReactContext): ViewGroup =
|
|
16
|
+
viewWrapperDelegate.createView(reactContext) as ViewGroup
|
|
17
|
+
|
|
18
|
+
@ReactProp(name = "proxiedProperties")
|
|
19
|
+
fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
|
|
20
|
+
viewWrapperDelegate.setProxiedProperties(view, proxiedProperties)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package expo.modules.kotlin.views
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
6
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
8
|
+
|
|
9
|
+
class SimpleViewManagerWrapper(
|
|
10
|
+
override val viewWrapperDelegate: ViewManagerWrapperDelegate
|
|
11
|
+
) : SimpleViewManager<View>(), ViewWrapperDelegateHolder {
|
|
12
|
+
override fun getName(): String = "ViewManagerAdapter_${viewWrapperDelegate.name}"
|
|
13
|
+
|
|
14
|
+
override fun createViewInstance(reactContext: ThemedReactContext): View =
|
|
15
|
+
viewWrapperDelegate.createView(reactContext)
|
|
16
|
+
|
|
17
|
+
@ReactProp(name = "proxiedProperties")
|
|
18
|
+
fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
|
|
19
|
+
viewWrapperDelegate.setProxiedProperties(view, proxiedProperties)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package expo.modules.kotlin.views
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.view.ViewGroup
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import expo.modules.core.ViewManager
|
|
9
|
+
import expo.modules.kotlin.recycle
|
|
10
|
+
|
|
11
|
+
class ViewManagerDefinition(
|
|
12
|
+
private val viewFactory: (Context) -> View,
|
|
13
|
+
private val viewType: Class<out View>,
|
|
14
|
+
private val props: Map<String, AnyViewProp>
|
|
15
|
+
) {
|
|
16
|
+
|
|
17
|
+
fun createView(context: Context): View = viewFactory(context)
|
|
18
|
+
|
|
19
|
+
fun getViewManagerType(): ViewManager.ViewManagerType {
|
|
20
|
+
return if (ViewGroup::class.java.isAssignableFrom(viewType)) {
|
|
21
|
+
ViewManager.ViewManagerType.GROUP
|
|
22
|
+
} else {
|
|
23
|
+
ViewManager.ViewManagerType.SIMPLE
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun setProps(propsToSet: ReadableMap, onView: View) {
|
|
28
|
+
val iterator = propsToSet.keySetIterator()
|
|
29
|
+
while (iterator.hasNextKey()) {
|
|
30
|
+
val key = iterator.nextKey()
|
|
31
|
+
val propDelegate = props[key] ?: continue
|
|
32
|
+
propsToSet.getDynamic(key).recycle {
|
|
33
|
+
try {
|
|
34
|
+
propDelegate.set(this, onView)
|
|
35
|
+
} catch (exception: Throwable) {
|
|
36
|
+
Log.e("ExpoModulesCore", "Cannot set the $key prop on the ${viewType.simpleName}.", exception)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalStdlibApi::class)
|
|
2
|
+
|
|
3
|
+
package expo.modules.kotlin.views
|
|
4
|
+
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.view.View
|
|
7
|
+
import expo.modules.kotlin.types.toAnyType
|
|
8
|
+
import kotlin.reflect.typeOf
|
|
9
|
+
|
|
10
|
+
class ViewManagerDefinitionBuilder {
|
|
11
|
+
@PublishedApi
|
|
12
|
+
internal var viewFactory: ((Context) -> View)? = null
|
|
13
|
+
@PublishedApi
|
|
14
|
+
internal var viewType: Class<out View>? = null
|
|
15
|
+
@PublishedApi
|
|
16
|
+
internal var props = mutableMapOf<String, AnyViewProp>()
|
|
17
|
+
|
|
18
|
+
fun build(): ViewManagerDefinition =
|
|
19
|
+
ViewManagerDefinition(
|
|
20
|
+
requireNotNull(viewFactory),
|
|
21
|
+
requireNotNull(viewType),
|
|
22
|
+
props
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
inline fun <reified ViewType : View> view(noinline body: (Context) -> ViewType) {
|
|
26
|
+
viewType = ViewType::class.java
|
|
27
|
+
viewFactory = body
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
inline fun <reified ViewType : View, reified PropType> prop(
|
|
31
|
+
name: String,
|
|
32
|
+
noinline body: (view: ViewType, prop: PropType) -> Unit
|
|
33
|
+
) {
|
|
34
|
+
props[name] = ConcreteViewProp(
|
|
35
|
+
name,
|
|
36
|
+
typeOf<PropType>().toAnyType(),
|
|
37
|
+
body
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package expo.modules.kotlin.views
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.View
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import expo.modules.kotlin.ModuleHolder
|
|
7
|
+
|
|
8
|
+
class ViewManagerWrapperDelegate(internal var moduleHolder: ModuleHolder) {
|
|
9
|
+
private val definition: ViewManagerDefinition
|
|
10
|
+
get() = requireNotNull(moduleHolder.definition.viewManagerDefinition)
|
|
11
|
+
|
|
12
|
+
val name: String
|
|
13
|
+
get() = moduleHolder.name
|
|
14
|
+
|
|
15
|
+
fun createView(context: Context): View =
|
|
16
|
+
definition.createView(context)
|
|
17
|
+
|
|
18
|
+
fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
|
|
19
|
+
definition.setProps(proxiedProperties, view)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -2,4 +2,8 @@ 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;
|
|
5
9
|
export default NativeModulesProxy;
|
|
@@ -3,6 +3,14 @@ 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
|
+
}
|
|
6
14
|
if (NativeProxy) {
|
|
7
15
|
Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {
|
|
8
16
|
NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};
|
|
@@ -12,7 +20,12 @@ if (NativeProxy) {
|
|
|
12
20
|
if (argumentsCount !== args.length) {
|
|
13
21
|
return Promise.reject(new Error(`Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${argumentsCount === 1 ? 'argument' : 'arguments'} but received ${args.length}`));
|
|
14
22
|
}
|
|
15
|
-
|
|
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
|
+
}
|
|
16
29
|
};
|
|
17
30
|
});
|
|
18
31
|
// 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;
|
|
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"]}
|
|
@@ -3,3 +3,6 @@ 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
|
+
};
|
|
@@ -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"]}
|
|
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"]}
|
|
@@ -20,7 +20,7 @@ export function requireNativeViewManager(viewName) {
|
|
|
20
20
|
const { NativeUnimoduleProxy } = NativeModules;
|
|
21
21
|
if (!NativeUnimoduleProxy.viewManagersNames.includes(viewName)) {
|
|
22
22
|
const exportedViewManagerNames = NativeUnimoduleProxy.viewManagersNames.join(', ');
|
|
23
|
-
console.warn(`The native view manager required by name (${viewName}) from NativeViewManagerAdapter isn't exported by
|
|
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
24
|
}
|
|
25
25
|
}
|
|
26
26
|
// Set up the React Native native component, which is an adapter to the universal module's view
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeViewManagerAdapter.native.js","sourceRoot":"","sources":["../src/NativeViewManagerAdapter.native.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE/F,gFAAgF;AAChF,0FAA0F;AAC1F,4CAA4C;AAC5C,EAAE;AACF,kGAAkG;AAClG,mGAAmG;AACnG,mGAAmG;AACnG,+DAA+D;AAE/D,kGAAkG;AAClG,+FAA+F;AAC/F,qCAAqC;AACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAMrD;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAU,QAAgB;IAChE,IAAI,OAAO,EAAE;QACX,MAAM,EAAE,oBAAoB,EAAE,GAAG,aAAa,CAAC;QAC/C,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAC9D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CACV,6CAA6C,QAAQ,
|
|
1
|
+
{"version":3,"file":"NativeViewManagerAdapter.native.js","sourceRoot":"","sources":["../src/NativeViewManagerAdapter.native.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE/F,gFAAgF;AAChF,0FAA0F;AAC1F,4CAA4C;AAC5C,EAAE;AACF,kGAAkG;AAClG,mGAAmG;AACnG,mGAAmG;AACnG,+DAA+D;AAE/D,kGAAkG;AAClG,+FAA+F;AAC/F,qCAAqC;AACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAMrD;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAU,QAAgB;IAChE,IAAI,OAAO,EAAE;QACX,MAAM,EAAE,oBAAoB,EAAE,GAAG,aAAa,CAAC;QAC/C,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAC9D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CACV,6CAA6C,QAAQ,8IAA8I,wBAAwB,IAAI,CAChO,CAAC;SACH;KACF;IAED,+FAA+F;IAC/F,UAAU;IACV,MAAM,mBAAmB,GAAG,sBAAsB,QAAQ,EAAE,CAAC;IAC7D,MAAM,oBAAoB,GACxB,sBAAsB,CAA2B,mBAAmB,CAAC,CAAC;IACxE,MAAM,0BAA0B,GAAG,CAAC,SAAS,CAAC,oBAAoB;QAChE,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,mBAAmB,CAAC;QACrD,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,IAAI;QACrC,WAAW,EAAE,EAAE;QACf,gBAAgB,EAAE,EAAE;KACrB,CAAC;IACF,MAAM,6BAA6B,GAAG;QACpC,UAAU;QACV,GAAG,iBAAiB;QACpB,GAAG,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,WAAW,CAAC;QACtD,GAAG,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,gBAAgB,CAAC;KAC5D,CAAC;IAEF,sFAAsF;IACtF,SAAS,sBAAsB,CAAC,KAAK,EAAE,GAAG;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;QAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;QAChE,OAAO,oBAAC,oBAAoB,OAAK,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,GAAI,CAAC;IAC9F,CAAC;IACD,sBAAsB,CAAC,WAAW,GAAG,WAAW,QAAQ,GAAG,CAAC;IAC5D,OAAO,KAAK,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,IAAI,CAAC,KAA0B,EAAE,SAAmB;IAC3D,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC5B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;KACzB;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,IAAI,CAAC,KAA0B,EAAE,SAAmB;IAC3D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QACrC,IAAI,IAAI,IAAI,KAAK,EAAE;YACjB,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;SAC1B;QACD,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC","sourcesContent":["import React from 'react';\nimport { NativeModules, UIManager, ViewPropTypes, requireNativeComponent } from 'react-native';\n\n// To make the transition from React Native's `requireNativeComponent` to Expo's\n// `requireNativeViewManager` as easy as possible, `requireNativeViewManager` is a drop-in\n// replacement for `requireNativeComponent`.\n//\n// For each view manager, we create a wrapper component that accepts all of the props available to\n// the author of the universal module. This wrapper component splits the props into two sets: props\n// passed to React Native's View (ex: style, testID) and custom view props, which are passed to the\n// adapter view component in a prop called `proxiedProperties`.\n\n// NOTE: React Native is moving away from runtime PropTypes and may remove ViewPropTypes, in which\n// case we will need another way to separate standard React Native view props from other props,\n// which we proxy through the adapter\nconst ViewPropTypesKeys = Object.keys(ViewPropTypes);\n\ntype NativeExpoComponentProps = {\n proxiedProperties: object;\n};\n\n/**\n * A drop-in replacement for `requireNativeComponent`.\n */\nexport function requireNativeViewManager<P = any>(viewName: string): React.ComponentType<P> {\n if (__DEV__) {\n const { NativeUnimoduleProxy } = NativeModules;\n if (!NativeUnimoduleProxy.viewManagersNames.includes(viewName)) {\n const exportedViewManagerNames = NativeUnimoduleProxy.viewManagersNames.join(', ');\n console.warn(\n `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}].`\n );\n }\n }\n\n // Set up the React Native native component, which is an adapter to the universal module's view\n // manager\n const reactNativeViewName = `ViewManagerAdapter_${viewName}`;\n const ReactNativeComponent =\n requireNativeComponent<NativeExpoComponentProps>(reactNativeViewName);\n const reactNativeUIConfiguration = (UIManager.getViewManagerConfig\n ? UIManager.getViewManagerConfig(reactNativeViewName)\n : UIManager[reactNativeViewName]) || {\n NativeProps: {},\n directEventTypes: {},\n };\n const reactNativeComponentPropNames = [\n 'children',\n ...ViewPropTypesKeys,\n ...Object.keys(reactNativeUIConfiguration.NativeProps),\n ...Object.keys(reactNativeUIConfiguration.directEventTypes),\n ];\n\n // Define a component for universal-module authors to access their native view manager\n function NativeComponentAdapter(props, ref) {\n const nativeProps = pick(props, reactNativeComponentPropNames);\n const proxiedProps = omit(props, reactNativeComponentPropNames);\n return <ReactNativeComponent {...nativeProps} proxiedProperties={proxiedProps} ref={ref} />;\n }\n NativeComponentAdapter.displayName = `Adapter<${viewName}>`;\n return React.forwardRef(NativeComponentAdapter);\n}\n\nfunction omit(props: Record<string, any>, propNames: string[]) {\n const copied = { ...props };\n for (const propName of propNames) {\n delete copied[propName];\n }\n return copied;\n}\n\nfunction pick(props: Record<string, any>, propNames: string[]) {\n return propNames.reduce((prev, curr) => {\n if (curr in props) {\n prev[curr] = props[curr];\n }\n return prev;\n }, {});\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <UIKit/UIKit.h>
|
|
4
|
+
#import <ExpoModulesCore/EXReactDelegateWrapper.h>
|
|
5
|
+
|
|
6
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
Provides backwards compatibility for existing projects with `AppDelegate`
|
|
10
|
+
written in Objective-C and that forwards all messages to the new `ExpoAppDelegate`.
|
|
11
|
+
If your `AppDelegate` is in Swift, it should inherit from `ExpoAppDelegate` class instead.
|
|
12
|
+
*/
|
|
13
|
+
@interface EXAppDelegateWrapper : UIResponder <UIApplicationDelegate>
|
|
14
|
+
|
|
15
|
+
@property (nonatomic, strong, readonly) EXReactDelegateWrapper *reactDelegate;
|
|
16
|
+
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
NS_ASSUME_NONNULL_END
|