From 5e7806816918e768de10915119bc09642bea6abf Mon Sep 17 00:00:00 2001 From: xRangerDE Date: Tue, 19 May 2026 04:04:33 +0200 Subject: [PATCH] =?UTF-8?q?release:=205.0.6=20=E2=80=94=20streamlink=20std?= =?UTF-8?q?out-Capture=20+=20CSS=20select+checkbox=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- package-lock.json | 4 ++-- package.json | 2 +- src/main.ts | 48 +++++++++++++++++++++++++++++++++++------------ src/styles.css | 27 +++++++++++++++----------- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index ceaf6ae..63baccd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "twitch-vod-manager", - "version": "5.0.5", + "version": "5.0.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "twitch-vod-manager", - "version": "5.0.5", + "version": "5.0.6", "license": "MIT", "dependencies": { "axios": "^1.6.0", diff --git a/package.json b/package.json index 68850a9..10a53a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "twitch-vod-manager", - "version": "5.0.5", + "version": "5.0.6", "description": "Twitch VOD Manager - Download Twitch VODs easily", "main": "dist/main.js", "author": "xRangerDE", diff --git a/src/main.ts b/src/main.ts index 478168d..019d2c8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3139,13 +3139,24 @@ function downloadVODPart( } }, 1000); + const stdoutBuffer: string[] = []; proc.stdout?.on('data', (data: Buffer) => { const line = data.toString(); - // No per-line stdout — streamlink emits 10-100 lines/sec during - // an active download, which floods the terminal in dev and the - // electron-launched console in prod. Progress + tag parsing - // below extracts everything we need; failures get logged via - // appendDebugLog from the consumer side. + // Capture non-progress lines auch fuer Diagnose — streamlink-Windows- + // Builds schreiben einige Errors auf stdout statt stderr (z.B. "error: + // No playable streams found on this URL"). Wenn stderr leer bleibt, + // greift der close-handler auf stdout zurueck. + stdoutBuffer.push(line); + if (stdoutBuffer.length > 200) stdoutBuffer.shift(); + const lower = line.toLowerCase(); + if (lower.includes('error:') || lower.includes('warning:')) { + appendDebugLog('download-part-stdout-err', { itemId, message: line.trim() }); + if (lower.includes('error:')) { + // Letzte echte streamlink-Errorzeile, auch wenn auf stdout + const errLine = line.split('\n').map(l => l.trim()).filter(l => l.toLowerCase().includes('error:')).pop(); + if (errLine) lastErrorLine = errLine; + } + } // Parse progress const match = line.match(/(\d+\.\d+)%/); @@ -3227,17 +3238,30 @@ function downloadVODPart( return; } - // Volle stderr-History im Debug-Log (kollabiert) — fuer Forensik - // wenn der User schreibt "es funktioniert nicht". User-facing - // genericError ist die echte streamlink-Fehlerzeile, nicht nur - // "Streamlink Fehlercode 1". + // Volle stderr+stdout-History im Debug-Log fuer Forensik. + // Streamlink-Windows-Builds schreiben Errors gelegentlich auf + // stdout statt stderr ("No playable streams found on this URL" + // war historisch ein stdout-Error). Wir mergen beide Streams + // damit immer SICHTBAR ist was passiert. const fullStderr = stderrBuffer.join('').trim(); - const userFacingError = lastErrorLine - || (fullStderr.split('\n').filter(l => l.trim()).pop() || '').trim() - || tBackend('streamlinkExitCode', { code: String(code ?? -1) }); + const fullStdout = stdoutBuffer.join('').trim(); + // Letzte Error-/Warning-Zeile aus beiden Streams suchen, falls + // lastErrorLine noch leer ist (z.B. weil streamlink ohne Output + // mit Code 1 exited — was bei pre-flight-Auth-Fails passiert). + let userFacingError = lastErrorLine; + if (!userFacingError) { + const combined = (fullStderr + '\n' + fullStdout).split('\n').map(l => l.trim()).filter(Boolean); + userFacingError = combined.filter(l => l.toLowerCase().includes('error:')).pop() + || combined.filter(l => !l.startsWith('[')).pop() + || ''; + } + if (!userFacingError) { + userFacingError = tBackend('streamlinkExitCode', { code: String(code ?? -1) }); + } appendDebugLog('download-part-failed', { itemId, filename, code, error: userFacingError, stderrTail: fullStderr.slice(-2000), + stdoutTail: fullStdout.slice(-2000), }); resolve({ success: false, error: userFacingError }); }); diff --git a/src/styles.css b/src/styles.css index 99acaf7..cdc26d5 100644 --- a/src/styles.css +++ b/src/styles.css @@ -756,20 +756,21 @@ input[type="checkbox"]:hover:not(:disabled) { } input[type="checkbox"]:checked { - background: var(--accent); + /* Inline-SVG-Checkmark statt rotated-border-Trick — robuster ueber + DPI-Skalierungen und Remote-Desktop-Renderings (RDP / mstsc), wo + die kleinen border-rotation-Pseudo-Elemente teilweise als + Dreiecke / Pfeile gerendert wurden. */ + background-color: var(--accent); + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3.5 8.5 6.5 11.5 12.5 5'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: center; + background-size: 12px; border-color: var(--accent); } input[type="checkbox"]:checked::after { - content: ''; - position: absolute; - left: 4px; - top: 0.5px; - width: 5px; - height: 9px; - border: solid #fff; - border-width: 0 2px 2px 0; - transform: rotate(45deg); + /* Pseudo-Element nicht mehr noetig — Checkmark kommt aus background. */ + content: none; } input[type="checkbox"]:focus-visible { @@ -1761,7 +1762,11 @@ select option { .form-group input:not([type="checkbox"]):not([type="radio"]), .form-group select { width: 100%; - background: var(--bg-main); + /* background-color (nicht background shorthand) — sonst wuerden + background-image (Chevron-SVG), background-repeat, background-size + und background-position aus der globalen `select`-Regel resettet, + was zu tiled Chevrons im Dropdown gefuehrt hat. */ + background-color: var(--bg-main); border: 1px solid rgba(255,255,255,0.1); border-radius: 4px; padding: 10px 12px;