Move Appearance tab to ts

This commit is contained in:
Jorik Schellekens 2020-05-28 13:55:07 +01:00
parent 0fd5714e21
commit 81922231ed
9 changed files with 295 additions and 180 deletions

View file

@ -0,0 +1,55 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed 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 dis from '../../dispatcher/dispatcher';
import SettingsStore, {SettingLevel} from '../SettingsStore';
import IWatcher from "./Watcher";
import { toPx } from '../../utils/units';
export class FontWatcher implements IWatcher {
public static readonly MIN_SIZE = 13;
public static readonly MAX_SIZE = 20;
private dispatcherRef: string;
constructor() {
this.dispatcherRef = null;
}
public start() {
this.setRootFontSize(SettingsStore.getValue("fontSize"));
this.dispatcherRef = dis.register(this.onAction);
}
public stop() {
dis.unregister(this.dispatcherRef);
}
private onAction = (payload) => {
if (payload.action === 'update-font-size') {
this.setRootFontSize(payload.size);
}
};
private setRootFontSize = (size) => {
const fontSize = Math.max(Math.min(FontWatcher.MAX_SIZE, size), FontWatcher.MIN_SIZE);
if (fontSize !== size) {
SettingsStore.setValue("fontSize", null, SettingLevel.Device, fontSize);
}
(<HTMLElement>document.querySelector(":root")).style.fontSize = toPx(fontSize);
};
}

View file

@ -0,0 +1,138 @@
/*
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
Licensed 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 SettingsStore, { SettingLevel } from '../SettingsStore';
import dis from '../../dispatcher/dispatcher';
import { Action } from '../../dispatcher/actions';
import ThemeController from "../controllers/ThemeController";
import { setTheme } from "../../theme";
import { ActionPayload } from '../../dispatcher/payloads';
export default class ThemeWatcher {
// XXX: I think this is unused.
static _instance = null;
private themeWatchRef: string;
private systemThemeWatchRef: string;
private dispatcherRef: string;
private preferDark: MediaQueryList;
private preferLight: MediaQueryList;
private currentTheme: string;
constructor() {
this.themeWatchRef = null;
this.systemThemeWatchRef = null;
this.dispatcherRef = null;
// we have both here as each may either match or not match, so by having both
// we can get the tristate of dark/light/unsupported
this.preferDark = (<any>global).matchMedia("(prefers-color-scheme: dark)");
this.preferLight = (<any>global).matchMedia("(prefers-color-scheme: light)");
this.currentTheme = this.getEffectiveTheme();
}
public start() {
this.themeWatchRef = SettingsStore.watchSetting("theme", null, this.onChange);
this.systemThemeWatchRef = SettingsStore.watchSetting("use_system_theme", null, this.onChange);
if (this.preferDark.addEventListener) {
this.preferDark.addEventListener('change', this.onChange);
this.preferLight.addEventListener('change', this.onChange);
}
this.dispatcherRef = dis.register(this.onAction);
}
public stop() {
if (this.preferDark.addEventListener) {
this.preferDark.removeEventListener('change', this.onChange);
this.preferLight.removeEventListener('change', this.onChange);
}
SettingsStore.unwatchSetting(this.systemThemeWatchRef);
SettingsStore.unwatchSetting(this.themeWatchRef);
dis.unregister(this.dispatcherRef);
}
private onChange = () => {
this.recheck();
};
private onAction = (payload: ActionPayload) => {
if (payload.action === Action.RecheckTheme) {
// XXX forceTheme
this.recheck(payload.forceTheme);
}
};
// XXX: forceTheme param added here as local echo appears to be unreliable
// https://github.com/vector-im/riot-web/issues/11443
public recheck(forceTheme?: string) {
const oldTheme = this.currentTheme;
this.currentTheme = forceTheme === undefined ? this.getEffectiveTheme() : forceTheme;
if (oldTheme !== this.currentTheme) {
setTheme(this.currentTheme);
}
}
public getEffectiveTheme(): string {
// Dev note: Much of this logic is replicated in the AppearanceUserSettingsTab
// XXX: checking the isLight flag here makes checking it in the ThemeController
// itself completely redundant since we just override the result here and we're
// now effectively just using the ThemeController as a place to store the static
// variable. The system theme setting probably ought to have an equivalent
// controller that honours the same flag, although probablt better would be to
// have the theme logic in one place rather than split between however many
// different places.
if (ThemeController.isLogin) return 'light';
// If the user has specifically enabled the system matching option (excluding default),
// then use that over anything else. We pick the lowest possible level for the setting
// to ensure the ordering otherwise works.
const systemThemeExplicit = SettingsStore.getValueAt(
SettingLevel.DEVICE, "use_system_theme", null, false, true);
if (systemThemeExplicit) {
console.log("returning explicit system theme");
if (this.preferDark.matches) return 'dark';
if (this.preferLight.matches) return 'light';
}
// If the user has specifically enabled the theme (without the system matching option being
// enabled specifically and excluding the default), use that theme. We pick the lowest possible
// level for the setting to ensure the ordering otherwise works.
const themeExplicit = SettingsStore.getValueAt(
SettingLevel.DEVICE, "theme", null, false, true);
if (themeExplicit) {
console.log("returning explicit theme: " + themeExplicit);
return themeExplicit;
}
// If the user hasn't really made a preference in either direction, assume the defaults of the
// settings and use those.
if (SettingsStore.getValue('use_system_theme')) {
if (this.preferDark.matches) return 'dark';
if (this.preferLight.matches) return 'light';
}
console.log("returning theme value");
return SettingsStore.getValue('theme');
}
public isSystemThemeSupported() {
return this.preferDark.matches || this.preferLight.matches;
}
}

View file

@ -0,0 +1,20 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed 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.
*/
export default interface IWatcher {
start(): void
stop(): void
}