summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author135e2 <[email protected]>2022-06-01 22:46:14 +0800
committer135e2 <[email protected]>2022-06-01 22:46:14 +0800
commitebcd72e6253ca7e2a90f8116f736ad12307f98bb (patch)
tree4b1c94c04b6608b724bea6876f8c116f47cde043
parenteb8a7b323891b870ddda677fa43e583c7477803d (diff)
parent762bdc4aae407afe1c00ae1e9b438e0e5807f1cd (diff)
downloadchromate-ebcd72e6253ca7e2a90f8116f736ad12307f98bb.tar.gz
chromate-ebcd72e6253ca7e2a90f8116f736ad12307f98bb.tar.bz2
chromate-ebcd72e6253ca7e2a90f8116f736ad12307f98bb.zip
Merge branch 'experimental' into dev
Conflicts: layout/_partial/head.ejs
-rw-r--r--layout/_partial/head.ejs6
-rw-r--r--layout/_partial/header.ejs3
-rw-r--r--layout/_partial/scripts.ejs3
-rw-r--r--layout/post.ejs4
-rw-r--r--source/css/style.css44
-rw-r--r--source/css/style.min.css2
-rw-r--r--source/js/script.js155
-rw-r--r--source/js/script.min.js2
-rw-r--r--source/js/script.ts168
9 files changed, 329 insertions, 58 deletions
diff --git a/layout/_partial/head.ejs b/layout/_partial/head.ejs
index e56722d..ed4f8d7 100644
--- a/layout/_partial/head.ejs
+++ b/layout/_partial/head.ejs
@@ -33,6 +33,6 @@
<!-- Scripts and styles -->
<%- css('css/style.min.css') %>
- <link rel="stylesheet" href="https://cdn.staticfile.org/bulma/0.9.4/css/bulma.min.css">
- <link media="(prefers-color-scheme: dark)" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jloh/bulma-prefers-dark/css/bulma-prefers-dark.min.css">
-</head>
+ <link rel="stylesheet" id="bulma-light" href="https://cdn.jsdelivr.net/npm/bulma/css/bulma.min.css">
+ <link rel="stylesheet" id="bulma-dark" href="https://cdn.jsdelivr.net/npm/[email protected]/darkly/bulmaswatch.min.css">
+</head> \ No newline at end of file
diff --git a/layout/_partial/header.ejs b/layout/_partial/header.ejs
index b32edbb..6c423a0 100644
--- a/layout/_partial/header.ejs
+++ b/layout/_partial/header.ejs
@@ -18,6 +18,9 @@
</div>
<div class="navbar-menu" id="header-menu">
<div class="navbar-end">
+ <a class="navbar-item" href="javaScript:void(0);" id="btn-toggle-dark">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
+ </a>
<% for (let item of theme.menubar) { %>
<a class="navbar-item is-uppercase" href="<%= item[0] %>">
<%= item[1] %>
diff --git a/layout/_partial/scripts.ejs b/layout/_partial/scripts.ejs
index a242775..14348a9 100644
--- a/layout/_partial/scripts.ejs
+++ b/layout/_partial/scripts.ejs
@@ -24,13 +24,14 @@
<script>
window.addEventListener("load", () => {
const theme_selector = (mode) => {
- if (mode === SystemDarkmodePrefrence.dark) {
+ if (mode === SystemDarkmodePreference.dark) {
document.getElementById("highlight-light-theme").setAttribute("disabled", "disabled");
document.getElementById("highlight-dark-theme").removeAttribute("disabled");
} else {
document.getElementById("highlight-dark-theme").setAttribute("disabled", "disabled");
document.getElementById("highlight-light-theme").removeAttribute("disabled");
}
+ console.debug(`highlightjs theme set to ${mode}`);
};
darklistener.add(theme_selector);
}, false);
diff --git a/layout/post.ejs b/layout/post.ejs
index 9befb97..3428ddf 100644
--- a/layout/post.ejs
+++ b/layout/post.ejs
@@ -63,7 +63,7 @@
const player = new Shikwasa({
container: () => document.querySelector('.post-podcast-player'),
- audio: {
+ audio: {
title: "<%= page.title %>",
artist: "<%= page.podcast.authors %>",
cover: "<%= page.podcast.cover %>",
@@ -82,7 +82,7 @@
window.player = player;
}, false);
</script>
- <% } %>
+ <% } %>
<section class="content is-size-6">
<%- page.content %>
</section>
diff --git a/source/css/style.css b/source/css/style.css
index 3a9430f..5a62406 100644
--- a/source/css/style.css
+++ b/source/css/style.css
@@ -8,19 +8,45 @@ pre {
-webkit-filter: grayscale(1) !important;
}
+:root {
+ --transition-speed: unset;
+ --background-color: white;
+ --brightness: 1;
+ --contrast: 1;
+}
+
@media(prefers-color-scheme:dark) {
- * {
- transition: backgourd-color .5s
- }
- .card {
- box-shadow: none!important;
- background-color: #121212!important
- }
- img:not([src*=".svg"]) {
- filter: brightness(.7) contrast(1.2);
+
+ :root:not([data-user-color-scheme]) {
+ --box-shadow: none!important;
+ --transition-speed: 0.5s;
+ --background-color: #121212!important;
+ --brightness: 0.7;
+ --contrast: 1.2;
}
}
+[data-user-color-scheme='dark'] {
+ --box-shadow: none!important;
+ --transition-speed: 0.5s;
+ --background-color: #121212!important;
+ --brightness: 0.7;
+ --contrast: 1.2;
+}
+
+* {
+ transition: backgourd-color var(--transition-speed);
+}
+
+.card {
+ box-shadow: var(--box-shadow);
+ background-color: var(--background-color);
+}
+
+img:not([src*=".svg"]) {
+ filter: brightness(--brightness) contrast(--contrast);
+}
+
@media screen and (max-width:1023px) {
.navbar-menu {
box-shadow: 0 8px 16px -8px rgb(10 10 10 / 10%)!important
diff --git a/source/css/style.min.css b/source/css/style.min.css
index d8c3a0b..ac94b6b 100644
--- a/source/css/style.min.css
+++ b/source/css/style.min.css
@@ -1 +1 @@
-pre{background-color:none!important;padding:0!important}#mourn{filter:grayscale(1)!important;-webkit-filter:grayscale(1)!important}@media(prefers-color-scheme:dark){*{transition:backgourd-color .5s}.card{box-shadow:none!important;background-color:#121212!important}img:not([src*=".svg"]){filter:brightness(.7) contrast(1.2)}}@media screen and (max-width:1023px){.navbar-menu{box-shadow:0 8px 16px -8px rgb(10 10 10 / 10%)!important}.post-content{padding-top:0!important}.post-card{margin:0!important}}.post-podcast-player{padding-bottom:1.5rem}.post-card{margin:0 1rem 0 1rem}.navbar-brand .navbar-item:hover{background-color:inherit!important}.entry{margin-bottom:1.5rem!important;margin-top:1.5rem!important;transition:box-shadow .1s}.entry:hover{box-shadow:0 1em 2em -.125em rgb(10 10 10 / 10%),0 0 0 1px rgb(10 10 10 / 2%)}.pagination-bar{padding-left:.25rem;padding-right:.25rem}.footer{padding:1rem 1rem 1rem!important;background-color:transparent!important}.subnav-top{border-bottom:1px solid;padding-bottom:1rem;display:inline}.subnav-bottom{margin-top:1.6rem!important} \ No newline at end of file
+pre{background-color:none!important;padding:0!important}#mourn{filter:grayscale(1)!important;-webkit-filter:grayscale(1)!important}:root{--transition-speed:unset;--background-color:white;--brightness:1;--contrast:1}@media(prefers-color-scheme:dark){:root:not([data-user-color-scheme]){--box-shadow:none!important;--transition-speed:0.5s;--background-color:#121212!important;--brightness:0.7;--contrast:1.2}}[data-user-color-scheme=dark]{--box-shadow:none!important;--transition-speed:0.5s;--background-color:#121212!important;--brightness:0.7;--contrast:1.2}*{transition:backgourd-color var(--transition-speed)}.card{box-shadow:var(--box-shadow);background-color:var(--background-color)}img:not([src*=".svg"]){filter:brightness(--brightness) contrast(--contrast)}@media screen and (max-width:1023px){.navbar-menu{box-shadow:0 8px 16px -8px rgb(10 10 10 / 10%)!important}.post-content{padding-top:0!important}.post-card{margin:0!important}}.post-podcast-player{padding-bottom:1.5rem}.post-card{margin:0 1rem 0 1rem}.navbar-brand .navbar-item:hover{background-color:inherit!important}.entry{margin-bottom:1.5rem!important;margin-top:1.5rem!important;transition:box-shadow .1s}.entry:hover{box-shadow:0 1em 2em -.125em rgb(10 10 10 / 10%),0 0 0 1px rgb(10 10 10 / 2%)}.pagination-bar{padding-left:.25rem;padding-right:.25rem}.footer{padding:1rem 1rem 1rem!important;background-color:transparent!important}.subnav-top{border-bottom:1px solid;padding-bottom:1rem;display:inline}.subnav-bottom{margin-top:1.5rem!important} \ No newline at end of file
diff --git a/source/js/script.js b/source/js/script.js
index 8a3daa5..665d379 100644
--- a/source/js/script.js
+++ b/source/js/script.js
@@ -1,4 +1,3 @@
-"use strict";
/* Add elements listener */
window.addEventListener("load", function () {
// Menubar burgers click listenr
@@ -20,15 +19,17 @@ window.addEventListener("load", function () {
var clsname = ".auto-dark";
var elements = Array.prototype.slice.call(document.querySelectorAll(clsname), 0);
elements.forEach(function (element) {
- if (mode === SystemDarkmodePrefrence.dark) {
+ if (mode === SystemDarkmodePreference.dark) {
element === null || element === void 0 ? void 0 : element.classList.add("is-dark");
element === null || element === void 0 ? void 0 : element.classList.remove("is-light");
}
else {
+ // If mode == null , fallback to light mode
element === null || element === void 0 ? void 0 : element.classList.add("is-light");
element === null || element === void 0 ? void 0 : element.classList.remove("is-dark");
}
});
+ console.debug("".concat(clsname, " class changed to ").concat(enumModeToStringMode(mode)));
};
darklistener.add(colorman);
// Add logo color selector
@@ -38,36 +39,128 @@ window.addEventListener("load", function () {
var lightsrc = logo === null || logo === void 0 ? void 0 : logo.getAttribute("data-src-lightmode");
if (!logo || !darksrc || !lightsrc)
return;
- var src = (mode === SystemDarkmodePrefrence.dark) ? darksrc : lightsrc;
+ var src = (mode === SystemDarkmodePreference.dark) ? darksrc : lightsrc;
logo.setAttribute("src", src);
+ console.debug("logo src changed to ".concat(enumModeToStringMode(mode), "src"));
};
darklistener.add(logoman);
+ // Add player theme handler
+ var playerman = function (mode) {
+ var shikwasa = document.body.querySelector('div[data-name="shikwasa"]');
+ shikwasa === null || shikwasa === void 0 ? void 0 : shikwasa.setAttribute("data-theme", enumModeToStringMode(mode) ? enumModeToStringMode(mode) : "light");
+ console.debug("shikwasa theme: ".concat(shikwasa === null || shikwasa === void 0 ? void 0 : shikwasa.getAttribute("data-theme")));
+ };
+ darklistener.add(playerman);
+ // Listen after all the setups (to get the handler work :p).
+ darklistener.listen();
});
/* Darkmode listener */
-var SystemDarkmodePrefrence;
-(function (SystemDarkmodePrefrence) {
- SystemDarkmodePrefrence[SystemDarkmodePrefrence["dark"] = 0] = "dark";
- SystemDarkmodePrefrence[SystemDarkmodePrefrence["light"] = 1] = "light";
-})(SystemDarkmodePrefrence || (SystemDarkmodePrefrence = {}));
+var SystemDarkmodePreference;
+(function (SystemDarkmodePreference) {
+ SystemDarkmodePreference[SystemDarkmodePreference["dark"] = 0] = "dark";
+ SystemDarkmodePreference[SystemDarkmodePreference["light"] = 1] = "light";
+})(SystemDarkmodePreference || (SystemDarkmodePreference = {}));
;
+var modeMap = {
+ dark: SystemDarkmodePreference.dark,
+ light: SystemDarkmodePreference.light
+};
+var invertDarkModeObj = {
+ 'dark': 'light',
+ 'light': 'dark'
+};
+var enumModeToStringMode = function (i) {
+ var keysArray = Object.keys(modeMap);
+ var result = keysArray.filter(function (key) { return isValidKey(key, modeMap) && modeMap[key] === i; });
+ return result ? result[0] : undefined;
+};
var DarkmodeListener = /** @class */ (function () {
function DarkmodeListener() {
var 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();
}
- DarkmodeListener.prototype._listen = function () {
+ DarkmodeListener.prototype.listen = function () {
var _this = this;
- var media = window.matchMedia('(prefers-color-scheme: dark)');
- var callback = function (event) {
- var mode = event.matches ? SystemDarkmodePrefrence.dark : SystemDarkmodePrefrence.light;
- _this._handlers.forEach(function (handler) {
- handler(mode);
- });
- _this._mode = mode;
+ var rootElement = document.documentElement;
+ var darkModeStorageKey = 'user-color-scheme';
+ var rootElementDarkModeAttributeName = 'data-user-color-scheme';
+ var darkModeTogglebuttonElement = document.getElementById('btn-toggle-dark');
+ var resetRootDarkModeAttributeAndLS = function () {
+ rootElement.removeAttribute(rootElementDarkModeAttributeName);
+ removeLS(darkModeStorageKey);
+ };
+ // Partially taken from https://blog.skk.moe/post/hello-darkmode-my-old-friend, CC BY-NC-SA 4.0
+ var applyCustomDarkModeSettings = function (mode) {
+ // 接受从「开关」处传来的模式,或者从 localStorage 读取
+ var LSSetting = getLS(darkModeStorageKey) == 'dark' ? SystemDarkmodePreference.dark : 'light' ? SystemDarkmodePreference.light : null;
+ var currentSetting = mode || LSSetting;
+ console.debug("applyCustomDarkModeSettings: ".concat(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;
+ }
+ var lightCSS = document.getElementById("bulma-light");
+ var darkCSS = document.getElementById("bulma-dark");
+ if (currentSetting == SystemDarkmodePreference.dark) {
+ rootElement.setAttribute(rootElementDarkModeAttributeName, 'dark');
+ lightCSS.setAttribute("media", "none");
+ darkCSS.setAttribute("media", "all");
+ _this._handlers.forEach(function (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(function (handler) {
+ handler(SystemDarkmodePreference.light);
+ console.debug('Invoking light theme handler...');
+ });
+ console.debug('Light theme applied.');
+ }
+ };
+ var toggleCustomDarkMode = function () {
+ var currentSetting = getLS(darkModeStorageKey);
+ if (currentSetting === null) {
+ var 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;
};
- media.addEventListener("change", callback);
+ applyCustomDarkModeSettings(null);
+ darkModeTogglebuttonElement === null || darkModeTogglebuttonElement === void 0 ? void 0 : darkModeTogglebuttonElement.addEventListener('click', function () {
+ // 当用户点击「开关」时,获得新的显示模式、写入 localStorage、并在页面上生效
+ console.debug('User clicked button. Doing black magic now...');
+ applyCustomDarkModeSettings(toggleCustomDarkMode());
+ });
};
DarkmodeListener.prototype.add = function (callback) {
callback(this._mode);
@@ -80,3 +173,27 @@ var DarkmodeListener = /** @class */ (function () {
}());
;
var darklistener = new DarkmodeListener();
+function setLS(k, v) {
+ try {
+ localStorage.setItem(k, v);
+ }
+ catch (e) { }
+}
+function removeLS(k) {
+ try {
+ localStorage.removeItem(k);
+ }
+ catch (e) { }
+}
+function getLS(k) {
+ try {
+ return localStorage.getItem(k);
+ }
+ catch (e) {
+ return null; // 与 localStorage 中没有找到对应 key 的行为一致
+ }
+}
+// 使用isValidKey判断key是否存在对象类型中
+function isValidKey(key, obj) {
+ return key in obj;
+}
diff --git a/source/js/script.min.js b/source/js/script.min.js
index 487569f..823246f 100644
--- a/source/js/script.min.js
+++ b/source/js/script.min.js
@@ -1 +1 @@
-"use strict"; window.addEventListener("load", function () { var a = Array.prototype.slice.call(document.querySelectorAll(".navbar-burger"), 0); if (a.length > 0) { a.forEach(function (d) { d.addEventListener("click", function () { var f = d.getAttribute("data-target"); d.classList.toggle("is-active"); if (!f) { return } var e = document.getElementById(f); e === null || e === void 0 ? void 0 : e.classList.toggle("is-active") }, false) }) } var c = function (f) { var e = ".auto-dark"; var d = Array.prototype.slice.call(document.querySelectorAll(e), 0); d.forEach(function (g) { if (f === SystemDarkmodePrefrence.dark) { g === null || g === void 0 ? void 0 : g.classList.add("is-dark"); g === null || g === void 0 ? void 0 : g.classList.remove("is-light") } else { g === null || g === void 0 ? void 0 : g.classList.add("is-light"); g === null || g === void 0 ? void 0 : g.classList.remove("is-dark") } }) }; darklistener.add(c); var b = function (h) { var e = document.getElementById("logo"); var g = e === null || e === void 0 ? void 0 : e.getAttribute("data-src-darkmode"); var d = e === null || e === void 0 ? void 0 : e.getAttribute("data-src-lightmode"); if (!e || !g || !d) { return } var f = (h === SystemDarkmodePrefrence.dark) ? g : d; e.setAttribute("src", f) }; darklistener.add(b) }); var SystemDarkmodePrefrence; (function (a) { a[a["dark"] = 0] = "dark"; a[a["light"] = 1] = "light" })(SystemDarkmodePrefrence || (SystemDarkmodePrefrence = {})); var DarkmodeListener = (function () { function a() { var b = window.matchMedia("(prefers-color-scheme: dark)").matches; this._mode = b ? SystemDarkmodePrefrence.dark : SystemDarkmodePrefrence.light; this._handlers = []; this._listen() } a.prototype._listen = function () { var d = this; var b = window.matchMedia("(prefers-color-scheme: dark)"); var c = function (e) { var f = e.matches ? SystemDarkmodePrefrence.dark : SystemDarkmodePrefrence.light; d._handlers.forEach(function (g) { g(f) }); d._mode = f }; b.addEventListener("change", c) }; a.prototype.add = function (b) { b(this._mode); this._handlers.push(b) }; a.prototype.mode = function () { return this._mode }; return a }()); var darklistener = new DarkmodeListener(); \ No newline at end of file
+window.addEventListener("load",function(){var burgers=Array.prototype.slice.call(document.querySelectorAll(".navbar-burger"),0);0<burgers.length&&burgers.forEach(function(element){element.addEventListener("click",function(){var idstr=element.getAttribute("data-target");element.classList.toggle("is-active"),!idstr||null!=(idstr=document.getElementById(idstr))&&idstr.classList.toggle("is-active")},!1)}),darklistener.add(function(mode){Array.prototype.slice.call(document.querySelectorAll(".auto-dark"),0).forEach(function(element){mode===SystemDarkmodePreference.dark?(null!=element&&element.classList.add("is-dark"),null!=element&&element.classList.remove("is-light")):(null!=element&&element.classList.add("is-light"),null!=element&&element.classList.remove("is-dark"))}),console.debug("".concat(".auto-dark"," class changed to ").concat(enumModeToStringMode(mode)))}),darklistener.add(function(mode){var logo=document.getElementById("logo"),darksrc=null==logo?void 0:logo.getAttribute("data-src-darkmode"),lightsrc=null==logo?void 0:logo.getAttribute("data-src-lightmode");logo&&darksrc&&lightsrc&&(darksrc=mode===SystemDarkmodePreference.dark?darksrc:lightsrc,logo.setAttribute("src",darksrc),console.debug("logo src changed to ".concat(enumModeToStringMode(mode),"src")))});darklistener.add(function(mode){var shikwasa=document.body.querySelector('div[data-name="shikwasa"]');null!=shikwasa&&shikwasa.setAttribute("data-theme",enumModeToStringMode(mode)?enumModeToStringMode(mode):"light"),console.debug("shikwasa theme: ".concat(null==shikwasa?void 0:shikwasa.getAttribute("data-theme")))}),darklistener.listen()}),function(SystemDarkmodePreference){SystemDarkmodePreference[SystemDarkmodePreference.dark=0]="dark",SystemDarkmodePreference[SystemDarkmodePreference.light=1]="light"}(SystemDarkmodePreference=SystemDarkmodePreference||{});var SystemDarkmodePreference,modeMap={dark:SystemDarkmodePreference.dark,light:SystemDarkmodePreference.light},invertDarkModeObj={dark:"light",light:"dark"},enumModeToStringMode=function(i){var result=Object.keys(modeMap).filter(function(key){return isValidKey(key,modeMap)&&modeMap[key]===i});return result?result[0]:void 0},DarkmodeListener=function(){function DarkmodeListener(){var darking=window.matchMedia("(prefers-color-scheme: dark)").matches;this._mode=darking?SystemDarkmodePreference.dark:SystemDarkmodePreference.light,this._handlers=[]}return DarkmodeListener.prototype.listen=function(){function applyCustomDarkModeSettings(mode){var LSSetting="dark"==getLS(darkModeStorageKey)?SystemDarkmodePreference.dark:SystemDarkmodePreference.light,mode=mode||LSSetting,LSSetting=(console.debug("applyCustomDarkModeSettings: ".concat(mode)),mode===_this._mode?(resetRootDarkModeAttributeAndLS(),console.debug("Resetting to auto mode...")):mode==SystemDarkmodePreference.dark||mode==SystemDarkmodePreference.light?(rootElement.setAttribute(rootElementDarkModeAttributeName,enumModeToStringMode(mode)),console.debug('Setting prop: "data-user-color-scheme" in HTML...')):(resetRootDarkModeAttributeAndLS(),console.debug("Initial setup, setting theme to light as default..."),mode=SystemDarkmodePreference.light),document.getElementById("bulma-light")),darkCSS=document.getElementById("bulma-dark");mode==SystemDarkmodePreference.dark?(rootElement.setAttribute(rootElementDarkModeAttributeName,"dark"),LSSetting.setAttribute("media","none"),darkCSS.setAttribute("media","all"),_this._handlers.forEach(function(handler){handler(SystemDarkmodePreference.dark),console.debug("Invoking dark theme handler...")}),console.debug("Dark theme applied.")):mode==SystemDarkmodePreference.light&&(rootElement.setAttribute(rootElementDarkModeAttributeName,"light"),LSSetting.setAttribute("media","all"),darkCSS.setAttribute("media","none"),_this._handlers.forEach(function(handler){handler(SystemDarkmodePreference.light),console.debug("Invoking light theme handler...")}),console.debug("Light theme applied."))}var _this=this,rootElement=document.documentElement,darkModeStorageKey="user-color-scheme",rootElementDarkModeAttributeName="data-user-color-scheme",darkModeTogglebuttonElement=document.getElementById("btn-toggle-dark"),resetRootDarkModeAttributeAndLS=function(){rootElement.removeAttribute(rootElementDarkModeAttributeName),removeLS(darkModeStorageKey)};applyCustomDarkModeSettings(null),null!=darkModeTogglebuttonElement&&darkModeTogglebuttonElement.addEventListener("click",function(){var curMode,currentSetting;console.debug("User clicked button. Doing black magic now..."),applyCustomDarkModeSettings((currentSetting=null===(currentSetting=getLS(darkModeStorageKey))?isValidKey(curMode=enumModeToStringMode(_this._mode),invertDarkModeObj)?invertDarkModeObj[curMode]:currentSetting:isValidKey(currentSetting,invertDarkModeObj)?invertDarkModeObj[currentSetting]:currentSetting,setLS(darkModeStorageKey,currentSetting),isValidKey(currentSetting,invertDarkModeObj)?modeMap[currentSetting]:null))})},DarkmodeListener.prototype.add=function(callback){callback(this._mode),this._handlers.push(callback)},DarkmodeListener.prototype.mode=function(){return this._mode},DarkmodeListener}(),darklistener=new DarkmodeListener;function setLS(k,v){try{localStorage.setItem(k,v)}catch(e){}}function removeLS(k){try{localStorage.removeItem(k)}catch(e){}}function getLS(k){try{return localStorage.getItem(k)}catch(e){return null}}function isValidKey(key,obj){return key in obj}
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