import SwiftUI #if os(iOS) import AVFAudio import UIKit #endif @main struct Audiobookshelf_swiftApp: App { @State private var appState = AppState() #if os(iOS) /// Bridges the UIKit-only `handleEventsForBackgroundURLSession` callback /// (used by iOS to wake the app when a background download completes) /// into the SwiftUI lifecycle. Without this, in-flight downloads can't /// notify the app of completion after a swipe-away. @UIApplicationDelegateAdaptor(BackgroundDownloadAppDelegate.self) private var appDelegate #endif init() { configureImageCache() #if os(iOS) configureAudioSession() #endif } /// Increases the shared URLCache so AsyncImage covers persist across renders /// and app launches. Default capacity is tiny (~4 MB / 20 MB). private func configureImageCache() { let memoryCapacity = 50 * 1024 * 1024 // 50 MB let diskCapacity = 500 * 1024 * 1024 // 500 MB URLCache.shared = URLCache( memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "covers" ) } var body: some Scene { #if os(macOS) WindowGroup { ContentView() .environment(appState) } .windowResizability(.contentSize) Settings { SettingsView() .environment(appState) } #else WindowGroup { ContentView() .environment(appState) } #endif } #if os(iOS) private func configureAudioSession() { // Nur die Kategorie registrieren — setActive(true) passiert erst in play(), // damit beim App-Start keine laufende Fremd-Wiedergabe unterbrochen wird. try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: []) } #endif } #if os(iOS) /// Receives the system's background URLSession completion callback and routes /// the handler to whichever `DownloadManager` is currently active. We can't /// reach the SwiftUI-owned `AppState` from here directly, so the handler is /// stashed on `DownloadManager.pendingBackgroundCompletion` and consumed when /// `urlSessionDidFinishEvents(forBackgroundURLSession:)` fires. final class BackgroundDownloadAppDelegate: NSObject, UIApplicationDelegate { func application( _ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void ) { DownloadManager.pendingBackgroundCompletion = completionHandler } } #endif