aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/transport.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-24 22:44:27 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-24 22:44:27 +0200
commitdf7eb105dda550989dccd3ba2bf22a50e919b19b (patch)
treeafc5de8f43d8fe188a5fdb41ffc504c211e07ccc /packages/meshbay-hub/src/meshbay_hub/static/transport.js
parent665fb2004e55b72ea483aa50fea81f6a6fd9c322 (diff)
downloadmeshbay-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/transport.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/transport.js20
1 files changed, 20 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
index 4f8e3b5..817db7a 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
@@ -109,6 +109,7 @@ class MeshBayTransport {
set onTmdbConfig(fn) { this._onTmdbConfig = fn; }
set onTmdbEnabled(fn) { this._onTmdbEnabled = fn; }
set onVideoRoot(fn) { this._onVideoRoot = fn; }
+ set onAudioRoot(fn) { this._onAudioRoot = fn; }
set onMusicbrainzConfig(fn) { this._onMusicbrainzConfig = fn; }
set onMusicbrainzEnabled(fn) { this._onMusicbrainzEnabled = fn; }
set onIndexProgress(fn) { this._onIndexProgress = fn; }
@@ -606,6 +607,19 @@ class MeshBayTransport {
}
/**
+ * Same shape as setVideoRoot above — the Music app's own entry point.
+ */
+ async setAudioRoot(path, signFn) {
+ const clean = (path || '').replace(/^\/+|\/+$/g, '');
+ const msg = await this._sendAndWait({ type: 'audio_root', v: '0.10', path: clean });
+ if (msg.type === 'error') throw new Error(msg.detail);
+ if (msg.type === 'admin_challenge') {
+ return this._authorizeAdminOp(msg, 'audio_root', clean, signFn);
+ }
+ return msg;
+ }
+
+ /**
* MusicBrainz metadata for one track's path (Music app, docs/musicbay.md
* §4.3) — same shape as fetchMediaMeta, minus a season/episode concept:
* album-level (release), resolved from the track's own artist/album
@@ -1540,6 +1554,12 @@ class MeshBayTransport {
this._onVideoRoot(msg.path || '');
}
+ // Same shape: the operator changed which folder is the Music app's
+ // entry point for this group.
+ if (msg.type === 'audio_root_ack' && this._onAudioRoot) {
+ this._onAudioRoot(msg.path || '');
+ }
+
// Node-wide, like tmdb_config_ack above — no token equivalent to hide,
// only whether a contact string is configured (docs/musicbay.md §3.2).
if (msg.type === 'musicbrainz_config_ack' && this._onMusicbrainzConfig) {