diff --git a/app/sovran_systemsos_web/server.py b/app/sovran_systemsos_web/server.py index 3180f92..a0259bf 100644 --- a/app/sovran_systemsos_web/server.py +++ b/app/sovran_systemsos_web/server.py @@ -57,6 +57,7 @@ ZEUS_CONNECT_FILE = "/var/lib/secrets/zeus-connect-url" REBOOT_COMMAND = ["reboot"] ONBOARDING_FLAG = "/var/lib/sovran/onboarding-complete" +AUTOLAUNCH_DISABLE_FLAG = "/var/lib/sovran/hub-autolaunch-disabled" # ── Tech Support constants ──────────────────────────────────────── @@ -1390,6 +1391,39 @@ async def api_onboarding_complete(): return {"ok": True} +# ── Auto-launch endpoints ───────────────────────────────────────── + +@app.get("/api/autolaunch/status") +async def api_autolaunch_status(): + """Check if Hub auto-launch on login is enabled.""" + disabled = os.path.exists(AUTOLAUNCH_DISABLE_FLAG) + return {"enabled": not disabled} + + +class AutolaunchToggleRequest(BaseModel): + enabled: bool + + +@app.post("/api/autolaunch/toggle") +async def api_autolaunch_toggle(req: AutolaunchToggleRequest): + """Enable or disable Hub auto-launch on login.""" + if req.enabled: + # Remove the disable flag to enable auto-launch + try: + os.remove(AUTOLAUNCH_DISABLE_FLAG) + except FileNotFoundError: + pass + else: + # Create the disable flag to suppress auto-launch + os.makedirs(os.path.dirname(AUTOLAUNCH_DISABLE_FLAG), exist_ok=True) + try: + with open(AUTOLAUNCH_DISABLE_FLAG, "w") as f: + f.write("") + except OSError as exc: + raise HTTPException(status_code=500, detail=f"Could not write flag file: {exc}") + return {"ok": True, "enabled": req.enabled} + + @app.get("/api/config") async def api_config(): cfg = load_config() diff --git a/app/sovran_systemsos_web/static/js/events.js b/app/sovran_systemsos_web/static/js/events.js index 8d5e9ea..a39ef00 100644 --- a/app/sovran_systemsos_web/static/js/events.js +++ b/app/sovran_systemsos_web/static/js/events.js @@ -105,12 +105,14 @@ async function init() { if (cfg.feature_manager) { loadFeatureManager(); } + loadAutolaunchToggle(); } catch (_) { await refreshServices(); loadNetwork(); checkUpdates(); setInterval(refreshServices, POLL_INTERVAL_SERVICES); setInterval(checkUpdates, POLL_INTERVAL_UPDATES); + loadAutolaunchToggle(); } } diff --git a/app/sovran_systemsos_web/static/js/features.js b/app/sovran_systemsos_web/static/js/features.js index 4c92cfb..0b30519 100644 --- a/app/sovran_systemsos_web/static/js/features.js +++ b/app/sovran_systemsos_web/static/js/features.js @@ -579,3 +579,66 @@ function buildFeatureCard(feat) { return card; } + +// ── Auto-launch toggle ──────────────────────────────────────────── + +async function loadAutolaunchToggle() { + try { + var data = await apiFetch("/api/autolaunch/status"); + renderAutolaunchToggle(data.enabled); + } catch (err) { + console.warn("Failed to load autolaunch status:", err); + } +} + +function renderAutolaunchToggle(enabled) { + // Remove existing section if any + var old = $sidebarFeatures.querySelector(".autolaunch-section"); + if (old) old.parentNode.removeChild(old); + + var section = document.createElement("div"); + section.className = "category-section autolaunch-section"; + + section.innerHTML = + '