import SwiftUI import FlixyDesign import FlixyPlayback import MediaKit /// Auswahl einer Spur — Ton **oder** Untertitel, nicht beides. /// /// Getrennt, weil es zwei verschiedene Fragen sind: die Tonspur wechselt man /// einmal am Anfang, die Untertitel mitten im Film. Beide in einem Sheet /// bedeutete jedes Mal Scrollen an der anderen Liste vorbei. struct TrackPickerSheet: View { enum Kind: Identifiable { case audio case subtitles var id: Self { self } var title: LocalizedStringKey { switch self { case .audio: "player.audioTracks" case .subtitles: "player.subtitleTracks" } } } let model: PlayerModel let kind: Kind @Environment(\.dismiss) private var dismiss @Environment(\.flixyAccent) private var accent var body: some View { NavigationStack { List { switch kind { case .audio: // **Die Spuren der Datei, nicht die des Players.** Rechnet // der Server um, kennt der Player genau eine — die, für // die er sich entschieden hat. Zur Auswahl steht, was in // der Datei liegt. ForEach(model.audioStreams) { stream in row( title: stream.name, isSelected: model.selectedAudioStream == stream ) { Task { await model.selectAudioStream(stream) } dismiss() } } if let gemerkt = model.rememberedTrackName { Section { Button(role: .destructive) { model.forgetRememberedTrack() } label: { Label("player.forgetRememberedTrack", systemImage: "arrow.uturn.backward") } .listRowBackground(Color.flixySurface) } header: { Text("player.rememberedTrack") } footer: { // Eine automatische Handlung, die man nicht sehen // kann, ist von einem Fehler nicht zu // unterscheiden. Text("player.rememberedTrackExplanation \(gemerkt)") } } case .subtitles: // „Aus" gehört in dieselbe Liste wie die Spuren, nicht als // eigener Schalter daneben: es ist eine Auswahl unter // mehreren, keine getrennte Eigenschaft. row( title: String(localized: "player.subtitlesOff"), isSelected: model.selectedSubtitleStream == nil ) { Task { await model.selectSubtitleStream(nil) } dismiss() } // Wie beim Ton die Spuren der Datei: ein umgerechneter // Stream bringt genau einen mit, und der heisst „CC". ForEach(model.subtitleStreams) { stream in row( title: stream.name, isSelected: model.selectedSubtitleStream == stream ) { Task { await model.selectSubtitleStream(stream) } dismiss() } } } } .scrollContentBackground(.hidden) .background(Color.flixyCanvas) .navigationTitle(Text(kind.title)) .flixyInlineTitle() .toolbar { ToolbarItem(placement: .confirmationAction) { Button("action.close") { dismiss() } } } } .flixyMediumSheet() } private func row(title: String, isSelected: Bool, action: @escaping () -> Void) -> some View { Button(action: action) { HStack { Text(title) .foregroundStyle(Color.flixyTextPrimary) Spacer() if isSelected { Image(systemName: "checkmark").foregroundStyle(accent) } } .contentShape(.rect) } .buttonStyle(.plain) .listRowBackground(Color.flixySurface) .accessibilityAddTraits(isSelected ? [.isButton, .isSelected] : .isButton) } }