From 24d80e5c959bee34dd6b97adf58f8ca8dfc0d861 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Sat, 3 Oct 2026 09:07:04 +0200 Subject: [PATCH] =?UTF-8?q?Offline=20fragte=20die=20Spurauswahl=20den=20Se?= =?UTF-8?q?rver=20=E2=80=94=20den=20es=20dort=20nicht=20gibt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deine Beobachtung, Schritt für Schritt nachgemessen: der Untertitel-Knopf war da, das Sheet zeigte nur „Aus". **Zwei Quellen für dieselbe Frage.** Der Knopf richtete sich nach den Spuren, die der Player in der Datei findet (`subtitleTracks`); die Liste nach den Spuren, die der Server gemeldet hat (`subtitleStreams`). Die kommen aus `chooseAudioStream`, und das läuft nur auf dem Online-Weg. Offline war die Liste deshalb leer — Knopf da, nichts dahinter. Offline listet das Sheet jetzt die Spuren der Datei und schaltet sie unmittelbar in der Engine um. Online bleibt es beim bisherigen Weg: dort heisst Umstellen „neu bestellen", weil ein umgerechneter Stream genau eine Spur mitbringt. **Der Tonspur-Knopf verschwindet, wo es nichts zu wählen gibt.** Eine Spur ist keine Wahl — ein Angebot, das nach dem Antippen nichts anbietet. Bei den Untertiteln genügt dagegen eine: „an oder aus" ist auch eine Wahl. **Belegt, dass die Spur wirklich ankommt.** Die heruntergeladene Datei direkt mit AVFoundation gelesen: Spuren in der Datei: 3 vide / soun / sbtl (sbtl = tx3g, also mov_text) Gruppe AVMediaCharacteristicLegible: 2 Auswahlmöglichkeiten Der Untertitel ist drin — er wurde nur nie angeboten. **Was dabei auffällt und offen bleibt:** alle Spuren der umgepackten Datei tragen die Sprache `und`. Jellyfin reicht die Sprachkennung beim Umpacken nicht durch, also heissen sie „Unknown language". Das ist eine eigene Sache; die App weiss, welche Sprache sie bestellt hat, und könnte sie beschriften. iOS und tvOS bauen. Co-Authored-By: Claude Opus 5 --- Flixy/Views/Player/PlayerModel.swift | 20 ++++++++++++++++ Flixy/Views/Player/PlayerView.swift | 4 ++-- Flixy/Views/Player/TrackPickerSheet.swift | 29 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Flixy/Views/Player/PlayerModel.swift b/Flixy/Views/Player/PlayerModel.swift index c67de49..ba90926 100644 --- a/Flixy/Views/Player/PlayerModel.swift +++ b/Flixy/Views/Player/PlayerModel.swift @@ -1529,6 +1529,26 @@ final class PlayerModel { seek(to: .milliseconds(marker.endMilliseconds)) } + /// Ob es bei der Tonspur überhaupt etwas zu wählen gibt. + /// + /// **Eine Spur ist keine Wahl.** Der Knopf stand auch dort, wo die Liste + /// genau einen Eintrag hatte — ein Angebot, das nach dem Antippen nichts + /// anbietet. + /// + /// Woher gezählt wird, hängt daran, wo die Datei liegt: online stehen die + /// Spuren des Servers zur Wahl (umstellen heisst dort: neu bestellen), + /// offline die der Datei. Siehe `TrackPickerSheet`. + var hasAudioChoice: Bool { + (isOffline ? audioTracks.count : audioStreams.count) > 1 + } + + /// Ob es Untertitel gibt. + /// + /// Hier genügt **einer**: „an oder aus" ist auch eine Wahl. + var hasSubtitleChoice: Bool { + isOffline ? !subtitleTracks.isEmpty : !subtitleStreams.isEmpty + } + func selectAudioTrack(_ track: MediaTrack) { engine?.selectAudioTrack(track) selectedAudioTrack = track diff --git a/Flixy/Views/Player/PlayerView.swift b/Flixy/Views/Player/PlayerView.swift index 029d390..5ec78f3 100644 --- a/Flixy/Views/Player/PlayerView.swift +++ b/Flixy/Views/Player/PlayerView.swift @@ -498,7 +498,7 @@ struct PlayerView: View { // Tonspur stellt man einmal am Anfang um, die Untertitel mitten im // Film. Ein gemeinsames Sheet bedeutete jedes Mal Scrollen an der // anderen Liste vorbei. - if !model.audioTracks.isEmpty { + if model.hasAudioChoice { trackButton( symbol: "waveform", label: "player.audioTracks", @@ -506,7 +506,7 @@ struct PlayerView: View { ) } - if !model.subtitleTracks.isEmpty { + if model.hasSubtitleChoice { trackButton( symbol: model.selectedSubtitleTrack == nil ? "captions.bubble" diff --git a/Flixy/Views/Player/TrackPickerSheet.swift b/Flixy/Views/Player/TrackPickerSheet.swift index b4efcdc..046dc0d 100644 --- a/Flixy/Views/Player/TrackPickerSheet.swift +++ b/Flixy/Views/Player/TrackPickerSheet.swift @@ -33,6 +33,19 @@ struct TrackPickerSheet: View { NavigationStack { List { switch kind { + case .audio where model.isOffline: + // **Offline zählt, was in der Datei liegt.** Die Liste des + // Servers gibt es hier nicht: `chooseAudioStream` läuft nur + // auf dem Online-Weg. Solange sie trotzdem gefragt wurde, + // blieb die Auswahl für heruntergeladene Titel leer — der + // Knopf war da, das Sheet zeigte nichts. + ForEach(model.audioTracks) { track in + row(title: track.displayName, isSelected: model.selectedAudioTrack == track) { + model.selectAudioTrack(track) + dismiss() + } + } + case .audio: // **Die Spuren der Datei, nicht die des Players.** Rechnet // der Server um, kennt der Player genau eine — die, für @@ -66,6 +79,22 @@ struct TrackPickerSheet: View { } } + case .subtitles where model.isOffline: + row( + title: String(localized: "player.subtitlesOff"), + isSelected: model.selectedSubtitleTrack == nil + ) { + model.selectSubtitleTrack(nil) + dismiss() + } + + ForEach(model.subtitleTracks) { track in + row(title: track.displayName, isSelected: model.selectedSubtitleTrack == track) { + model.selectSubtitleTrack(track) + dismiss() + } + } + case .subtitles: // „Aus" gehört in dieselbe Liste wie die Spuren, nicht als // eigener Schalter daneben: es ist eine Auswahl unter