@webspatial/platform-visionos 0.1.19 → 0.1.21

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webspatial/platform-visionos",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Used to publish WebSpatial projects to Apple Vision Pro",
5
5
  "type": "commonjs",
6
6
  "engines": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "info": {
3
- "version": 1,
4
- "author": "xcode"
3
+ "author": "xcode",
4
+ "version": 1
5
5
  }
6
6
  }
@@ -0,0 +1,20 @@
1
+ {
2
+ "images": [
3
+ {
4
+ "idiom": "universal",
5
+ "scale": "1x"
6
+ },
7
+ {
8
+ "idiom": "universal",
9
+ "scale": "2x"
10
+ },
11
+ {
12
+ "idiom": "universal",
13
+ "scale": "3x"
14
+ }
15
+ ],
16
+ "info": {
17
+ "author": "xcode",
18
+ "version": 1
19
+ }
20
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "images": [
3
+ {
4
+ "filename": "nav.png",
5
+ "idiom": "universal",
6
+ "scale": "1x"
7
+ },
8
+ {
9
+ "idiom": "universal",
10
+ "scale": "2x"
11
+ },
12
+ {
13
+ "idiom": "universal",
14
+ "scale": "3x"
15
+ }
16
+ ],
17
+ "info": {
18
+ "author": "xcode",
19
+ "version": 1
20
+ }
21
+ }
@@ -78,7 +78,7 @@ class WindowContainerMgr: ObservableObject {
78
78
  }
79
79
 
80
80
  private var wgSetting: WindowContainerPlainDefaultValues = .init(
81
- defaultSize: CGSize(width: 1080, height: 720),
81
+ defaultSize: CGSize(width: 1080, height: 720 + (pwaManager.display != .fullscreen ? NavView.navHeight : 0)),
82
82
  windowResizability: .automatic
83
83
  )
84
84
 
@@ -93,7 +93,8 @@ class WindowContainerMgr: ObservableObject {
93
93
  }
94
94
 
