@webspatial/platform-visionos 1.0.3 → 1.0.5
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/package.json +2 -2
- package/web-spatial/EventEmitter.swift +56 -0
- package/web-spatial/JSBCommand.swift +348 -0
- package/web-spatial/SpatialObject.swift +108 -0
- package/web-spatial/WebMsgCommand.swift +119 -0
- package/web-spatial/WebSpatialApp.swift +111 -0
- package/web-spatial/{libs/uiKitDelegate/Window.swift → Window.swift} +1 -0
- package/web-spatial/manager/Dynamic3DManager.swift +114 -0
- package/web-spatial/manager/JSBManager.swift +148 -0
- package/web-spatial/manager/WKWebViewManager.swift +39 -0
- package/web-spatial/{libs/webView/manifest.swift → manifest.swift} +16 -5
- package/web-spatial/model/SpatialApp.swift +190 -0
- package/web-spatial/model/SpatialScene.swift +1042 -0
- package/web-spatial/model/Spatialized2DElement.swift +128 -0
- package/web-spatial/model/SpatializedDynamic3DElement.swift +34 -0
- package/web-spatial/model/SpatializedElement.swift +95 -0
- package/web-spatial/model/SpatializedStatic3DElement.swift +19 -0
- package/web-spatial/model/dynamic3d/Geometry.swift +95 -0
- package/web-spatial/model/dynamic3d/SpatialComponent.swift +72 -0
- package/web-spatial/model/dynamic3d/SpatialEntity.swift +211 -0
- package/web-spatial/model/dynamic3d/SpatialMaterial.swift +39 -0
- package/web-spatial/model/dynamic3d/SpatialModelEntity.swift +39 -0
- package/web-spatial/model/dynamic3d/SpatialModelResource.swift +38 -0
- package/web-spatial/model/dynamic3d/SpatialTextureResource.swift +18 -0
- package/web-spatial/protocol/ScrollAbleSpatialElementContainer.swift +1 -0
- package/web-spatial/protocol/SpatialScrollAble.swift +8 -0
- package/web-spatial/protocol/SpatializedElementContainer.swift +8 -0
- package/web-spatial/protocol/WebMsgSender.swift +5 -0
- package/web-spatial/types/Vec2.swift +12 -0
- package/web-spatial/types/Vec3.swift +7 -0
- package/web-spatial/view/SceneHandlerUIView.swift +92 -0
- package/web-spatial/{views/ui/NavView.swift → view/SpatialNavView.swift} +149 -77
- package/web-spatial/view/SpatialSceneContentView.swift +218 -0
- package/web-spatial/view/SpatialSceneView.swift +53 -0
- package/web-spatial/view/Spatialized2DElementView.swift +96 -0
- package/web-spatial/view/SpatializedDynamic3DView.swift +104 -0
- package/web-spatial/view/SpatializedElementView.swift +178 -0
- package/web-spatial/view/SpatializedStatic3DView.swift +70 -0
- package/web-spatial/{views → view/view-modifier}/MaterialWithBorderCornerModifier.swift +28 -8
- package/web-spatial/webview/SpatialWebController.swift +300 -0
- package/web-spatial/webview/SpatialWebView.swift +34 -0
- package/web-spatial/webview/SpatialWebViewModel.swift +307 -0
- package/web-spatial.xcodeproj/project.pbxproj +126 -207
- package/web-spatial/libs/EventEmitter.swift +0 -25
- package/web-spatial/libs/SpatialComponent.swift +0 -24
- package/web-spatial/libs/SpatialEntity.swift +0 -172
- package/web-spatial/libs/SpatialInputComponent.swift +0 -19
- package/web-spatial/libs/SpatialMeshResource.swift +0 -12
- package/web-spatial/libs/SpatialModel3DComponent.swift +0 -51
- package/web-spatial/libs/SpatialModelComponent.swift +0 -25
- package/web-spatial/libs/SpatialObject.swift +0 -140
- package/web-spatial/libs/SpatialPhysicallyBasedMaterial.swift +0 -19
- package/web-spatial/libs/SpatialViewComponent.swift +0 -8
- package/web-spatial/libs/SpatialWindowComponent.swift +0 -454
- package/web-spatial/libs/SpatialWindowContainer.swift +0 -153
- package/web-spatial/libs/Utils/CommandManager.swift +0 -823
- package/web-spatial/libs/Utils/PerfClock.swift +0 -43
- package/web-spatial/libs/Utils/SceneManager.swift +0 -101
- package/web-spatial/libs/Utils/WindowContainerMgr.swift +0 -122
- package/web-spatial/libs/json/JsonParser.swift +0 -45
- package/web-spatial/libs/webView/UpdateSystem.swift +0 -26
- package/web-spatial/libs/webView/backend/NativeWebView.swift +0 -350
- package/web-spatial/views/ImmersiveView.swift +0 -17
- package/web-spatial/views/OpenDismissHandlerUI.swift +0 -45
- package/web-spatial/views/PlainWindowContainerView.swift +0 -132
- package/web-spatial/views/SpatialModel3DView.swift +0 -187
- package/web-spatial/views/SpatialViewUI.swift +0 -168
- package/web-spatial/views/SpatialWebViewUI.swift +0 -179
- package/web-spatial/views/VolumetricWindowContainerView.swift +0 -30
- package/web-spatial/web_spatialApp.swift +0 -141
- /package/web-spatial/{libs/Utils → Utils}/ColorExtension.swift +0 -0
- /package/web-spatial/{libs/Utils → Utils}/Logger.swift +0 -0
- /package/web-spatial/{views → view}/LoadingView.swift +0 -0
- /package/web-spatial/{views → view/view-modifier}/HideViewModifier.swift +0 -0
|
@@ -1,454 +0,0 @@
|
|
|
1
|
-
import Combine
|
|
2
|
-
import Foundation
|
|
3
|
-
import RealityKit
|
|
4
|
-
import SwiftUI
|
|
5
|
-
import WebKit
|
|
6
|
-
|
|
7
|
-
let DefaultPlainWindowContainerSize = CGSize(width: 1280, height: 720)
|
|
8
|
-
|
|
9
|
-
func getDocumentsDirectory() -> URL {
|
|
10
|
-
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
|
11
|
-
let documentsDirectory = paths[0]
|
|
12
|
-
return documentsDirectory
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
struct LoadingStyles {
|
|
16
|
-
var cornerRadius: CornerRadius = .init()
|
|
17
|
-
var windowContainerSize = DefaultPlainWindowContainerSize
|
|
18
|
-
var backgroundMaterial: BackgroundMaterial = .None
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
class NavInfo: ObservableObject {
|
|
22
|
-
@Published var url: String = ""
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@Observable
|
|
26
|
-
class SpatialWindowComponent: SpatialComponent {
|
|
27
|
-
override func inspect() -> [String: Any] {
|
|
28
|
-
let childEntitiesInfo = childResources.mapValues { spatialObject in
|
|
29
|
-
spatialObject.inspect()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let encoder = JSONEncoder()
|
|
33
|
-
encoder.outputFormatting = .prettyPrinted
|
|
34
|
-
|
|
35
|
-
var inspectInfo: [String: Any] = [
|
|
36
|
-
"scrollWithParent": scrollWithParent,
|
|
37
|
-
"resolutionX": resolutionX,
|
|
38
|
-
"resolutionY": resolutionY,
|
|
39
|
-
"parentWebviewID": parentWebviewID,
|
|
40
|
-
"parentWindowContainerID": parentWindowContainerID,
|
|
41
|
-
"childWindowContainers": childWindowContainers,
|
|
42
|
-
"spawnedNativeWebviewsCount": spawnedNativeWebviews.count,
|
|
43
|
-
"childResources": childEntitiesInfo,
|
|
44
|
-
"cornerRadius": cornerRadius.toJson(),
|
|
45
|
-
"backgroundMaterial": backgroundMaterial.rawValue,
|
|
46
|
-
"isOpaque": webViewNative!.webViewHolder.appleWebView!.isOpaque,
|
|
47
|
-
"isScrollEnabled": isScrollEnabled(),
|
|
48
|
-
]
|
|
49
|
-
|
|
50
|
-
let baseInspectInfo = super.inspect()
|
|
51
|
-
for (key, value) in baseInspectInfo {
|
|
52
|
-
inspectInfo[key] = value
|
|
53
|
-
}
|
|
54
|
-
return inspectInfo
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
var scrollOffset = CGPoint()
|
|
58
|
-
private var webViewNative: WebViewNative?
|
|
59
|
-
var resolutionX: Double = 0
|
|
60
|
-
var resolutionY: Double = 0
|
|
61
|
-
var scrollWithParent = false
|
|
62
|
-
|
|
63
|
-
var rotationAnchor: UnitPoint3D = .center
|
|
64
|
-
|
|
65
|
-
// Track the first load event of the webview so we don't see a flash of white before the page loads
|
|
66
|
-
var didFinishFirstLoad = false
|
|
67
|
-
|
|
68
|
-
// ID of the webview that created this or empty if its root
|
|
69
|
-
var parentWebviewID: String = ""
|
|
70
|
-
var parentWindowContainerID: String
|
|
71
|
-
var childWindowContainers = [String: WindowContainerData]()
|
|
72
|
-
var spawnedNativeWebviews = [String: WebViewNative]()
|
|
73
|
-
var navInfo = NavInfo()
|
|
74
|
-
|
|
75
|
-
// Resources that will be destroyed when this webpage is destoryed or if it is navigated away from
|
|
76
|
-
private var childResources = [String: SpatialObject]()
|
|
77
|
-
public func addChildSpatialObject(_ spatialObject: SpatialObject) {
|
|
78
|
-
childResources[spatialObject.id] = spatialObject
|
|
79
|
-
spatialObject
|
|
80
|
-
.on(
|
|
81
|
-
event: SpatialObject.Events.BeforeDestroyed.rawValue,
|
|
82
|
-
listener: onSptatialObjectDestroyed
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public func removeChildSpatialObject(_ spatialObject: SpatialObject) {
|
|
87
|
-
spatialObject
|
|
88
|
-
.off(
|
|
89
|
-
event: SpatialObject.Events.BeforeDestroyed.rawValue,
|
|
90
|
-
listener: onSptatialObjectDestroyed
|
|
91
|
-
)
|
|
92
|
-
childResources.removeValue(forKey: spatialObject.id)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
public func getChildSpatialObject(name: String) -> SpatialObject? {
|
|
96
|
-
return childResources[name]
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
public func destroyChild(name: String) {
|
|
100
|
-
childResources[name]?.destroy()
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private func onSptatialObjectDestroyed(_ object: Any, _ data: Any) {
|
|
104
|
-
let spatialObject = object as! SpatialObject
|
|
105
|
-
removeChildSpatialObject(spatialObject)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
private func onWindowContainerDestroyed(_ object: Any, _ data: Any) {
|
|
109
|
-
if let spatialObject = object as? SpatialWindowContainer {
|
|
110
|
-
spatialObject
|
|
111
|
-
.off(
|
|
112
|
-
event: SpatialObject.Events.BeforeDestroyed.rawValue,
|
|
113
|
-
listener: onWindowContainerDestroyed
|
|
114
|
-
)
|
|
115
|
-
childWindowContainers.removeValue(forKey: spatialObject.id)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/// Determines whether the current webview is a root webview.
|
|
120
|
-
///
|
|
121
|
-
/// A root webview is created when the Scene is initialized.
|
|
122
|
-
/// If the webview is created by another `SpatialWebview`, it is not considered a root webview.
|
|
123
|
-
/// For example, a `SpatialDiv` is not a root webview.
|
|
124
|
-
///
|
|
125
|
-
/// - Returns: `true` if the webview is a root webview (i.e., `parentWebviewID` is empty), otherwise `false`.
|
|
126
|
-
public func isRootWebview() -> Bool {
|
|
127
|
-
return parentWebviewID == ""
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public func setWindowContainer(uuid: String, wgd: WindowContainerData) {
|
|
131
|
-
childWindowContainers[uuid] = wgd
|
|
132
|
-
SpatialWindowContainer.getSpatialWindowContainer(uuid)!.on(
|
|
133
|
-
event: SpatialObject.Events.BeforeDestroyed.rawValue,
|
|
134
|
-
listener: onWindowContainerDestroyed
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Drag event handling
|
|
139
|
-
var dragStarted = false
|
|
140
|
-
var dragStart = 0.0
|
|
141
|
-
var dragVelocity = 0.0
|
|
142
|
-
|
|
143
|
-
var gotStyle = false
|
|
144
|
-
var opacity = 1.0
|
|
145
|
-
var cornerRadius: CornerRadius = .init()
|
|
146
|
-
|
|
147
|
-
private var _backgroundMaterial = BackgroundMaterial.None
|
|
148
|
-
var backgroundMaterial: BackgroundMaterial {
|
|
149
|
-
get {
|
|
150
|
-
return _backgroundMaterial
|
|
151
|
-
}
|
|
152
|
-
set(newValue) {
|
|
153
|
-
_backgroundMaterial = newValue
|
|
154
|
-
if isRootWebview() {
|
|
155
|
-
webViewNative?.webViewHolder.appleWebView?.isOpaque = _backgroundMaterial == .None
|
|
156
|
-
} else {
|
|
157
|
-
// it's spatial div
|
|
158
|
-
webViewNative?.webViewHolder.appleWebView?.isOpaque = false
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
var loadingStyles = LoadingStyles()
|
|
164
|
-
var isLoading = true
|
|
165
|
-
|
|
166
|
-
var didFailLoad = false
|
|
167
|
-
|
|
168
|
-
private var cancellables = Set<AnyCancellable>() // save subscriptions
|
|
169
|
-
|
|
170
|
-
init(parentWindowContainerID: String) {
|
|
171
|
-
self.parentWindowContainerID = parentWindowContainerID
|
|
172
|
-
super.init()
|
|
173
|
-
webViewNative = WebViewNative()
|
|
174
|
-
webViewNative?.webViewRef = self
|
|
175
|
-
_ = webViewNative?.createResources()
|
|
176
|
-
registerForceStyle()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
init(parentWindowContainerID: String, url: URL) {
|
|
180
|
-
self.parentWindowContainerID = parentWindowContainerID
|
|
181
|
-
super.init()
|
|
182
|
-
|
|
183
|
-
webViewNative = WebViewNative(url: url)
|
|
184
|
-
webViewNative?.webViewRef = self
|
|
185
|
-
_ = webViewNative?.createResources()
|
|
186
|
-
registerForceStyle()
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
func initFromURL(url: URL) {
|
|
190
|
-
webViewNative = WebViewNative(url: url)
|
|
191
|
-
webViewNative?.webViewRef = self
|
|
192
|
-
_ = webViewNative?.createResources()
|
|
193
|
-
registerForceStyle()
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// the url schema handler for forcestyle cannot bind seperately for every webview due to apple limitation. So this is a workaround like eventbus, webview will handle the message that has matched webview.
|
|
197
|
-
func registerForceStyle() {
|
|
198
|
-
webviewGetEarlyStyleData
|
|
199
|
-
.filter { [weak self] event in
|
|
200
|
-
self?.getView()?.webViewHolder.appleWebView == event.webview
|
|
201
|
-
}
|
|
202
|
-
.sink { [weak self] event in
|
|
203
|
-
self?.didGetEarlyStyle(style: event.style)
|
|
204
|
-
}
|
|
205
|
-
.store(in: &cancellables)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
func goBack() {
|
|
209
|
-
webViewNative?.webViewHolder.appleWebView?.goBack()
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
func goForward() {
|
|
213
|
-
webViewNative?.webViewHolder.appleWebView?.goForward()
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
func reload() {
|
|
217
|
-
webViewNative?.webViewHolder.appleWebView?.reload()
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
var canGoBack: Bool = false
|
|
221
|
-
|
|
222
|
-
var canGoForward: Bool = false
|
|
223
|
-
|
|
224
|
-
func navigateToURL(url: URL) {
|
|
225
|
-
webViewNative!.url = url
|
|
226
|
-
webViewNative!.webViewHolder.needsUpdate = true
|
|
227
|
-
webViewNative!.initialLoad()
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/// Remove webview window.name
|
|
231
|
-
///
|
|
232
|
-
/// The expectation is that when the app is reopened, the root page should not have a window.name. However, under the current scene mechanism, if the last closed scene had set a window.name, it will still exist the next time the app is opened.
|
|
233
|
-
///
|
|
234
|
-
/// Currently, window.name is only deleted when non-main scenes are closed along with the destruction of the WebView.
|
|
235
|
-
///
|
|
236
|
-
/// the root page should always have a blank name
|
|
237
|
-
|
|
238
|
-
func removeWebviewName(completion: (() -> Void)? = nil) {
|
|
239
|
-
webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.name = '';") { _, _ in
|
|
240
|
-
completion?()
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
func isScrollEnabled() -> Bool {
|
|
245
|
-
return webViewNative!.webViewHolder.appleWebView!.scrollView.isScrollEnabled
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/// Finds the nearest ancestor `SpatialWindowComponent` that has scrolling enabled.
|
|
249
|
-
///
|
|
250
|
-
/// This method traverses the entity hierarchy upwards, starting from the current `SpatialWindowComponent`,
|
|
251
|
-
/// and checks each ancestor `SpatialWindowComponent` to see if scrolling is enabled. If a suitable
|
|
252
|
-
/// component is found, it is returned; otherwise, `nil` is returned.
|
|
253
|
-
///
|
|
254
|
-
/// - Returns: The nearest ancestor `SpatialWindowComponent` with scrolling enabled, or `nil` if none is found.
|
|
255
|
-
func findNearestScrollEnabledSpatialWindowComponent() -> SpatialWindowComponent? {
|
|
256
|
-
var current: SpatialWindowComponent? = self
|
|
257
|
-
while current != nil {
|
|
258
|
-
if current!.isScrollEnabled() {
|
|
259
|
-
return current!
|
|
260
|
-
}
|
|
261
|
-
if let parentEntity = current?.entity?.parent {
|
|
262
|
-
current = parentEntity.getComponent(SpatialWindowComponent.self)
|
|
263
|
-
} else {
|
|
264
|
-
current = nil
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return current
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
func updateScrollOffset(delta: CGFloat) {
|
|
271
|
-
webViewNative!.webViewHolder.appleWebView!.scrollView.contentOffset.y += delta
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
func stopScrolling() {
|
|
275
|
-
webViewNative!.webViewHolder.appleWebView!.scrollView.stopScrollingAndZooming()
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
func getView() -> WebViewNative? {
|
|
279
|
-
return webViewNative
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
func setView(wv: WebViewNative) {
|
|
283
|
-
webViewNative = wv
|
|
284
|
-
webViewNative!.webViewRef = self
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
func evaluateJS(js: String) {
|
|
288
|
-
webViewNative!.webViewHolder.appleWebView!.evaluateJavaScript(js)
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
func getURL() -> URL? {
|
|
292
|
-
return webViewNative?.url
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
func setURL(url: URL) {
|
|
296
|
-
webViewNative!.url = url
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
func parseURL(url: String) -> String {
|
|
300
|
-
// Compute target url depending if the url is relative or not
|
|
301
|
-
var targetUrl = url
|
|
302
|
-
if !pwaManager.isLocal {
|
|
303
|
-
if url[...url.index(url.startIndex, offsetBy: 0)] == "/" {
|
|
304
|
-
// Absolute path
|
|
305
|
-
var port = ""
|
|
306
|
-
if let p = webViewNative?.url.port {
|
|
307
|
-
port = ":" + String(p)
|
|
308
|
-
}
|
|
309
|
-
let domain = webViewNative!.url.scheme! + "://" + webViewNative!.url.host()! + port + "/"
|
|
310
|
-
targetUrl = domain + String(url[url.index(url.startIndex, offsetBy: 1)...])
|
|
311
|
-
} else {
|
|
312
|
-
// Full url eg. http://domain.com
|
|
313
|
-
if let parsed = URL(string: url) {
|
|
314
|
-
if parsed.scheme != nil {
|
|
315
|
-
return url
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
// Reletive path
|
|
319
|
-
let localDir = NSString(string: webViewNative!.url.absoluteString)
|
|
320
|
-
let relPath = String(localDir.deletingLastPathComponent) + "/" + targetUrl
|
|
321
|
-
return relPath
|
|
322
|
-
}
|
|
323
|
-
} else {
|
|
324
|
-
if !(targetUrl.starts(with: "http://") || targetUrl.starts(with: "https://")) {
|
|
325
|
-
targetUrl = pwaManager.getLocalResourceURL(url: targetUrl)
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return targetUrl
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
func readWindowContainerID(id: String) -> String {
|
|
332
|
-
if id == "current" {
|
|
333
|
-
return parentWindowContainerID
|
|
334
|
-
} else {
|
|
335
|
-
return id
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
deinit {
|
|
340
|
-
webViewNative!.destroy()
|
|
341
|
-
cancellables.removeAll()
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
func completeEvent(requestID: Int, data: String = "{}") {
|
|
345
|
-
webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.__SpatialWebEvent({success: true, requestID:" + String(requestID) + ", data: " + data + "})")
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
func fireComponentEvent(componentId: String, data: String = "{}") {
|
|
349
|
-
webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.__SpatialWebEvent({resourceId:'" + componentId + "', data: " + data + "})")
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
func failEvent(requestID: Int, data: String = "{}") {
|
|
353
|
-
webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.__SpatialWebEvent({success: false, requestID:" + String(requestID) + ", data: " + data + "})")
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// Request information of webview that request this webview to load
|
|
357
|
-
weak var loadRequestWV: SpatialWindowComponent?
|
|
358
|
-
var loadRequestID = -1
|
|
359
|
-
|
|
360
|
-
// A load request of a child webview was loaded
|
|
361
|
-
func didLoadChild(loadRequestID: Int, resourceID: String) {
|
|
362
|
-
completeEvent(requestID: loadRequestID, data: "{createdID: '" + id + "'}")
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
func didFailLoadPage() {
|
|
366
|
-
didFailLoad = true
|
|
367
|
-
didFinishFirstLoad = true
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
func releaseChildResources() {
|
|
371
|
-
let spatialObjects = childResources.map { $0.value }
|
|
372
|
-
for spatialObject in spatialObjects {
|
|
373
|
-
spatialObject.destroy()
|
|
374
|
-
}
|
|
375
|
-
childResources = [String: SpatialObject]()
|
|
376
|
-
spawnedNativeWebviews = [String: WebViewNative]()
|
|
377
|
-
|
|
378
|
-
let wgkeys = childWindowContainers.map { $0.key }
|
|
379
|
-
for k in wgkeys {
|
|
380
|
-
SpatialWindowContainer.getSpatialWindowContainer(k)!.closeWindowData.send(childWindowContainers[k]!)
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
func didStartLoadPage() {
|
|
385
|
-
if didFinishFirstLoad {
|
|
386
|
-
webViewNative!.webViewHolder.appleWebView!.evaluateJavaScript("window.__WebSpatialUnloaded = true")
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
releaseChildResources()
|
|
390
|
-
let url = webViewNative?.webViewHolder.appleWebView?.url
|
|
391
|
-
webViewNative!.url = url!
|
|
392
|
-
|
|
393
|
-
// Mark that we havn't gotten a style update
|
|
394
|
-
gotStyle = false
|
|
395
|
-
isLoading = true
|
|
396
|
-
loadingStyles = LoadingStyles()
|
|
397
|
-
|
|
398
|
-
// FIXME:
|
|
399
|
-
// This is a workaround to force run UIViewRepresentable.update()
|
|
400
|
-
// SwiftUI not trigger it when go back from example page.
|
|
401
|
-
// Warning of `AttributeGraph: cycle detected through attribute` fired when goes to example page
|
|
402
|
-
webViewNative?.initialLoad()
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
func didSpawnWebView(wv: WebViewNative) {
|
|
406
|
-
let uuid = UUID().uuidString
|
|
407
|
-
wv.webViewHolder.appleWebView!.evaluateJavaScript("window._webSpatialID = '" + uuid + "'")
|
|
408
|
-
spawnedNativeWebviews[uuid] = wv
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
func didCloseWebView() {
|
|
412
|
-
// if need
|
|
413
|
-
if isRootWebview() {
|
|
414
|
-
SceneManager.Instance.closeRoot(self)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
func didStartReceivePageContent() {}
|
|
419
|
-
|
|
420
|
-
func didGetEarlyStyle(style: PreloadStyleSettings) {
|
|
421
|
-
if let cornerRadius = style.cornerRadius {
|
|
422
|
-
loadingStyles.cornerRadius = cornerRadius
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
if let backgroundMaterial = style.backgroundMaterial {
|
|
426
|
-
loadingStyles.backgroundMaterial = backgroundMaterial
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
func didFinishLoadPage() {
|
|
431
|
-
didFinishFirstLoad = true
|
|
432
|
-
didFailLoad = false
|
|
433
|
-
cornerRadius = loadingStyles.cornerRadius
|
|
434
|
-
backgroundMaterial = loadingStyles.backgroundMaterial
|
|
435
|
-
|
|
436
|
-
isLoading = false
|
|
437
|
-
|
|
438
|
-
// update navinfo
|
|
439
|
-
if let wv = webViewNative?.webViewHolder.appleWebView {
|
|
440
|
-
canGoBack = wv.canGoBack
|
|
441
|
-
canGoForward = wv.canGoForward
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
override func onDestroy() {
|
|
446
|
-
releaseChildResources()
|
|
447
|
-
didCloseWebView()
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
func didNavBackForward() {
|
|
451
|
-
// in JS calling history.go(-1) we should set needUpdate=true
|
|
452
|
-
webViewNative?.webViewHolder.needsUpdate = true
|
|
453
|
-
}
|
|
454
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import Combine
|
|
2
|
-
import Foundation
|
|
3
|
-
import RealityKit
|
|
4
|
-
import typealias RealityKit.Entity
|
|
5
|
-
|
|
6
|
-
@Observable
|
|
7
|
-
class SpatialWindowContainer: SpatialObject {
|
|
8
|
-
// save active plain windowContainer ids
|
|
9
|
-
static var activePlainWindowContainerIds: Set<String> = []
|
|
10
|
-
// get first active plain WindowContainerId
|
|
11
|
-
static var firstActivePlainWindowContainerId: String? {
|
|
12
|
-
return activePlainWindowContainerIds.first
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Resources that will be destroyed when this window group is removed
|
|
16
|
-
private var childResources = [String: SpatialObject]()
|
|
17
|
-
public func addChildResource(_ spatialObject: SpatialObject) {
|
|
18
|
-
childResources[spatialObject.id] = spatialObject
|
|
19
|
-
spatialObject
|
|
20
|
-
.on(
|
|
21
|
-
event: SpatialObject.Events.BeforeDestroyed.rawValue,
|
|
22
|
-
listener: onSptatialObjectDestroyed
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private func onSptatialObjectDestroyed(_ object: Any, _ data: Any) {
|
|
27
|
-
let spatialObject = object as! SpatialObject
|
|
28
|
-
spatialObject
|
|
29
|
-
.off(
|
|
30
|
-
event: SpatialObject.Events.BeforeDestroyed.rawValue,
|
|
31
|
-
listener: onSptatialObjectDestroyed
|
|
32
|
-
)
|
|
33
|
-
childResources.removeValue(forKey: spatialObject.id)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
public var childContainers = [String: SpatialWindowContainer]()
|
|
37
|
-
|
|
38
|
-
var wgd: WindowContainerData
|
|
39
|
-
static func getSpatialWindowContainer(_ name: String) -> SpatialWindowContainer? {
|
|
40
|
-
return SpatialObject.get(name) as? SpatialWindowContainer
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static func getOrCreateSpatialWindowContainer(_ name: String, _ data: WindowContainerData) -> SpatialWindowContainer? {
|
|
44
|
-
if let windowContainer = getSpatialWindowContainer(name) {
|
|
45
|
-
return windowContainer
|
|
46
|
-
}
|
|
47
|
-
let newWindowContainer = SpatialWindowContainer(name, data)
|
|
48
|
-
return newWindowContainer
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
init(_ name: String, _ data: WindowContainerData) {
|
|
52
|
-
wgd = data
|
|
53
|
-
if data.windowStyle == "Plain" {
|
|
54
|
-
SpatialWindowContainer.activePlainWindowContainerIds.insert(data.windowContainerID)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
super.init(name)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Resources
|
|
61
|
-
private var childEntities = [String: SpatialEntity]()
|
|
62
|
-
|
|
63
|
-
public func getEntities() -> [String: SpatialEntity] {
|
|
64
|
-
return childEntities
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
public func addEntity(_ spatialEntity: SpatialEntity) {
|
|
68
|
-
childEntities[spatialEntity.id] = spatialEntity
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public func removeEntity(_ spatialEntity: SpatialEntity) {
|
|
72
|
-
childEntities.removeValue(forKey: spatialEntity.id)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Global state
|
|
76
|
-
var toggleImmersiveSpace = PassthroughSubject<Bool, Never>()
|
|
77
|
-
|
|
78
|
-
var setSize = PassthroughSubject<CGSize, Never>()
|
|
79
|
-
var setResizeRange = PassthroughSubject<ResizeRange, Never>()
|
|
80
|
-
|
|
81
|
-
var updateFrame = false
|
|
82
|
-
var openWindowData = PassthroughSubject<WindowContainerData, Never>()
|
|
83
|
-
var closeWindowData = PassthroughSubject<WindowContainerData, Never>()
|
|
84
|
-
|
|
85
|
-
var setLoadingWindowData = PassthroughSubject<LoadingWindowContainerData, Never>()
|
|
86
|
-
|
|
87
|
-
override func onDestroy() {
|
|
88
|
-
// Note that destroy wont be called on immersive window container
|
|
89
|
-
// as there should only ever be one in existance
|
|
90
|
-
|
|
91
|
-
childEntities.forEach { $0.value.destroy() }
|
|
92
|
-
childEntities = [:]
|
|
93
|
-
|
|
94
|
-
// Destroy resources
|
|
95
|
-
let spatialObjects = childResources.map { $0.value }
|
|
96
|
-
for spatialObject in spatialObjects {
|
|
97
|
-
spatialObject.destroy()
|
|
98
|
-
}
|
|
99
|
-
childResources = [String: SpatialObject]()
|
|
100
|
-
|
|
101
|
-
// Destroy spatial containers
|
|
102
|
-
let spatialContainers = childContainers.map { $0.value }
|
|
103
|
-
for spatialObject in spatialContainers {
|
|
104
|
-
if spatialObject != self {
|
|
105
|
-
spatialObject.destroy()
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
childContainers = [String: SpatialWindowContainer]()
|
|
109
|
-
|
|
110
|
-
// Close the window group when this object is destroyed
|
|
111
|
-
SpatialWindowContainer.getSpatialWindowContainer(id)!.closeWindowData.send(wgd)
|
|
112
|
-
if wgd.windowStyle == "Plain" {
|
|
113
|
-
SpatialWindowContainer.activePlainWindowContainerIds.remove(wgd.windowContainerID)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
override func inspect() -> [String: Any] {
|
|
118
|
-
let childEntitiesInfo = childEntities.mapValues { entity in
|
|
119
|
-
entity.inspect()
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
let baseInspectInfo = super.inspect()
|
|
123
|
-
var inspectInfo: [String: Any] = ["childEntities": childEntitiesInfo]
|
|
124
|
-
for (key, value) in baseInspectInfo {
|
|
125
|
-
inspectInfo[key] = value
|
|
126
|
-
}
|
|
127
|
-
return inspectInfo
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
extension SpatialWindowContainer {
|
|
132
|
-
private static let RootID = "root"
|
|
133
|
-
static func getRootID() -> String {
|
|
134
|
-
return RootID
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
extension SpatialWindowContainer {
|
|
139
|
-
static let ImmersiveID = "Immersive"
|
|
140
|
-
|
|
141
|
-
static func getImmersiveWindowContainer() -> SpatialWindowContainer? {
|
|
142
|
-
return getSpatialWindowContainer(ImmersiveID)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
static func createImmersiveWindowContainer() -> SpatialWindowContainer {
|
|
146
|
-
if let windowContainer = getSpatialWindowContainer(ImmersiveID) {
|
|
147
|
-
logger.warning("Immersive already created! ")
|
|
148
|
-
return windowContainer
|
|
149
|
-
}
|
|
150
|
-
let wgd = WindowContainerData(windowStyle: "ImmersiveSpace", windowContainerID: "ImmersiveSpace")
|
|
151
|
-
return SpatialWindowContainer(ImmersiveID, wgd)
|
|
152
|
-
}
|
|
153
|
-
}
|