frontend: ensure ThemeService is initialized before app starts and apply the saved theme on initial load to prevent flickering
This commit is contained in:
parent
160cb3927d
commit
aceedaddfa
@ -7,7 +7,7 @@ export type Theme = 'light' | 'dark';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class ThemeService {
|
export class ThemeService {
|
||||||
private readonly THEME_KEY = 'ov-theme-preference';
|
private readonly THEME_KEY = 'ov-meet-theme';
|
||||||
private readonly _currentTheme = signal<Theme>('light');
|
private readonly _currentTheme = signal<Theme>('light');
|
||||||
|
|
||||||
// Computed signals for reactivity
|
// Computed signals for reactivity
|
||||||
@ -15,9 +15,7 @@ export class ThemeService {
|
|||||||
public readonly isDark = computed(() => this._currentTheme() === 'dark');
|
public readonly isDark = computed(() => this._currentTheme() === 'dark');
|
||||||
public readonly isLight = computed(() => this._currentTheme() === 'light');
|
public readonly isLight = computed(() => this._currentTheme() === 'light');
|
||||||
|
|
||||||
constructor(@Inject(DOCUMENT) private document: Document) {
|
constructor(@Inject(DOCUMENT) private document: Document) {}
|
||||||
this.initializeTheme();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the theme based on:
|
* Initializes the theme based on:
|
||||||
@ -25,7 +23,7 @@ export class ThemeService {
|
|||||||
* 2. System preference (prefers-color-scheme)
|
* 2. System preference (prefers-color-scheme)
|
||||||
* 3. Light theme as default
|
* 3. Light theme as default
|
||||||
*/
|
*/
|
||||||
private initializeTheme(): void {
|
initializeTheme(): void {
|
||||||
const savedTheme = this.getSavedTheme();
|
const savedTheme = this.getSavedTheme();
|
||||||
const systemPreference = this.getSystemPreference();
|
const systemPreference = this.getSystemPreference();
|
||||||
const initialTheme = savedTheme || systemPreference || 'light';
|
const initialTheme = savedTheme || systemPreference || 'light';
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { AppDataService, ThemeService } from '@lib/services';
|
import { AppDataService } from '@lib/services';
|
||||||
import packageInfo from '../../package.json';
|
import packageInfo from '../../package.json';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -11,10 +11,7 @@ import packageInfo from '../../package.json';
|
|||||||
imports: [RouterOutlet]
|
imports: [RouterOutlet]
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
constructor(
|
constructor(private appDataService: AppDataService) {}
|
||||||
private appDataService: AppDataService,
|
|
||||||
private themeService: ThemeService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.appDataService.setVersion(packageInfo.version);
|
this.appDataService.setVersion(packageInfo.version);
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
|
import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
|
||||||
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||||
import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
|
import { APP_INITIALIZER, ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
|
||||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { routes } from '@app/app.routes';
|
import { routes } from '@app/app.routes';
|
||||||
import { environment } from '@environment/environment';
|
import { environment } from '@environment/environment';
|
||||||
import { httpInterceptor } from '@lib/interceptors/index';
|
import { httpInterceptor } from '@lib/interceptors/index';
|
||||||
|
import { ThemeService } from '@lib/services/theme.service';
|
||||||
import { OpenViduComponentsConfig, OpenViduComponentsModule } from 'openvidu-components-angular';
|
import { OpenViduComponentsConfig, OpenViduComponentsModule } from 'openvidu-components-angular';
|
||||||
|
|
||||||
const ovComponentsconfig: OpenViduComponentsConfig = {
|
const ovComponentsconfig: OpenViduComponentsConfig = {
|
||||||
@ -14,6 +15,13 @@ const ovComponentsconfig: OpenViduComponentsConfig = {
|
|||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
|
{
|
||||||
|
provide: APP_INITIALIZER,
|
||||||
|
// Ensure the theme is initialized before the app starts
|
||||||
|
useFactory: (themeService: ThemeService) => () => themeService.initializeTheme(),
|
||||||
|
deps: [ThemeService],
|
||||||
|
multi: true
|
||||||
|
},
|
||||||
importProvidersFrom(OpenViduComponentsModule.forRoot(ovComponentsconfig)),
|
importProvidersFrom(OpenViduComponentsModule.forRoot(ovComponentsconfig)),
|
||||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
provideRouter(routes),
|
provideRouter(routes),
|
||||||
|
|||||||
@ -10,6 +10,16 @@
|
|||||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet" />
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Apply the saved theme on initial load to prevent flickering
|
||||||
|
(function () {
|
||||||
|
const savedTheme = localStorage.getItem('ov-meet-theme') || 'light';
|
||||||
|
if (savedTheme === 'dark') {
|
||||||
|
document.documentElement.setAttribute('data-theme', 'dark');
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="mat-typography" id="body">
|
<body class="mat-typography" id="body">
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { AppComponent } from '@app/app.component';
|
import { AppComponent } from '@app/app.component';
|
||||||
import { appConfig } from '@app/app.config';
|
import { appConfig } from '@app/app.config';
|
||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));
|
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user