Bei einer lokalen Datei kehrte der Spieler zurück, sobald sie lief — und
liess `item` leer. Daran hing mehr als der Titel: keine Marken, also kein
„Intro überspringen"; keine Nachbarfolgen, also keine Knöpfe zum Blättern.
Nur bei Heruntergeladenem, und darum sah es so lange nach einem Fehler in
der Erkennung aus. Jetzt werden die Angaben nachgeholt, während das Bild
schon läuft.
Dazu, was derselbe Weg betrifft: der Spieler sagt „Staffel 1 · Folge 6"
statt „S1 E6" — der Folgenname wird an einer Stelle gebaut, nicht an
dreien. Im Abspann einer Serie stehen zwei Knöpfe statt einem, weil der
Abspann zwei Fragen stellt.
Und die Abdrücke, mit denen der Tonabgleich geprüft wird, sind jetzt
echte: zwei Aufnahmen desselben dreissigsekündigen Stücks, verschiedene
Bitraten, durch fpcalc gedreht. Vorher war jede Prüfung mit erfundenen
Zahlen bestanden — und genau deshalb war nie belegt, dass der Abgleich an
echten Daten etwas findet. Er findet: 17,8–51,0 s und 72,7–105,9 s, bei
20–50 und 75–105.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
„Intro überspringen" lag im Web in der Bedienleiste und verschwand mit
ihr. Am Fernseher sieht man die Leiste gar nicht — der Knopf war also
da und trotzdem unsichtbar. Jetzt liegt er als eigene Schicht über dem
Bild und bleibt stehen, solange die Marke läuft.
**Im Abspann ist „überspringen" ohnehin die falsche Frage.** Was man
dort will, ist die nächste Folge; ans Ende dieser zu springen bringt
niemanden weiter. Gibt es eine, heisst der Knopf jetzt so — im Web wie
in der App, und in der App nicht mehr erst, wenn alles durchgelaufen
ist. Bei einem Film gibt es nichts danach: dort heisst „Abspann
überspringen" jetzt wirklich Schluss, statt auf ein stehendes Bild zu
spulen und den Spieler offen zu lassen.
Dazu der Titel über dem Spieler. Dort stand bei einer Folge „S1 E6" und
bei einer aus der Detailseite gestarteten sogar nur „Wiedergabe". Auf
einer Kachel ist die Kurzform richtig, dort zählt jeder Buchstabe; über
dem Spieler steht eine Zeile in einer leeren Fläche. Jetzt steht da
„Küstenwache · Staffel 1 · Folge 6 · Der Nebel kommt". In der App hiess
es „Episode" statt „Folge" — das eine Wort, das sonst nirgends steht.
Und drei Prüfungen für die Marken auf dem Weg in die App: aus einer
Serverantwort mit Vorspann und Abspann werden zwei Marken an der
richtigen Stelle. Die Übersetzung war nicht der Grund, warum der Knopf
dort fehlte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
**Der Aufmacher darf wechseln.** Bisher hing hinter jedem Titel genau ein
Hintergrundbild, und das Karussell war nach einer Woche ein Standbild.
Jetzt lassen sich bis zu fünf Aufnahmen aussuchen — im Bilderdialog unter
einem vierten Reiter, gespeist aus denselben Hintergründen.
Welches gerade gilt, entscheidet der Server aus Uhrzeit und Kennung: alle
fünf Stunden ein anderes, überall dasselbe — im Web, in der App, nach
einem Neustart. Ein Zufall je Abruf hiesse, dass das Bild beim Blättern
springt; eine gespeicherte Wahl hiesse einen Schreibvorgang je Titel und
Fenster. Die Kennung geht mit in die Rechnung, damit nicht alle Titel im
selben Augenblick umschalten.
Plakat und Hintergrund bleiben unberührt. Sie stehen hinter Kacheln und
Kopfzeilen, und dort soll nichts wechseln.
**Und der Abspann zählt als Schluss.** Eine Serie hängt sechs Minuten
Abspann an eine Folge von fünfundvierzig; neunzig Prozent liegen dann
mittendrin, und die Folge gilt erst als gesehen, wenn man ihn sich ganz
ansieht. Die Schwelle herunterzudrehen hiesse, jeden anderen Titel zu
früh abzuhaken. Der erkannte Abspann ist die genauere Antwort auf
dieselbe Frage — er zieht die Schwelle nach vorn, nie nach hinten.
Dazu der Verlauf über dem Aufmacher: er war immer noch zu dunkel. Jetzt
trägt der Schattenwurf der Schrift, was vorher eine Decke über dem
ganzen Bild tat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beides mit derselben Rechnung, nur in einem anderen Fenster: vorn die
ersten fünfzehn Minuten, hinten die letzten zehn. Was `Tonabgleich`
findet, hängt allein daran, welchen Ausschnitt man ihm gibt — eine
zweite Erkennung für den Abspann wäre dieselbe Suche ein zweites Mal.
Je Staffel verglichen, nicht je Serie: Serien wechseln ihren Vorspann
zwischen Staffeln, und über alle hinweg fände man nichts oder das
Falsche. Gefundenes über fünf Minuten wird verworfen — zwei Folgen, die
dieselbe Datei tragen, teilen vierzig, und darüber stünde sonst ein
Überspringen-Knopf.
Der Lauf geht auf Zuruf, nicht bei jedem Scan: er liest von jeder Folge
ein Stück Ton und dauert Minuten. Der Knopf dafür steht auf der
Serienseite, bei den Verwalterknöpfen.
Die Marken gehen im Folgenvertrag mit — als „intro" und „credits", die
Wörter, die die Apps von Jellyfin her ohnehin kennen. In der App zeichnet
sie der vorhandene Überspringen-Knopf, der bisher nie etwas zu tun
hatte; im Web ist er neu, rechtsbündig über der Zeitleiste.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Beschwerden, zwei Ursachen.
**„Niedrig" war nicht niedrig.** Mit 62 vh war es mittel mit anderem
Namen; die Spanne reichte nur nach oben, weil die fünfte Stufe damals
oben gebraucht wurde. Darunter steht jetzt „Flach" mit 46 vh — für den,
der den Aufmacher als Kopfzeile will und nicht als halbe Seite.
**Der Verlauf fing auf halber Höhe schon mit 55 % Deckung an** und wurde
erst bei 85 % durchsichtig. Von einem starken Bild blieb dadurch vor
allem Grau übrig. Jetzt kurz und steil: unten dunkel genug, dass die
Schrift trägt, und die obere Hälfte frei. Der Text sitzt unten links —
genau dort muss es tragen, und darüber nicht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Sprachwahl einer Serie steht zwischen dem Kopf und den Staffeln und
hatte als einziger Abschnitt dort keinen Abstand nach unten. Jetzt
denselben wie jeder andere.
Dazu: der Hinweissatz darunter verschwindet, wenn er leer ist. Ein leeres
Feld nimmt sonst Platz für einen Satz, den es nicht gibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vorher: eine Liste von Tagen, je Tag drei Knöpfe, und erst nach „Ansehen"
stand irgendwo Text. Wer wissen wollte, was gerade schiefgeht, brauchte
drei Handgriffe für eine Antwort, die auf der ersten Seite hätte stehen
können.
Jetzt ist „Protokolle" eine Liste von Ereignissen, wie man sie aus Home
Assistant kennt: der heutige Tag sofort und offen, neueste Zeile oben —
damit man zum Mitlesen nicht scrollen muss —, und alle vier Sekunden
kommt dazu, was dazugekommen ist. Fehler und Warnungen tragen die Farbe
am Rand statt im Text; eine ganze Zeile in Rot liest sich schlechter als
eine in Grau mit rotem Strich.
Die früheren Tage stehen darunter als Kacheln zum Herunterladen. Der
heutige nicht: er steht schon oben, und eine zweite Tür zum selben Raum
ist keine Hilfe.
Mehrzeiliges — ffmpeg schreibt gern vier Zeilen — hat keinen eigenen
Zeitstempel und gehört zur Zeile darüber. Es wird eingerückt gezeigt
statt verworfen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die verstrichene Zeit stand hinter dem Lautstärkeregler — „1:51:01"
direkt neben einem Schieber liest sich wie dessen Beschriftung — und die
verbleibende ganz rechts hinter den Menüs. Zwei Angaben über dieselbe
Sache, so weit auseinander wie möglich.
Jetzt stehen sie dort, wo man ohnehin hinsieht: links und rechts vom
Knopf, den man drückt.
Drei Spalten statt drei Flex-Kinder, denn die Mitte soll die Mitte des
Bildes sein und nicht die Mitte dessen, was links und rechts übrig
bleibt. Mit `space-between` wanderte der Knopf, sobald rechts ein Menü
dazukam oder links die Lautstärke wegfiel.
Schmal weicht, was man auch anders bekommt: die Lautstärke liegt am
Telefon auf einer Taste, und die verbleibende Zeit lässt sich an der
Leiste ablesen. Der Knopf in der Mitte weicht nicht — dort sucht ihn der
Daumen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die verstrichene Zeit stand hinter dem Lautstärkeregler, die verbleibende
ganz rechts hinter den Menüs. „1:48:20" direkt neben einem Schieber für
Lautstärke liest sich wie dessen Beschriftung — und die zweite Zahl, die
dazugehört, war einen halben Bildschirm entfernt.
Beide stehen jetzt links und rechts von dem Balken, über den sie Auskunft
geben. Schmal weicht die verbleibende Zeit; dort ist der Balken wichtiger
als die zweite Zahl.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
**Man konnte nicht sehen, ob ein Schlüssel wirkt.** Nach dem Eintragen
stand „Hinterlegt" da, und das war alles. Ob er stimmt, ob der Dienst
antwortet, ob zu einem Film überhaupt etwas zu holen ist — herausfinden
liess sich das nur, indem man die Metadaten über achthundert Titel
auffrischte und danach nachsah, ob sich etwas geändert hatte.
Jetzt gibt es „Verbindung prüfen". Es wird mit „The Matrix" gefragt, nicht
mit einem Film aus der Mediathek: der könnte schlicht unbekannt sein, und
dann wüsste man wieder nicht, ob es am Schlüssel liegt oder am Film. Die
Antwort nennt, was zurückkam — bei fanart.tv die Zahl der Plakate und
davon die in der eingestellten Sprache, denn genau dafür ist die Quelle da.
Gemessen am laufenden Server:
tmdb eingerichtet ok Erreichbar — Probeabruf ergab The Matrix (1999).
fanart — — Kein Schlüssel hinterlegt — die Quelle ist aus.
omdb — — Kein Schlüssel hinterlegt — die Quelle ist aus.
**Und die Übersicht war eine Ablage für alles geworden.** Zu Recht
angemerkt: es gibt eine Seite „Metadaten", und die Zugänge standen trotzdem
unter „Übersicht" — zwischen Servername, doppelten Einträgen, Fassung und
Speicherplatz. Die drei Quellen stehen jetzt dort, wo man sie sucht, jede
mit einem Satz dazu, was sie liefert und was sie dafür braucht.
Aufmacherhöhe und saisonale Reihen bekommen einen eigenen Bereich
„Darstellung". Eine Seite, die „Übersicht" heisst, ist nicht der Ort für
alles, was sonst nirgends passt.
**Am Telefon tat die Aufmacherhöhe gar nichts.** Gemeldet als „auf 100 %
ist es immer noch zu niedrig" — und das stimmte buchstäblich: unter 860
Pixeln Breite stand `height: min(52vh, 420px)` fest und überschrieb die
Einstellung vollständig. Ob „niedrig" oder „sehr hoch", es kamen immer
dieselben 52 vh heraus.
Jetzt hat jede Stufe zwei Höhen, eine fürs breite und eine fürs schmale
Bild; am Telefon fällt sie eine Spur flacher aus, weil der Bildschirm
hochkant ist und derselbe Anteil der ersten Kachelreihe dort den Platz
nähme. Dazu eine fünfte Stufe „Bildschirmhoch" — mehr ginge nicht
sinnvoll, darüber ist es kein Aufmacher mehr, sondern die ganze Seite.
Eine Prüfung hält ausserdem fest, dass ein Film ohne passendes Stichwort
und ohne passendes Genre nicht in der saisonalen Reihe steht. Anlass war
die Meldung, dort stünden harmlose Zeichentrickfilme — die Reihe arbeitet
richtig, sie macht nur sichtbar, wenn ein Titel auf den falschen Eintrag
zugeordnet ist.
765 Tests grün.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
IMDbs eigene Schnittstelle kostet Geld, Rotten Tomatoes vergibt Zugänge nur
an Partner, Letterboxd hat gar keine offene. OMDb liefert alle drei in
einer Antwort, über die IMDb-Kennung, die ohnehin schon an jedem Film steht.
**Eine Tabelle und kein Feld je Quelle.** `Movie.Rating` ist ein Skalar
ohne Quellenangabe, und das war richtig, solange es eine Quelle gab. Für
drei weitere wären es drei Spalten — und bei der vierten wieder eine
Migration. Jetzt ist jede Quelle eine Zeile, je Titel und Quelle eine, mit
eindeutigem Index darauf: ein zweiter Lauf schreibt um statt anzuhäufen.
**Zwei Werte je Bewertung, und beide gebraucht.** Der normierte Wert zum
Vergleichen und Sortieren, die Anzeige zum Hinschreiben. Rotten Tomatoes in
„8,7 von 10" umzurechnen wäre eine Lüge über die Quelle — dort steht 87 %,
und genau so kennt man es.
**Wieder keine zweite Metadatenquelle.** `IBewertungsquelle` liefert
Bewertungen, sonst nichts. Bei Titel und Beschreibung wären zwei Anbieter
zwei Wahrheiten; bei einer Bewertung ist jede Quelle eine eigene Zahl, und
da sind mehrere kein Widerspruch, sondern der Sinn der Sache.
**Ohne Kennung wird nicht gefragt.** OMDb kennt nur den Weg über die
IMDb-Kennung; nach einem Titel zu suchen hiesse, denselben Zuordnungsfehler
ein zweites Mal zu riskieren. Und auf Unbekanntes antwortet OMDb mit 200
und `Response: "False"` — das als Treffer durchzulassen legte eine leere
Bewertung ab, die danach als „keine Wertung" dastünde.
Angezeigt wird mit Kürzel statt Stern: vier gleich aussehende Zahlen
nebeneinander sagen nicht, woher sie kommen. Kein Logo — die Marken von
IMDb und Rotten Tomatoes mitzuliefern hiesse, fremde Zeichen auszuliefern.
Kein mitgelieferter Schlüssel, aus demselben Grund wie bei fanart.tv: OMDb
begrenzt auf tausend Abrufe am Tag je Schlüssel. Einzutragen unter
Einstellungen → Übersicht → Metadaten.
740 Tests grün, davon acht neue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein 21:9-Film war in der Breite richtig und in der Höhe nicht: der schwarze
Rand lag ganz unten statt gleichmässig oben und unten. Im Fenster fällt das
kaum auf, im Vollbild sofort.
Gemessen an einem 2560×1080-Film in einem 1024×768-Fenster:
Hülle 768 hoch
Videokasten 459 hoch, bei oben 0
Woran es lag: die Hülle ist ein Raster mit `place-items: center`. Damit
wird das Videoelement nicht gedehnt, und sein `height: 100%` löst sich
gegen eine Zeile auf, die ihre Höhe wiederum aus dem Element nimmt — die
Prozentangabe hatte nichts, woran sie sich halten konnte. Herausgekommen
ist ein Kasten, der weder die volle Höhe hatte noch mittig sass.
Jetzt liegt das Videoelement im grossen Spieler absolut über der ganzen
Hülle. `object-fit: contain` rechnet damit gegen den vollen Bildschirm und
legt den Rand von selbst zu gleichen Teilen oben und unten — in beiden
Richtungen, nicht nur in der einen, die vorher stimmte.
Nachher dieselbe Messung: Kasten 1024 × 768, oben 0.
Die kleine Leiste bleibt unberührt — sie positioniert dasselbe Element
ohnehin absolut und mit eigenen Massen; deshalb das `:not(.pl-klein)`.
Nachgemessen: 128 × 70, `object-fit: cover`, unverändert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
**Mehrfachfassungen lassen sich abhaken.** Zwei Dateien an einem Film sind
meist zwei Fassungen und völlig in Ordnung. In der Liste standen sie
trotzdem für immer: sie rechnet jedes Mal frisch, und es gab keinen Zustand.
Wer absichtlich zwei Fassungen hält, konnte die Gruppe nicht loswerden — und
unter den gewollten ging das Ungewollte unter.
Abgehakt wird eine Dateizahl, kein Zeitpunkt. Ein Zeitstempel müsste gegen
`MediaFile.ModifiedAt` verglichen werden, und eine alte Datei, frisch
hineinkopiert, behält ihre alte Zeit und käme nie wieder hoch. Die Anzahl
ist genau die Frage: kommt eine dritte Fassung dazu, meldet sich die Gruppe
von selbst zurück. Gerechnet wird sie auf dem Server — ein Client mit
veralteter Liste hakte sonst eine Gruppe mit zwei Dateien ab, die inzwischen
drei hat.
„Ignorierte zeigen" führt zurück, wie bei den erledigten Meldungen; ohne das
wäre das Abhaken unumkehrbar und niemand wüsste, was er weggeklickt hat.
**Die Startseite wartete dreimal nacheinander.** Erst die Serverauskunft,
dann Konto und Mediatheken, dann erst die Startseite — drei Rundreisen,
bevor das erste Bild in Auftrag ging. Liegt eine Sitzung im Speicher, laufen
die ersten beiden jetzt zugleich los. Nur dann: ohne Sitzung liefen
`/auth/me` und `/libraries` vor der Antwort auf `needsSetup` in ein 401, und
die Sitzungsprüfung kann daraufhin abmelden.
Gemessen am laufenden Server: `users/me`, `system/info` und `libraries`
starten alle bei 37 ms, die Startseitenabfragen folgen bei 73 ms. Vorher
lagen drei Runden dazwischen.
**Sieben Hintergrundbilder auf einmal waren sechs zu viel.** Jede Folie des
Aufmachers bekam sofort ihr `w1280`-Bild; sichtbar ist immer nur eine. Jetzt
lädt die sichtbare sofort und der Rest in der Leerlaufzeit — und wer
weiterschaltet, bevor das lief, bekommt sein Bild dann.
**Die Schrift kam von Google.** `display=swap` rettete den Text, nicht den
ersten Aufbau: ein Stylesheet blockiert das Zeichnen, und ein Heimserver
ohne Internet oder mit träger Namensauflösung wartete davor. Inter liegt
jetzt als zwei Dateien von zusammen sechzig Kilobyte im Projekt, variabel
für alle Schnitte, mit `unicode-range` getrennt nach latin und latin-ext.
Gemessen: null Anfragen an fonts.googleapis.com. Lizenztext liegt dabei.
**Und mein Untertitelvorrat bremste mit.** Er startete sofort beim
Hochfahren und las die ganze Mediathek — von derselben Platte, von der die
Startseite ihre Bilder holt. Jetzt beginnt er eine Minute später und stellt
zurück, solange eine Wiedergabe läuft. Die Datei bleibt dabei vorn in der
Reihe; verworfen wird nichts.
678 Tests grün, davon zwei neue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
**Der Einstellungsknopf lag hinter der Abspielleiste.** Gemessen: `.pl`
steht auf Stufe 150, `#chrome` auf gar keiner, und die kleine Leiste spannte
über die ganze Breite — genau über die unteren 72 Bildpunkte der
Seitenleiste, wo „Einstellungen" klebt. Weil der Spieler bei jedem Wechsel
der Adresse minimiert, stand sie zuverlässig im Weg, sobald man dorthin
wollte.
Die Leiste beginnt jetzt hinter der Seitenleiste. Nicht über die Stufen
gelöst, und das ist der Punkt: `#chrome` höher zu setzen hiesse, die
Seitenleiste läge auch über dem grossen Spieler — es ist dieselbe Hülle.
Dass diese Leiste Platz wegnimmt statt sich darüberzulegen, stand für
Inhalt, Hinweise und Auswahlleiste ohnehin schon da; die Seitenleiste war
die vergessene vierte. Gemessen, 1400 Bildpunkte breit: Leiste ab 240,
Knopf bei 0, keine Überschneidung, und ein Treffertest in der Knopfmitte
trifft den Knopf.
**Ein Klick auf eine Kategorie kam nie an.** Dort sprang der Code in die
Mediathek und suchte danach `.filterzeile select`, um den Wert zu setzen.
Die Filterzeile hat kein `<select>` — `auswahl()` baut einen Knopf, mit
Absicht und begründet. Der Zweig lief also nie, und man landete in der
ungefilterten Mediathek. Der Kommentar daneben behauptete das Gegenteil.
Das Genre steht jetzt in der Adresse: `#/m/{id}/mediathek/Horror`. Das
löst zugleich das zweite Problem — die Mediathek wird unter ihrem Weg
gemerkt, und stünde das Genre nur im Kopf, zeigte ein zweiter Besuch die
Liste des ersten. Geprüft: Klick setzt den Weg und die Pille, Neuladen
behält beides, Zurück führt auf die Kategorien, Vorwärts wieder hinein.
**Zurückgezogene Einladungen blieben für immer stehen.** Der Knopfblock
steckte ganz in `if (!e.revokedAt)`, eine erledigte Zeile hatte also gar
keinen Knopf. Die Serverbegründung — eine Zeile wegzuwerfen hiesse,
hinterher nicht mehr zu wissen, dass es den Link je gab — bleibt richtig,
sie gilt nur nicht ewig: eine Liste, aus der nichts verschwindet, wird
unlesbar, und dann sieht man die eine Zeile nicht mehr, um die es ging.
Deshalb kein umgedeutetes DELETE, sondern `?purge=true`, und das greift nur
bei einem Link, der ohnehin keine Tür mehr öffnet. Ein gültiger wird mit
einem deutschen Satz abgewiesen.
**Poster in der falschen Sprache.** „365 Tage" stand mit polnischem Plakat
da. Kein fehlender Anbieter: für den Schriftzug gab es die sprachgewichtete
Wahl längst, fürs Plakat wurde das blanke `poster_path` der Hauptantwort
genommen — bei TMDB das Bild der Originalsprache, wenn in der gewünschten
keines eingetragen ist. Die sortierte Liste lag im selben Abruf schon vor
und wurde ausschliesslich für den Schriftzug benutzt.
Plakat und Hintergrund nehmen jetzt dieselbe Rangfolge: eingestellte
Sprache, dann sprachlos, dann Englisch. Sprachlos vor Englisch ist keine
Verlegenheit — ein Bild ohne Sprachkennung trägt keinen Text, und ein
Plakat ohne Titel ist für einen deutschen Bestand besser als dasselbe mit
englischem. Im Bilderdialog stehen die Kandidaten jetzt ebenso sortiert.
Bestehende Titel ändern sich beim nächsten Auffrischen; von Hand gesetzte
Plakate bleiben unangetastet.
676 Tests grün, davon zehn neue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Voreinstellung des Browsers ist weisse Schrift auf schwarzem Kasten, in
einer Grösse, die er aus der Höhe des Videos rechnet. Auf einem grossen
Bildschirm aus drei Metern Abstand ist das zu klein, und wer schlecht sieht,
braucht es anders.
Einstellbar sind Grösse (60 bis 300 Prozent in Zehnerschritten),
Schriftfarbe (Weiss, Hellgelb, Hellblau, Schwarz) und Hintergrund
(Halbdunkel, Schwarz, Grau, Ohne).
Gestaltet wird mit `::cue`, nicht mit eigenen Kästen. Der Browser zeichnet
die Einblendungen selbst — Position, Umbruch, Zeilenabstand und die
Platzangaben aus der Datei. Das nachzubauen hiesse, all das noch einmal zu
schreiben und dabei schlechter zu werden.
Gemessen an einem Video mit echter Spur, Bild für Bild: 200 Prozent in
Hellgelb ohne Kasten und 140 Prozent in Hellblau auf Grau kommen beide so
heraus, wie sie gemeint sind.
Ohne Kasten setzt es von selbst einen Schatten. Weisse Schrift in einer
hellen Szene ist sonst weg, und das wäre eine Einstellung, die sich selbst
unbrauchbar macht. Mit Kasten wäre derselbe Schatten nur Unschärfe.
Die Einstellung sitzt im Untertitelmenü, abgetrennt unter den Spuren — wie
der Tonversatz im Tonmenü. Ob die Schrift gross genug ist, sieht man nur an
einem laufenden Film, in diesem Licht, aus diesem Abstand; wer dafür die
Wiedergabe verlassen muss, stellt zweimal falsch ein, bevor er einmal
richtig liegt.
Gemerkt wird im Browser, nicht am Konto: wie gross Schrift sein muss, hängt
am Bildschirm und am Abstand davor. Dasselbe Konto am Telefon und am
Fernseher will zwei verschiedene Grössen.
Farbfelder statt einer Liste mit Farbnamen — „Hellblau" muss man lesen und
sich vorstellen, ein Feld sieht man. Das gewählte trägt einen Ring aussen
herum und keinen Haken darin: ein Haken wäre auf Weiss unsichtbar und auf
Schwarz erst recht. „Ohne Hintergrund" zeigt ein Karomuster, weil ein
leeres Feld nach Weiss aussähe.
Gelesen wird nur, was bekannt ist. Ein fremder Eintrag im Speicher darf
nicht zu beliebigem CSS in der Seite werden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
„TONVERSATZ — OHNE VERSATZ" am Stück passte nicht in das schmale Menü und
stand auf zwei Zeilen — und sah damit nach zwei Dingen aus. Jetzt steht
der Name links und der eingestellte Wert rechts in derselben Zeile, der
Wert hell und ohne Versalien, damit man sieht, welches davon die
Einstellung ist. Die Liste ist dafür 230 statt 180 Bildpunkte breit —
„Ton 3 s früher" muss daneben passen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drei Anläufe, und du hattest jedes Mal recht.
**Er gehört ins Tonmenü** — aber sichtbar nicht zu den Spuren. Jetzt
trennt ihn ein Strich ab, darüber steht „TONVERSATZ — Ohne Versatz" als
Überschrift, darunter ein Regler. Drei Mittel, und jedes einzelne würde
schon sagen, dass das keine Sprache ist.
**Ein Regler statt Auswahlpunkten.** Feste Stufen hiessen: für jeden Wert
ein Eintrag, und die standen zwischen den Sprachen wie weitere Sprachen.
Gezogen wird von −3 bis +3 Sekunden in Hundertern; die Mitte ist als
Strich markiert, sonst trifft man die Null nur zufällig. Gerechnet wird
erst beim Loslassen, nicht beim Ziehen — jede Änderung baut den Strom neu
auf, und das tut man nicht zwanzigmal beim Hinschieben. Daneben
„Zurücksetzen", sobald etwas eingestellt ist.
**Und der Lautsprecher ist zurück.** Hier stand ein eigenes Zeichen, damit
er nicht zweimal in der Leiste auftaucht — links Stummschalten, rechts die
Tonspur. Die Wellenform erkannte aber niemand als „Ton". Zwei Lautsprecher
sind das kleinere Übel, zumal der linke beim Stummschalten
durchgestrichen wird und damit anders aussieht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vier Stufen unter Einstellungen → Verwaltung → Übersicht: niedrig, mittel,
hoch, sehr hoch. Mittel ist, was gestern fest verdrahtet war.
**Keine Pixelzahl.** Eine einzustellen hiesse, sie an jedem Bildschirm neu
einzustellen — der Aufmacher misst sich an der Fensterhöhe, nicht an einer
festen Grösse. Gemessen bei 800 Bildpunkten Fensterhöhe: 496, 576, 656,
736. Oben ist Schluss, bevor von der ersten Plakatreihe nichts mehr übrig
bleibt; sie soll zeigen, dass unten noch etwas kommt. Am Telefon bleibt es
flacher, dort wäre auch das weg.
**Sie reist mit der Systemauskunft mit**, nicht in einer eigenen Abfrage.
Die holt der Client ohnehin als Erstes, noch vor der Anmeldung; käme die
Höhe später, stünde der Aufmacher einen Augenblick in der Vorgabe und
spränge dann — genau das, was eine einstellbare Höhe vermeiden soll.
Gesetzt wird sie als Marke am `<html>`, das Regelwerk hängt vier Werte
daran.
Serverweit und nur für Admins, dieselbe Linie wie bei den
Wiedergaberegeln: eine Entscheidung des Gastgebers, nicht des Gastes.
Unbekanntes in der Spalte wird zur Vorgabe statt zu einem Fehler — eine
Startseite, die an einem alten Eintrag scheitert, wäre die schlechtere
Antwort.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`min(62vh, 560px)` → `min(72vh, 640px)`. Bei 800 Bildpunkten Fensterhöhe
gemessen: 576 statt 496, und die erste Plakatreihe lugt mit ihrem Beginn
bei 648 weiterhin über den Falz — sie soll ja zeigen, dass unten noch
etwas kommt.
Am Telefon bleibt es bei `min(52vh, 420px)`: dort ist der Aufmacher im
Verhältnis zum Bildschirm ohnehin höher.
Ein Satz musste mit, und der ist tragend: die Begründung, warum das
Aufklappen der Inhaltsangabe nicht schaukelt, nennt die feste Höhe
wörtlich. Die Zahl wird falsch, das Argument bleibt richtig.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wer einen Server für andere betreibt, erfährt von Fehlern zuletzt: dass
die deutsche Tonspur nach einer halben Stunde aussetzt, merkt der, der den
Film sieht, und nicht der, der ihn eingeräumt hat. Bisher gab es dafür
keinen Weg ausser dem Zuruf im Wohnzimmer.
Gemeldet wird an einem Film, einer Serie, einer einzelnen Staffel und
einer einzelnen Folge: Art (Bild, Ton, Untertitel, Angaben, Sonstiges),
eine freiwillige Stelle wie 0:34:12 und der Kommentar. Pflicht ist nur der
Kommentar — die beiden anderen machen aus einer Liste von Sätzen etwas,
das man sortieren und nachstellen kann.
**Eine Staffel gibt es als Zeile nicht**, und das prägt den Entwurf. Sie
ist Serie plus Nummer, so wie überall sonst in diesem Server; die Meldung
trägt deshalb drei Fremdschlüssel und daneben eine Staffelnummer. Dass die
Nummer auf eine Staffel zeigt, die es gibt, prüft der Endpunkt beim
Schreiben — die Datenbank kann es nicht, es gibt nichts, worauf sie zeigen
könnte.
**Die Rechteprüfung steht nirgends.** Wer einen Titel nicht sehen darf,
findet ihn beim Melden nicht — das erledigt der Freigabefilter, ohne ein
einziges `Where`. Elegant und genau deshalb leicht zu zerstören, darum
steht dafür ein Test da.
**Die eigene Liste überlebt fremde Entscheidungen.** Titel werden
nachgeschlagen, nicht verbunden: zieht ein Administrator einen Titel
zurück, nachdem jemand ihn gemeldet hat, bleibt die Meldung beim Melder
stehen — nur ohne Namen. Ein Join hätte sie verschwinden lassen, und das
wäre jemandes eigene Eingabe, weggenommen wegen einer fremden Entscheidung.
`IgnoreQueryFilters` wäre die bequeme Abkürzung und gäbe den Namen eines
unveröffentlichten Titels über einen Weg heraus, an den beim nächsten Mal
niemand denkt.
**Erledigt heisst abgehakt, nicht gelöscht**, als Zeitpunkt und nicht als
Haken — wie `PublishAt` und `ChangedSince`. Daneben steht „Wieder öffnen";
ein Fehlgriff wäre sonst endgültig. Das Archiv wird erst auf Zuruf geholt:
es wächst nur, und für den seltenen Blick dauernd zu zahlen lohnt nicht.
**Der Abschnitt steht neben der Prüfliste, nicht darin.** Die versteckt
sich, sobald nichts auf Freigabe wartet — das ist der Normalfall, und die
Meldungen verschwänden mit ihr. Umgekehrt bleibt der Meldungsabschnitt
stehen, auch wenn nichts drinsteht: ein Kanal, der sich versteckt, solange
ihn niemand benutzt hat, bringt niemandem bei, dass es ihn gibt.
Die Zahl an der Leiste holt sich nur, wer sie nicht ohnehin hat: steht „Zu
prüfen" offen, meldet der Abschnitt sie selbst und nach jedem Abhaken.
Nebenbei zwei Dinge am Dialog, die hier auffielen. Es gab **kein
mehrzeiliges Feld** — und das Einsammeln der Werte hätte ein `<textarea>`
still verschluckt: es ist kein `HTMLInputElement` und wäre ins Auffangnetz
für Auswahlfelder gelaufen, also als `undefined` hinausgegangen. Der
Server hätte „ohne Beschreibung" geantwortet, auf einem Dialog, in dem
sichtbar etwas steht. Und `dialog()` meldete sich als einziger nicht beim
Seitenwechsel an: ein Dialog von der Detailseite überlebte den
Zurück-Knopf und stand danach über der Mediathek.
Neun Testfälle auf dem Server, zwölf Läufe. Für den Web-Client gibt es in
diesem Projekt keine Tests; dort ist von Hand geprüft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ich hatte „die Beschreibung nur beim Hovern" gelesen und daraufhin
Beschreibung *und* Knöpfe ausgeblendet. Die Knöpfe gehören immer dahin: in
Ruhe steht oben, was läuft und was man damit tun kann.
Die Inhaltsangabe dagegen steht erst da, wenn man es will. Zwei Sekunden
auf dem Titel stehenbleiben, dann fährt er hoch und darunter klappt sie
auf; wer nur vorbeifährt, sieht nichts. Gibt es keine, passiert gar
nichts — der Absatz fällt dann ganz aus dem Fluss.
**Angefasst wird am Titel, losgelassen am ganzen Aufmacher.** Das ist die
ganze Vorsicht an dieser Stelle. Beim Aufklappen wächst der Block nach
oben, der Titel rückt um 77 Bildpunkte weg und steht nicht mehr unter dem
Zeiger. Hinge das Zuklappen an seinem `:hover`, wäre das die erste Hälfte
einer Schaukel. Der Aufmacher selbst kann das nicht: gemessen, offen wie
zu, 476 px hoch ab 48 — auf den Bildpunkt derselbe Kasten.
**Die Höhe wird gemessen, nicht geraten.** Nach `auto` lässt sich nicht
überblenden, und eine feste Obergrenze wäre bei einer einzeiligen Angabe
zu drei Vierteln Leerlauf. Gemessen wird bei jedem Folienwechsel und bei
jeder Fensteränderung; `scrollHeight` ginge nicht, der meldet bei einem
`-webkit-box` die ungeklammerte Höhe.
**Der Rasterabstand wandert mit.** Gemessen: zugeklappt stehen zwischen
Eckdaten und Knopfzeile 16 px — mit Inhaltsangabe wie ohne, und genau so
viele wie vorher. Aufgeklappt sind es 12 über und 16 unter dem Text, und
die Knopfzeile steht still (Unterkante 492 in beiden Zuständen).
Nebenbei kommt das Abbruchsignal endlich an: `hero()` nahm eines
entgegen, aber `main.ts` baute die Startseite ohne. Sie wird gemerkt — ihr
Neun-Sekunden-Takt lief also weiter, während man längst woanders war.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Inhaltsangabe und Knöpfe blenden sich beim Überfahren ein und wieder aus.
In Ruhe bleibt oben nur, *was* läuft — Schriftzug oder Name, Jahr,
Laufzeit, Freigabe. Was man damit tun kann und worum es geht, kommt auf
Zuruf. So ist das Bild in Ruhe ein Bild und nicht eine Wand aus Text
darüber.
**Langsamer herein als hinaus**, 340 gegen 220 Millisekunden: das
Erscheinen soll man sehen, das Verschwinden nicht abwarten müssen. Die
Pfeile gehen denselben Takt mit; sie standen auf 150 ms und blitzten
dagegen auf.
**Der Platz bleibt reserviert.** Mit `display: none` spränge beim ersten
Überfahren der ganze Block nach oben; geschaltet wird nur die Deckung.
Gemessen an derselben Folie: 349,2 px hoch mit Deckung 0, 349,2 px mit
Deckung 1.
**Der Terminhinweis bleibt stehen.** „Ab Di., 6. Okt., 18:00 Uhr" ist
keine Handlung, sondern die Auskunft, warum hier nichts zu drücken ist —
die darf nicht erst auf Zuruf kommen. Darum trifft die Regel `.btn` und
nicht die ganze Knopfzeile.
**Der Fokus zählt wie der Zeiger.** Ein Knopf, der unsichtbar den Fokus
bekommt, ist eine Sackgasse. Gemessen, mit abgeschalteten Übergängen:
in Ruhe alles auf 0; Fokus im Aufmacher — Text 1, beide Knöpfe 1, beide
Pfeile 0,72; nach dem Verlassen wieder 0.
`hover: hover` wie bei den Pfeilen: ohne Zeiger gäbe es kein Überfahren,
und „Abspielen" wäre nicht mehr erreichbar. Dort steht alles wie immer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sie liegen über dem Bild und damit über allem, was dort steht. Bei einem
einzeiligen Titel geht das gut. „Pirates of the Caribbean — Salazars
Rache" bricht um, die erste Zeile rückt nach oben — und der linke Pfeil
sitzt auf dem ersten Buchstaben.
Ständig sichtbar ist er dort ein Fleck, auf Zuruf ein Knopf. Also
erscheinen beide erst beim Überfahren des Aufmachers, in 150 ms, und
verschwinden wieder.
`hover: hover` ist dabei die ganze Vorsicht: auf einem Tablett gibt es
kein Überfahren, und ein Knopf, der nur dabei erscheint, wäre dort
schlicht nicht erreichbar. Dort bleibt alles, wie es war — unter 860
Bildpunkten gibt es die Pfeile ohnehin nicht, da wird gewischt.
Gemessen: in Ruhe Deckung 0, kein Zeigerziel. Zeiger über dem Aufmacher:
0,72 und anklickbar. Zeiger auf dem Pfeil: 1, dunklerer Grund, und der
Klick blättert tatsächlich weiter (Tastatur-Tabulator vom Knopf „Mehr"
aus: Deckung 1, `:focus-visible` greift, Umriss 2 px) — `pointer-events:
none` hält nur den Zeiger ab, nicht den Fokus.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Es stand auf `inset: 0` und lag damit auch hinter Seiten- und Kopfleiste —
beide undurchsichtig. Bei 1280×800 gemessen: 18,8 % der Breite, 7 % der
Höhe, zusammen 24,4 % der Bildfläche, die niemand je zu sehen bekam.
Solange alles weichgezeichnet war, fiel das nicht auf; ein verwischter
Rand sieht wie jeder andere aus. Scharf beginnt der Inhalt mitten im
Motiv — bei den Bergrettern mit einem angeschnittenen Kopf direkt an der
Kante der Seitenleiste.
Jetzt sitzt das Bild in dem Feld, in dem es auch zu sehen ist, und wird
darin ganz zugeschnitten: links die Seitenleistenbreite, oben die
Kopfleistenhöhe. Der Kontrast bleibt, wo er war — 3,95∶1 scharf statt
3,97∶1, derselbe Zuschnitt in einem anderen Feld.
Am Telefon gibt es keine Seitenleiste; dort nimmt die Navigationszeile
oben noch einen Streifen weg, solange man ganz oben steht, und ist nach
dem ersten Bildlauf weg.
Die beiden älteren Begründungen über der Regel standen noch da und sagten
inzwischen das Gegenteil — die eine erklärte, warum das Bild über die
volle Breite gehört. Sie sind zu einer zusammengefasst, die den ganzen Weg
erzählt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Er war es immer: 28 Bildpunkte Weichzeichnung über die ganze Detailseite,
damit der Text darüber lesbar bleibt. Oben steht aber gar nichts darüber —
dort ist das Bild das Beste, was die Seite zu bieten hat, und es lag als
Farbschlieren da. Unscharf gehört es erst, wenn wirklich etwas darüber
hinwegläuft: die Folgen, die Besetzung, die Medienangaben.
Jetzt folgt die Weichzeichnung dem Bildlauf, über etwa siebzig Prozent
einer Bildschirmhöhe und quadratisch statt geradlinig — die ersten
Bildpunkte sollen nichts tun, sonst wäre „scharf, solange nichts
darüberliegt" nach einem Fingerbreit schon dahin. Gerundet auf ganze
Bildpunkte, weil jeder neue Wert eine bildschirmfüllende Fläche neu
zeichnen lässt; über die ganze Strecke sind das 28 Male. Gemessen über 58
Bilder beim Hinunterrollen: 8,3 ms im Mittel, kein Bild über 9,2 ms.
**Und die Deckung geht mit, das ist der unscheinbare Teil.** Eine
Weichzeichnung verrührt die hellen Stellen mit den dunklen; ein scharfes
Bild hat die weisse Stelle genau dort, wo die Zeile steht. Gemessen an der
dunklen Vorlage von „Dark": vorher 4,07∶1, scharf bei derselben Deckung
nur noch 2,44∶1. An einer hellen — Hubschrauber vor blauem Himmel —
vorher 2,75∶1. Mit 0,28 scharf und 0,45 weich stehen beide wieder bei rund
4,0∶1, die helle sogar besser als zuvor.
Der Zuhörer räumt sich selbst ab: die Detailseite wird nicht gemerkt, und
für ungemerkte Ansichten ruft `einhaengen` kein Abbruchsignal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hochladen konnte man Plakat, Hintergrund und Schriftzug schon lange — der
Knopf stand da, der Endpunkt nahm an. Nur ankommen tat nichts: die Ablage
baute einen Schlüssel, den sie selbst nicht wiederfand (heute früh
repariert). Was blieb, waren drei Lücken, die man erst sieht, wenn der Weg
überhaupt funktioniert.
**Der Ausschnitt.** Ein Plakat steht hochkant im Verhältnis 2∶3, ein
Hintergrund liegt quer. Was man aussucht, passt selten von selbst — und
den Rest beschnitt bisher der Browser beim Anzeigen: mittig. Jetzt wählt
man selbst, zieht und vergrössert, und hochgeladen wird genau dieser
Ausschnitt: 600×900 beim Plakat, 1920×1080 beim Hintergrund. Gerechnet
wird im Browser; das spart die Leitung und dem Server eine Bildbibliothek.
**Der Schriftzug nicht.** Er ist ein PNG mit durchsichtigem Grund. Durch
dieselbe Mühle geschickt würde aus der Durchsicht ein weisses Rechteck —
ein Aufkleber über dem Bild. Er geht unverändert hinaus, Byte für Byte.
**Die Kachel merkte nichts.** Nach dem Hochladen fehlte der Anstoss nach
aussen; die Oberfläche zeigte weiter das alte Bild, bis man sie neu lud.
**Und zurück ging es gar nicht.** „Von Hand gesetzt" heisst auch: beim
Auffrischen bleibt es stehen. Ohne Rückweg wäre ein Fehlgriff ein
Dauerzustand — jetzt steht „Wieder automatisch" daneben, sobald etwas
festgesetzt ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Seite hiess „Verwaltung" und war für alle anderen gar nicht
erreichbar — „Meine Sprache" lag dadurch hinter einer Tür, die den meisten
verschlossen ist. Jetzt heisst sie **Einstellungen**, steht jedem offen und
hat zwei beschriftete Gruppen: oben, was einem selbst gehört (Mein Konto,
Geschaut), darunter — nur für Administratoren — **Verwaltung**. Die
Überschrift ist hier die halbe Aussage: sie sagt ohne weiteren Satz, wem
der untere Teil gehört.
In der Hauptleiste steht der Eintrag jetzt unten, ohne Gruppenüberschrift.
Eine Überschrift über einem einzigen Eintrag ist eine Überschrift über
nichts, und am Fuss sucht man Einstellungen ohnehin. `#/profil` und
`#/verwaltung/…` leiten weiter; ein Lesezeichen merkt davon nichts.
**Ein kurzes Menü am Bild.** Erst meldete der Klick ab — ohne Rückfrage.
Dann führte er auf die eigene Seite, und zum Abmelden musste man erst
dorthin. Beides sind zwei Punkte; ein Menü mit zwei Punkten ist ehrlicher
als eine Tür, hinter der eine zweite liegt.
**Und das Profilbild lässt sich zuschneiden.** Ein Profilbild ist rund,
was hochgeladen wird selten quadratisch — den Ausschnitt dem Browser zu
überlassen hiesse: mittig, und das trifft bei einem Porträt den Hals. Der
Dialog zeigt den runden Ausschnitt, man zieht und vergrössert, und
hochgeladen wird genau das: ein Quadrat von 512 Pixeln. Gemessen, es kommt
auch so an.
**Dazu die Spielerleiste.** Beide Knopfgruppen durften schrumpfen, ihre
Knöpfe aber nicht — wird es eng, steht der äusserste halb hinter dem
Fensterrand. Rechts sind es nur Knöpfe, da gibt es nichts nachzugeben;
links schon. Dazu seitlich `env(safe-area-inset-*)`, damit auf einem Gerät
mit runden Ecken nichts darunter liegt. Gemessen: vorher riss es ab 420
Pixeln, jetzt bis 320 nicht mehr.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Für „wie viel habe ich letzte Woche geschaut" gab es keine Daten.
`UserItemState` ist eine Zeile je Titel: der letzte Stand. Wer einen Film
zweimal sieht, überschreibt den ersten Durchgang; wann etwas lief, wusste
der Server nur fürs jeweils letzte Mal. Nachträglich erfinden lässt sich
das nicht.
Jetzt gibt es ein Sehprotokoll: **eine Zeile je Nutzer, Tag und Titel.**
Keine Sitzungen — die brauchen ein Ende, und das kommt oft nie an, wenn
der Browser zugemacht oder das Telefon zugeklappt wird. Tagesbündel haben
diesen Lebenslauf nicht, es wird nur addiert.
**Gezählt wird, was wirklich lief.** Der Zuwachs zwischen zwei Meldungen,
gedeckelt auf die Zeit, die dazwischen verstrichen ist (mal zwei als
Toleranz für doppelte Geschwindigkeit und ausgefallene Meldungen). Sonst
ergäbe ein Sprung von Minute 5 auf Minute 90 anderthalb Stunden Sehzeit in
zehn Sekunden. Gemessen an fünf Meldungen im Abstand von elf Sekunden:
88 Sekunden statt 190.
Dabei fiel ein zweiter Fall auf: war **gar keine** Zeit verstrichen, griff
kein Deckel statt eines engen — eine frisch angelegte Zeile hätte ihre
Anfangsstelle voll mitgezählt. Wer einen Film öffnet und sofort auf Minute
fünf springt, hat keine fünf Minuten gesehen.
Im Profil stehen drei Zahlen, und jede sagt, woher sie kommt: die
aufgezeichnete Zeit fängt heute an, die Zahl gesehener Titel steht seit
jeher fest. Dazu eine Wochenkurve, die häufigsten Genres und was zuletzt
lief. **Jeder sieht nur sich selbst, auch ein Administrator** — es gibt
keinen Weg, ein fremdes Konto zu meinen.
Zwei Dinge auf dem Weg dorthin:
**Eine stellbare Uhr für die Tests.** Zwei Minuten Film lassen sich nicht
in fünf Millisekunden sehen, und das ist richtig so — prüfen liess es sich
nur, indem die Zeit vergeht, ohne sie zu verbringen.
**Ein Namenskonflikt im CSS.** Die leeren Wochenbalken trugen die Klasse
`leer`, und die gehört längst der Fläche „hier ist nichts" — mitsamt
24 Pixeln Polster. Jeder leere Balken war dadurch 48 Pixel hoch, egal
welche Höhe dastand.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein Klick auf den Buchstabenkreis meldete ab. Keine Rückfrage, kein Menü,
kein Weg zurück — hinter einer Geste, die überall sonst „mein Konto"
heisst. Jetzt führt er auf `#/profil`; Abmelden steht dort als Knopf, mit
Nachfrage.
Auf der Seite: Bild wählen, tauschen, entfernen. Dazu „Meine Sprache" —
**umgezogen, nicht kopiert.** Sie stand mitten in der Verwaltung, und die
zeigt der Client nur Administratoren; der Endpunkt erlaubte sie längst
jedem. Wer kein Admin war, konnte seine eigene Sprache nirgends ändern.
Der Warnhinweis „weicht ab" bleibt in der Verwaltung, denn dort entsteht
die Verwirrung — er verweist jetzt aufs Profil.
**Vorher musste ein Fehler weg, der seit Monaten dasteht.**
`ImageCache.StoreStreamAsync` baute den Schlüssel aus 32 Hexzeichen plus
Dateiendung; `PfadFür` verlangt genau 64 Hexzeichen und nichts sonst. Es
gab keinen Wert, den beide gelten liessen: **jeder Bildupload gab `null`
zurück und endete in einem 502.** Kein Test fragte je danach — jetzt vier.
Damit geht nebenbei auch „eigenes Bild hochladen" für Filme und Serien
wieder.
Weil der Schlüssel keine Endung mehr trägt, kommt der Medientyp beim
Ausliefern aus den ersten Bytes der Datei. Vorher ging alles als
`image/jpeg` hinaus — bei TMDB stimmte das, bei einem hochgeladenen PNG
nicht.
**Und die gemerkte Sitzung war eine Kopie, die nie nachzog.** Sie wurde
bei der Anmeldung geschrieben und danach nie wieder. Wer sein Bild am
Telefon setzt und den Browser am Schreibtisch öffnet, fand dort den alten
Buchstaben — bis zum nächsten Anmelden. Gemessen und behoben: beim
Hochfahren wird das Konto abgeglichen, und das Profil meldet Änderungen
an die Kopfleiste, damit sie ohne Neuladen nachzieht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Verwaltung war eine Seite mit 1786 Zeilen. Wer das Protokoll sehen
wollte, scrollte an Mediatheken, Prüfliste, Benutzern und Speicher
vorbei — und jede neue Einstellung hätte sie länger gemacht.
Jetzt hat sie eine eigene Leiste mit sieben Bereichen, jeder mit seiner
Adresse: `#/verwaltung/protokolle` lässt sich ablegen, und ein Neuladen
bleibt dort stehen. Die Leiste sieht aus wie die Hauptleiste daneben,
damit sie als Navigation gelesen wird und nicht als Knopfreihe; am
Telefon wird aus der Spalte ein Streifen zum Schieben.
**Gebaut wird nur, was offen ist.** Das ist nicht nur sparsamer: das
Abspielfenster fragt im Fünf-Sekunden-Takt nach, die Mediathekenliste
beobachtet laufende Scans. Gemessen: nach dem Wechsel in einen anderen
Bereich kommt zwölf Sekunden lang keine Anfrage mehr.
`admin.ts` ist in acht Dateien zerlegt — eine je Bereich, dazu `teile.ts`
für die gemeinsame Überschrift und `index.ts` für Leiste und Weiche.
Zwei Dinge mussten dabei nachziehen:
**Die Markierung in der Hauptleiste.** Sie verglich stur zwei Segmente;
bei `#/verwaltung/metadaten` traf das auf keinen Eintrag, und
„Verwaltung" verlor seinen Balken. Jetzt gilt auch ein Segment.
**„5 Titel warten — ansehen".** Der Knopf sprang mit `scrollIntoView` zur
Prüfliste. Die steht nicht mehr im selben Dokument — er wechselt jetzt
den Bereich. Die Hervorhebung danach entfällt damit, und mit ihr ihr CSS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
**Pfeile.** Der Aufmacher hatte nur die Punkte; die Pfeile, die du gedrückt
hast, gehörten zur Reihe darunter. Jetzt stehen links und rechts über dem
Bild zwei grosse Knöpfe. Am Telefon gibt es sie nicht — dort nähme ein
Knopf über dem Bild ein Drittel der Breite —, dafür lässt sich wischen.
Nur waagerecht und erst ab 48 Pixeln, sonst käme man am Aufmacher nicht
mehr vorbeigescrollt.
**Und die Knöpfe springen nicht mehr.** „Abspielen" ist 128 Pixel breit,
„Fortsetzen ab 1:23:45" 207, der Terminhinweis 257 — alles in derselben
Flexreihe, also wanderte „Mehr" bei jedem Umblättern mit, und das
Karussell blättert von allein. Der vordere Platz hat jetzt eine feste
Breite. Gemessen: „Mehr" steht auf allen sieben Folien an derselben Stelle.
Dabei fielen zwei Dinge auf, die nicht am Umbau lagen:
**Der Textblock war so breit wie sein längster Satz.** Als blosses Flexkind
richtete er sich nach dem Inhalt — bei einer kurzen Inhaltsangabe schmaler
als bei einer langen. Auf dem Telefon rückte „Mehr" dadurch um fünfzig
Pixel, und mit dem festen Platz lief die Zeile sogar über den Bildschirm
hinaus; `overflow: hidden` schnitt die rechte Hälfte des Textes ab.
**Ein fehlender Schriftzug liess den Aufmacher namenlos.** Steht ein Logo
in den Metadaten, wurde der Titel daneben versteckt — auch wenn das Bild
gar nicht lud. Zu sehen war ein Platzhalter und sonst nichts. Jetzt tritt
der Name an seine Stelle.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die App meldete auf der Startseite „Dieser Titel ist auf dem Server nicht
mehr vorhanden" — über eine Folge, die sie selbst gerade anzeigte.
Gemessen im Quelltext: `item(id:)` probiert `/movies/{id}`, dann
`/series/{id}`, und wirft sonst `.notFound`. In „Weiterschauen" steht
eine Folge mit ihrer eigenen Kennung, und einen Endpunkt für eine
einzelne Folge gab es gar nicht. Jetzt gibt es `GET /api/v1/episodes/{id}`
— mit `SeriesId`, denn ohne die Serie fehlen der Folge Titel und Bild.
Im Simulator nachgestellt und nachgeprüft: die Seite steht.
**Zuletzt hinzugefügt.** Die App zeigte „Filme" und „Serien" — den Anfang
der Mediathek in der Reihenfolge der Datenbank, also immer denselben.
Jetzt je Mediathek eine Reihe „Neu in …", sortiert nach Zugang. Die
Kennungen beginnen nun mit `latest`, und daran hängen zwei Einstellungen,
die an einem Flaro-Server deshalb nichts taten: „Gesehenes in Neuzugängen
ausblenden" und „Aufmacher nur aus Neuzugängen".
**Geplante Titel.** `MediaItem` kennt jetzt `availableFrom`. Aufmacher und
Detailseite zeigen statt des Knopfes „Bald ist es soweit" mit dem Termin.
Die Kachel spielte trotzdem los — im Simulator kam der Spieler bis „Wird
vorbereitet …" —, also zählt ein geplanter Titel jetzt wie eine Sammlung:
nichts zu starten, der Tipp führt auf die Seite.
**Und das Bild im Aufmacher.** Bei einer angefangenen Folge stand dort ihr
Standbild statt des Bildes der Serie; wer der Serie eines ausgesucht
hatte, fand ein anderes vor. Die Kachel behält das Standbild — sie zeigt,
wo man steht —, der Aufmacher bekommt `SeriesBackdropImage`.
**Die Punkte im Karussell waren 26 × 3 Pixel.** Von drei Klicks auf
denselben Punkt traf nur der auf der Mittellinie; fünf Pixel daneben
geschah nichts. Der Knopf ist jetzt 27 Pixel hoch, sichtbar bleiben 3.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der geplante Film zeigte weiter „Abspielen" und „Herunterladen", und wer
drückte, bekam „Dieser Titel ist ab dem 6.10. um 18 Uhr verfügbar". Die
Sperre im Server war richtig; die Oberfläche wusste nur nichts davon.
Gemessen: die Liste führte `PublishAt` seit jeher mit, die Einzelabfrage
`GET /api/v1/movies/{id}` nicht — und die Detailseite entscheidet genau
daran. `publishAt` kam also immer als `null` an, die Prüfung lief ins
Leere. Dasselbe fehlte bei `GET /api/v1/series/{id}` und bei den Folgen.
Jetzt steht dort, wo sonst der Knopf stünde: „Bald ist es soweit", mit
dem Termin darunter. Kein Versprechen, das beim Klicken zurückgenommen
wird.
Der Test prüfte bisher nur die Liste — darum fiel es nicht auf. Er fragt
jetzt die Detailseite und schlägt ohne die Korrektur fehl.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Auflösung wurde allein aus der Höhe gebildet. Ein Kinoformat von 2.39:1
liegt als 1920×800 vor — nach der Höhe gerechnet kam „720p" heraus, und das
stand so in der Oberfläche. Jetzt zählt die grössere von Breite und Höhe;
Hochformat kippt damit nicht, und 4K-Breitbild heisst nicht mehr 1440p.
Die Detailansicht hat zwei Leserschaften, und bisher bekamen beide dasselbe.
Wer schauen will, sieht jetzt Laufzeit, Auflösung und die Sprachen — jede
einmal, statt „Englisch · Englisch · Englisch · Englisch · Deutsch". Wer die
Mediathek betreut, sieht darunter Dateiformat, Grösse und den Ordner. Der
Ordner verrät eine falsche Zuordnung in einer Sekunde: steht über der
Beschreibung „Hanni & Nanni 3" und der Ordner heisst „Hanni und Nanni", ist
die Sache klar. Er kommt nur für Administratoren überhaupt vom Server —
versteckt im Client wäre er weiterhin auslesbar.
Ein geplanter Titel war unsichtbar. Das ist die Hälfte, die nichts bringt:
dass er kommt, ist der Sinn des Planens. Er steht jetzt mit „Verfügbar ab …"
in der Mediathek, und die Datei geht trotzdem nicht heraus — Download wie
Strom lehnen bis zum Termin ab, auch für Administratoren. Wer vorziehen will,
hat „Jetzt veröffentlichen"; eine Hintertür für eine Rolle wäre eine Regel,
die manchmal gilt.
Was ein Auffrischen geändert hat, steht jetzt unter „Zu prüfen" — in einer
eigenen Gruppe mit „Zur Kenntnis" statt „Veröffentlichen". Diese Titel sind
sichtbar; es gibt nichts freizugeben, nur etwas abzuhaken.
Und das Protokoll sagt endlich, wo es knallt. „InvalidOperationException:
Nullable object must have a value." ohne eine einzige Zeile Herkunft ist für
niemanden eine Diagnose — weder für den Betreiber noch für mich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
„4 warten auf Freigabe" stand in der Mediathekenzeile, und die Liste darüber
war leer — sogar versteckt. Zwei Gründe, beide behoben.
Die Prüfliste wurde einmal beim Öffnen geholt und nie wieder. Findet ein
laufender Scan danach etwas Neues, zählt die Zeile es mit, die Liste aber
nicht. Sie hört jetzt auf dieselbe Meldung wie die Seitenleiste: Scan durch,
etwas freigegeben, Mediathek geändert — nachladen.
Und der Knopf gab blind frei. Auf die Frage „wo sehe ich die vier Filme?"
war das keine Antwort: er veröffentlichte sie, ohne sie zu zeigen. Jetzt
führt er dorthin, wo sie mit Plakat, Jahr und Dateiname stehen und sich
einzeln anhaken lassen — und hebt die Stelle kurz hervor, damit man nicht
weitersucht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deine drei Fälle haben eines gemeinsam, und es ist nicht das, was ich zuerst
vermutet hatte: keiner der Dateinamen nennt ein Jahr. Der Riegel von gestern
greift deshalb nicht.
Gemessen, woran es wirklich liegt. Bei TMDB heisst der Film „Hanni & Nanni",
auf der Platte „Hanni und Nanni". Das Kaufmanns-Und fällt im Vergleichs-
schlüssel als Sonderzeichen heraus, das Wort „und" bleibt stehen — die
Namensgleichheit griff also nie. Gewählt wurde stattdessen der erstbeste
Treffer, und das war „Hanni & Nanni 3". Der richtige stand auf Platz zwei,
und alle vier Treffer hatten dieselbe Beliebtheit: die Reihenfolge war
Zufall.
Bindewörter zwischen zwei Namen zählen jetzt nicht mehr mit — gestrichen,
nicht übersetzt, sonst bliebe „Batman and Robin" aussen vor. Am Wortanfang
bleiben sie stehen: „Und dann kam Polly" ist kein „dann kam Polly". Und die
Suche vergleicht über den Schlüssel statt Zeichen für Zeichen.
Das verhindert aber nur Neues. Was schon zusammengelegt ist, bleibt es —
deshalb gibt es jetzt „Eigener Film": eine Datei löst sich aus ihrem Titel
und wird ein eigener Eintrag, mit dem Titel aus dem Dateinamen und ohne
Kennung. Eine zu raten hiesse, denselben Fehler zu wiederholen; so steht sie
unter „Ohne Zuordnung" und ist in zwei Klicks richtig.
Der Super-Mario-Fall liegt anders: beide Titel treffen heute richtig. Der
steckt noch aus einem früheren Lauf fest und braucht das Trennen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Du hast drei Filme vermisst, und die Zahlen sagten schon, wo sie sind: 448
Filme plus 13 zweite Fassungen sind genau die 461 Dateien. Es fehlte keine
Datei; drei Filme steckten als Fassung in einem anderen.
Gemessen, warum. Der Dateinamenleser ist unschuldig — „Teil 2" bleibt im
Titel. TMDB aber liefert für „Heiligtümer des Todes Teil 1" wie für „Teil 2"
denselben Treffer zuerst, sobald ohne Jahr gesucht werden muss. Und weil
zwei Einträge dieselbe Kennung nicht teilen dürfen, wurde der zweite
geschluckt.
Zwei Dateien, deren Namen verschiedene Jahre nennen, sind jetzt verschiedene
Filme. Der erste Anlauf hatte ein Jahr Abstand als Toleranz erlaubt — für
Dezember-Erstaufführungen — und verschluckte damit genau den Fall, um den es
geht: Teil 1 ist von 2010, Teil 2 von 2011.
Dazu sieht man endlich, was nicht zugeordnet werden konnte. „Nicht
zugeordnet" listete bisher nur Dateien ganz ohne Titel, und die gibt es bei
Filmen nie — deshalb standen dort nur Serien. Daneben eine Liste der Titel
mit mehreren Dateien: zwei Fassungen sind die Regel, zwei verschiedene Filme
der Fehler, und an den Dateinamen sieht man es sofort.
Der Bearbeiten-Dialog hat jetzt Reiter statt Knöpfe, die weitere Fenster
öffnen — ein Fenster über einem Fenster, und man wusste nicht mehr, was man
zumacht. „Titel ändern" und „Bilder bearbeiten" sind aus dem Kontextmenü
raus; über „Bearbeiten" kommt man an beides.
Beim Prüfen gefunden: ein Dialog blieb nach einem Seitenwechsel über der
neuen Seite stehen. Er hängt an body, nicht am Inhaltsbereich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alphabetisch stimmt das, nur sieht man sie andersherum. Es gibt jetzt einen
Sortiertitel: „Harry Potter 1", „Harry Potter 2" — und die Reihe steht in
der Ordnung, in der man sie schaut. Leer gelassen bleibt alles wie bisher,
beim Titel ohne Artikel davor.
Er hat einen eigenen Merker, nicht den des Titels. Wer die Reihenfolge
festlegt, soll den Titel trotzdem weiter automatisch bekommen; beides an
einem Schalter hiesse, für das eine auf das andere zu verzichten. Eine
Korrektur der Zuordnung lässt ihn ebenfalls stehen.
Und WALL·E bleibt nicht mehr unter E. Die Kachel wurde nach einer Korrektur
zwar neu beschriftet, blieb aber an ihrem Platz — jetzt rutscht sie dorthin,
wo sie hingehört. Liegt der Platz im noch nicht geladenen Teil der Liste,
geht sie weg und sagt wohin, statt falsch stehenzubleiben.
Dazu ein Dialog, in dem alles zu einem Titel beieinander steht: Titel,
Sortiertitel, Bilder, Zuordnung. Die vier Menüpunkte gab es schon, jeder für
sich richtig — zusammen aber kein Ort. Wer einen Film geraderückt, macht
selten nur eines davon. Die Abkürzungen bleiben.
Beim Bauen gefunden: das Zurücksetzen des Sortiertitels endete in einer 500.
SortTitle.For ist eine C#-Methode, und EF Core übersetzt sie nicht nach SQL.
Es geht um eine Zeile — die wird jetzt geladen und zurückgeschrieben, statt
die Regel ein zweites Mal als SQL zu schreiben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
„Nächste Folge" führte ins Leere, und es lag weder am Scan noch am
Auffrischen: die Kachel trug die Folgenkennung und öffnete damit eine
Serienseite — die es unter dieser Kennung nie gibt. Heraus kam ausgerechnet
dort „Diese Serie gibt es nicht mehr", wo man gerade weiterschauen wollte.
Der Server kannte die Serie an beiden Stellen und schickte sie nur nicht mit.
Wohin die Kachel führt und was sie misst, ist jetzt getrennt. Beides auf
dieselbe Kennung zu legen wäre der nächste Fehler gewesen: „Als gesehen
markieren" hätte die ganze Serie abgehakt statt der einen Folge, die man zur
Hälfte gesehen hat.
Dazu Streichen wie im Dateimanager: gedrückt halten und darüberfahren wählt
aus, rückwärts über Gewähltes nimmt wieder weg. Ein kurzer Klick bleibt, was
er war. Abgetastet wird die Strecke zwischen zwei Zeigerereignissen, nicht
nur deren Endpunkte — gemessen: ein Zug über vier Kacheln erwischte sonst die
erste und die letzte. Plakate lassen sich nicht mehr durch die Gegend
schleppen.
„Abwählen" ist ein Kreuz geworden; als vierter Knopf neben drei Aktionen sah
es aus, als täte es etwas mit den Titeln.
In der kleinen Leiste lag das Vorschaubild über dem Fortschrittsstrich und
verdeckte ihn rechts. Und ein Klick genau darauf tat nichts, obwohl das die
Stelle ist, auf die man zeigt — jetzt holt auch das Bild den Film zurück.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Gesehen-Haken und die drei Punkte sassen beide oben rechts — auf dem
Plakat sah das aus wie ein Fehler. Jetzt hat jede Ecke eine Aufgabe: oben
links die Auswahl, oben rechts der Stand, unten links Abspielen, unten rechts
das Menü.
Der Knopf „Auswählen" ist weg. Gemessen, warum er stören musste: der längere
Text „Auswahl beenden" brach die Filterzeile um und schob das Raster um
zwanzig Bildpunkte nach unten. Und grundsätzlicher ist ein Modus ein Zustand,
den man kennen muss, bevor man etwas tun kann. Jetzt trägt jede Kachel oben
links ein Kästchen, das beim Überfahren erscheint — wie die drei Punkte auch.
Der erste Haken fängt die Auswahl an, der letzte beendet sie.
Der Spieler lässt sich verkleinern. Er rutscht in eine Leiste am unteren Rand
und läuft weiter, während man die Mediathek aufräumt; ein Klick darauf holt
ihn zurück. Dasselbe Videoelement, nur anders eingerahmt — ein zweiter
Spieler unten hiesse, das Video auszuhängen, und dabei hört es auf zu
spielen.
Das Zahnrad mit acht Strahlen sah aus wie eine Sonne. Jetzt: Wellenform für
den Ton, CC-Kasten für die Untertitel, Schieberegler für die Qualität. Alle
drei Menüs stehen immer da — vorher verschwanden sie bei nur einer Tonspur
oder ohne Untertitel, und wer sie suchte, fand nichts und wusste nicht warum.
Dabei gefunden und behoben: die Wiedergabe blieb nach zwanzig Sekunden
stehen, obwohl längst der ganze Rest auf der Platte lag. Results.File setzte
Last-Modified, der Browser legte die Playlist mit zwei Einträgen ab, und
hls.js bekam bei jedem Nachfragen dieselben zwei zurück. Eine wachsende Liste
ist das Gegenteil von zwischenspeicherbar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Browser bekam stillschweigend Apples Geräteprofil — und mit ihm HEVC, AC3
und EAC3, von denen er keines öffnet. Der Server packte die Datei
pflichtschuldig nach MP4 um, liess Bild und Ton dabei unberührt, und heraus
kam eine tadellose Datei, mit der Chrome nichts anfangen konnte. Umpacken
fasst das Bild nun einmal nicht an.
Jetzt sagt das Gerät selbst, was es kann, und es gibt einen zweiten Weg neben
der fertigen Datei: HLS, das nach Sekunden anfängt statt nach Minuten.
Dasselbe Rohr erledigt beides — mkv nach fMP4 mit „-c:v copy", 4K nach 480p
mit libx264 — und eine MP4, die der Browser ohnehin öffnet, geht ganz ohne
ffmpeg hinaus.
Dazu eine eigene Steuerleiste: Tonspur und Untertitel während der Wiedergabe
umschaltbar, vier Auflösungsstufen, Tastenkürzel, und bei einem Fehler ein
deutscher Satz statt eines schwarzen Bildes.
Gemessen statt vermutet: Chromium antwortet auf canPlayType für HLS mit
"maybe" und kann es dann doch nicht — deshalb entscheidet Hls.isSupported().
hls.js wiegt 372 KB und wird erst beim Abspielen geholt; die Oberfläche
bleibt bei 109.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine Serienkachel kannte der Server als Titel nicht: „als gesehen markieren"
lief in eine 404, und weil das Kontextmenü die Ablehnung verschluckte, geschah
sichtbar gar nichts. Dasselbe beim Favoriten. UserItemState bekommt eine
Serienkennung, das Häkchen zieht alle Folgen mit, und was wirft, erscheint als
Meldung statt in der Browserkonsole.
Dazu eine Mehrfachauswahl in der Mediathek — gesehen, ungesehen, Metadaten
neu holen für das Gewählte, in einer Anfrage statt in zweihundert. Ein neues
Plakat steht sofort auf der Kachel, und ein Titel, den es nicht mehr gibt,
endet nicht mehr in einer Sackgasse.
Gemessen: ein POST auf /refresh ohne Rumpf antwortete nach der Erweiterung mit
404 — also genau der Aufruf „alles auffrischen", den es länger gibt als die
Auswahl. Der Rumpf wird jetzt von Hand gelesen, und beide Formen stehen in
einer Prüfung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drei Zahlen, die alle stimmen und Verschiedenes meinen: Plex zählte 451
Filme, Flaro 449, und der Scan lief über 461 Dateien. Die
Mediathekszeile nennt sie jetzt getrennt — Titel, Folgen, Dateien,
zweite Fassungen und nicht Zugeordnetes. Damit beantwortet sich die
Frage selbst, statt offen zu bleiben.
Die Rechnung dahinter war beim ersten Versuch falsch: sie verglich
gegen alle Folgen und kam auf 1223 Titel bei 324 Dateien. Gezählt wird
jetzt, zu wie vielen Titeln überhaupt noch eine Datei daliegt — dann
geht Dateien = Titel + Fassungen + ohne auf, auch wenn etwas vermisst
wird. Nachgemessen mit einer echten Plex-Kopie: 3 Titel, 4 Dateien, 1
zweite Fassung.
Dazu trägt eine Kachel, die noch auf Freigabe wartet, jetzt ein Band —
„Wartet" oder „Geplant". Für einen Administrator standen wartende Titel
bisher mitten zwischen den freigegebenen, ohne dass etwas sie
unterschied; wer einen suchte, fand ihn nur über die Prüfliste. Dafür
reicht `PublishAt` jetzt bis in die Kachel durch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
„Metadaten auffrischen" hat an allem, was schon zugeordnet war, schlicht
nichts getan. Die Dublettenprüfung schlägt jeden Titel nach, der eine
TMDB-Kennung hat — beim Auffrischen also auch den gerade bearbeiteten.
Ohne Vergleich auf Gleichheit fand sich jeder als "Dublette seiner
selbst", wurde übersprungen und nie fortgeschrieben. Titel, Beschreibung
und Bilder blieben für immer so, wie sie beim allerersten Lauf
hereinkamen.
In der Oberfläche sah das aus, als wirke die Spracheinstellung nicht —
und genau so wurde es gemeldet. Gemessen, Ende zu Ende:
Serversprache en-US: 101 Dalmatians · The Lion King
Serversprache de-DE: 101 Dalmatiner · Der König der Löwen
Damit das nie wieder unbemerkt bleibt, weiss der Server jetzt, in welcher
Sprache er die Titel hat: eine Spalte MetadataLanguage, gesetzt beim
Anreichern, und in der Verwaltung eine Zeile mit der Verteilung. Weicht
etwas ab, frischt ein Knopf genau diese Titel auf — nicht den ganzen
Bestand, und ohne das Dateisystem noch einmal abzulaufen.
Dazu zwei Dinge, die ohne das nicht gingen: ein Titel lässt sich von Hand
setzen und wird dabei festgeschrieben wie ein Plakat, mit einem Weg
zurück. Und ein Titel, der auf Freigabe wartet, trägt jetzt dasselbe
Dreipunktemenü wie eine Kachel — Bilder, Zuordnung, Titel. Ausgerechnet
dort fehlte es, obwohl das der Eintrag ist, den man vor der Freigabe
geradeziehen will.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Befunde aus dem laufenden Betrieb.
Die Liste holte genau eine Seite. Der Server gibt höchstens 200 Einträge
je Zug — das ist richtig so —, nur fragte die Oberfläche nie nach der
zweiten. Bei 455 Filmen endete die Mediathek mitten im Alphabet, ohne
Hinweis, dass da noch etwas kommt. Jetzt wird beim Scrollen nachgeladen,
und die Zahl sagt „200 von 455" statt einer Behauptung, die man beim
Scrollen widerlegt.
Dabei kam heraus, dass ein IntersectionObserver eine Seite braucht, die
auch gezeichnet wird: im Fenster im Hintergrund löst er nicht aus, und
beim Prüfen blieb die Liste genau deshalb bei 200 stehen. Daneben steht
jetzt eine Prüfung am Scrollereignis, die überall greift.
Der zweite Befund: jede Folge zeigte zwei gleich aussehende Knopfreihen.
Es sind zwei Dateien — Plex' „Optimized for Mobile"-Kopien. Flaro kannte
„optimized", aber nicht „Optimized for Mobile", und sah ohnehin nur den
unmittelbaren Elternordner; Plex legt die Fassung aber als
`Plex Versions/Optimized for Mobile/<Serie>/<Staffel>/…` ab. Jetzt wird
drei Ebenen hoch gesucht, die Schublade `Plex Versions` benennt keine
Serie mehr, und an der Folge steht „Mobil" statt einer zweiten,
unerklärten Reihe.
Nicht um Plex zu bedienen — die Dateien liegen nun einmal so auf der
Platte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hinter der Auswahl steckt ein Abruf bei TMDB, der Titel, Besetzung und
Bilder nachlädt — mehrere Sekunden, in denen die Oberfläche aussah wie
vorher. Wer nichts sieht, klickt noch einmal, und dann laufen zwei.
Jetzt tritt die Liste zurück, die gewählte Zeile bekommt einen
Akzentrahmen und daneben steht „Wird zugeordnet…" mit laufendem Kreis.
Dazu das Plakat je Vorschlag. „Dark" von 2017 und „Dark Shadows" von
1966 sind an einer Textzeile kaum zu unterscheiden, am Bild in einer
Zehntelsekunde — und der Server lieferte die Adresse ohnehin schon mit,
sie wurde nur weggeworfen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Scan erfindet keine Serie mehr, wenn weder Ordner noch Dateiname
eine nennen — richtig so. Nur wurde die Datei dann übersprungen, ohne
Zeile, ohne Spur. In der Mediathek standen 58 Serien und niemand konnte
sagen, wo die anderen geblieben sind.
Jetzt bekommt jede solche Datei eine Zeile ohne Zuordnung. Damit ist sie
zählbar, auflistbar und nach einer besseren Regel nachträglich
zuzuordnen. Untersucht wird sie nicht: ffprobe auf 3559 Dateien kostet
eine halbe Stunde für Angaben, die niemand zu sehen bekommt, und sobald
die Zuordnung steht, holt der nächste Lauf es nach.
Dazu ein Abschnitt "Nicht zugeordnet" in der Verwaltung, nach Grund
gebündelt und mit den Pfaden zum Aufklappen. Zwei Gründe gibt es, und
sie verlangen Verschiedenes: fehlt die Folgennummer, muss umbenannt
werden; fehlt der Serienname, genügt ein Ordner darum herum. Die Liste
lässt sich als Datei herunterladen — eine, die man markieren und
kopieren muss, schickt niemand.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Pfeile sind weg; eine Mediathek wird in der Seitenleiste an ihren
Platz gezogen. Mit Pointer Events statt HTML5-Drag: letzteres kennt kein
Telefon, zeichnet ein Geisterbild, das sich nicht gestalten lässt, und
liefert während des Ziehens keine brauchbaren Koordinaten.
Mit Schwelle von sechs Bildpunkten — sonst verschiebt jeder leicht
wackelige Klick die Reihenfolge, und ein Klick ohne Bewegung führt
weiterhin zur Mediathek, auch im Bearbeitungsmodus. Die weichenden
Zeilen gleiten, die gezogene folgt dem Zeiger ohne Verzögerung; bei
„Bewegung reduzieren" gleitet nichts.
Die Pfeiltasten bleiben auf der fokussierten Zeile, nur ohne sichtbare
Knöpfe. Ziehen ist mit der Tastatur nicht bedienbar, und eine Funktion,
die nur mit der Maus erreichbar ist, ist für den, der keine benutzt, gar
keine.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Während eines Scans stand in der Mediathek 20, in der Verwaltung 14 und
in der Seitenleiste 0. Die Verwaltung frischte alle fünf Runden auf, die
Seitenleiste erst am Ende des Laufs. Jetzt laufen beide auf demselben
Takt, alle drei Runden.
Dazu: während ein Lauf läuft, sind Scannen, Metadaten auffrischen,
Zurücksetzen und Entfernen gesperrt — die ersten beiden prallen am
Server ab und sind nur verwirrend, die anderen beiden löschen Zeilen,
während der Lauf welche schreibt. Umbenennen und Prüfung bleiben
bedienbar. Die Sperre richtet sich nach dem Zustand, den der Server
meldet, nicht nach dem Klick: wer die Seite neu lädt, während ein Lauf
läuft, findet sie ebenfalls gesperrt vor.
Die Reihenfolge der Mediatheken wird jetzt in der Seitenleiste
umsortiert, über „Seitenleiste bearbeiten" neben der Überschrift. Sie
wirkt dort, also gehört der Griff dorthin — vorher schob man in den
Einstellungen und musste danach nachsehen, ob es das war, was man
wollte.
Der Zuordnungsdialog zeigt die Herkunft: Ordner, Zahl der Dateien und
ein paar Namen. Liegt eine Zuordnung völlig daneben, sagt der angezeigte
Titel nichts mehr darüber, welche Datei gemeint ist.
Und SQLite läuft jetzt im WAL-Modus. In der Vorgabe sperrt ein Schreiber
die ganze Datei: solange der Scan schrieb, kam keine Leseanfrage durch.
Genau so sah es aus — Bilddialog und Protokoll liefen während eines
Laufs sporadisch ins Leere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein grosser Commit, weil die Punkte einander bedingen: ohne lesbare
Fehlermeldung war die Serienerkennung nicht zu diagnostizieren, und ohne
Build-Kennung nicht einmal festzustellen, ob überhaupt der gebaute Stand
läuft. Zwei der neun Meldungen betrafen Funktionen, die seit Stunden im
Quelltext stehen.
Version und Build. Die Version steht fest; daneben eine Kennung aus
sechs Zeichen, die sich bei jedem Docker-Bau ändert. Sie steht in der
Verwaltung, unter /health und im Protokoll bei jedem Start. Damit ist
"reden wir vom selben Build?" in zwei Sekunden beantwortet statt in
einem halben Tag.
Serien. Lag eine Datei direkt im Serienordner und trug vor der
Folgennummer nichts, wurde der ganze Dateiname zum Serientitel: aus 95
Serien wurden 737, jede mit einer Folge, bei jedem Lauf neu. Dazu lief
der Scan in Verweise hinein — derselbe Ordner unter zwei Namen ergab
zwei Serien. Und weder neue noch umgezogene Dateien standen in der
Pfadliste des Laufs, weshalb ein doppelt gesehener Pfad eine zweite
Zeile mit gleichem (LibraryId, Path) anlegte und der
Eindeutigkeitsindex den ganzen Speichervorgang scheitern liess. Jede
Serienanlage wird jetzt im Tagesprotokoll begründet.
Fehlermeldungen. "An error occurred while saving the entity changes"
stand englisch in einer deutschen Oberfläche und nannte weder Ursache
noch nächsten Schritt. Jetzt geht der vollständige Text ins Protokoll
und ein deutscher Satz ohne Fehlercode in die Anzeige — auch für
"Failed to fetch", das aus dem Browser kam und nie übersetzt wurde.
Protokolle. Die Ansicht holte die ganze Datei und zeigte 800 Zeilen
davon; bei zwei Megabyte brach die Verbindung ab. Gelesen wird jetzt
serverseitig rückwärts, mit einem Knopf für mehr.
Auswahlfelder. Die drei <select> zeichnete das Betriebssystem: ein
helles Systemmenü mitten in der dunklen Oberfläche. Ersetzt durch ein
eigenes Listenfeld mit Tastaturbedienung.
Bildwahl. Drei Raster untereinander in einem scrollenden Dialog hiess
zwei Scrollebenen übereinander. Jetzt ein Reiter je Bildtyp.
Sprache. Die Serversprache stand in der Serverliste zwischen Name,
Metadaten und Fassung — gesucht und nicht gefunden. Sie hat jetzt einen
eigenen Abschnitt ganz oben.
Dazu: ein Knopf, der den erfassten Inhalt einer Mediathek verwirft, ohne
Name und Pfad mitzunehmen; ein Abschnitt Speicher mit den drei Pfaden,
ihrer Belegung und dem Leeren des Bildspeichers; und die Korrektur einer
Zuordnung frischt nur noch die Kachel auf statt die ganze Seite.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>