expo-modules-core 2.2.1 → 2.2.2
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 +6 -0
- package/android/build.gradle +2 -2
- package/ios/Api/Factories/ViewFactories.swift +7 -0
- package/ios/Core/DynamicTypes/DynamicSwiftUIViewType.swift +59 -0
- package/ios/Core/Exceptions/CommonExceptions.swift +5 -0
- package/ios/Core/Views/SwiftUI/SwiftUIHostingView.swift +11 -2
- package/ios/Core/Views/SwiftUI/SwiftUIViewDefinition.swift +10 -1
- package/ios/Core/Views/SwiftUI/SwiftUIViewDefinitionBuilder.swift +36 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 2.2.2 — 2025-02-14
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- [iOS] Support async functions by SwiftUI views ([#34853](https://github.com/expo/expo/pull/34853) by [@jakex7](https://github.com/jakex7))
|
|
18
|
+
|
|
13
19
|
## 2.2.1 — 2025-02-06
|
|
14
20
|
|
|
15
21
|
_This version does not introduce any user-facing changes._
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
|
3
3
|
apply plugin: 'com.android.library'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '2.2.
|
|
6
|
+
version = '2.2.2'
|
|
7
7
|
|
|
8
8
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
9
9
|
apply from: expoModulesCorePlugin
|
|
@@ -86,7 +86,7 @@ android {
|
|
|
86
86
|
defaultConfig {
|
|
87
87
|
consumerProguardFiles 'proguard-rules.pro'
|
|
88
88
|
versionCode 1
|
|
89
|
-
versionName "2.2.
|
|
89
|
+
versionName "2.2.2"
|
|
90
90
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
|
|
91
91
|
|
|
92
92
|
testInstrumentationRunner "expo.modules.TestRunner"
|
|
@@ -19,6 +19,13 @@ public func View<Props: ExpoSwiftUI.ViewProps, ViewType: ExpoSwiftUI.View<Props>
|
|
|
19
19
|
return ExpoSwiftUI.ViewDefinition(ViewType.self)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
public func View<Props: ExpoSwiftUI.ViewProps, ViewType: ExpoSwiftUI.View<Props>>(
|
|
23
|
+
_ viewType: ViewType.Type,
|
|
24
|
+
@ExpoSwiftUI.ViewDefinitionBuilder<ViewType> _ elements: @escaping () -> [AnyViewDefinitionElement]
|
|
25
|
+
) -> ExpoSwiftUI.ViewDefinition<Props, ViewType> {
|
|
26
|
+
return ExpoSwiftUI.ViewDefinition(ViewType.self, elements: elements())
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
// MARK: Props
|
|
23
30
|
|
|
24
31
|
/**
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
internal struct DynamicSwiftUIViewType<ViewType: ExpoSwiftUIView>: AnyDynamicType {
|
|
4
|
+
let innerType: ViewType.Type
|
|
5
|
+
|
|
6
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
7
|
+
return innerType == InnerType.self
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
11
|
+
if let viewType = type as? Self {
|
|
12
|
+
return viewType.innerType == innerType
|
|
13
|
+
}
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Casts from the React component instance to the view tag (`Int`).
|
|
19
|
+
*/
|
|
20
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
21
|
+
guard let viewTag = findViewTag(jsValue) else {
|
|
22
|
+
throw InvalidViewTagException()
|
|
23
|
+
}
|
|
24
|
+
return viewTag
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
Converts a value of type `Int` to a native view with that tag in the given app context.
|
|
29
|
+
*/
|
|
30
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
31
|
+
guard let viewTag = value as? Int else {
|
|
32
|
+
throw InvalidViewTagException()
|
|
33
|
+
}
|
|
34
|
+
guard Thread.isMainThread else {
|
|
35
|
+
throw NonMainThreadException()
|
|
36
|
+
}
|
|
37
|
+
guard let view = appContext.findView(withTag: viewTag, ofType: AnyExpoSwiftUIHostingView.self) else {
|
|
38
|
+
throw Exceptions.SwiftUIViewNotFound((tag: viewTag, type: innerType.self))
|
|
39
|
+
}
|
|
40
|
+
return view.getContentView()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var description: String {
|
|
44
|
+
return "View<\(innerType)>"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private func findViewTag(_ value: JavaScriptValue) -> Int? {
|
|
49
|
+
if value.isNumber() {
|
|
50
|
+
return value.getInt()
|
|
51
|
+
}
|
|
52
|
+
if value.isObject() {
|
|
53
|
+
let nativeTag = value.getObject().getProperty("nativeTag")
|
|
54
|
+
if nativeTag.isNumber() {
|
|
55
|
+
return nativeTag.getInt()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return nil
|
|
59
|
+
}
|
|
@@ -39,6 +39,11 @@ public struct Exceptions {
|
|
|
39
39
|
"Unable to find the '\(param.type)' view with tag '\(param.tag)'"
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
public final class SwiftUIViewNotFound<ViewType: ExpoSwiftUIView>: GenericException<(tag: Int, type: ViewType.Type)> {
|
|
43
|
+
override public var reason: String {
|
|
44
|
+
"Unable to find the '\(param.type)' view with tag '\(param.tag)'"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
42
47
|
|
|
43
48
|
/**
|
|
44
49
|
An exception to throw when there is no module implementing the `EXFileSystemInterface` interface.
|
|
@@ -7,6 +7,7 @@ import SwiftUI
|
|
|
7
7
|
*/
|
|
8
8
|
internal protocol AnyExpoSwiftUIHostingView {
|
|
9
9
|
func updateProps(_ rawProps: [String: Any])
|
|
10
|
+
func getContentView() -> any ExpoSwiftUI.View
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
extension ExpoSwiftUI {
|
|
@@ -21,6 +22,7 @@ extension ExpoSwiftUI {
|
|
|
21
22
|
It's an environment object that is observed by the content view.
|
|
22
23
|
*/
|
|
23
24
|
private let props: Props
|
|
25
|
+
private let contentView: any ExpoSwiftUI.View
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
View controller that embeds the content view into the UIKit view hierarchy.
|
|
@@ -31,8 +33,8 @@ extension ExpoSwiftUI {
|
|
|
31
33
|
Initializes a SwiftUI hosting view with the given SwiftUI view type.
|
|
32
34
|
*/
|
|
33
35
|
init(viewType: ContentView.Type, props: Props, appContext: AppContext) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
self.contentView = ContentView()
|
|
37
|
+
let rootView = AnyView(contentView.environmentObject(props))
|
|
36
38
|
self.props = props
|
|
37
39
|
self.hostingController = UIHostingController(rootView: rootView)
|
|
38
40
|
|
|
@@ -67,6 +69,13 @@ extension ExpoSwiftUI {
|
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
/**
|
|
73
|
+
Returns inner SwiftUI view.
|
|
74
|
+
*/
|
|
75
|
+
public func getContentView() -> any ExpoSwiftUI.View {
|
|
76
|
+
return contentView
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
/**
|
|
71
80
|
Returns a bool value whether the view supports prop with the given name.
|
|
72
81
|
*/
|
|
@@ -6,10 +6,11 @@ import Combine
|
|
|
6
6
|
/**
|
|
7
7
|
A protocol for SwiftUI views that need to access props.
|
|
8
8
|
*/
|
|
9
|
-
public protocol ExpoSwiftUIView<Props>: SwiftUI.View {
|
|
9
|
+
public protocol ExpoSwiftUIView<Props>: SwiftUI.View, AnyArgument {
|
|
10
10
|
associatedtype Props: ExpoSwiftUI.ViewProps
|
|
11
11
|
|
|
12
12
|
var props: Props { get }
|
|
13
|
+
static func getDynamicType() -> AnyDynamicType
|
|
13
14
|
|
|
14
15
|
init()
|
|
15
16
|
}
|
|
@@ -23,6 +24,10 @@ public extension ExpoSwiftUIView {
|
|
|
23
24
|
ForEach(props.children ?? []) { $0 }
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
static func getDynamicType() -> AnyDynamicType {
|
|
29
|
+
return DynamicSwiftUIViewType(innerType: Self.self)
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
extension ExpoSwiftUI {
|
|
@@ -36,6 +41,10 @@ extension ExpoSwiftUI {
|
|
|
36
41
|
super.init(HostingView<Props, ViewType>.self, elements: [])
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
init(_ viewType: ViewType.Type, elements: [AnyViewDefinitionElement]) {
|
|
45
|
+
super.init(HostingView<Props, ViewType>.self, elements: elements)
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
public override func createView(appContext: AppContext) -> UIView? {
|
|
40
49
|
let props = Props()
|
|
41
50
|
return HostingView(viewType: ViewType.self, props: props, appContext: appContext)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
extension ExpoSwiftUI {
|
|
4
|
+
/**
|
|
5
|
+
A result builder for the view elements such as prop setters or view events.
|
|
6
|
+
*/
|
|
7
|
+
@resultBuilder
|
|
8
|
+
public struct ViewDefinitionBuilder<ViewType: ExpoSwiftUI.View> {
|
|
9
|
+
public static func buildBlock(_ elements: AnyViewDefinitionElement...) -> [AnyViewDefinitionElement] {
|
|
10
|
+
return elements
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
Accepts functions as a view definition elements.
|
|
15
|
+
*/
|
|
16
|
+
public static func buildExpression<ElementType: ViewDefinitionFunctionElement>(
|
|
17
|
+
_ element: ElementType
|
|
18
|
+
) -> AnyViewDefinitionElement {
|
|
19
|
+
return element
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
Accepts functions that take the owner as a view definition elements.
|
|
24
|
+
*/
|
|
25
|
+
public static func buildExpression<ElementType: ViewDefinitionFunctionElement>(
|
|
26
|
+
_ element: ElementType
|
|
27
|
+
) -> AnyViewDefinitionElement where ElementType.ViewType == ViewType {
|
|
28
|
+
// Enforce async functions to run on the main queue
|
|
29
|
+
if var function = element as? AnyAsyncFunctionDefinition {
|
|
30
|
+
function.runOnQueue(.main)
|
|
31
|
+
function.takesOwner = true
|
|
32
|
+
}
|
|
33
|
+
return element
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@testing-library/react-native": "^12.5.2",
|
|
45
|
-
"expo-module-scripts": "^4.0.
|
|
45
|
+
"expo-module-scripts": "^4.0.4"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "7080126694798ca950d5dc3ef33483a17fa401bb"
|
|
48
48
|
}
|