import { Injectable, Renderer2, RendererFactory2 } from '@angular/core'; import { MediaMatcher } from '@angular/cdk/layout'; import { LocalStorage } from 'ngx-webstorage'; type ColorScheme = "dark" | "light"; @Injectable({ providedIn: 'root' }) export class ColorSchemeService { private renderer: Renderer2; matcher!: MediaQueryList; @LocalStorage('prefers-color-scheme') public colorSchemeOverride: ColorScheme; public activeColorScheme: BehaviorSubject = new BehaviorSubject("light"); constructor(rendererFactory: RendererFactory2, mediaMatcher: MediaMatcher ) { // Create new renderer from renderFactory, to make it possible to use renderer2 in a service this.renderer = rendererFactory.createRenderer(null, null); this.matcher = mediaMatcher.matchMedia('(prefers-color-scheme: dark)'); this._listener = this._listener.bind(this); } init() { this.matcher.addEventListener('change', this._listener); this.load(); } _listener(event: { matches: any; }) { this.activeColorScheme.next(event.matches ? 'dark' : 'light'); } destroy() { this.matcher.removeEventListener('change', this._listener); } _getColorScheme() { if (this.colorSchemeOverride) { this.colorSchemeOverride } else { this.matcher.matches ? 'dark' : 'light' } } load() { this.activeColorScheme.next(this._getColorScheme()); } update(scheme: ColorScheme) { this.colorSchemeOverride = scheme; this.activeColorScheme.next(scheme); } currentActive() { return this.colorScheme; } }