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:
@@ -0,0 +1,48 @@
|
||||
import SwiftUI
|
||||
|
||||
/// Unified right-click / long-press menu for any `LibraryItem` shown on the
|
||||
/// Home, Library, or Heruntergeladen screens. Includes both download actions
|
||||
/// (start / cancel / delete files) AND a "Fortschritt entfernen" action when
|
||||
/// the user has any server-side progress on the item.
|
||||
///
|
||||
/// The "Fortschritt entfernen" row was previously Home-only; the download
|
||||
/// rows were previously Library-only — combining them in one place means the
|
||||
/// same menu shows up regardless of which screen the user is on.
|
||||
@ViewBuilder
|
||||
func mediaItemContextMenu(for item: LibraryItem, app: AppState) -> some View {
|
||||
let key = item.downloadKey
|
||||
let state = app.downloads.state(for: key)
|
||||
if item.isPodcastContainer {
|
||||
Text("Episoden zum Download in der Podcast-Ansicht auswählen")
|
||||
} else {
|
||||
switch state {
|
||||
case .notDownloaded, .failed:
|
||||
Button {
|
||||
app.downloads.startDownload(item: item)
|
||||
} label: {
|
||||
Label("Für Offline herunterladen", systemImage: "arrow.down.circle")
|
||||
}
|
||||
case .downloading:
|
||||
Button {
|
||||
app.downloads.cancel(downloadKey: key)
|
||||
} label: {
|
||||
Label("Download abbrechen", systemImage: "xmark.circle")
|
||||
}
|
||||
case .downloaded:
|
||||
Button(role: .destructive) {
|
||||
app.downloads.delete(downloadKey: key)
|
||||
} label: {
|
||||
Label("Heruntergeladene Dateien löschen", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if app.progressCache[item.syncKey] != nil {
|
||||
Divider()
|
||||
Button(role: .destructive) {
|
||||
Task { await app.removeProgress(itemId: item.id, episodeId: item.episodeId) }
|
||||
} label: {
|
||||
Label("Fortschritt entfernen", systemImage: "arrow.uturn.backward.circle")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user