aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-07 21:19:11 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-07 21:19:11 +0200
commitd3bc50cca1c4dfe143c29a522b8cd57eb69ab92e (patch)
treeb953daa0406bdc6d38f991e5e95535e0c61c8bfc /packages/meshbay-hub/src/meshbay_hub/static
parentade41b05cce4a555197116568664220c5b3be9fa (diff)
downloadmeshbay-d3bc50cca1c4dfe143c29a522b8cd57eb69ab92e.tar.gz
fix(hub): keep "add a directory" when one node check is missed
A node busy indexing could miss the single 3 s check after a root was added, and the button stayed hidden until a reload. Ask up to four times before deciding there is no node on this machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/group-settings.js51
1 files changed, 38 insertions, 13 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
index 3ffa524..1a367be 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
@@ -14,6 +14,36 @@ import { inviteLinkHere, nodePkForLink } from './invite-link.js';
// ALLOWED_PREF_KEYS must list it, or every toggle snaps back.
export const INVITE_EMAIL_PREF = 'invite_email';
+// How many times the settings page asks the node on this machine before it
+// decides there is none. One ask is a 3 s `node:detect`, and a node busy
+// indexing a large root can miss it: a single miss used to hide "Add a
+// directory" until the page was reloaded. Found live, by a tester adding a
+// sixth directory while the others were still indexing.
+const NODE_CHECK_ATTEMPTS = 4;
+const NODE_CHECK_DELAY_MS = 2000;
+
+/**
+ * What the node on this machine says about `groupId`: `{ group }`, with
+ * `group` null when that node does not host it, or null when no node answers.
+ * A miss is asked again; a machine with no node set up at all is not.
+ */
+async function readLocalNode(node, groupId, attempts = NODE_CHECK_ATTEMPTS,
+ delayMs = NODE_CHECK_DELAY_MS) {
+ for (let i = 0; i < attempts; i++) {
+ if (i) await new Promise(r => setTimeout(r, delayMs));
+ try {
+ const detect = await node.detect();
+ if (!detect.detected) {
+ if (!detect.configured) return null;
+ continue;
+ }
+ const data = await node.op('groups');
+ return { group: (data.groups || []).find(g => g.id === groupId) || null };
+ } catch { /* busy, or mid-reload: ask again */ }
+ }
+ return null;
+}
+
// ── Shared Directories Table ────────────────────────────────────────────
/**
@@ -438,19 +468,14 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef,
const loadNodeInfo = useCallback(async () => {
if (!platform.node.available) return;
- try {
- const detect = await platform.node.detect();
- if (!detect.detected) { setNodeDetected(false); return; }
- setNodeDetected(true);
- const data = await platform.node.op('groups');
- const groups = data.groups || [];
- const ng = groups.find(g => g.id === groupId);
- setNodeHostsGroup(Boolean(ng));
- if (ng) {
- setNodeRoots(ng.roots || []);
- setNodeGroupName(ng.name || '');
- }
- } catch { setNodeDetected(false); }
+ const found = await readLocalNode(platform.node, groupId);
+ if (!found) { setNodeDetected(false); return; }
+ setNodeDetected(true);
+ setNodeHostsGroup(Boolean(found.group));
+ if (found.group) {
+ setNodeRoots(found.group.roots || []);
+ setNodeGroupName(found.group.name || '');
+ }
}, [groupId]);
useEffect(() => { loadNodeInfo(); }, [loadNodeInfo]);