aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-client
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-20 08:56:23 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-20 08:56:23 +0200
commitc8af746c846b5dbc792f7e4f0d806647d513cc5c (patch)
tree56c54ec5c703ec042589697b22b53e42451a61e4 /packages/meshbay-client
parent90c3c6a01f46c9b29c5d92702d7383f32e8951d7 (diff)
downloadmeshbay-c8af746c846b5dbc792f7e4f0d806647d513cc5c.tar.gz
feat(node): full Node admin panel — CLI parity, hot-reload, group lifecycle
Node admin panel (NodePage) now covers every CLI operation over MNP: group attach/detach, roster, member unpin, GEK rotate, denylist, reload. Daemon hot-loads new groups and tears down removed ones on config reload instead of requiring a full restart. Group attach/detach via MNP or local API triggers an automatic reload so the group is live immediately. Fixed GroupPage hang on first visit to a newly created group: the JWT issued at login didn't include the new group, the node rejected with not_a_member, and the token-refresh path returned without re-triggering the connect effect (Boolean(token) didn't change). Now bumps retryKey after a successful refresh so the effect re-runs with the fresh token. NodePage marks groups hosted by the node but absent from the hub with a "not on hub" badge so stale groups are visible and easy to remove. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-client')
-rw-r--r--packages/meshbay-client/src/main.js9
-rw-r--r--packages/meshbay-client/src/preload.js6
2 files changed, 15 insertions, 0 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js
index 0ed06d9..e7e7b15 100644
--- a/packages/meshbay-client/src/main.js
+++ b/packages/meshbay-client/src/main.js
@@ -559,6 +559,15 @@ function registerBridge() {
return true;
});
+ ipcMain.handle('root:choose', async () => {
+ const result = await dialog.showOpenDialog(mainWindow, {
+ properties: ['openDirectory', 'createDirectory'],
+ });
+ if (result.canceled || !result.filePaths.length) return null;
+ const chosen = result.filePaths[0];
+ return { path: chosen, name: path.basename(chosen) };
+ });
+
ipcMain.handle('save:begin', async (_e, suggestedName, opts) => {
const wanted = path.basename(String(suggestedName || 'download'));
const chosen = chosenDownloadDir();
diff --git a/packages/meshbay-client/src/preload.js b/packages/meshbay-client/src/preload.js
index 3804ad3..e3af68f 100644
--- a/packages/meshbay-client/src/preload.js
+++ b/packages/meshbay-client/src/preload.js
@@ -74,6 +74,12 @@ contextBridge.exposeInMainWorld('meshbay', {
forget: () => ipcRenderer.invoke('folder:forget'),
},
+ // Pick a directory to share as a group root. Returns { path, name } — the
+ // path is forwarded over MNP to the node, which is the local machine for D5.
+ rootPicker: {
+ choose: () => ipcRenderer.invoke('root:choose'),
+ },
+
// A sink that writes to disk as chunks arrive, never a buffer handed over at
// the end. `auto` uses the remembered folder without a dialog, which is what
// "save automatically" means; without one, or when the person asked to be