import { Injectable } from '@angular/core';
import { Theme } from 'ng-devui/theme';
import { ReplaySubject } from 'rxjs';
import { ThemeType } from 'src/app/@shared/models/theme';
import { LARGE_RADIUS, LARGE_SIZE, MEDIUM_RADIUS, MEDIUM_SIZE, NORMAL_RADIUS, NORMAL_SIZE } from 'src/config/custom-theme';
import { CustomThemeService } from './custom-theme.service';
export interface ThemeConfigItem {
name: string;
id: string;
data: {
'devui-border-radius'?: string;
'devui-border-radius-card'?: string;
'devui-font-size'?: string;
'devui-font-size-card-title'?: string;
'devui-font-size-page-title'?: string;
'devui-font-size-modal-title'?: string;
'devui-font-size-price'?: string;
'devui-font-size-data-overview'?: string;
'devui-font-size-icon'?: string;
'devui-font-size-sm'?: string;
'devui-font-size-md'?: string;
'devui-font-size-lg'?: string;
};
}
export interface ThemeConfig {
name: 'themes' | 'font' | 'radius';
icon: string;
items: ThemeConfigItem[];
}
@Injectable()
export class PersonalizeService {
themes: ThemeConfigItem[] = [];
private _themeChange = new ReplaySubject<any>(1);
configs: ThemeConfig[] = [
{
name: 'themes',
icon: 'icon-color',
items: [],
},
{
name: 'font',
icon: 'icon-font',
items: [
{
name: 'normal',
id: 'normal',
data: NORMAL_SIZE,
},
{
name: 'medium',
id: 'medium',
data: MEDIUM_SIZE,
},
{
name: 'large',
id: 'large',
data: LARGE_SIZE,
},
],
},
{
name: 'radius',
icon: 'icon-quick-stop',
items: [
{
name: 'normal',
id: 'normal',
data: NORMAL_RADIUS,
},
{
name: 'medium',
id: 'medium',
data: MEDIUM_RADIUS,
},
{
name: 'large',
id: 'large',
data: LARGE_RADIUS,
},
],
},
];
defaultCustom = {
brand: '#343a40',
isDark: false,
};
constructor(private customThemeService: CustomThemeService) {}
initTheme() {
if ((window as { [key: string]: any })['devuiThemes']) {
(window as { [key: string]: any })['devuiThemes'].devuiDarkTheme.data['devui-placeholder'] = '#8A8A8A';
this.themes = Object.values((window as { [key: string]: any })['devuiThemes']);
const { brand, isDark } = localStorage.getItem('user-custom-theme-config')
? JSON.parse(localStorage.getItem('user-custom-theme-config')!)
: this.defaultCustom;
const themeData = this.getCustomThemeData(brand, isDark);
this.setTheme((window as { [key: string]: any })['devuiThemes']['customTheme'], themeData, isDark);
this.configs[0].items = this.themes;
const themeId = localStorage.getItem('theme') || this.themes[0].id;
const fontId = localStorage.getItem('font') || this.configs[1].items[0].id;
const radiusId = localStorage.getItem('radius') || this.configs[2].items[0].id;
this.changeTheme(themeId, fontId, radiusId);
}
}
changeTheme(themeId: string, fId?: string, rId?: string) {
let theme: Theme;
const themes = (this.configs[0].items as any).filter((i: ThemeConfigItem) => {
return i.id === themeId;
});
const { radiusId, fontId, fontData, radiusData } = this.getSizeAndRadiusData(fId, rId);
const customData = Object.assign({}, fontData, radiusData);
if (themes.length) {
theme = themes[0];
} else {
theme = this.configs[0].items[0];
}
theme.data = Object.assign(theme.data, customData);
(window as { [key: string]: any })['devuiThemeService'].applyTheme(theme);
localStorage.setItem('theme', theme.id);
localStorage.setItem('font', fontId);
localStorage.setItem('radius', radiusId);
}
getCustomThemeData(color: string, isDark: boolean) {
const themeData = this.customThemeService.genThemeData(
[
{
colorName: 'devui-brand',
color: color,
},
],
isDark,
'hsl'
);
return themeData;
}
setTheme(theme: any, themeData: any, isDark: boolean) {
Object.assign(theme, {
data: themeData,
isDark,
});
}
getSizeAndRadiusData(fId?: string, rId?: string) {
const fontId = fId || localStorage.getItem('font') || this.configs[1].items[0].id;
const radiusId = rId || localStorage.getItem('radius') || this.configs[2].items[0].id;
const fonts = (this.configs[1].items as any).filter((font: any) => {
return font.id === fontId;
});
const radiusList = (this.configs[2].items as any).filter((radius: any) => {
return radius.id === radiusId;
});
return {
fontId,
radiusId,
fontData: fonts[0].data,
radiusData: radiusList[0].data,
};
}
setCustomThemeData(themeData: any, color: string, isDark: boolean) {
const len = this.configs[0].items.length;
const theme = this.configs[0].items[len - 1];
const { fontData, radiusData } = this.getSizeAndRadiusData();
Object.assign(themeData, fontData, radiusData);
this.setTheme(theme, color, isDark);
theme.data = Object.assign(theme.data, themeData);
(window as { [key: string]: any })['devuiThemeService'].applyTheme(theme);
localStorage.setItem('user-custom-theme-config', JSON.stringify({ brand: color, isDark }));
localStorage.setItem('theme', ThemeType.Custom);
}
setUiTheme() {
const currentTheme = (window as { [key: string]: any })['devuiCurrentTheme'] || ThemeType.Default;
this._themeChange.next(currentTheme);
}
getUiTheme() {
const themeService = (window as { [key: string]: any })['devuiThemeService'];
this.setUiTheme();
if (!(themeService && themeService.eventBus)) {
return;
}
const themeChangedFunc = () => {
this.setUiTheme();
};
themeService.eventBus.add('themeChanged', themeChangedFunc);
return this._themeChange.asObservable();
}
setRefTheme(themeId: string) {
const devuiThemes = Object.values((window as { [key: string]: any })['devuiThemes']);
const themes = devuiThemes.filter((i: Theme | unknown) => (i as Theme).id === themeId);
if (themes.length) {
(window as { [key: string]: any })['devuiThemeService'].applyTheme(themes[0]);
}
}
}