Files
aiturk-hermes-ide/apps/desktop/src/store/statusbar-prefs.ts
T

75 lines
3.1 KiB
TypeScript

import { Codecs, persistentAtom } from '@/lib/persisted'
const STATUSBAR_HIDDEN_STORAGE_KEY = 'hermes.desktop.statusbarHidden'
const STATUSBAR_VISIBLE_STORAGE_KEY = 'hermes.desktop.statusbarVisible'
// Whole-bar visibility, VS Code's `workbench.statusBar.visible`. On by default.
// Hiding it unmounts the bar (its 15s status poll goes with it), so the way back
// is the `view.toggleStatusbar` keybind or the ⌘K row, never the bar itself.
export const $statusbarVisible = persistentAtom(STATUSBAR_VISIBLE_STORAGE_KEY, true, Codecs.bool)
export function toggleStatusbarVisible() {
$statusbarVisible.set(!$statusbarVisible.get())
}
// Items the bar hides until the user turns them on from its context menu. The
// bar's job is to answer "is the backend healthy, where am I, what's it doing" —
// route shortcuts (cron/webhooks/agents), the terminal toggle, and the approval
// pill are navigation, not status, so they start out of the way. The per-turn
// session readouts (running/session timers, context meter, cache hit rate,
// tokens/sec) are diagnostics most users don't watch, so they start hidden too
// and the bar stays quiet mid-turn.
export const STATUSBAR_HIDDEN_BY_DEFAULT: readonly string[] = [
'agents',
'approval-mode',
'cache-hit-rate',
'context-usage',
'cron',
'running-timer',
'session-timer',
'system-resources',
'terminal',
'tokens-per-second',
'webhooks'
]
// Stored as the explicit hidden set (not the visible one) so an item added to
// the bar in a later version shows up for existing users instead of silently
// staying off. An empty array is a real value — the user turned everything on —
// so this uses a sanitizing json codec rather than Codecs.stringArray, which
// drops the key when empty and would resurrect the defaults on next launch.
export const $statusbarHiddenIds = persistentAtom<string[]>(
STATUSBAR_HIDDEN_STORAGE_KEY,
[...STATUSBAR_HIDDEN_BY_DEFAULT],
Codecs.json<string[]>(value =>
Array.isArray(value) ? value.filter((id): id is string => typeof id === 'string' && id.length > 0) : []
)
)
export function setStatusbarItemVisible(id: string, visible: boolean) {
const hidden = $statusbarHiddenIds.get()
if (visible === !hidden.includes(id)) {
return
}
$statusbarHiddenIds.set(visible ? hidden.filter(entry => entry !== id) : [...hidden, id])
}
/** Pure so the menu can derive its reset row's disabled state from the hidden
* list it already subscribes to, rather than reading the atom out of band.
* Set-compared: order is incidental (items are appended as they're hidden) and
* a duplicated id shouldn't read as a customization. */
export function isStatusbarLayoutDefault(hidden: readonly string[]) {
const ids = new Set(hidden)
return ids.size === STATUSBAR_HIDDEN_BY_DEFAULT.length && STATUSBAR_HIDDEN_BY_DEFAULT.every(id => ids.has(id))
}
/** Put the show/hide set back to what ships. Only touches item layout — whole-bar
* visibility is a separate preference, and resetting from the bar's own menu
* shouldn't make the bar the user is right-clicking disappear. */
export function resetStatusbarLayout() {
$statusbarHiddenIds.set([...STATUSBAR_HIDDEN_BY_DEFAULT])
}