summaryrefslogtreecommitdiff
path: root/overlays/spm/frontend/src/app/app.component.ts
diff options
context:
space:
mode:
Diffstat (limited to 'overlays/spm/frontend/src/app/app.component.ts')
-rw-r--r--overlays/spm/frontend/src/app/app.component.ts89
1 files changed, 84 insertions, 5 deletions
diff --git a/overlays/spm/frontend/src/app/app.component.ts b/overlays/spm/frontend/src/app/app.component.ts
index 7c231203..11c0f772 100644
--- a/overlays/spm/frontend/src/app/app.component.ts
+++ b/overlays/spm/frontend/src/app/app.component.ts
@@ -1,6 +1,18 @@
1import { Component, OnInit, OnDestroy } from '@angular/core'; 1import { Component, OnInit, OnDestroy, Inject, Renderer2, RendererFactory2 } from '@angular/core';
2import { DOCUMENT } from '@angular/common';
3import { MediaMatcher } from '@angular/cdk/layout';
4import { LocalStorage } from 'ngx-webstorage';
5import { BehaviorSubject, Subscription, Subject } from 'rxjs';
6import { Router, RouterEvent, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
7import { HttpClient, HttpHeaders } from '@angular/common/http';
2 8
3import { ColorSchemeService } from './color-scheme.service'; 9import { map, filter } from 'rxjs/operators';
10
11type ColorScheme = 'dark' | 'light';
12
13export interface DomainResponse {
14 domain: string;
15}
4 16
5@Component({ 17@Component({
6 selector: 'app-root', 18 selector: 'app-root',
@@ -8,14 +20,81 @@ import { ColorSchemeService } from './color-scheme.service';
8 styleUrls: ['./app.component.sass'] 20 styleUrls: ['./app.component.sass']
9}) 21})
10export class AppComponent implements OnInit, OnDestroy { 22export class AppComponent implements OnInit, OnDestroy {
23 private renderer: Renderer2;
24 colorSchemeMatcher: MediaQueryList;
25
11 title = 'spm-frontend'; 26 title = 'spm-frontend';
12 27
13 constructor(private colorSchemeService: ColorSchemeService) {} 28 public activeColorScheme$: BehaviorSubject<ColorScheme> = new BehaviorSubject<ColorScheme>('dark');
29
30 @LocalStorage('prefers-color-scheme')
31 public colorSchemeOverride?: ColorScheme;
32
33 colorSchemeSubscription?: Subscription;
34
35 router: Router;
36 public routerLoading$: Subject<boolean> = new Subject<boolean>();
37 routerEventSubscription?: Subscription;
38
39 http: HttpClient;
40 apiDomain$: Subject<string> = new Subject<string>();
41
42 constructor( rendererFactory: RendererFactory2,
43 mediaMatcher: MediaMatcher,
44 @Inject(DOCUMENT) private document: Document,
45 router: Router,
46 http: HttpClient,
47 ) {
48 this.renderer = rendererFactory.createRenderer(null, null);
49 this.colorSchemeMatcher = mediaMatcher.matchMedia('(prefers-color-scheme: dark)');
50 this.document = document;
51
52 this.colorSchemeListener = this.colorSchemeListener.bind(this);
53 this.colorSchemeMatcher.addEventListener('change', this.colorSchemeListener);
54 this.activeColorScheme$.next(this.getColorScheme());
55
56 this.router = router;
57 this.http = http;
58 }
59
60 private colorSchemeListener(event: { matches: boolean; }) {
61 this.activeColorScheme$.next(this.getColorScheme(event));
62 }
63
64 private getColorScheme(event?: { matches: boolean; }): ColorScheme {
65 if (this.colorSchemeOverride) {
66 return this.colorSchemeOverride;
67 } else if (event) {
68 return event.matches ? 'dark' : 'light';
69 } else {
70 return this.colorSchemeMatcher.matches ? 'dark' : 'light';
71 }
72 }
73
74 updateColorScheme(scheme: ColorScheme) {
75 this.colorSchemeOverride = scheme;
76 this.activeColorScheme$.next(scheme);
77 }
14 78
15 ngOnInit() { 79 ngOnInit() {
16 this.colorSchemeService.init(); 80 this.colorSchemeSubscription = this.activeColorScheme$.subscribe(scheme => { this.renderer.setAttribute(this.document.body, 'data-color-scheme', scheme); });
81
82 this.routerEventSubscription = this.router.events.pipe(
83 filter(event =>
84 event instanceof NavigationStart ||
85 event instanceof NavigationEnd ||
86 event instanceof NavigationCancel ||
87 event instanceof NavigationError
88 ),
89 map(event => event instanceof NavigationStart)
90 ).subscribe(this.routerLoading$);
91
92 this.http.get<DomainResponse>('/domain', { headers: new HttpHeaders({ 'Accept': 'application/json' }) }).pipe(map((resp: DomainResponse) => resp.domain)).subscribe(this.apiDomain$);
17 } 93 }
18 ngOnDestroy() { 94 ngOnDestroy() {
19 this.colorSchemeService.destroy(); 95 this.colorSchemeMatcher.removeEventListener('change', this.colorSchemeListener);
96
97 this.colorSchemeSubscription?.unsubscribe();
98 this.routerEventSubscription?.unsubscribe();
20 } 99 }
21} 100}