immich/web/src/lib/managers/theme-manager.svelte.ts
Min Idzelis b06b8ceef6
chore(web): upgrade ESLint and plugins (#22495)
* chore(web): upgrade ESLint and plugins, simplify linting configuration

- Update eslint from ^9.18.0 to ^9.36.0
- Update eslint plugins:
  - eslint-plugin-svelte: ^3.9.0 → ^3.12.4
  - eslint-plugin-unicorn: ^60.0.0 → ^61.0.2
  - svelte-eslint-parser: ^1.2.0 → ^1.3.3
  - typescript-eslint: ^8.28.0 → ^8.45.0
- Remove eslint-p dependency in favor of native eslint concurrency
- Add unicorn/no-array-sort rule exception
- Update linting scripts to use eslint's native --concurrency flag
- Update Makefile and mise.toml to reflect simplified lint commands
- Update GitHub Actions workflow to use standard pnpm lint command

* pnpm dedupe

---------

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
2025-10-06 12:41:28 -04:00

78 lines
1.8 KiB
TypeScript

import { browser } from '$app/environment';
import { Theme } from '$lib/constants';
import { eventManager } from '$lib/managers/event-manager.svelte';
import { PersistedLocalStorage } from '$lib/utils/persisted';
export interface ThemeSetting {
value: Theme;
system: boolean;
}
const getDefaultTheme = () => {
if (!browser) {
return Theme.DARK;
}
return globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.DARK : Theme.LIGHT;
};
class ThemeManager {
#theme = new PersistedLocalStorage<ThemeSetting>(
'color-theme',
{ value: getDefaultTheme(), system: false },
{
valid: (value): value is ThemeSetting => {
return Object.values(Theme).includes((value as ThemeSetting)?.value);
},
},
);
get theme() {
return this.#theme.current;
}
value = $derived(this.theme.value);
isDark = $derived(this.value === Theme.DARK);
constructor() {
eventManager.on('app.init', () => this.#onAppInit());
}
setSystem(system: boolean) {
this.#update(system ? 'system' : getDefaultTheme());
}
setTheme(theme: Theme) {
this.#update(theme);
}
toggleTheme() {
this.#update(this.value === Theme.DARK ? Theme.LIGHT : Theme.DARK);
}
#onAppInit() {
globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener(
'change',
() => {
if (this.theme.system) {
this.#update('system');
}
},
{ passive: true },
);
}
#update(value: Theme | 'system') {
const theme: ThemeSetting =
value === 'system' ? { system: true, value: getDefaultTheme() } : { system: false, value };
document.documentElement.classList.toggle('dark', !(theme.value === Theme.LIGHT));
this.#theme.current = theme;
eventManager.emit('theme.change', theme);
}
}
export const themeManager = new ThemeManager();