Schritt eins zur Apple-TV-Fassung: nichts davon ist sichtbar, aber ohne das lässt sich für tvOS nicht einmal übersetzen. **Der stille Fehler zuerst.** `FlixyPlatform.isMac` hatte einen `#else`-Zweig, der `true` zurückgab — eine Antwort auf eine Frage, die niemand gestellt hatte. Auf tvOS fiel er dort hindurch: kein Übersetzungsfehler, keine Warnung, nur ein Fernseher, der sich für einen Mac hielt. Jetzt steht dort `#error`. Die nächste Plattform bricht den Bau ab und verlangt eine Entscheidung, statt sich eine auszusuchen. Ein Test hält fest, dass nicht beides zugleich gelten darf; er hätte genau diesen Fehler gefangen. **Ein echter Übersetzungsfehler**, und er lag an der Reihenfolge: `UIPasteboard` steht hinter `canImport(UIKit)`, und das ist auf tvOS wahr. Der tvOS-Zweig steht deshalb jetzt davor — ein Fernseher hat ohnehin nichts, wohin man etwas einfügen könnte. **Drei Vermutungen waren falsch**, nachgeschlagen im tvOS-SDK statt geraten: `presentationDetents` gibt es dort seit tvOS 16 (übersetzt, bewirkt nur nichts — jetzt steht es ausdrücklich da), `.topBarTrailing` seit 14.0, und `isMac` hatte acht Fundstellen in fünf Dateien, nicht fünfzig in siebenundzwanzig. **Schrift und Abstände** bekommen einen eigenen Zweig statt durchzufallen. Nicht feste Grössen: Dynamic Type gibt es auf tvOS auch, und dass `body` dort grösser ausfällt, ist der Sinn der Sache. Falsch war nur die Zuordnung der Rollen — die Skala ist anders gespreizt, und eine Beschriftung in `subheadline` unter einem Plakat ist aus drei Metern Zierrat. Der Aufmacher geht auf `.title`, weil UIKit `largeTitle` auf tvOS gar nicht kennt und nirgends steht, was SwiftUI daraus macht. `screenMargin` steht auf 48 und nicht auf 90: die neunzig Punkte des Überscan-Bereichs liefert das System als Sicherheitsrand, und wer sie hier aufschlägt, hat hundertachtzig. **Zwei Dinge, die sich erst beim Bauen zeigten.** `FlixyDownloads` übersetzte nicht — `volumeAvailableCapacityForImportantUsage` gibt es auf tvOS nicht. Das Paket wird dort trotzdem mitverlinkt, damit `PlayerModel` den Koordinator nennen darf, ohne dass zweitausend Zeilen Wiedergabelogik von `#if` durchzogen werden; angelegt wird nie einer. Und `FlixyProbe` liess das ganze Paket scheitern: ein Kommandozeilenwerkzeug mit `getpass` und `Host`, das auf einem Fernseher nie laufen sollte, hielt den Bau für alle anderen auf. Es ist jetzt ausdrücklich macOS-only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75 lines
3.7 KiB
Swift
75 lines
3.7 KiB
Swift
// swift-tools-version: 6.2
|
|
import PackageDescription
|
|
|
|
let package = Package(
|
|
name: "FlixyKit",
|
|
// Quellsprache ist Englisch, damit die Schlüssel im Code lesbar bleiben.
|
|
// Deutsch kommt als Übersetzung dazu; die Systemsprache entscheidet.
|
|
defaultLocalization: "en",
|
|
// macOS steht hier nur, damit `swift test` die Logik-Tests ohne
|
|
// Simulator laufen lassen kann — das spart bei jedem Durchlauf Minuten.
|
|
// Welche Plattformen die Apps bedienen, legt project.yml fest: iOS für
|
|
// Flixy, tvOS für FlixyTV.
|
|
platforms: [.iOS(.v26), .macOS(.v26), .tvOS(.v26)],
|
|
products: [
|
|
.library(name: "MediaKit", targets: ["MediaKit"]),
|
|
.library(name: "PlexKit", targets: ["PlexKit"]),
|
|
.library(name: "JellyfinKit", targets: ["JellyfinKit"]),
|
|
.library(name: "FlixyDesign", targets: ["FlixyDesign"]),
|
|
.library(name: "FlixyPlayback", targets: ["FlixyPlayback"]),
|
|
.library(name: "FlixyDownloads", targets: ["FlixyDownloads"]),
|
|
],
|
|
targets: [
|
|
// Sprechen mit dem Server: Anmeldung, Endpunkte, Modelle. Kein SwiftUI,
|
|
// damit die gesamte Protokoll-Schicht ohne Oberfläche testbar bleibt.
|
|
// Die neutrale Grundschicht: Typen und Rechnungen, die für jeden
|
|
// Server gelten. Hängt von nichts ab — genau das macht sie zur
|
|
// Grundlage, auf der Plex, Jellyfin und später das Web-Projekt
|
|
// dasselbe meinen.
|
|
.target(name: "MediaKit"),
|
|
.testTarget(name: "MediaKitTests", dependencies: ["MediaKit"]),
|
|
|
|
.target(name: "PlexKit", dependencies: ["MediaKit"]),
|
|
|
|
// Jellyfin. Eigenes Target neben PlexKit, nicht darin: die beiden
|
|
// teilen die neutrale Schicht und sonst nichts. Wer später Plex
|
|
// herausnimmt, löscht ein Verzeichnis.
|
|
.target(name: "JellyfinKit", dependencies: ["MediaKit"], resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(
|
|
name: "JellyfinKitTests",
|
|
dependencies: ["JellyfinKit"],
|
|
resources: [.copy("Fixtures")]
|
|
),
|
|
|
|
// Ein Werkzeug für die Fragen, die reines HTTP sind — ohne Oberfläche,
|
|
// ohne Gerät, ohne Upload. Eine Runde dauert damit Sekunden statt
|
|
// eines halben Tages, und das Upload-Kontingent bleibt für Builds.
|
|
.executableTarget(name: "FlixyProbe", dependencies: ["MediaKit", "PlexKit", "JellyfinKit"]),
|
|
.testTarget(
|
|
name: "PlexKitTests",
|
|
dependencies: ["PlexKit"],
|
|
// Echte Server-Antworten als Dateien. `copy` statt `process`, weil
|
|
// sie unverändert im Bundle liegen sollen — sonst deutet Xcode die
|
|
// JSON-Dateien um.
|
|
resources: [.copy("Fixtures")]
|
|
),
|
|
|
|
// Farben, Typografie, wiederkehrende Bausteine. Hängt bewusst von
|
|
// nichts ab: dadurch bleibt das Umstellen der Akzentfarbe ein
|
|
// Token-Wechsel und keine Suche quer durch die App.
|
|
.target(name: "FlixyDesign", resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "FlixyDesignTests", dependencies: ["FlixyDesign"]),
|
|
|
|
// Die Wiedergabe-Abstraktion samt AVPlayer-Engine und der Entscheidung
|
|
// DirectPlay/Transcode. VLCKit steckt bewusst NICHT hier drin, sondern
|
|
// in FlixyPlaybackVLC — sonst zöge jeder Testlauf ein 920 MB großes
|
|
// xcframework hinter sich her.
|
|
.target(name: "FlixyPlayback", dependencies: ["MediaKit"]),
|
|
.testTarget(name: "FlixyPlaybackTests", dependencies: ["FlixyPlayback"]),
|
|
|
|
// Warteschlange, Hintergrundübertragung, Offline-Bestand.
|
|
.target(name: "FlixyDownloads", dependencies: ["MediaKit"], resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "FlixyDownloadsTests", dependencies: ["FlixyDownloads"]),
|
|
]
|
|
)
|