diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-27 22:21:07 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-27 22:21:07 +0200 |
| commit | c7899e2218af26f3bab6a157c70acf5eb7871da6 (patch) | |
| tree | 5ed08cfbf26cdd8d9dbf6ce1159fc259d611df2d /packages/meshbay-hub/src/meshbay_hub | |
| parent | 7422a777297347dc83e6c5b2e89c1a6fa99a36b0 (diff) | |
| download | meshbay-c7899e2218af26f3bab6a157c70acf5eb7871da6.tar.gz | |
fix(hub): the sidebar's Node section follows the node link
Reported on a real install: after the first click on Create group, the Node
section (Node, Create group) disappeared from the sidebar until a reload,
although the group was created and the node ran.
hasNodeKey was read once per session change and never again, so a node the
wizard linked stayed out of the sidebar; and that read swallowed its errors,
so a session blip (a refused renewal, then the desktop app's silent device
sign-in) followed by one failed request hid the section for good. The wizard
now tells the app when it has linked or started a node, the app asks again
then and after a group is created, and a failed read is retried -- never
applied to a session that has changed meanwhile.
The wizard also starts the node on its own for a node in waiting_for_hub.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/app.js | 33 | ||||
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/create-group-page.js | 10 |
2 files changed, 35 insertions, 8 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js index 6b20a63..3101be7 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js @@ -924,8 +924,31 @@ function App() { .catch(() => {}); }, [user, notifDisabled]); + // Whether this account has a node linked, which is what shows the sidebar's + // Node section. Asked again whenever a node may just have been linked (the + // Create Group wizard), not only when the session changes -- the section + // stayed hidden until a reload after the first group -- and retried rather + // than left false by one failed request after a session blip. + const nodeKeyAskedForRef = useRef(null); + const refreshNodeKey = useCallback(() => { + nodeKeyAskedForRef.current = user; + if (!user || !platform.capabilities.nodeAdmin) return; + // A late answer, or a retry, must not land on a session that has changed. + const current = () => nodeKeyAskedForRef.current === user; + const ask = (attempt) => hubFetch(`/v1/users/${user.username}/pubkeys`, { token: user.token }) + .then(data => { if (current()) setHasNodeKey(Boolean(data.pk_node_ed25519)); }) + .catch(() => { + if (attempt < 3 && current()) setTimeout(() => ask(attempt + 1), 2000 * attempt); + }); + ask(1); + }, [user]); + useEffect(() => { - if (!user) { setGroups([]); setNotifications([]); setUnreadCount(0); setHasNodeKey(false); return; } + if (!user) { + nodeKeyAskedForRef.current = null; + setGroups([]); setNotifications([]); setUnreadCount(0); setHasNodeKey(false); + return; + } hubFetch('/v1/groups/mine', { token: user.token }) .then(data => setGroups(data.groups || [])) .catch(() => setGroups([])); @@ -935,11 +958,7 @@ function App() { if (prefs.notifications_disabled === 'true') setNotifDisabled(true); }) .catch(() => {}); - if (platform.capabilities.nodeAdmin) { - hubFetch(`/v1/users/${user.username}/pubkeys`, { token: user.token }) - .then(data => setHasNodeKey(Boolean(data.pk_node_ed25519))) - .catch(() => {}); - } + refreshNodeKey(); fetchNotifications(); }, [user]); @@ -1176,10 +1195,12 @@ function App() { } else if (route === '/create-group') { page = html`<${LazyCreateGroupPage} token=${user.token} username=${user.username} allowPublicGroups=${allowPublicGroups} + onNodeLinked=${refreshNodeKey} onCreated=${() => { hubFetch('/v1/groups/mine', { token: user.token }) .then(data => setGroups(data.groups || [])) .catch(() => {}); + refreshNodeKey(); }} />`; } else if (route === '/node' && platform.capabilities.nodeAdmin && hasNodeKey) { page = html`<${LazyNodePage} groups=${groups} token=${user.token} username=${user.username} />`; diff --git a/packages/meshbay-hub/src/meshbay_hub/static/create-group-page.js b/packages/meshbay-hub/src/meshbay_hub/static/create-group-page.js index 85fe53c..7556010 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/create-group-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/create-group-page.js @@ -124,7 +124,7 @@ function CreateGroupFormSimple({ token, onCreated, allowPublicGroups = true }) { `; } -function CreateGroupWizard({ token, username, onCreated, allowPublicGroups = true }) { +function CreateGroupWizard({ token, username, onCreated, onNodeLinked, allowPublicGroups = true }) { const [step, setStep] = useState(0); const [nodeStatus, setNodeStatus] = useState(null); const [nodeStarting, setNodeStarting] = useState(false); @@ -151,7 +151,10 @@ function CreateGroupWizard({ token, username, onCreated, allowPublicGroups = tru await hubFetch('/v1/users/me/node_key', { method: 'PUT', token, body: { pk_node_ed25519: pk }, }); - }, [token]); + // The sidebar's Node section depends on this link; it only re-read it at + // sign-in, so the first node set up here stayed out of it until a reload. + if (onNodeLinked) onNodeLinked(); + }, [token, onNodeLinked]); const detectNode = useCallback(async () => { setNodeStatus(null); @@ -177,6 +180,8 @@ function CreateGroupWizard({ token, username, onCreated, allowPublicGroups = tru setError(''); try { const result = await platform.node.start({ hubUrl: HUB, username, token }); + // node.start links the key from the main process, out of this page's sight. + if (onNodeLinked) onNodeLinked(); setNodeStatus({ detected: true, ...result }); setNodeStarting(false); setStep(1); @@ -337,6 +342,7 @@ function CreateGroupWizard({ token, username, onCreated, allowPublicGroups = tru && !provisionAttempted.current && (nodeStatus.status === 'waiting_for_account' || nodeStatus.status === 'waiting_for_node_key' + || nodeStatus.status === 'waiting_for_hub' || nodeStatus.status === 'starting')) { provisionAttempted.current = true; startNode(); |