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, 26 insertions, 8 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 1b2661c..dfde172 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js @@ -88,8 +88,10 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, const [nodeRoots, setNodeRoots] = useState([]); const [isNodeAdmin, setIsNodeAdmin] = useState(false); - // DEPRECATED: memberUpload is now derived from per-root writable flags. - // Kept as state only for backward compat with nodes that still send it. + // Legacy: the group-wide upload switch a node speaking MNP 1.0 sends on its + // handshake ack. Per-root `writable` replaced it, and this is read only when + // the roots carry no flags at all — see `attachRoot` below. Defaults to true + // so such a node behaves as it always did. 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 @@ -539,11 +541,26 @@ 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. 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; + // Where an attachment goes, answered once for the whole page. + // + // Files does not use this — it uploads into the root being browsed, which is + // the only unambiguous answer once a group can have several writable roots. + // Chat has no folder to browse, so it needs one picked for it, and this is + // the same rule the node applies when a client names no root at all. It + // becomes an operator-chosen directory in phase 2 (refactor-groups.md §1.7). + // + // `memberUpload` is the fallback for a node still speaking MNP 1.0, whose + // roots carry no `writable` at all: there, the single upload root is the one + // the node marked, and the ack's computed flag is all we get. + const writableRoots = useMemo( + () => nodeRoots.filter((r) => r.writable && r.available !== false), + [nodeRoots]); + const legacyNode = nodeRoots.length > 0 + && nodeRoots.every((r) => r.writable === undefined); + const attachRoot = writableRoots.length ? writableRoots[0].name + : (legacyNode && memberUpload + ? (nodeRoots.find((r) => r.upload) || nodeRoots[0]).name + : ''); // A single dispatcher so any app can open the right modal without owning // video/preview state itself — Files' table and Chat's attachments both @@ -587,7 +604,7 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, groupId, transportRef, gekRef, status, username, entries, availableEntries, nodeDirs, nodeRoots, setEntries, setNodeDirs, setNodeRoots, applyIndex, - isNodeAdmin, operatorPaired, mayUpload, userId, setError, onPreview, + isNodeAdmin, operatorPaired, attachRoot, userId, setError, onPreview, onRefreshIndex: refreshIndex, onActivity: touchActivity, videoRoot, onVideoRoot: (path) => setVideoRoot(path), audioRoot, onAudioRoot: (path) => setAudioRoot(path), @@ -717,6 +734,7 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, transportRef=${transportRef} gekRef=${gekRef} isNodeAdmin=${isNodeAdmin} userId=${userId} operatorPaired=${operatorPaired} connected=${status === 'connected'} + mnpRoots=${nodeRoots} enabledApps=${enabledApps} onEnabledApps=${(keys) => setEnabledApps(keys)} scanSettings=${scanSettings} |