74 lines
2.9 KiB
Swift
74 lines
2.9 KiB
Swift
import SwiftUI
|
|
import WatchConnectivity
|
|
import WatchKit
|
|
|
|
@main
|
|
struct NavidromeWatchApp: App {
|
|
|
|
@WKApplicationDelegateAdaptor(NavidromeWatchDelegate.self) var appDelegate
|
|
|
|
@StateObject private var watchManager = WatchSessionManager.shared
|
|
@StateObject private var audioPlayer = WatchAudioPlayer.shared
|
|
@StateObject private var offlineStore = WatchOfflineStore.shared
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
WatchRootView()
|
|
.environmentObject(watchManager)
|
|
.environmentObject(audioPlayer)
|
|
.environmentObject(offlineStore)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Watch App Delegate
|
|
// Required to handle WKURLSessionRefreshBackgroundTask — without this, the
|
|
// background URLSession in WatchOfflineStore never fires its completion delegate
|
|
// when downloads finish while the app is suspended. sessionSendsLaunchEvents=true
|
|
// in WatchOfflineStore has no effect without this handler (AUDIT-053).
|
|
class NavidromeWatchDelegate: NSObject, WKApplicationDelegate {
|
|
|
|
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
|
|
for task in backgroundTasks {
|
|
switch task {
|
|
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
|
|
// Re-connect the background URLSession by identifier so the system
|
|
// can hand back the completed download events to WatchOfflineStore's
|
|
// URLSessionDownloadDelegate. Merely accessing the backgroundSession
|
|
// lazy property is enough — it registers the delegate and the system
|
|
// delivers pending delegate calls immediately after.
|
|
let identifier = urlSessionTask.sessionIdentifier
|
|
if identifier == "com.navidromeplayer.watch.download" {
|
|
_ = WatchOfflineStore.shared.backgroundSession
|
|
print("[Watch] WKURLSessionRefreshBackgroundTask handled: \(identifier)")
|
|
}
|
|
urlSessionTask.setTaskCompletedWithSnapshot(false)
|
|
|
|
case let refreshTask as WKApplicationRefreshBackgroundTask:
|
|
// Opportunity for a lightweight library metadata refresh.
|
|
Task {
|
|
if WatchSessionManager.shared.activeServer != nil {
|
|
try? await WatchSessionManager.shared.syncLibrary()
|
|
}
|
|
refreshTask.setTaskCompletedWithSnapshot(false)
|
|
}
|
|
|
|
default:
|
|
task.setTaskCompletedWithSnapshot(false)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct WatchRootView: View {
|
|
@EnvironmentObject var watchManager: WatchSessionManager
|
|
@EnvironmentObject var offlineStore: WatchOfflineStore
|
|
|
|
var body: some View {
|
|
if offlineStore.songs.isEmpty && watchManager.servers.isEmpty {
|
|
WatchSetupView()
|
|
} else {
|
|
WatchLibraryView()
|
|
}
|
|
}
|
|
}
|