Home screen, library-wide search, splash with orbital particles, macOS download fix

- Add Netflix-style Home with recent audiobooks/podcasts, list/grid toggle shared with Library
- Add searchable libraries — audiobooks filter on title/author; podcasts also index and search episodes across the whole library
- Add unified context menu (download / progress remove) across Home, Library, and PodcastDetail
- Rework cover badges: listened checkmark top-right, download indicator bottom-right; hide progress bar when finished
- Add AirPlay picker in PlayerBar
- Replace splash with four-phase animation: orbital particles → attract → flash → fade; cross-platform iOS+macOS, runtime AppIcon lookup
- Fix macOS parallel downloads: align connection settings with iOS, raise timeoutIntervalForRequest to 300s
- Fix progress deletion using server-side progress UUID (DELETE /api/me/progress/:id)
- Bump CFBundleVersion to 8

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-06-23 08:54:43 +02:00
parent 1dbd133b75
commit a17a61ad9a
20 changed files with 1423 additions and 267 deletions

View File

@@ -0,0 +1,36 @@
import SwiftUI
import AVKit
/// Cross-platform SwiftUI wrapper around `AVRoutePickerView`. Opens the system
/// route picker (AirPlay devices, Bluetooth, HomePod, Apple TV, etc.) when
/// tapped. Available on iOS 11+ and macOS 10.15+ via AppKit.
///
/// The actual audio routing requires `AVPlayer.allowsExternalPlayback = true`
/// see `PlayerEngine.load(...)` where the queue player is configured.
#if os(iOS)
struct AirPlayPickerButton: UIViewRepresentable {
var tintColor: UIColor = .label
var activeTintColor: UIColor = .systemGreen
func makeUIView(context: Context) -> AVRoutePickerView {
let view = AVRoutePickerView()
view.tintColor = tintColor
view.activeTintColor = activeTintColor
view.prioritizesVideoDevices = false
return view
}
func updateUIView(_ uiView: AVRoutePickerView, context: Context) {
uiView.tintColor = tintColor
uiView.activeTintColor = activeTintColor
}
}
#else
struct AirPlayPickerButton: NSViewRepresentable {
func makeNSView(context: Context) -> AVRoutePickerView {
AVRoutePickerView()
}
func updateNSView(_ nsView: AVRoutePickerView, context: Context) {}
}
#endif