diff --git a/webapp/packages/core-bootstrap/src/manifest.ts b/webapp/packages/core-bootstrap/src/manifest.ts index cb9186f5be..f67ac5c9d5 100644 --- a/webapp/packages/core-bootstrap/src/manifest.ts +++ b/webapp/packages/core-bootstrap/src/manifest.ts @@ -78,7 +78,7 @@ import { import { RouterService, ScreenService } from '@cloudbeaver/core-routing'; import { EnvironmentService, GraphQLService } from '@cloudbeaver/core-sdk'; import { LocalStorageSaveService, SettingsService } from '@cloudbeaver/core-settings'; -import { ThemeService } from '@cloudbeaver/core-theming'; +import { ThemeService, ThemeSettingsService } from '@cloudbeaver/core-theming'; import { coreUIManifest } from '@cloudbeaver/core-ui'; import { coreViewManifest } from '@cloudbeaver/core-view'; @@ -158,6 +158,7 @@ export const coreManifests: PluginManifest[] = [ SessionService, SettingsMenuService, SettingsService, + ThemeSettingsService, ThemeService, ServerService, ], diff --git a/webapp/packages/core-settings/src/SettingsService.ts b/webapp/packages/core-settings/src/SettingsService.ts index f875f50938..71e24fc78b 100644 --- a/webapp/packages/core-settings/src/SettingsService.ts +++ b/webapp/packages/core-settings/src/SettingsService.ts @@ -19,7 +19,7 @@ export class SettingsService { * @param key * @param settings - observable object expected */ - registerSettings>(settings: T, key: string): void { + registerSettings>(settings: T, key: string): void { this.localStorageSaveService.withAutoSave(settings, key); } } diff --git a/webapp/packages/core-theming/src/ThemeService.ts b/webapp/packages/core-theming/src/ThemeService.ts index 1b0681244c..af582d8fdc 100644 --- a/webapp/packages/core-theming/src/ThemeService.ts +++ b/webapp/packages/core-theming/src/ThemeService.ts @@ -18,9 +18,12 @@ import { DbeaverError, NotificationService } from '@cloudbeaver/core-events'; import { SettingsService } from '@cloudbeaver/core-settings'; import { themes } from './themes'; +import { defaultThemeSettings } from './ThemeSettingsService'; +import { ThemeSettingsService } from './ThemeSettingsService'; import type { ClassCollection } from './themeUtils'; const COMMON_STYLES: any[] = []; +const THEME_SETTINGS_KEY = 'themeSettings'; export interface ITheme { name: string; @@ -29,8 +32,9 @@ export interface ITheme { loader: () => Promise; } -const THEME_SETTINGS_KEY = 'themeSettings'; -const DEFAULT_THEME_ID = 'light'; +interface ISettings { + currentThemeId: string; +} @injectable() export class ThemeService extends Bootstrap { @@ -38,33 +42,40 @@ export class ThemeService extends Bootstrap { return Array.from(this.themeMap.values()); } - get currentThemeId() { + get defaultThemeId(): string { + return this.themeSettingsService.settings.getValue('defaultTheme'); + } + + get currentThemeId(): string { return this.settings.currentThemeId; } get currentTheme(): ITheme { - let theme = this.themeMap.get(this.settings.currentThemeId); + let theme = this.themeMap.get(this.currentThemeId); + if (!theme) { - theme = this.themeMap.get(DEFAULT_THEME_ID)!; + theme = this.themeMap.get(defaultThemeSettings.defaultTheme)!; } return theme; } - private themeMap: Map = new Map(); - private settings = { - currentThemeId: DEFAULT_THEME_ID, + private readonly themeMap: Map = new Map(); + private readonly settings: ISettings = { + currentThemeId: defaultThemeSettings.defaultTheme, }; constructor( - private notificationService: NotificationService, - private settingsService: SettingsService + private readonly notificationService: NotificationService, + private readonly settingsService: SettingsService, + private readonly themeSettingsService: ThemeSettingsService, ) { super(); makeObservable(this, { themes: computed, currentTheme: computed, + defaultThemeId: computed, themeMap: observable.shallow, settings: observable, setCurrentThemeId: action, @@ -76,6 +87,7 @@ export class ThemeService extends Bootstrap { } async load(): Promise { + this.setCurrentThemeId(this.defaultThemeId); this.settingsService.registerSettings(this.settings, THEME_SETTINGS_KEY); await this.changeThemeAsync(this.currentThemeId); } @@ -94,8 +106,8 @@ export class ThemeService extends Bootstrap { try { await this.loadThemeStylesAsync(themeId); } catch (e) { - if (themeId !== DEFAULT_THEME_ID) { - return this.changeThemeAsync(DEFAULT_THEME_ID); // try to fallback to default theme + if (themeId !== defaultThemeSettings.defaultTheme) { + return this.changeThemeAsync(defaultThemeSettings.defaultTheme); // try to fallback to default theme } throw e; } diff --git a/webapp/packages/core-theming/src/ThemeSettingsService.ts b/webapp/packages/core-theming/src/ThemeSettingsService.ts new file mode 100644 index 0000000000..e5955cef3c --- /dev/null +++ b/webapp/packages/core-theming/src/ThemeSettingsService.ts @@ -0,0 +1,27 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2021 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +import { injectable } from '@cloudbeaver/core-di'; +import { PluginManagerService } from '@cloudbeaver/core-plugin'; + +import { themes } from './themes'; + +interface IDefaultSettings { + defaultTheme: string; +} + +export const defaultThemeSettings: IDefaultSettings = { + defaultTheme: themes[0].id, +}; + +@injectable() +export class ThemeSettingsService { + readonly settings = this.pluginManagerService.getPluginSettings('core.user', defaultThemeSettings); + + constructor(private readonly pluginManagerService: PluginManagerService) { } +} diff --git a/webapp/packages/core-theming/src/index.ts b/webapp/packages/core-theming/src/index.ts index 04c8861a8e..82d7de56e7 100644 --- a/webapp/packages/core-theming/src/index.ts +++ b/webapp/packages/core-theming/src/index.ts @@ -1,3 +1,4 @@ export * from './ThemeService'; export * from './themeUtils'; export * from './useStyles'; +export * from './ThemeSettingsService';