1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2024-11-03 21:04:03 +08:00

Adding experimental support to dark themes #587 #68 #140

This commit is contained in:
Patrik J. Braun 2023-03-12 00:07:17 +01:00
parent 2287893bf4
commit 609d2127d9
5 changed files with 136 additions and 3 deletions

View File

@ -489,6 +489,20 @@ export class ClientLightboxConfig {
loopVideos: boolean = false;
}
@SubConfigClass<TAGS>({tags: {client: true}, softReadonly: true})
export class ThemesConfig {
@ConfigProperty({
tags: {
name: $localize`Enable`,
experimental: true
} as TAGS,
description: $localize`Enable themes and color modes.`
})
enabled: boolean = false;
}
@SubConfigClass<TAGS>({tags: {client: true}, softReadonly: true})
export class ClientGalleryConfig {
@ConfigProperty({
@ -578,6 +592,7 @@ export class ClientGalleryConfig {
description: $localize`Adds a button to flattens the file structure, by listing the content of all subdirectories. (Won't work if the gallery has multiple folders with the same path.)`
})
enableDirectoryFlattening: boolean = false;
@ConfigProperty({
tags: {
name: $localize`Lightbox`,
@ -585,6 +600,14 @@ export class ClientGalleryConfig {
},
})
Lightbox: ClientLightboxConfig = new ClientLightboxConfig();
@ConfigProperty({
tags: {
name: $localize`ThemesConfig`,
priority: ConfigPriority.advanced,
},
})
Themes: ThemesConfig = new ThemesConfig();
}
@SubConfigClass({tags: {client: true}, softReadonly: true})

View File

@ -104,6 +104,7 @@ import {JobProgressComponent} from './ui/settings/workflow/progress/job-progress
import {SettingsEntryComponent} from './ui/settings/template/settings-entry/settings-entry.component';
import {UsersComponent} from './ui/settings/users/users.component';
import {SharingsListComponent} from './ui/settings/sharings-list/sharings-list.component';
import {ThemeService} from './model/theme.service';
@Injectable()
export class MyHammerConfig extends HammerGestureConfig {
@ -267,6 +268,7 @@ Marker.prototype.options.icon = iconDefault;
SeededRandomService,
OverlayService,
QueryService,
ThemeService,
DuplicateService,
FacesService,
VersionService,

View File

@ -0,0 +1,82 @@
import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {Config} from '../../../common/config/public/Config';
@Injectable({
providedIn: 'root'
})
export class ThemeService {
mode: ThemeMode = ThemeMode.light;
public readonly darkMode: BehaviorSubject<boolean> = new BehaviorSubject(false);
public readonly matcher = window.matchMedia('(prefers-color-scheme: dark)');
constructor() {
this.darkMode.subscribe((darkMode: boolean) => {
this.applyMode(darkMode);
}
);
}
listenToModePreference() {
if (this.mode !== ThemeMode.auto) {
return;
}
this.darkMode.next(window.matchMedia('(prefers-color-scheme: dark)').matches);
this.matcher.addEventListener('change', event => {
this.darkMode.next(event.matches);
});
}
stopListening() {
this.matcher.removeAllListeners();
}
applyMode(darkMode: boolean) {
if (!Config.Gallery.Themes.enabled) {
return;
}
if (!darkMode) {
document.documentElement.removeAttribute('data-bs-theme');
} else {
document.documentElement.setAttribute('data-bs-theme', 'dark');
}
}
setMode(mode: ThemeMode) {
this.mode = mode;
if (this.mode === ThemeMode.light) {
this.darkMode.next(false);
this.stopListening();
} else if (this.mode === ThemeMode.dark) {
this.darkMode.next(true);
this.stopListening();
} else if (this.mode === ThemeMode.auto) {
this.listenToModePreference();
}
}
toggleMode() {
switch (this.mode) {
case ThemeMode.light:
this.setMode(ThemeMode.dark);
break;
case ThemeMode.dark:
this.setMode(ThemeMode.auto);
break;
case ThemeMode.auto:
this.setMode(ThemeMode.light);
break;
}
}
}
export enum ThemeMode {
light = 1, dark, auto
}
export enum AppliedThemeMode {
light = 1, dark
}

View File

@ -63,7 +63,7 @@
<li class="nav-item divider-vertical d-xl-block d-none">
</li>
<li class="nav-item dropdown">
<div class="btn-group" dropdown #dropdown="bs-dropdown" placement="bottom"
<div class="btn-group" dropdown #dropdown="bs-dropdown" placement="bottom"
[insideClick]="true">
<button id="button-alignment" dropdownToggle
type="button" class="btn btn-dark dropdown-toggle"
@ -87,7 +87,28 @@
<li class="nav-item d-xl-none" *ngIf="showShare">
<app-gallery-share [dropDownItem]="true"></app-gallery-share>
</li>
<hr class="d-xl-none"/>
<li role="menuitem" *ngIf="themesEnabled">
<div class="dropdown-item bg-transparent">
<button class="btn w-100 btn-secondary" (click)="themeService.toggleMode()">
<ng-container [ngSwitch]="themeService.mode">
<ng-container *ngSwitchCase="ThemeMode.light">
<span class="oi oi-sun"></span>
<ng-container i18n>Light</ng-container>
</ng-container>
<ng-container *ngSwitchCase="ThemeMode.dark">
<span class="oi oi-moon"></span>
<ng-container i18n>Dark</ng-container>
</ng-container>
<ng-container *ngSwitchCase="ThemeMode.auto">
<span class="oi oi-moon"></span>
<span class="oi oi-sun" style="margin-left: -0.8rem"></span>
<ng-container i18n>Auto</ng-container>
</ng-container>
</ng-container>
</button>
</div>
</li>
<hr/>
<ng-container *ngFor="let link of navbarLinks">
<li class="nav-item d-md-none"
*ngIf="link.type === NavigationLinkTypes.albums && isAlbumsAvailable()">

View File

@ -12,6 +12,7 @@ import {Utils} from '../../../../common/Utils';
import {PageHelper} from '../../model/page.helper';
import {BsDropdownDirective} from 'ngx-bootstrap/dropdown';
import {LanguageComponent} from '../language/language.component';
import {ThemeMode, ThemeService} from '../../model/theme.service';
@Component({
selector: 'app-frame',
@ -30,6 +31,7 @@ export class FrameComponent {
public readonly navbarLinks = Config.Gallery.NavBar.links;
public readonly NavigationLinkTypes = NavigationLinkTypes;
public readonly stringify = JSON.stringify;
public readonly themesEnabled = Config.Gallery.Themes.enabled;
/* sticky top navbar */
private lastScroll = {
@ -44,11 +46,14 @@ export class FrameComponent {
@ViewChild('dropdown', {static: true}) dropdown: BsDropdownDirective;
@ViewChild('languageSelector', {static: true}) languageSelector: LanguageComponent;
ThemeMode = ThemeMode;
constructor(
private authService: AuthenticationService,
public notificationService: NotificationService,
public queryService: QueryService,
private router: Router
private router: Router,
public themeService: ThemeService
) {
this.user = this.authService.user;
}