From a379eb38673aad097e1f178307865ec40a5ac3ea Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Tue, 24 Mar 2026 18:36:37 -0500 Subject: Revert "fix(app): startup efficiency (#18854)" This reverts commit 546748a461539ca63e188ee07ab2b143c5ac2c83. --- packages/ui/src/theme/context.tsx | 286 ++++++++++---------------------------- 1 file changed, 71 insertions(+), 215 deletions(-) (limited to 'packages/ui/src/theme') diff --git a/packages/ui/src/theme/context.tsx b/packages/ui/src/theme/context.tsx index 7d25ac397..9808c8e84 100644 --- a/packages/ui/src/theme/context.tsx +++ b/packages/ui/src/theme/context.tsx @@ -1,7 +1,7 @@ import { createEffect, onCleanup, onMount } from "solid-js" import { createStore } from "solid-js/store" import { createSimpleContext } from "../context/helper" -import oc2ThemeJson from "./themes/oc-2.json" +import { DEFAULT_THEMES } from "./default-themes" import { resolveThemeVariant, themeToCss } from "./resolve" import type { DesktopTheme } from "./types" @@ -15,101 +15,14 @@ const STORAGE_KEYS = { } as const const THEME_STYLE_ID = "oc-theme" -let files: Record Promise<{ default: DesktopTheme }>> | undefined -let ids: string[] | undefined -let known: Set | undefined - -function getFiles() { - if (files) return files - files = import.meta.glob<{ default: DesktopTheme }>("./themes/*.json") - return files -} - -function themeIDs() { - if (ids) return ids - ids = Object.keys(getFiles()) - .map((path) => path.slice("./themes/".length, -".json".length)) - .sort() - return ids -} - -function knownThemes() { - if (known) return known - known = new Set(themeIDs()) - return known -} - -const names: Record = { - "oc-2": "OC-2", - amoled: "AMOLED", - aura: "Aura", - ayu: "Ayu", - carbonfox: "Carbonfox", - catppuccin: "Catppuccin", - "catppuccin-frappe": "Catppuccin Frappe", - "catppuccin-macchiato": "Catppuccin Macchiato", - cobalt2: "Cobalt2", - cursor: "Cursor", - dracula: "Dracula", - everforest: "Everforest", - flexoki: "Flexoki", - github: "GitHub", - gruvbox: "Gruvbox", - kanagawa: "Kanagawa", - "lucent-orng": "Lucent Orng", - material: "Material", - matrix: "Matrix", - mercury: "Mercury", - monokai: "Monokai", - nightowl: "Night Owl", - nord: "Nord", - "one-dark": "One Dark", - onedarkpro: "One Dark Pro", - opencode: "OpenCode", - orng: "Orng", - "osaka-jade": "Osaka Jade", - palenight: "Palenight", - rosepine: "Rose Pine", - shadesofpurple: "Shades of Purple", - solarized: "Solarized", - synthwave84: "Synthwave '84", - tokyonight: "Tokyonight", - vercel: "Vercel", - vesper: "Vesper", - zenburn: "Zenburn", -} -const oc2Theme = oc2ThemeJson as DesktopTheme function normalize(id: string | null | undefined) { return id === "oc-1" ? "oc-2" : id } -function read(key: string) { - if (typeof localStorage !== "object") return null - try { - return localStorage.getItem(key) - } catch { - return null - } -} - -function write(key: string, value: string) { - if (typeof localStorage !== "object") return - try { - localStorage.setItem(key, value) - } catch {} -} - -function drop(key: string) { - if (typeof localStorage !== "object") return - try { - localStorage.removeItem(key) - } catch {} -} - function clear() { - drop(STORAGE_KEYS.THEME_CSS_LIGHT) - drop(STORAGE_KEYS.THEME_CSS_DARK) + localStorage.removeItem(STORAGE_KEYS.THEME_CSS_LIGHT) + localStorage.removeItem(STORAGE_KEYS.THEME_CSS_DARK) } function ensureThemeStyleElement(): HTMLStyleElement { @@ -122,7 +35,6 @@ function ensureThemeStyleElement(): HTMLStyleElement { } function getSystemMode(): "light" | "dark" { - if (typeof window !== "object") return "light" return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" } @@ -133,7 +45,9 @@ function applyThemeCss(theme: DesktopTheme, themeId: string, mode: "light" | "da const css = themeToCss(tokens) if (themeId !== "oc-2") { - write(isDark ? STORAGE_KEYS.THEME_CSS_DARK : STORAGE_KEYS.THEME_CSS_LIGHT, css) + try { + localStorage.setItem(isDark ? STORAGE_KEYS.THEME_CSS_DARK : STORAGE_KEYS.THEME_CSS_LIGHT, css) + } catch {} } const fullCss = `:root { @@ -155,122 +69,74 @@ function cacheThemeVariants(theme: DesktopTheme, themeId: string) { const variant = isDark ? theme.dark : theme.light const tokens = resolveThemeVariant(variant, isDark) const css = themeToCss(tokens) - write(isDark ? STORAGE_KEYS.THEME_CSS_DARK : STORAGE_KEYS.THEME_CSS_LIGHT, css) + try { + localStorage.setItem(isDark ? STORAGE_KEYS.THEME_CSS_DARK : STORAGE_KEYS.THEME_CSS_LIGHT, css) + } catch {} } } export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ name: "Theme", init: (props: { defaultTheme?: string; onThemeApplied?: (theme: DesktopTheme, mode: "light" | "dark") => void }) => { - const themeId = normalize(read(STORAGE_KEYS.THEME_ID) ?? props.defaultTheme) ?? "oc-2" - const colorScheme = (read(STORAGE_KEYS.COLOR_SCHEME) as ColorScheme | null) ?? "system" - const mode = colorScheme === "system" ? getSystemMode() : colorScheme const [store, setStore] = createStore({ - themes: { - "oc-2": oc2Theme, - } as Record, - themeId, - colorScheme, - mode, + themes: DEFAULT_THEMES as Record, + themeId: normalize(props.defaultTheme) ?? "oc-2", + colorScheme: "system" as ColorScheme, + mode: getSystemMode(), previewThemeId: null as string | null, previewScheme: null as ColorScheme | null, }) - const loads = new Map>() - - const load = (id: string) => { - const next = normalize(id) - if (!next) return Promise.resolve(undefined) - const hit = store.themes[next] - if (hit) return Promise.resolve(hit) - const pending = loads.get(next) - if (pending) return pending - const file = getFiles()[`./themes/${next}.json`] - if (!file) return Promise.resolve(undefined) - const task = file() - .then((mod) => { - const theme = mod.default - setStore("themes", next, theme) - return theme - }) - .finally(() => { - loads.delete(next) - }) - loads.set(next, task) - return task - } - - const applyTheme = (theme: DesktopTheme, themeId: string, mode: "light" | "dark") => { - applyThemeCss(theme, themeId, mode) - props.onThemeApplied?.(theme, mode) - } - - const ids = () => { - const extra = Object.keys(store.themes) - .filter((id) => !knownThemes().has(id)) - .sort() - const all = themeIDs() - if (extra.length === 0) return all - return [...all, ...extra] - } - - const loadThemes = () => Promise.all(themeIDs().map(load)).then(() => store.themes) - - const onStorage = (e: StorageEvent) => { - if (e.key === STORAGE_KEYS.THEME_ID && e.newValue) { - const next = normalize(e.newValue) - if (!next) return - if (next !== "oc-2" && !knownThemes().has(next) && !store.themes[next]) return - setStore("themeId", next) - if (next === "oc-2") { - clear() - return - } - void load(next).then((theme) => { - if (!theme || store.themeId !== next) return - cacheThemeVariants(theme, next) - }) - } + window.addEventListener("storage", (e) => { + if (e.key === STORAGE_KEYS.THEME_ID && e.newValue) setStore("themeId", e.newValue) if (e.key === STORAGE_KEYS.COLOR_SCHEME && e.newValue) { setStore("colorScheme", e.newValue as ColorScheme) - setStore("mode", e.newValue === "system" ? getSystemMode() : (e.newValue as "light" | "dark")) + setStore("mode", e.newValue === "system" ? getSystemMode() : (e.newValue as any)) } - } - - if (typeof window === "object") { - window.addEventListener("storage", onStorage) - onCleanup(() => window.removeEventListener("storage", onStorage)) - } + }) onMount(() => { const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") - const onMedia = () => { - if (store.colorScheme !== "system") return - setStore("mode", getSystemMode()) + const handler = () => { + if (store.colorScheme === "system") { + setStore("mode", getSystemMode()) + } } - mediaQuery.addEventListener("change", onMedia) - onCleanup(() => mediaQuery.removeEventListener("change", onMedia)) - - const rawTheme = read(STORAGE_KEYS.THEME_ID) - const savedTheme = normalize(rawTheme ?? props.defaultTheme) ?? "oc-2" - const savedScheme = (read(STORAGE_KEYS.COLOR_SCHEME) as ColorScheme | null) ?? "system" - if (rawTheme && rawTheme !== savedTheme) { - write(STORAGE_KEYS.THEME_ID, savedTheme) + mediaQuery.addEventListener("change", handler) + onCleanup(() => mediaQuery.removeEventListener("change", handler)) + + const savedTheme = localStorage.getItem(STORAGE_KEYS.THEME_ID) + const themeId = normalize(savedTheme) + const savedScheme = localStorage.getItem(STORAGE_KEYS.COLOR_SCHEME) as ColorScheme | null + if (themeId && store.themes[themeId]) { + setStore("themeId", themeId) + } + if (savedTheme && themeId && savedTheme !== themeId) { + localStorage.setItem(STORAGE_KEYS.THEME_ID, themeId) clear() } - if (savedTheme !== store.themeId) setStore("themeId", savedTheme) - if (savedScheme !== store.colorScheme) setStore("colorScheme", savedScheme) - setStore("mode", savedScheme === "system" ? getSystemMode() : savedScheme) - void load(savedTheme).then((theme) => { - if (!theme || store.themeId !== savedTheme) return - cacheThemeVariants(theme, savedTheme) - }) + if (savedScheme) { + setStore("colorScheme", savedScheme) + if (savedScheme !== "system") { + setStore("mode", savedScheme) + } + } + const currentTheme = store.themes[store.themeId] + if (currentTheme) { + cacheThemeVariants(currentTheme, store.themeId) + } }) + const applyTheme = (theme: DesktopTheme, themeId: string, mode: "light" | "dark") => { + applyThemeCss(theme, themeId, mode) + props.onThemeApplied?.(theme, mode) + } + createEffect(() => { const theme = store.themes[store.themeId] - if (!theme) return - applyTheme(theme, store.themeId, store.mode) + if (theme) { + applyTheme(theme, store.themeId, store.mode) + } }) const setTheme = (id: string) => { @@ -279,26 +145,23 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ console.warn(`Theme "${id}" not found`) return } - if (next !== "oc-2" && !knownThemes().has(next) && !store.themes[next]) { + const theme = store.themes[next] + if (!theme) { console.warn(`Theme "${id}" not found`) return } setStore("themeId", next) + localStorage.setItem(STORAGE_KEYS.THEME_ID, next) if (next === "oc-2") { - write(STORAGE_KEYS.THEME_ID, next) clear() return } - void load(next).then((theme) => { - if (!theme || store.themeId !== next) return - cacheThemeVariants(theme, next) - write(STORAGE_KEYS.THEME_ID, next) - }) + cacheThemeVariants(theme, next) } const setColorScheme = (scheme: ColorScheme) => { setStore("colorScheme", scheme) - write(STORAGE_KEYS.COLOR_SCHEME, scheme) + localStorage.setItem(STORAGE_KEYS.COLOR_SCHEME, scheme) setStore("mode", scheme === "system" ? getSystemMode() : scheme) } @@ -306,9 +169,6 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ themeId: () => store.themeId, colorScheme: () => store.colorScheme, mode: () => store.mode, - ids, - name: (id: string) => store.themes[id]?.name ?? names[id] ?? id, - loadThemes, themes: () => store.themes, setTheme, setColorScheme, @@ -316,28 +176,24 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ previewTheme: (id: string) => { const next = normalize(id) if (!next) return - if (next !== "oc-2" && !knownThemes().has(next) && !store.themes[next]) return + const theme = store.themes[next] + if (!theme) return setStore("previewThemeId", next) - void load(next).then((theme) => { - if (!theme || store.previewThemeId !== next) return - const mode = store.previewScheme - ? store.previewScheme === "system" - ? getSystemMode() - : store.previewScheme - : store.mode - applyTheme(theme, next, mode) - }) + const previewMode = store.previewScheme + ? store.previewScheme === "system" + ? getSystemMode() + : store.previewScheme + : store.mode + applyTheme(theme, next, previewMode) }, previewColorScheme: (scheme: ColorScheme) => { setStore("previewScheme", scheme) - const mode = scheme === "system" ? getSystemMode() : scheme + const previewMode = scheme === "system" ? getSystemMode() : scheme const id = store.previewThemeId ?? store.themeId - void load(id).then((theme) => { - if (!theme) return - if ((store.previewThemeId ?? store.themeId) !== id) return - if (store.previewScheme !== scheme) return - applyTheme(theme, id, mode) - }) + const theme = store.themes[id] + if (theme) { + applyTheme(theme, id, previewMode) + } }, commitPreview: () => { if (store.previewThemeId) { @@ -352,10 +208,10 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ cancelPreview: () => { setStore("previewThemeId", null) setStore("previewScheme", null) - void load(store.themeId).then((theme) => { - if (!theme) return + const theme = store.themes[store.themeId] + if (theme) { applyTheme(theme, store.themeId, store.mode) - }) + } }, } }, -- cgit v1.2.3