FastAPI-Backend und React-Frontend mit Konten, Sendungsverfolgung, Projekt-Artikeln, Vorrat & Einkauf mit Rezeptabgleich, Reise-Weltkarte, Kanban-Projekten mit Priorität, Server-Monitoring und den Designs Matrix und Blackwall. Betrieb per Docker hinter nginx (siehe DEPLOY.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.7 KiB
JavaScript
47 lines
1.7 KiB
JavaScript
// Designs der Oberfläche. Die Auswahl wird pro Browser gespeichert; index.html setzt sie vor dem ersten
|
|
// Zeichnen (kein Aufblitzen des falschen Designs), dieses Modul hält sie danach aktuell.
|
|
const KEY = 'p42.design';
|
|
const EVENT = 'p42:design';
|
|
|
|
export const THEMES = [
|
|
{ key: 'matrix', name: 'Matrix', hint: 'Rotes Retro-Terminal', swatch: ['#ff3a3a', '#1d0505'], color: '#050000' },
|
|
{ key: 'blackwall', name: 'Blackwall', hint: 'Cyberpunk-Netrunner', swatch: ['#ff2d6f', '#3ff6ff', '#1a0508'], color: '#060104' },
|
|
];
|
|
|
|
const valid = (key) => THEMES.some((t) => t.key === key);
|
|
|
|
export function getTheme() {
|
|
const current = document.documentElement.dataset.theme;
|
|
return valid(current) ? current : 'matrix';
|
|
}
|
|
|
|
export function setTheme(key) {
|
|
if (!valid(key)) return;
|
|
try { localStorage.setItem(KEY, key); } catch { /* ignorieren */ }
|
|
const still = document.documentElement.classList.contains('calm')
|
|
|| window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
// Überblenden, wo der Browser View Transitions kann; kurz warten, bis React den neuen Hintergrund gezeichnet hat
|
|
if (document.startViewTransition && !still) {
|
|
document.startViewTransition(async () => {
|
|
apply(key);
|
|
await new Promise((resolve) => { setTimeout(resolve, 40); });
|
|
});
|
|
} else {
|
|
apply(key);
|
|
}
|
|
}
|
|
|
|
export function onThemeChange(fn) {
|
|
window.addEventListener(EVENT, fn);
|
|
return () => window.removeEventListener(EVENT, fn);
|
|
}
|
|
|
|
function apply(key) {
|
|
document.documentElement.dataset.theme = key;
|
|
// Browser-Leiste (Handy) passend einfärben
|
|
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', THEMES.find((t) => t.key === key).color);
|
|
window.dispatchEvent(new Event(EVENT));
|
|
}
|
|
|
|
apply(getTheme());
|