Move theme menu to the header and group present chrome under it.
Also align Token stats with the settings shell and drop leftover lifecycle toggle wiring. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+116
@@ -0,0 +1,116 @@
|
||||
/** Color themes + present chrome — aligned with llm_workflow_engine ThemeToggle. */
|
||||
|
||||
export const COLOR_THEMES = [
|
||||
{
|
||||
id: "paper",
|
||||
name: "仿纸暖黄",
|
||||
description: "经典护眼,像 Kindle",
|
||||
icon: "📖",
|
||||
},
|
||||
{
|
||||
id: "modern",
|
||||
name: "现代清爽",
|
||||
description: "干净明快,适合网文",
|
||||
icon: "✨",
|
||||
},
|
||||
{
|
||||
id: "dark",
|
||||
name: "夜间暗色",
|
||||
description: "黑底灰字,夜间必备",
|
||||
icon: "🌙",
|
||||
},
|
||||
{
|
||||
id: "green",
|
||||
name: "豆沙绿",
|
||||
description: "自然疗愈,绿色经典",
|
||||
icon: "🍃",
|
||||
},
|
||||
];
|
||||
|
||||
/** 呈现壳气质(tone_chrome),与色主题同属「主题」菜单 */
|
||||
export const PRESENT_CHROMES = [
|
||||
{ id: "default", name: "默认", description: "跟随壳本身" },
|
||||
{ id: "messenger", name: "讯息", description: "气泡对话感" },
|
||||
{ id: "book", name: "书页", description: "阅读排版感" },
|
||||
{ id: "terminal", name: "终端", description: "等宽终端感" },
|
||||
];
|
||||
|
||||
const STORAGE_KEY = "wa-color-theme";
|
||||
const CHROME_STORAGE_KEY = "wa-present-chrome";
|
||||
const THEME_IDS = new Set(COLOR_THEMES.map((t) => t.id));
|
||||
const CHROME_IDS = new Set(PRESENT_CHROMES.map((t) => t.id));
|
||||
const DEFAULT_THEME = "modern";
|
||||
const DEFAULT_CHROME = "default";
|
||||
|
||||
export function normalizeColorTheme(id) {
|
||||
const v = String(id || "").trim();
|
||||
return THEME_IDS.has(v) ? v : DEFAULT_THEME;
|
||||
}
|
||||
|
||||
export function getStoredColorTheme() {
|
||||
try {
|
||||
return normalizeColorTheme(localStorage.getItem(STORAGE_KEY));
|
||||
} catch {
|
||||
return DEFAULT_THEME;
|
||||
}
|
||||
}
|
||||
|
||||
export function themeById(id) {
|
||||
const tid = normalizeColorTheme(id);
|
||||
return COLOR_THEMES.find((t) => t.id === tid) || COLOR_THEMES[1];
|
||||
}
|
||||
|
||||
export function applyColorTheme(id) {
|
||||
const theme = normalizeColorTheme(id);
|
||||
document.documentElement.setAttribute("data-color-theme", theme);
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, theme);
|
||||
} catch {
|
||||
/* ignore quota / private mode */
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
export function initColorTheme() {
|
||||
return applyColorTheme(getStoredColorTheme());
|
||||
}
|
||||
|
||||
export function normalizePresentChrome(id) {
|
||||
const v = String(id || "").trim();
|
||||
return CHROME_IDS.has(v) ? v : DEFAULT_CHROME;
|
||||
}
|
||||
|
||||
export function getStoredPresentChrome() {
|
||||
try {
|
||||
return normalizePresentChrome(localStorage.getItem(CHROME_STORAGE_KEY));
|
||||
} catch {
|
||||
return DEFAULT_CHROME;
|
||||
}
|
||||
}
|
||||
|
||||
export function chromeById(id) {
|
||||
const cid = normalizePresentChrome(id);
|
||||
return PRESENT_CHROMES.find((t) => t.id === cid) || PRESENT_CHROMES[0];
|
||||
}
|
||||
|
||||
export function applyPresentChrome(id) {
|
||||
const chrome = normalizePresentChrome(id);
|
||||
document.documentElement.setAttribute("data-present-chrome", chrome);
|
||||
try {
|
||||
localStorage.setItem(CHROME_STORAGE_KEY, chrome);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
document.querySelectorAll(".present-shell").forEach((el) => {
|
||||
for (const cls of [...el.classList]) {
|
||||
if (cls.startsWith("present-tone--")) el.classList.remove(cls);
|
||||
}
|
||||
el.classList.add(`present-tone--${chrome}`);
|
||||
});
|
||||
return chrome;
|
||||
}
|
||||
|
||||
export function initPresentChrome() {
|
||||
return applyPresentChrome(getStoredPresentChrome());
|
||||
}
|
||||
Reference in New Issue
Block a user