expo-modules-core 1.5.7 → 1.5.8
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 +12 -4
- package/android/build.gradle +4 -2
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +24 -21
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +57 -49
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +30 -27
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/tracing/ExpoTrace.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/views/ErrorView.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +0 -28
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +47 -8
- package/ios/AppDelegates/ExpoAppDelegate.swift +43 -2
- package/package.json +2 -2
- package/android/src/main/java/expo/modules/kotlin/views/ErrorViewGroup.kt +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -10,13 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 1.5.8 — 2023-07-23
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fork `uuid@3.4.0` and move into `expo-modules-core`. Remove the original dependency. ([#23249](https://github.com/expo/expo/pull/23249) by [@alanhughes](https://github.com/alanjhughes))
|
|
18
|
+
- Fixed the `ErrorViewGroup` cannot be cast to module view class exception on Android. ([#23651](https://github.com/expo/expo/pull/23651) by [@lukmccall](https://github.com/lukmccall))
|
|
19
|
+
- [iOS] Fix allowed orientations set in `Info.plist` being ignored when no delegates requested a different orientation. ([#23593](https://github.com/expo/expo/pull/23593) by [@behenate](https://github.com/behenate))
|
|
20
|
+
|
|
13
21
|
## 1.5.7 — 2023-07-12
|
|
14
22
|
|
|
15
23
|
### 🐛 Bug fixes
|
|
16
24
|
|
|
17
25
|
- Fixed regressions and crashes in the dev client introduced by [#23405](https://github.com/expo/expo/pull/23405). ([#23491](https://github.com/expo/expo/pull/23491) by [@kudo](https://github.com/kudo))
|
|
18
26
|
|
|
19
|
-
## 1.5.6
|
|
27
|
+
## 1.5.6 - 2023-07-10
|
|
20
28
|
|
|
21
29
|
### 🐛 Bug fixes
|
|
22
30
|
|
|
@@ -24,14 +32,14 @@
|
|
|
24
32
|
- Fixed `SoLoader` does not work on Android. ([#23415](https://github.com/expo/expo/pull/23415) by [@kudo](https://github.com/kudo))
|
|
25
33
|
- Fixed slower boot time on Android. ([#23345](https://github.com/expo/expo/pull/23345) by [@lukmccall](https://github.com/lukmccall))
|
|
26
34
|
|
|
27
|
-
## 1.5.5
|
|
35
|
+
## 1.5.5 - 2023-07-07
|
|
28
36
|
|
|
29
37
|
### 🐛 Bug fixes
|
|
30
38
|
|
|
31
39
|
- Improved the OkHttp network inspector stability on Android. ([#23350](https://github.com/expo/expo/pull/23350) by [@kudo](https://github.com/kudo))
|
|
32
|
-
- [iOS] Fix conversion to `URL` type that failed despite receiving a string that contained a valid URL. ([#23331](https://github.com/expo/expo/pull/23331) by [@alanhughes](https://github.com/alanjhughes))
|
|
40
|
+
- [iOS] Fix conversion to `URL` type that failed despite receiving a string that contained a valid URL. ([#23331](https://github.com/expo/expo/pull/23331) by [@alanhughes](https://github.com/alanjhughes)) ([#23331](https://github.com/expo/expo/pull/23331) by [@alanjhughes](https://github.com/alanjhughes))
|
|
33
41
|
|
|
34
|
-
## 1.5.4
|
|
42
|
+
## 1.5.4 - 2023-07-04
|
|
35
43
|
|
|
36
44
|
### 🐛 Bug fixes
|
|
37
45
|
|
package/android/build.gradle
CHANGED
|
@@ -6,7 +6,7 @@ apply plugin: 'maven-publish'
|
|
|
6
6
|
apply plugin: "de.undercouch.download"
|
|
7
7
|
|
|
8
8
|
group = 'host.exp.exponent'
|
|
9
|
-
version = '1.5.
|
|
9
|
+
version = '1.5.8'
|
|
10
10
|
|
|
11
11
|
buildscript {
|
|
12
12
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -160,7 +160,7 @@ android {
|
|
|
160
160
|
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
161
161
|
consumerProguardFiles 'proguard-rules.pro'
|
|
162
162
|
versionCode 1
|
|
163
|
-
versionName "1.5.
|
|
163
|
+
versionName "1.5.8"
|
|
164
164
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
|
|
165
165
|
|
|
166
166
|
testInstrumentationRunner "expo.modules.TestRunner"
|
|
@@ -279,6 +279,8 @@ dependencies {
|
|
|
279
279
|
implementation "androidx.activity:activity-ktx:1.7.1" // androidx.appcompat:appcompat:1.4.1 depends on version 1.2.3, so we enforce higher one here
|
|
280
280
|
implementation "androidx.fragment:fragment-ktx:1.5.7" // androidx.appcomapt:appcompat:1.4.1 depends on version 1.3.4, so we enforce higher one here
|
|
281
281
|
|
|
282
|
+
implementation("androidx.tracing:tracing-ktx:1.1.0")
|
|
283
|
+
|
|
282
284
|
//noinspection GradleDynamicVersion
|
|
283
285
|
implementation 'com.facebook.react:react-native:+'
|
|
284
286
|
|
|
@@ -40,6 +40,7 @@ import expo.modules.kotlin.jni.JSIInteropModuleRegistry
|
|
|
40
40
|
import expo.modules.kotlin.modules.Module
|
|
41
41
|
import expo.modules.kotlin.providers.CurrentActivityProvider
|
|
42
42
|
import expo.modules.kotlin.sharedobjects.SharedObjectRegistry
|
|
43
|
+
import expo.modules.kotlin.tracing.trace
|
|
43
44
|
import kotlinx.coroutines.CoroutineName
|
|
44
45
|
import kotlinx.coroutines.CoroutineScope
|
|
45
46
|
import kotlinx.coroutines.Dispatchers
|
|
@@ -120,26 +121,28 @@ class AppContext(
|
|
|
120
121
|
* Initializes a JSI part of the module registry.
|
|
121
122
|
* It will be a NOOP if the remote debugging was activated.
|
|
122
123
|
*/
|
|
123
|
-
fun installJSIInterop() = synchronized
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
124
|
+
fun installJSIInterop() = synchronized(this) {
|
|
125
|
+
trace("AppContext.installJSIInterop") {
|
|
126
|
+
try {
|
|
127
|
+
jsiInterop = JSIInteropModuleRegistry(this)
|
|
128
|
+
val reactContext = reactContextHolder.get() ?: return@trace
|
|
129
|
+
val jsContextProvider = legacyModule<JavaScriptContextProvider>() ?: return@trace
|
|
130
|
+
val jsContextHolder = jsContextProvider.javaScriptContextRef
|
|
131
|
+
val catalystInstance = reactContext.catalystInstance ?: return@trace
|
|
132
|
+
jsContextHolder
|
|
133
|
+
.takeIf { it != 0L }
|
|
134
|
+
?.let {
|
|
135
|
+
jsiInterop.installJSI(
|
|
136
|
+
it,
|
|
137
|
+
jniDeallocator,
|
|
138
|
+
jsContextProvider.jsCallInvokerHolder,
|
|
139
|
+
catalystInstance.nativeCallInvokerHolder as CallInvokerHolderImpl
|
|
140
|
+
)
|
|
141
|
+
logger.info("✅ JSI interop was installed")
|
|
142
|
+
}
|
|
143
|
+
} catch (e: Throwable) {
|
|
144
|
+
logger.error("❌ Cannot install JSI interop: $e", e)
|
|
145
|
+
}
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
148
|
|
|
@@ -271,7 +274,7 @@ class AppContext(
|
|
|
271
274
|
internal val errorManager: ErrorManagerModule?
|
|
272
275
|
get() = registry.getModule()
|
|
273
276
|
|
|
274
|
-
internal fun onDestroy() {
|
|
277
|
+
internal fun onDestroy() = trace("AppContext.onDestroy") {
|
|
275
278
|
reactContextHolder.get()?.removeLifecycleEventListener(reactLifecycleDelegate)
|
|
276
279
|
registry.post(EventName.MODULE_DESTROY)
|
|
277
280
|
registry.cleanUp()
|
|
@@ -7,6 +7,7 @@ import expo.modules.adapters.react.NativeModulesProxy
|
|
|
7
7
|
import expo.modules.kotlin.defaultmodules.NativeModulesProxyModuleName
|
|
8
8
|
import expo.modules.kotlin.exception.CodedException
|
|
9
9
|
import expo.modules.kotlin.exception.UnexpectedException
|
|
10
|
+
import expo.modules.kotlin.tracing.trace
|
|
10
11
|
import expo.modules.kotlin.views.GroupViewManagerWrapper
|
|
11
12
|
import expo.modules.kotlin.views.SimpleViewManagerWrapper
|
|
12
13
|
import expo.modules.kotlin.views.ViewManagerWrapperDelegate
|
|
@@ -42,55 +43,61 @@ class KotlinInteropModuleRegistry(
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
fun exportedModulesConstants(): Map<ModuleName, ModuleConstants>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
fun exportedModulesConstants(): Map<ModuleName, ModuleConstants> =
|
|
47
|
+
trace("KotlinInteropModuleRegistry.exportedModulesConstants") {
|
|
48
|
+
registry
|
|
49
|
+
// prevent infinite recursion - exclude NativeProxyModule constants
|
|
50
|
+
.filter { holder -> holder.name != NativeModulesProxyModuleName }
|
|
51
|
+
.associate { holder ->
|
|
52
|
+
holder.name to holder.definition.constantsProvider()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun exportMethods(exportKey: (String, List<ModuleMethodInfo>) -> Unit = { _, _ -> }): Map<ModuleName, List<ModuleMethodInfo>> =
|
|
57
|
+
trace("KotlinInteropModuleRegistry.exportMethods") {
|
|
58
|
+
registry.associate { holder ->
|
|
59
|
+
val methodsInfo = holder
|
|
60
|
+
.definition
|
|
61
|
+
.asyncFunctions
|
|
62
|
+
.map { (name, method) ->
|
|
63
|
+
mapOf(
|
|
64
|
+
"name" to name,
|
|
65
|
+
"argumentsCount" to method.argsCount
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
exportKey(holder.name, methodsInfo)
|
|
69
|
+
holder.name to methodsInfo
|
|
51
70
|
}
|
|
52
|
-
|
|
71
|
+
}
|
|
53
72
|
|
|
54
|
-
fun
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.definition
|
|
58
|
-
.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
fun exportViewManagers(): List<ViewManager<*, *>> =
|
|
74
|
+
trace("KotlinInteropModuleRegistry.exportViewManagers") {
|
|
75
|
+
registry
|
|
76
|
+
.filter { it.definition.viewManagerDefinition != null }
|
|
77
|
+
.map {
|
|
78
|
+
val wrapperDelegate = ViewManagerWrapperDelegate(it)
|
|
79
|
+
when (it.definition.viewManagerDefinition!!.getViewManagerType()) {
|
|
80
|
+
expo.modules.core.ViewManager.ViewManagerType.SIMPLE -> SimpleViewManagerWrapper(wrapperDelegate)
|
|
81
|
+
expo.modules.core.ViewManager.ViewManagerType.GROUP -> GroupViewManagerWrapper(wrapperDelegate)
|
|
82
|
+
}
|
|
64
83
|
}
|
|
65
|
-
exportKey(holder.name, methodsInfo)
|
|
66
|
-
holder.name to methodsInfo
|
|
67
84
|
}
|
|
68
|
-
}
|
|
69
85
|
|
|
70
|
-
fun
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
fun viewManagersMetadata(): Map<String, Map<String, Any>> =
|
|
87
|
+
trace("KotlinInteropModuleRegistry.viewManagersMetadata") {
|
|
88
|
+
registry
|
|
89
|
+
.filter { it.definition.viewManagerDefinition != null }
|
|
90
|
+
.associate { holder ->
|
|
91
|
+
holder.name to mapOf(
|
|
92
|
+
"propsNames" to (holder.definition.viewManagerDefinition?.propsNames ?: emptyList())
|
|
93
|
+
)
|
|
78
94
|
}
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
fun viewManagersMetadata(): Map<String, Map<String, Any>> {
|
|
83
|
-
return registry
|
|
84
|
-
.filter { it.definition.viewManagerDefinition != null }
|
|
85
|
-
.associate { holder ->
|
|
86
|
-
holder.name to mapOf(
|
|
87
|
-
"propsNames" to (holder.definition.viewManagerDefinition?.propsNames ?: emptyList())
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
95
|
+
}
|
|
91
96
|
|
|
92
97
|
fun extractViewManagersDelegateHolders(viewManagers: List<ViewManager<*, *>>): List<ViewWrapperDelegateHolder> =
|
|
93
|
-
|
|
98
|
+
trace("KotlinInteropModuleRegistry.extractViewManagersDelegateHolders") {
|
|
99
|
+
viewManagers.filterIsInstance<ViewWrapperDelegateHolder>()
|
|
100
|
+
}
|
|
94
101
|
|
|
95
102
|
/**
|
|
96
103
|
* Since React Native v0.55, {@link com.facebook.react.ReactPackage#createViewManagers(ReactApplicationContext)}
|
|
@@ -100,15 +107,16 @@ class KotlinInteropModuleRegistry(
|
|
|
100
107
|
* the instance that was bound with the prop method won't be the same as the instance returned by module registry.
|
|
101
108
|
* To fix that we need to update all modules holder in exported view managers.
|
|
102
109
|
*/
|
|
103
|
-
fun updateModuleHoldersInViewManagers(viewWrapperHolders: List<ViewWrapperDelegateHolder>)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
fun updateModuleHoldersInViewManagers(viewWrapperHolders: List<ViewWrapperDelegateHolder>) =
|
|
111
|
+
trace("KotlinInteropModuleRegistry.updateModuleHoldersInViewManagers") {
|
|
112
|
+
viewWrapperHolders
|
|
113
|
+
.map { it.viewWrapperDelegate }
|
|
114
|
+
.forEach { holderWrapper ->
|
|
115
|
+
holderWrapper.moduleHolder = requireNotNull(registry.getModuleHolder(holderWrapper.moduleHolder.name)) {
|
|
116
|
+
"Cannot update the module holder for ${holderWrapper.moduleHolder.name}."
|
|
117
|
+
}
|
|
109
118
|
}
|
|
110
|
-
|
|
111
|
-
}
|
|
119
|
+
}
|
|
112
120
|
|
|
113
121
|
fun onDestroy() {
|
|
114
122
|
appContext.onDestroy()
|
|
@@ -11,6 +11,7 @@ import expo.modules.kotlin.exception.MethodNotFoundException
|
|
|
11
11
|
import expo.modules.kotlin.exception.exceptionDecorator
|
|
12
12
|
import expo.modules.kotlin.jni.JavaScriptModuleObject
|
|
13
13
|
import expo.modules.kotlin.modules.Module
|
|
14
|
+
import expo.modules.kotlin.tracing.trace
|
|
14
15
|
import kotlinx.coroutines.launch
|
|
15
16
|
import kotlin.reflect.KClass
|
|
16
17
|
|
|
@@ -23,38 +24,40 @@ class ModuleHolder(val module: Module) {
|
|
|
23
24
|
* Cached instance of HybridObject used by CPP to interact with underlying [expo.modules.kotlin.modules.Module] object.
|
|
24
25
|
*/
|
|
25
26
|
val jsObject by lazy {
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
trace("$name.jsObject") {
|
|
28
|
+
val appContext = module.appContext
|
|
29
|
+
val jniDeallocator = appContext.jniDeallocator
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
JavaScriptModuleObject(jniDeallocator, name).apply {
|
|
32
|
+
initUsingObjectDefinition(appContext, definition.objectDefinition)
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
val viewFunctions = definition.viewManagerDefinition?.asyncFunctions
|
|
35
|
+
if (viewFunctions?.isNotEmpty() == true) {
|
|
36
|
+
val viewPrototype = JavaScriptModuleObject(jniDeallocator, "${name}_${definition.viewManagerDefinition?.viewType?.name}")
|
|
37
|
+
appContext.jniDeallocator.addReference(viewPrototype)
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
viewFunctions.forEach { function ->
|
|
40
|
+
function.attachToJSObject(appContext, viewPrototype)
|
|
41
|
+
}
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
registerViewPrototype(viewPrototype)
|
|
44
|
+
}
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
definition.classData.forEach { clazz ->
|
|
47
|
+
val clazzModuleObject = JavaScriptModuleObject(jniDeallocator, clazz.name)
|
|
48
|
+
.initUsingObjectDefinition(module.appContext, clazz.objectDefinition)
|
|
49
|
+
appContext.jniDeallocator.addReference(clazzModuleObject)
|
|
50
|
+
|
|
51
|
+
val constructor = clazz.constructor
|
|
52
|
+
registerClass(
|
|
53
|
+
clazz.name,
|
|
54
|
+
clazzModuleObject,
|
|
55
|
+
constructor.takesOwner,
|
|
56
|
+
constructor.argsCount,
|
|
57
|
+
constructor.getCppRequiredTypes().toTypedArray(),
|
|
58
|
+
constructor.getJNIFunctionBody(clazz.name, appContext)
|
|
59
|
+
)
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
}
|
|
@@ -2,6 +2,7 @@ package expo.modules.kotlin
|
|
|
2
2
|
|
|
3
3
|
import expo.modules.kotlin.events.EventName
|
|
4
4
|
import expo.modules.kotlin.modules.Module
|
|
5
|
+
import expo.modules.kotlin.tracing.trace
|
|
5
6
|
import kotlinx.coroutines.CoroutineName
|
|
6
7
|
import kotlinx.coroutines.CoroutineScope
|
|
7
8
|
import kotlinx.coroutines.Dispatchers
|
|
@@ -16,7 +17,7 @@ class ModuleRegistry(
|
|
|
16
17
|
@PublishedApi
|
|
17
18
|
internal val registry = mutableMapOf<String, ModuleHolder>()
|
|
18
19
|
|
|
19
|
-
fun register(module: Module) {
|
|
20
|
+
fun register(module: Module) = trace("ModuleRegistry.register(${module.javaClass})") {
|
|
20
21
|
module._appContext = requireNotNull(appContext.get()) { "Cannot create a module for invalid app context." }
|
|
21
22
|
|
|
22
23
|
val holder = ModuleHolder(module)
|
|
@@ -3,6 +3,7 @@ package expo.modules.kotlin.modules
|
|
|
3
3
|
import android.os.Bundle
|
|
4
4
|
import expo.modules.kotlin.AppContext
|
|
5
5
|
import expo.modules.kotlin.providers.AppContextProvider
|
|
6
|
+
import expo.modules.kotlin.tracing.trace
|
|
6
7
|
import kotlinx.coroutines.CoroutineScope
|
|
7
8
|
|
|
8
9
|
abstract class Module : AppContextProvider {
|
|
@@ -35,6 +36,6 @@ abstract class Module : AppContextProvider {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
@Suppress("FunctionName")
|
|
38
|
-
inline fun Module.ModuleDefinition(block: ModuleDefinitionBuilder.() -> Unit): ModuleDefinitionData {
|
|
39
|
-
return ModuleDefinitionBuilder(this).also(block).buildModule()
|
|
39
|
+
inline fun Module.ModuleDefinition(crossinline block: ModuleDefinitionBuilder.() -> Unit): ModuleDefinitionData {
|
|
40
|
+
return trace("${this.javaClass}.ModuleDefinition") { ModuleDefinitionBuilder(this).also(block).buildModule() }
|
|
40
41
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package expo.modules.kotlin.tracing
|
|
2
|
+
|
|
3
|
+
import androidx.tracing.Trace
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wrap the specified [block] in calls to [Trace.beginSection] (with expo tag and the supplied [blockName])
|
|
7
|
+
* and [Trace.endSection].
|
|
8
|
+
*
|
|
9
|
+
* @param blockName A name of the code section to appear in the trace.
|
|
10
|
+
* @param block A block of code which is being traced.
|
|
11
|
+
*/
|
|
12
|
+
inline fun <T> trace(blockName: String, crossinline block: () -> T) =
|
|
13
|
+
androidx.tracing.trace("[ExpoModulesCore] $blockName", block)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package expo.modules.kotlin.views
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.View
|
|
5
|
+
import android.view.ViewGroup
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A NOOP view, which is used when an error occurs.
|
|
9
|
+
*/
|
|
10
|
+
open class ErrorView(context: Context) : View(context)
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A NOOP view group, which is used when an error occurs.
|
|
14
|
+
*/
|
|
15
|
+
class ErrorGroupView(context: Context) : ViewGroup(context) {
|
|
16
|
+
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) = Unit
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fun View.isErrorView(): Boolean {
|
|
20
|
+
return this is ErrorView || this is ErrorGroupView
|
|
21
|
+
}
|
|
@@ -336,9 +336,9 @@ class ViewDefinitionBuilder<T : View>(
|
|
|
336
336
|
)
|
|
337
337
|
|
|
338
338
|
return if (ViewGroup::class.java.isAssignableFrom(viewClass.java)) {
|
|
339
|
-
|
|
339
|
+
ErrorGroupView(context)
|
|
340
340
|
} else {
|
|
341
|
-
|
|
341
|
+
ErrorView(context)
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
344
|
|
|
@@ -4,16 +4,11 @@ import android.content.Context
|
|
|
4
4
|
import android.view.View
|
|
5
5
|
import android.view.ViewGroup
|
|
6
6
|
import com.facebook.react.bridge.ReactContext
|
|
7
|
-
import com.facebook.react.bridge.ReadableMap
|
|
8
7
|
import expo.modules.adapters.react.NativeModulesProxy
|
|
9
8
|
import expo.modules.core.ViewManager
|
|
10
9
|
import expo.modules.kotlin.AppContext
|
|
11
|
-
import expo.modules.kotlin.DynamicNull
|
|
12
10
|
import expo.modules.kotlin.exception.CodedException
|
|
13
|
-
import expo.modules.kotlin.exception.toCodedException
|
|
14
11
|
import expo.modules.kotlin.functions.BaseAsyncFunctionComponent
|
|
15
|
-
import expo.modules.kotlin.logger
|
|
16
|
-
import expo.modules.kotlin.recycle
|
|
17
12
|
|
|
18
13
|
class ViewManagerDefinition(
|
|
19
14
|
private val viewFactory: (Context, AppContext) -> View,
|
|
@@ -38,29 +33,6 @@ class ViewManagerDefinition(
|
|
|
38
33
|
}
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
fun setProps(propsToSet: ReadableMap, onView: View) {
|
|
42
|
-
props.forEach { (name, propDelegate) ->
|
|
43
|
-
try {
|
|
44
|
-
if (propsToSet.hasKey(name)) {
|
|
45
|
-
propsToSet
|
|
46
|
-
.getDynamic(name)
|
|
47
|
-
.recycle {
|
|
48
|
-
propDelegate.set(this, onView)
|
|
49
|
-
}
|
|
50
|
-
} else if (propDelegate.isNullable) {
|
|
51
|
-
propDelegate.set(DynamicNull, onView)
|
|
52
|
-
}
|
|
53
|
-
} catch (exception: Throwable) {
|
|
54
|
-
logger.error("❌ Cannot set the '$name' prop on the '${viewType.simpleName}'", exception)
|
|
55
|
-
|
|
56
|
-
handleException(
|
|
57
|
-
onView,
|
|
58
|
-
exception.toCodedException()
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
36
|
fun handleException(view: View, exception: CodedException) {
|
|
65
37
|
val reactContext = (view.context as? ReactContext) ?: return
|
|
66
38
|
val nativeModulesProxy = reactContext
|
|
@@ -7,9 +7,9 @@ import com.facebook.react.common.MapBuilder
|
|
|
7
7
|
import expo.modules.core.utilities.ifNull
|
|
8
8
|
import expo.modules.kotlin.ModuleHolder
|
|
9
9
|
import expo.modules.kotlin.events.normalizeEventName
|
|
10
|
-
import expo.modules.kotlin.exception.CodedException
|
|
11
10
|
import expo.modules.kotlin.exception.OnViewDidUpdatePropsException
|
|
12
11
|
import expo.modules.kotlin.exception.exceptionDecorator
|
|
12
|
+
import expo.modules.kotlin.exception.toCodedException
|
|
13
13
|
import expo.modules.kotlin.logger
|
|
14
14
|
import expo.modules.kotlin.viewevent.ViewEventDelegate
|
|
15
15
|
import kotlin.reflect.full.declaredMemberProperties
|
|
@@ -42,9 +42,16 @@ class ViewManagerWrapperDelegate(internal var moduleHolder: ModuleHolder) {
|
|
|
42
42
|
exceptionDecorator({ OnViewDidUpdatePropsException(view.javaClass.kotlin, it) }) {
|
|
43
43
|
it.invoke(view)
|
|
44
44
|
}
|
|
45
|
-
} catch (exception:
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
} catch (exception: Throwable) {
|
|
46
|
+
// The view wasn't constructed correctly, so errors are expected.
|
|
47
|
+
// We can ignore them.
|
|
48
|
+
if (view.isErrorView()) {
|
|
49
|
+
return@let
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
val codedException = exception.toCodedException()
|
|
53
|
+
logger.error("❌ Error occurred when invoking 'onViewDidUpdateProps' on '${view.javaClass.simpleName}'", codedException)
|
|
54
|
+
definition.handleException(view, codedException)
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
57
|
}
|
|
@@ -65,15 +72,47 @@ class ViewManagerWrapperDelegate(internal var moduleHolder: ModuleHolder) {
|
|
|
65
72
|
while (iterator.hasNextKey()) {
|
|
66
73
|
val key = iterator.nextKey()
|
|
67
74
|
expoProps[key]?.let { expoProp ->
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
try {
|
|
76
|
+
expoProp.set(propsMap.getDynamic(key), view)
|
|
77
|
+
} catch (exception: Throwable) {
|
|
78
|
+
// The view wasn't constructed correctly, so errors are expected.
|
|
79
|
+
// We can ignore them.
|
|
80
|
+
if (view.isErrorView()) {
|
|
81
|
+
return@let
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
val codedException = exception.toCodedException()
|
|
85
|
+
logger.error("❌ Cannot set the '$name' prop on the '$view'", codedException)
|
|
86
|
+
definition.handleException(
|
|
87
|
+
view,
|
|
88
|
+
codedException
|
|
89
|
+
)
|
|
90
|
+
} finally {
|
|
91
|
+
handledProps.add(key)
|
|
92
|
+
}
|
|
70
93
|
}
|
|
71
94
|
}
|
|
72
95
|
return handledProps
|
|
73
96
|
}
|
|
74
97
|
|
|
75
|
-
fun onDestroy(view: View)
|
|
76
|
-
|
|
98
|
+
fun onDestroy(view: View) {
|
|
99
|
+
try {
|
|
100
|
+
definition.onViewDestroys?.invoke(view)
|
|
101
|
+
} catch (exception: Throwable) {
|
|
102
|
+
// The view wasn't constructed correctly, so errors are expected.
|
|
103
|
+
// We can ignore them.
|
|
104
|
+
if (view.isErrorView()) {
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
val codedException = exception.toCodedException()
|
|
109
|
+
logger.error("❌ '$view' wasn't able to destroy itself", codedException)
|
|
110
|
+
definition.handleException(
|
|
111
|
+
view,
|
|
112
|
+
codedException
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
77
116
|
|
|
78
117
|
fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
|
|
79
118
|
val builder = MapBuilder.builder<String, Any>()
|
|
@@ -290,11 +290,27 @@ open class ExpoAppDelegate: UIResponder, UIApplicationDelegate {
|
|
|
290
290
|
|
|
291
291
|
// MARK: - Managing Interface Geometry
|
|
292
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Sets allowed orientations for the application. It will use the values from `Info.plist`as the orientation mask unless a subscriber requested
|
|
295
|
+
* a different orientation.
|
|
296
|
+
*/
|
|
293
297
|
public func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
|
|
298
|
+
let deviceOrientationMask = allowedOrientations(for: UIDevice.current.userInterfaceIdiom)
|
|
299
|
+
let universalOrientationMask = allowedOrientations(for: .unspecified)
|
|
300
|
+
let infoPlistOrientations = deviceOrientationMask.isEmpty ? universalOrientationMask : deviceOrientationMask
|
|
301
|
+
|
|
302
|
+
let parsedSubscribers = subscribers.filter {
|
|
303
|
+
$0.responds(to: #selector(application(_:supportedInterfaceOrientationsFor:)))
|
|
304
|
+
}
|
|
305
|
+
|
|
294
306
|
// We want to create an intersection of all orientations set by subscribers.
|
|
295
|
-
|
|
296
|
-
|
|
307
|
+
let subscribersMask: UIInterfaceOrientationMask = parsedSubscribers.reduce(.all) { result, subscriber in
|
|
308
|
+
guard let requestedOrientation = subscriber.application?(application, supportedInterfaceOrientationsFor: window) else {
|
|
309
|
+
return result
|
|
310
|
+
}
|
|
311
|
+
return requestedOrientation.intersection(result)
|
|
297
312
|
}
|
|
313
|
+
return parsedSubscribers.isEmpty ? infoPlistOrientations : subscribersMask
|
|
298
314
|
}
|
|
299
315
|
|
|
300
316
|
// MARK: - Statics
|
|
@@ -330,3 +346,28 @@ open class ExpoAppDelegate: UIResponder, UIApplicationDelegate {
|
|
|
330
346
|
}
|
|
331
347
|
}
|
|
332
348
|
}
|
|
349
|
+
|
|
350
|
+
private func allowedOrientations(for userInterfaceIdiom: UIUserInterfaceIdiom) -> UIInterfaceOrientationMask {
|
|
351
|
+
// For now only iPad-specific orientations are supported
|
|
352
|
+
let deviceString = userInterfaceIdiom == .pad ? "~pad" : ""
|
|
353
|
+
var mask: UIInterfaceOrientationMask = []
|
|
354
|
+
guard let orientations = Bundle.main.infoDictionary?["UISupportedInterfaceOrientations\(deviceString)"] as? [String] else {
|
|
355
|
+
return mask
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
for orientation in orientations {
|
|
359
|
+
switch orientation {
|
|
360
|
+
case "UIInterfaceOrientationPortrait":
|
|
361
|
+
mask.insert(.portrait)
|
|
362
|
+
case "UIInterfaceOrientationLandscapeLeft":
|
|
363
|
+
mask.insert(.landscapeLeft)
|
|
364
|
+
case "UIInterfaceOrientationLandscapeRight":
|
|
365
|
+
mask.insert(.landscapeRight)
|
|
366
|
+
case "UIInterfaceOrientationPortraitUpsideDown":
|
|
367
|
+
mask.insert(.portraitUpsideDown)
|
|
368
|
+
default:
|
|
369
|
+
break
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return mask
|
|
373
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@testing-library/react-hooks": "^7.0.1",
|
|
43
43
|
"expo-module-scripts": "^3.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "c0d646e9295094bca877513e500d3c9f2e990c42"
|
|
46
46
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
package expo.modules.kotlin.views
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.view.ViewGroup
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A NOOP view group, which is used when an error occurs.
|
|
8
|
-
*/
|
|
9
|
-
class ErrorViewGroup(context: Context) : ViewGroup(context) {
|
|
10
|
-
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) = Unit
|
|
11
|
-
}
|