craft-native 0.0.220 → 0.0.221
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/dist/cli.js
CHANGED
|
@@ -3424,7 +3424,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
|
|
|
3424
3424
|
`);
|
|
3425
3425
|
}
|
|
3426
3426
|
// package.json
|
|
3427
|
-
var version = "0.0.
|
|
3427
|
+
var version = "0.0.221";
|
|
3428
3428
|
|
|
3429
3429
|
// bin/cli.ts
|
|
3430
3430
|
var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -1105,23 +1105,58 @@ struct CraftSplashView: View {
|
|
|
1105
1105
|
}
|
|
1106
1106
|
|
|
1107
1107
|
// MARK: - Deep Link Manager
|
|
1108
|
+
/// Launch intent settles when UIKit delivers its URL or completes activation,
|
|
1109
|
+
/// independently of when a page or native screen registers its listeners.
|
|
1110
|
+
final class CraftInitialLinkState {
|
|
1111
|
+
private(set) var url: URL?
|
|
1112
|
+
private(set) var settled = false
|
|
1113
|
+
private var readers: [(URL?) -> Void] = []
|
|
1114
|
+
|
|
1115
|
+
func receive(_ url: URL) {
|
|
1116
|
+
guard !settled else { return }
|
|
1117
|
+
self.url = url
|
|
1118
|
+
settle()
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
func settle() {
|
|
1122
|
+
guard !settled else { return }
|
|
1123
|
+
settled = true
|
|
1124
|
+
let waiting = readers
|
|
1125
|
+
readers.removeAll()
|
|
1126
|
+
for reader in waiting { reader(url) }
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
func resolve(_ completion: @escaping (URL?) -> Void) {
|
|
1130
|
+
if settled { completion(url) }
|
|
1131
|
+
else { readers.append(completion) }
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1108
1135
|
class DeepLinkManager {
|
|
1109
1136
|
static let shared = DeepLinkManager()
|
|
1110
1137
|
|
|
1111
|
-
private
|
|
1138
|
+
private let launch = CraftInitialLinkState()
|
|
1139
|
+
private var initialURL: URL? { launch.url }
|
|
1140
|
+
private var activationObservers: [NSObjectProtocol] = []
|
|
1112
1141
|
// Every link that arrived while no page could receive it, in order. This
|
|
1113
1142
|
// was a single slot, so a second link before the bridge was ready replaced
|
|
1114
1143
|
// the first; on a cold start, that could be the link that launched the app.
|
|
1115
1144
|
private var pendingURLs: [URL] = []
|
|
1116
1145
|
private weak var webView: WKWebView?
|
|
1117
1146
|
private var isReady = false
|
|
1118
|
-
//
|
|
1119
|
-
//
|
|
1120
|
-
// is no answer to getInitialURL.
|
|
1147
|
+
// Replay bookkeeping only. A native screen can become ready before UIKit
|
|
1148
|
+
// delivers the launch URL; listener readiness cannot classify that URL.
|
|
1121
1149
|
private var hasBeenReady = false
|
|
1122
1150
|
private var nativeListeners: [UUID: (URL, Bool) -> Void] = [:]
|
|
1123
1151
|
|
|
1124
|
-
private init() {
|
|
1152
|
+
private init() {
|
|
1153
|
+
for name in [UIApplication.didBecomeActiveNotification, UIApplication.didEnterBackgroundNotification] {
|
|
1154
|
+
activationObservers.append(NotificationCenter.default.addObserver(forName: name, object: nil, queue: .main) { [weak self] _ in
|
|
1155
|
+
self?.launch.settle()
|
|
1156
|
+
})
|
|
1157
|
+
}
|
|
1158
|
+
if UIApplication.shared.applicationState == .active { launch.settle() }
|
|
1159
|
+
}
|
|
1125
1160
|
|
|
1126
1161
|
func setWebView(_ webView: WKWebView) {
|
|
1127
1162
|
self.webView = webView
|
|
@@ -1146,9 +1181,7 @@ class DeepLinkManager {
|
|
|
1146
1181
|
}
|
|
1147
1182
|
|
|
1148
1183
|
func handleURL(_ url: URL) {
|
|
1149
|
-
|
|
1150
|
-
initialURL = url
|
|
1151
|
-
}
|
|
1184
|
+
launch.receive(url)
|
|
1152
1185
|
|
|
1153
1186
|
// A hybrid app opens a native path's screen itself, and tells the
|
|
1154
1187
|
// native screens that listen; every other link is the page's. An
|
|
@@ -1179,6 +1212,17 @@ class DeepLinkManager {
|
|
|
1179
1212
|
return initialURL
|
|
1180
1213
|
}
|
|
1181
1214
|
|
|
1215
|
+
/// A foreground scene can draw before SwiftUI delivers its launch activity.
|
|
1216
|
+
/// A headless background launch has no scene or foreground URL to await.
|
|
1217
|
+
func resolveInitialURL(_ completion: @escaping (URL?) -> Void) {
|
|
1218
|
+
let application = UIApplication.shared
|
|
1219
|
+
if application.applicationState == .active ||
|
|
1220
|
+
(application.applicationState == .background && application.connectedScenes.isEmpty) {
|
|
1221
|
+
launch.settle()
|
|
1222
|
+
}
|
|
1223
|
+
launch.resolve(completion)
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1182
1226
|
@discardableResult
|
|
1183
1227
|
func addNativeListener(_ listener: @escaping (URL, Bool) -> Void) -> UUID {
|
|
1184
1228
|
let token = UUID()
|
|
@@ -258,7 +258,10 @@ enum CraftNativeActions {
|
|
|
258
258
|
sync = .success(currentAppState())
|
|
259
259
|
case ("DeepLinks", "getInitialURL"):
|
|
260
260
|
if config.enableDeepLinks {
|
|
261
|
-
|
|
261
|
+
DeepLinkManager.shared.resolveInitialURL { url in
|
|
262
|
+
complete(requestToken, .success(claimInitialDeepLink(url).map(deepLinkData) ?? NSNull()), completion)
|
|
263
|
+
}
|
|
264
|
+
return
|
|
262
265
|
} else {
|
|
263
266
|
sync = failure("CAPABILITY_DISABLED", "Deep links are disabled")
|
|
264
267
|
}
|
|
@@ -809,12 +812,12 @@ enum CraftNativeActions {
|
|
|
809
812
|
else { task.resume() }
|
|
810
813
|
}
|
|
811
814
|
|
|
812
|
-
private static func claimInitialDeepLink() -> URL? {
|
|
815
|
+
private static func claimInitialDeepLink(_ url: URL?) -> URL? {
|
|
813
816
|
cancellationLock.lock()
|
|
814
817
|
defer { cancellationLock.unlock() }
|
|
815
818
|
guard !initialDeepLinkClaimed else { return nil }
|
|
816
819
|
initialDeepLinkClaimed = true
|
|
817
|
-
return
|
|
820
|
+
return url
|
|
818
821
|
}
|
|
819
822
|
|
|
820
823
|
private static func complete(
|