Commit Graph
9 Commits
Author SHA1 Message Date
GuidoandClaude Opus 5 53dacc9f1d Plakate hochkant, Weiterschauen im Querformat
Alle Reihen zeigten Querformat-Kacheln. Für „Weiterschauen" ist das
richtig — man erkennt die Szene wieder, an der man aufgehört hat. Beim
Aussuchen sucht man dagegen nach Plakaten, und die sind hochkant.

Die Unterscheidung hängt an der Hub-Kennung, nicht am Titel: der kommt
in der Sprache des Servers, und die Startseite sähe sonst auf Englisch
anders aus als auf Deutsch, ohne dass jemand auf die Ursache käme.
`ondeck` zählt mit — ältere Serverfassungen nennen es so.

Bei Folgen in Hochkant-Reihen wird das Serienplakat genommen, nicht das
Szenenbild: ein 16:9-Bild hochkant beschnitten zeigt einen zufälligen
Ausschnitt und ist zum Wiedererkennen wertlos.

Plakate sind schmaler als Szenenbilder, damit bei gleicher Höhe mehr
nebeneinander passen — mehr Auswahl auf einen Blick ist der Zweck.

Vier Tests, darunter einer, der festhält, dass der übersetzte Titel die
Form nicht bestimmen darf.

149 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 22:44:13 +02:00
GuidoandClaude Opus 5 ac0c27c026 Fünf Punkte aus dem Praxistest
iPad meldete sich nie an
  Die Ursache ist unangenehm speziell: Wer im Browser schon bei Plex
  angemeldet ist, wird von app.plex.tv/auth sofort auf watch.plex.tv
  weitergeschickt — OHNE dass der Code verknüpft wird. Man sieht sich
  angemeldet, die App wartet vergeblich, und es gibt keinerlei Hinweis.

  Jetzt wird plex.tv/link mit eingetragenem Code geöffnet. Diese Seite
  tut nur eine Sache: den Code bestätigen. Die Gerätekennung steckt
  ohnehin schon im PIN.

  Dazu ein Ausweg: bleibt es nach fünfzehn Sekunden ohne Token, erscheint
  der Code im Anmeldebildschirm zum Abtippen. Schließt man das Fenster
  ohne Erfolg, bleibt er stehen statt abzumelden — er gilt weiter.

Download fragte nicht nach der Qualität
  Jetzt Original, Full HD, HD oder Sparsam, jeweils mit geschätzter
  Größe. Die Größe ist das eigentliche Entscheidungskriterium — „Full HD"
  allein sagt nicht, ob es aufs Telefon passt.
  Die komprimierten Stufen laufen über den Universal-Transcoder und sind
  weiterhin NICHT am Server geprüft; steht so im Quelltext.

Schwarzes Bild ohne Anzeige
  Der Player kannte nur „spielt" und „spielt nicht". Wartete er auf
  Daten, stand man vor einem Standbild ohne Hinweis. Es gibt jetzt einen
  eigenen Pufferzustand mit Anzeige.

Aufmacher war beschnitten
  Er stand auf 3:4, Plex liefert als `art` aber 16:9 — mit scaledToFill
  ging links und rechts je ein Viertel verloren, ohne dass man es dem
  Bild ansah. Die Seitenverhältnisse liegen jetzt an einer Stelle in
  FlixyAspectRatio.

Schwarze Leiste über dem Aufmacher
  .ultraThinMaterial statt undurchsichtigem Grund: das Bild läuft
  unscharf hinter der Leiste weiter, statt an einer harten Kante zu
  enden. Weichgezeichnet, nicht abgedunkelt.

