From ff748604331ed19051ec2a55d5fd7f68c73ed032 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:43:43 +0000 Subject: [PATCH 1/2] Fix web test failures in theme and auth diagnostics Agent-Logs-Url: https://github.com/OpenKnots/okcode/sessions/cdf0b3b9-acf6-479d-aeef-64537e9fb78f Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com> --- apps/web/src/components/chat/threadError.ts | 2 + apps/web/src/hooks/useTheme.ts | 61 +++++++++++++++++---- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/apps/web/src/components/chat/threadError.ts b/apps/web/src/components/chat/threadError.ts index 72e6398d6..c1f61778c 100644 --- a/apps/web/src/components/chat/threadError.ts +++ b/apps/web/src/components/chat/threadError.ts @@ -16,6 +16,8 @@ const AUTH_FAILURE_PATTERNS = [ "run codex login", "run `claude auth login`", "run claude auth login", + "authenticated with `claude auth login`", + "authenticated with claude auth login", "codex cli is not authenticated", "claude is not authenticated", "supported anthropic credential", diff --git a/apps/web/src/hooks/useTheme.ts b/apps/web/src/hooks/useTheme.ts index bebf966f0..45157f6c7 100644 --- a/apps/web/src/hooks/useTheme.ts +++ b/apps/web/src/hooks/useTheme.ts @@ -15,6 +15,7 @@ const STORAGE_KEY = "okcode:theme"; const COLOR_THEME_STORAGE_KEY = "okcode:color-theme"; const FONT_FAMILY_STORAGE_KEY = "okcode:font-family"; const MEDIA_QUERY = "(prefers-color-scheme: dark)"; +const canUseDOM = typeof window !== "undefined" && typeof document !== "undefined"; const SERVER_SNAPSHOT: ThemeSnapshot = { theme: "system", @@ -30,18 +31,46 @@ function emitChange() { for (const listener of listeners) listener(); } +function safeLocalStorageGet(key: string): string | null { + if (!canUseDOM) { + return null; + } + + try { + return window.localStorage.getItem(key); + } catch { + return null; + } +} + +function safeLocalStorageSet(key: string, value: string) { + if (!canUseDOM) { + return; + } + + try { + window.localStorage.setItem(key, value); + } catch { + // Ignore storage failures and keep the in-memory theme usable. + } +} + function getSystemDark(): boolean { + if (!canUseDOM) { + return false; + } + return window.matchMedia(MEDIA_QUERY).matches; } function getStored(): Theme { - const raw = localStorage.getItem(STORAGE_KEY); + const raw = safeLocalStorageGet(STORAGE_KEY); if (raw === "light" || raw === "dark" || raw === "system") return raw; return "system"; } function getStoredColorTheme(): ColorTheme { - const raw = localStorage.getItem(COLOR_THEME_STORAGE_KEY); + const raw = safeLocalStorageGet(COLOR_THEME_STORAGE_KEY); const normalized = raw === "cotton-candy" ? "purple-stuff" : raw; if ( @@ -52,8 +81,8 @@ function getStoredColorTheme(): ColorTheme { normalized === "hot-tamale" || normalized === "custom" ) { - if (normalized !== raw) { - localStorage.setItem(COLOR_THEME_STORAGE_KEY, normalized); + if (normalized !== raw && raw != null) { + safeLocalStorageSet(COLOR_THEME_STORAGE_KEY, normalized); } return normalized; @@ -62,7 +91,7 @@ function getStoredColorTheme(): ColorTheme { } function getStoredFontFamily(): FontFamily { - const raw = localStorage.getItem(FONT_FAMILY_STORAGE_KEY); + const raw = safeLocalStorageGet(FONT_FAMILY_STORAGE_KEY); if (raw === "dm-sans" || raw === "inter" || raw === "plus-jakarta-sans") { return raw; } @@ -167,12 +196,18 @@ function syncDesktopTheme(theme: Theme) { } // Initialize custom theme + overrides on module load -initCustomTheme(); +if (canUseDOM) { + initCustomTheme(); -// Apply immediately on module load to prevent flash -applyTheme(getStored()); + // Apply immediately on module load to prevent flash + applyTheme(getStored()); +} function getSnapshot(): ThemeSnapshot { + if (!canUseDOM) { + return SERVER_SNAPSHOT; + } + const theme = getStored(); const systemDark = theme === "system" ? getSystemDark() : false; const colorTheme = getStoredColorTheme(); @@ -197,6 +232,10 @@ function getServerSnapshot(): ThemeSnapshot { } function subscribe(listener: () => void): () => void { + if (!canUseDOM) { + return () => {}; + } + listeners.push(listener); // Listen for system preference changes @@ -237,19 +276,19 @@ export function useTheme() { theme === "system" ? (snapshot.systemDark ? "dark" : "light") : theme; const setTheme = useCallback((next: Theme) => { - localStorage.setItem(STORAGE_KEY, next); + safeLocalStorageSet(STORAGE_KEY, next); applyTheme(next, true); emitChange(); }, []); const setColorTheme = useCallback((next: ColorTheme) => { - localStorage.setItem(COLOR_THEME_STORAGE_KEY, next); + safeLocalStorageSet(COLOR_THEME_STORAGE_KEY, next); applyTheme(getStored(), true); emitChange(); }, []); const setFontFamily = useCallback((next: FontFamily) => { - localStorage.setItem(FONT_FAMILY_STORAGE_KEY, next); + safeLocalStorageSet(FONT_FAMILY_STORAGE_KEY, next); applyFont(next); emitChange(); }, []); From 374d1f16219f63341f0b7318202beed97f78a09e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:54:39 +0000 Subject: [PATCH 2/2] Address review feedback in theme storage guard Agent-Logs-Url: https://github.com/OpenKnots/okcode/sessions/cdf0b3b9-acf6-479d-aeef-64537e9fb78f Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com> --- apps/web/src/hooks/useTheme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/hooks/useTheme.ts b/apps/web/src/hooks/useTheme.ts index 45157f6c7..80b783b8a 100644 --- a/apps/web/src/hooks/useTheme.ts +++ b/apps/web/src/hooks/useTheme.ts @@ -81,7 +81,7 @@ function getStoredColorTheme(): ColorTheme { normalized === "hot-tamale" || normalized === "custom" ) { - if (normalized !== raw && raw != null) { + if (normalized !== raw && raw !== null) { safeLocalStorageSet(COLOR_THEME_STORAGE_KEY, normalized); }