aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-07 10:35:09 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-07 10:35:09 +0200
commit2c0903c648e24b4e2adf20492398e8b67d033b49 (patch)
tree0435f298010f0f946362f28baebbe88337ca8768 /packages/meshbay-hub/src/meshbay_hub/static/music-app.js
parent0ed078c92cabab1dab0f70f321562032ea549ce6 (diff)
parenteeda274d751c537f4ecef3087994a16a9517478f (diff)
downloadmeshbay-2c0903c648e24b4e2adf20492398e8b67d033b49.tar.gz
Merge branch 'refactor/groups-phase1'
Groups refactor, phases 1-3. The root model replaces the old `upload` flag and group-wide `member_upload` with per-root `writable`/`removable`/`ejected`, carried by a `RootSet` that both front doors — the loopback API and signed MNP — reach through the same `ops` functions. MNP goes to 1.1, additively: the roots table now rides on `index_delta`, so a root added, removed, ejected or plugged reaches every connected client instead of only whoever reloaded. The group UI becomes a plugin architecture: an application is a registry entry in `apps.js` plus its own files, with directories stored generically by `ops.set_app_directories` under whatever the app is called. A reference application, hidden behind `?dev=1`, is what makes that claim testable — adding it is what found the two places still naming apps by hand. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011pvMdvLBG92jyhvD5pD6us
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.js23
1 files changed, 14 insertions, 9 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 616f169..f622b5d 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
@@ -52,19 +52,20 @@ function foldKey(s) {
// 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;
+function underAudioRoot(entry, directories) {
+ const dirs = directories || [];
+ if (!dirs.length) return false;
const p = entry.path || '';
- return p === audioRoot || p.startsWith(audioRoot + '/');
+ return dirs.some((d) => p === d || p.startsWith(d + '/'));
}
-function groupMusicEntries(entries, audioRoot) {
+function groupMusicEntries(entries, musicDirectories) {
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;
+ if (!underAudioRoot(e, musicDirectories)) continue;
const artistRaw = (e.artist || '').trim();
if (!artistRaw) { tracks.push(e); continue; }
const artistKey = foldKey(artistRaw);
@@ -453,7 +454,8 @@ function FlatList({ tracks, artists, onPlayQueue }) {
// -- shell --------------------------------------------------------------------
function MusicApp({
- groupId, transportRef, gekRef, status, entries, audioRoot, musicbrainzConfig, onPlayQueue,
+ groupId, transportRef, gekRef, status, entries, availableEntries,
+ musicDirectories, musicbrainzConfig, onPlayQueue,
hideFilter,
}) {
const [mode, setMode] = useState(loadViewMode);
@@ -465,8 +467,11 @@ function MusicApp({
const setModeAndSave = (m) => { setMode(m); saveViewMode(m); };
+ const musicEntries = availableEntries || entries;
+ const configured = (musicDirectories || []).length > 0;
const { tracks, artists, albums } = useMemo(
- () => groupMusicEntries(entries, audioRoot), [entries, audioRoot]);
+ () => groupMusicEntries(musicEntries, musicDirectories),
+ [musicEntries, musicDirectories]);
const needle = filter.trim().toLowerCase();
const filteredArtists = useMemo(() => {
@@ -492,10 +497,10 @@ function MusicApp({
${status === 'offline' && html`
<p class="page-message">${t('group.offline_title')} ${t('group.offline_hint')}</p>
`}
- ${status === 'connected' && !audioRoot && html`
+ ${status === 'connected' && !configured && html`
<p class="page-message">${t('music.no_root_configured')}</p>
`}
- ${status === 'connected' && audioRoot && html`
+ ${status === 'connected' && configured && html`
<div class="video-toolbar">
<button class="tb-btn ${mode === 'grid' ? 'active' : ''}"
onClick=${() => setModeAndSave('grid')}>