# Flixy > Ein nativer Plex-Client für iPhone und iPad — dunkel, mit ausfahrbarer > Seitenleiste und Offline-Downloads. Der Name ist ein Platzhalter. Siehe [`Flixy/Branding.swift`](Flixy/Branding.swift). ## Stand Alle sechs Phasen sind gebaut. Anmeldung, Blättern und Wiedergabe laufen am echten Server; der Rest ist unterschiedlich weit geprüft. Der Fahrplan steht in [`docs/superpowers/specs/2026-09-11-flixy-design.md`](docs/superpowers/specs/2026-09-11-flixy-design.md). | Phase | Inhalt | Stand | |---|---|---| | 0 | Projektgerüst, Design-Tokens, Navigation | ✅ | | 1 | Anmeldung, Bibliothek, DirectPlay | ✅ am Server geprüft, iPhone und iPad | | 2 | Transcoding, adaptive Bitrate, Spuren, Sync | ✅ Wiedergabe geprüft; Transcoding selbst noch nicht erzwungen | | 3 | Download-Engine und Offline-Wiedergabe | ⚠️ Downloads starten, Offline-Wiedergabe noch nicht bestätigt | | 4 | Download-Intelligenz | ⚠️ komprimierte Downloads ungeprüft | | 5 | Feinschliff und Personalisierung | ✅ gebaut, teilweise geprüft | | 6 | Live-TV mit EPG | ⚠️ Empfänger werden gefunden, Sender noch nicht bestätigt | „Ungeprüft" heißt: die Logik ist von Tests abgedeckt, an einem echten Bestand aber noch nicht gesehen. ### Was der Praxistest gelehrt hat Drei Fehler, die kein Test gefunden hätte, weil sie in Annahmen über fremde Bibliotheken steckten — sie stehen als Warnung im jeweiligen Quelltext: - **VLCKit ruft seinen Delegaten vom eigenen Thread**, nicht über die Hauptwarteschlange. `MainActor.assumeIsolated` brach die App beim Drücken auf Play hart ab. - **`app.plex.tv/auth` verknüpft den Code nicht**, wenn man im Browser schon bei Plex angemeldet ist — es springt auf watch.plex.tv weiter. `plex.tv/link` tut es zuverlässig. - **`URLSessionDownloadTask` gilt auch bei 404 als erfolgreich** und legt die Fehlerseite als Datei ab. ## Aufbau Die Xcode-Projektdatei wird aus `project.yml` erzeugt und ist **nicht** eingecheckt — das erspart Konflikte in der `pbxproj`. ```bash xcodegen generate open Flixy.xcodeproj ``` > **Wichtig: Xcode vorher beenden.** > > `xcodegen generate` schreibt `project.pbxproj` neu. Ein geöffnetes Xcode > liest das nicht nach — es hält seinen eigenen Stand im Speicher und > überschreibt die frisch erzeugte Datei beim nächsten Sichern wieder. Neue > Dateien fehlen dann im Build, ohne dass irgendwo ein Fehler auftaucht. > > Das ist der Preis dafür, die Projektdatei aus Git herauszuhalten. Immer wenn > Dateien dazukommen oder `project.yml` sich ändert: Xcode mit ⌘Q beenden, > `xcodegen generate`, neu öffnen. > > Ob der Build aktuell ist, steht in der App unter **Einstellungen → > Diagnose** als Build-Datum. Der Code liegt zum größten Teil in lokalen Packages unter `Packages/FlixyKit`. Das App-Target enthält nur Oberfläche und Navigation. | Modul | Aufgabe | Hängt ab von | |---|---|---| | `PlexKit` | Anmeldung, Endpunkte, Modelle. Kein SwiftUI. | — | | `FlixyDesign` | Farben, Typografie, wiederkehrende Bausteine. | — | | `FlixyPlayback` | Wiedergabe-Abstraktion und die Entscheidung DirectPlay/Transcode. | `PlexKit` | | `FlixyDownloads` | Warteschlange, Hintergrundübertragung, Offline-Bestand. | `PlexKit` | ### Warum zwei Player iOS spielt weder Matroska-Dateien noch DTS- oder TrueHD-Ton — und genau das liegt in typischen Plex-Beständen. `PlaybackDecider` prüft deshalb pro Datei, ob AVPlayer sie nativ öffnen kann (dann gibt es Bild-in-Bild und AirPlay gratis), und schickt sie sonst an VLCKit. Ab Phase 2 kommt der dritte Weg dazu: Server-Transcoding. Dafür ist genau eine Funktion zu erweitern — `PlaybackDecider.decide(media:part:policy:)`. Die Oberfläche bleibt unberührt. ## Tests Die Logik-Tests laufen ohne Simulator, deshalb in Sekunden: ```bash cd Packages/FlixyKit && swift test ``` Die wichtigste Testdatei ist `PlaybackDeciderTests` — sie hält fest, welche Datei auf welchem Weg landet, und schlägt an, sobald jemand `DeviceCapabilities` anfasst. Die Antwort-Vorlagen unter `Tests/PlexKitTests/Fixtures` sind von Hand geschrieben und gehören durch echte Mitschnitte ersetzt, sobald ein Server erreichbar ist — siehe das README dort. Die Oberfläche wird von Hand im Simulator geprüft. ## Was noch am echten Server zu prüfen ist 1. **Komprimierte Downloads.** Sie laufen über den Universal-Transcoder mit `protocol=http` statt über die umständliche Sync-API. Offen: ob Plex eine `Content-Length` mitschickt (ohne sie gibt es keinen Fortschrittsbalken und kein Fortsetzen) und ob die Datei durchsuchbar ist. Original bleibt solange Voreinstellung. Siehe `transcodedDownloadURL` in `PlexServer+Playback.swift`. Ein Fehlschlag erscheint immerhin als solcher — die Plausibilitätsprüfung in `DownloadCoordinator.implausibility` verwirft Fehlerseiten und abgebrochene Übertragungen, statt sie als fertig zu verbuchen. 2. **Live-TV: die Senderliste.** Dass die Empfänger unter `Dvr` gefunden werden, ist geprüft. Ob `/livetv/dvrs/{id}/channels` die Sender liefert, nicht. Die Ansicht unterscheidet beide Fälle: „Kein Empfänger eingerichtet" gegen „Keine Sender" — daran ist ablesbar, wo es hakt. 3. **App-Größe.** Die iOS-Slice von VLCKit ist unstripped 239 MB. Was davon im fertigen Archiv übrig bleibt, ist noch nicht gemessen. 4. **Große Dateien im Hintergrund.** Das Verhalten mit einem 40-GB-Remux — vor allem Pausieren und Fortsetzen — ist nur gegen Testdaten geprüft. ## Voraussetzungen - Xcode 26 oder neuer - iOS 26.0 auf dem Zielgerät - XcodeGen (`brew install xcodegen`) ## Live-TV untersuchen, ohne zu bauen Die Live-TV-Schnittstelle von Plex ist nirgends beschrieben, und jede Vermutung darüber ging bisher als TestFlight-Build hinaus und kam als Screenshot zurück. Irgendwann war das Upload-Kontingent des Tages aufgebraucht — für eine Frage, die keine Oberfläche braucht. ```bash cd Packages/FlixyKit && swift run FlixyProbe ``` Beim ersten Lauf zeigt das Werkzeug einen Code für plex.tv/link; danach liegt der Token im Schlüsselbund dieses Rechners. Es sucht den Server, liest Senderliste und Programm und probiert das Einschalten durch — mit derselben Logik wie die App, nur in Sekunden statt in einem halben Tag. Ausgegeben werden Pfade, Kennungen und die Antworten des Servers. Keine vollständigen Adressen, also auch kein Token.