move terminal-verbosity toggle from agent overflow menu to /settings.html
Per mara: 'i wanted you to put this in .../settings.html' — the toggle belongs with the other operator-local browser preferences, not buried in each agent's own overflow menu. Extracted the get/set + localStorage key into @hive/shared/prefs.js so settings.html (writer) and every per-agent app.js (reader, via HiveTerminal.create's expandDetails option) agree on the exact same key without two independently-typed copies that could drift. Removed the now-unused overflow-menu toggle + its agent.css rules from the agent page. Docs moved from docs/web-ui/agent.md's overflow-button section to docs/web-ui/dashboard.md's S3TT1NGS section, next to the existing browser-notifications preference.
This commit is contained in:
parent
3b299375e3
commit
da3fc9bf95
8 changed files with 79 additions and 83 deletions
|
|
@ -101,16 +101,6 @@ through. Three flex columns:
|
|||
the `/effort <level>` slash command). The active level's button is
|
||||
highlighted; `renderEffortChip` keeps the picker in sync with
|
||||
`StateSnapshot.effort` from the cold-load snapshot.
|
||||
A third separator + **settings** section holds a single
|
||||
`role="menuitemcheckbox"` toggle, `☐/☑ expand tool output` — flips
|
||||
whether otherwise-collapsed `<details>` rows in the terminal (long
|
||||
tool-results, Write/Edit diffs, …) default open. Pure client-side:
|
||||
persisted to this browser's `localStorage` only (no backend field,
|
||||
no `/api/*` call), read live by the shared terminal factory's
|
||||
`expandDetails` option (see docs/web-ui/shape.md::Shared terminal
|
||||
pane) so toggling mid-session applies to the next rendered row
|
||||
without a reload. Rows that already default open regardless (send /
|
||||
ask / answer / recv) are unaffected either way.
|
||||
The popover's display rules are scoped to `:not([hidden])` so the
|
||||
`[hidden]` HTML attribute's UA `display: none` isn't overridden by
|
||||
the author CSS's `display: flex` — the popover stays hidden until
|
||||
|
|
|
|||
|
|
@ -622,10 +622,9 @@ frontend reads.
|
|||
|
||||
Operator-local preferences. State lives in the browser's
|
||||
`localStorage` — preferences do NOT sync between devices and
|
||||
do NOT survive a profile wipe. Today the tab holds one section
|
||||
(browser notifications); future preferences (theme, density,
|
||||
etc.) land here as sibling `<h3>` blocks
|
||||
under the same `<section id="tab-pane-settings">`.
|
||||
do NOT survive a profile wipe. Two sections today (browser
|
||||
notifications, agent terminal); future preferences (theme, density,
|
||||
etc.) land here as sibling `<h3>` blocks in `settings.html`.
|
||||
|
||||
**◇ browser notifications** — `🔔 enable notifications` button when
|
||||
permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted
|
||||
|
|
@ -636,6 +635,19 @@ single status line explains why. See `### Browser notifications`
|
|||
below for the dispatch model + the three signals the dashboard
|
||||
emits OS notifications on.
|
||||
|
||||
**◇ agent terminal** — a single `☐/☑ expand tool output panels`
|
||||
toggle button (`role="switch"`, live `aria-checked`). Controls whether
|
||||
every per-agent page's terminal defaults otherwise-collapsed
|
||||
`<details>` rows (long tool-results, Write/Edit diffs, …) open; rows
|
||||
that already default open regardless (send/ask/answer/recv) are
|
||||
unaffected either way. Pure client-side — the key + get/set live in
|
||||
`@hive/shared/prefs.js` (`getExpandDetailsPref`/`setExpandDetailsPref`)
|
||||
so this page and every agent page's `app.js` read/write the exact same
|
||||
`localStorage` key without a backend field; the shared terminal
|
||||
factory reads it live via its `expandDetails` option (see
|
||||
docs/web-ui/shape.md::Shared terminal pane), so a change here applies
|
||||
to any already-open agent tab's next rendered row without a reload.
|
||||
|
||||
The FL0W page does NOT host this pane — settings live only on the
|
||||
dashboard's S3TT1NGS tab (reach it via the FL0W page's `← home`
|
||||
back-link → Dashboard). Notifications still fire on the FL0W page when
|
||||
|
|
|
|||
|
|
@ -299,19 +299,6 @@ h2, h3 {
|
|||
border-color: var(--purple-dim);
|
||||
background: color-mix(in srgb, var(--purple) 6%, transparent);
|
||||
}
|
||||
.overflow-item-verbosity {
|
||||
color: var(--muted);
|
||||
}
|
||||
.overflow-item-verbosity:hover {
|
||||
color: var(--fg);
|
||||
background: color-mix(in srgb, var(--purple) 8%, transparent);
|
||||
border-color: var(--purple-dim);
|
||||
}
|
||||
.overflow-item-verbosity.active {
|
||||
color: var(--purple);
|
||||
border-color: var(--purple-dim);
|
||||
background: color-mix(in srgb, var(--purple) 6%, transparent);
|
||||
}
|
||||
|
||||
/* Header pill — inbox / loose-ends triggers. Compact, count-prominent. */
|
||||
.header-pill {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { create as termCreate, linkify as termLinkify } from '@hive/shared/termi
|
|||
import { asyncBtn, bindAsyncForms } from '@hive/shared/forms.js';
|
||||
import { themedConfirm } from '@hive/shared/modal.js';
|
||||
import { el } from '@hive/shared/dom.js';
|
||||
import { getExpandDetailsPref } from '@hive/shared/prefs.js';
|
||||
import '@hive/shared/side-panel.js'; // registers <hive-side-panel> — side-effect import
|
||||
import { marked } from 'marked';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
|
@ -26,22 +27,6 @@ window.marked = marked;
|
|||
({ '&':'&', '<':'<', '>':'>', '"':'"' }[c])
|
||||
);
|
||||
|
||||
// "Expand tool output by default" terminal-verbosity preference —
|
||||
// pure client-side, browser-local (localStorage only, no backend
|
||||
// field). See the overflow-menu settings toggle below + the
|
||||
// `expandDetails` option passed to HiveTerminal.create().
|
||||
const EXPAND_DETAILS_KEY = 'hive-agent-expand-details';
|
||||
function getExpandDetailsPref() {
|
||||
try { return localStorage.getItem(EXPAND_DETAILS_KEY) === '1'; }
|
||||
catch { return false; }
|
||||
}
|
||||
function setExpandDetailsPref(v) {
|
||||
try {
|
||||
if (v) localStorage.setItem(EXPAND_DETAILS_KEY, '1');
|
||||
else localStorage.removeItem(EXPAND_DETAILS_KEY);
|
||||
} catch { /* localStorage unavailable — preference is session-only */ }
|
||||
}
|
||||
|
||||
// Base URL of the host dashboard (core backend). Set once the first
|
||||
// /api/state lands. Operator-authority actions (answering a question
|
||||
// as the operator) POST here rather than to this agent's own socket —
|
||||
|
|
@ -310,40 +295,6 @@ window.marked = marked;
|
|||
}
|
||||
}
|
||||
|
||||
// ─── settings: expand tool output by default ───────────────────
|
||||
// Pure client-side, browser-local preference (no backend involved) —
|
||||
// see docs/web-ui/agent.md::Overflow button. Controls the *default*
|
||||
// open state of otherwise-collapsed `<details>` rows in the live
|
||||
// terminal (long tool-results, Write/Edit diffs, …); rows that
|
||||
// already default open (send/ask/answer/recv) are unaffected.
|
||||
// Read live by the shared terminal factory (HiveTerminal.create's
|
||||
// `expandDetails` option below), so toggling mid-session applies to
|
||||
// the next rendered row without a reload.
|
||||
const settingsSep = el('div', { class: 'overflow-sep', 'aria-hidden': 'true' });
|
||||
const settingsLabel = el('div', { class: 'overflow-section-label' }, 'settings');
|
||||
menu.append(settingsSep, settingsLabel);
|
||||
const expandIcon = el('span', { class: 'overflow-item-icon', 'aria-hidden': 'true' },
|
||||
getExpandDetailsPref() ? '☑' : '☐');
|
||||
const expandBtn = el('button', {
|
||||
type: 'button',
|
||||
class: 'overflow-item overflow-item-verbosity' + (getExpandDetailsPref() ? ' active' : ''),
|
||||
role: 'menuitemcheckbox',
|
||||
'aria-checked': String(getExpandDetailsPref()),
|
||||
title: 'expand tool output panels by default in this terminal (persisted to this browser only)',
|
||||
id: 'expand-details-btn',
|
||||
},
|
||||
expandIcon,
|
||||
'expand tool output',
|
||||
);
|
||||
expandBtn.addEventListener('click', () => {
|
||||
const next = !getExpandDetailsPref();
|
||||
setExpandDetailsPref(next);
|
||||
expandBtn.classList.toggle('active', next);
|
||||
expandBtn.setAttribute('aria-checked', String(next));
|
||||
expandIcon.textContent = next ? '☑' : '☐';
|
||||
});
|
||||
menu.append(expandBtn);
|
||||
|
||||
overflowMenuPopulated = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@
|
|||
<button type="button" id="notif-unmute" class="btn btn-notif" hidden>🔔 unmute</button>
|
||||
<span id="notif-status" class="meta" hidden></span>
|
||||
</div>
|
||||
|
||||
<h3>◇ agent terminal</h3>
|
||||
<p class="meta">applies to every agent's terminal viewed in this browser — whether otherwise-collapsed tool-output panels (long results, Write/Edit diffs, …) default open. rows that already default open (send/ask/answer/recv) are unaffected either way.</p>
|
||||
<div id="verbosity-row" class="notif-row">
|
||||
<button type="button" id="expand-details-toggle" class="btn btn-notif" role="switch"></button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script type="module" src="/static/settings.js" defer></script>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,37 @@
|
|||
// /settings.html — operator-local preferences page.
|
||||
//
|
||||
// Extracted from the dashboard S3TT1NGS tab. Today the only setting is
|
||||
// the browser-notification toggle: NOTIF.bind() wires the enable / mute /
|
||||
// unmute buttons and persists state to localStorage. The dashboard's
|
||||
// NOTIF.show() calls (approvals / questions) read that same localStorage
|
||||
// state + the browser-level permission, so firing still works from the
|
||||
// dashboard even though the toggle UI now lives on its own page.
|
||||
// Extracted from the dashboard S3TT1NGS tab. The browser-notification
|
||||
// toggle: NOTIF.bind() wires the enable / mute / unmute buttons and
|
||||
// persists state to localStorage. The dashboard's NOTIF.show() calls
|
||||
// (approvals / questions) read that same localStorage state + the
|
||||
// browser-level permission, so firing still works from the dashboard
|
||||
// even though the toggle UI now lives on its own page.
|
||||
//
|
||||
// The agent-terminal-verbosity toggle below is a second, unrelated
|
||||
// browser-local preference — @hive/shared/prefs.js owns the key name +
|
||||
// get/set so this page and every per-agent page's app.js agree on it
|
||||
// without a backend field. Both preferences are per-origin localStorage,
|
||||
// so they only apply within this browser (per the page's own copy).
|
||||
//
|
||||
// initServerWarnings() renders the shared top-of-page warnings banner,
|
||||
// matching the other stand-alone pages (FL0W / L0GS / H0M3).
|
||||
import { NOTIF, initServerWarnings } from './common.js';
|
||||
import { getExpandDetailsPref, setExpandDetailsPref } from '@hive/shared/prefs.js';
|
||||
|
||||
initServerWarnings();
|
||||
NOTIF.bind();
|
||||
|
||||
(function bindExpandDetailsToggle() {
|
||||
const btn = document.getElementById('expand-details-toggle');
|
||||
if (!btn) return;
|
||||
function render() {
|
||||
const on = getExpandDetailsPref();
|
||||
btn.textContent = on ? '☑ expand tool output panels' : '☐ expand tool output panels';
|
||||
btn.setAttribute('aria-checked', String(on));
|
||||
}
|
||||
btn.addEventListener('click', () => {
|
||||
setExpandDetailsPref(!getExpandDetailsPref());
|
||||
render();
|
||||
});
|
||||
render();
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
"./terminal.css": "./src/terminal/terminal.css",
|
||||
"./chrome.css": "./src/chrome.css",
|
||||
"./forms.js": "./src/forms.js",
|
||||
"./prefs.js": "./src/prefs.js",
|
||||
"./dom.js": "./src/dom.js",
|
||||
"./modal.js": "./src/modal.js",
|
||||
"./shadow-css.js": "./src/shadow-css.js",
|
||||
|
|
|
|||
27
frontend/packages/shared/src/prefs.js
Normal file
27
frontend/packages/shared/src/prefs.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Tiny browser-local (localStorage) preference helpers shared by the
|
||||
// dashboard's /settings.html and the per-agent page — both need the
|
||||
// exact same key name to actually talk to each other via the browser's
|
||||
// shared per-origin storage (settings.html is where the operator sets
|
||||
// the preference; every per-agent page's terminal reads it), so the
|
||||
// get/set pair — and the key itself — live here once rather than as
|
||||
// independent copies in each package that could drift out of sync.
|
||||
|
||||
const EXPAND_DETAILS_KEY = 'hive-agent-expand-details';
|
||||
|
||||
// Whether a per-agent terminal's otherwise-collapsed `<details>` panels
|
||||
// (long tool-results, Write/Edit diffs, …) should default open. Pure
|
||||
// client-side — no backend field, nothing round-trips through
|
||||
// `/api/*`. Read live (not cached) by the shared terminal factory's
|
||||
// `expandDetails` option — see docs/web-ui/shape.md::Shared terminal
|
||||
// pane — so a preference change on /settings.html applies to the next
|
||||
// rendered row in any already-open agent tab without a reload.
|
||||
export function getExpandDetailsPref() {
|
||||
try { return localStorage.getItem(EXPAND_DETAILS_KEY) === '1'; }
|
||||
catch { return false; }
|
||||
}
|
||||
export function setExpandDetailsPref(v) {
|
||||
try {
|
||||
if (v) localStorage.setItem(EXPAND_DETAILS_KEY, '1');
|
||||
else localStorage.removeItem(EXPAND_DETAILS_KEY);
|
||||
} catch { /* localStorage unavailable — preference is session-only */ }
|
||||
}
|
||||
Loading…
Reference in a new issue