import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ThemeService { private readonly THEME_COOKIE = 'theme-preference'; private darkModeSubject = new BehaviorSubject(this.getInitialTheme()); darkMode$ = this.darkModeSubject.asObservable(); constructor() { // Theme beim Start anwenden this.applyTheme(this.darkModeSubject.value); } /** * Ermittelt das initiale Theme: * 1. Cookie-Präferenz (falls vorhanden) * 2. Browser-System-Einstellung (prefers-color-scheme) */ private getInitialTheme(): boolean { const cookieTheme = this.getCookie(this.THEME_COOKIE); if (cookieTheme !== null) { return cookieTheme === 'dark'; } // Fallback auf System-Präferenz return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; } /** * Schaltet zwischen Light und Dark Mode um */ toggleTheme(): void { const newTheme = !this.darkModeSubject.value; this.setTheme(newTheme); } /** * Setzt ein spezifisches Theme */ setTheme(isDark: boolean): void { this.darkModeSubject.next(isDark); this.applyTheme(isDark); this.setCookie(this.THEME_COOKIE, isDark ? 'dark' : 'light', 365); } /** * Gibt das aktuelle Theme zurück */ isDarkMode(): boolean { return this.darkModeSubject.value; } /** * Wendet das Theme auf das Document an */ private applyTheme(isDark: boolean): void { if (isDark) { document.body.classList.add('dark-theme'); } else { document.body.classList.remove('dark-theme'); } } /** * Setzt ein Cookie */ private setCookie(name: string, value: string, days: number): void { const expires = new Date(); expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000); document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/;SameSite=Lax`; } /** * Liest ein Cookie aus */ private getCookie(name: string): string | null { const nameEQ = name + '='; const ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); } return null; } }