139 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 22:06:51 +02:00
GuidoandClaude Opus 5 bf0a63a924 Vier Punkte aus dem Praxistest
Download-Knopf tat nichts
  DownloadService.plan gab still nil zurück, wenn es keinen Auftrag
  bauen konnte, und download() reichte das als nil weiter. Der Knopf sah
  aus, als wäre er kaputt, dabei war der Grund jedes Mal bekannt. Es
  gibt jetzt einen eigenen Ablehnungsgrund mit vier unterschiedlichen
  Begründungen — keine Verbindung, keine Datei, kein abrufbarer Teil,
  keine Adresse. Eine Funktion, die kommentarlos nichts tut, ist selbst
  der Fehler.

Live-TV galt als „nicht eingerichtet"
  Plex legt die Empfängerliste unter dem Schlüssel `Dvr` ab, die Hülle
  kannte aber nur Metadata, Directory und Hub. Sie las eine leere Liste
  und zog daraus die falsche Schlussfolgerung — auf einem Server, auf
  dem ein Empfänger eingerichtet war. Dasselbe galt für die
  Anbieterliste unter `MediaProvider`, ohne die es keinen
  Programmführer gibt.

  Beim Umbau wäre beinahe die Fehlerdiagnose verloren gegangen: mit
  `try?` über alle Schlüssel verschwände auch ein echter Dekodierfehler
  und ergäbe stillschweigend eine leere Liste. Aus „ein Feld heißt jetzt
  anders" würde „die Mediathek ist leer". Jetzt wird erst geprüft, ob
  der Schlüssel da ist, und dann ohne try? dekodiert. Fünf Tests halten
  beides fest.

Qualität im Player wählbar
  Automatisch, Original, 1080p, 720p, 480p. Der Eingriff wird genau dann
  gebraucht, wenn es ruckelt — dafür will niemand den Film verlassen.
  Ein Wechsel baut den Strom neu auf (die Stufe steckt in der Adresse),
  merkt sich die Stelle und fährt sie wieder an. Der alte Transcoder
  wird vorher angehalten, sonst rechnet der Server zwei Ströme für einen
  Zuschauer.

AVPlayer-Anzeige entfernt
  Sie war eine Prüfhilfe aus Phase 1. Dieselbe Angabe steht weiterhin
  unter Einstellungen → Diagnose, wo sie hingehört.

137 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 21:44:20 +02:00
GuidoandClaude Opus 5 1756ed11cc Anmeldung über die Plex-Seite statt über einen Code
Kein Code mehr zum Abtippen. Die Anmeldemaske kommt von Plex und öffnet
sich über ASWebAuthenticationSession in einem Fenster innerhalb der App;
nach dem Anmelden schickt Plex über forwardUrl auf ein eigenes Schema
zurück, das Fenster schließt sich von selbst.

Der PIN steckt weiterhin darunter — er ist der einzige Weg, auf dem Plex
einen Token herausgibt. Sichtbar ist er nicht mehr.

Was das bringt:
- Kein Fernseher-Gefühl mehr.
- Zwei-Faktor läuft mit, weil Plex die Seite selbst ausliefert.
- Das Passwort erreicht Flixy nie. Steht auch so unter dem Knopf.
- prefersEphemeralWebBrowserSession = false: wer in Safari schon bei
  Plex angemeldet ist, braucht nur zu bestätigen.

Zwei Details, die sonst still scheitern:
- Die Rückadresse wird strenger kodiert als die übrigen Werte. `:` und
  `/` lässt urlQueryAllowed durch, und für Plex endete der Wert dann
  beim ersten Schrägstrich — der Rücksprung käme nie.
- Das Schema muss in CFBundleURLTypes stehen, sonst kennt iOS es nicht
  und das Fenster bliebe offen stehen.

Als Schema die Bundle-Kennung statt eines kurzen Worts wie „flixy":
ein kurzes könnte eine andere App beanspruchen und die Anmeldung
abfangen.

132 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 20:22:52 +02:00
GuidoandClaude Opus 5 b7fc18823a Phase 5: Nachladen, Startseiten-Layout
Nachladen
- DownloadRefiller wählt aus, WELCHE Folgen fehlen; wie viele, rechnet
  die Regel-Engine. Getrennt, weil das Rechnen ohne Server auskommt und
  damit prüfbar ist.
