diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-22 16:40:54 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-22 16:40:54 +0200 |
| commit | 9c136a0e37add42f5d0c8675a797969cfe690de0 (patch) | |
| tree | d5dfd3a7e2289a769dc987f086eec3f475054f85 /packages/meshbay-hub | |
| parent | 2dbd70484e65ae57e18c323381136077cd00adad (diff) | |
| download | meshbay-9c136a0e37add42f5d0c8675a797969cfe690de0.tar.gz | |
fix: first-run wizard reliability and node startup performance
Node daemon no longer blocks startup on slow directory scans — initial
indexing runs in the background so the node reaches "running" immediately
after transports are up. Fixes the wizard failing to detect the node when
large USB/NAS roots take minutes to scan.
Also: wizard key-linking deadlock resolved (main.js links during poll),
invite form stays in DOM during reconnects (disabled instead of destroyed),
pairing code bridges to renderer, and firewall docs for LAN casting added.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/app.js | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js index 595674d..5c2bada 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js @@ -1201,8 +1201,7 @@ function CreateGroupWizard({ token, username, onCreated }) { setNodeStarting(true); setError(''); try { - const result = await platform.node.start({ hubUrl: HUB, username }); - await linkNodeKey(result.pk_node_ed25519); + const result = await platform.node.start({ hubUrl: HUB, username, token }); setNodeStatus({ detected: true, ...result }); setNodeStarting(false); setStep(1); @@ -1299,6 +1298,7 @@ function CreateGroupWizard({ token, username, onCreated }) { const pairResult = await platform.node.call('POST', '/api/operator/pair'); if (pairResult && pairResult.code) { await platform.node.setPairingCode(pairResult.code); + _pendingJoinCode = pairResult.code; } update('done'); @@ -2977,37 +2977,38 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, ${error && html`<div class="error-msg" style="margin-bottom:12px">${error}</div>`} ${/* Inviting needs the node: it is the node that wraps the group key and - issues the code, not the hub. Public groups admit anyone — no invite. */ + issues the code, not the hub. Public groups admit anyone — no invite. + The form stays in the DOM so a brief reconnect does not destroy the + input the user is typing into — controls are disabled instead. */ isAdmin && group?.join_policy !== 'open' && html` <div class="settings-section"> <h3 class="settings-heading">${t('members.invite_title')}</h3> - ${!connected && html` + ${!connected ? html` <p class="settings-hint">${t('group.offline_title')}</p> - `} - ${connected && !operatorPaired && html` + ` : !operatorPaired ? html` <p class="settings-hint"> ${isNodeAdmin ? t('members.invite_needs_pairing') : t('members.invite_ask_operator')} </p> - `} - ${connected && operatorPaired && html` - <form onSubmit=${doInvite}> - ${inviteCode && html` - <div class="success-msg" style="margin-bottom:8px"> - <p>${t('members.invite_code_ready', { user: inviteCode.username })}</p> - <p class="code-display">${inviteCode.code}</p> - <p>${t('members.invite_code_hint')}</p> - </div> - `} - <div class="form-row"> - <input type="text" placeholder="${t('members.username_placeholder')}" - value=${inviteUser} onInput=${e => setInviteUser(e.target.value)} required /> - <button class="admin-btn" type="submit" disabled=${inviting}> - ${inviting ? '...' : t('members.invite_btn')} - </button> + ` : ''} + <form onSubmit=${doInvite}> + ${inviteCode && html` + <div class="success-msg" style="margin-bottom:8px"> + <p>${t('members.invite_code_ready', { user: inviteCode.username })}</p> + <p class="code-display">${inviteCode.code}</p> + <p>${t('members.invite_code_hint')}</p> </div> - </form> - `} + `} + <div class="form-row"> + <input type="text" placeholder="${t('members.username_placeholder')}" + value=${inviteUser} onInput=${e => setInviteUser(e.target.value)} + disabled=${!connected || !operatorPaired} required /> + <button class="admin-btn" type="submit" + disabled=${inviting || !connected || !operatorPaired}> + ${inviting ? '...' : t('members.invite_btn')} + </button> + </div> + </form> </div> `} |