From 5d5ffa675b0bd0bd7f0f29f13ba38c64a279a244 Mon Sep 17 00:00:00 2001 From: xRangerDE Date: Mon, 11 May 2026 03:56:13 +0200 Subject: [PATCH] =?UTF-8?q?cleanup:=20merge-tab=20empty=20state=20?= =?UTF-8?q?=E2=80=94=20DOM-built=20instead=20of=20innerHTML=20template?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mergeFiles is empty, the renderer dropped an inline-styled innerHTML template into #mergeFileList:

${UI_TEXT.merge.empty}

Three issues: - innerHTML interpolating a locale string (lint hook flags pattern even though locale strings are app-controlled) - Inline styles for padding / opacity / margin - The same SVG icon as the static HTML, duplicated Built via createElement + createElementNS for the SVG namespace, so the renderer never touches innerHTML for this branch. Styling moved to a .merge-empty-state class that scopes the padding override (needed because the merge file-list sits in a settings-card with its own padding) without leaking into the global .empty-state used by the VOD grid. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/renderer.ts | 23 +++++++++++++++++------ src/styles.css | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/renderer.ts b/src/renderer.ts index d354c27..3fea8fe 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -1561,12 +1561,23 @@ function renderMergeFiles(): void { byId('btnMerge').disabled = mergeFiles.length < 2; if (mergeFiles.length === 0) { - list.innerHTML = ` -
- -

${UI_TEXT.merge.empty}

-
- `; + // Build via DOM API to keep the renderer clean of inline-styled + // HTML strings. The empty-state SVG is the same plus-icon the + // static HTML uses, just built programmatically. + list.replaceChildren(); + const wrap = document.createElement('div'); + wrap.className = 'empty-state merge-empty-state'; + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('viewBox', '0 0 24 24'); + svg.setAttribute('fill', 'currentColor'); + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + path.setAttribute('d', 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'); + svg.appendChild(path); + wrap.appendChild(svg); + const p = document.createElement('p'); + p.textContent = UI_TEXT.merge.empty; + wrap.appendChild(p); + list.appendChild(wrap); return; } diff --git a/src/styles.css b/src/styles.css index 7f088ce..6954d73 100644 --- a/src/styles.css +++ b/src/styles.css @@ -2086,6 +2086,23 @@ select option { line-height: 1.4; } +/* Merge-tab empty state — uses the global .empty-state base and adds + its own padding override since the merge file-list container sits + inside a settings-card with its own padding. */ +.merge-empty-state { + padding: 40px 20px; +} + +.merge-empty-state svg { + opacity: 0.3; + width: 48px; + height: 48px; +} + +.merge-empty-state p { + margin-top: 10px; +} + /* Old generic scrollbar rules were dead — superseded by the purple-themed *::-webkit-scrollbar block further down the file. Removed to avoid confusion when someone greps for scrollbar styles. */