diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-24 22:44:27 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-24 22:44:27 +0200 |
| commit | df7eb105dda550989dccd3ba2bf22a50e919b19b (patch) | |
| tree | afc5de8f43d8fe188a5fdb41ffc504c211e07ccc /packages/meshbay-hub/src/meshbay_hub/static/music-app.js | |
| parent | 665fb2004e55b72ea483aa50fea81f6a6fd9c322 (diff) | |
| download | meshbay-df7eb105dda550989dccd3ba2bf22a50e919b19b.tar.gz | |
feat(hub): audio_root wiring, mutually-exclusive players, Settings rework
Five related pieces of polish against the Music app and Settings, all
from the same conversation:
- Music app now requires audio_root, same as Videos requires video_root:
an empty-state message until one is set, and grouping filtered to only
what's under it (underAudioRoot, mirroring video-app.js's
underVideoRoot). Wires the new audio_root/audio_root_ack pair through
transport.js and group-page.js state the same way video_root already
flows.
- Starting one player now stops the other — opening a film closes the
music queue, starting a track closes the video modal. Both used to run
at once, found live.
- Group Settings reworked: every section but a bare form (invite,
pair-operator, approve-device) is now collapsible (CollapsibleSection);
the uploads on/off button is a real toggle switch (ToggleSwitch,
reused for TMDB/MusicBrainz's enabled switches too, each now with an
icon + status badge in its header instead of a plain checkbox row);
and shared directories, the Videos root picker, and the new Music root
picker are merged into one "Directories" section (RootFolderRow) instead
of three separate ones scattered down the page — the root pickers only
show once their app is actually enabled.
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/music-app.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/music-app.js | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js index cb14fb4..298e259 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js @@ -46,12 +46,24 @@ function foldKey(s) { .replace(/\s*&\s*/g, ' and ').replace(/\s+/g, ' ').trim(); } -function groupMusicEntries(entries) { +// Same shape as video-app.js's underVideoRoot: an unset root means "show +// nothing" (docs/musicbay.md's amended §2.1 — the node itself runs no +// tag/cover enrichment for this group before a root is chosen either, +// daemon.py's _enrich_new_audio_entries), not "the whole shared tree" — +// falling back to that would just show files nothing has enriched. +function underAudioRoot(entry, audioRoot) { + if (!audioRoot) return false; + const p = entry.path || ''; + return p === audioRoot || p.startsWith(audioRoot + '/'); +} + +function groupMusicEntries(entries, audioRoot) { const tracks = []; // no artist at all, even after the folder fallback -- rare, but real const byArtistKey = new Map(); // foldKey(artist) -> { artist, albumsByKey: Map, loose: [] } for (const e of entries) { if (e.type !== 'audio') continue; + if (!underAudioRoot(e, audioRoot)) continue; const artistRaw = (e.artist || '').trim(); if (!artistRaw) { tracks.push(e); continue; } const artistKey = foldKey(artistRaw); @@ -381,7 +393,7 @@ function FlatList({ tracks, artists, onPlayQueue }) { // -- shell -------------------------------------------------------------------- function MusicApp({ - groupId, transportRef, gekRef, status, entries, musicbrainzConfig, onPlayQueue, + groupId, transportRef, gekRef, status, entries, audioRoot, musicbrainzConfig, onPlayQueue, }) { const [mode, setMode] = useState(loadViewMode); const [filter, setFilter] = useState(''); @@ -392,7 +404,8 @@ function MusicApp({ const setModeAndSave = (m) => { setMode(m); saveViewMode(m); }; - const { tracks, artists, albums } = useMemo(() => groupMusicEntries(entries), [entries]); + const { tracks, artists, albums } = useMemo( + () => groupMusicEntries(entries, audioRoot), [entries, audioRoot]); const needle = filter.trim().toLowerCase(); const filteredArtists = useMemo(() => { @@ -418,7 +431,10 @@ function MusicApp({ ${status === 'offline' && html` <p class="page-message">${t('group.offline_title')} ${t('group.offline_hint')}</p> `} - ${status === 'connected' && html` + ${status === 'connected' && !audioRoot && html` + <p class="page-message">${t('music.no_root_configured')}</p> + `} + ${status === 'connected' && audioRoot && html` <div class="video-toolbar"> <button class="tb-btn ${mode === 'grid' ? 'active' : ''}" onClick=${() => setModeAndSave('grid')}> |