Skip to content

Commit 6388cba

Browse files
committed
fix(app): remove oc-1 theme
1 parent 5cc61e1 commit 6388cba

7 files changed

Lines changed: 126 additions & 50 deletions

File tree

packages/app/e2e/settings/settings.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,42 @@ test("changing theme persists in localStorage", async ({ page, gotoSession }) =>
116116
expect(dataTheme).toBe(storedThemeId)
117117
})
118118

119+
test("legacy oc-1 theme migrates to oc-2", async ({ page, gotoSession }) => {
120+
await page.addInitScript(() => {
121+
localStorage.setItem("opencode-theme-id", "oc-1")
122+
localStorage.setItem("opencode-theme-css-light", "--background-base:#fff;")
123+
localStorage.setItem("opencode-theme-css-dark", "--background-base:#000;")
124+
})
125+
126+
await gotoSession()
127+
128+
await expect(page.locator("html")).toHaveAttribute("data-theme", "oc-2")
129+
130+
await expect
131+
.poll(async () => {
132+
return await page.evaluate(() => {
133+
return localStorage.getItem("opencode-theme-id")
134+
})
135+
})
136+
.toBe("oc-2")
137+
138+
await expect
139+
.poll(async () => {
140+
return await page.evaluate(() => {
141+
return localStorage.getItem("opencode-theme-css-light")
142+
})
143+
})
144+
.toBeNull()
145+
146+
await expect
147+
.poll(async () => {
148+
return await page.evaluate(() => {
149+
return localStorage.getItem("opencode-theme-css-dark")
150+
})
151+
})
152+
.toBeNull()
153+
})
154+
119155
test("changing font persists in localStorage and updates CSS variable", async ({ page, gotoSession }) => {
120156
await gotoSession()
121157

packages/app/public/oc-theme-preload.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
;(function () {
2-
var themeId = localStorage.getItem("opencode-theme-id") || "oc-2"
2+
var key = "opencode-theme-id"
3+
var themeId = localStorage.getItem(key) || "oc-2"
4+
5+
if (themeId === "oc-1") {
6+
themeId = "oc-2"
7+
localStorage.setItem(key, themeId)
8+
localStorage.removeItem("opencode-theme-css-light")
9+
localStorage.removeItem("opencode-theme-css-dark")
10+
}
311

412
var scheme = localStorage.getItem("opencode-color-scheme") || "system"
513
var isDark = scheme === "dark" || (scheme === "system" && matchMedia("(prefers-color-scheme: dark)").matches)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { beforeEach, describe, expect, test } from "bun:test"
2+
3+
const src = await Bun.file(new URL("../public/oc-theme-preload.js", import.meta.url)).text()
4+
5+
const run = () => Function(src)()
6+
7+
beforeEach(() => {
8+
document.head.innerHTML = ""
9+
document.documentElement.removeAttribute("data-theme")
10+
document.documentElement.removeAttribute("data-color-scheme")
11+
localStorage.clear()
12+
Object.defineProperty(window, "matchMedia", {
13+
value: () =>
14+
({
15+
matches: false,
16+
}) as MediaQueryList,
17+
configurable: true,
18+
})
19+
})
20+
21+
describe("theme preload", () => {
22+
test("migrates legacy oc-1 to oc-2 before mount", () => {
23+
localStorage.setItem("opencode-theme-id", "oc-1")
24+
localStorage.setItem("opencode-theme-css-light", "--background-base:#fff;")
25+
localStorage.setItem("opencode-theme-css-dark", "--background-base:#000;")
26+
27+
run()
28+
29+
expect(document.documentElement.dataset.theme).toBe("oc-2")
30+
expect(document.documentElement.dataset.colorScheme).toBe("light")
31+
expect(localStorage.getItem("opencode-theme-id")).toBe("oc-2")
32+
expect(localStorage.getItem("opencode-theme-css-light")).toBeNull()
33+
expect(localStorage.getItem("opencode-theme-css-dark")).toBeNull()
34+
expect(document.getElementById("oc-theme-preload")).toBeNull()
35+
})
36+
37+
test("keeps cached css for non-default themes", () => {
38+
localStorage.setItem("opencode-theme-id", "nightowl")
39+
localStorage.setItem("opencode-theme-css-light", "--background-base:#fff;")
40+
41+
run()
42+
43+
expect(document.documentElement.dataset.theme).toBe("nightowl")
44+
expect(document.getElementById("oc-theme-preload")?.textContent).toContain("--background-base:#fff;")
45+
})
46+
})

packages/ui/src/theme/context.tsx

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ const STORAGE_KEYS = {
1616

1717
const THEME_STYLE_ID = "oc-theme"
1818

19+
function normalize(id: string | null | undefined) {
20+
return id === "oc-1" ? "oc-2" : id
21+
}
22+
23+
function clear() {
24+
localStorage.removeItem(STORAGE_KEYS.THEME_CSS_LIGHT)
25+
localStorage.removeItem(STORAGE_KEYS.THEME_CSS_DARK)
26+
}
27+
1928
function ensureThemeStyleElement(): HTMLStyleElement {
2029
const existing = document.getElementById(THEME_STYLE_ID) as HTMLStyleElement | null
2130
if (existing) return existing
@@ -71,7 +80,7 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
7180
init: (props: { defaultTheme?: string }) => {
7281
const [store, setStore] = createStore({
7382
themes: DEFAULT_THEMES as Record<string, DesktopTheme>,
74-
themeId: props.defaultTheme ?? "oc-2",
83+
themeId: normalize(props.defaultTheme) ?? "oc-2",
7584
colorScheme: "system" as ColorScheme,
7685
mode: getSystemMode(),
7786
previewThemeId: null as string | null,
@@ -89,9 +98,14 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
8998
onCleanup(() => mediaQuery.removeEventListener("change", handler))
9099

91100
const savedTheme = localStorage.getItem(STORAGE_KEYS.THEME_ID)
101+
const themeId = normalize(savedTheme)
92102
const savedScheme = localStorage.getItem(STORAGE_KEYS.COLOR_SCHEME) as ColorScheme | null
93-
if (savedTheme && store.themes[savedTheme]) {
94-
setStore("themeId", savedTheme)
103+
if (themeId && store.themes[themeId]) {
104+
setStore("themeId", themeId)
105+
}
106+
if (savedTheme && themeId && savedTheme !== themeId) {
107+
localStorage.setItem(STORAGE_KEYS.THEME_ID, themeId)
108+
clear()
95109
}
96110
if (savedScheme) {
97111
setStore("colorScheme", savedScheme)
@@ -113,14 +127,23 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
113127
})
114128

115129
const setTheme = (id: string) => {
116-
const theme = store.themes[id]
130+
const next = normalize(id)
131+
if (!next) {
132+
console.warn(`Theme "${id}" not found`)
133+
return
134+
}
135+
const theme = store.themes[next]
117136
if (!theme) {
118137
console.warn(`Theme "${id}" not found`)
119138
return
120139
}
121-
setStore("themeId", id)
122-
localStorage.setItem(STORAGE_KEYS.THEME_ID, id)
123-
cacheThemeVariants(theme, id)
140+
setStore("themeId", next)
141+
localStorage.setItem(STORAGE_KEYS.THEME_ID, next)
142+
if (next === "oc-2") {
143+
clear()
144+
return
145+
}
146+
cacheThemeVariants(theme, next)
124147
}
125148

126149
const setColorScheme = (scheme: ColorScheme) => {
@@ -138,15 +161,17 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
138161
setColorScheme,
139162
registerTheme: (theme: DesktopTheme) => setStore("themes", theme.id, theme),
140163
previewTheme: (id: string) => {
141-
const theme = store.themes[id]
164+
const next = normalize(id)
165+
if (!next) return
166+
const theme = store.themes[next]
142167
if (!theme) return
143-
setStore("previewThemeId", id)
168+
setStore("previewThemeId", next)
144169
const previewMode = store.previewScheme
145170
? store.previewScheme === "system"
146171
? getSystemMode()
147172
: store.previewScheme
148173
: store.mode
149-
applyThemeCss(theme, id, previewMode)
174+
applyThemeCss(theme, next, previewMode)
150175
},
151176
previewColorScheme: (scheme: ColorScheme) => {
152177
setStore("previewScheme", scheme)

packages/ui/src/theme/default-themes.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { DesktopTheme } from "./types"
2-
import oc1ThemeJson from "./themes/oc-1.json"
32
import oc2ThemeJson from "./themes/oc-2.json"
43
import tokyoThemeJson from "./themes/tokyonight.json"
54
import draculaThemeJson from "./themes/dracula.json"
@@ -16,7 +15,6 @@ import carbonfoxThemeJson from "./themes/carbonfox.json"
1615
import gruvboxThemeJson from "./themes/gruvbox.json"
1716
import auraThemeJson from "./themes/aura.json"
1817

19-
export const oc1Theme = oc1ThemeJson as DesktopTheme
2018
export const oc2Theme = oc2ThemeJson as DesktopTheme
2119
export const tokyonightTheme = tokyoThemeJson as DesktopTheme
2220
export const draculaTheme = draculaThemeJson as DesktopTheme
@@ -35,7 +33,6 @@ export const auraTheme = auraThemeJson as DesktopTheme
3533

3634
export const DEFAULT_THEMES: Record<string, DesktopTheme> = {
3735
"oc-2": oc2Theme,
38-
"oc-1": oc1Theme,
3936
aura: auraTheme,
4037
ayu: ayuTheme,
4138
carbonfox: carbonfoxTheme,

packages/ui/src/theme/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export { ThemeProvider, useTheme, type ColorScheme } from "./context"
3535

3636
export {
3737
DEFAULT_THEMES,
38-
oc1Theme,
3938
oc2Theme,
4039
tokyonightTheme,
4140
draculaTheme,

packages/ui/src/theme/themes/oc-1.json

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)