Get theme automatically from system setting

Uses CSS `prefers-color-scheme` to get the user's preferred colour
scheme. Also bundles up some theme logic into its own class.
This commit is contained in:
David Baker 2019-11-20 13:41:06 +00:00
parent 55e5e63199
commit 5a700b518a
5 changed files with 100 additions and 18 deletions

View file

@ -27,7 +27,7 @@ import LanguageDropdown from "../../../elements/LanguageDropdown";
import AccessibleButton from "../../../elements/AccessibleButton";
import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog";
import PropTypes from "prop-types";
import {enumerateThemes} from "../../../../../theme";
import {enumerateThemes, ThemeWatcher} from "../../../../../theme";
import PlatformPeg from "../../../../../PlatformPeg";
import MatrixClientPeg from "../../../../../MatrixClientPeg";
import sdk from "../../../../..";
@ -50,6 +50,7 @@ export default class GeneralUserSettingsTab extends React.Component {
this.state = {
language: languageHandler.getCurrentLanguage(),
theme: SettingsStore.getValueAt(SettingLevel.ACCOUNT, "theme"),
useSystemTheme: SettingsStore.getValueAt(SettingLevel.DEVICE, "use_system_theme"),
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
serverSupportsSeparateAddAndBind: null,
idServerHasUnsignedTerms: false,
@ -177,16 +178,22 @@ export default class GeneralUserSettingsTab extends React.Component {
// so remember what the value was before we tried to set it so we can revert
const oldTheme = SettingsStore.getValue('theme');
SettingsStore.setValue("theme", null, SettingLevel.ACCOUNT, newTheme).catch(() => {
dis.dispatch({action: 'set_theme', value: oldTheme});
dis.dispatch({action: 'recheck_theme'});
this.setState({theme: oldTheme});
});
this.setState({theme: newTheme});
// The settings watcher doesn't fire until the echo comes back from the
// server, so to make the theme change immediately we need to manually
// do the dispatch now
dis.dispatch({action: 'set_theme', value: newTheme});
dis.dispatch({action: 'recheck_theme'});
};
_onUseSystemThemeChanged = (checked) => {
this.setState({useSystemTheme: checked});
dis.dispatch({action: 'recheck_theme'});
}
_onPasswordChangeError = (err) => {
// TODO: Figure out a design that doesn't involve replacing the current dialog
let errMsg = err.error || "";
@ -297,11 +304,24 @@ export default class GeneralUserSettingsTab extends React.Component {
_renderThemeSection() {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
const themeWatcher = new ThemeWatcher();
let systemThemeSection;
if (themeWatcher.isSystemThemeSupported()) {
systemThemeSection = <div>
<SettingsFlag name="use_system_theme" level={SettingLevel.DEVICE}
onChange={this._onUseSystemThemeChanged}
/>
</div>;
}
return (
<div className="mx_SettingsTab_section mx_GeneralUserSettingsTab_themeSection">
<span className="mx_SettingsTab_subheading">{_t("Theme")}</span>
{systemThemeSection}
<Field id="theme" label={_t("Theme")} element="select"
value={this.state.theme} onChange={this._onThemeChange}>
value={this.state.theme} onChange={this._onThemeChange}
disabled={this.state.useSystemTheme}
>
{Object.entries(enumerateThemes()).map(([theme, text]) => {
return <option key={theme} value={theme}>{text}</option>;
})}