1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-23 01:27:14 +02:00

save preferred theme mode #587 #68 #140

This commit is contained in:
Patrik J. Braun 2023-03-14 21:16:19 +01:00
parent d2a24b4b56
commit 70119241e1
3 changed files with 70 additions and 28 deletions

View File

@ -24,6 +24,11 @@ export enum ConfigPriority {
basic = 0, advanced, underTheHood basic = 0, advanced, underTheHood
} }
export enum ThemeModes {
light = 1, dark, auto
}
export type TAGS = { export type TAGS = {
client?: true, client?: true,
priority?: ConfigPriority, priority?: ConfigPriority,
@ -500,6 +505,17 @@ export class ThemesConfig {
description: $localize`Enable themes and color modes.` description: $localize`Enable themes and color modes.`
}) })
enabled: boolean = false; enabled: boolean = false;
@ConfigProperty({
type: ThemeModes,
tags: {
name: $localize`Default theme mode`,
experimental: true,
uiDisabled: (sb: ThemesConfig) => !sb.enabled,
} as TAGS,
description: $localize`Sets the default theme mode that is used for the application.`
})
defaultMode: ThemeModes = ThemeModes.light;
} }
@ -603,7 +619,7 @@ export class ClientGalleryConfig {
@ConfigProperty({ @ConfigProperty({
tags: { tags: {
name: $localize`ThemesConfig`, name: $localize`Themes`,
priority: ConfigPriority.advanced, priority: ConfigPriority.advanced,
}, },
}) })

View File

@ -1,17 +1,24 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs'; import {BehaviorSubject} from 'rxjs';
import {ThemeModes} from '../../../common/config/public/ClientConfig';
import {Config} from '../../../common/config/public/Config'; import {Config} from '../../../common/config/public/Config';
import {GalleryCacheService} from '../ui/gallery/cache.gallery.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ThemeService { export class ThemeService {
mode: ThemeMode = ThemeMode.light; mode: ThemeModes = ThemeModes.light;
public readonly darkMode: BehaviorSubject<boolean> = new BehaviorSubject(false); public readonly darkMode: BehaviorSubject<boolean> = new BehaviorSubject(false);
public readonly matcher = window.matchMedia('(prefers-color-scheme: dark)'); public readonly matcher = window.matchMedia('(prefers-color-scheme: dark)');
constructor() { constructor(private cachingService: GalleryCacheService) {
if (cachingService.getThemeMode()) {
this.setMode(cachingService.getThemeMode());
} else {
this.setMode(Config.Gallery.Themes.defaultMode);
}
this.darkMode.subscribe((darkMode: boolean) => { this.darkMode.subscribe((darkMode: boolean) => {
this.applyMode(darkMode); this.applyMode(darkMode);
} }
@ -19,7 +26,7 @@ export class ThemeService {
} }
listenToModePreference() { listenToModePreference() {
if (this.mode !== ThemeMode.auto) { if (this.mode !== ThemeModes.auto) {
return; return;
} }
this.darkMode.next(window.matchMedia('(prefers-color-scheme: dark)').matches); this.darkMode.next(window.matchMedia('(prefers-color-scheme: dark)').matches);
@ -44,39 +51,36 @@ export class ThemeService {
} }
} }
setMode(mode: ThemeMode) { setMode(mode: ThemeModes) {
if (this.mode === mode) {
return;
}
this.mode = mode; this.mode = mode;
if (this.mode === ThemeMode.light) { if (this.mode === ThemeModes.light) {
this.darkMode.next(false); this.darkMode.next(false);
this.stopListening(); this.stopListening();
} else if (this.mode === ThemeMode.dark) { } else if (this.mode === ThemeModes.dark) {
this.darkMode.next(true); this.darkMode.next(true);
this.stopListening(); this.stopListening();
} else if (this.mode === ThemeMode.auto) { } else if (this.mode === ThemeModes.auto) {
this.listenToModePreference(); this.listenToModePreference();
} }
this.cachingService.setThemeMode(this.mode);
} }
toggleMode() { toggleMode() {
switch (this.mode) { switch (this.mode) {
case ThemeMode.light: case ThemeModes.light:
this.setMode(ThemeMode.dark); this.setMode(ThemeModes.dark);
break; break;
case ThemeMode.dark: case ThemeModes.dark:
this.setMode(ThemeMode.auto); this.setMode(ThemeModes.auto);
break; break;
case ThemeMode.auto: case ThemeModes.auto:
this.setMode(ThemeMode.light); this.setMode(ThemeModes.light);
break; break;
} }
} }
} }
export enum ThemeMode {
light = 1, dark, auto
}
export enum AppliedThemeMode {
light = 1, dark
}

View File

@ -9,6 +9,7 @@ import {VersionService} from '../../model/version.service';
import {SearchQueryDTO, SearchQueryTypes,} from '../../../../common/entities/SearchQueryDTO'; import {SearchQueryDTO, SearchQueryTypes,} from '../../../../common/entities/SearchQueryDTO';
import {ContentWrapper} from '../../../../common/entities/ConentWrapper'; import {ContentWrapper} from '../../../../common/entities/ConentWrapper';
import {ContentWrapperWithError} from './content.service'; import {ContentWrapperWithError} from './content.service';
import {ThemeModes} from '../../../../common/config/public/ClientConfig';
interface CacheItem<T> { interface CacheItem<T> {
timestamp: number; timestamp: number;
@ -17,13 +18,14 @@ interface CacheItem<T> {
@Injectable() @Injectable()
export class GalleryCacheService { export class GalleryCacheService {
private static readonly CONTENT_PREFIX = 'content:'; private static readonly CONTENT_PREFIX = 'CONTENT:';
private static readonly AUTO_COMPLETE_PREFIX = 'autocomplete:'; private static readonly AUTO_COMPLETE_PREFIX = 'AUTOCOMPLETE:';
private static readonly INSTANT_SEARCH_PREFIX = 'instant_search:'; private static readonly INSTANT_SEARCH_PREFIX = 'INSTANT_SEARCH:';
private static readonly SEARCH_PREFIX = 'search:'; private static readonly SEARCH_PREFIX = 'SEARCH:';
private static readonly SORTING_PREFIX = 'sorting:'; private static readonly SORTING_PREFIX = 'SORTING:';
private static readonly VERSION = 'version'; private static readonly VERSION = 'VERSION';
private static readonly SLIDESHOW_SPEED = 'slideshow_speed'; private static readonly SLIDESHOW_SPEED = 'SLIDESHOW_SPEED';
private static THEME_MODE = 'THEME_MODE';
constructor(private versionService: VersionService) { constructor(private versionService: VersionService) {
// if it was a forced reload not a navigation, clear cache // if it was a forced reload not a navigation, clear cache
@ -315,4 +317,24 @@ export class GalleryCacheService {
console.error(e); console.error(e);
} }
} }
getThemeMode(): ThemeModes {
const key = GalleryCacheService.THEME_MODE;
const tmp = localStorage.getItem(key) as keyof typeof ThemeModes;
if (tmp != null) {
return ThemeModes[tmp];
}
return null;
}
setThemeMode(mode: ThemeModes): void {
try {
const key = GalleryCacheService.THEME_MODE;
localStorage.setItem(key, ThemeModes[mode]);
} catch (e) {
this.reset();
console.error(e);
}
}
} }