diff --git a/Flixy/Session/PlexWebAuthenticator.swift b/Flixy/Session/PlexWebAuthenticator.swift index d45c6b3..ec96cbe 100644 --- a/Flixy/Session/PlexWebAuthenticator.swift +++ b/Flixy/Session/PlexWebAuthenticator.swift @@ -1,3 +1,38 @@ +#if os(tvOS) +import Foundation + +/// **Auf dem Fernseher gibt es kein Anmeldefenster.** +/// +/// `ASWebAuthenticationSession` steht im tvOS-SDK, aber fast alles daran ist +/// als nicht verfügbar markiert: kein `presentationContextProvider`, kein +/// `prefersEphemeralWebBrowserSession`, nicht einmal `cancel()`. Ein +/// Fernseher hat auch keinen Browser, in dem sich jemand bei Plex anmelden +/// würde — und Plex ist in der ersten Fassung ohnehin nicht dabei. +/// +/// **Der Typ bleibt trotzdem stehen.** `FlixySession` hält ihn als Feld und +/// ruft ihn an sechs Stellen; ihn herauszuschneiden hiesse, die +/// Zustandsmaschine der Anmeldung für eine Plattform zu spalten, die diesen +/// Zweig nie betritt. Dieselbe Bauform wie bei `OrientationLock`: derselbe +/// Name, dieselben Aufrufe, und nichts passiert. +@MainActor +final class PlexWebAuthenticator { + enum Failure: Error, Equatable { + case cancelled + case presentationFailed(String) + } + + /// Immer „ging nicht": wer hier landet, soll nicht warten. + private(set) var outcome: Failure? + private(set) var didReturn = false + + func present(url: URL, callbackScheme: String) { + outcome = .presentationFailed(String(localized: "signIn.windowFailed")) + didReturn = true + } + + func dismiss() {} +} +#else import AuthenticationServices import Foundation #if canImport(UIKit) @@ -114,3 +149,4 @@ extension PlexWebAuthenticator: ASWebAuthenticationPresentationContextProviding #endif } } +#endif diff --git a/FlixyTV/FlixyTVApp.swift b/FlixyTV/FlixyTVApp.swift new file mode 100644 index 0000000..97e73f7 --- /dev/null +++ b/FlixyTV/FlixyTVApp.swift @@ -0,0 +1,27 @@ +import SwiftUI +import FlixyDesign + +/// Die App auf dem Fernseher. +/// +/// **Eine eigene Wurzel statt eines Zweigs in `FlixyApp`.** 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: `Flixy/Session/` +/// kommt über einen Pfadeintrag in `project.yml` mit. Die Naht verläuft +/// zwischen Modell und Ansicht, nicht zwischen den Plattformen. +/// +/// **Kein SwiftData.** Der `ModelContainer` der iOS-App trägt ausschliesslich +/// Downloads, und die gibt es hier nicht. +@main +struct FlixyTVApp: App { + var body: some Scene { + WindowGroup { + TVRootView() + } + } +} diff --git a/FlixyTV/Info.plist b/FlixyTV/Info.plist new file mode 100644 index 0000000..5e5ecc3 --- /dev/null +++ b/FlixyTV/Info.plist @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Flixy + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + ITSAppUsesNonExemptEncryption + + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + NSLocalNetworkUsageDescription + Flixy benötigt Zugriff auf das lokale Netzwerk, um deinen Jellyfin-Server zu erreichen. + UIUserInterfaceStyle + Dark + + diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..03434f1 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images": [ + { + "idiom": "tv", + "filename": "back.png", + "scale": "1x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/back.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/back.png new file mode 100644 index 0000000..4fc1add Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/back.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..74d6a72 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..761c276 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,14 @@ +{ + "layers": [ + { + "filename": "Front.imagestacklayer" + }, + { + "filename": "Back.imagestacklayer" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..136d873 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images": [ + { + "idiom": "tv", + "filename": "front.png", + "scale": "1x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/front.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/front.png new file mode 100644 index 0000000..f0aec62 Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/front.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..74d6a72 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..8b663ed --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "tv", + "filename": "back.png", + "scale": "1x" + }, + { + "idiom": "tv", + "filename": "back@2x.png", + "scale": "2x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back.png new file mode 100644 index 0000000..2d16d20 Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back@2x.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back@2x.png new file mode 100644 index 0000000..ce0d3b9 Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back@2x.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..74d6a72 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..761c276 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,14 @@ +{ + "layers": [ + { + "filename": "Front.imagestacklayer" + }, + { + "filename": "Back.imagestacklayer" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..cc67194 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "tv", + "filename": "front.png", + "scale": "1x" + }, + { + "idiom": "tv", + "filename": "front@2x.png", + "scale": "2x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front.png new file mode 100644 index 0000000..10e2d1f Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front@2x.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front@2x.png new file mode 100644 index 0000000..d0aeae2 Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front@2x.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..74d6a72 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json new file mode 100644 index 0000000..ee6c66c --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -0,0 +1,32 @@ +{ + "assets": [ + { + "filename": "App Icon.imagestack", + "idiom": "tv", + "role": "primary-app-icon", + "size": "400x240" + }, + { + "filename": "App Icon - App Store.imagestack", + "idiom": "tv", + "role": "primary-app-icon", + "size": "1280x768" + }, + { + "filename": "Top Shelf Image.imageset", + "idiom": "tv", + "role": "top-shelf-image", + "size": "1920x720" + }, + { + "filename": "Top Shelf Image Wide.imageset", + "idiom": "tv", + "role": "top-shelf-image-wide", + "size": "2320x720" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..a6ab638 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "tv", + "filename": "topshelfwide.png", + "scale": "1x" + }, + { + "idiom": "tv", + "filename": "topshelfwide@2x.png", + "scale": "2x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/topshelfwide.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/topshelfwide.png new file mode 100644 index 0000000..4d0dceb Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/topshelfwide.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/topshelfwide@2x.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/topshelfwide@2x.png new file mode 100644 index 0000000..aca2855 Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/topshelfwide@2x.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..e6a1375 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "tv", + "filename": "topshelf.png", + "scale": "1x" + }, + { + "idiom": "tv", + "filename": "topshelf@2x.png", + "scale": "2x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/topshelf.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/topshelf.png new file mode 100644 index 0000000..b151f3c Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/topshelf.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/topshelf@2x.png b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/topshelf@2x.png new file mode 100644 index 0000000..7018415 Binary files /dev/null and b/FlixyTV/Resources/TVAssets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/topshelf@2x.png differ diff --git a/FlixyTV/Resources/TVAssets.xcassets/Contents.json b/FlixyTV/Resources/TVAssets.xcassets/Contents.json new file mode 100644 index 0000000..74d6a72 --- /dev/null +++ b/FlixyTV/Resources/TVAssets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FlixyTV/Views/TVRootView.swift b/FlixyTV/Views/TVRootView.swift new file mode 100644 index 0000000..9366d0c --- /dev/null +++ b/FlixyTV/Views/TVRootView.swift @@ -0,0 +1,19 @@ +import SwiftUI +import FlixyDesign + +/// Was auf dem Fernseher zu sehen ist. +/// +/// Zunächst nur der Name: dieser Schritt beweist Target, Icon, Signierung und +/// Paketauflösung, bevor eine Zeile Logik daran hängt. Scheitert etwas davon, +/// scheitert es hier in fünf Minuten statt später mit sechs offenen +/// Baustellen daneben. +struct TVRootView: View { + var body: some View { + ZStack { + Color.flixyCanvas.ignoresSafeArea() + Text(Branding.appName) + .font(.flixyHero) + .foregroundStyle(.white) + } + } +} diff --git a/Packages/FlixyKit/Sources/FlixyDesign/FlixyFont.swift b/Packages/FlixyKit/Sources/FlixyDesign/FlixyFont.swift index 3ea27ff..f2b1afa 100644 --- a/Packages/FlixyKit/Sources/FlixyDesign/FlixyFont.swift +++ b/Packages/FlixyKit/Sources/FlixyDesign/FlixyFont.swift @@ -109,15 +109,20 @@ public enum FlixySpacing { /// /// **Was das ist.** Ein Fernseher zeigt nicht zwingend das ganze Bild: je nach /// Gerät und Einstellung schneidet er am Rand ab, und was dort steht, sieht -/// niemand. Apple nennt für 1920×1080 einen sicheren Bereich von neunzig -/// Punkten seitlich und sechzig oben wie unten. +/// niemand. /// -/// Ein **Bild** darf darüber hinausgehen — ein Aufmacher soll das sogar. -/// Schrift und Knöpfe nicht. Die Zahl steht hier für die Fälle, in denen der -/// Sicherheitsrand absichtlich übergangen wird und der Text trotzdem drinnen -/// bleiben muss. +/// **Nachgemessen, nicht abgeschrieben.** Im Simulator eines Apple TV 4K +/// meldet SwiftUI bei 1920×1080 genau diese Ränder — sechzig oben und unten, +/// **achtzig** seitlich, Nutzfläche also 1760×960. Die verbreitete Angabe +/// „neunzig" stimmt nicht; eine zweite Quelle nannte achtzig und hatte recht. +/// +/// **Und man bekommt sie geschenkt.** SwiftUI legt sie von selbst als +/// Sicherheitsrand an — deshalb steht in `FlixySpacing.screenMargin` nur die +/// Rinne innerhalb davon. Die Zahl hier ist für die Gegenrichtung: ein +/// bildfüllender Aufmacher, der den Sicherheitsrand absichtlich übergeht und +/// dessen Schrift trotzdem drinbleiben muss. public enum FlixySafeArea { - public static let tv = EdgeInsets(top: 60, leading: 90, bottom: 60, trailing: 90) + public static let tv = EdgeInsets(top: 60, leading: 80, bottom: 60, trailing: 80) } public enum FlixyRadius { diff --git a/project.yml b/project.yml index 03812b7..a09d1b7 100644 --- a/project.yml +++ b/project.yml @@ -5,6 +5,7 @@ options: deploymentTarget: iOS: "26.0" macOS: "26.0" + tvOS: "26.0" createIntermediateGroups: true groupSortPosition: top developmentLanguage: en @@ -155,6 +156,87 @@ targets: Flixy benötigt Zugriff auf das lokale Netzwerk, um deinen Plex-Server zu finden und Medien direkt von ihm zu laden. + # Die Fassung für den Fernseher. + # + # **Eigene Ansichten, geteilte Modelle.** Die Quellenpfade sind die ganze + # Aussage dieses Blocks: `FlixyTV/` gehört nur hierher, `Flixy/Session/` + # gehört beiden. Keine Datei muss dafür umziehen — XcodeGen nimmt Pfade je + # Ziel, und die iOS-Fassung sieht von der ganzen Sache nichts. + FlixyTV: + type: application + platform: tvOS + # Aus demselben Grund ausgeschrieben wie bei Flixy — siehe dort. + scheme: {} + sources: + # Die eigenen Ansichten. + - path: FlixyTV + # Die Modelle. + - path: Flixy/Session + excludes: + # Ein Fernseher dreht sich nicht. + - "OrientationLock.swift" + # Downloads gibt es hier nicht. + - "DownloadService.swift" + - "DownloadRefiller.swift" + # Kommt mit dem Player in Schritt sieben. Solange es ihn nicht gibt, + # hätte die Anmeldung beim System nichts anzumelden. + - "NowPlaying.swift" + # Reines Modell trotz des Ordnernamens: LoadState, ErrorText und + # MediaRoute liegen zusammen in einer Datei. + - path: Flixy/Views/LoadState.swift + type: file + - path: Flixy/Branding.swift + type: file + # Die Texte. Dieselben Schlüssel, dieselben Übersetzungen. + - path: Flixy/Resources/Localizable.xcstrings + type: file + dependencies: + - package: FlixyKit + product: MediaKit + # Mitgenommen, obwohl Plex in Fassung 1 nicht angeboten wird: + # FlixySession kennt PlexResource und PlexBackend in seiner + # Zustandsmaschine. Das Paket mitzunehmen ist billiger, als die Sitzung + # zu spalten — PlexClientIdentity benutzt nur UIDevice, und das gibt es + # auf tvOS. + - package: FlixyKit + product: PlexKit + - package: FlixyKit + product: JellyfinKit + - package: FlixyKit + product: FlixyDesign + - package: FlixyKit + product: FlixyPlayback + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: com.scarriffleservices.flixy.tv + PRODUCT_NAME: Flixy + # Nur Apple TV. + TARGETED_DEVICE_FAMILY: "3" + # Kein AppIcon.icon: Icon Composer deckt iOS, macOS und watchOS ab, + # tvOS nicht. Der Name zeigt auf die Brand-Assets-Gruppe im Katalog, + # und der Katalog liegt unter FlixyTV/Resources. + ASSETCATALOG_COMPILER_APPICON_NAME: "App Icon & Top Shelf Image" + CODE_SIGN_STYLE: Automatic + info: + path: FlixyTV/Info.plist + properties: + CFBundleDisplayName: Flixy + UIUserInterfaceStyle: Dark + ITSAppUsesNonExemptEncryption: false + # Was hier **nicht** steht, und warum: + # + # UILaunchScreen — tvOS hat kein Startbild dieser Art. + # UISupportedInterfaceOrientations — ein Fernseher dreht sich nicht. + # NSSupportsLiveActivities — ActivityKit fehlt im tvOS-SDK. + # CFBundleURLTypes — das Schema ist für die Plex-Rückkehr. + # UIBackgroundModes: audio — ein Apple TV schickt keine App in den + # Hintergrund, aus dem sie weiterspielen müsste. + NSAppTransportSecurity: + NSAllowsLocalNetworking: true + NSLocalNetworkUsageDescription: >- + Flixy benötigt Zugriff auf das lokale Netzwerk, um deinen + Jellyfin-Server zu erreichen. + # Nur zum Hinsehen: fährt die App mit der Attrappe in einen bestimmten # Zustand und hält sie dort an, damit von außen fotografiert werden kann. # Kein Teil der App, wird nie mitgeliefert.