2fcf6821c8c8013a28cc214b22d184526dee5459
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2fcf6821c8 |
Plex ist raus — und nahm zwei stille Fehler mit
Vollständig entfernt: das Paket `PlexKit` samt 108 Tests, der Web-Authenticator, die Anmeldung über plex.tv, die Serverauswahl und alles, was daran hing. 43 Dateien gelöscht, 68 Stellen in 28 weiteren bereinigt. **Zwei Dinge hätten beim blossen Streichen still das Falsche getan.** `playbackUnavailableMessage` deckte im Else-Zweig zwei Lagen gleichzeitig ab — „es ist Plex" und „niemand ist angemeldet". Wer die Serverart naiv herausstreicht, bekommt als nicht angemeldeter Nutzer „Jellyfin-Wiedergabe steht aus" statt „Server nicht erreichbar". Die Unterscheidung hängt jetzt daran, ob überhaupt ein Server da ist. Die Schlüsselbund-Einträge `plex.account` und `plex.server` wurden allein über den Authenticator aus dem gelöschten Paket entfernt. Danach stünde `plex.account` in keiner Zeile dieses Projekts mehr: wer sich nie abgemeldet hat, trüge ein gültiges Token am fremden Konto bis in alle Ewigkeit mit sich, ohne dass irgendein Weg es noch löschen könnte. `purgePlexLeftovers()` räumt beide Token und fünf Voreinstellungen einmalig ab — und fasst nichts an, wo nichts liegt, damit kein Jellyfin-Nutzer dafür seinen Mediathekenspeicher verliert. **Was Nutzer sehen.** Die Berechtigungsfrage fürs lokale Netz sagte wörtlich, die App brauche es, „um deinen Plex-Server zu finden" — das stand so im Systemdialog. Der Anmeldebildschirm hatte zwei Knöpfe, und der hervorgehobene war der für Plex; der verbliebene erbt die Hervorhebung, denn ein Knopf, der aussieht wie die zweite Wahl, lässt nach der ersten suchen. 14 verwaiste Textbausteine sind weg, vier umformuliert. Darunter einer, der schlicht nicht mehr stimmte: `signIn.privacy` versprach, das Passwort erreiche diese App nie. Beim Jellyfin-Rückfall auf das Passwort tut es das sehr wohl. Die Zusage, die weiterhin gilt, ist die über fremde Dienste — und nur die steht jetzt da. **Was ausdrücklich bleibt:** `MediaBackend`. Diese Abstraktion hat zwei Server gleichzeitig getragen, und der Steckplatz, den Plex räumt, ist genau der, auf den Halo kommt. `ServerKind` fällt dagegen weg — mit einem Fall ist es ein Bool, das `backend != nil` schon beantwortet. Nebenbei zog die README nach. Sie beschrieb noch einen „nativen Plex-Client" mit zwei Playern und VLCKit, beides seit Längerem nicht mehr wahr. 368 Tests grün (von 476 minus die 108 aus PlexKitTests, kein anderer). iOS und tvOS bauen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6b927c21b0 |
VLC ist weg — es gibt nur noch einen Spieler
Du hattest recht mit der Erwartung, nur nicht mit dem Stand: entfernt war er nicht. Was wir gemacht haben, war, ihm Arbeit wegzunehmen — DTS, TrueHD und Vorbis gehen seit Kurzem über das Umpacken beim Server. Übrig blieb er an einer Stelle, `PlaybackDecider.fallback`. Jetzt ist er ganz weg, samt dem 920-MB-Binärpaket. **Was an seine Stelle tritt.** Die Entscheidung sagt nicht mehr, *wer* spielt, sondern *was ankommt*: direkt, umgepackt oder umgerechnet. `PlaybackEngineKind` fällt damit weg, `directPlay` trägt keine Engine mehr, und `PlaybackPolicy` kennt kein `allowsFallbackEngine`. **Das Auffangnetz bleibt, nur anders geknüpft.** Scheiterte das Umpacken am Player, sprang bisher VLC ein — der Server entscheidet erst beim Ausliefern, ob er die Ströme wirklich kopieren kann, und manche Antworten nimmt AVPlayer nicht an. Statt der zweiten Engine rechnet der Server jetzt neu (`fallBackToTranscode`). Teurer für ihn, aber es kommt etwas an, statt einer schwarzen Wand mit einer Fehlernummer. **Offline wäre das ein Rückschritt gewesen** — dort gibt es keinen Server, der einspringt. Deshalb ging der vorige Commit voraus: was heruntergeladen wird, kommt schon in einer Hülle, die der Systemplayer öffnet. Was dadurch überall gilt, auch für Dateien, die bisher bei VLC landeten: Bild-in-Bild, AirPlay, Bedienung im Sperrbildschirm — und dasselbe Verhalten auf dem Apple TV, wo es VLC ohnehin nie gab. Die Attrappe heißt ihren Schalter jetzt `--dts` statt `--vlc`: der Fall ist geblieben, sein Ziel nicht. iOS und tvOS bauen, 494 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6010229b80 |
Die Pakete wissen jetzt, was ein Fernseher ist
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> |
||
|
|
afab93f53a |
FlixyProbe kann die Leiter zählen
Die Frage, von der alles Weitere abhängt, ist eine Tatsachenfrage: Liefert der Server eine HLS-Liste mit mehreren Stufen oder mit einer? Sie über einen Build aufs Gerät zu beantworten kostet einen halben Tag; über HTTP kostet sie Sekunden. Genau dafür gibt es dieses Werkzeug. `--playlist <adresse>` holt eine Playlist und zählt die `EXT-X-STREAM-INF`-Zeilen mitsamt Bandbreite und Auflösung. Es unterscheidet dabei die drei Fälle, die man auseinanderhalten muss: eine Master-Playlist mit mehreren Stufen, eine mit genau einer — und eine Varianten-Playlist, die gar keine Stufen führt, sondern Schnipsel. Die letzte Verwechslung ist die naheliegende: `main.m3u8` sieht aus wie eine Playlist und ist die falsche. `--jellyfin <host>` meldet sich an, holt einen Film, lässt den Server eine Transcode-Adresse aushandeln und prüft sie dreimal: unverändert, als `master.m3u8`, und als `master.m3u8` mit `enableAdaptiveBitrateStreaming=true`. Damit steht danach fest, ob der Umbau in JellyfinBackend überhaupt etwas bringen kann. Das Passwort wird eingetippt statt übergeben, ohne Echo und ohne Ablage. Gedruckt werden Pfad und die **Namen** der Abfragewerte, nie die vollständige Adresse mit Schlüssel — dieselbe Regel, nach der das Werkzeug schon vorher gebaut war. Beide Modi laufen vor der Plex-Anmeldung: die eine Frage hat mit Plex nichts zu tun, die andere bringt ihre eigene Anmeldung mit. Der Leser selbst ist gegen drei erfundene Playlists geprüft — mehrstufig, einstufig, und eine Schnipselliste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5696254034 |
Jellyfin: der Anmeldebildschirm bietet jetzt beides an
Der Anmeldebildschirm kannte nur Plex. JellyfinKit war fertig, aber von der App aus nicht erreichbar — „ich sehe nix von Jellyfin". Quick Connect steht vorn: der Server nennt einen sechsstelligen Code, den man in einem bereits angemeldeten Client bestätigt. Das Passwort erreicht Flixy dabei nie, dieselbe Zusage wie bei Plex. Benutzername und Passwort sind der Rückfall für Server, auf denen Quick Connect abgeschaltet ist; das Passwort wird dann für die Dauer einer Anfrage gehalten und danach weggeworfen. Die Adresse wird nicht erraten, sondern durchprobiert. „192.168.1.50" kann alles Mögliche heißen, und die Reihenfolge ist der Kern von JellyfinAddress: eine IP-Adresse im eigenen Netz spricht fast nie HTTPS, ein Domänenname fast immer. Andersherum wartet man bei jedem Server ohne Zertifikat erst auf eine Zeitüberschreitung. Die Sitzung hält von hier an einen Server hinter dem neutralen Vertrag, nicht mehr einen Plex-Server. Die Ansichten haben das nicht gemerkt — genau dafür war MediaKit da. Dabei fällt ab, was Jellyfin kann und Plex nicht: Favoriten stehen im Aktionsmenü, sobald der Server sie kennt, Sterne nur dort, wo es sie gibt. Was noch nicht geht und deshalb auch nicht behauptet wird: Wiedergabe und Live-TV sprechen weiter unmittelbar mit Plex. Bei Jellyfin verschwindet der Live-TV-Eintrag aus der Seitenleiste, und der Player sagt, dass die Wiedergabe der nächste Schritt ist, statt „Server nicht erreichbar" zu melden — er ist ja erreichbar. Nebenbei zwei Stellen, die der Übersetzer aus Plex hinterlassen hat: `catch is CancellationError` griff seit den getippten Fehlern nie mehr, weil eine abgebrochene Netzanfrage als Übertragungsfehler zurückkommt; und das Ersatz-Hintergrundbild einer Folge war toter Code, weil die linke Seite des `??` gar nicht optional war. TokenStore wandert nach MediaKit — Tokens sind nichts Plex-Eigenes. Die Konten sind nach Server getrennt, damit ein späteres Umschalten nicht jedes Mal eine neue Anmeldung kostet; „Abmelden" räumt trotzdem beide ab. 248 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9540f26dd8 |
JellyfinKit: anmelden, stöbern, übersetzen
Der zweite Server. Eigenes Target neben PlexKit, nicht darin — die beiden teilen die neutrale Schicht und sonst nichts. Die Anmeldung geht zuerst über **Quick Connect**: die App zeigt einen sechsstelligen Code, den man in einem bereits angemeldeten Client bestätigt. Damit gilt hier dieselbe Zusage wie bei Plex — das Passwort erreicht Flixy nie. Benutzername und Passwort bleiben als Rückfall, falls der Server Quick Connect abgeschaltet hat; dann hält die App das Passwort für die Dauer einer Anfrage und speichert es nirgends. Zwei Stellen, an denen sich eine Übersetzung verrechnet, und die deshalb Tests haben: Jellyfin zählt Zeiten in Ticks zu hundert Nanosekunden. Eine Null zu viel, und aus 44 Minuten werden siebeneinhalb Stunden. Und es meldet die **ungesehenen** Folgen, nicht die gesehenen. Ungeprüft übernommen stünde bei einer fast fertigen Serie „9 von 24" statt „15 von 24". Dass die Adressen den Token tragen, steht hier von Anfang an — bei Plex hat genau das tagelang gekostet, weil AVPlayer keine Kopfzeilen mitschickt. Zwei Fähigkeiten sind ausdrücklich nicht da: Sterne-Bewertungen kennt Jellyfin nicht, nur Daumen hoch und runter. Und die Adresse einer verkleinerten Fassung gibt es erst nach einer Anfrage — sie zu erfinden hieße, eine Adresse anzubieten, die nicht antwortet. Die Startseite ist nachsichtig gebaut: fällt „Als Nächstes" aus, bleibt deshalb nicht die ganze Seite leer. Die App bietet Jellyfin noch nicht an — das ist der nächste Schritt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5b2b86b66b |
MediaKit: die Grundschicht, auf der Plex und Jellyfin dasselbe meinen
Erster Schritt zu Jellyfin, und er besteht vor allem aus Wegnehmen. `PlaybackDecider` nahm bisher Plex-Modelle entgegen und las daraus sechs Felder. Das band die Entscheidung an einen bestimmten Server, obwohl an der Frage „kann iOS das öffnen?" nichts serverspezifisch ist. Jetzt nimmt er ein `MediaProfile` — Container, Codecs, Bitrate, ob die Datei untersucht ist. Wie ernst die Kopplung war, zeigte der Player selbst: für die Offline-Wiedergabe baute er sich **erfundene** Plex-Werte zusammen — eine Media mit Kennung 0, ein Part mit dem Dateinamen als Schlüssel, zusammengesetzte Spurlisten —, nur damit die Signatur passte. Für eine Datei, die längst auf dem Gerät lag und mit Plex nichts mehr zu tun hatte. Dieser Hack ist weg. Neu ist das Target `MediaKit`: Typen und Rechnungen, die für jeden Server gelten, ohne eine einzige Abhängigkeit. Darin `MediaProfile` und die `Duration`-Brücke, die bisher in PlexKit stand — „weil es die unterste Schicht ist". Das stimmte, solange es nur einen Server gab. Damit kennen Wiedergabe und Downloads Plex nicht mehr. Zwei der Abhängigkeiten waren ohnehin tot; die dritte trug nur diese Brücke. Die wichtigste Testtabelle des Projekts ist mitgewandert und dabei kürzer geworden: dort steht jetzt, worauf es ankommt, statt vollständiger Modelle mit Kennungen und Dateipfaden, von denen niemand etwas las. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
12bb49615b |
Player: die Qualitätsleiter des Servers, Bitrate im Blick, Doppeltipp
Die vier erfundenen Stufen weichen der Leiter, die der Server selbst meldet: 64, 96, 208, 320, 720, 1500, 2000, 3000, 4000, 8000, 10000, 12000, 20000 kbps mit den Auflösungen, die Plex dafür vorsieht. Eine eigene Leiter hieße, Stufen anzubieten, die der Transcoder nicht kennt — er rundet dann still auf die nächste, und die Anzeige log. Angeboten wird nur, was zur Quelle passt. Eine 720p-Datei auf 1080p hochzurechnen bringt kein Bild dazu, und die Stufen sähen alle gleich aus. Oben im Blatt steht, was tatsächlich über die Leitung kommt — gemessene Bitrate, Auflösung, verworfene Bilder. Der Unterschied zur gewählten Stufe ist keine Haarspalterei: die eine sagt, was erlaubt ist, die andere, was ankommt. Ruckelt es trotz hoher Stufe, steht die Antwort dort. „Nur Ton" gibt es, aber ehrlich beschriftet: Plex kennt für Videos keinen reinen Tonstrom, also wird die unterste Sprosse geholt und das Bild ausgeblendet. Dazu Doppeltipp links und rechts für zehn Sekunden zurück und vor. Die Reihenfolge der Gesten ist entscheidend — das einfache Tippen verschluckt sonst das doppelte. Die Kachel hängt nicht mehr in vier Ecken fest, sondern klebt links oder rechts und ist in der Höhe frei. Vier Ecken sind schnell gebaut, aber im Weg: steht sie über einem Knopf, bleiben drei Orte, die ebenso stören. Größer wird sie durch Zusammen- und Auseinanderziehen; der Griff ist weg, er saß zwangsläufig auf dem Bild und stritt sich mit dem Verschieben. Und die Begriffe: „Motor" für engine sagt kein deutscher Entwickler. Fachwörter, die im Deutschen englisch bleiben, bleiben jetzt englisch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
03a8d1f899 |
Ein Werkzeug für die Fragen, die reines HTTP sind
Das Upload-Kontingent des Tages ist aufgebraucht — verbraucht von meinen eigenen Vermutungen über eine Schnittstelle, die keine Oberfläche braucht. Jede Runde ging als TestFlight-Build hinaus und kam als Screenshot zurück. `swift run FlixyProbe` macht dasselbe in Sekunden: anmelden, Server suchen, Senderliste und Programm lesen, das Einschalten durchprobieren — mit derselben Logik wie die App. Der Token kommt über die übliche Anmeldung und liegt im Schlüsselbund dieses Rechners; gedruckt werden Pfade, Kennungen und Antworten, keine vollständigen Adressen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6150b018ec |
Vier Punkte: Player-Hänger, kaputte Downloads, Stufenliste, Kopfleiste
Player hing sich auf Die Qualitätsauswahl war ein Menu. Schloss man es durch einen Tipp ins Bild, blieb eine unsichtbare Ebene zurück, die alle weiteren Tipps schluckte — die Bedienelemente kamen nicht mehr, pausieren ging nicht mehr. Jetzt ein confirmationDialog, der sich selbst wegräumt. Nach dem Schließen werden die Bedienelemente eingeblendet und die Ausblendfrist neu gestartet. Downloads galten als fertig, waren aber leer Zwei Fehler übereinander. Erstens gilt ein URLSessionDownloadTask auch bei 404 oder 500 als erfolgreich und legt die Fehlerseite als Datei ab. Zweitens überschrieb ich danach die erwartete Größe mit der empfangenen — womit die Anzeige auf hundert Prozent stand und der Beweis weg war. 873 MB waren in einer Sekunde „fertig", und beim Abspielen kam nur „Wiedergabe wurde unterbrochen". Jetzt wird der Statuscode geprüft, die erwartete Größe bleibt stehen, und eine unplausible Datei wird verworfen statt verbucht: unter 100 KB ist keine Videodatei, unter der Hälfte der angekündigten Größe ist eine abgebrochene Übertragung. Sechs Tests dazu. Stufenliste ergab keinen Sinn Für einen 720p-Inhalt standen Original, Full HD und HD mit derselben geschätzten Größe untereinander — das sah aus, als wäre die Schätzung kaputt. Sie war es nicht, die Stufen waren es: hochrechnen bringt nur eine größere Datei. Angeboten wird jetzt nur noch, was unter der Auflösung der Datei liegt, und beim Original steht dabei, was es ist: „Original · 720p · 873 MB". Kopfleiste Kein Hintergrund mehr statt eines weichgezeichneten — die Knöpfe bringen ihre eigene Glasfläche mit. Der Titel ist weg: der Name der App gehört auf den Homescreen, nicht über jeden Bildschirm. 145 Tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
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> |