2026-04-20 22:58:25 +02:00
|
|
|
window.workTrackerTheme = (() => {
|
|
|
|
|
const storageKey = "worktracker.themeMode";
|
|
|
|
|
const mediaQuery = window.matchMedia
|
|
|
|
|
? window.matchMedia("(prefers-color-scheme: dark)")
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
function normalize(mode) {
|
|
|
|
|
const normalized = (mode || "system").toString().toLowerCase();
|
|
|
|
|
return normalized === "light" || normalized === "dark" || normalized === "system"
|
|
|
|
|
? normalized
|
|
|
|
|
: "system";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function resolve(mode) {
|
|
|
|
|
if (mode === "system") {
|
|
|
|
|
return mediaQuery && mediaQuery.matches ? "dark" : "light";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function apply(mode) {
|
|
|
|
|
const normalized = normalize(mode);
|
|
|
|
|
const effectiveMode = resolve(normalized);
|
|
|
|
|
|
|
|
|
|
document.documentElement.setAttribute("data-bs-theme", effectiveMode);
|
|
|
|
|
document.documentElement.setAttribute("data-theme-mode", normalized);
|
|
|
|
|
document.documentElement.style.colorScheme = effectiveMode;
|
|
|
|
|
localStorage.setItem(storageKey, normalized);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleSystemThemeChange() {
|
|
|
|
|
const currentMode = normalize(localStorage.getItem(storageKey) || document.documentElement.getAttribute("data-theme-mode"));
|
|
|
|
|
if (currentMode === "system") {
|
|
|
|
|
apply(currentMode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mediaQuery) {
|
|
|
|
|
if (typeof mediaQuery.addEventListener === "function") {
|
|
|
|
|
mediaQuery.addEventListener("change", handleSystemThemeChange);
|
|
|
|
|
}
|
|
|
|
|
else if (typeof mediaQuery.addListener === "function") {
|
|
|
|
|
mediaQuery.addListener(handleSystemThemeChange);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
init() {
|
|
|
|
|
apply(localStorage.getItem(storageKey) || document.documentElement.getAttribute("data-theme-mode"));
|
|
|
|
|
},
|
|
|
|
|
setTheme(mode) {
|
|
|
|
|
apply(mode);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
})();
|
|
|
|
|
|
2026-04-20 23:17:35 +02:00
|
|
|
window.workTrackerPreferences = {
|
|
|
|
|
getBool(key) {
|
|
|
|
|
try {
|
|
|
|
|
const value = localStorage.getItem(key);
|
|
|
|
|
if (value === null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value === "true") {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value === "false") {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setBool(key, value) {
|
|
|
|
|
try {
|
|
|
|
|
localStorage.setItem(key, value ? "true" : "false");
|
|
|
|
|
}
|
|
|
|
|
catch {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-22 23:58:55 +02:00
|
|
|
window.workTrackerDateInput = (() => {
|
|
|
|
|
const listeners = new WeakMap();
|
|
|
|
|
|
|
|
|
|
function unregisterOutsideClick(root) {
|
|
|
|
|
const existingListener = listeners.get(root);
|
|
|
|
|
if (!existingListener) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.removeEventListener("pointerdown", existingListener, true);
|
|
|
|
|
listeners.delete(root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function registerOutsideClick(root, dotNetReference) {
|
|
|
|
|
if (!root || !dotNetReference) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unregisterOutsideClick(root);
|
|
|
|
|
|
|
|
|
|
const listener = (event) => {
|
|
|
|
|
if (root.contains(event.target)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dotNetReference.invokeMethodAsync("ClosePopupFromOutsideClickAsync");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
listeners.set(root, listener);
|
|
|
|
|
document.addEventListener("pointerdown", listener, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
registerOutsideClick,
|
|
|
|
|
unregisterOutsideClick
|
|
|
|
|
};
|
|
|
|
|
})();
|
|
|
|
|
|
2026-04-20 22:58:25 +02:00
|
|
|
window.workTrackerTheme.init();
|