aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/group-page.js
diff options
context:
space:
mode:
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.js34
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}