From be141d0073e205000777c4ff5f43cf15c8d8f934 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sun, 14 Jun 2026 09:28:14 -0700 Subject: [PATCH] video dashboard: Library card is a live scan tool (parity with music) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Refresh/Deep Scan buttons already fired a scan, but the card gave no feedback so it looked dead. Now it mirrors music's dashboard library card: - a progress section (phase + bar + detail) appears during a scan, driven by the shared scan events (real percent); - buttons disable while scanning; - the card hydrates on load/return — if a scan is already running, video-scan.js re-emits progress and the card shows it; - stats refresh when the scan finishes. Reuses music's .library-status-progress classes. 84 tests green. --- tests/test_video_side_shell.py | 2 ++ webui/index.html | 5 ++++ webui/static/video/video-dashboard.js | 41 +++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/tests/test_video_side_shell.py b/tests/test_video_side_shell.py index 9090a7a2..70a530f2 100644 --- a/tests/test_video_side_shell.py +++ b/tests/test_video_side_shell.py @@ -184,6 +184,8 @@ def test_dashboard_library_card_has_refresh_and_deep_buttons(): assert 'data-video-scan-mode="full"' in block # Refresh assert 'data-video-scan-mode="deep"' in block # Deep Scan assert "library-status-actions" in block + # The card shows live scan progress (parity with the music dashboard). + assert "data-video-dash-progress" in block and "data-video-dash-bar" in block def test_scan_module_referenced_and_isolated(): diff --git a/webui/index.html b/webui/index.html index 327bd0b7..cc991879 100644 --- a/webui/index.html +++ b/webui/index.html @@ -608,6 +608,11 @@ + diff --git a/webui/static/video/video-dashboard.js b/webui/static/video/video-dashboard.js index aae122dc..667b95cf 100644 --- a/webui/static/video/video-dashboard.js +++ b/webui/static/video/video-dashboard.js @@ -117,8 +117,43 @@ loadStats(); } + // ── Library card: live scan progress (parity with the music dashboard) ── + // The scan buttons (data-video-scan-mode) are wired by video-scan.js; here + // we reflect progress on the card and hydrate if a scan is already running + // (video-scan.js re-emits the progress event on load). + function dashButtons() { + return document.querySelectorAll( + '.video-subpage[data-video-subpage="video-dashboard"] [data-video-scan-mode]'); + } + + function onDashScanProgress(e) { + var s = e.detail || {}; + if (s.state !== 'scanning') return; + var prog = document.querySelector('[data-video-dash-progress]'); + if (prog) prog.classList.remove('hidden'); + var phase = (s.phase || 'scanning'); + var phaseEl = document.querySelector('[data-video-dash-phase]'); + if (phaseEl) phaseEl.textContent = phase.charAt(0).toUpperCase() + phase.slice(1); + var bar = document.querySelector('[data-video-dash-bar]'); + if (bar) bar.style.width = (s.percent != null ? s.percent : 100) + '%'; + var detail = document.querySelector('[data-video-dash-detail]'); + if (detail) { + detail.textContent = (s.movies || 0) + ' movies, ' + (s.shows || 0) + ' shows' + + (s.percent != null ? ' · ' + s.percent + '%' : ''); + } + var btns = dashButtons(); + for (var i = 0; i < btns.length; i++) btns[i].disabled = true; + } + + function onDashScanDone() { + var prog = document.querySelector('[data-video-dash-progress]'); + if (prog) prog.classList.add('hidden'); + var btns = dashButtons(); + for (var i = 0; i < btns.length; i++) btns[i].disabled = false; + loadStats(); + } + document.addEventListener('soulsync:video-page-shown', onPageShown); - // Dashboard scan buttons (data-video-scan-mode) are wired by video-scan.js; - // refresh the live counts whenever any scan finishes. - document.addEventListener('soulsync:video-scan-done', function () { loadStats(); }); + document.addEventListener('soulsync:video-scan-progress', onDashScanProgress); + document.addEventListener('soulsync:video-scan-done', onDashScanDone); })();