mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-31 23:04:01 +08:00
74 lines
2.6 KiB
JavaScript
74 lines
2.6 KiB
JavaScript
(() => {
|
|
const root = document.documentElement;
|
|
const preference = matchMedia("(prefers-color-scheme: dark)");
|
|
const key = "ofdgo.theme";
|
|
let mode = root.dataset.themeMode || "system";
|
|
let material = root.dataset.windowChoice || "acrylic";
|
|
let host = null, report = null, pending = Promise.resolve(), revision = 0, committed = null;
|
|
if (!root.dataset.themeMode) {
|
|
try { mode = localStorage.getItem(key) || "system"; } catch {}
|
|
}
|
|
if (!["system", "light", "dark"].includes(mode)) mode = "system";
|
|
function apply() {
|
|
root.dataset.themeMode = mode;
|
|
root.dataset.theme = mode === "system" ? preference.matches ? "dark" : "light" : mode;
|
|
document.querySelector('meta[name="theme-color"]').content = root.dataset.theme === "dark" ? "#272e33" : "#fafbfc";
|
|
for (const button of document.querySelectorAll("[data-theme-choice]")) button.dataset.pressed = String(button.dataset.themeChoice === mode);
|
|
for (const button of document.querySelectorAll("[data-material-choice]")) button.dataset.pressed = String(button.dataset.materialChoice === material);
|
|
}
|
|
function sync() {
|
|
if (!host) return;
|
|
const value = {mode, dark: root.dataset.theme === "dark", material};
|
|
const current = ++revision;
|
|
pending = pending.then(() => host.call("appearance", value)).then(() => { committed = value; }).catch(error => {
|
|
if (current === revision) {
|
|
mode = committed.mode;
|
|
material = committed.material;
|
|
apply();
|
|
}
|
|
report(error);
|
|
});
|
|
}
|
|
async function flush() {
|
|
let current;
|
|
do {
|
|
current = pending;
|
|
await current;
|
|
} while (current !== pending);
|
|
}
|
|
function set(value) {
|
|
mode = value;
|
|
apply();
|
|
if (!host) {
|
|
try { localStorage.setItem(key, mode); } catch {}
|
|
}
|
|
sync();
|
|
}
|
|
preference.addEventListener("change", () => {
|
|
if (mode !== "system") return;
|
|
apply();
|
|
sync();
|
|
});
|
|
window.addEventListener("storage", event => {
|
|
if (host || event.key !== key && event.key !== null) return;
|
|
mode = ["light", "dark"].includes(event.newValue) ? event.newValue : "system";
|
|
apply();
|
|
});
|
|
window.ofdgoTheme = {set, flush, connect(value, onError) {
|
|
host = value;
|
|
report = onError;
|
|
const materials = (root.dataset.windowMaterials || "").split(",");
|
|
if (host && materials.length > 1) {
|
|
document.querySelector(".appearance-material").hidden = false;
|
|
for (const button of document.querySelectorAll("[data-material-choice]")) {
|
|
button.hidden = !materials.includes(button.dataset.materialChoice);
|
|
button.addEventListener("click", () => { material = button.dataset.materialChoice; apply(); sync(); });
|
|
}
|
|
}
|
|
apply();
|
|
sync();
|
|
}};
|
|
apply();
|
|
committed = {mode, material};
|
|
})();
|