- In Ausstrahlungsreihenfolge, Specials in Staffel 0 bleiben außen vor.
- Läuft nach dem Ansehen und beim Start, nicht auf einem Zeitgeber: eine
  App, die im Hintergrund unaufgefordert Gigabytes lädt, wäre eine
  unangenehme Überraschung auf der Mobilfunkrechnung.

Startseiten-Layout
- Reihen ein-/ausblenden und per Bearbeiten-Modus umsortieren.
- Die Anordnungslogik liegt als HubArrangement in PlexKit statt im
  App-Target — dort ist sie ohne Simulator testbar, und dort sitzen die
  unangenehmen Fälle: neue Reihen vom Server landen am Ende statt zu
  verschwinden, verschwundene aus der gespeicherten Liste stören nicht,
  ein doppelter Eintrag stürzt nicht ab. 11 Tests.

126 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 17:43:20 +02:00
GuidoandClaude Opus 5 55bcfe2fbf Phase 2: Transcoding, adaptive Bitrate, Spuren, Marker, Sync
Der Decider brauchte keine Änderung — nur eine andere Richtlinie.
Genau dafür war er gebaut.

Transcoding
- TranscodeRequest baut die Parameter für /video/:/transcode/universal.
  directStream=1 lässt Plex nur umpacken, wenn der Bildcodec passt,
  statt pauschal neu zu kodieren.
- Vor dem Start wird der Server gefragt (decision); sagt er nein, steht
  der Grund im Klartext da statt eines schwarzen Bildes.
- Beim Verlassen wird der Transcoder angehalten. Ohne dieses Signal
  rechnet der Server minutenlang für niemanden weiter.
- Die adaptive Bitrate kommt mit HLS: AVPlayer wechselt sie selbst.

Qualitätseinstellungen
- Getrennt für WLAN und Mobilfunk, fünf spürbare Stufen.
  Voreinstellung: zuhause Original, unterwegs 4 Mbit.
- NetworkConditions erkennt Mobilfunk über isExpensive — das deckt auch
  den Hotspot ab, der technisch WLAN ist und trotzdem Volumen kostet.

Spuren und Marken
- Ton- und Untertitelwahl im Player, bevorzugte Sprache in den
  Einstellungen, nachsichtiger Sprachvergleich (de/deu/ger/de-DE).
- Intro- und Abspann-Marken mit Überspringen-Knopf, optional
  automatisch. Bereits übersprungene Marken werden gemerkt, sonst käme
  man nach einem Rücksprung nie ins Intro zurück.
- Nächste Folge inkl. Staffelwechsel; Specials in Staffel 0 werden
  nicht vorgezogen.

Fortschritt
- Alle zehn Sekunden an den Server, plus Schlussmeldung beim Verlassen.
  Erst die nimmt den Titel aus „wird gerade abgespielt" heraus.
- markWatched/markUnwatched/rate/refreshLibrary stehen bereit.

86 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 17:24:17 +02:00
GuidoandClaude Opus 5 d0a84f35de Drei Fehler aus dem ersten Praxistest
Anmelde-Adresse wurde doppelt kodiert
  URLComponents.fragment kodiert beim Setzen erneut, aus %5B wurde
  %255B. Plex antwortete mit „Diese Anfrage konnte nicht abgeschlossen
  werden". Die Adresse wird jetzt von Hand zusammengesetzt.

Verbindungssuche hing bis zu anderthalb Minuten
  probeTimeout war deklariert, aber nirgends angewendet — es galt der
  URLSession-Standard von 60 Sekunden. Zusammen mit der Prüfung Rang
  für Rang kostete eine schweigende lokale Adresse die volle Zeit,
  bevor der direkte Weg überhaupt begann. Jetzt laufen alle Adressen
  gleichzeitig, mit Zeitgrenze, und die Rangordnung entscheidet unter
  den erreichbaren.

