diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-11 14:17:55 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-11 17:51:51 +0200 |
| commit | d4935aa2a28fcbab8c3556e3532e53667092701e (patch) | |
| tree | 2898874e80493bb7067401b4462b51edba267e69 /packages/meshbay-hub/src/meshbay_hub/static | |
| parent | bca6fc3f0884fcdb0455b502ee4495b04945baee (diff) | |
| download | meshbay-d4935aa2a28fcbab8c3556e3532e53667092701e.tar.gz | |
feat: gate the create-group wizard on whether a node is bundled
MeshBay Light has no bundled meshbay-node.exe, so the create-group wizard
(which assumes it can start a local node) needs its own signal, not just
platform.node.available. main.js exposes it over IPC (node:bundled) by
checking the packaged resources directory rather than trusting a build-time
constant; preload.js and platform.js carry it through the usual
contextBridge/wrapper path.
winCanElevateServiceMode() replaces the two prior 'app.isPackaged' checks
for whether the app can offer service-mode elevation -- Light is packaged
but has no service-mode.ps1 to elevate into, so packaged alone was already
the wrong test even before this target existed.
create-group-page.js gates the wizard step that starts a node on the new
capability instead of hiding the whole feature; node-page.js's comment fix
is unrelated cosmetic drift caught in the same pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static')
3 files changed, 44 insertions, 11 deletions
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 c3b542f..f81247d 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 @@ -8,7 +8,32 @@ import { Icon } from './icon.js'; import { SharedDirectoriesTable } from './group-settings.js'; export function CreateGroupPage(props) { - if (platform.node.available) return html`<${CreateGroupWizard} ...${props} />`; + // The wizard assumes a LOCAL node it can link right there (waiting_for_ + // account / waiting_for_node_key, below) -- exactly what a "Light" desktop + // build (electron-builder.light.yml, no bundled node-runtime) does not + // have. Without this check that polling loop hangs forever, the same + // "Detecting local node…" failure mode already found and fixed once for + // Full (see the Windows-port history around linkNodeKeyAndAwaitRunning). + // `bundled` starts null (unknown) and resolves once via IPC; a plain + // browser has no bridge at all and skips straight to false, the same + // outcome `platform.node.available` already gave it. Falling back to + // CreateGroupFormSimple is not a lesser feature for Light -- it is the + // exact form a browser-only member already uses to create a group with no + // node of their own; hosting it can be linked from a device that has one. + const [bundled, setBundled] = useState(null); + useEffect(() => { + if (!platform.node.available) { setBundled(false); return undefined; } + let cancelled = false; + platform.node.bundled().then((b) => { if (!cancelled) setBundled(b); }); + return () => { cancelled = true; }; + }, []); + + if (platform.node.available && bundled === null) { + return html`<div class="page-message"> + <span class="spinner"></span>${' '}${t('node.service_checking')} + </div>`; + } + if (platform.node.available && bundled) return html`<${CreateGroupWizard} ...${props} />`; return html`<${CreateGroupFormSimple} ...${props} />`; } diff --git a/packages/meshbay-hub/src/meshbay_hub/static/node-page.js b/packages/meshbay-hub/src/meshbay_hub/static/node-page.js index c1d57f9..6dcaa58 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/node-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/node-page.js @@ -55,11 +55,10 @@ function NodeServicePanel({ onChanged }) { return i.autostart ? 'signin' : 'off'; }; - // Switching mode itself — the installer's own choice is effectively one-shot - // (it skips the question once the firewall rules exist for any reason, and - // per-user mode sets those up on its own with no Scheduled Task), so this is - // the only way back in if service mode was declined, or out if it is no - // longer wanted. One elevation, task + firewall together, same script. + // Switching mode itself — the installer's own radio page only runs once, + // at install time, so this is the only way back in if service mode was + // declined there, or out if it is no longer wanted. One elevation, task + + // firewall together, same script the installer runs. // // The two mechanisms are mutually exclusive by construction here: never // both installed at once, which would start the daemon twice (once at diff --git a/packages/meshbay-hub/src/meshbay_hub/static/platform.js b/packages/meshbay-hub/src/meshbay_hub/static/platform.js index e93ffb3..43b8ba8 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/platform.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/platform.js @@ -231,6 +231,16 @@ export const node = { async installed() { return bridge && bridge.node ? bridge.node.installed() : { installed: false }; }, + /** + * Does THIS build ship its own node (Full) or not (Light)? Distinct from + * `installed`, which also counts one merely found on PATH. A browser has + * no bridge at all, so it resolves false the same as `available` does -- + * create-group-page.js already falls back to the node-free form for that + * case, and Light should take the same fallback. + */ + async bundled() { + return bridge && bridge.node ? bridge.node.bundled() : false; + }, async start(opts) { if (!bridge || !bridge.node) throw new Error('Node bridge not available'); return bridge.node.start(opts); @@ -288,11 +298,10 @@ export const node = { }, /** * Windows only: switch INTO or OUT OF service mode after install — the - * installer's own choice is effectively one-shot (build/installer.nsh skips - * it once the firewall rules exist for any reason, and per-user mode sets - * those up on its own with no Scheduled Task), so this is the only way back - * in if it was declined, or out if it was chosen and no longer wanted. One - * elevation, task + firewall together — same script the installer runs. + * installer's own radio page (build/installer.nsh) only runs once, at + * install time, so this is the only way back in if a different mode was + * chosen there and is no longer wanted. One elevation, task + firewall + * together — same script the installer runs. */ serviceMode: { available: Boolean(bridge && bridge.node && bridge.node.serviceMode), |