diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-05 09:28:03 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-05 09:28:03 +0200 |
| commit | 7601991ccb1d75637c055062c38b1852eeef9700 (patch) | |
| tree | 022d6ce76e632d005417c82e92e0277614a92689 /packages/meshbay-hub | |
| parent | 301c8998bfdcac80ad3302e2d2ebe853e2ea6de1 (diff) | |
| download | meshbay-7601991ccb1d75637c055062c38b1852eeef9700.tar.gz | |
feat(client): a Node-page toggle to switch into/out of service mode
The installer's own mode question is effectively one-shot: customInstall
skips it entirely once the firewall rules already exist, for any reason --
and per-user mode sets those up on its own, with no Scheduled Task involved.
So declining once (or the rules existing from something unrelated, as
happened on a dev machine this session) was a dead end: no reinstall, repair,
or uninstall/reinstall cycle could ever bring the question back, since
uninstall defaults to leaving both alone.
Add the other door in (and out): a checkbox on the Node page, next to the
existing per-user autostart toggle, wired main.js -> preload.js -> platform.js
-> node-page.js. It runs packaging/win/service-mode.ps1 -- the exact script
installer.nsh already runs -- via one Start-Process -Verb RunAs elevation, so
the two paths can never disagree about what service mode means. The elevation
helper writes a tiny param()-based .ps1 to %TEMP% so the target script path
and its arguments bind through real PowerShell parameters instead of nested
string-quoting.
Also fixes a real pre-existing gap found while checking this: 8 of the 10
locale catalogues (all but en/fr) were missing the autostart/service-mode
keys added in an earlier commit this session (b782886) -- test_locales.py's
key-set-parity check uses a for-loop with an inline assert, so it stopped at
the first mismatch (fr) and never actually reached the other eight. Backfilled
all five keys (three pre-existing, two new) in de/es/it/ja/nl/pl/pt-BR/zh-CN.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub')
12 files changed, 84 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js index b66c847..bb81fee 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js @@ -678,6 +678,11 @@ export default { 'node.service_stopping': 'Wird angehalten…', 'node.service_restart': 'Neu starten', 'node.service_restarting': 'Wird neu gestartet…', + 'node.autostart_label': 'Automatisch bei der Anmeldung starten', + 'node.autostart_updating': 'Wird aktualisiert…', + 'node.service_mode_hint': 'Läuft als Hintergrunddienst — startet beim Booten, vor der Anmeldung.', + 'node.service_mode_label': 'Als Hintergrunddienst ausführen (startet beim Booten, vor der Anmeldung)', + 'node.service_mode_updating': 'Modus wird gewechselt — achten Sie auf eine Administrator-Eingabeaufforderung…', 'node.not_operator': 'Ihr Node konnte nicht erreicht werden. Stellen Sie sicher, dass er läuft.', 'node.offline': 'Node ist offline', 'node.retry': 'Erneut versuchen', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js index 196b9cc..2817432 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js @@ -737,6 +737,8 @@ export default { 'node.autostart_label': 'Start automatically at sign-in', 'node.autostart_updating': 'Updating…', 'node.service_mode_hint': 'Running as a background service — it starts at boot, before sign-in.', + 'node.service_mode_label': 'Run as a background service (starts at boot, before sign-in)', + 'node.service_mode_updating': 'Switching mode — check for an administrator prompt…', 'node.offline': 'Node is offline', 'node.no_groups': 'No groups configured on this node.', 'node.retry': 'Retry', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js index 8d06a2d..0f3ce21 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js @@ -674,6 +674,11 @@ export default { 'node.service_stopping': 'Deteniendo…', 'node.service_restart': 'Reiniciar', 'node.service_restarting': 'Reiniciando…', + 'node.autostart_label': 'Iniciar automáticamente al iniciar sesión', + 'node.autostart_updating': 'Actualizando…', + 'node.service_mode_hint': 'Se ejecuta como servicio en segundo plano — se inicia al arrancar, antes de iniciar sesión.', + 'node.service_mode_label': 'Ejecutar como servicio en segundo plano (se inicia al arrancar, antes de iniciar sesión)', + 'node.service_mode_updating': 'Cambiando de modo — compruebe si aparece un aviso de administrador…', 'node.not_operator': 'No se pudo contactar con su node. Asegúrese de que esté en ejecución.', 'node.offline': 'Node sin conexión', 'node.retry': 'Reintentar', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js index fe38500..c3c4846 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js @@ -680,6 +680,8 @@ export default { 'node.autostart_label': 'Démarrer automatiquement à l\'ouverture de session', 'node.autostart_updating': 'Mise à jour…', 'node.service_mode_hint': 'Fonctionne comme service en arrière-plan — démarre au boot, avant l\'ouverture de session.', + 'node.service_mode_label': 'Exécuter comme service en arrière-plan (démarre au boot, avant l\'ouverture de session)', + 'node.service_mode_updating': 'Changement de mode — vérifiez une invite d\'administrateur…', 'node.not_operator': 'Impossible de joindre votre node. Vérifiez qu\'il est en cours d\'exécution.', 'node.offline': 'Node hors ligne', 'node.retry': 'Réessayer', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js index 52e18a8..f39ab3c 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js @@ -676,6 +676,11 @@ export default { 'node.service_stopping': 'Arresto…', 'node.service_restart': 'Riavvia', 'node.service_restarting': 'Riavvio…', + 'node.autostart_label': 'Avvia automaticamente all\'accesso', + 'node.autostart_updating': 'Aggiornamento…', + 'node.service_mode_hint': 'In esecuzione come servizio in background — si avvia all\'avvio del sistema, prima dell\'accesso.', + 'node.service_mode_label': 'Esegui come servizio in background (si avvia all\'avvio del sistema, prima dell\'accesso)', + 'node.service_mode_updating': 'Cambio modalità — controlli se compare una richiesta di amministratore…', 'node.not_operator': 'Impossibile raggiungere il suo node. Si assicuri che sia in esecuzione.', 'node.offline': 'Node non in linea', 'node.retry': 'Riprova', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js index c0560b3..1544940 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js @@ -664,6 +664,11 @@ export default { 'node.service_stopping': '停止中…', 'node.service_restart': '再起動', 'node.service_restarting': '再起動中…', + 'node.autostart_label': 'サインイン時に自動的に開始する', + 'node.autostart_updating': '更新中…', + 'node.service_mode_hint': 'バックグラウンドサービスとして実行中 — サインインより前、起動時に開始します。', + 'node.service_mode_label': 'バックグラウンドサービスとして実行する(サインインより前、起動時に開始)', + 'node.service_mode_updating': 'モードを切り替え中 — 管理者の確認ダイアログをご確認ください…', 'node.not_operator': 'node に接続できませんでした。node が実行中であることをご確認ください。', 'node.offline': 'Node はオフラインです', 'node.retry': '再試行', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js index da6dc04..19feec2 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js @@ -678,6 +678,11 @@ export default { 'node.service_stopping': 'Stoppen…', 'node.service_restart': 'Herstarten', 'node.service_restarting': 'Herstarten…', + 'node.autostart_label': 'Automatisch starten bij aanmelden', + 'node.autostart_updating': 'Bijwerken…', + 'node.service_mode_hint': 'Actief als achtergrondservice — start bij het opstarten, vóór het aanmelden.', + 'node.service_mode_label': 'Uitvoeren als achtergrondservice (start bij het opstarten, vóór het aanmelden)', + 'node.service_mode_updating': 'Modus wijzigen — let op een beheerdersprompt…', 'node.not_operator': 'Uw node is niet bereikbaar. Controleer of hij draait.', 'node.offline': 'Node is offline', 'node.retry': 'Opnieuw proberen', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js index 29feebe..512c4f3 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js @@ -696,6 +696,11 @@ export default { 'node.service_stopping': 'Zatrzymywanie…', 'node.service_restart': 'Uruchom ponownie', 'node.service_restarting': 'Ponowne uruchamianie…', + 'node.autostart_label': 'Uruchamiaj automatycznie przy logowaniu', + 'node.autostart_updating': 'Aktualizowanie…', + 'node.service_mode_hint': 'Działa jako usługa w tle — uruchamia się przy starcie systemu, przed zalogowaniem.', + 'node.service_mode_label': 'Uruchom jako usługę w tle (uruchamia się przy starcie systemu, przed zalogowaniem)', + 'node.service_mode_updating': 'Zmiana trybu — proszę sprawdzić, czy pojawiło się okno uprawnień administratora…', 'node.not_operator': 'Nie udało się połączyć z Pana/Pani node. Upewnij się, że działa.', 'node.offline': 'Node jest niedostępny', 'node.retry': 'Ponów', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js index d2fc355..8e33d74 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js @@ -675,6 +675,11 @@ export default { 'node.service_stopping': 'Parando…', 'node.service_restart': 'Reiniciar', 'node.service_restarting': 'Reiniciando…', + 'node.autostart_label': 'Iniciar automaticamente ao entrar na sessão', + 'node.autostart_updating': 'Atualizando…', + 'node.service_mode_hint': 'Em execução como serviço em segundo plano — inicia na inicialização, antes do login.', + 'node.service_mode_label': 'Executar como serviço em segundo plano (inicia na inicialização, antes do login)', + 'node.service_mode_updating': 'Alternando modo — verifique se aparece um aviso de administrador…', 'node.not_operator': 'Não foi possível alcançar seu node. Verifique se ele está em execução.', 'node.offline': 'Node está off-line', 'node.retry': 'Tentar novamente', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js index 6840774..299dc4f 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js @@ -651,6 +651,11 @@ export default { 'node.service_stopping': '正在停止…', 'node.service_restart': '重启', 'node.service_restarting': '正在重启…', + 'node.autostart_label': '登录时自动启动', + 'node.autostart_updating': '正在更新…', + 'node.service_mode_hint': '以后台服务方式运行 — 在开机时启动,早于登录。', + 'node.service_mode_label': '以后台服务方式运行(在开机时启动,早于登录)', + 'node.service_mode_updating': '正在切换模式 — 请留意管理员权限提示…', 'node.not_operator': '无法连接到您的 node。请确保它正在运行。', 'node.offline': 'Node 已离线', 'node.retry': '重试', 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 d242b75..2a0b0d7 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/node-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/node-page.js @@ -53,6 +53,17 @@ function NodeServicePanel({ onChanged }) { : platform.node.autostart.install())); }, [act, info]); + // 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. + const toggleServiceMode = useCallback(() => { + act('serviceMode', () => (info && info.mode === 'service' + ? platform.node.serviceMode.remove() + : platform.node.serviceMode.install())); + }, [act, info]); + if (!platform.node.service.available) return null; if (!info || info.supported === false) { return html`<div class="node-service"> @@ -99,6 +110,14 @@ function NodeServicePanel({ onChanged }) { ${' '}${busy === 'autostart' ? t('node.autostart_updating') : t('node.autostart_label')} </label> `} + ${platform.node.serviceMode.available && typeof info.mode === 'string' && html` + <label class="toggle-switch ${busy ? 'toggle-switch-disabled' : ''}"> + <input type="checkbox" checked=${info.mode === 'service'} disabled=${!!busy} + onChange=${toggleServiceMode} /> + <span class="toggle-switch-track"><span class="toggle-switch-thumb"></span></span> + ${' '}${busy === 'serviceMode' ? t('node.service_mode_updating') : t('node.service_mode_label')} + </label> + `} </div>`; } diff --git a/packages/meshbay-hub/src/meshbay_hub/static/platform.js b/packages/meshbay-hub/src/meshbay_hub/static/platform.js index b1025c5..8f5d484 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/platform.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/platform.js @@ -282,6 +282,27 @@ export const node = { return bridge.node.autostart('remove'); }, }, + /** + * 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. + */ + serviceMode: { + available: Boolean(bridge && bridge.node && bridge.node.serviceMode), + async install() { + if (!bridge || !bridge.node || !bridge.node.serviceMode) + throw new Error('Node bridge not available'); + return bridge.node.serviceMode('install'); + }, + async remove() { + if (!bridge || !bridge.node || !bridge.node.serviceMode) + throw new Error('Node bridge not available'); + return bridge.node.serviceMode('remove'); + }, + }, }; /** |