@swiftbrowser/native 0.17.1 → 0.17.3
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": "@swiftbrowser/native",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Run a @swiftbrowser/react app natively: the runtime a JavaScriptCore-hosted app needs (timers, console, fetch and the other web globals over the SwiftBrowser Native bridge), the `run` entry that renders into the native SwiftUI renderer, and the bundler that builds app.js for the Xcode target.",
|
|
6
6
|
"repository": {
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@babel/core": "^7.29.7",
|
|
62
|
-
"@swiftbrowser/react": "0.17.
|
|
63
|
-
"@swiftbrowser/web": "0.17.
|
|
62
|
+
"@swiftbrowser/react": "0.17.3",
|
|
63
|
+
"@swiftbrowser/web": "0.17.3",
|
|
64
64
|
"esbuild": "^0.28.2",
|
|
65
65
|
"react-refresh": "^0.17.0"
|
|
66
66
|
},
|
|
@@ -147,12 +147,21 @@ struct ScrollViewElement: View {
|
|
|
147
147
|
@State private var visible: [Int] = []
|
|
148
148
|
@State private var idle = true
|
|
149
149
|
@State private var reported: Int?
|
|
150
|
+
@State private var appeared = false
|
|
150
151
|
|
|
151
152
|
var body: some View {
|
|
152
153
|
let props = ScrollViewProps(props: node.props)
|
|
153
154
|
let axes: Axis.Set = props.axes == "horizontal" ? .horizontal : props.axes == "both" ? [.horizontal, .vertical] : .vertical
|
|
154
155
|
let request = Self.scrollRequest(in: node)
|
|
155
156
|
let anchor = props.positionAnchor.map(UnitPoint.init(spec:))
|
|
157
|
+
// A request not yet served is the position already in this pass, the
|
|
158
|
+
// one that draws the content it came with (the app may have changed
|
|
159
|
+
// the content around its target): served in `onChange`, a pass later,
|
|
160
|
+
// the pass between would draw the new content at the old offset. Not
|
|
161
|
+
// before the view appears: the first pass has no size to scroll in,
|
|
162
|
+
// and the position the request then sets in `onAppear` would be no
|
|
163
|
+
// change, so nothing would scroll.
|
|
164
|
+
let ahead = request.flatMap { appeared && $0.serial > served && Self.positionServes($0, props: props) ? $0.id : nil }
|
|
156
165
|
ScrollViewReader { proxy in
|
|
157
166
|
let scroll = ScrollView(axes, showsIndicators: props.showsIndicators) {
|
|
158
167
|
ChildrenView(node: node)
|
|
@@ -161,7 +170,7 @@ struct ScrollViewElement: View {
|
|
|
161
170
|
let snapped: AnyView = props.snap == "paging" ? AnyView(refreshed.scrollTargetBehavior(.paging))
|
|
162
171
|
: props.snap == "viewAligned" ? AnyView(refreshed.scrollTargetBehavior(.viewAligned)) : refreshed
|
|
163
172
|
let positioned: AnyView = props.reportsPosition
|
|
164
|
-
? reportingSettled(AnyView(snapped.scrollPosition(id: Binding(get: { position }, set: { next in
|
|
173
|
+
? reportingSettled(AnyView(snapped.scrollPosition(id: Binding(get: { ahead ?? position }, set: { next in
|
|
165
174
|
guard next != position else { return }
|
|
166
175
|
position = next
|
|
167
176
|
// Where the settled position is reported, the binding only follows the view.
|
|
@@ -169,7 +178,10 @@ struct ScrollViewElement: View {
|
|
|
169
178
|
}), anchor: anchor)), anchor: anchor)
|
|
170
179
|
: snapped
|
|
171
180
|
positioned
|
|
172
|
-
.onAppear {
|
|
181
|
+
.onAppear {
|
|
182
|
+
perform(request, props: props, with: proxy)
|
|
183
|
+
appeared = true
|
|
184
|
+
}
|
|
173
185
|
.onChange(of: request?.serial) { _, _ in perform(request, props: props, with: proxy) }
|
|
174
186
|
}
|
|
175
187
|
}
|
|
@@ -194,15 +206,19 @@ struct ScrollViewElement: View {
|
|
|
194
206
|
let id = request.id
|
|
195
207
|
Task { @MainActor in
|
|
196
208
|
try? await Task.sleep(for: .milliseconds(450))
|
|
197
|
-
if idle {
|
|
209
|
+
if idle { reportSettled(id) }
|
|
198
210
|
}
|
|
199
211
|
}
|
|
200
|
-
|
|
201
|
-
let ownAxes = request.axes == props.axes && props.axes != "both"
|
|
202
|
-
if props.reportsPosition, ownAxes, request.anchor == nil || request.anchor == props.positionAnchor.map(UnitPoint.init(spec:)) { return }
|
|
212
|
+
if Self.positionServes(request, props: props) { return }
|
|
203
213
|
proxy.scrollTo(request.id, anchor: request.anchor)
|
|
204
214
|
}
|
|
205
215
|
|
|
216
|
+
/// On its own axes, at its own anchor, the position binding scrolls this view alone; else the proxy, which scrolls every scroll view around the target.
|
|
217
|
+
static func positionServes(_ request: ScrollRequest, props: ScrollViewProps) -> Bool {
|
|
218
|
+
let ownAxes = request.axes == props.axes && props.axes != "both"
|
|
219
|
+
return props.reportsPosition && ownAxes && (request.anchor == nil || request.anchor == props.positionAnchor.map(UnitPoint.init(spec:)))
|
|
220
|
+
}
|
|
221
|
+
|
|
206
222
|
/// Tells the app the target at the anchor, once per target, after the
|
|
207
223
|
/// pass that found it: the app answers synchronously, with a pass of its
|
|
208
224
|
/// own, which must not land in the middle of SwiftUI's update (as
|
|
@@ -214,6 +230,19 @@ struct ScrollViewElement: View {
|
|
|
214
230
|
Task { @MainActor in app?.dispatch(.scrollPosition(id)) }
|
|
215
231
|
}
|
|
216
232
|
|
|
233
|
+
/// Reports where a scroll settled, and lets go of the position: the app
|
|
234
|
+
/// may answer by changing the content around the target (Amindia's
|
|
235
|
+
/// calendar loads the weeks either side of the day it hears of) and
|
|
236
|
+
/// asking for the target again. Held, the position would have to let go
|
|
237
|
+
/// then and take the target back a pass later, and the pass between would
|
|
238
|
+
/// draw the new content at the old offset (a frame of the wrong week).
|
|
239
|
+
/// Let go now, nothing moves, and the request lands with the content.
|
|
240
|
+
private func reportSettled(_ id: Int?) {
|
|
241
|
+
guard let id else { return }
|
|
242
|
+
report(id)
|
|
243
|
+
if position == id { position = nil }
|
|
244
|
+
}
|
|
245
|
+
|
|
217
246
|
/// Whether this OS reports the settled position (`reportingSettled`) rather than the binding's every change.
|
|
218
247
|
static var reportsSettled: Bool {
|
|
219
248
|
#if !canImport(FoundationBridge)
|
|
@@ -238,7 +267,7 @@ struct ScrollViewElement: View {
|
|
|
238
267
|
}
|
|
239
268
|
.onScrollPhaseChange { old, phase in
|
|
240
269
|
idle = phase == .idle
|
|
241
|
-
if idle, old != .idle {
|
|
270
|
+
if idle, old != .idle { reportSettled(Self.target(at: anchor, among: visible)) }
|
|
242
271
|
})
|
|
243
272
|
}
|
|
244
273
|
#endif
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/wasm/SwiftBrowserNative.wasm
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 49330000 bytes
|
|
4
|
+
sha256: e1e3caa6b59f0db479d22e2969623ed0609ecda85225d254b534cf952a6ca929
|