7
7
8
8
import Foundation
9
9
import JavaScriptCore
10
-
11
- #if SWIFT_PACKAGE
12
10
import PlayerUI
13
- #endif
14
11
15
- public typealias AsyncHookHandler = ( JSValue ) async throws -> AsyncNodeHandlerType
12
+ public typealias AsyncHookHandler = ( JSValue , JSValue ) async throws -> AsyncNodeHandlerType
16
13
17
14
public enum AsyncNodeHandlerType {
18
15
case multiNode( [ ReplacementNode ] )
19
16
case singleNode( ReplacementNode )
17
+ case emptyNode
18
+ }
19
+
20
+ /// Extension for `ReplacementNode` to convert it to a `JSValue` in a given `JSContext`.
21
+ public extension ReplacementNode {
22
+ /// Converts the `ReplacementNode` to a `JSValue` in the provided `JSContext`.
23
+ ///
24
+ /// - Parameter context: The `JSContext` in which the `JSValue` will be created.
25
+ /// - Returns: A `JSValue` representing the `ReplacementNode`, or `nil` if the conversion fails.
26
+ func toJSValue( context: JSContext ) -> JSValue ? {
27
+ switch self {
28
+ case . encodable( let encodable) :
29
+ let encoder = JSONEncoder ( )
30
+ do {
31
+ let res = try encoder. encode ( encodable)
32
+ return context. evaluateScript ( " ( \( String ( data: res, encoding: . utf8) ?? " " ) ) " ) as JSValue
33
+ } catch {
34
+ return nil
35
+ }
36
+ case . concrete( let jsValue) :
37
+ return jsValue
38
+ }
39
+ }
40
+ }
41
+
42
+ /// Extension for `AsyncNodeHandlerType` to convert it to a `JSValue` in a given `JSContext`.
43
+ public extension AsyncNodeHandlerType {
44
+ /// Converts the `AsyncNodeHandlerType` to a `JSValue` in the provided `JSContext`.
45
+ ///
46
+ /// - Parameter context: The `JSContext` in which the `JSValue` will be created.
47
+ /// - Returns: A `JSValue` representing the `AsyncNodeHandlerType`, or `nil` if the conversion fails.
48
+ func handlerTypeToJSValue( context: JSContext ) -> JSValue ? {
49
+ switch self {
50
+ case . multiNode( let replacementNodes) :
51
+ let jsValueArray = replacementNodes. compactMap {
52
+ $0. toJSValue ( context: context)
53
+ }
54
+ return context. objectForKeyedSubscript ( " Array " ) . objectForKeyedSubscript ( " from " ) . call ( withArguments: [ jsValueArray] )
55
+
56
+ case . singleNode( let replacementNode) :
57
+ return replacementNode. toJSValue ( context: context)
58
+
59
+ case . emptyNode:
60
+ return nil
61
+ }
62
+ }
20
63
}
21
64
22
65
/**
@@ -32,8 +75,8 @@ public class AsyncNodePlugin: JSBasePlugin, NativePlugin {
32
75
/**
33
76
Constructs the AsyncNodePlugin
34
77
- Parameters:
35
- - handler: The callback that is used to tap into the core `onAsyncNode` hook
36
- exposed to users of the plugin allowing them to supply the replacement node used in the tap callback
78
+ - handler: The callback that is used to tap into the core `onAsyncNode` hook
79
+ exposed to users of the plugin allowing them to supply the replacement node used in the tap callback
37
80
*/
38
81
public convenience init ( plugins: [ JSBasePlugin ] = [ AsyncNodePluginPlugin ( ) ] , _ handler: @escaping AsyncHookHandler ) {
39
82
@@ -46,53 +89,17 @@ public class AsyncNodePlugin: JSBasePlugin, NativePlugin {
46
89
super. setup ( context: context)
47
90
48
91
if let pluginRef = pluginRef {
49
- self . hooks = AsyncNodeHook ( onAsyncNode: AsyncHook ( baseValue: pluginRef, name: " onAsyncNode " ) )
92
+ self . hooks = AsyncNodeHook ( onAsyncNode: AsyncHook2 ( baseValue: pluginRef, name: " onAsyncNode " ) )
50
93
}
51
94
52
- hooks? . onAsyncNode. tap ( { node in
95
+ hooks? . onAsyncNode. tap ( { node, callback in
53
96
// hook value is the original node
54
97
guard let asyncHookHandler = self . asyncHookHandler else {
55
98
return JSValue ( )
56
99
}
57
100
58
- let replacementNode = try await ( asyncHookHandler) ( node)
59
-
60
- switch replacementNode {
61
- case . multiNode( let replacementNodes) :
62
- let jsValueArray = replacementNodes. compactMap ( { node in
63
- switch node {
64
- case . concrete( let jsValue) :
65
- return jsValue
66
- case . encodable( let encodable) :
67
- let encoder = JSONEncoder ( )
68
- do {
69
- let res = try encoder. encode ( encodable)
70
- return context. evaluateScript ( " ( \( String ( data: res, encoding: . utf8) ?? " " ) ) " ) as JSValue
71
- } catch {
72
- return nil
73
- }
74
- }
75
- } )
76
-
77
- return context. objectForKeyedSubscript ( " Array " ) . objectForKeyedSubscript ( " from " ) . call ( withArguments: [ jsValueArray] )
78
-
79
- case . singleNode( let replacementNode) :
80
- switch replacementNode {
81
-
82
- case . encodable( let encodable) :
83
- let encoder = JSONEncoder ( )
84
- do {
85
- let res = try encoder. encode ( encodable)
86
- return context. evaluateScript ( " ( \( String ( data: res, encoding: . utf8) ?? " " ) ) " ) as JSValue
87
- } catch {
88
- break
89
- }
90
- case . concrete( let jsValue) :
91
- return jsValue
92
- }
93
- }
94
-
95
- return nil
101
+ let replacementNode = try await ( asyncHookHandler) ( node, callback)
102
+ return replacementNode. handlerTypeToJSValue ( context: context) ?? JSValue ( )
96
103
} )
97
104
}
98
105
@@ -102,29 +109,29 @@ public class AsyncNodePlugin: JSBasePlugin, NativePlugin {
102
109
- returns: An array of arguments to construct the plugin
103
110
*/
104
111
override public func getArguments( ) -> [ Any ] {
105
- for plugin in plugins {
106
- plugin. context = self . context
107
- }
112
+ for plugin in plugins {
113
+ plugin. context = self . context
114
+ }
108
115
109
- return [ [ " plugins " : plugins. map { $0. pluginRef } ] ]
110
- }
116
+ return [ [ " plugins " : plugins. map { $0. pluginRef } ] ]
117
+ }
111
118
112
119
override open func getUrlForFile( fileName: String ) -> URL ? {
113
- #if SWIFT_PACKAGE
120
+ #if SWIFT_PACKAGE
114
121
ResourceUtilities . urlForFile ( name: fileName, ext: " js " , bundle: Bundle . module)
115
- #else
122
+ #else
116
123
ResourceUtilities . urlForFile (
117
124
name: fileName,
118
125
ext: " js " ,
119
126
bundle: Bundle ( for: AsyncNodePlugin . self) ,
120
127
pathComponent: " PlayerUIAsyncNodePlugin.bundle "
121
128
)
122
- #endif
129
+ #endif
123
130
}
124
131
}
125
132
126
133
public struct AsyncNodeHook {
127
- public let onAsyncNode : AsyncHook < JSValue >
134
+ public let onAsyncNode : AsyncHook2 < JSValue , JSValue >
128
135
}
129
136
130
137
/**
@@ -165,7 +172,7 @@ public struct AssetPlaceholderNode: Encodable {
165
172
public struct AsyncNode : Codable , Equatable {
166
173
var id : String
167
174
var async : Bool = true
168
-
175
+
169
176
public init ( id: String ) {
170
177
self . id = id
171
178
}
@@ -180,15 +187,15 @@ public class AsyncNodePluginPlugin: JSBasePlugin {
180
187
}
181
188
182
189
override open func getUrlForFile( fileName: String ) -> URL ? {
183
- #if SWIFT_PACKAGE
190
+ #if SWIFT_PACKAGE
184
191
ResourceUtilities . urlForFile ( name: fileName, ext: " js " , bundle: Bundle . module)
185
- #else
192
+ #else
186
193
ResourceUtilities . urlForFile (
187
194
name: fileName,
188
195
ext: " js " ,
189
196
bundle: Bundle ( for: AsyncNodePluginPlugin . self) ,
190
197
pathComponent: " PlayerUIAsyncNodePlugin.bundle "
191
198
)
192
- #endif
199
+ #endif
193
200
}
194
201
}
0 commit comments