Groesse in vier Stufen, Schrift und Hintergrund als fuenf feste Paare — Weiss, Weiss auf Schwarz, Schwarz auf Weiss, Gelb, Gelb auf Schwarz. Feste Paare statt zweier Regler, weil unabhaengige Achsen unlesbare Mischungen zulassen: Schwarz auf durchsichtig ueber einer Nachtszene ist eine gueltige Einstellung und eine wertlose. Die Uebersetzung nach AVFoundation ist eine Tabelle aus Schluesseln, bei der jeder Fehler lautlos ist — ein falscher Schluessel laesst den Initialisierer `nil` zurueckgeben, und dann gibt es gar keine Regel. Auf dem Bildschirm sieht „keine Regel\" genauso aus wie „Regel ohne Wirkung\". Zehn Tests decken das ab, darunter die drei Fallen: Alpha zuerst in der Farbe, Prozentwert statt Punktgroesse, und der Hintergrund auch fuer „durchsichtig\" ausdruecklich gesetzt statt weggelassen — weggelassen gilt sonst, was Jellyfins WebVTT selbst mitbringt, und das ist oft ein schwarzer Kasten. Als Protokollmethode, nicht als Feld an `PlaybackSource`: die wird einmal beim Oeffnen gelesen, und eine Einstellung, die erst beim naechsten Film wirkt, haelt jeder fuer kaputt. Angewandt wird an zwei Stellen — am laufenden Gegenstand und am frisch angelegten. Nur das erste zu tun hiesse, dass die naechste Folge wieder in der Vorgabe erscheint. VLC erbt die leere Vorgabe. Die Einstellungsseite sagt beides: dass es fuer den Standardplayer gilt, und dass eingebrannte Bilduntertitel von Blu-rays sich nicht gestalten lassen, weil es dort keinen Text gibt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
45 lines
1.5 KiB
Swift
45 lines
1.5 KiB
Swift
import Foundation
|
|
import Observation
|
|
import FlixyPlayback
|
|
|
|
/// Wie Untertitel aussehen sollen — gemerkt über Neustarts hinweg.
|
|
///
|
|
/// Eigener Typ statt zweier Felder an `PlaybackSettings`, aus demselben Grund
|
|
/// wie bei `LanguagePreferences`: dort geht es um Qualität und Leitung, hier
|
|
/// um Darstellung. Zwei Fragen, zwei Orte.
|
|
///
|
|
/// **Die Werte selbst liegen in `SubtitleStyle`**, also im prüfbaren Teil.
|
|
/// Hier steht nur, wie sie einen Neustart überleben.
|
|
@MainActor
|
|
@Observable
|
|
final class SubtitleAppearance {
|
|
private enum Key {
|
|
static let size = "flixy.subtitles.size"
|
|
static let palette = "flixy.subtitles.palette"
|
|
}
|
|
|
|
private let defaults: UserDefaults
|
|
|
|
var size: SubtitleStyle.Size {
|
|
didSet { defaults.set(size.rawValue, forKey: Key.size) }
|
|
}
|
|
|
|
var palette: SubtitleStyle.Palette {
|
|
didSet { defaults.set(palette.rawValue, forKey: Key.palette) }
|
|
}
|
|
|
|
init(defaults: UserDefaults = .standard) {
|
|
self.defaults = defaults
|
|
// Über `object(forKey:)`, nicht über `integer(forKey:)`: das gäbe für
|
|
// „nie gesetzt" eine Null zurück, und die ist keine gültige Stufe.
|
|
self.size = (defaults.object(forKey: Key.size) as? Int)
|
|
.flatMap(SubtitleStyle.Size.init(rawValue:)) ?? .normal
|
|
self.palette = defaults.string(forKey: Key.palette)
|
|
.flatMap(SubtitleStyle.Palette.init(rawValue:)) ?? .whiteOnClear
|
|
}
|
|
|
|
var style: SubtitleStyle {
|
|
SubtitleStyle(size: size, palette: palette)
|
|
}
|
|
}
|