Kein Zurück während des Ladens
  Die Kopfzeile mit dem Schließen-Knopf wurde nur im Zustand .playing
  gezeichnet. Bei langsamer Verbindung saß man ohne Ausweg vor einem
  Ladekreis. Sie liegt jetzt als eigene Ebene darüber und erscheint
  auch beim Vorbereiten — samt Titel, damit erkennbar bleibt, worauf
  gewartet wird.

Sechs neue Tests, darunter drei, die die Zeitgrenze der
Verbindungssuche an einer schweigenden Adresse nachstellen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 17:17:18 +02:00
GuidoandClaude Opus 5 9a69df4635 Phase 1: Anmeldung, Bibliothek, Detailseiten, Hybrid-Player
Die Datenschicht:
- plex.tv-Anmeldung über das PIN-Verfahren, Token im Schlüsselbund
- Serversuche und Verbindungsauswahl nach Rang (lokal vor direkt vor
  Vermittlung), mit Abgleich der Server-Kennung gegen veraltete
  plex.direct-Adressen
- PlexServer als einzige Stelle, an der die App Endpunkte kennt:
  Mediatheken, Hubs, seitenweises Blättern mit Filtern, Metadaten,
  Staffeln/Folgen, Suche

Die Oberfläche:
- Startseite mit Aufmacher und den Reihen vom Server
- Mediathek als Raster oder Liste, mit Filter- und Sortierblatt
- Detailseiten für Filme, Folgen, Serien und Staffeln inkl. Besetzung,
  Fassungsauswahl und aufklappbaren technischen Angaben
- Suche mit gemerkten Anfragen
- Vollbildplayer mit eigenem Chrome

Der Player:
- AVPlayerEngine und VLCPlayerEngine hinter einem gemeinsamen Protokoll
- VLCKit liegt in einem eigenen Package (FlixyVLC), damit `swift test`
  in FlixyKit nicht das 920-MB-Binärpaket mitzieht

Am echten plex.tv geprüft: der Anmeldecode kommt an. Dabei fiel auf,
dass `strong=true` einen dreißigstelligen Code liefert, der sich bei
plex.tv/link nicht eintippen lässt — jetzt der kurze.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 16:46:28 +02:00
GuidoandClaude Opus 5 1ed64bf166 Phase 0: Projektgerüst, Design-Tokens und Navigation
Legt das Fundament für den Plex-Client an:

- XcodeGen-Projekt nach dem Muster von Onyx (com.scarriffleservices,
  strict concurrency, Projektdatei nicht eingecheckt)
- FlixyKit mit vier Modulen: PlexKit, FlixyDesign, FlixyPlayback,
  FlixyDownloads. macOS steht als Plattform mit drin, damit die
  Logik-Tests ohne Simulator laufen.
- FlixyDesign: dunkle Farb-Tokens, Schriftskala, Poster- und
  Querformat-Kacheln, Aufmacher-Bild. Die Akzentfarbe fließt über die
  Umgebung und wird per WCAG-Rechnung lesbar gehalten.
- PlexKit: Kopfzeilen-Identität, Transport-Protokoll, Fehlerarten und
  die Medienmodelle samt nachsichtigem Decoder.
- FlixyPlayback: VideoPlayerEngine-Protokoll und PlaybackDecider — die
  eine Funktion, an der Phase 2 das Transcoding andockt.
- Ausfahrbare Seitenleiste auf dem iPhone, Split-View auf dem iPad.
- 45 Tests, alle grün.

VLCKit 4.0.0-a24 ist vorab geprüft: baut über SPM unter Swift 6 mit
strict concurrency. Die iOS-Slice ist mit 239 MB allerdings gewichtig,
deshalb bekommt sie in Phase 1 ein eigenes Target.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 16:04:40 +02:00