- Chapter navigation with auto-scroll to current chapter and end-of-chapter sleep timer - Opt-in listening history (local-only) with XML export and per-item quick menu - Bookmarks with server sync via Audiobookshelf API - Live MB counter during downloads via URLSessionDownloadTask delegate - In-progress downloads shown in "Heruntergeladen" with dimmed cover + ring overlay - Cover image cache (50 MB memory / 500 MB disk URLCache) - German/English localization (de.lproj, en.lproj) - Loading spinner now triggers immediately on view switch instead of waiting for the network Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
57 lines
1.5 KiB
Swift
57 lines
1.5 KiB
Swift
import SwiftUI
|
|
#if os(iOS)
|
|
import AVFAudio
|
|
#endif
|
|
|
|
@main
|
|
struct Audiobookshelf_swiftApp: App {
|
|
@State private var appState = AppState()
|
|
|
|
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
|
|
}
|