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 | 34 |
1 files changed, 25 insertions, 9 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 466af53..1b2661c 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js @@ -1,5 +1,5 @@ import { - html, useState, useEffect, useCallback, useRef, + html, useState, useEffect, useCallback, useRef, useMemo, } from './vendor/htm-preact.js'; import { t } from './i18n.js'; import { Icon } from './icon.js'; @@ -88,9 +88,8 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, const [nodeRoots, setNodeRoots] = useState([]); const [isNodeAdmin, setIsNodeAdmin] = useState(false); - // Whether ordinary members may upload here. The node decides and enforces it; - // this only says whether to offer the controls. Defaults to true so a node - // that predates the setting behaves as it always did. + // DEPRECATED: memberUpload is now derived from per-root writable flags. + // Kept as state only for backward compat with nodes that still send it. const [memberUpload, setMemberUpload] = useState(true); // Which applications this group has enabled, from the node. Falls back to // every registered app when a node predates the setting (or hasn't answered @@ -348,6 +347,11 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, transport.onPhotoRoots = (roots) => setPhotoRoots(roots); transport.onMusicbrainzEnabled = (enabled) => setMusicbrainzConfig((prev) => ({ ...(prev || {}), enabled })); + transport.onRootsChanged = (msg) => { + if (msg.roots) { + setNodeRoots(msg.roots); + } + }; // 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 @@ -536,8 +540,10 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, }, [groupId, token, descDraft, onGroupUpdated]); // Asked in two places — the Files toolbar and the chat composer — so it is - // answered once. The operator is never locked out of their own node. - const mayUpload = memberUpload || isNodeAdmin; + // answered once. Per-root writable flags replace the old binary toggle; + // falls back to the legacy memberUpload for old nodes. + const hasWritableRoot = nodeRoots.some((r) => r.writable); + const mayUpload = hasWritableRoot || memberUpload || isNodeAdmin; // A single dispatcher so any app can open the right modal without owning // video/preview state itself — Files' table and Chat's attachments both @@ -566,9 +572,21 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, setPreviewEntry(entry); }, [entries, onPlayQueue, onStopMusic]); + const unavailRoots = useMemo(() => { + const s = new Set(); + for (const r of nodeRoots) if (!r.available) s.add(r.name); + return s; + }, [nodeRoots]); + const availableEntries = useMemo( + () => entries.filter((e) => { + const root = (e.path || '').split('/')[0]; + return !root || !unavailRoots.has(root); + }), [entries, unavailRoots]); + const commonProps = { groupId, transportRef, gekRef, status, username, - entries, nodeDirs, nodeRoots, setEntries, setNodeDirs, setNodeRoots, applyIndex, + entries, availableEntries, nodeDirs, nodeRoots, + setEntries, setNodeDirs, setNodeRoots, applyIndex, isNodeAdmin, operatorPaired, mayUpload, userId, setError, onPreview, onRefreshIndex: refreshIndex, onActivity: touchActivity, videoRoot, onVideoRoot: (path) => setVideoRoot(path), @@ -699,8 +717,6 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, transportRef=${transportRef} gekRef=${gekRef} isNodeAdmin=${isNodeAdmin} userId=${userId} operatorPaired=${operatorPaired} connected=${status === 'connected'} - memberUpload=${memberUpload} - onMemberUpload=${(allowed) => setMemberUpload(allowed)} enabledApps=${enabledApps} onEnabledApps=${(keys) => setEnabledApps(keys)} scanSettings=${scanSettings} |