Global refresh rate in Settings drives every live view and each machine's sampler; per-page pickers removed
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
a4f39859b6
commit
bbf0f2580f
+13
-11
@@ -2,6 +2,7 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { api, DashPrefs, Sample, Series, Temp } from './api'
|
||||
import Sparkline from './Sparkline'
|
||||
import { Loading, Spinner, toast } from './ui'
|
||||
import { fmtMs, useRefreshMs } from './prefs'
|
||||
|
||||
const MAX = 300
|
||||
const S1 = 'var(--s1)', S2 = 'var(--s2)'
|
||||
@@ -23,8 +24,8 @@ const MODULES: Module[] = [
|
||||
]
|
||||
const byId = (id: string) => MODULES.find((m) => m.id === id)
|
||||
|
||||
const INTERVALS = [100, 250, 500, 1000, 2000] as const
|
||||
const DEFAULT_INTERVAL = 2000
|
||||
const clampSampler = (ms: number) => Math.min(2000, Math.max(100, ms))
|
||||
|
||||
interface Layout { order: string[]; hidden: Set<string>; hiddenItems: Set<string>; intervalMs: number }
|
||||
|
||||
@@ -37,7 +38,6 @@ function normalize(p: DashPrefs): Layout {
|
||||
return { order, hidden: new Set((p.hidden ?? []).filter((id) => known.has(id))), hiddenItems: new Set(p.hiddenItems ?? []), intervalMs: iv }
|
||||
}
|
||||
const toPrefs = (l: Layout): DashPrefs => ({ order: l.order, hidden: [...l.hidden], hiddenItems: [...l.hiddenItems], intervalMs: l.intervalMs })
|
||||
const fmtMs = (ms: number) => (ms >= 1000 ? `${ms / 1000} s` : `${ms} ms`)
|
||||
const fmtWindow = (ms: number) => { const s = Math.round((MAX * ms) / 1000); return s >= 60 ? `${Math.round(s / 60)} min` : `${s} s` }
|
||||
|
||||
// ---- formatting ----
|
||||
@@ -266,8 +266,9 @@ export default function Dashboard() {
|
||||
const savedTimer = useRef<number | undefined>(undefined)
|
||||
const hist = useRef<Series | null>(null)
|
||||
const saveTimer = useRef<number | undefined>(undefined)
|
||||
const refreshMs = useRefreshMs()
|
||||
const intervalRef = useRef(DEFAULT_INTERVAL)
|
||||
intervalRef.current = layout.intervalMs
|
||||
intervalRef.current = refreshMs
|
||||
|
||||
// Persist layout changes server-side (debounced) so every device sees the same dashboard.
|
||||
const update = useCallback((fn: (l: Layout) => Layout) => {
|
||||
@@ -328,6 +329,13 @@ export default function Dashboard() {
|
||||
return () => { stop = true; clearTimeout(timer); document.removeEventListener('visibilitychange', onVis) }
|
||||
}, [])
|
||||
|
||||
// The sampler on this machine follows the global rate (clamped to what it supports).
|
||||
useEffect(() => {
|
||||
if (!loaded) return
|
||||
const want = clampSampler(refreshMs)
|
||||
if (layout.intervalMs !== want) update((l) => ({ ...l, intervalMs: want }))
|
||||
}, [refreshMs, loaded]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
if (!latest) return <div className="dash">{err ? <div className="error">{err}</div> : <Loading label="Collecting metrics…" />}</div>
|
||||
|
||||
const edit: Edit = {
|
||||
@@ -371,14 +379,8 @@ export default function Dashboard() {
|
||||
<div className={'dash' + (editing ? ' editing' : '')}>
|
||||
<div className="dash-bar">
|
||||
{err && <span className="error">{err}</span>}
|
||||
{editing ? (
|
||||
<label className="hint">Update every
|
||||
<select className="btn" value={layout.intervalMs} onChange={(e) => update((l) => ({ ...l, intervalMs: Number(e.target.value) }))}>
|
||||
{INTERVALS.map((ms) => <option key={ms} value={ms}>{fmtMs(ms)}</option>)}
|
||||
</select>
|
||||
· last {fmtWindow(layout.intervalMs)} · ▲▼ reorder · ✕ hide
|
||||
</label>
|
||||
) : <span className="hint">last {fmtWindow(latest.interval_ms || layout.intervalMs)} · {fmtMs(latest.interval_ms || layout.intervalMs)}</span>}
|
||||
{editing ? <span className="hint">last {fmtWindow(latest.interval_ms || layout.intervalMs)} · ▲▼ reorder · ✕ hide · refresh rate is in Settings</span>
|
||||
: <span className="hint">last {fmtWindow(latest.interval_ms || layout.intervalMs)} · {fmtMs(latest.interval_ms || layout.intervalMs)}</span>}
|
||||
<span className="spacer" />
|
||||
{saving === 'saving' && <span className="saved"><Spinner /> saving</span>}
|
||||
{saving === 'saved' && <span className="saved">saved ✓</span>}
|
||||
|
||||
Reference in New Issue
Block a user