diff --git a/web-app/src/app/app.component.ts b/web-app/src/app/app.component.ts index cb1d008b9db..4f75cfae024 100644 --- a/web-app/src/app/app.component.ts +++ b/web-app/src/app/app.component.ts @@ -6,6 +6,8 @@ import { environment } from '@env/environment'; import { NzModalService } from 'ng-zorro-antd/modal'; import { VERSION as VERSION_ZORRO } from 'ng-zorro-antd/version'; +import { ThemeService } from './service/theme.service'; + @Component({ selector: 'app-root', template: ` ` @@ -17,6 +19,7 @@ export class AppComponent implements OnInit { private router: Router, private titleSrv: TitleService, private modalSrv: NzModalService, + private themeService: ThemeService, @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService ) { renderer.setAttribute(el.nativeElement, 'ng-alain-version', VERSION_ALAIN.full); @@ -46,5 +49,10 @@ export class AppComponent implements OnInit { this.modalSrv.closeAll(); } }); + // set theme + const storedTheme = localStorage.getItem('theme'); + if (storedTheme) { + this.themeService.changeTheme(storedTheme); + } } } diff --git a/web-app/src/app/routes/setting/settings/system-config/system-config.component.ts b/web-app/src/app/routes/setting/settings/system-config/system-config.component.ts index 16aec313486..f8cca553529 100644 --- a/web-app/src/app/routes/setting/settings/system-config/system-config.component.ts +++ b/web-app/src/app/routes/setting/settings/system-config/system-config.component.ts @@ -26,6 +26,7 @@ import { finalize } from 'rxjs/operators'; import { SystemConfig } from '../../../../pojo/SystemConfig'; import { GeneralConfigService } from '../../../../service/general-config.service'; +import { ThemeService } from '../../../../service/theme.service'; @Component({ selector: 'app-system-config', @@ -38,6 +39,7 @@ export class SystemConfigComponent implements OnInit { private notifySvc: NzNotificationService, private configService: GeneralConfigService, private settings: SettingsService, + private themeService: ThemeService, @Inject(DOCUMENT) private doc: any, @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService ) {} @@ -103,22 +105,8 @@ export class SystemConfigComponent implements OnInit { } ); } + changeTheme(theme: string): void { - const style = this.doc.createElement('link'); - style.type = 'text/css'; - style.rel = 'stylesheet'; - if (theme == 'dark') { - style.id = 'dark-theme'; - style.href = 'assets/style.dark.css'; - } else if (theme == 'compact') { - style.id = 'compact-theme'; - style.href = 'assets/style.compact.css'; - } else { - const dom = document.getElementById('dark-theme'); - if (dom) { - dom.remove(); - } - } - this.doc.body.append(style); + this.themeService.changeTheme(theme); } } diff --git a/web-app/src/app/service/theme.service.ts b/web-app/src/app/service/theme.service.ts new file mode 100644 index 00000000000..1201831066c --- /dev/null +++ b/web-app/src/app/service/theme.service.ts @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { DOCUMENT } from '@angular/common'; +import { Inject, Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class ThemeService { + private readonly themeKey = 'theme'; + + constructor(@Inject(DOCUMENT) private doc: any) {} + + setTheme(theme: string): void { + localStorage.setItem(this.themeKey, theme); + } + + getTheme(): string | null { + return localStorage.getItem(this.themeKey); + } + + clearTheme(): void { + localStorage.removeItem(this.themeKey); + } + + changeTheme(theme: string): void { + const style = this.doc.createElement('link'); + style.type = 'text/css'; + style.rel = 'stylesheet'; + + if (theme === 'dark') { + style.id = 'dark-theme'; + style.href = 'assets/style.dark.css'; + } else if (theme === 'compact') { + style.id = 'compact-theme'; + style.href = 'assets/style.compact.css'; + } else { + const darkDom = this.doc.getElementById('dark-theme'); + if (darkDom) darkDom.remove(); + + const compactDom = this.doc.getElementById('compact-theme'); + if (compactDom) compactDom.remove(); + + this.clearTheme(); + + return; + } + + this.setTheme(theme); + + // remove old theme + const existingLink = this.doc.getElementById(style.id); + if (existingLink) { + existingLink.remove(); + } + + // add new theme + this.doc.body.appendChild(style); + } +}