@webview-native-ui/engine 0.0.6 → 0.0.8
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/README.md +19 -12
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/native/session.d.ts +5 -0
- package/dist/native/session.js +125 -16
- package/dist/native/updates.d.ts +16 -0
- package/dist/native/updates.js +108 -0
- package/dist/native/values.d.ts +5 -0
- package/dist/native/values.js +27 -0
- package/dist/projection/surface.d.ts +35 -0
- package/dist/projection/surface.js +81 -0
- package/dist/projection/surfaces.d.ts +20 -0
- package/dist/projection/surfaces.js +116 -0
- package/docs/README.md +70 -0
- package/docs/advanced/README.md +20 -0
- package/docs/advanced/android-placement.md +48 -0
- package/docs/advanced/native-handoff.md +89 -0
- package/docs/advanced/renderer.md +148 -0
- package/docs/advanced/update-queue.md +58 -0
- package/docs/advanced/web-projection.md +88 -0
- package/docs/assets/ios-native-capture-comparison.png +0 -0
- package/docs/concepts.md +97 -0
- package/docs/configuration/README.md +29 -0
- package/docs/configuration/capture.md +27 -0
- package/docs/configuration/events.md +35 -0
- package/docs/configuration/ionic-overlays.md +65 -0
- package/docs/configuration/values.md +125 -0
- package/docs/cordova.md +1 -1
- package/docs/{capacitor-plugin.md → getting-started/capacitor.md} +45 -47
- package/docs/{cordova-plugin.md → getting-started/cordova.md} +32 -15
- package/docs/getting-started/initialization.md +79 -0
- package/docs/maintenance.md +38 -8
- package/docs/{projection-containers.md → reference/containers.md} +6 -2
- package/docs/reference/platforms.md +137 -0
- package/docs/reference/projection.md +134 -0
- package/docs/reference/state.md +39 -0
- package/ios/Sources/WebViewNativeUIEngine/ClippedView.swift +12 -12
- package/ios/Sources/WebViewNativeUIEngine/CoveredSnapshots.swift +68 -7
- package/ios/Sources/WebViewNativeUIEngine/Frame.swift +10 -10
- package/ios/Sources/WebViewNativeUIEngine/NativeUIProjection.swift +74 -39
- package/ios/Sources/WebViewNativeUIEngine/Resources/native-ui-engine.js +6 -6
- package/ios/Sources/WebViewNativeUIEngine/ScrollBindings.swift +2 -0
- package/ios/Sources/WebViewNativeUIEngine/ScrollTracker.swift +9 -7
- package/package.json +9 -4
- package/docs/projection.md +0 -368
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
/// Keeps native content at full size while clipping hit testing and visible pixels.
|
|
3
3
|
public final class NativeUIClippedView: UIView {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
public let content: UIView
|
|
5
|
+
public init(content: UIView) { self.content = content; super.init(frame: .zero); addSubview(content) }
|
|
6
|
+
@available(*, unavailable) required init?(coder: NSCoder) { fatalError() }
|
|
7
|
+
public func place(_ frame: CGRect, clip: CGRect? = nil) {
|
|
8
|
+
clipsToBounds = clip != nil
|
|
9
|
+
let visible = clip.map { frame.intersection($0) } ?? frame
|
|
10
|
+
isHidden = visible.isNull || visible.isEmpty
|
|
11
|
+
guard !isHidden else { return }
|
|
12
|
+
if self.frame != visible { self.frame = visible }
|
|
13
|
+
let local = CGRect(x: frame.minX - visible.minX, y: frame.minY - visible.minY, width: frame.width, height: frame.height)
|
|
14
|
+
if content.frame != local { content.frame = local }
|
|
15
|
+
}
|
|
16
16
|
}
|
|
@@ -27,6 +27,66 @@ public final class NativeUICoveredSnapshots {
|
|
|
27
27
|
private var observer: SnapshotTouchObserver?
|
|
28
28
|
private let directory = FileManager.default.temporaryDirectory.appendingPathComponent("native-ui-snapshots-\(UUID().uuidString)")
|
|
29
29
|
public private(set) var coveringToken: String?
|
|
30
|
+
/// Dispatch the renderer's existing ordered image-handoff transport on the main thread.
|
|
31
|
+
/// The renderer supplies eligible native bounds and the complete views that may be hidden.
|
|
32
|
+
public func handle(_ request: [String: Any], in webView: UIView,
|
|
33
|
+
frames: @escaping (Set<String>, Int) -> [String: CGRect],
|
|
34
|
+
views: (Set<String>) -> [UIView]?, complete: @escaping ([String: Any]) -> Void) {
|
|
35
|
+
let token = request["token"] as? String ?? ""
|
|
36
|
+
switch request["action"] as? String {
|
|
37
|
+
case "prepare":
|
|
38
|
+
guard let ids = request["ids"] as? [String], !ids.isEmpty, !ids.contains(""), Set(ids).count == ids.count,
|
|
39
|
+
let revision = request["revision"] as? Int,
|
|
40
|
+
let width = request["viewportWidth"] as? Double, width.isFinite, width > 0 else { complete([:]); return }
|
|
41
|
+
let expected = Set(ids)
|
|
42
|
+
let firstFrames = frames(expected, revision)
|
|
43
|
+
guard Set(firstFrames.keys) == expected else { complete([:]); return }
|
|
44
|
+
var initial: [String: CGRect]? = firstFrames
|
|
45
|
+
prepare(frames: {
|
|
46
|
+
let measured = initial ?? frames(expected, revision)
|
|
47
|
+
initial = nil
|
|
48
|
+
return Set(measured.keys) == expected ? measured : [:]
|
|
49
|
+
}, in: webView, viewportWidth: width, complete: complete)
|
|
50
|
+
case "cover":
|
|
51
|
+
let ids = identifiers(for: token)
|
|
52
|
+
let destination = request["parts"] == nil ? nil : projectionFrames(request, in: webView)
|
|
53
|
+
guard !ids.isEmpty, let selected = views(ids), !selected.isEmpty,
|
|
54
|
+
request["parts"] == nil || destination != nil else { complete(["shown": false]); return }
|
|
55
|
+
var seen = Set<ObjectIdentifier>()
|
|
56
|
+
complete(["shown": cover(token, in: webView, views: selected.filter { seen.insert(ObjectIdentifier($0)).inserted },
|
|
57
|
+
transient: request["transient"] as? Bool == true, frames: destination)])
|
|
58
|
+
case "restore":
|
|
59
|
+
guard let destination = projectionFrames(request, in: webView) else { complete(["shown": false]); return }
|
|
60
|
+
complete(["shown": restore(in: webView, token: token, frames: destination)])
|
|
61
|
+
case "painted", "restored":
|
|
62
|
+
retireCopy(token, entry: request["action"] as? String == "painted")
|
|
63
|
+
complete([:])
|
|
64
|
+
case "release": release(token); complete([:])
|
|
65
|
+
case "reset": reset(); complete([:])
|
|
66
|
+
default: complete([:])
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Convert Web viewport CSS pixels to native points, rejecting partial or malformed destinations.
|
|
71
|
+
func projectionFrames(_ request: [String: Any], in webView: UIView) -> [String: CGRect]? {
|
|
72
|
+
guard let token = request["token"] as? String,
|
|
73
|
+
let width = request["viewportWidth"] as? Double, width.isFinite, width > 0,
|
|
74
|
+
webView.bounds.width > 0, let parts = request["parts"] as? [[String: Any]], !parts.isEmpty else { return nil }
|
|
75
|
+
let scale = webView.bounds.width / width
|
|
76
|
+
var result: [String: CGRect] = [:]
|
|
77
|
+
for part in parts {
|
|
78
|
+
guard let ids = part["ids"] as? [String], !ids.isEmpty,
|
|
79
|
+
let x = part["x"] as? Double, let y = part["y"] as? Double,
|
|
80
|
+
let w = part["width"] as? Double, let h = part["height"] as? Double,
|
|
81
|
+
[x, y, w, h, x * scale, y * scale, w * scale, h * scale].allSatisfy({ $0.isFinite }), w > 0, h > 0 else { return nil }
|
|
82
|
+
for id in ids {
|
|
83
|
+
guard !id.isEmpty, result[id] == nil else { return nil }
|
|
84
|
+
result[id] = CGRect(x: x * scale, y: y * scale, width: w * scale, height: h * scale)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return !result.isEmpty && Set(result.keys) == identifiers(for: token) ? result : nil
|
|
88
|
+
}
|
|
89
|
+
|
|
30
90
|
public var covering: Bool { coveringToken != nil }
|
|
31
91
|
|
|
32
92
|
public func observe(_ window: UIWindow, changed: @escaping (Bool) -> Void) {
|
|
@@ -46,7 +106,7 @@ public final class NativeUICoveredSnapshots {
|
|
|
46
106
|
// Gesture release can keep changing SwiftUI button bounds after touchesEnded.
|
|
47
107
|
// Wait off the presentation path for unchanged rendered geometry, not a guessed delay.
|
|
48
108
|
public func prepare(frames: @escaping () -> [String: CGRect], in webView: UIView, viewportWidth: CGFloat,
|
|
49
|
-
|
|
109
|
+
complete: @escaping ([String: Any]) -> Void) {
|
|
50
110
|
let stamp = generation
|
|
51
111
|
let start = CACurrentMediaTime()
|
|
52
112
|
func sample(_ previous: [String: CGRect], _ stable: Int) {
|
|
@@ -63,7 +123,7 @@ public final class NativeUICoveredSnapshots {
|
|
|
63
123
|
}
|
|
64
124
|
|
|
65
125
|
private func capture(frames: [String: CGRect], in webView: UIView, viewportWidth: CGFloat,
|
|
66
|
-
|
|
126
|
+
complete: @escaping ([String: Any]) -> Void) {
|
|
67
127
|
guard !touching, let window = webView.window, !frames.isEmpty,
|
|
68
128
|
viewportWidth > 0, webView.bounds.width > 0 else { complete([:]); return }
|
|
69
129
|
let stamp = generation
|
|
@@ -88,8 +148,9 @@ public final class NativeUICoveredSnapshots {
|
|
|
88
148
|
guard let space = CGColorSpace(name: CGColorSpace.extendedDisplayP3),
|
|
89
149
|
let outputSpace = CGColorSpace(name: CGColorSpace.displayP3),
|
|
90
150
|
let context = CGContext(data: nil, width: Int(bounds.width * scale), height: Int(bounds.height * scale),
|
|
91
|
-
|
|
92
|
-
|
|
151
|
+
bitsPerComponent: 16, bytesPerRow: 0, space: space,
|
|
152
|
+
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue |
|
|
153
|
+
CGBitmapInfo.floatComponents.rawValue | CGBitmapInfo.byteOrder16Little.rawValue)
|
|
93
154
|
else { complete([:]); return }
|
|
94
155
|
context.translateBy(x: 0, y: bounds.height * scale)
|
|
95
156
|
context.scaleBy(x: scale, y: -scale)
|
|
@@ -116,12 +177,12 @@ public final class NativeUICoveredSnapshots {
|
|
|
116
177
|
for (index, crop) in crops.enumerated() {
|
|
117
178
|
guard let pixels = crop.image.cgImage,
|
|
118
179
|
let png = imageContext.pngRepresentation(of: CIImage(cgImage: pixels), format: .RGBA16,
|
|
119
|
-
|
|
180
|
+
colorSpace: outputSpace, options: [:]) else { throw CocoaError(.fileWriteUnknown) }
|
|
120
181
|
// Native entry/return copies must use the same encoded pixels as Web,
|
|
121
182
|
// including gamut clipping performed by integer PNG conversion.
|
|
122
183
|
guard let source = CGImageSourceCreateWithData(png as CFData, nil),
|
|
123
184
|
let decoded = CGImageSourceCreateImageAtIndex(source, 0,
|
|
124
|
-
|
|
185
|
+
[kCGImageSourceShouldCacheImmediately: true] as CFDictionary)
|
|
125
186
|
else { throw CocoaError(.fileWriteUnknown) }
|
|
126
187
|
let image = UIImage(cgImage: decoded, scale: scale, orientation: .up)
|
|
127
188
|
let file = directory.appendingPathComponent("\(token)-\(index).png")
|
|
@@ -238,7 +299,7 @@ public final class NativeUICoveredSnapshots {
|
|
|
238
299
|
}
|
|
239
300
|
}
|
|
240
301
|
|
|
241
|
-
|
|
302
|
+
// Observes the start of interaction without recognizing or delaying the app's gestures.
|
|
242
303
|
private final class SnapshotTouchObserver: UIGestureRecognizer {
|
|
243
304
|
private let changed: (Bool) -> Void
|
|
244
305
|
private var touches = Set<UITouch>()
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import CoreGraphics
|
|
2
2
|
public struct NativeUIFrame: Codable, Equatable {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
public let x: Double
|
|
4
|
+
public let y: Double
|
|
5
|
+
public let width: Double
|
|
6
|
+
public let height: Double
|
|
7
|
+
public init(x: Double, y: Double, width: Double, height: Double) { self.x = x; self.y = y; self.width = width; self.height = height }
|
|
8
|
+
public var rect: CGRect { CGRect(x: x, y: y, width: width, height: height) }
|
|
9
|
+
public var isValid: Bool { [x, y, width, height].allSatisfy(\.isFinite) && width > 0 && height > 0 }
|
|
10
10
|
}
|
|
11
11
|
public struct NativeUIScrollNode: Decodable {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
public let id: String
|
|
13
|
+
public let scroll: NativeUIScrollPlacement?
|
|
14
|
+
public init(id: String, scroll: NativeUIScrollPlacement?) { self.id = id; self.scroll = scroll }
|
|
15
15
|
}
|
|
@@ -7,6 +7,16 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
7
7
|
public enum Runtime: String { case capacitor, cordova }
|
|
8
8
|
public enum FailedFallback: String { case web, native }
|
|
9
9
|
|
|
10
|
+
public struct ValueBinding {
|
|
11
|
+
public let property: String?
|
|
12
|
+
public init(property: String? = nil) { self.property = property }
|
|
13
|
+
fileprivate var configuration: [String: Any] {
|
|
14
|
+
var value: [String: Any] = [:]
|
|
15
|
+
if let property { value["property"] = property }
|
|
16
|
+
return value
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
10
20
|
public struct ReceiveListeners {
|
|
11
21
|
public struct Projection {
|
|
12
22
|
public let native: [String]
|
|
@@ -46,6 +56,7 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
46
56
|
private let origins: Set<String>
|
|
47
57
|
private let allowedOriginsJSON: String
|
|
48
58
|
private let canCapture: () -> Bool
|
|
59
|
+
private let readValues: (() -> [String: Any])?
|
|
49
60
|
private let runtime: Runtime
|
|
50
61
|
private let receiveListeners: ReceiveListeners
|
|
51
62
|
private let notificationLock = NSLock()
|
|
@@ -67,34 +78,44 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
67
78
|
private var captured: [String: [String: UIView]] = [:]
|
|
68
79
|
|
|
69
80
|
public convenience init(webView: WKWebView?, plugin: String, projectionSelector: String,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
receiveListeners: ReceiveListeners = .init(),
|
|
82
|
+
allowedOrigins: Set<String> = ["capacitor://localhost", "app://localhost", "https://localhost", "http://localhost"],
|
|
83
|
+
failedFallback: FailedFallback = .web, runtime: Runtime = .capacitor,
|
|
84
|
+
captureDelayMs: Double = 50,
|
|
85
|
+
values: [String: ValueBinding] = [:], readValues: (() -> [String: Any])? = nil,
|
|
86
|
+
canCapture: @escaping () -> Bool = { true }, view: @escaping () -> UIView?) throws {
|
|
75
87
|
try self.init(webView: webView, plugin: plugin, projectionSelector: projectionSelector,
|
|
76
88
|
receiveListeners: receiveListeners, allowedOrigins: allowedOrigins, failedFallback: failedFallback, runtime: runtime,
|
|
77
|
-
captureDelayMs: captureDelayMs,
|
|
89
|
+
captureDelayMs: captureDelayMs, values: values, readValues: readValues, canCapture: canCapture,
|
|
90
|
+
snapshots: NativeUICoveredSnapshots(), view: view)
|
|
78
91
|
}
|
|
79
92
|
init(webView: WKWebView?, plugin: String, projectionSelector: String,
|
|
80
93
|
receiveListeners: ReceiveListeners = .init(),
|
|
81
94
|
allowedOrigins: Set<String> = ["capacitor://localhost", "app://localhost", "https://localhost", "http://localhost"],
|
|
82
95
|
failedFallback: FailedFallback = .web, runtime: Runtime = .capacitor,
|
|
83
96
|
captureDelayMs: Double = 50,
|
|
97
|
+
values: [String: ValueBinding] = [:], readValues: (() -> [String: Any])? = nil,
|
|
84
98
|
canCapture: @escaping () -> Bool = { true }, snapshots: NativeUICoveredSnapshots,
|
|
85
99
|
view: @escaping () -> UIView?) throws {
|
|
100
|
+
// JSONSerialization produces valid UTF-8.
|
|
101
|
+
// swiftlint:disable:next force_unwrapping
|
|
86
102
|
self.allowedOriginsJSON = String(data: try JSONSerialization.data(withJSONObject: Array(allowedOrigins)), encoding: .utf8)!
|
|
87
103
|
self.runtime = runtime
|
|
88
104
|
self.snapshots = snapshots
|
|
89
105
|
self.receiveListeners = receiveListeners
|
|
106
|
+
self.readValues = readValues
|
|
90
107
|
guard let webView else { throw ProjectionError.missingWebView }
|
|
91
108
|
self.webView = webView; self.views = { view().map { ["view": $0] } ?? [:] }; self.origins = allowedOrigins; self.canCapture = canCapture
|
|
92
109
|
super.init()
|
|
93
110
|
precondition(Thread.isMainThread)
|
|
94
111
|
guard captureDelayMs.isFinite, captureDelayMs >= 0, captureDelayMs <= 2147483647,
|
|
95
112
|
!projectionSelector.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { throw ProjectionError.invalidConfiguration }
|
|
96
|
-
|
|
97
|
-
"captureDelayMs": captureDelayMs, "receiveListeners": receiveListeners.configuration,
|
|
113
|
+
var config: [String: Any] = ["id": id, "plugin": plugin, "projectionSelector": projectionSelector,
|
|
114
|
+
"captureDelayMs": captureDelayMs, "receiveListeners": receiveListeners.configuration,
|
|
115
|
+
"failedFallback": failedFallback.rawValue, "runtime": runtime.rawValue]
|
|
116
|
+
if readValues != nil { config["values"] = values.mapValues { $0.configuration } }
|
|
117
|
+
// JSONSerialization produces valid UTF-8.
|
|
118
|
+
// swiftlint:disable:next force_unwrapping
|
|
98
119
|
let json = String(data: try JSONSerialization.data(withJSONObject: config), encoding: .utf8)!
|
|
99
120
|
let allowed = allowedOriginsJSON
|
|
100
121
|
let runtime = try Self.runtime()
|
|
@@ -110,8 +131,8 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
110
131
|
public func receive(_ eventName: String, data: [String: Any]? = nil) {
|
|
111
132
|
guard receiveListeners.match.allSatisfy({ key, expected in
|
|
112
133
|
guard let actual = data?[key] else { return false }
|
|
113
|
-
if let
|
|
114
|
-
return CFGetTypeID(
|
|
134
|
+
if let actualNumber = actual as? NSNumber, let expectedNumber = expected as? NSNumber {
|
|
135
|
+
return CFGetTypeID(actualNumber) == CFGetTypeID(expectedNumber) && actualNumber == expectedNumber
|
|
115
136
|
}
|
|
116
137
|
return (actual as? String).map { $0 == expected as? String } ?? false
|
|
117
138
|
}) else { return }
|
|
@@ -162,21 +183,11 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
162
183
|
self.reply(key, value)
|
|
163
184
|
}
|
|
164
185
|
let token = request["token"] as? String ?? ""
|
|
165
|
-
func projectionFrames() -> [String: CGRect]? {
|
|
166
|
-
guard let width = request["viewportWidth"] as? Double, width.isFinite, width > 0,
|
|
167
|
-
let parts = request["parts"] as? [[String: Any]] else { return nil }
|
|
168
|
-
var frames: [String: CGRect] = [:]
|
|
169
|
-
let scale = webView.bounds.width / width
|
|
170
|
-
for part in parts {
|
|
171
|
-
guard let ids = part["ids"] as? [String], let x = part["x"] as? Double, let y = part["y"] as? Double,
|
|
172
|
-
let w = part["width"] as? Double, let h = part["height"] as? Double,
|
|
173
|
-
[x,y,w,h].allSatisfy({ $0.isFinite }), w > 0, h > 0 else { return nil }
|
|
174
|
-
for id in ids { frames[id] = CGRect(x: x*scale, y: y*scale, width: w*scale, height: h*scale) }
|
|
175
|
-
}
|
|
176
|
-
guard Set(frames.keys) == snapshots.identifiers(for: token), !frames.isEmpty else { return nil }
|
|
177
|
-
return frames
|
|
178
|
-
}
|
|
179
186
|
switch request["action"] as? String {
|
|
187
|
+
case "values":
|
|
188
|
+
let values = readValues?() ?? [:]
|
|
189
|
+
guard JSONSerialization.isValidJSONObject(values) else { self.reply(key, [:], error: "Native values must be JSON values"); return }
|
|
190
|
+
complete(["values": values])
|
|
180
191
|
case "connect":
|
|
181
192
|
if !connected { destination = (views().values.contains(where: { !$0.isHidden }) ? "native" : "none"); connected = true }
|
|
182
193
|
complete(["destination": recordedDestination ?? destination])
|
|
@@ -195,11 +206,19 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
195
206
|
guard !current.isEmpty, current.values.allSatisfy({ $0.layer.mask == nil }) else { complete(["tracked": false]); return }
|
|
196
207
|
let nodes = current.map { id, view -> NativeUIScrollNode in
|
|
197
208
|
let frame = view.convert(view.bounds, to: webView)
|
|
198
|
-
return NativeUIScrollNode(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
209
|
+
return NativeUIScrollNode(
|
|
210
|
+
id: id,
|
|
211
|
+
scroll: NativeUIScrollPlacement(
|
|
212
|
+
id: placement.id, offsetX: placement.offsetX, offsetY: placement.offsetY,
|
|
213
|
+
viewport: placement.viewport, clip: placement.clip,
|
|
214
|
+
contentWidth: placement.contentWidth, contentHeight: placement.contentHeight,
|
|
215
|
+
frame: NativeUIFrame(
|
|
216
|
+
x: frame.minX/scale-placement.viewport.x+placement.offsetX,
|
|
217
|
+
y: frame.minY/scale-placement.viewport.y+placement.offsetY,
|
|
218
|
+
width: frame.width/scale, height: frame.height/scale
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
)
|
|
203
222
|
}
|
|
204
223
|
let rejected = scrolling.replace(nodes, in: webView, scale: scale) { [weak self, weak webView] id, frame, clip in
|
|
205
224
|
guard let self, let webView, self.visible, !self.snapshots.hidesNativeControls,
|
|
@@ -216,7 +235,8 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
216
235
|
}
|
|
217
236
|
complete(["tracked": rejected.isEmpty])
|
|
218
237
|
case "prepare":
|
|
219
|
-
guard visible, canCapture(), let ids = request["ids"] as? [String],
|
|
238
|
+
guard visible, canCapture(), let ids = request["ids"] as? [String],
|
|
239
|
+
let width = request["viewportWidth"] as? Double, width.isFinite, width > 0,
|
|
220
240
|
let window = webView.window else { complete([:]); return }
|
|
221
241
|
let selected = views().filter { ids.contains($0.key) }
|
|
222
242
|
guard selected.count == ids.count else { complete([:]); return }
|
|
@@ -235,7 +255,11 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
235
255
|
guard let ids = part["ids"] as? [String], let x = part["x"] as? CGFloat, let y = part["y"] as? CGFloat,
|
|
236
256
|
let w = part["width"] as? CGFloat, let h = part["height"] as? CGFloat else { continue }
|
|
237
257
|
let image = CGRect(x: x*scale, y: y*scale, width: w*scale, height: h*scale)
|
|
238
|
-
for id in ids {
|
|
258
|
+
for id in ids {
|
|
259
|
+
if let view = selected[id] {
|
|
260
|
+
entries[id] = Anchor(native: view.convert(view.bounds, to: webView), image: image)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
239
263
|
}
|
|
240
264
|
self.anchors[token] = entries
|
|
241
265
|
}
|
|
@@ -244,27 +268,33 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
244
268
|
case "cover":
|
|
245
269
|
let selected = captured[token] ?? [:], current = views()
|
|
246
270
|
let valid = visible && canCapture() && !selected.isEmpty && selected.allSatisfy { current[$0.key] === $0.value }
|
|
247
|
-
let frames = request["parts"] == nil ? nil : projectionFrames()
|
|
271
|
+
let frames = request["parts"] == nil ? nil : snapshots.projectionFrames(request, in: webView)
|
|
248
272
|
guard request["parts"] == nil || frames != nil else { complete(["shown": false]); return }
|
|
249
273
|
restoreAccepted = true
|
|
250
|
-
complete(["shown": valid && snapshots.cover(
|
|
274
|
+
complete(["shown": valid && snapshots.cover(
|
|
275
|
+
token, in: webView,
|
|
276
|
+
views: Array(Dictionary(grouping: selected.values, by: { ObjectIdentifier($0) }).values.compactMap { $0.first }),
|
|
277
|
+
transient: true, frames: frames
|
|
278
|
+
)])
|
|
251
279
|
case "restore":
|
|
252
280
|
restoreAccepted = false
|
|
253
|
-
guard let frames = projectionFrames() else { complete(["shown": false]); return }
|
|
281
|
+
guard let frames = snapshots.projectionFrames(request, in: webView) else { complete(["shown": false]); return }
|
|
254
282
|
let current = views()
|
|
255
283
|
// Preserve renderer-owned constraints. Translation follows the corresponding DOM's movement.
|
|
256
284
|
for (id, frame) in frames {
|
|
257
|
-
guard let view = current[id], captured[token]?[id] === view, let anchor = anchors[token]?[id]
|
|
285
|
+
guard let view = current[id], captured[token]?[id] === view, let anchor = anchors[token]?[id]
|
|
286
|
+
else { complete(["shown": false]); return }
|
|
258
287
|
let old = view.convert(view.bounds, to: webView)
|
|
259
288
|
guard abs(old.width-anchor.native.width) < 0.1, abs(old.height-anchor.native.height) < 0.1,
|
|
260
|
-
abs(frame.width-anchor.image.width) < 0.1, abs(frame.height-anchor.image.height) < 0.1
|
|
289
|
+
abs(frame.width-anchor.image.width) < 0.1, abs(frame.height-anchor.image.height) < 0.1
|
|
290
|
+
else { complete(["shown": false]); return }
|
|
261
291
|
}
|
|
262
292
|
for (id, frame) in frames {
|
|
263
293
|
guard let view = current[id], let parent = view.superview, let anchor = anchors[token]?[id] else { continue }
|
|
264
294
|
let old = view.convert(view.bounds, to: webView)
|
|
265
295
|
let from = parent.convert(CGPoint(x: old.midX, y: old.midY), from: webView)
|
|
266
296
|
let to = parent.convert(CGPoint(x: anchor.native.midX+frame.minX-anchor.image.minX,
|
|
267
|
-
|
|
297
|
+
y: anchor.native.midY+frame.minY-anchor.image.minY), from: webView)
|
|
268
298
|
view.transform.tx += to.x-from.x; view.transform.ty += to.y-from.y
|
|
269
299
|
}
|
|
270
300
|
restoreAccepted = snapshots.restore(in: webView, token: token, frames: frames)
|
|
@@ -301,8 +331,8 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
301
331
|
guard let data = try? JSONSerialization.data(withJSONObject: values), let json = String(data: data, encoding: .utf8) else { return }
|
|
302
332
|
evaluate("globalThis.WebViewNativeUIEngineRuntime?.receive(...\(json))")
|
|
303
333
|
}
|
|
304
|
-
/// Call with the plugin's teardown. Does not destroy the renderer's views or DOM.
|
|
305
334
|
deinit { destroy() }
|
|
335
|
+
/// Call with the plugin's teardown. Does not destroy the renderer's views or DOM.
|
|
306
336
|
public func destroy() {
|
|
307
337
|
guard !closed else { return }
|
|
308
338
|
closed = true
|
|
@@ -313,8 +343,13 @@ public final class NativeUIProjection: NSObject, WKScriptMessageHandler {
|
|
|
313
343
|
controller.removeAllUserScripts()
|
|
314
344
|
remaining.forEach { controller.addUserScript($0) }
|
|
315
345
|
}
|
|
346
|
+
// A successful hide notification can precede its Web acknowledgement and teardown.
|
|
347
|
+
let keepHidden = (recordedDestination ?? destination) == "none"
|
|
348
|
+
let visibility = keepHidden
|
|
349
|
+
? (Array(views().values) + hiddenByProjection + captured.values.flatMap { $0.values }).map { ($0, $0.isHidden) }
|
|
350
|
+
: []
|
|
316
351
|
snapshots.reset(); resetScrolling(); captured.removeAll(); anchors.removeAll()
|
|
317
|
-
if
|
|
352
|
+
if keepHidden { visibility.forEach { $0.0.isHidden = $0.1 } } else { hiddenByProjection.forEach { $0.isHidden = false } }
|
|
318
353
|
hiddenByProjection.removeAll()
|
|
319
354
|
}
|
|
320
355
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
"use strict";var WebViewNativeUIEngineRuntime=(()=>{var
|
|
1
|
+
"use strict";var WebViewNativeUIEngineRuntime=(()=>{var Ge=Object.defineProperty;var ut=Object.getOwnPropertyDescriptor;var ft=Object.getOwnPropertyNames;var pt=Object.prototype.hasOwnProperty;var mt=(t,r)=>{for(var o in r)Ge(t,o,{get:r[o],enumerable:!0})},vt=(t,r,o,v)=>{if(r&&typeof r=="object"||typeof r=="function")for(let y of ft(r))!pt.call(t,y)&&y!==o&&Ge(t,y,{get:()=>r[y],enumerable:!(v=ut(r,y))||v.enumerable});return t};var ht=t=>vt(Ge({},"__esModule",{value:!0}),t);var Ot={};mt(Ot,{hide:()=>kt,notify:()=>Mt,receive:()=>xt,show:()=>Ht,start:()=>Ct,stop:()=>Rt});var tt=(t,r,o)=>{for(let[v,y]of Object.entries(r)){if(!/^[a-z][a-z0-9-]*$/.test(v))throw new TypeError("Native value keys must be lowercase attribute names");let f=(Object.hasOwn(o,v)?o[v]:void 0)?.property;if(f&&(!/^[a-zA-Z][\w]*$/.test(f)||/^on/i.test(f)||["innerHTML","outerHTML","textContent","innerText","style","constructor","prototype"].includes(f)))throw new TypeError("Native value binding requires a data property");let P=JSON.stringify(y);if(P===void 0)throw new TypeError("Native values must be JSON values");if(f){let p=t;JSON.stringify(p[f])!==P&&(p[f]=y)}else{let p=`data-native-ui-value-${v}`,M=typeof y=="string"?y:P;t.getAttribute(p)!==M&&t.setAttribute(p,M)}}};var yt=Symbol.for("webview-native-ui-engine.projection-placement");var Ue=t=>t?.[yt];var gt=(t,r)=>{if(t.matches("ion-toast, ion-menu"))return!1;let o=t;if(o.showBackdrop===!1)return!1;if(!t.matches("ion-modal"))return!0;let v=r??o.initialBreakpoint;return v===void 0||v>(o.backdropBreakpoint??0)},wt=Symbol.for("@webview-native-ui/engine/overlays/v1"),bt=t=>{let r=new Set,o=new Set,v=new Set,y=new WeakMap,m=new WeakSet,f=new Map,P=[],p={},M=new Map,x,j=g=>{for(let d of[...v])try{d(g)}catch(w){console.error("Native UI overlay listener failed",w)}},B=(g,d,w)=>{d==="willPresent"||d==="didPresent"?(m.delete(g),r.add(g)):d==="didDismiss"&&(m.add(g),r.delete(g),o.delete(g),y.delete(g));let c=w?.detail?.breakpoint;typeof c=="number"&&c>0&&y.set(g,c),j({element:g,phase:d,event:w})},k=(g=!1)=>{let d=!1;for(let w of r)(!w.isConnected||w.ownerDocument!==t||!P.some(({selector:c})=>w.matches(c)))&&(r.delete(w),o.delete(w),d=!0);for(let w of t.querySelectorAll(P.map(({selector:c})=>c).join(",")))!r.has(w)&&!m.has(w)&&(g||!w.matches("ion-popover"))&&(w.presented||w.classList.contains("show-menu"))&&(r.add(w),d=!0);d&&j({phase:"change"})};return{get active(){return r},subscribe(g){return v.add(g),()=>{v.delete(g)}},setNative(g,d){o.has(g)!==d&&(d?o.add(g):o.delete(g),j({element:g,phase:"change"}))},isExcluded(g){return!!p.exclude&&g.matches(p.exclude)},isNative(g){return o.has(g)},get stack(){let g=[...r].filter(w=>w.isConnected&&w.ownerDocument===t),d=w=>{let c=Number.parseFloat(t.defaultView.getComputedStyle(w).zIndex);return Number.isFinite(c)?c:w.overlayIndex??0};return g.sort((w,c)=>d(w)-d(c)),g},isCovered(g){let d=this.stack,w=d.reduce((c,W,R)=>W.contains(g)?R:c,-1);return d.some((c,W)=>{if(o.has(c)||p.exclude&&c.matches(p.exclude))return!1;let R=p.covers?.(c,g);return R!==void 0?R:W>w&&!c.contains(g)&&(c.matches("ion-menu")||gt(c,y.get(c)))})},enable(g,d){let w={...p,...d},c=[...g,...w.additional??[]];w.exclude&&t.querySelector(w.exclude);let W=new Map;for(let l of c){t.querySelector(l.selector);for(let[V,$]of Object.entries(l.events)){let G=W.get($);if(G&&G.phase!==V)throw new TypeError(`Overlay event "${$}" has conflicting phases`);W.set($,{phase:V,selector:G?`${G.selector}, ${l.selector}`:l.selector})}}p=w,P=c,M=W;for(let l of M.keys()){if(f.has(l))continue;let V=$=>{let G=M.get(l),ye=$.composedPath().find(J=>J instanceof t.defaultView.HTMLElement&&J.matches(G.selector));ye&&B(ye,G.phase,$)};t.addEventListener(l,V,!0),f.set(l,()=>t.removeEventListener(l,V,!0))}for(let[l,V]of f)M.has(l)||(V(),f.delete(l));let R=!x;x||(x=new MutationObserver(()=>k()),x.observe(t.documentElement,{childList:!0,subtree:!0}),t.addEventListener("nativeUIOverlayAdopted",l=>{let V=l.detail;V?.ownerDocument===t&&B(V,"willPresent",l)})),k(R),(R||d)&&j({phase:"change"})}}},nt=t=>{let r=t;return r[wt]??=bt(t)};function*Ne(t){let r=t;for(;r;){let o=r.getRootNode();r=r.assignedSlot??r.parentElement??(o instanceof ShadowRoot?o.host:null),r&&(yield r)}}var Et=({x:t,y:r,width:o,height:v})=>({x:t,y:r,width:o,height:v}),ot=t=>{let r=t.getBoundingClientRect(),o=getComputedStyle(t),v=parseFloat(o.borderLeftWidth)||0,y=parseFloat(o.borderTopWidth)||0;return{x:r.left+v,y:r.top+y,width:r.width-v-(parseFloat(o.borderRightWidth)||0),height:r.height-y-(parseFloat(o.borderBottomWidth)||0)}},Ke=(t,r,o)=>{let v=[t,...Ne(t)],y=v.indexOf(r);if(y<=0||r===t.ownerDocument.scrollingElement)return;let m=t.ownerDocument.defaultView;if(m.visualViewport&&(m.visualViewport.scale!==1||m.visualViewport.offsetLeft||m.visualViewport.offsetTop))return;let f=0,P=0,p=m.innerWidth,M=m.innerHeight;for(let[k,g]of v.entries()){let d=getComputedStyle(g);if(d.transform!=="none"&&!new DOMMatrixReadOnly(d.transform).isIdentity||d.zoom&&d.zoom!=="normal"&&Number(d.zoom)!==1||[d.translate,d.rotate,d.scale,d.perspective].some(R=>R&&R!=="none")||d.writingMode&&d.writingMode!=="horizontal-tb"||k<y&&/^(fixed|sticky)$/.test(d.position))return;if(k===0)continue;if(d.scrollbarGutter&&d.scrollbarGutter!=="auto")return;let w=/^(auto|scroll|hidden|clip)$/.test(d.overflowX),c=/^(auto|scroll|hidden|clip)$/.test(d.overflowY);if(k<y&&(w||c))return;let W=g===t.ownerDocument.scrollingElement;if(k>y&&((w||W)&&g.scrollWidth>g.clientWidth||(c||W)&&g.scrollHeight>g.clientHeight)||(w||c)&&[d.borderTopLeftRadius,d.borderTopRightRadius,d.borderBottomLeftRadius,d.borderBottomRightRadius].some(R=>parseFloat(R)>0)||d.clipPath&&d.clipPath!=="none"||d.maskImage&&d.maskImage!=="none")return;if(k>=y){let R=ot(g);w&&(f=Math.max(f,R.x),p=Math.min(p,R.x+R.width)),c&&(P=Math.max(P,R.y),M=Math.min(M,R.y+R.height))}}let x=getComputedStyle(r);if(!/^(auto|scroll)$/.test(x.overflowX)&&!/^(auto|scroll)$/.test(x.overflowY))return;let j=ot(r);if(p<=f||M<=P||!j.width||!j.height)return;let B=Et(t.getBoundingClientRect());return{id:o(r),offsetX:r.scrollLeft,offsetY:r.scrollTop,viewport:j,clip:{x:f,y:P,width:p-f,height:M-P},contentWidth:r.scrollWidth,contentHeight:r.scrollHeight,frame:{...B,x:B.x-j.x+r.scrollLeft,y:B.y-j.y+r.scrollTop}}};var it=t=>{let r=globalThis;if(r.Capacitor?.convertFileSrc)return r.Capacitor.convertFileSrc(t);if(!t.startsWith("file:"))return t;if(r.WkWebView?.convertFilePath)return r.WkWebView.convertFilePath(t);throw new Error("Native UI file URL requires a host resource handler")};var he=t=>new Promise((r,o)=>{let v=setTimeout(()=>o(new Error("Native UI bridge timed out")),5e3);t.then(r,o).finally(()=>clearTimeout(v))}),Xe=async t=>{try{return await he(t)}catch(r){throw t.then(o=>o.remove()).catch(()=>{}),r}};var Ye=async(t,r)=>{let o=new Map;for(let P of t.update??[])o.set(P,{updated:!0});for(let P of["native","web","none"])for(let p of t.projection?.[P]??[]){let M=o.get(p)??{updated:!1};if(M.destination&&M.destination!==P)throw new TypeError(`Projection event "${p}" has conflicting destinations`);o.set(p,{...M,destination:P})}let v=!1,y=[],m=async()=>{v=!0;let p=(await Promise.allSettled(y.splice(0).map(M=>Promise.resolve().then(()=>M.remove())))).find(M=>M.status==="rejected");if(p?.status==="rejected")throw p.reason},f=[...o].map(async([P,p])=>{let M=await Xe(Promise.resolve().then(()=>t.addListener(P,x=>{!v&&(!t.accepts||t.accepts(x))&&r(p.destination,p.updated)})));v?await M.remove():y.push(M)});try{return await Promise.all(f),{remove:m}}catch(P){throw await m().catch(()=>{}),P}};var xe=":is([data-native-ui-snapshot-source], [data-native-ui-snapshot-prepared], [data-native-ui-snapshot-content])",rt=`
|
|
2
2
|
@layer native-ui-projection {
|
|
3
|
-
${
|
|
4
|
-
${
|
|
5
|
-
${
|
|
3
|
+
${xe}, ${xe} *, ${xe}::part(native) { visibility: hidden !important; }
|
|
4
|
+
${xe}::before, ${xe}::after,
|
|
5
|
+
${xe} *::before, ${xe} *::after {
|
|
6
6
|
visibility: hidden !important;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
[data-native-ui-snapshot-visible] { opacity:1!important;overflow:visible!important; }
|
|
10
10
|
[data-native-ui-snapshot-visible][data-native-ui-snapshot-positioned] { position:relative!important; }
|
|
11
|
-
`,
|
|
11
|
+
`,st=`
|
|
12
12
|
@layer native-ui-projection {
|
|
13
13
|
:host([data-native-ui-snapshot-content]),
|
|
14
14
|
:host([data-native-ui-snapshot-content])::before,
|
|
@@ -19,4 +19,4 @@ ${je} *::before, ${je} *::after {
|
|
|
19
19
|
visibility: hidden !important;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
`;var Et=(t,i=!1)=>JSON.stringify(t.map(({control:r})=>[r.id,r.kind,r.placement,i?0:r.x,i?0:r.y,r.width,r.height,r.dark,r.rtl])),Pt=async(t,i,r)=>{let v=r.captureDelayMs??50;if(!Number.isFinite(v)||v<0||v>2147483647)throw new RangeError("captureDelayMs must be a finite, nonnegative timer interval");let h="native",d=t.element.ownerDocument,p=d.defaultView,T=Array.from(p.crypto.getRandomValues(new Uint32Array(4)),e=>e.toString(16)).join("-"),f=e=>e.isConnected&&e.ownerDocument===d,L=e=>!!e?.isConnected&&e.ownerDocument===d,C=new Map,j=new Set,B=e=>{j.delete(e),e.style.setProperty("display","none","important"),e.removeAttribute("data-native-ui-projection-image"),e.removeAttribute("src"),le()},S=i.send.bind(i),y="data-native-ui-snapshot",l=`${t.namespace}:sources-change`,g=new Set,c=new Set,D=new Set,x=new WeakMap,m=0,O=e=>JSON.stringify(e.map(o=>{x.has(o.scope)||x.set(o.scope,++m);let n=r.transient&&!r.opaqueUnderlay?o.scope.element.getBoundingClientRect():void 0,s=n?{...o,control:{...o.control,x:o.control.x-n.x,y:o.control.y-n.y}}:o;return[x.get(o.scope),Et([s],!!r.opaqueUnderlay)]})),A=new Map,N=e=>{let o=e.getRootNode();return o.nodeType===11&&"host"in o?o:d},oe=e=>{if(A.has(e))return;let o=d.createElement("style");o.setAttribute("data-native-ui-snapshot-base",""),o.textContent=rt+(e.nodeType===11?it:""),(e.nodeType===11?e:e.head).append(o),A.set(e,o)},F=e=>{let o=[...e.getAnimations({subtree:!0}),...[...se.get(e)??[]].flatMap(n=>n.shadowRoot?.getAnimations()??[])];for(let n of o)"transitionProperty"in n&&n.transitionProperty==="visibility"&&n.cancel()},se=new Map,Se=e=>{let o=se.get(e)??new Set;se.set(e,o);let n=e.hasAttribute("data-native-ui-snapshot-source")||e.hasAttribute("data-native-ui-snapshot-prepared"),s=P=>{if(!P.hasAttribute("data-native-ui-projection-node")){if(P.shadowRoot){o.add(P),oe(P.shadowRoot);for(let M of P.shadowRoot.children)s(M)}for(let M of P.children)s(M)}};s(e);for(let P of o)P.toggleAttribute("data-native-ui-snapshot-content",n);F(e)},W=()=>`${p.innerWidth}:${p.innerHeight}:${p.devicePixelRatio}`,Z=!1,ae=!1,J=0,me=0,R,U,b,q=!1,X=!1,we=0,Oe=0,ee=0,ve=0,z=0,be=-1,V=!1,te=!1,Y,le=()=>{let e=new Set(Y?.candidates.map(n=>n.scope.element));for(let[n,s]of C){let P=!V&&n.isConnected&&e.has(n);if(P&&(b||X||Z))continue;let M=P?2*Math.max(1,R?.scopes.filter(k=>k.element===n).length??0):0,H=Math.max(0,M-s.filter(k=>j.has(k)).length),I=s.filter(k=>j.has(k)||H-- >0?!0:(k.remove(),!1));I.length?C.set(n,I):C.delete(n)}let o=new Set([...Y?.candidates.map(n=>n.scope.element.getRootNode())??[],...b?.scopes.map(n=>n.element.getRootNode())??[],...R?.scopes.map(n=>n.element.getRootNode())??[],...[...j].map(n=>n.getRootNode()),...[...se.values()].flatMap(n=>[...n].map(s=>s.shadowRoot))]);for(let[n,s]of A)n.nodeType===11&&!o.has(n)&&(s.remove(),A.delete(n))},he=new Set,Ie=(e,o,n)=>{let s=()=>{he.delete(s)&&(S({action:e,token:o}).catch(()=>{}),e==="restored"&&le())};he.add(s),n&&!V?p.requestAnimationFrame(()=>p.requestAnimationFrame(s)):s()},de=new Set,xe=()=>{de.forEach(e=>D.delete(e)),de.clear()},He=(e,o=!1)=>{!e||e===R||e===b||(e.images.forEach(n=>{B(n)}),Ie("release",e.data.token,o))},Ee=e=>e.filter(o=>{if(!L(o.scope.element)||![o.element,...o.sources??[]].every(f))return!1;if(o.control.scroll){let n=o.element.getBoundingClientRect(),s=o.control.scroll.clip;if(n.right<=s.x||n.bottom<=s.y||n.left>=s.x+s.width||n.top>=s.y+s.height)return!1}return r.eligible?.(o)??!0}),qe=async()=>{if(ve=0,V||h!=="native"||te||q||b||r.blocked()||!Y||R?.revision===Y.revision&&be===z)return;let{revision:e,candidates:o}=Y,n=ee,s=z,P=W(),M=Ee(o);if(!M.length)return;te=!0;let H,I=!1,k=[];try{let re=!1,ie=S({action:"prepare",revision:r.captureRevision?.()??e,viewportWidth:p.innerWidth,ids:M.map(w=>w.control.id)});ie.then(w=>{re&&w.token&&S({action:"release",token:w.token}).catch(()=>{})}).catch(()=>{});try{H=await pe(ie)}finally{re=!0}if(!H.token||!H.parts?.length)return;let Ce=new Set(M.map(w=>w.control.id));if(H.parts.some(w=>!w.url.startsWith("file:")&&!/^\/__native_ui_engine__\/nativeUI[a-fA-F0-9]+\/[a-fA-F0-9-]+-[0-9]+\.png$/.test(w.url)||!w.ids.length||w.ids.some(G=>!Ce.has(G))||![w.x,w.y,w.width,w.height].every(Number.isFinite)||w.width<=0||w.height<=0)||new Set(H.parts.flatMap(w=>w.ids)).size!==Ce.size||H.parts.some(w=>new Set(w.ids.map(G=>M.find(Me=>Me.control.id===G).scope)).size!==1)||(await pe(Promise.all(H.parts.map(async w=>{let G=M.find(Ye=>w.ids.includes(Ye.control.id)).scope.element,Me=C.get(G);Me||(Me=[],C.set(G,Me));let fe=Me.find(Ye=>!j.has(Ye));return fe||(fe=d.createElement("img"),fe.setAttribute("data-native-ui-projection-node",""),Me.push(fe)),j.add(fe),k.push(fe),fe.src=ot(w.url),await fe.decode(),fe}))),V||h!=="native"||q||b||r.blocked()||ee!==n||W()!==P||Y?.revision!==e||M.some(w=>!L(w.scope.element)||![w.element,...w.sources??[]].every(f))))return;let Re=R,et={data:H,images:k,sources:Array.from(new Set(M.flatMap(w=>[w.element,...w.sources??[]]))),targets:H.parts.map(w=>M.find(G=>w.ids.includes(G.control.id)).element),scopes:H.parts.map(w=>M.find(G=>w.ids.includes(G.control.id)).scope),parents:H.parts.map(w=>M.find(G=>w.ids.includes(G.control.id)).scope.element.parentNode),frames:[],viewport:P,revision:e,layout:O(M)};try{if(!Ue(et))throw new Error("Projection destination is unavailable")}catch(w){Q();try{Ue(),R?.sources.forEach(G=>{D.add(G),de.add(G)})}catch{$()}throw w}R=et,xe(),R.sources.forEach(w=>{D.add(w),de.add(w)}),r.opaqueUnderlay&&S({action:"prepared",token:H.token}).catch(()=>{}),p.dispatchEvent(new Event(l)),be=s,I=!0,He(Re)}catch{}finally{I||k.forEach(re=>{B(re)}),H?.token&&!I&&S({action:"release",token:H.token}).catch(()=>{}),te=!1,Y&&(Y.revision!==e||z!==s)&&ue()}},ue=()=>{p.clearTimeout(ve),!V&&h==="native"&&!b&&!q&&!r.blocked()&&(ve=p.setTimeout(()=>{qe()},v))},Ae,a=(e,o)=>{if(o.some(s=>s.scope.element.ownerDocument!==d||[s.element,...s.sources??[]].some(P=>P.ownerDocument!==d)))throw new TypeError("All projection sources and fallback scopes must share one Document");if(r.blocked())return;!b&&R&&R.layout!==O(Ee(o))&&Le();let n=O(o);Ae!==n&&(Ae=n,z++,ee++),Y?.revision!==e&&ee++,Y={revision:e,candidates:o},le(),(R?.revision!==e||be!==z)&&ue()},u=e=>{!b&&R&&e&&Y?.candidates.some(o=>o.scrollElement===e&&R.sources.includes(o.element))&&Le(),b&&ke(),z++,ee++,ue()},E=await Be(i.listen(({active:e})=>{q=e,ee++,p.clearTimeout(ve),e||ue()})),_=new Set,ce=e=>{se.get(e)?.forEach(o=>o.removeAttribute("data-native-ui-snapshot-content")),_.delete(e)&&e.removeAttribute("data-native-ui-snapshot-prepared"),e.removeAttribute("data-native-ui-snapshot-visible"),e.removeAttribute(y),e.removeAttribute("data-native-ui-snapshot-positioned"),e.removeAttribute("data-native-ui-snapshot-source"),F(e),se.delete(e)},Q=()=>{me++,p.cancelAnimationFrame(J);for(let e of Fe.keys())e.style.setProperty("opacity","0","important");Fe.clear(),J=0,Z=!1,ae=!1,xe(),b?.sources.forEach(e=>{g.delete(e),c.delete(e)}),K.forEach(ce),K.clear(),A.forEach((e,o)=>{(V||o.nodeType===11&&!o.host.isConnected)&&(e.remove(),A.delete(o))})},$=(e=b,o=X)=>{if(b!==e)return;let n=new Set([b,R]);Q(),b=void 0,R=void 0,X=!1,p.clearTimeout(we),n.forEach(s=>He(s,o)),r.wake()},ne=()=>{if(!b)return;if(R!==b){$();return}let e=b;me++,p.cancelAnimationFrame(J),J=0,Z=ae=!1,e.sources.forEach(o=>{g.delete(o),c.delete(o)}),K.forEach(o=>o.removeAttribute("data-native-ui-snapshot-source")),Xe(e,!!r.opaqueUnderlay),b=void 0,X=!1,p.clearTimeout(we),Ie("restored",e.data.token,!0),e.sources.forEach(o=>{D.add(o),de.add(o)}),r.wake()},Pe=()=>{X&&ne(),he.forEach(e=>e())},De=e=>e.scopes.map(o=>L(o.element)?o.element:void 0),K=new Set,Xe=(e,o)=>{for(let n of K)n.toggleAttribute("data-native-ui-snapshot-visible",o),Se(n);e.images.forEach(n=>n.style.setProperty("opacity",o?"1":"0","important"))},Te=new Map,Fe=new Map,ke=()=>{let e=[];for(let[o,n]of Fe){let{target:s,frame:P}=n;if(!s.isConnected){o.remove();continue}let M=s.shadowRoot??s;o.parentNode!==M&&M.insertBefore(o,null);let H=s.getBoundingClientRect(),I=o.getBoundingClientRect(),k=parseFloat(o.style.width)||P.width,re=parseFloat(o.style.height)||P.height,ie=I.width/k||1,Ce=I.height/re||1,Re=n.scale??(n.scale={x:ie,y:Ce});e.push({element:o,left:(parseFloat(o.style.left)||0)+(H.x+P.x*ie/Re.x-I.x)/ie,top:(parseFloat(o.style.top)||0)+(H.y+P.y*Ce/Re.y-I.y)/Ce,width:P.width/Re.x,height:P.height/Re.y})}for(let{element:o,...n}of e)for(let[s,P]of Object.entries(n)){let M=`${P}px`;o.style.getPropertyValue(s)!==M&&o.style.setProperty(s,M,"important")}},Ue=(e=b??R)=>{if(!e||X)return!1;if(!e.sources.every(f)||De(e).some(n=>!n))return Le(),!1;let o=De(e);if(b){if(o.some(s=>!s?.isConnected||!A.has(N(s))))return $(b,!1),!1;let n=new Set;for(let[s,P]of e.targets.entries()){let M=Te.get(P),H=o[s];!M||!H?.isConnected||(H.setAttribute(y,M),H.setAttribute("data-native-ui-snapshot-source",""),n.add(H))}for(let s of K)n.has(s)||ce(s);return K.clear(),n.forEach(s=>K.add(s)),Xe(e,ae),!0}C.forEach(n=>n.forEach(s=>{e.images.includes(s)||(s.style.setProperty("display","none","important"),s.removeAttribute("data-native-ui-projection-image"))})),Te.clear(),Fe.clear(),K.forEach(ce),K.clear();for(let n of new Set(o)){if(!n)continue;K.add(n),oe(N(n));let s=o.flatMap((I,k)=>I===n?[k]:[]),P=`${T}-${s[0]}`;n.setAttribute(y,P),n!==e.targets[s[0]]&&(n.setAttribute("data-native-ui-snapshot-prepared",""),_.add(n)),n.toggleAttribute("data-native-ui-snapshot-visible",!!r.opaqueUnderlay),Se(n);let M=n.getBoundingClientRect();n.toggleAttribute("data-native-ui-snapshot-positioned",p.getComputedStyle(n).position==="static");let H=n.shadowRoot??n;for(let I of[...s].reverse()){let k=e.images[I],re=e.data.parts[I],ie=e.frames[I]??{x:r.opaqueUnderlay?0:re.x-M.x,y:r.opaqueUnderlay?0:re.y-M.y,width:re.width,height:re.height};e.frames[I]=ie,Te.set(e.targets[I],P),k.inert=!0,k.setAttribute("aria-hidden","true"),k.setAttribute("data-native-ui-projection-image",P),k.style.cssText="all:initial!important;position:absolute!important;display:block!important;visibility:visible!important;pointer-events:none!important;image-rendering:pixelated!important;will-change:opacity!important;opacity:0!important;",k.style.setProperty("width",`${ie.width}px`,"important"),k.style.setProperty("height",`${ie.height}px`,"important"),k.style.setProperty("left","0px","important"),k.style.setProperty("top","0px","important"),k.style.setProperty("opacity",r.opaqueUnderlay?"1":"0","important"),k.parentNode!==H&&H.insertBefore(k,null),Fe.set(k,{target:n,frame:ie})}}return e.parents=e.scopes.map(n=>n.element.parentNode),ke(),!0},Je=e=>e.images.map((o,n)=>{let s=o.getBoundingClientRect();return{...e.data.parts[n],x:s.x,y:s.y,width:s.width,height:s.height}}),Ke=()=>{if(Pe(),V||h==="none"||b)return;let e=R;if(!e||e.viewport!==W()||!e.sources.every(f)||r.current&&!r.current(e.targets)||e.targets.some(s=>!Te.has(s))||De(e).some(s=>!s?.isConnected)||[...K].some(s=>!s.isConnected))return;e.scopes.some((s,P)=>s.element.parentNode!==e.parents[P])&&Ue(),ke();let o=++me,n=()=>me===o;Z=!0,ae=!!r.opaqueUnderlay,b=e,ee++,p.clearTimeout(ve),e.sources.forEach(s=>{g.add(s)}),K.forEach(s=>s.setAttribute("data-native-ui-snapshot-source","")),Xe(e,ae),J=p.requestAnimationFrame(()=>{J=0,n()&&(Z=!1,r.wake())}),pe(S({action:"cover",token:e.data.token,...r.transient?{transient:!0,viewportWidth:p.innerWidth,parts:Je(e)}:{}})).then(s=>{if(n()){if(Z=!1,s?.shown!==!0){$(e,!1);return}X||(ae=!0,e.sources.forEach(P=>c.add(P)),Ue(),ke()),p.cancelAnimationFrame(J),J=p.requestAnimationFrame(()=>{J=0,n()&&S({action:"painted",token:e.data.token}).catch(()=>{n()&&$(e,!1)})}),r.wake()}}).catch(()=>{n()&&$(e,!1)})},Ze=()=>{if(!(!b||V||X)){if(!b.sources.every(f)||De(b).some(e=>!e)||r.current&&!r.current(b.targets)){$(b,!1);return}if(!r.blocked()){if(ke(),r.transient){let e=b;if(De(e).some(s=>!s?.isConnected)){$(e,!1);return}let n=Je(e);r.opaqueUnderlay||n.every((s,P)=>s.width===e.data.parts[P].width&&s.height===e.data.parts[P].height)?e.data={...e.data,parts:n}:R=void 0,S({action:"restore",token:e.data.token,viewportWidth:p.innerWidth,parts:n}).catch(()=>{})}Oe=r.revision?.()??Y?.revision??0,X=!0,b.sources.forEach(e=>g.delete(e)),we=p.setTimeout(()=>{X&&$(b,!1)},250),r.wake()}}},lt=(e,o,n)=>{!X||!b||n===void 0||n<=Oe||!r.transient&&e||b.data.parts.every(s=>s.ids.every(P=>o?.includes(P)))&&(ne(),ue())},Le=(e=!1)=>{he.forEach(n=>n()),ee++,p.clearTimeout(ve);let o=R;if(R=void 0,(e||V)&&(U=void 0),r.retainPreparedUntilRelease&&!b&&!e&&!V){if(o){let n={};U=n,pe(S({action:"release",token:o.data.token})).catch(()=>{}).finally(()=>{if(o.images.forEach(s=>{B(s)}),U===n&&(U=void 0,!(R||b))){for(let s of K)s.getAttribute(y)!==Te.get(s)&&(K.delete(s),_.delete(s));Q(),Te.clear(),p.dispatchEvent(new Event(l))}})}if(U)return}He(o),b?$(b,!1):(Q(),Te.clear(),p.dispatchEvent(new Event(l)))},Qe;try{r.events&&(Qe=await ze(r.events,(e,o)=>{if(!V){if(e&&(h=e),h==="none"){Le();return}e==="web"&&Ke(),e==="native"&&(Ze(),ue()),o&&u()}}))}catch(e){throw V=!0,Le(),await pe(Promise.resolve(E.remove())).catch(()=>{}),e}return{get owners(){return[...g]},get visibleOwners(){return[...c]},get preparedOwners(){return[...D]},consider:a,changed:u,moved:ke,get token(){return X?void 0:b?.data.token},begin:Ke,get restoring(){return X},get handoffPending(){return Z},retireRestoration:Pe,end:Ze,updated:lt,invalidate:Le,async destroy(){V=!0,Le(),C.forEach(e=>e.forEach(o=>o.remove())),C.clear(),await Promise.allSettled([pe(Promise.resolve().then(()=>E?.remove())),pe(Promise.resolve().then(()=>Qe?.remove()))])}}},st=async(t,i,r)=>{let v=await Pt(t,i,r),h=v.consider;return Object.assign(v,{consider:(d,p)=>h(d,p.map(T=>({...T,scope:t})))})};var at=(t,i)=>{if(t.nodeType!==1||t.namespaceURI!=="http://www.w3.org/1999/xhtml"||!t.ownerDocument||!("style"in t))throw new TypeError("A Web projection scope requires an HTMLElement fallback");if(t.matches("img, input, textarea, select, video, audio, canvas, iframe, embed, object, br, hr, area, base, link, meta, source, track, wbr"))throw new TypeError("A Web projection fallback must be a container element; use the existing fallback container");return Object.freeze({element:t,namespace:i})};var ct=async(t,i,r={addListener:async(v,h)=>globalThis.Capacitor.addListener(t.plugin,v,h)})=>{let v="view",h=t.receiveListeners,d=!1,p=!1,T="native",f="native",L=tt(document),C=()=>T==="native"&&m&&L.isCovered(m)?"web":T,j=!1,B=!1,S=!1,y=!1,l,g,c,D=!1,x=()=>{let a=D;D=!0;try{c?.begin()}finally{D=a}},m,O={},A,N=0,oe=()=>{N++,A=void 0;let a=Ne(m);a?.owner===O&&(a.projected=!1,a.owner=void 0)},F={listen:a=>i.listen(u=>{a(u),!u.active&&B&&(B=!1,he()),u.precovered&&Ie(u.precovered)}),send:a=>{if(!t.placementHandoff)return i.send(a);let u=Ne(m);if(a.action==="cover"){let $=A===a.token&&u?.owner===O&&u.projected,ne=++N;return A=a.token,u&&(u.owner=O,u.projected=!!$),i.send(a).then(Pe=>(ne===N&&u===Ne(m)&&u?.owner===O&&(u.projected=Pe?.shown===!0),Pe)).catch(Pe=>{throw ne===N&&u?.owner===O&&(oe(),u.invalidate()),Pe})}let E=a.action==="release"&&a.token===A,_=A&&(a.action==="restore"||E||a.action==="reset"||a.action==="visibility"&&a.visible);_&&N++;let ce=N,Q=()=>{ce!==N||u?.owner!==O||(oe(),u.invalidate())};try{let $=_&&u?.owner===O?{...a,token:"token"in a?a.token:A,placement:u.measure()}:a;return i.send($).then(async ne=>(a.action==="release"&&ne?.requiresPlacement&&(u&&(!u.owner||u.owner===O)?ne=await i.send({...a,placement:u.measure()}):(await i.send({action:"visibility",visible:!1}),ne=await i.send(a))),ce===N&&(a.action==="resume"||E||a.action==="reset"||a.action==="visibility")&&oe(),ne)).catch(ne=>{throw Q(),ne})}catch($){return Q(),Promise.reject($)}}},se=0,Se=0,W=0,Z=!1,ae=!1,J=!1,me=!1,R=document.createElement("style"),U=`data-native-ui-session-${t.id.replace(/[^a-zA-Z0-9-]/g,"")}`;R.textContent=`[${U}="native"], [${U}="native"] *, [${U}="none"], [${U}="none"] * {visibility:hidden!important}`,document.documentElement.append(R);let b=()=>{let a=document.querySelectorAll(t.projectionSelector);return a.length===1&&a[0]instanceof HTMLElement?a[0]:void 0},q=()=>{m&&(f==="web"||f==="native"&&S?m.removeAttribute(U):m.setAttribute(U,f))},X=()=>{if(!m?.isConnected)return[];let a=m.getBoundingClientRect(),u={x:a.x,y:a.y,width:a.width,height:a.height},E=l&&Ge(m,l,()=>t.id);return[{element:m,scrollElement:l,control:{id:v,...u,...E?{scroll:E}:{}}}]},we=async()=>{if(d)return;let a=W,u=t.failedFallback==="native"&&C()==="native"&&!!m?.isConnected;await F.send({action:"visibility",visible:u}).catch(()=>{}),!(d||a!==W)&&(u||f==="none"?q():m?.removeAttribute(U))},Oe=()=>{if(!j||f!=="native"||!m?.isConnected||c?.token||c?.restoring)return;let a=t.failedFallback==="native";F.send({action:"visibility",visible:a}).catch(()=>{}),a?q():m.removeAttribute(U)},ee=()=>{if(d||D)return;if(Oe(),f==="web"&&c&&!c.token&&!c.restoring){F.send({action:"visibility",visible:!1}).catch(()=>{}),m?.removeAttribute(U);return}if(Z||!c?.restoring||f!=="native")return;Z=!0;let a=W,u=c;F.send({action:"resume"}).then(()=>{d||a!==W||u!==c||(S=!1,u.updated(void 0,[v],++se),q(),z())}).catch(()=>{a!==W||d||(u.invalidate(),we())}).finally(()=>{Z=!1,ee()})},ve=async()=>{if(d||ae||j)return;if(c?.restoring){ee();return}let a=b();if(a!==m){if(W++,oe(),m?.removeAttribute(U),await c?.destroy(),c=void 0,d)return;m=a,S=!1,V.disconnect(),m&&V.observe(m)}if(de(),f=C(),!m){await F.send({action:"visibility",visible:!1});return}if(!c){ae=!0;let u=W;try{let E=await st(at(m,t.id),F,{wake:ee,captureDelayMs:t.captureDelayMs,retainPreparedUntilRelease:t.nativeDragHandoff,blocked:()=>f!=="native"||j||S&&!c?.token,revision:()=>se,captureRevision:t.captureMode==="view"?()=>Se:void 0,transient:!0,opaqueUnderlay:t.captureMode==="view"});if(d||u!==W){await E.destroy();return}c=E}finally{ae=!1}}if(!d){if(f==="native"&&S){await F.send({action:"visibility",visible:!1}),q();return}if(f==="native"){let u=W;if(await F.send({action:"visibility",visible:!0}),d||u!==W||f!=="native")return;q(),l=[...We(m)].find(Q=>{let $=getComputedStyle(Q);return/auto|scroll/.test($.overflowX+$.overflowY)&&(Q.scrollHeight>Q.clientHeight||Q.scrollWidth>Q.clientWidth)});let E=l&&Ge(m,l,()=>t.id),_=t.nativeDragHandoff&&t.captureMode==="view"&&l?{viewport:l.getBoundingClientRect(),offsetX:l.scrollLeft,offsetY:l.scrollTop,rangeX:Math.max(0,l.scrollWidth-l.clientWidth),rangeY:Math.max(0,l.scrollHeight-l.clientHeight)}:void 0,ce=await F.send({action:"track",viewportWidth:innerWidth,...E?{scroll:E}:{},..._?{gesture:_}:{}});if(d||u!==W)return;y=ce?.tracked===!0,c.consider(t.captureMode==="view"?Se:++se,X())}else await F.send({action:"visibility",visible:!1}),q()}},z=()=>{d||(J=!0,!(!p||me)&&(me=!0,Promise.resolve().then(async()=>{try{for(;J&&!d;)J=!1,await ve()}catch{await we()}finally{me=!1,J&&z()}})))},be=()=>{c?.invalidate(),z()},V=new ResizeObserver(be);window.addEventListener("resize",be);let te=new Set,Y=new WeakSet,le=a=>{let u=a.composedPath()[0]??a.target;if(!(d||f!=="native"||!m||Y.has(a)||u!==document&&![...We(m)].includes(u))){if(Y.add(a),y&&u===l){c?.changed(u);return}j?t.captureMode==="view"?c?.moved():c?.changed():((Z||c?.restoring)&&W++,j=!0,x(),S=t.failedFallback!=="native",c?.token?m.removeAttribute(U):Oe()),he()}};function he(){clearTimeout(g),g=setTimeout(()=>{B||(j=!1,!(d||f!=="native")&&(c?.end(),c?.restoring||z()))},100)}function Ie(a){if(d||f!=="native"||!m?.isConnected||!c||(B=!0,c.token))return;(Z||c.restoring)&&W++,A=a;let u=Ne(m);if(u&&(u.owner=O,u.projected=!0),j=!0,x(),!c.token){j=!1,we();return}he()}let de=()=>{let a=new Set(m?We(m):[]),u=a.size!==te.size||[...a].some(E=>!te.has(E));for(let E of te)a.has(E)||(E.removeEventListener("scroll",le),E.removeEventListener("slotchange",xe),te.delete(E));for(let E of a)te.has(E)||(E.addEventListener("scroll",le,{passive:!0}),E.addEventListener("slotchange",xe),te.add(E));u&&(y=!1,l=void 0,c?.invalidate(),z())},xe=()=>{de(),z()};document.addEventListener("scroll",le,!0);let He=new MutationObserver(a=>{de(),b()!==m?z():m&&a.some(u=>u.type==="childList")&&Ee(C())});He.observe(document.documentElement,{childList:!0,attributes:!0,subtree:!0});let Ee=(a,u=!1)=>{if(d||!u&&a===f)return;j=!1,B=!1,clearTimeout(g),f=a,W++;let E=W;f==="none"?F.send({action:"visibility",visible:!1}).then(()=>{f!=="none"||E!==W||d||(c?.invalidate(!0),q())}).catch(()=>{f!=="none"||E!==W||d||(c?.invalidate(!0),q())}):f==="web"?(x(),c?.token||F.send({action:"visibility",visible:!1}).catch(()=>{}),q()):f==="native"&&(c?.end(),c?.restoring||z())},qe=L.subscribe(()=>queueMicrotask(()=>Ee(C()))),ue,Ae=async()=>{if(!d){d=!0,oe(),W++,qe(),He.disconnect(),V.disconnect(),window.removeEventListener("resize",be),document.removeEventListener("scroll",le,!0);for(let a of te)a.removeEventListener("scroll",le),a.removeEventListener("slotchange",xe);te.clear(),clearTimeout(g),m?.removeAttribute(U),R.remove(),await Promise.allSettled([Promise.resolve(ue?.remove()),c?.destroy()])}};try{let a=W;ue=await ze({addListener:(E,_)=>r.addListener(E,_),update:h?.update,projection:h?.projection,accepts:E=>!h?.match||Object.entries(h?.match).every(([_,ce])=>typeof E=="object"&&E!==null&&E[_]===ce)},(E,_)=>{d||(E&&(E==="native"&&(S=!1),T=E,F.send({action:"destination",destination:E}).catch(()=>{}),Ee(C(),!0)),_&&(Se++,c?.changed(),f==="native"&&z()))});let u=await F.send({action:"connect"});return W===a&&["native","web","none"].includes(u?.destination)&&(T=u.destination),f=C(),p=!0,z(),{destroy:Ae,show:()=>{S=!1,T="native",Ee(C(),!0)},hide:()=>{T=f="none",W++,j=!1,B=!1,clearTimeout(g),c?.invalidate(!0),q()}}}catch(a){throw await Ae(),a}};var ye=new Map,ge=new Map,$e=new Map,Tt=Array.from(crypto.getRandomValues(new Uint32Array(4)),t=>t.toString(16)).join("-"),Ve=new Map,Lt=(t,i,r)=>Ve.get(t)?.get(i)?.(r),Mt=0,jt=(t,i)=>new Promise((r,v)=>{let h=`${t}:${Tt}:${++Mt}`,d=setTimeout(()=>{ge.delete(h),v(new Error("Native UI session timed out"))},5e3);ge.set(h,{resolve:r,reject:v,timer:d});let p=JSON.stringify({key:h,request:i}),T=globalThis,f=T.webkit?.messageHandlers?.[t]??T[t]??T.nativeUIEngine;if(!f){clearTimeout(d),ge.delete(h),v(new Error("Native UI session unavailable"));return}try{f.postMessage(p)}catch(L){clearTimeout(d),ge.delete(h),v(L)}}),St=(t,i,r,v)=>{if(i===null){$e.get(t)?.(r);return}let h=ge.get(i);!h||!i.startsWith(`${t}:`)||(ge.delete(i),clearTimeout(h.timer),v?h.reject(new Error(v)):h.resolve(r))},xt=t=>{ye.get(t)?.show()},Ht=t=>(ye.get(t)?.hide(),!0),kt=async t=>{let i=ye.get(t);ye.delete(t),Ve.delete(t),$e.delete(t);for(let[r,v]of ge)r.startsWith(`${t}:`)&&(ge.delete(r),clearTimeout(v.timer),v.reject(new Error("Native UI session closed")));await i?.destroy()},Ct=async t=>{if(ye.has(t.id))return;let i,r=!1,v,h={show:()=>{v="native",i?.show()},hide:()=>{v="none",i?.hide()},destroy:async()=>{r=!0,await i?.destroy()}};ye.set(t.id,h);try{if(document.readyState==="loading"&&await new Promise(p=>document.addEventListener("DOMContentLoaded",()=>p(),{once:!0})),r)return;let d=new Map;t.runtime==="cordova"&&Ve.set(t.id,d),i=await ct(t,{send:p=>jt(t.id,p),listen:async p=>($e.set(t.id,p),{remove:()=>{$e.get(t.id)===p&&$e.delete(t.id)}})},t.runtime==="cordova"?{addListener:async(p,T)=>(d.set(p,T),{remove:()=>{d.delete(p)}})}:void 0),v==="none"?i.hide():v==="native"&&i.show(),r&&await i.destroy()}catch(d){throw ye.get(t.id)===h&&(ye.delete(t.id),Ve.delete(t.id)),d}};return vt(Rt);})();
|
|
22
|
+
`;var Pt=(t,r=!1)=>JSON.stringify(t.map(({control:o})=>[o.id,o.kind,o.placement,r?0:o.x,r?0:o.y,o.width,o.height,o.dark,o.rtl])),Tt=async(t,r,o)=>{let v=o.captureDelayMs??50;if(!Number.isFinite(v)||v<0||v>2147483647)throw new RangeError("captureDelayMs must be a finite, nonnegative timer interval");let y="native",m=t.element.ownerDocument,f=m.defaultView,P=Array.from(f.crypto.getRandomValues(new Uint32Array(4)),e=>e.toString(16)).join("-"),p=e=>e.isConnected&&e.ownerDocument===m,M=e=>!!e?.isConnected&&e.ownerDocument===m,x=new Map,j=new Set,B=e=>{j.delete(e),e.style.setProperty("display","none","important"),e.removeAttribute("data-native-ui-projection-image"),e.removeAttribute("src"),He()},k=r.send.bind(r),g="data-native-ui-snapshot",d=`${t.namespace}:sources-change`,w=new Set,c=new Set,W=new Set,R=new WeakMap,l=0,V=e=>JSON.stringify(e.map(i=>{R.has(i.scope)||R.set(i.scope,++l);let n=o.transient&&!o.opaqueUnderlay?i.scope.element.getBoundingClientRect():void 0,a=n?{...i,control:{...i.control,x:i.control.x-n.x,y:i.control.y-n.y}}:i;return[R.get(i.scope),Pt([a],!!o.opaqueUnderlay)]})),$=new Map,G=e=>{let i=e.getRootNode();return i.nodeType===11&&"host"in i?i:m},ye=e=>{if($.has(e))return;let i=m.createElement("style");i.setAttribute("data-native-ui-snapshot-base",""),i.textContent=rt+(e.nodeType===11?st:""),(e.nodeType===11?e:e.head).append(i),$.set(e,i)},J=e=>{let i=[...e.getAnimations({subtree:!0}),...[...K.get(e)??[]].flatMap(n=>n.shadowRoot?.getAnimations()??[])];for(let n of i)"transitionProperty"in n&&n.transitionProperty==="visibility"&&n.cancel()},K=new Map,ee=e=>{let i=K.get(e)??new Set;K.set(e,i);let n=e.hasAttribute("data-native-ui-snapshot-source")||e.hasAttribute("data-native-ui-snapshot-prepared"),a=T=>{if(!T.hasAttribute("data-native-ui-projection-node")){if(T.shadowRoot){i.add(T),ye(T.shadowRoot);for(let S of T.shadowRoot.children)a(S)}for(let S of T.children)a(S)}};a(e);for(let T of i)T.toggleAttribute("data-native-ui-snapshot-content",n);J(e)},pe=()=>`${f.innerWidth}:${f.innerHeight}:${f.devicePixelRatio}`,re=!1,le=!1,te=0,de=0,L,me,b,H=!1,D=!1,Pe=0,Te=0,oe=0,ue=0,I=0,fe=-1,A=!1,Fe=!1,Y,He=()=>{let e=new Set(Y?.candidates.map(n=>n.scope.element));for(let[n,a]of x){let T=!A&&n.isConnected&&e.has(n);if(T&&(b||D||re))continue;let S=T?2*Math.max(1,L?.scopes.filter(O=>O.element===n).length??0):0,C=Math.max(0,S-a.filter(O=>j.has(O)).length),U=a.filter(O=>j.has(O)||C-- >0?!0:(O.remove(),!1));U.length?x.set(n,U):x.delete(n)}let i=new Set([...Y?.candidates.map(n=>n.scope.element.getRootNode())??[],...b?.scopes.map(n=>n.element.getRootNode())??[],...L?.scopes.map(n=>n.element.getRootNode())??[],...[...j].map(n=>n.getRootNode()),...[...K.values()].flatMap(n=>[...n].map(a=>a.shadowRoot))]);for(let[n,a]of $)n.nodeType===11&&!i.has(n)&&(a.remove(),$.delete(n))},ge=new Set,Ve=(e,i,n)=>{let a=()=>{ge.delete(a)&&(k({action:e,token:i}).catch(()=>{}),e==="restored"&&He())};ge.add(a),n&&!A?f.requestAnimationFrame(()=>f.requestAnimationFrame(a)):a()},q=new Set,ke=()=>{q.forEach(e=>W.delete(e)),q.clear()},Le=(e,i=!1)=>{!e||e===L||e===b||(e.images.forEach(n=>{B(n)}),Ve("release",e.data.token,i))},se=e=>e.filter(i=>{if(!M(i.scope.element)||![i.element,...i.sources??[]].every(p))return!1;if(i.control.scroll){let n=i.element.getBoundingClientRect(),a=i.control.scroll.clip;if(n.right<=a.x||n.bottom<=a.y||n.left>=a.x+a.width||n.top>=a.y+a.height)return!1}return o.eligible?.(i)??!0}),ze=async()=>{if(ue=0,A||y!=="native"||Fe||H||b||o.blocked()||!Y||L?.revision===Y.revision&&fe===I)return;let{revision:e,candidates:i}=Y,n=oe,a=I,T=pe(),S=se(i);if(!S.length)return;Fe=!0;let C,U=!1,O=[];try{let ae=!1,ce=k({action:"prepare",revision:o.captureRevision?.()??e,viewportWidth:f.innerWidth,ids:S.map(E=>E.control.id)});ce.then(E=>{ae&&E.token&&k({action:"release",token:E.token}).catch(()=>{})}).catch(()=>{});try{C=await he(ce)}finally{ae=!0}if(!C.token||!C.parts?.length)return;let We=new Set(S.map(E=>E.control.id));if(C.parts.some(E=>!E.url.startsWith("file:")&&!/^\/__native_ui_engine__\/nativeUI[a-fA-F0-9]+\/[a-fA-F0-9-]+-[0-9]+\.png$/.test(E.url)||!E.ids.length||E.ids.some(_=>!We.has(_))||![E.x,E.y,E.width,E.height].every(Number.isFinite)||E.width<=0||E.height<=0)||new Set(C.parts.flatMap(E=>E.ids)).size!==We.size||C.parts.some(E=>new Set(E.ids.map(_=>S.find(Se=>Se.control.id===_).scope)).size!==1)||(await he(Promise.all(C.parts.map(async E=>{let _=S.find(_e=>E.ids.includes(_e.control.id)).scope.element,Se=x.get(_);Se||(Se=[],x.set(_,Se));let ve=Se.find(_e=>!j.has(_e));return ve||(ve=m.createElement("img"),ve.setAttribute("data-native-ui-projection-node",""),Se.push(ve)),j.add(ve),O.push(ve),ve.src=it(E.url),await ve.decode(),ve}))),A||y!=="native"||H||b||o.blocked()||oe!==n||pe()!==T||Y?.revision!==e||S.some(E=>!M(E.scope.element)||![E.element,...E.sources??[]].every(p))))return;let De=L,et={data:C,images:O,sources:Array.from(new Set(S.flatMap(E=>[E.element,...E.sources??[]]))),targets:C.parts.map(E=>S.find(_=>E.ids.includes(_.control.id)).element),scopes:C.parts.map(E=>S.find(_=>E.ids.includes(_.control.id)).scope),parents:C.parts.map(E=>S.find(_=>E.ids.includes(_.control.id)).scope.element.parentNode),frames:[],viewport:T,revision:e,layout:V(S)};try{if(!Q(et))throw new Error("Projection destination is unavailable")}catch(E){Ae();try{Q(),L?.sources.forEach(_=>{W.add(_),q.add(_)})}catch{ne()}throw E}L=et,ke(),L.sources.forEach(E=>{W.add(E),q.add(E)}),o.opaqueUnderlay&&k({action:"prepared",token:C.token}).catch(()=>{}),f.dispatchEvent(new Event(d)),fe=a,U=!0,Le(De)}catch{}finally{U||O.forEach(ae=>{B(ae)}),C?.token&&!U&&k({action:"release",token:C.token}).catch(()=>{}),Fe=!1,Y&&(Y.revision!==e||I!==a)&&ie()}},ie=()=>{f.clearTimeout(ue),!A&&y==="native"&&!b&&!H&&!o.blocked()&&(ue=f.setTimeout(()=>{ze()},v))},Re,Je=(e,i)=>{if(i.some(a=>a.scope.element.ownerDocument!==m||[a.element,...a.sources??[]].some(T=>T.ownerDocument!==m)))throw new TypeError("All projection sources and fallback scopes must share one Document");if(o.blocked())return;!b&&L&&L.layout!==V(se(i))&&je();let n=V(i);Re!==n&&(Re=n,I++,oe++),Y?.revision!==e&&oe++,Y={revision:e,candidates:i},He(),(L?.revision!==e||fe!==I)&&ie()},Me=e=>{!b&&L&&e&&Y?.candidates.some(i=>i.scrollElement===e&&L.sources.includes(i.element))&&je(),b&&z(),I++,oe++,ie()},Ce=await Xe(r.listen(({active:e})=>{H=e,oe++,f.clearTimeout(ue),e||ie()})),Oe=new Set,we=e=>{K.get(e)?.forEach(i=>i.removeAttribute("data-native-ui-snapshot-content")),Oe.delete(e)&&e.removeAttribute("data-native-ui-snapshot-prepared"),e.removeAttribute("data-native-ui-snapshot-visible"),e.removeAttribute(g),e.removeAttribute("data-native-ui-snapshot-positioned"),e.removeAttribute("data-native-ui-snapshot-source"),J(e),K.delete(e)},Ae=()=>{de++,f.cancelAnimationFrame(te);for(let e of Z.keys())e.style.setProperty("opacity","0","important");Z.clear(),te=0,re=!1,le=!1,ke(),b?.sources.forEach(e=>{w.delete(e),c.delete(e)}),h.forEach(we),h.clear(),$.forEach((e,i)=>{(A||i.nodeType===11&&!i.host.isConnected)&&(e.remove(),$.delete(i))})},ne=(e=b,i=D)=>{if(b!==e)return;let n=new Set([b,L]);Ae(),b=void 0,L=void 0,D=!1,f.clearTimeout(Pe),n.forEach(a=>Le(a,i)),o.wake()},$e=()=>{if(!b)return;if(L!==b){ne();return}let e=b;de++,f.cancelAnimationFrame(te),te=0,re=le=!1,e.sources.forEach(i=>{w.delete(i),c.delete(i)}),h.forEach(i=>i.removeAttribute("data-native-ui-snapshot-source")),N(e,!!o.opaqueUnderlay),b=void 0,D=!1,f.clearTimeout(Pe),Ve("restored",e.data.token,!0),e.sources.forEach(i=>{W.add(i),q.add(i)}),o.wake()},s=()=>{D&&$e(),ge.forEach(e=>e())},u=e=>e.scopes.map(i=>M(i.element)?i.element:void 0),h=new Set,N=(e,i)=>{for(let n of h)n.toggleAttribute("data-native-ui-snapshot-visible",i),ee(n);e.images.forEach(n=>n.style.setProperty("opacity",i?"1":"0","important"))},F=new Map,Z=new Map,z=()=>{let e=[];for(let[i,n]of Z){let{target:a,frame:T}=n;if(!a.isConnected){i.remove();continue}let S=a.shadowRoot??a;i.parentNode!==S&&S.insertBefore(i,null);let C=a.getBoundingClientRect(),U=i.getBoundingClientRect(),O=parseFloat(i.style.width)||T.width,ae=parseFloat(i.style.height)||T.height,ce=U.width/O||1,We=U.height/ae||1,De=n.scale??(n.scale={x:ce,y:We});e.push({element:i,left:(parseFloat(i.style.left)||0)+(C.x+T.x*ce/De.x-U.x)/ce,top:(parseFloat(i.style.top)||0)+(C.y+T.y*We/De.y-U.y)/We,width:T.width/De.x,height:T.height/De.y})}for(let{element:i,...n}of e)for(let[a,T]of Object.entries(n)){let S=`${T}px`;i.style.getPropertyValue(a)!==S&&i.style.setProperty(a,S,"important")}},Q=(e=b??L)=>{if(!e||D)return!1;if(!e.sources.every(p)||u(e).some(n=>!n))return je(),!1;let i=u(e);if(b){if(i.some(a=>!a?.isConnected||!$.has(G(a))))return ne(b,!1),!1;let n=new Set;for(let[a,T]of e.targets.entries()){let S=F.get(T),C=i[a];!S||!C?.isConnected||(C.setAttribute(g,S),C.setAttribute("data-native-ui-snapshot-source",""),n.add(C))}for(let a of h)n.has(a)||we(a);return h.clear(),n.forEach(a=>h.add(a)),N(e,le),!0}x.forEach(n=>n.forEach(a=>{e.images.includes(a)||(a.style.setProperty("display","none","important"),a.removeAttribute("data-native-ui-projection-image"))})),F.clear(),Z.clear(),h.forEach(we),h.clear();for(let n of new Set(i)){if(!n)continue;h.add(n),ye(G(n));let a=i.flatMap((U,O)=>U===n?[O]:[]),T=`${P}-${a[0]}`;n.setAttribute(g,T),n!==e.targets[a[0]]&&(n.setAttribute("data-native-ui-snapshot-prepared",""),Oe.add(n)),n.toggleAttribute("data-native-ui-snapshot-visible",!!o.opaqueUnderlay),ee(n);let S=n.getBoundingClientRect();n.toggleAttribute("data-native-ui-snapshot-positioned",f.getComputedStyle(n).position==="static");let C=n.shadowRoot??n;for(let U of[...a].reverse()){let O=e.images[U],ae=e.data.parts[U],ce=e.frames[U]??{x:o.opaqueUnderlay?0:ae.x-S.x,y:o.opaqueUnderlay?0:ae.y-S.y,width:ae.width,height:ae.height};e.frames[U]=ce,F.set(e.targets[U],T),O.inert=!0,O.setAttribute("aria-hidden","true"),O.setAttribute("data-native-ui-projection-image",T),O.style.cssText="all:initial!important;position:absolute!important;display:block!important;visibility:visible!important;pointer-events:none!important;image-rendering:pixelated!important;will-change:opacity!important;opacity:0!important;",O.style.setProperty("width",`${ce.width}px`,"important"),O.style.setProperty("height",`${ce.height}px`,"important"),O.style.setProperty("left","0px","important"),O.style.setProperty("top","0px","important"),O.style.setProperty("opacity",o.opaqueUnderlay?"1":"0","important"),O.parentNode!==C&&C.insertBefore(O,null),Z.set(O,{target:n,frame:ce})}}return e.parents=e.scopes.map(n=>n.element.parentNode),z(),!0},X=e=>e.images.map((i,n)=>{let a=i.getBoundingClientRect();return{...e.data.parts[n],x:a.x,y:a.y,width:a.width,height:a.height}}),Ie=()=>{if(s(),A||y==="none"||b)return;let e=L;if(!e||e.viewport!==pe()||!e.sources.every(p)||o.current&&!o.current(e.targets)||e.targets.some(a=>!F.has(a))||u(e).some(a=>!a?.isConnected)||[...h].some(a=>!a.isConnected))return;e.scopes.some((a,T)=>a.element.parentNode!==e.parents[T])&&Q(),z();let i=++de,n=()=>de===i;re=!0,le=!!o.opaqueUnderlay,b=e,oe++,f.clearTimeout(ue),e.sources.forEach(a=>{w.add(a)}),h.forEach(a=>a.setAttribute("data-native-ui-snapshot-source","")),N(e,le),te=f.requestAnimationFrame(()=>{te=0,n()&&(re=!1,o.wake())}),he(k({action:"cover",token:e.data.token,...o.transient?{transient:!0,viewportWidth:f.innerWidth,parts:X(e)}:{}})).then(a=>{if(n()){if(re=!1,a?.shown!==!0){ne(e,!1);return}D||(le=!0,e.sources.forEach(T=>c.add(T)),Q(),z()),f.cancelAnimationFrame(te),te=f.requestAnimationFrame(()=>{te=0,n()&&k({action:"painted",token:e.data.token}).catch(()=>{n()&&ne(e,!1)})}),o.wake()}}).catch(()=>{n()&&ne(e,!1)})},Ze=()=>{if(!(!b||A||D)){if(!b.sources.every(p)||u(b).some(e=>!e)||o.current&&!o.current(b.targets)){ne(b,!1);return}if(!o.blocked()){if(z(),o.transient){let e=b;if(u(e).some(a=>!a?.isConnected)){ne(e,!1);return}let n=X(e);o.opaqueUnderlay||n.every((a,T)=>a.width===e.data.parts[T].width&&a.height===e.data.parts[T].height)?e.data={...e.data,parts:n}:L=void 0,k({action:"restore",token:e.data.token,viewportWidth:f.innerWidth,parts:n}).catch(()=>{})}Te=o.revision?.()??Y?.revision??0,D=!0,b.sources.forEach(e=>w.delete(e)),Pe=f.setTimeout(()=>{D&&ne(b,!1)},250),o.wake()}}},dt=(e,i,n)=>{!D||!b||n===void 0||n<=Te||!o.transient&&e||b.data.parts.every(a=>a.ids.every(T=>i?.includes(T)))&&($e(),ie())},je=(e=!1)=>{ge.forEach(n=>n()),oe++,f.clearTimeout(ue);let i=L;if(L=void 0,(e||A)&&(me=void 0),o.retainPreparedUntilRelease&&!b&&!e&&!A){if(i){let n={};me=n,he(k({action:"release",token:i.data.token})).catch(()=>{}).finally(()=>{if(i.images.forEach(a=>{B(a)}),me===n&&(me=void 0,!(L||b))){for(let a of h)a.getAttribute(g)!==F.get(a)&&(h.delete(a),Oe.delete(a));Ae(),F.clear(),f.dispatchEvent(new Event(d))}})}if(me)return}Le(i),b?ne(b,!1):(Ae(),F.clear(),f.dispatchEvent(new Event(d)))},Qe;try{o.events&&(Qe=await Ye(o.events,(e,i)=>{if(!A){if(e&&(y=e),y==="none"){je();return}e==="web"&&Ie(),e==="native"&&(Ze(),ie()),i&&Me()}}))}catch(e){throw A=!0,je(),await he(Promise.resolve(Ce.remove())).catch(()=>{}),e}return{get owners(){return[...w]},get visibleOwners(){return[...c]},get preparedOwners(){return[...W]},consider:Je,changed:Me,moved:z,get token(){return D?void 0:b?.data.token},begin:Ie,get restoring(){return D},get handoffPending(){return re},retireRestoration:s,end:Ze,updated:dt,invalidate:je,async destroy(){A=!0,je(),x.forEach(e=>e.forEach(i=>i.remove())),x.clear(),await Promise.allSettled([he(Promise.resolve().then(()=>Ce?.remove())),he(Promise.resolve().then(()=>Qe?.remove()))])}}},at=async(t,r,o)=>{let v=await Tt(t,r,o),y=v.consider;return Object.assign(v,{consider:(m,f)=>y(m,f.map(P=>({...P,scope:t})))})};var ct=(t,r)=>{if(t.nodeType!==1||t.namespaceURI!=="http://www.w3.org/1999/xhtml"||!t.ownerDocument||!("style"in t))throw new TypeError("A Web projection scope requires an HTMLElement fallback");if(t.matches("img, input, textarea, select, video, audio, canvas, iframe, embed, object, br, hr, area, base, link, meta, source, track, wbr"))throw new TypeError("A Web projection fallback must be a container element; use the existing fallback container");return Object.freeze({element:t,namespace:r})};var lt=async(t,r,o={addListener:async(v,y)=>globalThis.Capacitor.addListener(t.plugin,v,y)})=>{let v="view",y=t.receiveListeners,m=!1,f=!1,P="native",p="native",M=nt(document),x=()=>P==="native"&&l&&M.isCovered(l)?"web":P,j=!1,B=!1,k=!1,g=!1,d,w,c,W=!1,R=()=>{let s=W;W=!0;try{c?.begin()}finally{W=s}},l,V=0,$,G=()=>{V++,$?.(),$=void 0},ye=async()=>{if(!t.values||!l||m)return;let s=l;G();let u=V,h=()=>!m&&u===V&&l===s&&fe()===s&&s.isConnected;if(s.localName.includes("-")&&!s.matches(":defined")&&Object.values(t.values).some(F=>F.property)){if(await Promise.race([s.ownerDocument.defaultView.customElements.whenDefined(s.localName),new Promise(F=>{$=F})]),!h())return;$=void 0}let N=await r.send({action:"values"}).catch(()=>{});if(h()&&N?.values&&typeof N.values=="object"&&!Array.isArray(N.values))try{tt(s,N.values,t.values)}catch(F){console.warn("[Native UI Engine] Cannot reflect values",F)}},J={},K,ee=0,pe=new Set,re=()=>{},le=new Promise(s=>{re=s}),te=()=>{pe.clear(),re(),le=new Promise(s=>{re=s})},de=()=>{ee++,K=void 0;let s=Ue(l);s?.owner===J&&(s.projected=!1,s.owner=void 0)},L={listen:s=>r.listen(u=>{s(u),!u.active&&B&&(B=!1,Re()),u.precovered&&Je(u.precovered)}),send:s=>{if(!t.placementHandoff)return r.send(s);if(s.action==="visibility"&&!s.visible&&te(),s.action==="visibility"&&s.visible&&pe.size){let z=H,Q=ee,X=l,Ie=le;return Promise.race([Promise.allSettled([...pe]),Ie]).then(()=>m||Ie!==le||z!==H||Q!==ee||X!==l||!X?.isConnected||fe()!==l||x()!=="native"?{}:L.send(s))}let u=Ue(l);if(s.action==="cover"){let z=K===s.token&&u?.owner===J&&u.projected,Q=++ee;return K=s.token,u&&(u.owner=J,u.projected=!!z),r.send(s).then(X=>(Q===ee&&u===Ue(l)&&u?.owner===J&&(u.projected=X?.shown===!0),X)).catch(X=>{throw Q===ee&&u?.owner===J&&(de(),u.invalidate()),X})}let h=s.action==="release"&&s.token===K,N=K&&(s.action==="restore"||h||s.action==="reset"||s.action==="visibility"&&s.visible);N&&ee++;let F=ee,Z=()=>{F!==ee||u?.owner!==J||(de(),u.invalidate())};try{let z=N&&u?.owner===J?{...s,token:"token"in s?s.token:K,placement:u.measure()}:s,Q=r.send(z).then(async X=>(s.action==="release"&&X?.requiresPlacement&&(u&&(!u.owner||u.owner===J)?X=await r.send({...s,placement:u.measure()}):(await r.send({action:"visibility",visible:!1}),X=await r.send(s))),F===ee&&(s.action==="resume"||h||s.action==="reset"||s.action==="visibility")&&de(),X)).catch(X=>{throw Z(),X});return s.action!=="release"||!t.nativeDragHandoff?Q:(pe.add(Q),Q.finally(()=>pe.delete(Q)))}catch(z){return Z(),Promise.reject(z)}}},me=0,b=0,H=0,D,Pe=!1,Te=!1,oe=!1,ue=document.createElement("style"),I=`data-native-ui-session-${t.id.replace(/[^a-zA-Z0-9-]/g,"")}`;ue.textContent=`[${I}="native"], [${I}="native"] *, [${I}="none"], [${I}="none"] * {visibility:hidden!important}`,document.documentElement.append(ue);let fe=()=>{let s=document.querySelectorAll(t.projectionSelector);return s.length===1&&s[0]instanceof HTMLElement?s[0]:void 0},A=()=>{let s=x();l&&l.getAttribute("data-native-ui-destination")!==s&&l.setAttribute("data-native-ui-destination",s),l&&(p==="web"||p==="native"&&k?l.removeAttribute(I):l.setAttribute(I,p))},Fe=()=>{if(!l?.isConnected)return[];let s=l.getBoundingClientRect(),u={x:s.x,y:s.y,width:s.width,height:s.height},h=d&&Ke(l,d,()=>t.id);return[{element:l,scrollElement:d,control:{id:v,...u,...h?{scroll:h}:{}}}]},Y=async()=>{if(m)return;let s=H,u=t.failedFallback==="native"&&x()==="native"&&!!l?.isConnected;await L.send({action:"visibility",visible:u}).catch(()=>{}),!(m||s!==H)&&(u||p==="none"?A():l?.removeAttribute(I))},He=()=>{if(!j||p!=="native"||!l?.isConnected||c?.token||c?.restoring)return;let s=t.failedFallback==="native";L.send({action:"visibility",visible:s}).catch(()=>{}),s?A():l.removeAttribute(I)},ge=()=>{if(m||W)return;if(He(),p==="web"&&c&&!c.token&&!c.restoring){L.send({action:"visibility",visible:!1}).catch(()=>{}),l?.removeAttribute(I);return}if(!c?.restoring||D===c||p!=="native")return;D=c;let s=H,u=c;L.send({action:"resume"}).then(()=>{m||s!==H||u!==c||fe()!==l||(k=!1,u.updated(void 0,[v],++me),A(),q())}).catch(()=>{s!==H||m||(u.invalidate(),Y())}).finally(()=>{D===u&&(D=void 0),ge()})},Ve=async()=>{if(m||Pe)return;if(fe()!==l){H++,j=!1,B=!1,clearTimeout(w),de(),l?.removeAttribute(I),l?.removeAttribute("data-native-ui-destination"),G();let u=c,h=l;c=void 0,l=void 0,Le.disconnect(),Me();try{h&&await L.send({action:"visibility",visible:!1})}finally{await u?.destroy()}if(m)return;l=fe(),k=!1,l&&(Le.observe(l),ye())}if(Me(),!j){if(c?.restoring){ge();return}if(p=x(),!l){await L.send({action:"visibility",visible:!1});return}if(!c){Pe=!0;let u=H;try{let h=await at(ct(l,t.id),L,{wake:ge,captureDelayMs:t.captureDelayMs,retainPreparedUntilRelease:t.nativeDragHandoff,blocked:()=>p!=="native"||j||k&&!c?.token,revision:()=>me,captureRevision:t.captureMode==="view"?()=>b:void 0,transient:!0,opaqueUnderlay:t.captureMode==="view"});if(m||u!==H){await h.destroy();return}c=h}finally{Pe=!1}}if(!m){if(p==="native"&&k){await L.send({action:"visibility",visible:!1}),A();return}if(p==="native"){let u=H;if(await L.send({action:"visibility",visible:!0}),m||u!==H||p!=="native"||j)return;A(),d=[...Ne(l)].find(Z=>{let z=getComputedStyle(Z);return/auto|scroll/.test(z.overflowX+z.overflowY)&&(Z.scrollHeight>Z.clientHeight||Z.scrollWidth>Z.clientWidth)});let h=d&&Ke(l,d,()=>t.id),N=t.nativeDragHandoff&&t.captureMode==="view"&&d?{viewport:d.getBoundingClientRect(),offsetX:d.scrollLeft,offsetY:d.scrollTop,rangeX:Math.max(0,d.scrollWidth-d.clientWidth),rangeY:Math.max(0,d.scrollHeight-d.clientHeight)}:void 0,F=await L.send({action:"track",viewportWidth:innerWidth,...h?{scroll:h}:{},...N?{gesture:N}:{}});if(m||u!==H)return;g=F?.tracked===!0,c.consider(t.captureMode==="view"?b:++me,Fe())}else await L.send({action:"visibility",visible:!1}),A()}}},q=()=>{m||(Te=!0,!(!f||oe)&&(oe=!0,Promise.resolve().then(async()=>{try{for(;Te&&!m;)Te=!1,await Ve()}catch{await Y()}finally{oe=!1,Te&&q()}})))},ke=()=>{c?.invalidate(),q()},Le=new ResizeObserver(ke);window.addEventListener("resize",ke);let se=new Set,ze=new WeakSet,ie=s=>{let u=s.composedPath()[0]??s.target;if(!(m||p!=="native"||!l||ze.has(s)||u!==document&&![...Ne(l)].includes(u))){if(ze.add(s),g&&u===d){c?.changed(u);return}j?t.captureMode==="view"?c?.moved():c?.changed():((D||c?.restoring)&&H++,j=!0,R(),k=t.failedFallback!=="native",c?.token?l.removeAttribute(I):He()),Re()}};function Re(){clearTimeout(w),w=setTimeout(()=>{B||(j=!1,!(m||p!=="native")&&(c?.end(),c?.restoring||q()))},100)}function Je(s){if(m||p!=="native"||!l?.isConnected||!c||(B=!0,c.token))return;(D||c.restoring)&&H++,K=s;let u=Ue(l);if(u&&(u.owner=J,u.projected=!0),j=!0,R(),!c.token){j=!1,Y();return}Re()}let Me=()=>{let s=new Set(l?Ne(l):[]),u=s.size!==se.size||[...s].some(h=>!se.has(h));for(let h of se)s.has(h)||(h.removeEventListener("scroll",ie),h.removeEventListener("slotchange",Ce),se.delete(h));for(let h of s)se.has(h)||(h.addEventListener("scroll",ie,{passive:!0}),h.addEventListener("slotchange",Ce),se.add(h));u&&(g=!1,d=void 0,c?.invalidate(),q())},Ce=()=>{Me(),q()};document.addEventListener("scroll",ie,!0);let Oe=new MutationObserver(s=>{Me(),fe()!==l?q():l&&s.some(u=>u.type==="childList")&&we(x())});Oe.observe(document.documentElement,{childList:!0,attributes:!0,subtree:!0});let we=(s,u=!1)=>{if(m||!u&&s===p)return;j=!1,B=!1,clearTimeout(w),p=s,H++;let h=H;p==="none"?L.send({action:"visibility",visible:!1}).then(()=>{p!=="none"||h!==H||m||(c?.invalidate(!0),A())}).catch(()=>{p!=="none"||h!==H||m||(c?.invalidate(!0),A())}):p==="web"?(R(),c?.token||L.send({action:"visibility",visible:!1}).catch(()=>{}),A()):p==="native"&&(c?.end(),c?.restoring||q())},Ae=M.subscribe(()=>queueMicrotask(()=>we(x()))),ne,$e=async()=>{if(!m){m=!0,te(),G(),de(),H++,Ae(),Oe.disconnect(),Le.disconnect(),window.removeEventListener("resize",ke),document.removeEventListener("scroll",ie,!0);for(let s of se)s.removeEventListener("scroll",ie),s.removeEventListener("slotchange",Ce);se.clear(),clearTimeout(w),l?.removeAttribute(I),l?.removeAttribute("data-native-ui-destination"),ue.remove(),await Promise.allSettled([Promise.resolve(ne?.remove()),c?.destroy()])}};try{let s=H;ne=await Ye({addListener:(h,N)=>o.addListener(h,N),update:y?.update,projection:y?.projection,accepts:h=>!y?.match||Object.entries(y?.match).every(([N,F])=>typeof h=="object"&&h!==null&&h[N]===F)},(h,N)=>{m||(h&&(h==="native"&&(k=!1),P=h,L.send({action:"destination",destination:h}).catch(()=>{}),we(x(),!0)),N&&(ye(),b++,c?.changed(),p==="native"&&q()))});let u=await L.send({action:"connect"});return H===s&&["native","web","none"].includes(u?.destination)&&(P=u.destination),p=x(),f=!0,q(),{destroy:$e,show:()=>{k=!1,P="native",we(x(),!0)},hide:()=>{P=p="none",H++,te(),j=!1,B=!1,clearTimeout(w),c?.invalidate(!0),A()}}}catch(s){throw await $e(),s}};var be=new Map,Ee=new Map,Be=new Map,Lt=Array.from(crypto.getRandomValues(new Uint32Array(4)),t=>t.toString(16)).join("-"),qe=new Map,Mt=(t,r,o)=>qe.get(t)?.get(r)?.(o),jt=0,St=(t,r)=>new Promise((o,v)=>{let y=`${t}:${Lt}:${++jt}`,m=setTimeout(()=>{Ee.delete(y),v(new Error("Native UI session timed out"))},5e3);Ee.set(y,{resolve:o,reject:v,timer:m});let f=JSON.stringify({key:y,request:r}),P=globalThis,p=P.webkit?.messageHandlers?.[t]??P[t]??P.nativeUIEngine;if(!p){clearTimeout(m),Ee.delete(y),v(new Error("Native UI session unavailable"));return}try{p.postMessage(f)}catch(M){clearTimeout(m),Ee.delete(y),v(M)}}),xt=(t,r,o,v)=>{if(r===null){Be.get(t)?.(o);return}let y=Ee.get(r);!y||!r.startsWith(`${t}:`)||(Ee.delete(r),clearTimeout(y.timer),v?y.reject(new Error(v)):y.resolve(o))},Ht=t=>{be.get(t)?.show()},kt=t=>(be.get(t)?.hide(),!0),Rt=async t=>{let r=be.get(t);be.delete(t),qe.delete(t),Be.delete(t);for(let[o,v]of Ee)o.startsWith(`${t}:`)&&(Ee.delete(o),clearTimeout(v.timer),v.reject(new Error("Native UI session closed")));await r?.destroy()},Ct=async t=>{if(be.has(t.id))return;let r,o=!1,v,y={show:()=>{v="native",r?.show()},hide:()=>{v="none",r?.hide()},destroy:async()=>{o=!0,await r?.destroy()}};be.set(t.id,y);try{if(document.readyState==="loading"&&await new Promise(f=>document.addEventListener("DOMContentLoaded",()=>f(),{once:!0})),o)return;let m=new Map;t.runtime==="cordova"&&qe.set(t.id,m),r=await lt(t,{send:f=>St(t.id,f),listen:async f=>(Be.set(t.id,f),{remove:()=>{Be.get(t.id)===f&&Be.delete(t.id)}})},t.runtime==="cordova"?{addListener:async(f,P)=>(m.set(f,P),{remove:()=>{m.delete(f)}})}:void 0),v==="none"?r.hide():v==="native"&&r.show(),o&&await r.destroy()}catch(m){throw be.get(t.id)===y&&(be.delete(t.id),qe.delete(t.id)),m}};return ht(Ot);})();
|