Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 5x 5x 5x 5x 40x 40x 40x 71x 40x 34x 34x 34x 34x 40x 40x 3x 9x 40x 40x 40x 27x 13x 13x 13x 34x 34x 34x 34x 34x 34x 40x 40x | import { isPlatformBrowser } from '@angular/common';
import { Injectable, signal, effect, PLATFORM_ID, inject } from '@angular/core';
export type Theme = 'light' | 'dark';
const THEME_KEY = 'drevo-theme';
@Injectable({
providedIn: 'root',
})
export class ThemeService {
private readonly platformId = inject(PLATFORM_ID);
private readonly isBrowser = isPlatformBrowser(this.platformId);
readonly theme = signal<Theme>(this.getInitialTheme());
readonly isDark = () => this.theme() === 'dark';
constructor() {
effect(() => {
const currentTheme = this.theme();
Eif (this.isBrowser) {
this.applyTheme(currentTheme);
this.saveTheme(currentTheme);
}
});
Eif (this.isBrowser) {
this.listenToSystemThemeChanges();
}
}
toggleTheme(): void {
this.theme.update(current => (current === 'light' ? 'dark' : 'light'));
}
setTheme(theme: Theme): void {
this.theme.set(theme);
}
private getInitialTheme(): Theme {
Iif (!this.isBrowser) {
return 'light';
}
const savedTheme = localStorage.getItem(THEME_KEY) as Theme | null;
if (savedTheme && (savedTheme === 'light' || savedTheme === 'dark')) {
return savedTheme;
}
return this.getSystemTheme();
}
private getSystemTheme(): Theme {
Iif (this.isBrowser && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
}
private applyTheme(theme: Theme): void {
const root = document.documentElement;
Iif (theme === 'dark') {
root.classList.add('dark-theme');
root.classList.remove('light-theme');
root.style.colorScheme = 'dark';
} else {
root.classList.add('light-theme');
root.classList.remove('dark-theme');
root.style.colorScheme = 'light';
}
}
private saveTheme(theme: Theme): void {
localStorage.setItem(THEME_KEY, theme);
}
private listenToSystemThemeChanges(): void {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', e => {
// Apply system theme only if user hasn't explicitly chosen one
const savedTheme = localStorage.getItem(THEME_KEY);
if (!savedTheme) {
this.theme.set(e.matches ? 'dark' : 'light');
}
});
}
}
|