|
|
@@ -4,15 +4,13 @@
|
|
|
* Generates a minimal inline script that:
|
|
|
* 1. Reads theme preferences from localStorage
|
|
|
* 2. Applies cached theme CSS immediately (avoiding FOUC)
|
|
|
- * 3. Falls back to embedded default theme CSS on first visit
|
|
|
+ *
|
|
|
+ * The default (oc-1) theme is provided by `@opencode-ai/ui/styles` via `theme.css`,
|
|
|
+ * so the preload script only runs when a non-default theme is selected.
|
|
|
*
|
|
|
* The script should be placed in the document <head> before any stylesheets.
|
|
|
*/
|
|
|
|
|
|
-import { resolveThemeVariant, themeToCss } from "./resolve"
|
|
|
-import type { DesktopTheme } from "./types"
|
|
|
-import oc1Theme from "./themes/oc-1.json"
|
|
|
-
|
|
|
// Storage keys used by both the preload script and the ThemeProvider
|
|
|
export const STORAGE_KEYS = {
|
|
|
THEME_ID: "opencode-theme-id",
|
|
|
@@ -27,34 +25,17 @@ export function getThemeCacheKey(themeId: string, mode: "light" | "dark"): strin
|
|
|
return `${STORAGE_KEYS.THEME_CSS_PREFIX}-${themeId}-${mode}`
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Generate the embedded default theme CSS for the preload script.
|
|
|
- * This is used as a fallback when no cached theme exists.
|
|
|
- */
|
|
|
-function generateEmbeddedDefaults(): { light: string; dark: string } {
|
|
|
- const theme = oc1Theme as DesktopTheme
|
|
|
- const lightTokens = resolveThemeVariant(theme.light, false)
|
|
|
- const darkTokens = resolveThemeVariant(theme.dark, true)
|
|
|
-
|
|
|
- return {
|
|
|
- light: themeToCss(lightTokens),
|
|
|
- dark: themeToCss(darkTokens),
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* Generate the inline preload script.
|
|
|
*
|
|
|
* This script should be placed in the document <head> to avoid FOUC.
|
|
|
- * It reads theme preferences from localStorage and applies the theme CSS
|
|
|
- * immediately, falling back to an embedded default theme.
|
|
|
+ * It reads theme preferences from localStorage and applies cached theme CSS
|
|
|
+ * immediately.
|
|
|
*/
|
|
|
export function generatePreloadScript(): string {
|
|
|
- const defaults = generateEmbeddedDefaults()
|
|
|
-
|
|
|
// Minified version of the preload logic
|
|
|
// Variables: T=themeId, S=scheme, D=isDark, M=mode, C=css, K=cacheKey
|
|
|
- return `(function(){var T=localStorage.getItem("${STORAGE_KEYS.THEME_ID}")||"oc-1";var S=localStorage.getItem("${STORAGE_KEYS.COLOR_SCHEME}")||"system";var D=S==="dark"||(S==="system"&&matchMedia("(prefers-color-scheme:dark)").matches);var M=D?"dark":"light";var K="${STORAGE_KEYS.THEME_CSS_PREFIX}-"+T+"-"+M;var C=localStorage.getItem(K);if(!C&&T==="oc-1"){C=D?${JSON.stringify(defaults.dark)}:${JSON.stringify(defaults.light)}}if(C){var s=document.createElement("style");s.id="oc-theme-preload";s.textContent=":root{color-scheme:"+M+";--text-mix-blend-mode:"+(D?"plus-lighter":"multiply")+";"+C+"}";document.head.appendChild(s)}document.documentElement.dataset.theme=T;document.documentElement.dataset.colorScheme=M})();`
|
|
|
+ return `(function(){var T=localStorage.getItem("${STORAGE_KEYS.THEME_ID}");if(!T)return;var S=localStorage.getItem("${STORAGE_KEYS.COLOR_SCHEME}")||"system";var D=S==="dark"||(S==="system"&&matchMedia("(prefers-color-scheme:dark)").matches);var M=D?"dark":"light";document.documentElement.dataset.theme=T;document.documentElement.dataset.colorScheme=M;if(T==="oc-1")return;var K="${STORAGE_KEYS.THEME_CSS_PREFIX}-"+T+"-"+M;var C=localStorage.getItem(K);if(C){var s=document.createElement("style");s.id="oc-theme-preload";s.textContent=":root{color-scheme:"+M+";--text-mix-blend-mode:"+(D?"plus-lighter":"multiply")+";"+C+"}";document.head.appendChild(s)}})();`
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -62,15 +43,16 @@ export function generatePreloadScript(): string {
|
|
|
* Useful for debugging.
|
|
|
*/
|
|
|
export function generatePreloadScriptFormatted(): string {
|
|
|
- const defaults = generateEmbeddedDefaults()
|
|
|
-
|
|
|
return `(function() {
|
|
|
var THEME_KEY = "${STORAGE_KEYS.THEME_ID}";
|
|
|
var SCHEME_KEY = "${STORAGE_KEYS.COLOR_SCHEME}";
|
|
|
var CSS_PREFIX = "${STORAGE_KEYS.THEME_CSS_PREFIX}";
|
|
|
|
|
|
- // Read preferences from localStorage
|
|
|
- var themeId = localStorage.getItem(THEME_KEY) || "oc-1";
|
|
|
+ // Only preload when a theme is selected
|
|
|
+ var themeId = localStorage.getItem(THEME_KEY);
|
|
|
+ if (!themeId) return;
|
|
|
+
|
|
|
+ // Read color scheme preference
|
|
|
var scheme = localStorage.getItem(SCHEME_KEY) || "system";
|
|
|
|
|
|
// Determine if dark mode
|
|
|
@@ -78,17 +60,17 @@ export function generatePreloadScriptFormatted(): string {
|
|
|
(scheme === "system" && matchMedia("(prefers-color-scheme: dark)").matches);
|
|
|
var mode = isDark ? "dark" : "light";
|
|
|
|
|
|
+ // Set data attributes for CSS/JS reference
|
|
|
+ document.documentElement.dataset.theme = themeId;
|
|
|
+ document.documentElement.dataset.colorScheme = mode;
|
|
|
+
|
|
|
+ // Default theme is handled by theme.css
|
|
|
+ if (themeId === "oc-1") return;
|
|
|
+
|
|
|
// Try to get cached CSS for this theme + mode
|
|
|
var cacheKey = CSS_PREFIX + "-" + themeId + "-" + mode;
|
|
|
var css = localStorage.getItem(cacheKey);
|
|
|
|
|
|
- // Fallback to embedded default for oc-1 theme
|
|
|
- if (!css && themeId === "oc-1") {
|
|
|
- css = isDark
|
|
|
- ? ${JSON.stringify(defaults.dark)}
|
|
|
- : ${JSON.stringify(defaults.light)};
|
|
|
- }
|
|
|
-
|
|
|
// Apply CSS if we have it
|
|
|
if (css) {
|
|
|
var style = document.createElement("style");
|
|
|
@@ -100,9 +82,5 @@ export function generatePreloadScriptFormatted(): string {
|
|
|
"}";
|
|
|
document.head.appendChild(style);
|
|
|
}
|
|
|
-
|
|
|
- // Set data attributes for CSS/JS reference
|
|
|
- document.documentElement.dataset.theme = themeId;
|
|
|
- document.documentElement.dataset.colorScheme = mode;
|
|
|
})();`
|
|
|
}
|