80 lines
2.7 KiB
Swift
80 lines
2.7 KiB
Swift
|
|
import SwiftUI
|
||
|
|
|
||
|
|
// MARK: - App Delegate (Background Upload Session)
|
||
|
|
|
||
|
|
class AppDelegate: NSObject, UIApplicationDelegate {
|
||
|
|
func application(
|
||
|
|
_ application: UIApplication,
|
||
|
|
handleEventsForBackgroundURLSession identifier: String,
|
||
|
|
completionHandler: @escaping () -> Void
|
||
|
|
) {
|
||
|
|
if identifier == "com.navidromeplayer.batchupload" {
|
||
|
|
ZipImportManager.shared.setBackgroundCompletionHandler(completionHandler)
|
||
|
|
DebugLogger.shared.log("Background session woke app: \(identifier)", category: "Upload")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@main
|
||
|
|
struct NavidromePlayerApp: App {
|
||
|
|
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||
|
|
|
||
|
|
@StateObject private var serverManager = ServerManager.shared
|
||
|
|
@StateObject private var audioPlayer = AudioPlayer.shared
|
||
|
|
@StateObject private var offlineManager = OfflineManager.shared
|
||
|
|
|
||
|
|
// Initialize WatchConnectivity so sync works immediately
|
||
|
|
private let watchConnectivity = WatchConnectivityManager.shared
|
||
|
|
|
||
|
|
init() {
|
||
|
|
// Dismiss keyboard when scrolling any scroll view
|
||
|
|
UIScrollView.appearance().keyboardDismissMode = .interactive
|
||
|
|
}
|
||
|
|
|
||
|
|
var body: some Scene {
|
||
|
|
WindowGroup {
|
||
|
|
RootView()
|
||
|
|
.environmentObject(serverManager)
|
||
|
|
.environmentObject(audioPlayer)
|
||
|
|
.environmentObject(offlineManager)
|
||
|
|
.tint(Color(red: 1.0, green: 0.176, blue: 0.333)) // iOS 8 Music pink
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
struct RootView: View {
|
||
|
|
@EnvironmentObject var serverManager: ServerManager
|
||
|
|
|
||
|
|
var body: some View {
|
||
|
|
Group {
|
||
|
|
if serverManager.servers.isEmpty {
|
||
|
|
// No servers configured — show login
|
||
|
|
LoginView()
|
||
|
|
} else {
|
||
|
|
// Servers exist — show main UI immediately (connects in background)
|
||
|
|
MainTabView()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
.dismissKeyboardOnTap()
|
||
|
|
.task {
|
||
|
|
ImageCache.shared.trimDiskCache()
|
||
|
|
AudioPreFetcher.shared.cleanOldPrefetches(keeping: AudioPlayer.shared.queue)
|
||
|
|
|
||
|
|
if serverManager.activeServer != nil {
|
||
|
|
await serverManager.connectToActive()
|
||
|
|
|
||
|
|
// Background sync — fills LibraryCache so UI never waits for network
|
||
|
|
SyncEngine.shared.syncIfNeeded()
|
||
|
|
|
||
|
|
// Flush any pending optimistic actions (star/unstar that failed offline)
|
||
|
|
OptimisticActionQueue.shared.flush()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Connect Companion push client if enabled
|
||
|
|
if CompanionSettings.shared.isEnabled {
|
||
|
|
CompanionPushClient.shared.connect()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|