import SwiftUI import FlaroDesign import FlaroPlayback import MediaKit import JellyfinKit /// Die App auf dem Fernseher. /// /// **Eine eigene Wurzel statt eines Zweigs in `FlaroApp`.** Der Unterschied /// zwischen Telefon und Fernseher ist keine Feinheit der Darstellung, sondern /// die Bedienart: kein Finger, keine Grössenklasse, keine Werkzeugleiste, kein /// Ziehen zum Aktualisieren, keine halbhohen Sheets — und dafür ein Fokus, den /// es auf iOS gar nicht gibt. Ein `#if os(tvOS)` in der bestehenden Wurzel /// wäre kein Zweig, sondern ein zweiter Rumpf in derselben Datei, und der /// nächste, der die iOS-Seite ändert, bräche die andere, ohne es zu merken. /// /// **Die Modelle dagegen werden geteilt**, nicht kopiert: `Flaro/Session/` /// kommt über einen Pfadeintrag in `project.yml` mit. Die Naht verläuft /// zwischen Modell und Ansicht, nicht zwischen den Plattformen. /// /// **Kein SwiftData und kein Download-Koordinator.** Der `ModelContainer` der /// iOS-App trägt ausschliesslich Downloads, und die gibt es hier nicht — damit /// fällt beides weg. @main struct FlaroTVApp: App { @State private var session: FlaroSession @State private var theme = FlaroTheme() @State private var playback = PlaybackCoordinator() @State private var playbackSettings = PlaybackSettings() @State private var languages = LanguagePreferences() @State private var quickPlay = QuickPlay() @State private var subtitleAppearance = SubtitleAppearance() @State private var homeLayout = HomeLayoutSettings() @State private var diagnostics = PlaybackDiagnostics() /// Beobachtet die Verbindung. Lebt hier, damit der Beobachter einmal läuft /// statt bei jedem Öffnen des Players neu zu starten. /// /// Ein Apple TV hängt fast immer am Kabel oder an festem WLAN — aber /// „fast" ist kein Grund, die Entscheidungen des Players zu raten. @State private var network = NetworkConditions() init() { _session = State(initialValue: FlaroSession( jellyfinIdentity: JellyfinIdentity.current( client: Branding.appName, version: Branding.version ), tokenStore: KeychainTokenStore(service: Branding.keychainService) )) } var body: some Scene { WindowGroup { TVRootView() .environment(session) .environment(theme) .environment(playback) .environment(playbackSettings) .environment(languages) .environment(quickPlay) .environment(subtitleAppearance) .environment(homeLayout) .environment(diagnostics) .environment(network) .flaroAccent(theme) .tint(theme.accentColor) // Ein Fernseher ist immer dunkel. Der Schalter in der // Info.plist gilt fürs System, diese Zeile für die Vorschauen. .preferredColorScheme(.dark) } } }