From 86fde7d62cf761b567c6e4a9be837e2bebbec0e6 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Fri, 19 Jun 2026 14:17:45 -0700 Subject: [PATCH] video search UI: show slskd peers/username, live vs demo, errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Result meta now adapts to the source: Soulseek shows '👤 uploader · N peers · N slots' (real slskd availability); torrent/usenet keep '▲ seeders' (still mock). - Results header shows a '● live' badge for real slskd searches vs an amber 'demo data' badge for the still-mocked sources — so it's never ambiguous again. - slskd errors ('not configured', network) surface as a clear ⚠ line in the panel. JS/CSS balance clean. --- webui/static/video/video-download-view.js | 15 +++++++++++++-- webui/static/video/video-side.css | 8 +++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/webui/static/video/video-download-view.js b/webui/static/video/video-download-view.js index 436b010f..6fe8e09b 100644 --- a/webui/static/video/video-download-view.js +++ b/webui/static/video/video-download-view.js @@ -218,12 +218,14 @@ postJSON('/api/video/downloads/search', params).then(function (d) { _setScanning(triggerRows, false); if (!resultsEl.isConnected) return; + if (d && d.error) { resultsEl.innerHTML = '
⚠ ' + esc(d.error) + '
'; return; } var rows = (d && d.results) || []; if (!rows.length) { resultsEl.innerHTML = '
No matching releases found.
'; return; } var okN = rows.filter(function (r) { return r.accepted; }).length; + var live = d && d.live ? '● live' : 'demo data'; resultsEl.innerHTML = '
' + rows.length + ' result' + (rows.length === 1 ? '' : 's') + - ' · ' + okN + ' meet your profile
' + + ' · ' + okN + ' meet your profile' + live + '' + rows.map(resultCardHTML).join(''); }); } @@ -237,6 +239,15 @@ return res === '2160p' ? '4k' : res === '1080p' ? '1080' : res === '720p' ? '720' : 'sd'; } + // Availability differs by source: slskd has a peer (uploader); torrent/usenet seeders. + function resAvailHTML(r) { + if (r.username) { + return '👤' + esc(r.username) + + (r.peers > 1 ? ' · ' + r.peers + ' peers' : '') + (r.slots ? ' · ' + r.slots + ' slots' : '') + ''; + } + return '▲ ' + (r.seeders || 0) + ' seeders'; + } + // Readable card: a big resolution tile anchors it, a plain-English quality summary // leads, the raw release name is demoted to a muted one-liner, then size/seeders. function resultCardHTML(r) { @@ -259,7 +270,7 @@ '
' + esc(r.title) + '
' + '
' + '💾' + r.size_gb + ' GB' + - '▲ ' + (r.seeders || 0) + ' seeders' + + resAvailHTML(r) + (r.group ? '' + esc(r.group) + '' : '') + '
' + '' + diff --git a/webui/static/video/video-side.css b/webui/static/video/video-side.css index f45ba930..f60bb62e 100644 --- a/webui/static/video/video-side.css +++ b/webui/static/video/video-side.css @@ -3260,9 +3260,15 @@ body[data-side="video"] #soulsync-toggle { display: none; } border: 2px solid rgba(255, 255, 255, 0.2); border-top-color: rgb(var(--accent-rgb)); animation: vdlSpin 0.7s linear infinite; } @keyframes vdlSpin { to { transform: rotate(360deg); } } .vdl-res-empty { font-size: 12.5px; color: rgba(255, 255, 255, 0.45); padding: 9px 2px; } -.vdl-res-head { font-size: 11.5px; font-weight: 700; color: rgba(255, 255, 255, 0.5); margin: 4px 0 10px; } +.vdl-res-head { display: flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 700; + color: rgba(255, 255, 255, 0.5); margin: 4px 0 10px; } .vdl-res-head strong { color: #fff; } .vdl-res-okn { color: #8fe7af; } +.vdl-res-live, .vdl-res-demo { margin-left: auto; font-size: 10px; font-weight: 800; padding: 2px 8px; border-radius: 999px; + text-transform: uppercase; letter-spacing: 0.04em; } +.vdl-res-live { background: rgba(108, 211, 145, 0.16); color: #8fe7af; } +.vdl-res-demo { background: rgba(245, 158, 11, 0.14); color: #fbcd7a; } +.vdl-res-err { color: #fbcd7a; } /* result row: [resolution tile] [body: summary + name + meta] [grab] */ .vdl-res { display: flex; align-items: stretch; gap: 12px; border-radius: 13px; border: 1px solid rgba(255, 255, 255, 0.08); background: rgba(255, 255, 255, 0.035);