77 lines
2.3 KiB
JavaScript
77 lines
2.3 KiB
JavaScript
(function (window, document) {
|
||||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
var STORAGE_KEY = 'trafficpumper.theme';
|
|||
|
|
var DEFAULT_PREFERENCE = 'system';
|
|||
|
|
var VALID_PREFERENCES = ['light', 'dark', 'system'];
|
|||
|
|
var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|||
|
|
var preference = readPreference();
|
|||
|
|
|
|||
|
|
function isValid(value) {
|
|||
|
|
return VALID_PREFERENCES.indexOf(value) !== -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function readPreference() {
|
|||
|
|
try {
|
|||
|
|
var stored = window.localStorage.getItem(STORAGE_KEY);
|
|||
|
|
return isValid(stored) ? stored : DEFAULT_PREFERENCE;
|
|||
|
|
} catch (error) {
|
|||
|
|
return DEFAULT_PREFERENCE;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function resolve(value) {
|
|||
|
|
return value === 'system' ? (mediaQuery.matches ? 'dark' : 'light') : value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function apply() {
|
|||
|
|
var resolved = resolve(preference);
|
|||
|
|
document.documentElement.setAttribute('data-bs-theme', resolved);
|
|||
|
|
document.documentElement.style.colorScheme = resolved;
|
|||
|
|
|
|||
|
|
window.dispatchEvent(new window.CustomEvent('trafficpumper:theme-change', {
|
|||
|
|
detail: { preference: preference, resolved: resolved }
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
return resolved;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function setPreference(value) {
|
|||
|
|
if (!isValid(value)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
preference = value;
|
|||
|
|
try {
|
|||
|
|
window.localStorage.setItem(STORAGE_KEY, value);
|
|||
|
|
} catch (error) {
|
|||
|
|
// Depolama kapalıysa tema oturum boyunca yine çalışır.
|
|||
|
|
}
|
|||
|
|
apply();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function onSystemThemeChange() {
|
|||
|
|
if (preference === 'system') {
|
|||
|
|
apply();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (typeof mediaQuery.addEventListener === 'function') {
|
|||
|
|
mediaQuery.addEventListener('change', onSystemThemeChange);
|
|||
|
|
} else if (typeof mediaQuery.addListener === 'function') {
|
|||
|
|
mediaQuery.addListener(onSystemThemeChange);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.ThemeManager = Object.freeze({
|
|||
|
|
storageKey: STORAGE_KEY,
|
|||
|
|
getPreference: function () { return preference; },
|
|||
|
|
getResolvedTheme: function () { return resolve(preference); },
|
|||
|
|
setPreference: setPreference,
|
|||
|
|
apply: apply
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Bu dosya <head> içinde senkron çalıştığı için ilk boyadan önce uygulanır.
|
|||
|
|
apply();
|
|||
|
|
}(window, document));
|