diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/group-page.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/group-page.js | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js index aa6b29c..01ab4e0 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js @@ -11,6 +11,7 @@ import { import { visibleApps } from './apps.js'; import { FilePreview } from './files-app.js'; import { VideoPlayer } from './video-player.js'; +import { MusicPlayerBar } from './music-player.js'; import { GroupSettingsPanel } from './group-settings.js'; /** @@ -86,6 +87,18 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, // Which folder is the Videos app's entry point for this group — '' // (the default) means the whole group index. Set from Files, per-group. const [videoRoot, setVideoRoot] = useState(''); + // MusicBrainz on/off (per-group) + whether a contact string is configured + // (node-wide) — docs/musicbay.md §3.2, same shape as tmdbConfig above. + const [musicbrainzConfig, setMusicbrainzConfig] = useState(null); + // What music-app.js hands over when a track/album is clicked — owned here + // (not by music-app.js) so playback survives switching tabs, the same + // reasoning the video/preview modals are shell-owned. `nonce` makes + // "play this same album again from track 0" a distinct value every time, + // so MusicPlayerBar's queue-init effect always re-runs. + const [musicQueue, setMusicQueue] = useState(null); + const onPlayQueue = useCallback((tracks, startIndex) => { + setMusicQueue({ tracks, startIndex, nonce: Date.now() }); + }, []); // Paired ≠ operator account. `is_node_admin` says the hub account owning this // node is the one connecting; this says the node pinned *this browser's* key // as an operator key. Only the second one lets you sign an invite, and only @@ -214,6 +227,10 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, language: ack.tmdb_language || '', }); setVideoRoot(ack.video_root || ''); + setMusicbrainzConfig({ + enabled: ack.musicbrainz_enabled !== false, + contactConfigured: !!ack.musicbrainz_contact_configured, + }); // Changed while we are connected, by an operator who may be someone // else entirely. Without this the button stays until a reconnection, // and a button that is still there is a button people press. @@ -227,6 +244,10 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, transport.onTmdbConfig = (cfg) => setTmdbConfig((prev) => ({ ...(prev || {}), ...cfg })); transport.onTmdbEnabled = (enabled) => setTmdbConfig((prev) => ({ ...(prev || {}), enabled })); transport.onVideoRoot = (path) => setVideoRoot(path); + transport.onMusicbrainzConfig = (cfg) => + setMusicbrainzConfig((prev) => ({ ...(prev || {}), ...cfg })); + transport.onMusicbrainzEnabled = (enabled) => + setMusicbrainzConfig((prev) => ({ ...(prev || {}), enabled })); // The node's own scan (a root added while we were already connected, // or reconcile catching one back up) — never the entries, just // enough to animate the sidebar dot. Guaranteed a final push at the @@ -418,6 +439,7 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, onRefreshIndex: refreshIndex, onActivity: touchActivity, videoRoot, onVideoRoot: (path) => setVideoRoot(path), tmdbConfig, + musicbrainzConfig, onPlayQueue, }; return html` @@ -534,6 +556,9 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, tmdbConfig=${tmdbConfig} onTmdbConfig=${(cfg) => setTmdbConfig((prev) => ({ ...(prev || {}), ...cfg }))} onTmdbEnabled=${(enabled) => setTmdbConfig((prev) => ({ ...(prev || {}), enabled }))} + musicbrainzConfig=${musicbrainzConfig} + onMusicbrainzConfig=${(cfg) => setMusicbrainzConfig((prev) => ({ ...(prev || {}), ...cfg }))} + onMusicbrainzEnabled=${(enabled) => setMusicbrainzConfig((prev) => ({ ...(prev || {}), enabled }))} entries=${entries} nodeDirs=${nodeDirs} videoRoot=${videoRoot} onVideoRoot=${(path) => setVideoRoot(path)} @@ -566,6 +591,14 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, onClose=${() => setVideoEntry(null)} onDownload=${() => downloadFileForModal(videoEntry)} /> `} + ${/* Outside the tab-switched area on purpose (docs/musicbay.md §2.3): + once something has been played this session, the bar stays + mounted and keeps playing regardless of which tab is active — + switching to Chat or Files must not stop the music. Renders + nothing of its own until onPlayQueue has been called once. */ + musicQueue && html` + <${MusicPlayerBar} transportRef=${transportRef} gekRef=${gekRef} queue=${musicQueue} /> + `} </div> `; } |