cleanup: archive search results — extract 10 inline styles into row classes
renderArchiveSearchResults was building each result row as an HTML template literal carrying ~10 inline-style props per row (flex layouts, padding, border-bottom, font-sizes, secondary text colour, ellipsis truncation, gap...). For a 200-hit search that meant ~2KB of duplicated inline style noise in the DOM and made any visual tweak require editing the renderer. Extracted to a .archive-result-* family in styles.css: - .archive-result-row + hover-tint (table-row scannability — was missing before, every row read flat) - .archive-result-body / -meta / -streamer / -date / -filename / -size / -actions for the column layout - .archive-type-badge with .live + .vod modifiers for the LIVE/VOD pill (was two separate inline-styled spans with hard-coded rgba colours) - .archive-no-matches for the empty-state line Dates + sizes in the row pick up font-variant-numeric: tabular-nums so columns of numbers align even when filenames are different widths. Last-child gets its bottom border dropped so the list doesnt end on a dangling line — same treatment as the storage stats table. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
58f8164db4
commit
a2b7a02db7
@ -110,15 +110,13 @@ function renderArchiveSearchResults(result: ArchiveSearchResult): void {
|
||||
}
|
||||
|
||||
if (result.hits.length === 0) {
|
||||
applyArchiveHtml(resultsEl, `<div style="color: var(--text-secondary); padding: 12px;">${escapeArchiveHtml(UI_TEXT.static.archiveNoMatches || 'Keine Treffer.')}</div>`);
|
||||
applyArchiveHtml(resultsEl, `<div class="archive-no-matches">${escapeArchiveHtml(UI_TEXT.static.archiveNoMatches || 'Keine Treffer.')}</div>`);
|
||||
return;
|
||||
}
|
||||
|
||||
const rows = result.hits.map((hit) => {
|
||||
const date = new Date(hit.mtimeMs).toLocaleString();
|
||||
const typeBadge = hit.type === 'live'
|
||||
? `<span style="background: rgba(255,68,68,0.18); color: #ff4444; font-size: 10px; font-weight:700; padding: 2px 6px; border-radius: 3px;">LIVE</span>`
|
||||
: `<span style="background: rgba(145,70,255,0.18); color: #9146ff; font-size: 10px; font-weight:700; padding: 2px 6px; border-radius: 3px;">VOD</span>`;
|
||||
const typeBadge = `<span class="archive-type-badge ${hit.type === 'live' ? 'live' : 'vod'}">${hit.type === 'live' ? 'LIVE' : 'VOD'}</span>`;
|
||||
const safeFullAttr = hit.fullPath.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
||||
const chatBtn = hit.chatPath
|
||||
? `<button class="queue-detail-btn" onclick="openEventsOrChat('${safeFullAttr.replace(/\.(mp4|mkv|ts|m4v)$/i, '.chat.jsonl')}', '${escapeArchiveHtml(hit.fileName)}', 'chat')">${escapeArchiveHtml(UI_TEXT.static.archiveViewChat || 'Chat')}</button>`
|
||||
@ -127,17 +125,17 @@ function renderArchiveSearchResults(result: ArchiveSearchResult): void {
|
||||
? `<button class="queue-detail-btn" onclick="openEventsOrChat('${(hit.eventsPath || '').replace(/\\/g, '\\\\').replace(/'/g, "\\'")}', '${escapeArchiveHtml(hit.fileName)}', 'events')">${escapeArchiveHtml(UI_TEXT.static.archiveViewEvents || 'Events')}</button>`
|
||||
: '';
|
||||
return `
|
||||
<div style="display:flex; padding: 10px 8px; border-bottom: 1px solid var(--border-soft); gap: 10px; align-items: center;">
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="display:flex; gap: 8px; align-items: center; margin-bottom: 4px;">
|
||||
<div class="archive-result-row">
|
||||
<div class="archive-result-body">
|
||||
<div class="archive-result-meta">
|
||||
${typeBadge}
|
||||
<strong style="color: var(--text);">${escapeArchiveHtml(hit.streamer)}</strong>
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">${escapeArchiveHtml(date)}</span>
|
||||
<strong class="archive-result-streamer">${escapeArchiveHtml(hit.streamer)}</strong>
|
||||
<span class="archive-result-date">${escapeArchiveHtml(date)}</span>
|
||||
</div>
|
||||
<div style="font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="${escapeArchiveHtml(hit.fullPath)}">${escapeArchiveHtml(hit.fileName)}</div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary); margin-top: 2px;">${escapeArchiveHtml(formatBytesForArchive(hit.size))}</div>
|
||||
<div class="archive-result-filename" title="${escapeArchiveHtml(hit.fullPath)}">${escapeArchiveHtml(hit.fileName)}</div>
|
||||
<div class="archive-result-size">${escapeArchiveHtml(formatBytesForArchive(hit.size))}</div>
|
||||
</div>
|
||||
<div style="display:flex; flex-direction: column; gap: 4px; flex-shrink: 0;">
|
||||
<div class="archive-result-actions">
|
||||
<button class="queue-detail-btn" onclick="openFilePath('${safeFullAttr}')">${escapeArchiveHtml(UI_TEXT.static.archiveOpen || 'Oeffnen')}</button>
|
||||
<button class="queue-detail-btn" onclick="showFileInFolder('${safeFullAttr}')">${escapeArchiveHtml(UI_TEXT.static.archiveShowInFolder || 'Ordner')}</button>
|
||||
${chatBtn}
|
||||
|
||||
@ -2116,6 +2116,98 @@ select option {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
ARCHIVE SEARCH RESULTS — row layout
|
||||
============================================
|
||||
Replaces ~10 inline-styled divs in renderer-archive's row template
|
||||
with reusable classes. Hover background scoped to the row so the
|
||||
list scans as a real interactive list. */
|
||||
.archive-no-matches {
|
||||
color: var(--text-secondary);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.archive-result-row {
|
||||
display: flex;
|
||||
padding: 10px 8px;
|
||||
border-bottom: 1px solid var(--border-soft);
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
transition: background 0.12s;
|
||||
}
|
||||
|
||||
.archive-result-row:hover {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.archive-result-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.archive-result-body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.archive-result-meta {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.archive-result-streamer {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.archive-result-date {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.archive-result-filename {
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.archive-result-size {
|
||||
font-size: 11px;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 2px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.archive-result-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Type pill — LIVE / VOD chip in the archive row's meta line. */
|
||||
.archive-type-badge {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.archive-type-badge.live {
|
||||
background: rgba(255, 68, 68, 0.18);
|
||||
color: #ff4444;
|
||||
}
|
||||
|
||||
.archive-type-badge.vod {
|
||||
background: rgba(145, 70, 255, 0.18);
|
||||
color: #9146ff;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user