summaryrefslogtreecommitdiff
path: root/source/js/script.ts
diff options
context:
space:
mode:
Diffstat (limited to 'source/js/script.ts')
-rw-r--r--source/js/script.ts168
1 files changed, 146 insertions, 22 deletions
diff --git a/source/js/script.ts b/source/js/script.ts
index 912c1d9..bfc1d64 100644
--- a/source/js/script.ts
+++ b/source/js/script.ts
@@ -17,73 +17,197 @@ window.addEventListener("load", () => {
}
// Add header hover page class changer
- const colorman = (mode: SystemDarkmodePrefrence) => {
+ const colorman = (mode: SystemDarkmodePreference) => {
let clsname: string = ".auto-dark";
const elements: Element[] = Array.prototype.slice.call(
document.querySelectorAll(clsname), 0);
elements.forEach((element) => {
- if (mode === SystemDarkmodePrefrence.dark) {
+ if (mode === SystemDarkmodePreference.dark) {
element?.classList.add("is-dark");
element?.classList.remove("is-light");
} else {
+ // If mode == null , fallback to light mode
element?.classList.add("is-light");
element?.classList.remove("is-dark");
}
})
+ console.debug(`${clsname} class changed to ${enumModeToStringMode(mode)}`);
}
darklistener.add(colorman);
// Add logo color selector
- const logoman = (mode: SystemDarkmodePrefrence) => {
+ const logoman = (mode: SystemDarkmodePreference) => {
const logo = document.getElementById("logo");
const darksrc = logo?.getAttribute("data-src-darkmode");
const lightsrc = logo?.getAttribute("data-src-lightmode");
if (!logo || !darksrc || !lightsrc)
return;
- let src = (mode === SystemDarkmodePrefrence.dark) ? darksrc : lightsrc;
+ let src = (mode === SystemDarkmodePreference.dark) ? darksrc : lightsrc;
logo.setAttribute("src", src);
+ console.debug(`logo src changed to ${enumModeToStringMode(mode)}src`);
}
darklistener.add(logoman);
-
+
+ // Add player theme handler
+ const playerman = (mode: SystemDarkmodePreference) => {
+ const shikwasa = document.body.querySelector('div[data-name="shikwasa"]');
+ shikwasa?.setAttribute("data-theme", enumModeToStringMode(mode) ? enumModeToStringMode(mode)! : "light");
+ console.debug(`shikwasa theme: ${shikwasa?.getAttribute("data-theme")}`);
+ };
+ darklistener.add(playerman);
+
+ // Listen after all the setups (to get the handler work :p).
+ darklistener.listen();
});
/* Darkmode listener */
-enum SystemDarkmodePrefrence {
+enum SystemDarkmodePreference {
dark = 0,
light = 1
};
+const modeMap = {
+ dark: SystemDarkmodePreference.dark,
+ light: SystemDarkmodePreference.light
+};
+
+const invertDarkModeObj: Object = {
+ 'dark': 'light',
+ 'light': 'dark'
+};
+
+const enumModeToStringMode = (i: SystemDarkmodePreference) => {
+ let keysArray = Object.keys(modeMap);
+ let result = keysArray.filter(key => isValidKey(key, modeMap) && modeMap[key] === i);
+ return result ? result[0] : undefined;
+};
+
class DarkmodeListener {
- private _mode: SystemDarkmodePrefrence;
- private _handlers: ((mode: SystemDarkmodePrefrence) => void)[];
+ private _mode: SystemDarkmodePreference;
+ private _handlers: ((mode: SystemDarkmodePreference) => void)[];
public constructor() {
let darking = window.matchMedia('(prefers-color-scheme: dark)').matches;
- this._mode = darking ? SystemDarkmodePrefrence.dark : SystemDarkmodePrefrence.light;
+ this._mode = darking ? SystemDarkmodePreference.dark : SystemDarkmodePreference.light;
this._handlers = [];
- this._listen();
}
- private _listen(): void {
- let media = window.matchMedia('(prefers-color-scheme: dark)');
- let callback = (event: MediaQueryListEvent) => {
- let mode = event.matches ? SystemDarkmodePrefrence.dark : SystemDarkmodePrefrence.light;
- this._handlers.forEach(handler => {
- handler(mode);
- });
- this._mode = mode;
- };
- media.addEventListener("change", callback);
+ public listen(): void {
+ const rootElement = document.documentElement;
+ const darkModeStorageKey = 'user-color-scheme';
+ const rootElementDarkModeAttributeName = 'data-user-color-scheme';
+ const darkModeTogglebuttonElement = document.getElementById('btn-toggle-dark');
+
+ const resetRootDarkModeAttributeAndLS = () => {
+ rootElement.removeAttribute(rootElementDarkModeAttributeName);
+ removeLS(darkModeStorageKey);
+ }
+
+ // Partially taken from https://blog.skk.moe/post/hello-darkmode-my-old-friend, CC BY-NC-SA 4.0
+ const applyCustomDarkModeSettings = (mode: any) => {
+ // 接受从「开关」处传来的模式,或者从 localStorage 读取
+ let LSSetting = getLS(darkModeStorageKey) == 'dark' ? SystemDarkmodePreference.dark : 'light' ? SystemDarkmodePreference.light : null;
+ let currentSetting: SystemDarkmodePreference = mode || LSSetting;
+ console.debug(`applyCustomDarkModeSettings: ${currentSetting}`);
+ if (currentSetting === this._mode) {
+ // 当用户自定义的显示模式和 prefers-color-scheme 相同时重置、恢复到自动模式
+ resetRootDarkModeAttributeAndLS();
+ console.debug('Resetting to auto mode...');
+ } else if (currentSetting == SystemDarkmodePreference.dark || currentSetting == SystemDarkmodePreference.light) {
+ // 否则设置为用户自定义的显示模式
+ rootElement.setAttribute(rootElementDarkModeAttributeName, enumModeToStringMode(currentSetting)!);
+ console.debug('Setting prop: "data-user-color-scheme" in HTML...');
+ } else {
+ // 首次访问或从未使用过开关、localStorage 中没有存储的值,currentSetting 是 null
+ // 或者 localStorage 被篡改,currentSetting 不是合法值
+ // 默认显示浅色主题
+ resetRootDarkModeAttributeAndLS();
+ console.debug('Initial setup, setting theme to light as default...')
+ currentSetting = SystemDarkmodePreference.light;
+ }
+ let lightCSS = document.getElementById("bulma-light")!
+ let darkCSS = document.getElementById("bulma-dark")!
+ if (currentSetting == SystemDarkmodePreference.dark) {
+ rootElement.setAttribute(rootElementDarkModeAttributeName, 'dark');
+ lightCSS.setAttribute("media", "none");
+ darkCSS.setAttribute("media", "all");
+ this._handlers.forEach(handler => {
+ handler(SystemDarkmodePreference.dark);
+ console.debug('Invoking dark theme handler...');
+ });
+ console.debug('Dark theme applied.');
+ } else if (currentSetting == SystemDarkmodePreference.light) {
+ rootElement.setAttribute(rootElementDarkModeAttributeName, 'light');
+ lightCSS.setAttribute("media", "all");
+ darkCSS.setAttribute("media", "none");
+ this._handlers.forEach(handler => {
+ handler(SystemDarkmodePreference.light);
+ console.debug('Invoking light theme handler...');
+ });
+ console.debug('Light theme applied.');
+ }
+
+ }
+
+ const toggleCustomDarkMode = () => {
+ let currentSetting = getLS(darkModeStorageKey);
+ if (currentSetting === null) {
+ let curMode = enumModeToStringMode(this._mode)!;
+ currentSetting = isValidKey(curMode, invertDarkModeObj) ? invertDarkModeObj[curMode] : currentSetting;
+ } else if (currentSetting == 'dark' || 'light') {
+ // 从 localStorage 中读取模式,并取相反的模式
+ currentSetting = isValidKey(currentSetting, invertDarkModeObj) ? invertDarkModeObj[currentSetting] : currentSetting;
+ } else {
+ // 不知道出了什么幺蛾子,比如 localStorage 被篡改成非法值
+ return; // 直接 return;
+ }
+ // 将相反的模式写入 localStorage
+ setLS(darkModeStorageKey, currentSetting);
+ return isValidKey(currentSetting!, invertDarkModeObj) ? modeMap[currentSetting!] : null;
+ }
+
+ applyCustomDarkModeSettings(null);
+
+ darkModeTogglebuttonElement?.addEventListener('click', () => {
+ // 当用户点击「开关」时,获得新的显示模式、写入 localStorage、并在页面上生效
+ console.debug('User clicked button. Doing black magic now...');
+ applyCustomDarkModeSettings(toggleCustomDarkMode());
+ });
}
- public add(callback: (mode: SystemDarkmodePrefrence) => void): void {
+ public add(callback: (mode: SystemDarkmodePreference) => void): void {
callback(this._mode);
this._handlers.push(callback);
}
- public mode(): SystemDarkmodePrefrence {
+ public mode(): SystemDarkmodePreference {
return this._mode;
}
};
var darklistener = new DarkmodeListener();
+
+function setLS(k: string, v: any) {
+ try {
+ localStorage.setItem(k, v);
+ } catch (e) { }
+}
+
+function removeLS(k: string) {
+ try {
+ localStorage.removeItem(k);
+ } catch (e) { }
+}
+
+function getLS(k: string) {
+ try {
+ return localStorage.getItem(k);
+ } catch (e) {
+ return null; // 与 localStorage 中没有找到对应 key 的行为一致
+ }
+}
+
+// 使用isValidKey判断key是否存在对象类型中
+function isValidKey(key: string, obj: object): key is keyof typeof obj {
+ return key in obj;
+} \ No newline at end of file