From 0d86d84307daf5b488b9a2eb354dcc7930270e3a Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sun, 14 Jun 2026 00:17:00 -0700 Subject: [PATCH] video side: Settings shows the real music settings page (identically) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Video Settings was a 'coming soon' placeholder. Now it reuses the actual #settings-page, shown identically for now (no hiding of music-only bits yet) — the foundation for adding the Movies/TV library mapping next. - video-side.js: SHARED_PAGES maps video-settings -> the music 'settings' page; showPage sets body[data-video-page] and triggers the shared loadPageData loader (same init music navigation uses) instead of a video subpage. - CSS reveals #settings-page (and hides the video host) when data-side=video + data-video-page=video-settings; id selector outranks the blanket music-page hide. 81 tests green. --- tests/test_video_side_shell.py | 10 ++++++++++ webui/static/video/video-side.css | 10 ++++++++++ webui/static/video/video-side.js | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/tests/test_video_side_shell.py b/tests/test_video_side_shell.py index 842489ae..77c9f05b 100644 --- a/tests/test_video_side_shell.py +++ b/tests/test_video_side_shell.py @@ -184,6 +184,16 @@ def test_scan_module_referenced_and_isolated(): assert "/api/video/scan/request" in _SCAN_JS +def test_video_settings_reuses_real_music_settings_page(): + # The video Settings nav shows the actual #settings-page (identically, for + # now) via CSS + the shared loadPageData loader — not a video subpage. + assert "'video-settings': 'settings'" in _JS or '"video-settings": "settings"' in _JS + assert "loadPageData" in _JS + css = _CSS_PATH.read_text(encoding="utf-8") + assert 'data-video-page="video-settings"] #settings-page' in css + assert 'data-video-page="video-settings"] #video-page-host' in css + + def test_controller_is_isolated_iife_with_no_globals(): stripped = _JS.strip() # Wrapped in an IIFE → declares no module-level globals that could collide diff --git a/webui/static/video/video-side.css b/webui/static/video/video-side.css index e04b1ad3..b1d5fb50 100644 --- a/webui/static/video/video-side.css +++ b/webui/static/video/video-side.css @@ -108,6 +108,16 @@ body[data-side="video"] .status-section { display: none; } +/* ── Shared pages: show the REAL music page on the video side ───────────── */ +/* For now Settings is shown identically (no hiding of music-only bits yet). + The id selector + extra attribute outrank the blanket music-page hide rule. */ +body[data-side="video"][data-video-page="video-settings"] #settings-page { + display: block !important; +} +body[data-side="video"][data-video-page="video-settings"] #video-page-host { + display: none !important; +} + /* ── Dashboard header: match music, minus the sweep animation ──────────── */ /* The header reuses music's .dashboard-header markup/CSS for an identical look; we only mute the ambient sweep on the video side (equiv may return later, diff --git a/webui/static/video/video-side.js b/webui/static/video/video-side.js index 720973c9..4e5ddaf3 100644 --- a/webui/static/video/video-side.js +++ b/webui/static/video/video-side.js @@ -40,6 +40,11 @@ { id: 'video-help', label: 'Help & Docs', shared: true }, ]; + // "Shared" video pages reuse the REAL music page (shown identically on the + // video side for now) instead of a video subpage: video page id -> music + // page id. CSS reveals the music page; we trigger its loader once shown. + var SHARED_PAGES = { 'video-settings': 'settings' }; + function readSide() { try { return localStorage.getItem(SIDE_KEY) === 'video' ? 'video' : 'music'; @@ -88,6 +93,19 @@ // for this event instead of being called directly, keeping each isolated. function showPage(pageId) { var meta = pageMeta(pageId); + // Drives the CSS that reveals shared music pages (e.g. Settings) and + // hides the video host for them. + document.body.setAttribute('data-video-page', meta.id); + + var sharedMusicId = SHARED_PAGES[meta.id]; + if (sharedMusicId) { + // The real music page is shown by CSS; load its data the same way a + // music-side navigation would. (loadPageData is a shared global.) + if (typeof loadPageData === 'function') loadPageData(sharedMusicId); + document.dispatchEvent(new CustomEvent('soulsync:video-page-shown', { detail: meta.id })); + return; + } + var host = document.getElementById('video-page-host'); if (!host) return; var matched = null;