From 92f607a8647cdc5f80da380a97f4181b10682849 Mon Sep 17 00:00:00 2001 From: bbassie <17990055+bbassie@users.noreply.github.com> Date: Thu, 25 Jun 2026 00:30:12 +0000 Subject: [PATCH 1/2] Remember the instance console chat/log toggle The Console "Chat/Log" filter toggle on the instance page now persists its state to localStorage, so turning it off (to see full logs) is remembered across reloads. It still defaults to on (chat only) when nothing is stored. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/web_ui/src/components/InstanceViewPage.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/web_ui/src/components/InstanceViewPage.tsx b/packages/web_ui/src/components/InstanceViewPage.tsx index 06cb11b7..6bfa9759 100644 --- a/packages/web_ui/src/components/InstanceViewPage.tsx +++ b/packages/web_ui/src/components/InstanceViewPage.tsx @@ -30,6 +30,9 @@ import { MetricRelativeDate } from "./system_metrics"; type MenuItem = Required["items"][number]; const { Title } = Typography; +// Remembers the console "Chat/Log" toggle across reloads (defaults to on). +const consoleActionsOnlyKey = "instance-console-actions-only"; + type InstanceDescriptionProps = { host?: Readonly; instance: Readonly; @@ -177,7 +180,9 @@ export default function InstanceViewPage() { let params = useParams(); let instanceId = Number(params.id); const [maxLevel, setMaxLevel] = useState("server"); - const [actionsOnly, setActionsOnly] = useState(true); + const [actionsOnly, setActionsOnly] = useState( + () => localStorage.getItem(consoleActionsOnlyKey) !== "false" + ); let navigate = useNavigate(); @@ -234,7 +239,10 @@ export default function InstanceViewPage() { checkedChildren="Chat" unCheckedChildren="Log" checked={actionsOnly} - onChange={setActionsOnly} + onChange={value => { + setActionsOnly(value); + localStorage.setItem(consoleActionsOnlyKey, String(value)); + }} /> Date: Thu, 25 Jun 2026 02:07:35 +0000 Subject: [PATCH 2/2] Add useLocalStorage hook for the console toggle Move the instance console chat/log toggle persistence into a generic useLocalStorage hook that defers the write so it never blocks the toggle update. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/components/InstanceViewPage.tsx | 10 ++---- packages/web_ui/src/util/useLocalStorage.ts | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 packages/web_ui/src/util/useLocalStorage.ts diff --git a/packages/web_ui/src/components/InstanceViewPage.tsx b/packages/web_ui/src/components/InstanceViewPage.tsx index 6bfa9759..e83e206d 100644 --- a/packages/web_ui/src/components/InstanceViewPage.tsx +++ b/packages/web_ui/src/components/InstanceViewPage.tsx @@ -25,6 +25,7 @@ import { useHost } from "../model/host"; import InstanceStatusTag from "./InstanceStatusTag"; import Link from "./Link"; import { instancePublicAddress } from "../util/instance"; +import useLocalStorage from "../util/useLocalStorage"; import { MetricRelativeDate } from "./system_metrics"; type MenuItem = Required["items"][number]; @@ -180,9 +181,7 @@ export default function InstanceViewPage() { let params = useParams(); let instanceId = Number(params.id); const [maxLevel, setMaxLevel] = useState("server"); - const [actionsOnly, setActionsOnly] = useState( - () => localStorage.getItem(consoleActionsOnlyKey) !== "false" - ); + const [actionsOnly, setActionsOnly] = useLocalStorage(consoleActionsOnlyKey, true); let navigate = useNavigate(); @@ -239,10 +238,7 @@ export default function InstanceViewPage() { checkedChildren="Chat" unCheckedChildren="Log" checked={actionsOnly} - onChange={value => { - setActionsOnly(value); - localStorage.setItem(consoleActionsOnlyKey, String(value)); - }} + onChange={setActionsOnly} /> (key: string, defaultValue: T): [T, (value: T) => void] { + const [value, setValue] = useState(() => { + const stored = localStorage.getItem(key); + if (stored === null) { + return defaultValue; + } + try { + return JSON.parse(stored) as T; + } catch { + return defaultValue; + } + }); + + function set(next: T) { + setValue(next); + setTimeout(() => { + try { + localStorage.setItem(key, JSON.stringify(next)); + } catch { + // Ignore storage errors (e.g. quota exceeded or storage disabled). + } + }, 0); + } + + return [value, set]; +}