From 8b2c857c3fbe3bb30d7694b2cb1d3be712046280 Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Sun, 19 Jul 2026 17:59:23 +0200 Subject: [PATCH] feat(settings): wire session, away-digest, and cron button visibility toggles Per-device App Settings > Header Displays toggles that show/hide the session manager and away-digest header buttons (default OFF) and the cron footer button (default ON). Adds the load/save/apply/default/displayKeys wiring in settings-ui.js plus the marker CSS in styles.css. Client-only display keys, stripped from the settings PUT so they never reach the strict server schema (mirrors the showAttachmentsButton pattern); session/away stay hidden on phones via the existing mobile.css rules. The button markup and checkbox rows landed earlier in 5728b86. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/web/public/settings-ui.js | 39 +++++++++++++++++++++++++++++++++++ src/web/public/styles.css | 25 ++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/web/public/settings-ui.js b/src/web/public/settings-ui.js index 8341d23b..03ed69d4 100644 --- a/src/web/public/settings-ui.js +++ b/src/web/public/settings-ui.js @@ -324,6 +324,10 @@ Object.assign(CodemanApp.prototype, { document.getElementById('appSettingsShowMultiMonitorButton').checked = settings.showMultiMonitorButton ?? defaults.showMultiMonitorButton ?? false; document.getElementById('appSettingsShowPlanUsageLimits').checked = settings.showPlanUsageLimits ?? defaults.showPlanUsageLimits ?? false; document.getElementById('appSettingsShowRedrawButton').checked = settings.showRedrawButton ?? defaults.showRedrawButton ?? false; + // Session Manager + Away Digest buttons default OFF; Cron button defaults ON. + document.getElementById('appSettingsShowSessionButton').checked = settings.showSessionButton ?? defaults.showSessionButton ?? false; + document.getElementById('appSettingsShowAwayDigestButton').checked = settings.showAwayDigestButton ?? defaults.showAwayDigestButton ?? false; + document.getElementById('appSettingsShowCronButton').checked = settings.showCronButton ?? defaults.showCronButton ?? true; // Gesture control lives in the Input section (alongside Local Echo / CJK Input) // but is only available when the instance runs with CODEMAN_GESTURE=1 (server sets // window.__codemanGestureAvailable). Hide just this item otherwise so the toggle @@ -1432,6 +1436,9 @@ Object.assign(CodemanApp.prototype, { showMultiMonitorButton: document.getElementById('appSettingsShowMultiMonitorButton').checked, showPlanUsageLimits: document.getElementById('appSettingsShowPlanUsageLimits').checked, showRedrawButton: document.getElementById('appSettingsShowRedrawButton').checked, + showSessionButton: document.getElementById('appSettingsShowSessionButton').checked, + showAwayDigestButton: document.getElementById('appSettingsShowAwayDigestButton').checked, + showCronButton: document.getElementById('appSettingsShowCronButton').checked, gestureControlEnabled: document.getElementById('appSettingsGestureControl').checked, subagentTrackingEnabled: document.getElementById('appSettingsSubagentTracking').checked, subagentActiveTabOnly: document.getElementById('appSettingsSubagentActiveTabOnly').checked, @@ -1613,6 +1620,11 @@ Object.assign(CodemanApp.prototype, { showAttachmentsButton: _ahb, webglRendererEnabled: _wgl, terminalWheelLocalScrollback: _twls, + // Per-device header/toolbar button toggles — client-only, and absent from + // SettingsUpdateSchema (.strict()), so sending them would 400 the PUT. + showSessionButton: _ssb, + showAwayDigestButton: _adb, + showCronButton: _crb, ...serverSettings } = settings; try { @@ -1770,6 +1782,9 @@ Object.assign(CodemanApp.prototype, { showPlanUsageLimits: false, showAttachmentsButton: false, showRedrawButton: false, + showSessionButton: false, + showAwayDigestButton: false, + showCronButton: true, // Input gestureControlEnabled: false, // Feature toggles - keep tracking on even on mobile @@ -1917,6 +1932,29 @@ Object.assign(CodemanApp.prototype, { redrawBtn.classList.toggle('btn-redraw-terminal--hidden', !showRedrawButton); } + // Session Manager button — opt-in, hidden by default (App Settings → Display). + // Marker class (base is display:inline-flex !important); phones keep it hidden + // via mobile.css regardless. Sessions stay reachable via the Ctrl+K palette. + const showSessionButton = settings.showSessionButton ?? defaults.showSessionButton ?? false; + const sessionBtn = document.querySelector('.btn-session-manager'); + if (sessionBtn) { + sessionBtn.classList.toggle('btn-session-manager--hidden', !showSessionButton); + } + + // Away Digest button — opt-in, hidden by default. Same marker pattern. + const showAwayDigestButton = settings.showAwayDigestButton ?? defaults.showAwayDigestButton ?? false; + const awayDigestBtn = document.querySelector('.btn-away-digest'); + if (awayDigestBtn) { + awayDigestBtn.classList.toggle('btn-away-digest--hidden', !showAwayDigestButton); + } + + // Cron button (footer toolbar) — shown by default; hide when disabled. + const showCronButton = settings.showCronButton ?? defaults.showCronButton ?? true; + const cronBtn = document.querySelector('.btn-cron'); + if (cronBtn) { + cronBtn.classList.toggle('btn-cron--hidden', !showCronButton); + } + // Notification bell is retired (notifications live in Settings → Notifications // + the drawer); keep it hidden regardless of the notification-enabled state. const notifBtn = document.querySelector('.btn-notifications'); @@ -2155,6 +2193,7 @@ Object.assign(CodemanApp.prototype, { 'subagentActiveTabOnly', 'tabTwoRows', 'localEchoEnabled', 'cjkInputEnabled', 'extendedKeyboardBar', 'skin', 'showPlanUsageLimits', 'showAttachmentsButton', 'webglRendererEnabled', 'terminalWheelLocalScrollback', + 'showSessionButton', 'showAwayDigestButton', 'showCronButton', ]); // The plan-usage chip is a PER-DEVICE display setting (default OFF): desktop // can show it while mobile stays hidden. It used to sync, so an older diff --git a/src/web/public/styles.css b/src/web/public/styles.css index bb334dfc..f4f4335a 100644 --- a/src/web/public/styles.css +++ b/src/web/public/styles.css @@ -9471,6 +9471,31 @@ kbd { display: none !important; } +/* "Session Manager" + "Away Digest" header buttons — opt-in (App Settings → + Display), hidden by default. Same marker pattern as the response viewer: a + base inline-flex !important so an inline style can't override it, and a + more-specific marker rule to hide. Phones keep them hidden regardless via the + higher-specificity mobile.css rule (.btn-icon-header.btn-...). */ +.btn-session-manager { + display: inline-flex !important; +} +.btn-session-manager.btn-session-manager--hidden { + display: none !important; +} +.btn-away-digest { + display: inline-flex !important; +} +.btn-away-digest.btn-away-digest--hidden { + display: none !important; +} + +/* "Cron" footer-toolbar button — shown by default (App Settings → Display can + hide it). Toolbar button, not a header icon, so only the hide marker is + needed; out-specify any base .btn-toolbar display. */ +.btn-toolbar.btn-cron--hidden { + display: none !important; +} + /* "Ultracode Agents" header launcher — opt-in (App Settings → Display), hidden by default everywhere (so the mobile-header-buttons-policy guard auto-excludes it). Base inline-flex !important + a more-specific marker rule to hide. */