diff options
Diffstat (limited to 'packages/meshbay-client')
| -rw-r--r-- | packages/meshbay-client/src/main.js | 99 | ||||
| -rw-r--r-- | packages/meshbay-client/src/tray-icon.png | bin | 415 -> 504 bytes | |||
| -rw-r--r-- | packages/meshbay-client/src/tray-icon@2x.png | bin | 755 -> 967 bytes |
3 files changed, 77 insertions, 22 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js index 71b56be..273d151 100644 --- a/packages/meshbay-client/src/main.js +++ b/packages/meshbay-client/src/main.js @@ -339,6 +339,19 @@ let mainWindow = null; // files are the interface's, the main process has no i18n, and a second string // table is how two of them start disagreeing. let tray = null; +let trayLabels = null; +let trayTimer = null; +let nodeService = null; // assigned by registerBridge() + +const TRAY_FALLBACK = { + show: 'Show MeshBay', quit: 'Quit', + start_node: 'Start the node', stop_node: 'Stop the node', +}; + +// libappindicator offers no "menu is about to open" event, so a menu built once +// would show a stale Start/Stop for as long as the app runs. `systemctl --user +// show` is a few milliseconds and this only ticks while an indicator exists. +const TRAY_POLL_MS = 5000; function showFromTray() { if (!mainWindow) return; @@ -347,18 +360,51 @@ function showFromTray() { mainWindow.focus(); } +async function buildTrayMenu() { + const text = { ...TRAY_FALLBACK, ...(trayLabels || {}) }; + const items = [{ label: text.show, click: showFromTray }]; + + // Only when there is a daemon to act on: not installed means no entry at all, + // rather than a control that reports failure when used. + let status = null; + try { + status = nodeService ? await nodeService.status() : null; + } catch { + status = null; // unreadable state is the same as no control + } + if (status && status.supported && status.installed) { + const running = status.activeState === 'active'; + items.push({ type: 'separator' }); + items.push({ + label: running ? text.stop_node : text.start_node, + click: async () => { + try { + // `restart` starts a stopped unit, which is what systemd's restart + // means; there is no separate start verb to call. + if (running) await nodeService.stop(); + else await nodeService.restart(); + } catch (err) { + console.error('[MeshBay] tray: node action failed', err); + } + refreshTrayMenu(); // reflect the new state without waiting a tick + }, + }); + } + + items.push({ type: 'separator' }, + { label: text.quit, click: () => app.quit() }); + return Menu.buildFromTemplate(items); +} + +async function refreshTrayMenu() { + if (!tray) return; + tray.setContextMenu(await buildTrayMenu()); +} + function ensureTray(labels) { - const text = { - show: (labels && labels.show) || 'Show MeshBay', - quit: (labels && labels.quit) || 'Quit', - }; + if (labels) trayLabels = labels; // the person may have changed language if (tray) { - // Relabel in place: the person may have changed language since it was made. - tray.setContextMenu(Menu.buildFromTemplate([ - { label: text.show, click: showFromTray }, - { type: 'separator' }, - { label: text.quit, click: () => app.quit() }, - ])); + refreshTrayMenu(); return tray; } // In src/, not build/: electron-builder packages only `src/**` and `ui/**` @@ -366,17 +412,13 @@ function ensureTray(labels) { // missing from every installed one. tray = new Tray(path.join(__dirname, 'tray-icon.png')); tray.setToolTip('MeshBay'); - tray.setContextMenu(Menu.buildFromTemplate([ - { label: text.show, click: showFromTray }, - { type: 'separator' }, - { label: text.quit, click: () => app.quit() }, - ])); + refreshTrayMenu(); // Harmless where it does nothing (GNOME), useful on desktops that do send it. tray.on('click', showFromTray); + if (!trayTimer) trayTimer = setInterval(refreshTrayMenu, TRAY_POLL_MS); return tray; } - function createWindow() { const bounds = (config.window && config.window.width) ? config.window : { width: 1200, height: 800, @@ -1073,7 +1115,16 @@ function registerBridge() { // of the Node page. Deliberately not `probeNode()`: that asks the daemon's // own HTTP API, which cannot answer while the daemon is stopped or crash- // looping — exactly the states this panel exists to show and act on. - ipcMain.handle('node:service-status', async () => { + // The tray menu drives the same daemon controls as the Node page. Declared + // here because these close over registerBridge's helpers; the tray is created + // long after, so it reads them through this binding rather than duplicating + // the systemctl and Task Scheduler branches. + nodeService = { status: nodeServiceStatus, stop: nodeServiceStop, + restart: nodeServiceRestart }; + + ipcMain.handle('node:service-status', () => nodeServiceStatus()); + + async function nodeServiceStatus() { if (process.platform === 'win32') { const svc = await winServiceTaskStatus(); if (svc.installed) { @@ -1133,9 +1184,11 @@ function registerBridge() { }); }); }); - }); + } - ipcMain.handle('node:service-stop', async () => { + ipcMain.handle('node:service-stop', () => nodeServiceStop()); + + async function nodeServiceStop() { if (process.platform === 'win32') { const svc = await winServiceTaskStatus(); if (svc.installed) await winServiceTaskEnd(); @@ -1154,9 +1207,11 @@ function registerBridge() { }); }); return { stopped: true }; - }); + } - ipcMain.handle('node:service-restart', async () => { + ipcMain.handle('node:service-restart', () => nodeServiceRestart()); + + async function nodeServiceRestart() { if (process.platform === 'win32') { const svc = await winServiceTaskStatus(); if (svc.installed) await winServiceTaskEnd(); @@ -1181,7 +1236,7 @@ function registerBridge() { }); }); return { restarted: true }; - }); + } // Install / remove the Windows Startup-folder launcher, and query it. ipcMain.handle('node:autostart', async (_e, action) => { diff --git a/packages/meshbay-client/src/tray-icon.png b/packages/meshbay-client/src/tray-icon.png Binary files differindex 394604d..98fd63b 100644 --- a/packages/meshbay-client/src/tray-icon.png +++ b/packages/meshbay-client/src/tray-icon.png diff --git a/packages/meshbay-client/src/tray-icon@2x.png b/packages/meshbay-client/src/tray-icon@2x.png Binary files differindex 3e533fb..9cf613d 100644 --- a/packages/meshbay-client/src/tray-icon@2x.png +++ b/packages/meshbay-client/src/tray-icon@2x.png |