import {effect, Injectable, signal, WritableSignal} from '@angular/core'; import {Theme} from "../models/theme"; @Injectable({ providedIn: 'root' }) export class ThemeSwitchService { private readonly THEME_KEY = 'app-theme-mode'; public theme: WritableSignal = signal(Theme.DEFAULT_THEME); constructor() { effect(() => { const currentTheme = this.theme(); localStorage.setItem(this.THEME_KEY, currentTheme.code); const html = document.querySelector('html')!; const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const isDark = currentTheme.code === 'dark' || (currentTheme.code === 'system' && systemPrefersDark); html.classList.toggle('dark', isDark); }); window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { if (this.theme().code === 'system') { this.theme.update(t => t); } }); } initialize() { console.info('initializing dark mode service'); const stored = Theme.THEMES.find(theme => theme.code === localStorage.getItem(this.THEME_KEY)); if (stored === undefined) { this.theme.set(Theme.DEFAULT_THEME); return; } if (stored.code === 'dark' || stored.code === 'light' || stored.code === 'system') { this.theme.set(stored); } else { this.theme.set(Theme.DEFAULT_THEME); } } switchToTheme(theme: Theme) { console.info(`switching to theme: ${theme.name}`); this.theme.set(theme); } isDarkMode(): boolean { return this.theme().code === 'dark' || (this.theme().code === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches); } }