Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/shared/src/prefs.ts
iris be6036b216 swarm-ui: a hide debug output toggle in the header's settings menu
The row moves from the per-agent page into @hive/shared so both pages mount
the same one. The terminal's debug rows now follow the preference as it
changes, so rows already on screen hide or show at once instead of only the
rows that arrive after the toggle.
2026-10-12 21:41:23 +02:00

76 lines
3 KiB
TypeScript

// Tiny browser-local (localStorage) preference helper, in `@hive/shared`
// so a future second consumer (e.g. swarm-ui's own terminal) gets the
// exact same key name for free via the browser's shared per-origin
// storage, rather than an independent copy that could drift.
// `ExpandDetailsSetting` / `HideDebugSetting` (the settings popover rows
// of the per-agent page and of the swarm UI) are the only writers today;
// `Row.tsx` is the only reader of either.
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 applies to the next rendered row in
// any already-open agent tab without a reload.
export function getExpandDetailsPref(): boolean {
try {
return localStorage.getItem(EXPAND_DETAILS_KEY) === "1";
} catch {
return false;
}
}
export function setExpandDetailsPref(v: boolean): void {
try {
if (v) localStorage.setItem(EXPAND_DETAILS_KEY, "1");
else localStorage.removeItem(EXPAND_DETAILS_KEY);
} catch {
/* localStorage unavailable — preference is session-only */
}
}
const HIDE_DEBUG_KEY = "hive-agent-hide-debug";
// Whether a per-agent terminal's `debug`-level rows (thinking, coalesced
// ticks, ambient harness chatter — see docs/web-ui/terminal-rendering.md's
// Levels table) should be skipped entirely rather than rendered muted.
// Same shape as `getExpandDetailsPref` above: pure client-side, no
// backend field, read live (not cached) so a change applies to the next
// rendered row without a reload.
export function getHideDebugPref(): boolean {
try {
return localStorage.getItem(HIDE_DEBUG_KEY) === "1";
} catch {
return false;
}
}
export function setHideDebugPref(v: boolean): void {
try {
if (v) localStorage.setItem(HIDE_DEBUG_KEY, "1");
else localStorage.removeItem(HIDE_DEBUG_KEY);
} catch {
/* localStorage unavailable — preference is session-only */
}
for (const listener of hideDebugListeners) listener();
}
const hideDebugListeners = new Set<() => void>();
// Calls `listener` whenever the preference changes: in this tab through
// `setHideDebugPref`, in another tab of the same origin through the
// browser's `storage` event. Returns the unsubscribe. This is what lets a
// terminal that is already showing rows follow the toggle, instead of only
// the rows that arrive after it.
export function subscribeHideDebugPref(listener: () => void): () => void {
hideDebugListeners.add(listener);
const onStorage = (e: StorageEvent) => {
if (e.key === HIDE_DEBUG_KEY || e.key === null) listener();
};
window.addEventListener("storage", onStorage);
return () => {
hideDebugListeners.delete(listener);
window.removeEventListener("storage", onStorage);
};
}