110 lines
3.1 KiB
TypeScript
110 lines
3.1 KiB
TypeScript
/*
|
|
* https://github.com/morethanwords/tweb
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
*/
|
|
|
|
import type {AppTheme} from '../config/state';
|
|
import IS_TOUCH_SUPPORTED from '../environment/touchSupport';
|
|
import rootScope from '../lib/rootScope';
|
|
import {hslaStringToHex} from './color';
|
|
|
|
export class ThemeController {
|
|
private themeColor: string;
|
|
private _themeColorElem: Element;
|
|
private systemTheme: AppTheme['name'];
|
|
|
|
constructor() {
|
|
rootScope.addEventListener('theme_change', () => {
|
|
this.setTheme();
|
|
});
|
|
|
|
// rootScope.addEventListener('settings_updated', ())
|
|
}
|
|
|
|
private get themeColorElem() {
|
|
if(this._themeColorElem !== undefined) {
|
|
return this._themeColorElem;
|
|
}
|
|
|
|
return this._themeColorElem = document.head.querySelector('[name="theme-color"]') as Element || null;
|
|
}
|
|
|
|
public setThemeColor(color = this.themeColor) {
|
|
if(!color) {
|
|
color = this.isNight() ? '#212121' : '#ffffff';
|
|
}
|
|
|
|
const themeColorElem = this.themeColorElem;
|
|
if(themeColorElem) {
|
|
themeColorElem.setAttribute('content', color);
|
|
}
|
|
}
|
|
|
|
public setThemeListener() {
|
|
try {
|
|
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
const checkDarkMode = () => {
|
|
// const theme = this.getTheme();
|
|
this.systemTheme = darkModeMediaQuery.matches ? 'night' : 'day';
|
|
// const newTheme = this.getTheme();
|
|
|
|
if(rootScope.myId) {
|
|
rootScope.dispatchEvent('theme_change');
|
|
} else {
|
|
this.setTheme();
|
|
}
|
|
};
|
|
|
|
if('addEventListener' in darkModeMediaQuery) {
|
|
darkModeMediaQuery.addEventListener('change', checkDarkMode);
|
|
} else if('addListener' in darkModeMediaQuery) {
|
|
(darkModeMediaQuery as any).addListener(checkDarkMode);
|
|
}
|
|
|
|
checkDarkMode();
|
|
} catch(err) {
|
|
|
|
}
|
|
}
|
|
|
|
public applyHighlightningColor() {
|
|
let hsla: string;
|
|
const theme = themeController.getTheme();
|
|
if(theme.settings?.highlightningColor) {
|
|
hsla = theme.settings.highlightningColor;
|
|
document.documentElement.style.setProperty('--message-highlightning-color', hsla);
|
|
} else {
|
|
document.documentElement.style.removeProperty('--message-highlightning-color');
|
|
}
|
|
|
|
if(!IS_TOUCH_SUPPORTED && hsla) {
|
|
themeController.themeColor = hslaStringToHex(hsla);
|
|
}
|
|
}
|
|
|
|
public setTheme() {
|
|
const isNight = this.isNight();
|
|
const colorScheme = document.head.querySelector('[name="color-scheme"]');
|
|
if(colorScheme) {
|
|
colorScheme.setAttribute('content', isNight ? 'dark' : 'light');
|
|
}
|
|
|
|
document.documentElement.classList.toggle('night', isNight);
|
|
this.setThemeColor();
|
|
|
|
this.applyHighlightningColor();
|
|
}
|
|
|
|
public isNight() {
|
|
return this.getTheme().name === 'night';
|
|
}
|
|
|
|
public getTheme(name: AppTheme['name'] = rootScope.settings.theme === 'system' ? this.systemTheme : rootScope.settings.theme) {
|
|
return rootScope.settings.themes.find((t) => t.name === name);
|
|
}
|
|
}
|
|
|
|
const themeController = new ThemeController();
|
|
export default themeController;
|