Die Tabelle stand noch auf „Phase 0 steht". Inzwischen laufen Anmeldung, Blättern und Wiedergabe am echten Server — auf iPhone und iPad. Die offenen Punkte sind jetzt einzeln benannt statt pauschal „ungeprüft". Dazu ein Abschnitt über die drei Fehler, die kein Test gefunden hätte, weil sie in Annahmen über fremde Bibliotheken steckten: VLCKits Thread, die nicht verknüpfende Auth-Seite von Plex, und der Download-Task, der auch bei 404 als erfolgreich gilt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
130 lines
5.5 KiB
Markdown
130 lines
5.5 KiB
Markdown
# 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`)
|