Hauptfix (User-Report): in der VOD-Grid sass der Trim/Queue-Button bei
Cards mit 1-zeiligem Titel hoeher als bei 2-zeiligen Nachbarn. Ursache:
.vod-card war ein Block, Buttons flossen mit dem Content. Grid streckt
zwar alle Cards einer Reihe gleich hoch, aber der Leerraum landete unten.
Fix: .vod-card = flex column, .vod-actions = margin-top:auto -> Buttons
docken am Boden an. Verifiziert per Playwright ueber xqc (16 Reihen),
papaplatte (6), xrohat (12): maxButtonTopSpread = 0px in allen.
Weitere Funde aus dem Screenshot-Pass (scripts/ui-screenshot.js):
- Globale Basis-Dark-Theme-Regel fuer alle text-Inputs + textarea, damit
bare Inputs ohne .form-group/.form-stack Wrapper nie OS-weiss durchkommen
(#cutterFilePath war weiss im Dark-Theme).
- Cutter-Preview-Placeholder 'Video auswahlen um Vorschau zu sehen' war
hardcoded Deutsch ohne id -> id + Locale-Key + Wiring (zeigt jetzt
'Select a video to see a preview' im EN-Mode).
- Clips-Button '#btnClip' wurde nie lokalisiert (zeigte immer 'Clip
herunterladen') -> setText-Wiring ergaenzt, nutzt existierenden
clips.downloadButton key.
scripts/ui-screenshot.js: neues Harness das die App startet, durch
Tabs/Streamer/Themes navigiert, Screenshots macht + Button-Alignment
programmatisch misst.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root Cause (User-Report): bei Part 1/6 Multi-Part-Download mit 869 MB
schon geladen, blieb der Bar auf einer fixen Position weit links — sah
aus als ob ein paar % erreicht waeren obwohl viel mehr lief.
Drei Probleme die das aus 5.0.1-5.0.11 noch ueberlebt haben:
1. downloadVODPart Path A (1-Sek-Heartbeat) emittierte progress=-1
wenn HLS kein known total hat. UI flippte zwischen 'determinate
bei letztem streamlink-%' und 'indeterminate-Animation' — User
sah einen 35%-Bar der zwischen Streamlink-%-Updates kurz aufpoppt.
2. Part-based-Split (download_mode='parts', langes VOD in N Stunden-
Parts) hat downloadVODPart's onProgress UNGEWRAPPT an die UI
gegeben. Bar zeigte 'X% von Part i' statt 'gewichtete overall %'.
Bei Part-Wechsel sprang er von 100% zurueck auf 0%. Bei Part 1
mit 50% Stream-Progress zeigte der Bar 50% obwohl overall erst
bei 8.3% (1 von 6 Parts halb fertig).
3. Full-VOD-Download (kein --hls-duration) hatte kein expected total
fuer den bytes-Estimate -> blieb in indeterminate-Mode.
Fixes:
- downloadVODPart bekommt optionalen Parameter.
Path A schaetzt jetzt progress aus downloadedBytes / (duration *
~625 KB/s, Twitch ~5 Mbit/s Schaetzung), gecappt bei 95%. Wenn
streamlink-stdout-% rauskommt, override mit dem (genauer). Nur
noch progress=-1 wenn weder bytes noch streamlink-% verfuegbar.
- Part-based-Split (downloadVodWithStrategy) wrappt onProgress jetzt
mit einem Aggregator: pro Part den max-bekannten %-Wert merken,
overallProgress = avg(allParts). Bei Part-Done aus dem Loop
partProgresses[i] = 100 setzen. Bar steigt monoton von 0% auf
100% ueber alle Parts.
- Full-VOD-Download passt totalDuration als expectedTotalSec an
downloadVODPart, sodass auch hier der bytes-Estimate greift.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.0.9 hatte .form-stack input/select und .input-narrow Dark-Theme-Styling
gegeben, aber der border-color in der base rule ist rgba(255,255,255,0.1) —
auf hellem Light-Theme-Background unsichtbar. Im Light-Theme-Block sind
.form-group und .add-streamer schon ueberschrieben, .form-stack und
.input-narrow fehlten.
Fix: light-theme border-color rgba(0,0,0,0.12) auch fuer .form-stack
input/select und .input-narrow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DEFAULT_METADATA_CACHE_MINUTES und DEFAULT_PERFORMANCE_MODE waren
dupliziert in main.ts und src/main/domain/config-normalize.ts. Wenn jemand
einen Default aendert (z.B. metadata-cache von 10 auf 15min), ist die
andere Seite still drift-anfaellig — config laedt den alten Default
beim Erst-Start aber normalize-Funktion fallt auf den neuen zurueck.
Fix: beide Konstanten werden jetzt aus config-normalize.ts exportiert
und in main.ts importiert. Single source of truth.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inputs/Selects in .form-stack Containern (Auto-Cleanup: Tage-Schwelle,
Bereich, Aktion) und bare .input-narrow Inputs (Auto-VOD: Poll-Intervall,
Max. Alter) hatten OS-default-weisse Backgrounds — die existierende
.form-group-Regel matched die Selektoren nicht.
Fix: .form-stack-Selektoren parallel zu .form-group hinzugefuegt, und
.input-narrow stylt sich jetzt selbst (background-color + border +
hover/focus state) damit auch bare Inputs ohne wrapper consistent
aussehen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
.form-group input[type='checkbox'] hatte width:auto, das die 16x16 aus
der globalen Regel ueberschrieben hat (Klassen-Specificity > Type-
Specificity). Vor 5.0.6 unsichtbar weil der rotated-border-Checkmark
absolut positioniert war und keine Box-Breite brauchte. Mit dem 5.0.6
inline-SVG-Checkmark brauchts echte Breite — daher in den Settings
plotzlich nur noch 1-2px schmale Vertikalstreifen sichtbar statt
echter Checkboxen.
Fix: width:16px explicit in der .form-group-Regel, behaelt die globale
Groesse bei.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Streamlink Diagnose:
- stdout-Buffer wird jetzt zusaetzlich zu stderr gesammelt; einige
streamlink-Builds schreiben 'error:'-Lines auf stdout statt stderr,
was bisher zu leerem stderrTail + 'Streamlink exit code 1' ohne
Detail-Info gefuehrt hat.
- download-part-failed Debug-Log enthaelt jetzt stderrTail UND
stdoutTail (jeweils letzte 2000 chars), plus User-facing-Error wird
aus beiden Streams kombiniert gesucht.
CSS:
- .form-group select: 'background: ...' Shorthand wurde durch
'background-color: ...' ersetzt — Shorthand hatte background-image
(Chevron-SVG), background-repeat, background-position, background-size
aus der globalen select-Regel resettet, was zu tiled Chevrons im
Dropdown gefuehrt hat ('Best (default) ▼▼▼▼▼▼...').
- input[type='checkbox']:checked: rotated-border-Trick durch inline-
SVG-Checkmark ersetzt — die rotated borders renderten in mstsc/RDP-
Sessions teilweise als Pfeile statt Haken (DPI-Skalierungs-Artefakt).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Problem: User berichtet 'streamlink exit code 1' bei VOD-Downloads ohne
sinnvolle Fehlermeldung — UI zeigt 'Retrying in 8s (unknown)...'. Root
Cause: classifyDownloadError matched die echten Twitch-Errors nicht und
nur die letzte stderr-Zeile wurde im Debug-Log gespeichert.
Fixes:
- Volle stderr-History wird gepuffert + im download-part-failed Debug-Log
als stderrTail (letzte 2000 chars) gespeichert
- UI bekommt jetzt die echte streamlink Error-Zeile statt 'Streamlink
Fehlercode N' (prefer 'error:'-prefixed Zeilen, dann last non-bracket
non-INFO line)
- classifyDownloadError matcht jetzt zusaetzlich: 'no playable streams',
'could not find any kind of stream', 'access token', 'session token',
'signature', 'integrity token', 'subscriber only', 'sub-only',
'not subscribed', 'http error', 'connectionerror', 'readerror'
Streamlink-Args:
- --stream-segment-attempts 5 (default 3 — mehr Retries bei flaky CDN)
- --stream-segment-timeout 20
- --stream-timeout 120
- --retry-streams 3 (retry initial stream listing)
- --retry-max 2
Damit ueberlebt der Download transiente Twitch-CDN-Hicks und der User
sieht im naechsten Fail die echte Fehlerursache in der UI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Probleme der 5.0.3:
- CSS .vod-storyboard-preview hatte noch aspect-ratio:16/9, top:0, left:0, right:0
- JS hat dann inset:0 + aspect-ratio:auto inline gesetzt
- Im Electron-28-Chromium kam ein Layout-Konflikt raus -> Overlay-Box-
Dimensions wichen von Host ab -> backgroundSize-Skalierung passte nicht
zu visible-area -> mehrere Cells gleichzeitig sichtbar (Sprite-Sheet-
Look statt Single-Cell-Preview)
Fix 5.0.4:
- CSS-Klasse hat NUR noch Visual+Stacking (opacity, transition, border-
radius, overflow:hidden, z-index, position:absolute, pointer-events)
- KEIN top/left/right/bottom/width/height/aspect-ratio im CSS
- JS setzt alles inline und voll explicit: top=0, left=0, width=Xpx,
height=Ypx aus hostRect (.vod-thumb-wrap)
- Sanity-Guards fuer width/height<=0 und cellWidth/cellHeight<=0
- scaleX und scaleY weiter unabhaengig fuer korrekte Cell-Box-Fuellung
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wechsel von explicit width/height auf inset:0 (top/right/bottom/left:0,
width/height:auto, aspect-ratio:auto override des CSS-Legacy 16/9). Damit
fuellt das Overlay garantiert das gesamte .vod-thumb-wrap — kein leerer
Streifen mehr am oberen oder unteren Rand der Hover-Vorschau, egal ob
Twitch Storyboard-Cell-Aspect oder Subpixel-Rendering minimal abweicht.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix 1: scaleX und scaleY werden jetzt unabhaengig berechnet. Twitch
Storyboard-Cells haben nicht zwingend 16:9; eine einheitliche scale-Variable
fuehrte zu Subpixel-Leakage am oberen oder unteren Rand mit Inhalt aus der
Nachbarzelle. Mit getrennter Achsen-Skalierung fuellt eine Cell die Overlay-
Box exakt.
Fix 2: Bulk-Select-Checkbox und Downloaded-Badge werden waehrend des Hover-
Previews ausgeblendet (vorher nur die Duration-Badge). Mein vorheriger Move
des Overlays in .vod-thumb-wrap hatte die Z-Order so geaendert, dass diese
Elemente jetzt sichtbar drueber lagen.
219 unit tests + e2e gruen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bug 1 — VOD-Hover Storyboard zeigte am unteren Rand einen statischen Streifen vom Original-Thumbnail (Subpixel-Mismatch + Aspect-Ratio-Konflikt). Fix: Overlay haengt jetzt an .vod-thumb-wrap statt .vod-card, mit explizitem width+height aus dem Thumbnail-BoundingRect — keine CSS-aspect-ratio-Interferenz mehr.
Bug 2 — Merge-Group Download zeigte einen eingefrorenen Progress-Bar bei Multi-Part-VODs (Part X/Y). Root Cause: der weighted-progress Wrapper clamped progress=-1 (HLS unknown-total 1s-Tick) auf 0, was overallProgress auf priorWeight fix-nagelte. Bar oszillierte zwischen indeterminate-animation und einem fixen ~10% Wert. Fix: lastVodProgress persistiert zwischen Path-A-Ticks und Path-B-Streamlink-%-Lines, sodass der Bar smooth waehrend einer Part hochzaehlt.
210 unit tests + e2e:release gruen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pillar 5 (UI Power) erweitert: Ctrl+K matched jetzt auch Streamer-Namen
(tippe Name oder @login → springt direkt zum Streamer im VODs-Tab).
Plus .gitignore-Hygiene.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pillar 7 (Auto-Discovery) gets the Helix top-clips-crawler module (9 tests).
Pillar 5 (UI Power) gets its first visible component: Command Palette via
Ctrl+K with 6 tab-jump commands.
219 unit tests + e2e:release gruen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan 04 abgeschlossen.
- schema-v5.ts: chunk_index table (item_id, chunk_seq, sha1_hex, bytes)
- src/main/infra/chunk-hash.ts: sha1 buffer + streaming file
- src/main/domain/chunk-index-store.ts: CRUD + dedupe lookup
- 143 unit tests (vorher 126, +17 fuer schema + hash + store)
- npm run test:e2e:release gruen
Integration mit dem live Recorder folgt in Plan 04b. Plan 04 ist rein
additiv; kein bestehender Recorder-Code wurde modifiziert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>