color update al
This commit is contained in:
parent
a0317d3ddf
commit
3bdc3e2dfe
|
|
@ -1,6 +1,7 @@
|
|||
import { ColorSchema } from "../../../typings";
|
||||
import { proxyWithHistory } from "valtio-history";
|
||||
import { createDarkTheme, createLightTheme } from "../../utils/theme";
|
||||
import { changeThemeSchema } from "../../utils/theme";
|
||||
import { subscribe } from "valtio";
|
||||
|
||||
// // 模拟计算属性
|
||||
// watch((get) => {
|
||||
|
|
@ -8,23 +9,28 @@ import { createDarkTheme, createLightTheme } from "../../utils/theme";
|
|||
// counterStore.double = counterStore.count * 2
|
||||
// })
|
||||
|
||||
const initString = `{"onLight": {}, "onDark": {}}`;
|
||||
const initValue = {
|
||||
onLight: {},
|
||||
onDark: {},
|
||||
};
|
||||
|
||||
export const useThemeStore = proxyWithHistory({
|
||||
// 取值的时候,本地存储有就从本地获取
|
||||
colors: JSON.parse(
|
||||
localStorage.getItem("colors") || initString
|
||||
localStorage.getItem("colors") || JSON.stringify(initValue)
|
||||
) as ColorSchema,
|
||||
init: () => {
|
||||
createLightTheme(useThemeStore.value.colors.onLight);
|
||||
createDarkTheme(useThemeStore.value.colors.onDark!);
|
||||
changeThemeSchema(useThemeStore.value.colors);
|
||||
},
|
||||
updateColors: (value: ColorSchema) => {
|
||||
// 更新的时候,订阅更新一下本地存储
|
||||
localStorage.setItem("colors", JSON.stringify(value));
|
||||
// 在更新的时候同步更新到style
|
||||
createLightTheme(value.onLight);
|
||||
createDarkTheme(value.onDark!);
|
||||
useThemeStore.value.colors = value;
|
||||
},
|
||||
});
|
||||
|
||||
subscribe(useThemeStore, () => {
|
||||
// 更新的时候,订阅更新一下本地存储
|
||||
localStorage.setItem("colors", JSON.stringify(useThemeStore.value.colors));
|
||||
// 在更新的时候同步更新到style
|
||||
changeThemeSchema(useThemeStore.value.colors);
|
||||
console.log("useThemeStore updated");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { Change } from "../../../typings";
|
||||
|
||||
export const useDebounce = (fn: Function, delay: number) => {
|
||||
let timeout: any;
|
||||
return (...args: any[]) => {
|
||||
|
|
@ -5,3 +7,34 @@ export const useDebounce = (fn: Function, delay: number) => {
|
|||
timeout = setTimeout(() => fn(...args), delay);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取对象比较的结果
|
||||
* @param obj1 原始对象
|
||||
* @param obj2 目标对象
|
||||
* @returns 返回修改的key
|
||||
*/
|
||||
export function compareObjects(
|
||||
obj1: Record<string, any>,
|
||||
obj2: Record<string, any>
|
||||
): Change[] {
|
||||
const changes: Change[] = [];
|
||||
|
||||
for (const key in obj1) {
|
||||
if (obj1.hasOwnProperty(key)) {
|
||||
if (!obj2.hasOwnProperty(key)) {
|
||||
changes.push({ key, type: "remove" });
|
||||
} else if (obj1[key] !== obj2[key]) {
|
||||
changes.push({ key, type: "update" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in obj2) {
|
||||
if (obj2.hasOwnProperty(key) && !obj1.hasOwnProperty(key)) {
|
||||
changes.push({ key, type: "add" });
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@ import {
|
|||
ReverseHandlerConfig,
|
||||
RGBString,
|
||||
RGBValue,
|
||||
ThemeBlockCache,
|
||||
ThemeMode,
|
||||
ThemeSection,
|
||||
ThemeVariables,
|
||||
UpdateThemeColor,
|
||||
} from "../../../typings";
|
||||
import { themeColorSchema } from "../../data/colors";
|
||||
import { useDebounce } from "../function";
|
||||
import { compareObjects, useDebounce } from "../function";
|
||||
|
||||
/**
|
||||
* 更新主题颜色
|
||||
|
|
@ -30,6 +32,20 @@ export function updateThemeColor({
|
|||
}
|
||||
}
|
||||
|
||||
export function generateCssText(
|
||||
themeClass: string,
|
||||
themeVariables: ThemeVariables
|
||||
): string {
|
||||
let cssRules = `.${themeClass} {`;
|
||||
for (const variable in themeVariables) {
|
||||
if (themeVariables.hasOwnProperty(variable)) {
|
||||
cssRules += `--${variable}: ${themeVariables[variable]};`;
|
||||
}
|
||||
}
|
||||
cssRules += "}";
|
||||
return cssRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建主题
|
||||
* @param themeClass 主题类名
|
||||
|
|
@ -48,14 +64,8 @@ export function createTheme(
|
|||
//设置id属性,方便后面进行删除等操作
|
||||
styleSheet.id = id;
|
||||
|
||||
// 构建 CSS 规则
|
||||
let cssRules = `.${themeClass} {`;
|
||||
for (const variable in themeVariables) {
|
||||
if (themeVariables.hasOwnProperty(variable)) {
|
||||
cssRules += `--${variable}: ${themeVariables[variable]};`;
|
||||
}
|
||||
}
|
||||
cssRules += "}";
|
||||
// // 构建 CSS 规则
|
||||
const cssRules = generateCssText(themeClass, themeVariables);
|
||||
|
||||
// 插入 CSS 规则到样式表中
|
||||
if ((styleSheet as any).styleSheet) {
|
||||
|
|
@ -68,6 +78,14 @@ export function createTheme(
|
|||
// 将样式表添加到文档头部
|
||||
document.head.appendChild(styleSheet);
|
||||
|
||||
if (themeClass === themeMap.light) {
|
||||
themeLightCache.obj = themeVariables;
|
||||
}
|
||||
|
||||
if (themeClass === themeMap.dark) {
|
||||
themeDarkCache.obj = themeVariables;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
@ -371,10 +389,10 @@ const themeMap = {
|
|||
*/
|
||||
export const createLightTheme = (themeVariables: ThemeVariables) => {
|
||||
return useDebounce(() => {
|
||||
if (themeLightId) {
|
||||
document.getElementById(themeLightId)?.remove();
|
||||
if (themeLightCache.id) {
|
||||
document.getElementById(themeLightCache.id)?.remove();
|
||||
}
|
||||
themeLightId = createTheme(themeMap.light, themeVariables);
|
||||
themeLightCache.id = createTheme(themeMap.light, themeVariables);
|
||||
}, 50)();
|
||||
};
|
||||
|
||||
|
|
@ -385,10 +403,10 @@ export const createLightTheme = (themeVariables: ThemeVariables) => {
|
|||
*/
|
||||
export const createDarkTheme = (themeVariables: ThemeVariables) => {
|
||||
return useDebounce(() => {
|
||||
if (themeDarkId) {
|
||||
document.getElementById(themeDarkId)?.remove();
|
||||
if (themeDarkCache.id) {
|
||||
document.getElementById(themeDarkCache.id)?.remove();
|
||||
}
|
||||
themeDarkId = createTheme(themeMap.dark, themeVariables);
|
||||
themeDarkCache.id = createTheme(themeMap.dark, themeVariables);
|
||||
}, 50)();
|
||||
};
|
||||
|
||||
|
|
@ -410,17 +428,23 @@ export const getColorAsync = async () => {
|
|||
/**
|
||||
* 主题ID
|
||||
*/
|
||||
let themeLightId: string | null = null;
|
||||
let themeDarkId: string | null = null;
|
||||
const themeLightCache: ThemeBlockCache = {
|
||||
id: "",
|
||||
obj: {},
|
||||
};
|
||||
const themeDarkCache: ThemeBlockCache = {
|
||||
id: "",
|
||||
obj: {},
|
||||
};
|
||||
|
||||
// 在退出的时候删除这两个主题,防止重复加载
|
||||
window.addEventListener("unload", () => {
|
||||
setTimeout(() => {
|
||||
if (themeLightId) {
|
||||
document.getElementById(themeLightId)?.remove();
|
||||
if (themeLightCache.id) {
|
||||
document.getElementById(themeLightCache.id)?.remove();
|
||||
}
|
||||
if (themeDarkId) {
|
||||
document.getElementById(themeDarkId)?.remove();
|
||||
if (themeDarkCache.id) {
|
||||
document.getElementById(themeDarkCache.id)?.remove();
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
|
@ -431,14 +455,71 @@ window.addEventListener("unload", () => {
|
|||
*/
|
||||
export const changeThemeSchema = (schema: ColorSchema) => {
|
||||
// 通过id删除原有的主题,然后重新生成
|
||||
if (themeLightId) {
|
||||
document.getElementById(themeLightId)?.remove();
|
||||
if (themeLightCache.id) {
|
||||
// document.getElementById(themeLightId)?.remove();
|
||||
updateThemeBlock("light", schema.onLight);
|
||||
} else {
|
||||
themeLightCache.id = createTheme(themeMap.light, schema.onLight);
|
||||
}
|
||||
if (themeDarkId) {
|
||||
document.getElementById(themeDarkId)?.remove();
|
||||
if (themeDarkCache.id) {
|
||||
// document.getElementById(themeDarkId)?.remove();
|
||||
updateThemeBlock("dark", schema.onDark!);
|
||||
} else {
|
||||
themeDarkCache.id = createTheme(themeMap.dark, schema.onDark!);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据对象更新关系检查来更新主题块
|
||||
* @param mode 主题模式
|
||||
* @param colors 主题颜色
|
||||
* @returns 主题块
|
||||
*/
|
||||
export const updateThemeBlock = (mode: ThemeMode, colors: ThemeVariables) => {
|
||||
// 通过id拿到block然后更新里面的内容
|
||||
const id = mode == "light" ? themeLightCache.id : themeDarkCache.id;
|
||||
|
||||
if (!id) {
|
||||
throw new Error("Theme ID not found");
|
||||
return;
|
||||
}
|
||||
const block = document.getElementById(id);
|
||||
if (block) {
|
||||
const innerText = block.innerText;
|
||||
let result;
|
||||
if (mode == "light") {
|
||||
result = compareObjects(themeLightCache.obj, colors);
|
||||
} else {
|
||||
result = compareObjects(themeDarkCache.obj, colors);
|
||||
}
|
||||
|
||||
if (!(result && result.length)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newText = innerText;
|
||||
|
||||
result.forEach((item) => {
|
||||
switch (item.type) {
|
||||
case "update":
|
||||
const regUpdate = new RegExp(`--${item.key}:.*?;`, "g");
|
||||
newText = innerText.replace(
|
||||
regUpdate,
|
||||
`--${item.key}: ${colors[item.key]};`
|
||||
);
|
||||
break;
|
||||
case "remove":
|
||||
const regRemove = new RegExp(`--${item.key}:.*?;`, "g");
|
||||
newText = innerText.replace(regRemove, "");
|
||||
break;
|
||||
case "add":
|
||||
newText = `${innerText}\n--${item.key}: ${colors[item.key]};`;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
block.innerText = newText;
|
||||
}
|
||||
themeLightId = createTheme(themeMap.light, schema.onLight);
|
||||
themeDarkId = createTheme(themeMap.dark, schema.onDark!);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -44,3 +44,17 @@ export type ThemeSection = "dark" | "light" | "system";
|
|||
export type ReverseHandlerType = "reverse" | "none" | "lighten" | "darken";
|
||||
|
||||
export type ReverseHandlerConfig = Record<string, ReverseHandlerType>;
|
||||
|
||||
export type ThemeMode = "dark" | "light";
|
||||
|
||||
export type ThemeBlockCache = {
|
||||
id: string;
|
||||
obj: Record<string, string>;
|
||||
};
|
||||
|
||||
export type ChangeType = "update" | "remove" | "add";
|
||||
|
||||
export type Change = {
|
||||
key: string;
|
||||
type: ChangeType;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue