Files
Flaro/Flixy/Views/Settings/PlaybackSettingsView.swift
T
ScarriffleandClaude Opus 5 21c5a8b46b Player: vier Knöpfe, die vorher fehlten oder nichts sagten
**Eine Taste zum Vergrößern** unten rechts auf der Kachel. Das Antippen der
Fläche vergrößert weiterhin, aber auf derselben Fläche liegen schon das Ziehen
und das Aufziehen — und was dabei danebengeht, sieht aus wie „reagiert nicht".
Ein Knopf geht nicht daneben.

**Ton und Untertitel getrennt.** Es sind zwei verschiedene Fragen: die Tonspur
stellt man einmal am Anfang um, die Untertitel mitten im Film. In einem
gemeinsamen Blatt scrollte man jedes Mal an der anderen Liste vorbei. Das
Untertitel-Symbol ist gefüllt, solange welche laufen — so sieht man es, ohne
das Blatt zu öffnen. Und eine Auswahl schließt das Blatt jetzt selbst.

**AirPlay.** Nicht nachgebaut, sondern die Systemstelle: sie kennt Geräte, die
eine App nie aufzählen könnte. Der Knopf erscheint nur beim Systemplayer — VLC
zeichnet selbst und kann kein AirPlay, und ein Knopf, der dort ins Leere
führte, wäre schlimmer als keiner.

**Die Qualität steht als Text da**, nicht als drei Schieberegler: „1080p",
„720p", „Auto". Bei „automatisch" steht dort, was gerade tatsächlich ankommt —
das weiß nur der Player, und ihn zu fragen ist ehrlicher, als „Auto"
hinzuschreiben und die Antwort schuldig zu bleiben.

Dazu die Einstellungen mit farbigen Symbolen und einer Kopfkarte je Bereich.
Das ist nicht nur Zierde: in einer Liste aus zehn gleich aussehenden Zeilen
findet das Auge nichts wieder, und „das mit dem blauen Zahnrad" ist eine
brauchbare Beschreibung. Die Farben sind fest und ausdrücklich **nicht** die
Akzentfarbe — trüge alles dieselbe, unterschiede sie nichts mehr.

Und der Aufmacher läuft jetzt unter der Seitenleiste weiter
(`backgroundExtensionEffect`): die Ränder werden gespiegelt und weich
fortgeschrieben, während Titel und Knöpfe stehen bleiben. Vorher endete das
Bild an der Kante der Leiste, und beim Weiterwandern schob sich das nächste an
einer harten Linie ins Bild.

263 Tests grün. Player-Knöpfe und Einstellungen angesehen; den Aufmacher hinter
der Leiste konnte ich an den einfarbigen Flächen der Attrappe nicht sicher
beurteilen — der Simulator ist dabei erneut abgestürzt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 15:36:24 +02:00

113 lines
4.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
import FlixyDesign
import FlixyPlayback
/// Alles, was die Wiedergabe betrifft.
///
/// Vorher stand das verstreut in der langen Liste der Einstellungen, zwischen
/// Serverangaben und Downloads. Zusammen ergibt es einen Bildschirm, den man
/// einmal durchgeht und dann in Ruhe lässt.
struct PlaybackSettingsView: View {
@Environment(PlaybackSettings.self) private var settings
@Environment(\.flixyAccent) private var accent
var body: some View {
@Bindable var settings = settings
Form {
SettingsHeader(
symbol: "play.rectangle",
colour: SettingsPalette.playback,
title: "settings.playback",
explanation: "settings.playbackExplanation"
)
Section {
Picker("settings.qualityWifi", selection: $settings.wifiQuality) {
ForEach(PlaybackSettings.Quality.allCases) { quality in
Text(quality.label).tag(quality)
}
}
Picker("settings.qualityCellular", selection: $settings.cellularQuality) {
ForEach(PlaybackSettings.Quality.allCases) { quality in
Text(quality.label).tag(quality)
}
}
} header: {
Text("settings.quality")
} footer: {
Text("settings.qualityExplanation")
}
Section {
Toggle("settings.rememberQuality", isOn: $settings.remembersQuality)
Toggle("settings.showBitrate", isOn: $settings.showsBitrate)
} footer: {
Text("settings.rememberQualityExplanation")
}
Section {
Picker("settings.rewind", selection: $settings.rewindSeconds) {
ForEach(PlaybackSettings.skipChoices, id: \.self) { seconds in
Text("settings.seconds \(seconds)").tag(seconds)
}
}
Picker("settings.forward", selection: $settings.forwardSeconds) {
ForEach(PlaybackSettings.skipChoices, id: \.self) { seconds in
Text("settings.seconds \(seconds)").tag(seconds)
}
}
Picker("settings.defaultRate", selection: $settings.defaultRate) {
ForEach(PlaybackSettings.rateChoices, id: \.self) { rate in
Text(rateLabel(rate)).tag(rate)
}
}
} header: {
Text("settings.controls")
} footer: {
// Zurück und vor getrennt, weil sie verschiedene Zwecke haben:
// zurück, weil man etwas nicht verstanden hat; vor, weil man
// etwas überspringen will.
Text("settings.controlsExplanation")
}
Section {
Toggle("settings.lockLandscape", isOn: $settings.locksLandscape)
} footer: {
Text("settings.lockLandscapeExplanation")
}
Section {
Toggle("settings.autoSkipIntro", isOn: $settings.autoSkipIntro)
Toggle("settings.autoSkipCredits", isOn: $settings.autoSkipCredits)
Toggle("settings.autoPlayNext", isOn: $settings.autoPlayNext)
} header: {
Text("settings.episodes")
}
}
.tint(accent)
.scrollContentBackground(.hidden)
.background(Color.flixyCanvas)
.navigationTitle(Text("settings.playback"))
.navigationBarTitleDisplayMode(.inline)
}
private func rateLabel(_ rate: Double) -> String {
rate == 1
? String(localized: "settings.rateNormal")
: rate.formatted(.number.precision(.fractionLength(0...2))) + "×"
}
}
extension PlaybackSettings.Quality {
var label: LocalizedStringKey {
switch self {
case .original: "quality.original"
case .high: "quality.high"
case .medium: "quality.medium"
case .low: "quality.low"
case .minimal: "quality.minimal"
}
}
}