Skip to content

Commit 448b4f8

Browse files
CopilotBunsDev
andauthored
Fix web test failures from SSR theme import and Claude auth diagnostics (#456)
* 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> * 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> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
1 parent 23ac756 commit 448b4f8

2 files changed

Lines changed: 52 additions & 11 deletions

File tree

apps/web/src/components/chat/threadError.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ const AUTH_FAILURE_PATTERNS = [
1616
"run codex login",
1717
"run `claude auth login`",
1818
"run claude auth login",
19+
"authenticated with `claude auth login`",
20+
"authenticated with claude auth login",
1921
"codex cli is not authenticated",
2022
"claude is not authenticated",
2123
"supported anthropic credential",

apps/web/src/hooks/useTheme.ts

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const STORAGE_KEY = "okcode:theme";
1515
const COLOR_THEME_STORAGE_KEY = "okcode:color-theme";
1616
const FONT_FAMILY_STORAGE_KEY = "okcode:font-family";
1717
const MEDIA_QUERY = "(prefers-color-scheme: dark)";
18+
const canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
1819

1920
const SERVER_SNAPSHOT: ThemeSnapshot = {
2021
theme: "system",
@@ -30,18 +31,46 @@ function emitChange() {
3031
for (const listener of listeners) listener();
3132
}
3233

34+
function safeLocalStorageGet(key: string): string | null {
35+
if (!canUseDOM) {
36+
return null;
37+
}
38+
39+
try {
40+
return window.localStorage.getItem(key);
41+
} catch {
42+
return null;
43+
}
44+
}
45+
46+
function safeLocalStorageSet(key: string, value: string) {
47+
if (!canUseDOM) {
48+
return;
49+
}
50+
51+
try {
52+
window.localStorage.setItem(key, value);
53+
} catch {
54+
// Ignore storage failures and keep the in-memory theme usable.
55+
}
56+
}
57+
3358
function getSystemDark(): boolean {
59+
if (!canUseDOM) {
60+
return false;
61+
}
62+
3463
return window.matchMedia(MEDIA_QUERY).matches;
3564
}
3665

3766
function getStored(): Theme {
38-
const raw = localStorage.getItem(STORAGE_KEY);
67+
const raw = safeLocalStorageGet(STORAGE_KEY);
3968
if (raw === "light" || raw === "dark" || raw === "system") return raw;
4069
return "system";
4170
}
4271

4372
function getStoredColorTheme(): ColorTheme {
44-
const raw = localStorage.getItem(COLOR_THEME_STORAGE_KEY);
73+
const raw = safeLocalStorageGet(COLOR_THEME_STORAGE_KEY);
4574
const normalized = raw === "cotton-candy" ? "purple-stuff" : raw;
4675

4776
if (
@@ -52,8 +81,8 @@ function getStoredColorTheme(): ColorTheme {
5281
normalized === "hot-tamale" ||
5382
normalized === "custom"
5483
) {
55-
if (normalized !== raw) {
56-
localStorage.setItem(COLOR_THEME_STORAGE_KEY, normalized);
84+
if (normalized !== raw && raw !== null) {
85+
safeLocalStorageSet(COLOR_THEME_STORAGE_KEY, normalized);
5786
}
5887

5988
return normalized;
@@ -62,7 +91,7 @@ function getStoredColorTheme(): ColorTheme {
6291
}
6392

6493
function getStoredFontFamily(): FontFamily {
65-
const raw = localStorage.getItem(FONT_FAMILY_STORAGE_KEY);
94+
const raw = safeLocalStorageGet(FONT_FAMILY_STORAGE_KEY);
6695
if (raw === "dm-sans" || raw === "inter" || raw === "plus-jakarta-sans") {
6796
return raw;
6897
}
@@ -167,12 +196,18 @@ function syncDesktopTheme(theme: Theme) {
167196
}
168197

169198
// Initialize custom theme + overrides on module load
170-
initCustomTheme();
199+
if (canUseDOM) {
200+
initCustomTheme();
171201

172-
// Apply immediately on module load to prevent flash
173-
applyTheme(getStored());
202+
// Apply immediately on module load to prevent flash
203+
applyTheme(getStored());
204+
}
174205

175206
function getSnapshot(): ThemeSnapshot {
207+
if (!canUseDOM) {
208+
return SERVER_SNAPSHOT;
209+
}
210+
176211
const theme = getStored();
177212
const systemDark = theme === "system" ? getSystemDark() : false;
178213
const colorTheme = getStoredColorTheme();
@@ -197,6 +232,10 @@ function getServerSnapshot(): ThemeSnapshot {
197232
}
198233

199234
function subscribe(listener: () => void): () => void {
235+
if (!canUseDOM) {
236+
return () => {};
237+
}
238+
200239
listeners.push(listener);
201240

202241
// Listen for system preference changes
@@ -237,19 +276,19 @@ export function useTheme() {
237276
theme === "system" ? (snapshot.systemDark ? "dark" : "light") : theme;
238277

239278
const setTheme = useCallback((next: Theme) => {
240-
localStorage.setItem(STORAGE_KEY, next);
279+
safeLocalStorageSet(STORAGE_KEY, next);
241280
applyTheme(next, true);
242281
emitChange();
243282
}, []);
244283

245284
const setColorTheme = useCallback((next: ColorTheme) => {
246-
localStorage.setItem(COLOR_THEME_STORAGE_KEY, next);
285+
safeLocalStorageSet(COLOR_THEME_STORAGE_KEY, next);
247286
applyTheme(getStored(), true);
248287
emitChange();
249288
}, []);
250289

251290
const setFontFamily = useCallback((next: FontFamily) => {
252-
localStorage.setItem(FONT_FAMILY_STORAGE_KEY, next);
291+
safeLocalStorageSet(FONT_FAMILY_STORAGE_KEY, next);
253292
applyFont(next);
254293
emitChange();
255294
}, []);

0 commit comments

Comments
 (0)