95
95
  func updateWindowContainerPlainDefaultValues(_ data: WindowContainerPlainDefaultValues) {
96
- if let newSize = data.defaultSize {
96
+ if var newSize = data.defaultSize {
97
+ newSize.height += (pwaManager.display != .fullscreen ? NavView.navHeight : 0)
97
98
  wgSetting.defaultSize = newSize
98
99
  }
99
100
  if let newResizability = data.windowResizability {
@@ -175,9 +175,13 @@ class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler, WKUID
175
175
  return nil
176
176
  }
177
177
 
178
- let wvNative = WebViewNative()
179
-
180
- _ = wvNative.createResources(configuration: configuration)
178
+ var wvNative = WebViewNative()
179
+ var needsUpdate = false
180
+ if resource.starts(with: "file://") {
181
+ wvNative.url = URL(string: resource)!
182
+ needsUpdate = true
183
+ }
184
+ _ = wvNative.createResources(configuration: configuration, needsUpdate: needsUpdate)
181
185
 
182
186
  webViewRef!.didSpawnWebView(wv: wvNative)
183
187
 
@@ -229,7 +233,7 @@ struct WebViewNative: UIViewRepresentable {
229
233
  return c
230
234
  }
231
235
 
232
- func createResources(configuration: WKWebViewConfiguration? = nil) -> WKWebView {
236
+ func createResources(configuration: WKWebViewConfiguration? = nil, needsUpdate: Bool = false) -> WKWebView {
233
237
  if webViewHolder.appleWebView == nil {
234
238
  webViewHolder.webViewCoordinator = makeCoordinator()
235
239
  let userContentController = WKUserContentController()
@@ -259,7 +263,7 @@ struct WebViewNative: UIViewRepresentable {
259
263
  webViewHolder.appleWebView!.allowsLinkPreview = true
260
264
  webViewHolder.appleWebView!.navigationDelegate = webViewHolder.webViewCoordinator
261
265
  webViewHolder.appleWebView!.scrollView.delegate = webViewHolder.webViewCoordinator
262
- webViewHolder.needsUpdate = (configuration != nil) ? false : true
266
+ webViewHolder.needsUpdate = (configuration != nil && !needsUpdate) ? false : true
263
267
  }
264
268
 
265
269
  return webViewHolder.appleWebView!
@@ -24,6 +24,7 @@ struct PWAManager: Codable {
24
24
  resizability: "automatic"
25
25
  )
26
26
  var useMainScene: Bool = true
27
+ private var version: String = "PACKAGE_VERSION"
27
28
 
28
29
  mutating func _init() {
29
30
  let urlType = start_url.split(separator: "://").first
@@ -86,6 +87,10 @@ struct PWAManager: Codable {
86
87
  }
87
88
  return resource
88
89
  }
90
+
91
+ func getVersion() -> String {
92
+ return version
93
+ }
89
94
  }
90
95
 
91
96
  enum PWADisplayMode: Codable {
Binary file
@@ -28,34 +28,115 @@ struct SpatialWebViewUI: View {
28
28
  let parentYOffset = Float(wv.scrollOffset.y)
29
29
 
30
30
  let childEntities = ent.getEntities()
31
+ VStack(spacing: 0) {
32
+ if wv.isRootWebview() && pwaManager.display != .fullscreen {
33
+ NavView(swc: wv, navInfo: wv.navInfo)
34
+ Spacer()
35
+ }
36
+ // Display child entities of the webview
37
+ ZStack {
38
+ OptionalClip(clipEnabled: ent.coordinateSpace != .ROOT && wv.isScrollEnabled()) {
39
+ ZStack {
40
+ ForEach(Array(childEntities.keys), id: \.self) { key in
41
+ if let e = childEntities[key] {
42
+ let _ = e.forceUpdate ? 0 : 0
43
+ if let childWindowcomponent = e.getComponent(SpatialWindowComponent.self) {
44
+ if e.coordinateSpace == .DOM {
45
+ let view = childWindowcomponent
46
+ let x = CGFloat(e.modelEntity.position.x)
47
+ let y = CGFloat(e.modelEntity.position.y - (view.scrollWithParent ? parentYOffset : 0))
48
+ let z = CGFloat(e.modelEntity.position.z) + (e.zIndex * zOrderBias)
49
+ let width = CGFloat(view.resolutionX)
50
+ let height = CGFloat(view.resolutionY)
51
+ let anchor = view.rotationAnchor
52
+
53
+ // Matrix = MTranslate X MRotate X MScale
54
+ SpatialWebViewUI().environment(e)
55
+ .frame(width: width, height: height)
56
+ // use .offset(smallVal) to workaround for glassEffect not working and small width/height spatialDiv not working
57
+ .offset(z: 0.0001)
58
+ .scaleEffect(
59
+ x: CGFloat(e.modelEntity.scale.x),
60
+ y: CGFloat(e.modelEntity.scale.y),
61
+ z: CGFloat(e.modelEntity.scale.z),
62
+ anchor: anchor
63
+ )
64
+ .rotation3DEffect(
65
+ Rotation3D(simd_quatf(
66
+ ix: e.modelEntity.orientation.vector.x,
67
+ iy: e.modelEntity.orientation.vector.y,
68
+ iz: e.modelEntity.orientation.vector.z,
69
+ r: e.modelEntity.orientation.vector.w
70
+ )),
71
+ anchor: anchor
72
+ )
73
+
74
+ .position(x: x, y: y)
75
+ .offset(z: z)
76
+ .gesture(
77
+ DragGesture()
78
+ .onChanged { gesture in
79
+ let scrollEnabled = view.isScrollEnabled()
80
+ if !scrollEnabled {
81
+ // Check if there is a nearest scroll-enabled SpatialWindowComponent in the current SpatialEntity
82
+ // and scroll it if it exists
83
+ if let targetScrollWV = wv.findNearestScrollEnabledSpatialWindowComponent() {
84
+ if !view.dragStarted {
85
+ view.dragStarted = true
86
+ view.dragStart = (gesture.translation.height)
87
+ }
88
+
89
+ // TODO: this should have velocity
90
+ let delta = view.dragStart - gesture.translation.height
91
+ view.dragStart = gesture.translation.height
92
+ targetScrollWV.updateScrollOffset(delta: delta)
93
+ }
94
+ }
95
+ }
96
+ .onEnded { _ in
97
+ let scrollEnabled = view.isScrollEnabled()
31
98
 
32
- // Display child entities of the webview
33
- ZStack {
34
- OptionalClip(clipEnabled: ent.coordinateSpace != .ROOT && wv.isScrollEnabled()) {
35
- ZStack {
36
- ForEach(Array(childEntities.keys), id: \.self) { key in
37
- if let e = childEntities[key] {
38
- let _ = e.forceUpdate ? 0 : 0
39
- if let childWindowcomponent = e.getComponent(SpatialWindowComponent.self) {
99
+ if !scrollEnabled {
100
+ if let targetScrollWV = wv.findNearestScrollEnabledSpatialWindowComponent() {
101
+ view.dragStarted = false
102
+ view.dragStart = 0
103
+
104
+ targetScrollWV.stopScrolling()
105
+ }
106
+ }
107
+ }
108
+ )
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ // Model3D content
115
+ ForEach(Array(childEntities.keys), id: \.self) { key in
116
+ if let e = childEntities[key] {
117
+ let _ = e.forceUpdate ? 0 : 0
118
+ SpatialModel3DView(parentYOffset: parentYOffset)
119
+ .environment(e)
120
+ }
121
+ }
122
+
123
+ // SpatialView content
124
+ ForEach(Array(childEntities.keys), id: \.self) { key in
125
+ if let e = childEntities[key] {
40
126
  if e.coordinateSpace == .DOM {
41
- let view = childWindowcomponent
42
- let x = CGFloat(e.modelEntity.position.x)
43
- let y = CGFloat(e.modelEntity.position.y - (view.scrollWithParent ? parentYOffset : 0))
44
- let z = CGFloat(e.modelEntity.position.z) + (e.zIndex * zOrderBias)
45
- let width = CGFloat(view.resolutionX)
46
- let height = CGFloat(view.resolutionY)
47
- let anchor = view.rotationAnchor
48
-
49
- // Matrix = MTranslate X MRotate X MScale
50
- SpatialWebViewUI().environment(e)
51
- .frame(width: width, height: height)
52
- // use .offset(smallVal) to workaround for glassEffect not working and small width/height spatialDiv not working
53
- .offset(z: 0.0001)
54
- .scaleEffect(
127
+ if let viewComponent = e.getComponent(SpatialViewComponent.self) {
128
+ let _ = e.forceUpdate ? 0 : 0
129
+ let x = CGFloat(e.modelEntity.position.x)
130
+ let y = CGFloat(e.modelEntity.position.y - parentYOffset)
131
+ let z = CGFloat(e.modelEntity.position.z)
132
+
133
+ let width = CGFloat(viewComponent.resolutionX)
134
+ let height = CGFloat(viewComponent.resolutionY)
135
+
136
+ SpatialViewUI().environment(e).frame(width: width, height: height).scaleEffect(
55
137
  x: CGFloat(e.modelEntity.scale.x),
56
138
  y: CGFloat(e.modelEntity.scale.y),
57
- z: CGFloat(e.modelEntity.scale.z),
58
- anchor: anchor
139
+ z: CGFloat(e.modelEntity.scale.z)
59
140
  )
60
141
  .rotation3DEffect(
61
142
  Rotation3D(simd_quatf(
@@ -63,125 +144,49 @@ struct SpatialWebViewUI: View {
63
144
  iy: e.modelEntity.orientation.vector.y,
64
145
  iz: e.modelEntity.orientation.vector.z,
65
146
  r: e.modelEntity.orientation.vector.w
66
- )),
67
- anchor: anchor
68
- )
69
-
70
- .position(x: x, y: y)
147
+ ))
148
+ ).position(x: x, y: y)
71
149
  .offset(z: z)
72
- .gesture(
73
- DragGesture()
74
- .onChanged { gesture in
75
- let scrollEnabled = view.isScrollEnabled()
76
- if !scrollEnabled {
77
- // Check if there is a nearest scroll-enabled SpatialWindowComponent in the current SpatialEntity
78
- // and scroll it if it exists
79
- if let targetScrollWV = wv.findNearestScrollEnabledSpatialWindowComponent() {
80
- if !view.dragStarted {
81
- view.dragStarted = true
82
- view.dragStart = (gesture.translation.height)
83
- }
84
-
85
- // TODO: this should have velocity
86
- let delta = view.dragStart - gesture.translation.height
87
- view.dragStart = gesture.translation.height
88
- targetScrollWV.updateScrollOffset(delta: delta)
89
- }
90
- }
91
- }
92
- .onEnded { _ in
93
- let scrollEnabled = view.isScrollEnabled()
94
-
95
- if !scrollEnabled {
96
- if let targetScrollWV = wv.findNearestScrollEnabledSpatialWindowComponent() {
97
- view.dragStarted = false
98
- view.dragStart = 0
99
-
100
- targetScrollWV.stopScrolling()
101
- }
102
- }
103
- }
104
- )
150
+ }
105
151
  }
106
152
  }
107
153
  }
108
- }
109
-
110
- // Model3D content
111
- ForEach(Array(childEntities.keys), id: \.self) { key in
112
- if let e = childEntities[key] {
113
- let _ = e.forceUpdate ? 0 : 0
114
- SpatialModel3DView(parentYOffset: parentYOffset)
115
- .environment(e)
116
- }
117
- }
154
+ }.frame(maxWidth: .infinity, maxHeight: .infinity).frame(maxDepth: 0, alignment: .back).offset(z: 0)
155
+ }
118
156
 
119
- // SpatialView content
120
- ForEach(Array(childEntities.keys), id: \.self) { key in
121
- if let e = childEntities[key] {
122
- if e.coordinateSpace == .DOM {
123
- if let viewComponent = e.getComponent(SpatialViewComponent.self) {
124
- let _ = e.forceUpdate ? 0 : 0
125
- let x = CGFloat(e.modelEntity.position.x)
126
- let y = CGFloat(e.modelEntity.position.y - parentYOffset)
127
- let z = CGFloat(e.modelEntity.position.z)
128
-
129
- let width = CGFloat(viewComponent.resolutionX)
130
- let height = CGFloat(viewComponent.resolutionY)
131
-
132
- SpatialViewUI().environment(e).frame(width: width, height: height).scaleEffect(
133
- x: CGFloat(e.modelEntity.scale.x),
134
- y: CGFloat(e.modelEntity.scale.y),
135
- z: CGFloat(e.modelEntity.scale.z)
136
- )
137
- .rotation3DEffect(
138
- Rotation3D(simd_quatf(
139
- ix: e.modelEntity.orientation.vector.x,
140
- iy: e.modelEntity.orientation.vector.y,
141
- iz: e.modelEntity.orientation.vector.z,
142
- r: e.modelEntity.orientation.vector.w
143
- ))
144
- ).position(x: x, y: y)
145
- .offset(z: z)
146
- }
157
+ // Display the main webview
158
+ if wv.didFailLoad {
159
+ VStack {
160
+ Text("Failed to load webpage. Is the server running?")
161
+ .foregroundColor(.white)
162
+ Button("Reload") {
163
+ if let url = wv.getURL() {
164
+ wv.navigateToURL(url: url)
165
+ } else {
166
+ logger.warning("Unable to reload URL")
147
167
  }
148
168
  }
149
- }
150
- }.frame(maxWidth: .infinity, maxHeight: .infinity).frame(maxDepth: 0, alignment: .back).offset(z: 0)
151
- }
152
-
153
- // Display the main webview
154
- if wv.didFailLoad {
155
- VStack {
156
- Text("Failed to load webpage. Is the server running?")
157
169
  .foregroundColor(.white)
158
- Button("Reload") {
159
- if let url = wv.getURL() {
160
- wv.navigateToURL(url: url)
161
- } else {
162
- logger.warning("Unable to reload URL")
163
- }
164
170
  }
165
- .foregroundColor(.white)
166
- }
167
- .frame(maxWidth: .infinity, maxHeight: .infinity).glassBackgroundEffect()
171
+ .frame(maxWidth: .infinity, maxHeight: .infinity).glassBackgroundEffect()
168
172
 
169
- } else {
170
- wv.getView()
171
- .materialWithBorderCorner(
172
- wv.backgroundMaterial,
173
- wv.cornerRadius
174
- )
173
+ } else {
174
+ wv.getView()
175
+ .materialWithBorderCorner(
176
+ wv.backgroundMaterial,
177
+ wv.cornerRadius
178
+ )
175
179
 
176
- .frame(maxWidth: .infinity, maxHeight: .infinity)
177
- }
178
- }
179
- .opacity(wv.opacity)
180
- .hidden(!ent.visible)
181
- .ornament(attachmentAnchor: .scene(.bottomTrailing), contentAlignment: .bottomTrailing) {
182
- if wv.isRootWebview() && pwaManager.display != .fullscreen {
183
- NavView(swc: wv, navInfo: wv.navInfo)
180
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
181
+ }
184
182
  }
183
+ .opacity(wv.opacity)
184
+ .hidden(!ent.visible)
185
+ // .ornament(attachmentAnchor: .scene(.top), contentAlignment: .top) {
186
+ // if wv.isRootWebview() && pwaManager.display != .fullscreen {
187
+ // NavView(swc: wv, navInfo: wv.navInfo)
188
+ // }
189
+ // }
185
190
  }
186
191
  }
187
192
  }
@@ -2,113 +2,137 @@ import SwiftUI
2
2
  import WebKit
3
3
 
4
4
  struct NavView: View {
5
+ static let navHeight: CGFloat = 80
5
6
  @State var swc: SpatialWindowComponent?
6
7
  @StateObject var navInfo: NavInfo
7
- @State var showUrl: Bool = true
8
+ @State var showUrl: Bool = false
9
+ @State private var showNav: Bool = false
8
10
  @State private var showCopyTip = false
9
11
  @State private var navWidth: CGFloat = 0
10
- @State private var navHeight: CGFloat = 0
12
+ @State private var contentHeight: CGFloat = 68
11
13
  @State private var texWidth: CGFloat = 0
12
14
  @State private var firstGetSize: Bool = true
15
+ @Namespace var hoverNamespace
16
+ var navHoverGroup: HoverEffectGroup {
17
+ HoverEffectGroup(hoverNamespace)
18
+ }
13
19
 
14
20
  var body: some View {
15
- ZStack(alignment: .bottomTrailing) {
16
- ZStack {}.frame(width: navWidth, height: navHeight)
17
- VStack(alignment: .trailing, spacing: 5) {
18
- if showUrl {
19
- Text(pwaManager.name).padding(10)
20
- if pwaManager.display == .minimal {
21
- HStack(spacing: 5) {
22
- Button(action: {
23
- swc?.goBack()
24
- }, label: {
25
- Image(systemName: "arrow.left")
26
- })
27
- .disabled(!(swc?.canGoBack ?? false))
28
- Button(action: {
29
- swc?.goForward()
30
- }, label: {
31
- Image(systemName: "arrow.right")
32
- })
33
- .disabled(!(swc?.canGoBack ?? false))
34
- Button(action: {
35
- swc?.reload()
36
- }, label: {
37
- Image(systemName: "arrow.clockwise")
38
- })
39
- Button(
40
- action: {
41
- swc?
42
- .navigateToURL(
43
- url: URL(string: pwaManager.start_url)!
44
- )
45
- },
46
- label: {
47
- Image(systemName: "house.fill")
48
- }
49
- )
50
- }
51
- }
21
+ ZStack {
22
+ ZStack {
23
+ HStack {
24
+ Image("logo").resizable().frame(width: 44, height: 44)
25
+ .cornerRadius(100)
26
+ NavButton(action: { print("click"); showNav = true }, children: Image(systemName: "link"))
27
+ }
28
+ .padding(12)
29
+ .background(.thinMaterial)
30
+ .hoverEffect(in: navHoverGroup) { effect, isActive, _ in
31
+ effect.opacity((isActive && !showNav) ? 1 : 0)
52
32
  }
53
- HStack(spacing: 5) {
54
- if showUrl {
55
- Text(
56
- navInfo.url.count > 0 ? navInfo.url : (swc?.getURL()?.absoluteString ?? "")
57
- )
58
- .padding()
59
- .lineLimit(1)
60
- .overlay(GeometryReader { geo -> AnyView in
61
- DispatchQueue.main.async {
62
- if geo.size.width > 0 {
63
- texWidth = .minimum(300, geo.size.width)
33
+ Image("nav").resizable().frame(width: 29, height: 29).hoverEffect(.highlight).hoverEffect(in: navHoverGroup) { effect, isActive, _ in
34
+ effect.opacity((isActive && !showNav) ? 0 : 1)
35
+ }
36
+ }
37
+ .frame(height: contentHeight)
38
+ .cornerRadius(100)
39
+ .hoverEffect(in: navHoverGroup) { effect, isActive, proxy in
40
+ effect.clipShape(.capsule.size(
41
+ width: isActive ? proxy.size.width : proxy.size.height,
42
+ height: proxy.size.height,
43
+ anchor: .center
44
+ ))
45
+ }
46
+ .opacity(showNav ? 0 : 1)
47
+ // if showNav {
48
+ HStack(spacing: 14) {
49
+ if pwaManager.display == .minimal {
50
+ NavButton(action: { swc?.goBack() }, children: Image(systemName: "arrow.left"), clearBackGround: true).disabled(!(swc?.canGoBack ?? false))
51
+ NavButton(action: { swc?.goForward() }, children: Image(systemName: "arrow.right"), clearBackGround: true).disabled(!(swc?.canGoBack ?? false))
52
+ }
53
+ NavButton(action: { swc?.reload() }, children: Image(systemName: "arrow.clockwise"), clearBackGround: true)
54
+ NavButton(action: { swc?.navigateToURL(url: URL(string: pwaManager.start_url)!) }, children: Image(systemName: "house.fill"), clearBackGround: true)
55
+ NavButton(action: { withAnimation(.easeInOut(duration: 0.5)) { showUrl = true } }, children: Image(systemName: "link"), clearBackGround: true)
56
+ NavButton(action: { showNav = false }, children: Image(systemName: "chevron.up"))
57
+ }
58
+ .padding(12)
59
+ .glassBackgroundEffect(in: RoundedRectangle(cornerRadius: 100))
60
+ .opacity(withAnimation(.easeInOut(duration: 0.5)) { showNav ? 1 : 0 })
61
+ .ornament(attachmentAnchor: .scene(.top), contentAlignment: .top) {
62
+ if showUrl {
63
+ HStack(spacing: 14) {
64
+ Text(navInfo.url.count > 0 ? navInfo.url : (swc?.getURL()?.absoluteString ?? ""))
65
+ .padding()
66
+ .lineLimit(1)
67
+ .overlay(GeometryReader { geo -> AnyView in
68
+ DispatchQueue.main.async {
69
+ if geo.size.width > 0 {
70
+ texWidth = .minimum(300, geo.size.width)
71
+ }
64
72
  }
65
- }
66
- return AnyView(EmptyView())
67
- })
68
- .frame(width: .maximum(300, texWidth))
69
- Button(action: {
73
+ return AnyView(EmptyView())
74
+ })
75
+ .frame(width: .maximum(300, texWidth))
76
+ NavButton(action: {
70
77
  UIPasteboard.general.string = swc?.getURL()?.absoluteString ?? ""
71
78
  showCopyTip = true
72
79
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
73
80
  showCopyTip = false
74
81
  }
75
- }, label: {
76
- Text("copy")
77
- })
82
+ }, children: Image(systemName: "square.on.square"))
83
+ NavButton(action: { showUrl = false }, children: Image(systemName: "xmark"))
78
84
  }
79
-
80
- Button(action: {
81
- withAnimation(.easeInOut(duration: 0.5)) {
82
- showUrl.toggle()
83
- }
84
- }, label: {
85
- Image(systemName: showUrl ? "xmark" : "info")
86
- })
87
- }
88
- }
89
- .padding()
90
- .glassBackgroundEffect(in: RoundedRectangle(cornerRadius: 15))
91
- .popover(isPresented: $showCopyTip) {
92
- Text("copied!")
93
- .padding()
94
- .cornerRadius(10)
95
- }
96
- .overlay(GeometryReader { geo -> AnyView in
97
- DispatchQueue.main.async {
98
- if firstGetSize {
99
- navWidth = geo.size.width
100
- navHeight = geo.size.height
101
- firstGetSize.toggle()
102
- showUrl.toggle()
103
- print(navWidth)
85
+ .padding(12)
86
+ .glassBackgroundEffect(in: RoundedRectangle(cornerRadius: 100))
87
+ .popover(isPresented: $showCopyTip) {
88
+ Text("copied!")
89
+ .padding()
90
+ .cornerRadius(10)
104
91
  }
105
92
  }
106
- return AnyView(EmptyView())
107
- })
108
- .opacity(firstGetSize ? 0 : 1)
93
+ }
94
+ // }
95
+ }
96
+
97
+ // else{
98
+
99
+ // }
100
+ }
101
+ }
102
+
103
+ struct NavButtonStyle: ButtonStyle {
104
+ func makeBody(configuration: Configuration) -> some View {
105
+ configuration.label
106
+ .background(Color.clear)
107
+ }
108
+ }
109
+
110
+ struct NavButton: View {
111
+ var action: () -> Void
112
+ var children: Image
113
+ var size: CGFloat = 44
114
+ var padding: CGFloat = 10
115
+ var clearBackGround: Bool = false
116
+ var body: some View {
117
+ if clearBackGround {
118
+ Button(action: action, label: {
119
+ Circle()
120
+ .fill(Color.white.opacity(0))
121
+ .frame(width: size, height: size)
122
+ .overlay(
123
+ children.frame(width: size, height: size).padding(padding)
124
+ )
125
+ }).frame(width: size, height: size).buttonStyle(NavButtonStyle()).hoverEffect(.highlight)
126
+ } else {
127
+ Button(action: action, label: {
128
+ Circle()
129
+ .fill(Color.white.opacity(0))
130
+ .frame(width: size, height: size)
131
+ .overlay(
132
+ children.frame(width: size, height: size).padding(padding)
133
+ )
134
+ }).frame(width: size, height: size).hoverEffect(.highlight)
109
135
  }
110
- .frame(width: firstGetSize ? .infinity : navWidth, height: firstGetSize ? .infinity : navHeight)
111
- .offset(z: 30)
112
136
  }
113
137
  }
114
138
 
@@ -11,7 +11,7 @@ let clock = PerfClock()
11
11
  let logger = Logger()
12
12
 
13
13
  // To load a local path, remove http:// eg. "static-web/"
14
- let nativeAPIVersion = getPackageVersion()
14
+ let nativeAPIVersion = pwaManager.getVersion()
15
15
 
16
16
  // start URL
17
17
  let startURL = pwaManager.start_url
@@ -22,6 +22,7 @@
22
22
  2B2F1D9B2BEDA975006897EE /* PlainWindowContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B2F1D9A2BEDA975006897EE /* PlainWindowContainerView.swift */; };
23
23
  2B37E8E12D002C4D0096749A /* MaterialWithBorderCornerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B37E8E02D002C2B0096749A /* MaterialWithBorderCornerModifier.swift */; };
24
24
  2B67BBAC2D151C1A00BBC689 /* manifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B67BBAB2D151C1500BBC689 /* manifest.swift */; };
25
+ 2B6BA5DF2DF0607400D40337 /* nav.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6BA5DE2DF0607400D40337 /* nav.png */; };
25
26
  2B85209C2BFD5FDB0038FE29 /* UpdateSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B85209B2BFD5FDB0038FE29 /* UpdateSystem.swift */; };
26
27
  2B9909932C3605A9004826D1 /* Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B9909922C3605A9004826D1 /* Window.swift */; };
27
28
  2BA06D712D4380C60020B505 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA06D702D4380C30020B505 /* LoadingView.swift */; };
@@ -31,7 +32,6 @@
31
32
  2BC261222D38F1DA00BCA977 /* NavView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BC261202D38F1DA00BCA977 /* NavView.swift */; };
32
33
  2BC9A2212D1E829B00912170 /* HideViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BC9A2202D1E829B00912170 /* HideViewModifier.swift */; };
33
34
  2BD510562D54A30D0001E5E6 /* SceneManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD510552D54A2FF0001E5E6 /* SceneManager.swift */; };
34
- 2BD5880E2DB1237F00C0E13B /* version.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD5880D2DB1236000C0E13B /* version.swift */; };
35
35
  2BDBED5F2D3F885A0065443F /* SpatialModel3DComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BDBED5E2D3F885A0065443F /* SpatialModel3DComponent.swift */; };
36
36
  2BDBED632D3FE8EC0065443F /* SpatialModel3DView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BDBED622D3FE8EA0065443F /* SpatialModel3DView.swift */; };
37
37
  2BDBF9B62C4ED9F600D269D7 /* static-web in Resources */ = {isa = PBXBuildFile; fileRef = 2BDBF9B52C4ED9F600D269D7 /* static-web */; };
@@ -77,6 +77,7 @@
77
77
  2B2F1D9A2BEDA975006897EE /* PlainWindowContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlainWindowContainerView.swift; sourceTree = "<group>"; };
78
78
  2B37E8E02D002C2B0096749A /* MaterialWithBorderCornerModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaterialWithBorderCornerModifier.swift; sourceTree = "<group>"; };
79
79
  2B67BBAB2D151C1500BBC689 /* manifest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = manifest.swift; sourceTree = "<group>"; };
80
+ 2B6BA5DE2DF0607400D40337 /* nav.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nav.png; sourceTree = "<group>"; };
80
81
  2B85209B2BFD5FDB0038FE29 /* UpdateSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateSystem.swift; sourceTree = "<group>"; };
81
82
  2B9909922C3605A9004826D1 /* Window.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Window.swift; sourceTree = "<group>"; };
82
83
  2BA06D702D4380C30020B505 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
@@ -86,7 +87,6 @@
86
87
  2BC261202D38F1DA00BCA977 /* NavView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavView.swift; sourceTree = "<group>"; };
87
88
  2BC9A2202D1E829B00912170 /* HideViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideViewModifier.swift; sourceTree = "<group>"; };
88
89
  2BD510552D54A2FF0001E5E6 /* SceneManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneManager.swift; sourceTree = "<group>"; };
89
- 2BD5880D2DB1236000C0E13B /* version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = version.swift; sourceTree = "<group>"; };
90
90
  2BDBED5E2D3F885A0065443F /* SpatialModel3DComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpatialModel3DComponent.swift; sourceTree = "<group>"; };
91
91
  2BDBED622D3FE8EA0065443F /* SpatialModel3DView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpatialModel3DView.swift; sourceTree = "<group>"; };
92
92
  2BDBF9B52C4ED9F600D269D7 /* static-web */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "static-web"; sourceTree = "<group>"; };
@@ -126,7 +126,6 @@
126
126
  isa = PBXGroup;
127
127
  children = (
128
128
  2B0FF4F32DD2711800C3F20A /* PerfClock.swift */,
129
- 2BD5880D2DB1236000C0E13B /* version.swift */,
130
129
  2BD510552D54A2FF0001E5E6 /* SceneManager.swift */,
131
130
  2B0B43092CBE21540003CEF3 /* CommandManager.swift */,
132
131
  2B0B1C0F2C494E5400E644F9 /* Logger.swift */,
@@ -161,6 +160,7 @@
161
160
  2B2F1D8A2BED4CD0006897EE /* libs */,
162
161
  2B2F1D6A2BEBFAAA006897EE /* web_spatialApp.swift */,
163
162
  2B2F1D702BEBFAAC006897EE /* Assets.xcassets */,
163
+ 2B6BA5DE2DF0607400D40337 /* nav.png */,
164
164
  2B2F1D752BEBFAAC006897EE /* Info.plist */,
165
165
  2B2F1D722BEBFAAC006897EE /* Preview Content */,
166
166
  );
@@ -354,6 +354,7 @@
354
354
  files = (
355
355
  2BDBF9B62C4ED9F600D269D7 /* static-web in Resources */,
356
356
  2B2F1D742BEBFAAC006897EE /* Preview Assets.xcassets in Resources */,
357
+ 2B6BA5DF2DF0607400D40337 /* nav.png in Resources */,
357
358
  2B2F1D712BEBFAAC006897EE /* Assets.xcassets in Resources */,
358
359
  );
359
360
  runOnlyForDeploymentPostprocessing = 0;
@@ -391,7 +392,6 @@
391
392
  2BDBED5F2D3F885A0065443F /* SpatialModel3DComponent.swift in Sources */,
392
393
  2B2F1D6B2BEBFAAA006897EE /* web_spatialApp.swift in Sources */,
393
394
  2B0B1C102C494E5400E644F9 /* Logger.swift in Sources */,
394
- 2BD5880E2DB1237F00C0E13B /* version.swift in Sources */,
395
395
  2B37E8E12D002C4D0096749A /* MaterialWithBorderCornerModifier.swift in Sources */,
396
396
  2BC261222D38F1DA00BCA977 /* NavView.swift in Sources */,
397
397
  2BAC1BE22CDC49040022E29B /* SpatialViewUI.swift in Sources */,
@@ -1,25 +0,0 @@
1
- import Foundation
2
-
3
- struct PackageJSON: Codable {
4
- let version: String
5
- }
6
-
7
- func getPackageVersion() -> String {
8
- let currentFileURL = URL(fileURLWithPath: #file) // path of version
9
- let currentDirectoryURL = currentFileURL.deletingLastPathComponent()
10
-
11
- let packageJSONURL = currentDirectoryURL
12
- .deletingLastPathComponent()
13
- .deletingLastPathComponent()
14
- .deletingLastPathComponent() // .. project root
15
- .appendingPathComponent("package.json")
16
-
17
- do {
18
- // read file
19
- let data = try Data(contentsOf: packageJSONURL)
20
- let package = try JSONDecoder().decode(PackageJSON.self, from: data)
21
- return package.version
22
- } catch {
23
- fatalError("⚠️ Error reading package.json at \(packageJSONURL.path): \(error)")
24
- }
25
- }