mirror of https://github.com/vector-im/riot-web
Merge remote-tracking branch 'origin/develop' into matthew/nunito-ransom-fix
commit
3409ad97d8
|
@ -59,7 +59,7 @@ import { ValidatedServerConfig } from "../../utils/AutoDiscoveryUtils";
|
||||||
import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
|
import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
|
||||||
import DMRoomMap from '../../utils/DMRoomMap';
|
import DMRoomMap from '../../utils/DMRoomMap';
|
||||||
import { countRoomsWithNotif } from '../../RoomNotifs';
|
import { countRoomsWithNotif } from '../../RoomNotifs';
|
||||||
import { setTheme } from "../../theme";
|
import { ThemeWatcher } from "../../theme";
|
||||||
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
||||||
import { defer } from "../../utils/promise";
|
import { defer } from "../../utils/promise";
|
||||||
|
|
||||||
|
@ -274,7 +274,8 @@ export default createReactClass({
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
this._themeWatchRef = SettingsStore.watchSetting("theme", null, this._onThemeChanged);
|
this._themeWatcher = new ThemeWatcher();
|
||||||
|
this._themeWatcher.start();
|
||||||
|
|
||||||
this.focusComposer = false;
|
this.focusComposer = false;
|
||||||
|
|
||||||
|
@ -361,7 +362,7 @@ export default createReactClass({
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
Lifecycle.stopMatrixClient();
|
Lifecycle.stopMatrixClient();
|
||||||
dis.unregister(this.dispatcherRef);
|
dis.unregister(this.dispatcherRef);
|
||||||
SettingsStore.unwatchSetting(this._themeWatchRef);
|
this._themeWatcher.stop();
|
||||||
window.removeEventListener("focus", this.onFocus);
|
window.removeEventListener("focus", this.onFocus);
|
||||||
window.removeEventListener('resize', this.handleResize);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize);
|
this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize);
|
||||||
|
@ -384,13 +385,6 @@ export default createReactClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onThemeChanged: function(settingName, roomId, atLevel, newValue) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'set_theme',
|
|
||||||
value: newValue,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
startPageChangeTimer() {
|
startPageChangeTimer() {
|
||||||
// Tor doesn't support performance
|
// Tor doesn't support performance
|
||||||
if (!performance || !performance.mark) return null;
|
if (!performance || !performance.mark) return null;
|
||||||
|
@ -672,9 +666,6 @@ export default createReactClass({
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'set_theme':
|
|
||||||
setTheme(payload.value);
|
|
||||||
break;
|
|
||||||
case 'on_logging_in':
|
case 'on_logging_in':
|
||||||
// We are now logging in, so set the state to reflect that
|
// We are now logging in, so set the state to reflect that
|
||||||
// NB. This does not touch 'ready' since if our dispatches
|
// NB. This does not touch 'ready' since if our dispatches
|
||||||
|
|
|
@ -34,7 +34,7 @@ import dis from '../../../dispatcher';
|
||||||
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
||||||
const ENABLE_REACT_PERF = false;
|
const ENABLE_REACT_PERF = false;
|
||||||
|
@ -69,8 +69,11 @@ export default class AppTile extends React.Component {
|
||||||
* @return {Object} Updated component state to be set with setState
|
* @return {Object} Updated component state to be set with setState
|
||||||
*/
|
*/
|
||||||
_getNewState(newProps) {
|
_getNewState(newProps) {
|
||||||
const widgetPermissionId = [newProps.room.roomId, encodeURIComponent(newProps.url)].join('_');
|
// This is a function to make the impact of calling SettingsStore slightly less
|
||||||
const hasPermissionToLoad = localStorage.getItem(widgetPermissionId);
|
const hasPermissionToLoad = () => {
|
||||||
|
const currentlyAllowedWidgets = SettingsStore.getValue("allowedWidgets", newProps.room.roomId);
|
||||||
|
return !!currentlyAllowedWidgets[newProps.eventId];
|
||||||
|
};
|
||||||
|
|
||||||
const PersistedElement = sdk.getComponent("elements.PersistedElement");
|
const PersistedElement = sdk.getComponent("elements.PersistedElement");
|
||||||
return {
|
return {
|
||||||
|
@ -78,10 +81,9 @@ export default class AppTile extends React.Component {
|
||||||
// True while the iframe content is loading
|
// True while the iframe content is loading
|
||||||
loading: this.props.waitForIframeLoad && !PersistedElement.isMounted(this._persistKey),
|
loading: this.props.waitForIframeLoad && !PersistedElement.isMounted(this._persistKey),
|
||||||
widgetUrl: this._addWurlParams(newProps.url),
|
widgetUrl: this._addWurlParams(newProps.url),
|
||||||
widgetPermissionId: widgetPermissionId,
|
|
||||||
// Assume that widget has permission to load if we are the user who
|
// Assume that widget has permission to load if we are the user who
|
||||||
// added it to the room, or if explicitly granted by the user
|
// added it to the room, or if explicitly granted by the user
|
||||||
hasPermissionToLoad: hasPermissionToLoad === 'true' || newProps.userId === newProps.creatorUserId,
|
hasPermissionToLoad: newProps.userId === newProps.creatorUserId || hasPermissionToLoad(),
|
||||||
error: null,
|
error: null,
|
||||||
deleting: false,
|
deleting: false,
|
||||||
widgetPageTitle: newProps.widgetPageTitle,
|
widgetPageTitle: newProps.widgetPageTitle,
|
||||||
|
@ -446,24 +448,38 @@ export default class AppTile extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO -- Store permission in account data so that it is persisted across multiple devices */
|
|
||||||
_grantWidgetPermission() {
|
_grantWidgetPermission() {
|
||||||
console.warn('Granting permission to load widget - ', this.state.widgetUrl);
|
const roomId = this.props.room.roomId;
|
||||||
localStorage.setItem(this.state.widgetPermissionId, true);
|
console.info("Granting permission for widget to load: " + this.props.eventId);
|
||||||
this.setState({hasPermissionToLoad: true});
|
const current = SettingsStore.getValue("allowedWidgets", roomId);
|
||||||
// Now that we have permission, fetch the IM token
|
current[this.props.eventId] = true;
|
||||||
this.setScalarToken();
|
SettingsStore.setValue("allowedWidgets", roomId, SettingLevel.ROOM_ACCOUNT, current).then(() => {
|
||||||
|
this.setState({hasPermissionToLoad: true});
|
||||||
|
|
||||||
|
// Fetch a token for the integration manager, now that we're allowed to
|
||||||
|
this.setScalarToken();
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
// We don't really need to do anything about this - the user will just hit the button again.
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_revokeWidgetPermission() {
|
_revokeWidgetPermission() {
|
||||||
console.warn('Revoking permission to load widget - ', this.state.widgetUrl);
|
const roomId = this.props.room.roomId;
|
||||||
localStorage.removeItem(this.state.widgetPermissionId);
|
console.info("Revoking permission for widget to load: " + this.props.eventId);
|
||||||
this.setState({hasPermissionToLoad: false});
|
const current = SettingsStore.getValue("allowedWidgets", roomId);
|
||||||
|
current[this.props.eventId] = false;
|
||||||
|
SettingsStore.setValue("allowedWidgets", roomId, SettingLevel.ROOM_ACCOUNT, current).then(() => {
|
||||||
|
this.setState({hasPermissionToLoad: false});
|
||||||
|
|
||||||
// Force the widget to be non-persistent
|
// Force the widget to be non-persistent (able to be deleted/forgotten)
|
||||||
ActiveWidgetStore.destroyPersistentWidget(this.props.id);
|
ActiveWidgetStore.destroyPersistentWidget(this.props.id);
|
||||||
const PersistedElement = sdk.getComponent("elements.PersistedElement");
|
const PersistedElement = sdk.getComponent("elements.PersistedElement");
|
||||||
PersistedElement.destroyElement(this._persistKey);
|
PersistedElement.destroyElement(this._persistKey);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
// We don't really need to do anything about this - the user will just hit the button again.
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formatAppTileName() {
|
formatAppTileName() {
|
||||||
|
@ -720,6 +736,7 @@ AppTile.displayName ='AppTile';
|
||||||
|
|
||||||
AppTile.propTypes = {
|
AppTile.propTypes = {
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
|
eventId: PropTypes.string, // required for room widgets
|
||||||
url: PropTypes.string.isRequired,
|
url: PropTypes.string.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
room: PropTypes.object.isRequired,
|
room: PropTypes.object.isRequired,
|
||||||
|
|
|
@ -67,13 +67,15 @@ module.exports = createReactClass({
|
||||||
return ev.getStateKey() === ActiveWidgetStore.getPersistentWidgetId();
|
return ev.getStateKey() === ActiveWidgetStore.getPersistentWidgetId();
|
||||||
});
|
});
|
||||||
const app = WidgetUtils.makeAppConfig(
|
const app = WidgetUtils.makeAppConfig(
|
||||||
appEvent.getStateKey(), appEvent.getContent(), appEvent.getSender(), persistentWidgetInRoomId,
|
appEvent.getStateKey(), appEvent.getContent(), appEvent.getSender(),
|
||||||
|
persistentWidgetInRoomId, appEvent.getId(),
|
||||||
);
|
);
|
||||||
const capWhitelist = WidgetUtils.getCapWhitelistForAppTypeInRoomId(app.type, persistentWidgetInRoomId);
|
const capWhitelist = WidgetUtils.getCapWhitelistForAppTypeInRoomId(app.type, persistentWidgetInRoomId);
|
||||||
const AppTile = sdk.getComponent('elements.AppTile');
|
const AppTile = sdk.getComponent('elements.AppTile');
|
||||||
return <AppTile
|
return <AppTile
|
||||||
key={app.id}
|
key={app.id}
|
||||||
id={app.id}
|
id={app.id}
|
||||||
|
eventId={app.eventId}
|
||||||
url={app.url}
|
url={app.url}
|
||||||
name={app.name}
|
name={app.name}
|
||||||
type={app.type}
|
type={app.type}
|
||||||
|
|
|
@ -107,7 +107,9 @@ module.exports = createReactClass({
|
||||||
this.props.room.roomId, WidgetUtils.getRoomWidgets(this.props.room),
|
this.props.room.roomId, WidgetUtils.getRoomWidgets(this.props.room),
|
||||||
);
|
);
|
||||||
return widgets.map((ev) => {
|
return widgets.map((ev) => {
|
||||||
return WidgetUtils.makeAppConfig(ev.getStateKey(), ev.getContent(), ev.getSender());
|
return WidgetUtils.makeAppConfig(
|
||||||
|
ev.getStateKey(), ev.getContent(), ev.getSender(), ev.getRoomId(), ev.getId(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -159,6 +161,7 @@ module.exports = createReactClass({
|
||||||
return (<AppTile
|
return (<AppTile
|
||||||
key={app.id}
|
key={app.id}
|
||||||
id={app.id}
|
id={app.id}
|
||||||
|
eventId={app.eventId}
|
||||||
url={app.url}
|
url={app.url}
|
||||||
name={app.name}
|
name={app.name}
|
||||||
type={app.type}
|
type={app.type}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import LanguageDropdown from "../../../elements/LanguageDropdown";
|
||||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||||
import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog";
|
import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {enumerateThemes} from "../../../../../theme";
|
import {enumerateThemes, ThemeWatcher} from "../../../../../theme";
|
||||||
import PlatformPeg from "../../../../../PlatformPeg";
|
import PlatformPeg from "../../../../../PlatformPeg";
|
||||||
import MatrixClientPeg from "../../../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../../../MatrixClientPeg";
|
||||||
import sdk from "../../../../..";
|
import sdk from "../../../../..";
|
||||||
|
@ -50,6 +50,7 @@ export default class GeneralUserSettingsTab extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
language: languageHandler.getCurrentLanguage(),
|
language: languageHandler.getCurrentLanguage(),
|
||||||
theme: SettingsStore.getValueAt(SettingLevel.ACCOUNT, "theme"),
|
theme: SettingsStore.getValueAt(SettingLevel.ACCOUNT, "theme"),
|
||||||
|
useSystemTheme: SettingsStore.getValueAt(SettingLevel.DEVICE, "use_system_theme"),
|
||||||
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
|
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
|
||||||
serverSupportsSeparateAddAndBind: null,
|
serverSupportsSeparateAddAndBind: null,
|
||||||
idServerHasUnsignedTerms: false,
|
idServerHasUnsignedTerms: false,
|
||||||
|
@ -177,16 +178,25 @@ export default class GeneralUserSettingsTab extends React.Component {
|
||||||
// so remember what the value was before we tried to set it so we can revert
|
// so remember what the value was before we tried to set it so we can revert
|
||||||
const oldTheme = SettingsStore.getValue('theme');
|
const oldTheme = SettingsStore.getValue('theme');
|
||||||
SettingsStore.setValue("theme", null, SettingLevel.ACCOUNT, newTheme).catch(() => {
|
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: oldTheme});
|
||||||
});
|
});
|
||||||
this.setState({theme: newTheme});
|
this.setState({theme: newTheme});
|
||||||
// The settings watcher doesn't fire until the echo comes back from the
|
// 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
|
// server, so to make the theme change immediately we need to manually
|
||||||
// do the dispatch now
|
// do the dispatch now
|
||||||
dis.dispatch({action: 'set_theme', value: newTheme});
|
// XXX: The local echoed value appears to be unreliable, in particular
|
||||||
|
// when settings custom themes(!) so adding forceTheme to override
|
||||||
|
// the value from settings.
|
||||||
|
dis.dispatch({action: 'recheck_theme', forceTheme: newTheme});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_onUseSystemThemeChanged = (checked) => {
|
||||||
|
this.setState({useSystemTheme: checked});
|
||||||
|
dis.dispatch({action: 'recheck_theme'});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_onPasswordChangeError = (err) => {
|
_onPasswordChangeError = (err) => {
|
||||||
// TODO: Figure out a design that doesn't involve replacing the current dialog
|
// TODO: Figure out a design that doesn't involve replacing the current dialog
|
||||||
let errMsg = err.error || "";
|
let errMsg = err.error || "";
|
||||||
|
@ -297,11 +307,24 @@ export default class GeneralUserSettingsTab extends React.Component {
|
||||||
|
|
||||||
_renderThemeSection() {
|
_renderThemeSection() {
|
||||||
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
|
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 (
|
return (
|
||||||
<div className="mx_SettingsTab_section mx_GeneralUserSettingsTab_themeSection">
|
<div className="mx_SettingsTab_section mx_GeneralUserSettingsTab_themeSection">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Theme")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("Theme")}</span>
|
||||||
|
{systemThemeSection}
|
||||||
<Field id="theme" label={_t("Theme")} element="select"
|
<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]) => {
|
{Object.entries(enumerateThemes()).map(([theme, text]) => {
|
||||||
return <option key={theme} value={theme}>{text}</option>;
|
return <option key={theme} value={theme}>{text}</option>;
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -364,6 +364,7 @@
|
||||||
"Automatically replace plain text Emoji": "Automatically replace plain text Emoji",
|
"Automatically replace plain text Emoji": "Automatically replace plain text Emoji",
|
||||||
"Mirror local video feed": "Mirror local video feed",
|
"Mirror local video feed": "Mirror local video feed",
|
||||||
"Enable Community Filter Panel": "Enable Community Filter Panel",
|
"Enable Community Filter Panel": "Enable Community Filter Panel",
|
||||||
|
"Match system dark mode setting": "Match system dark mode setting",
|
||||||
"Allow Peer-to-Peer for 1:1 calls": "Allow Peer-to-Peer for 1:1 calls",
|
"Allow Peer-to-Peer for 1:1 calls": "Allow Peer-to-Peer for 1:1 calls",
|
||||||
"Send analytics data": "Send analytics data",
|
"Send analytics data": "Send analytics data",
|
||||||
"Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device",
|
"Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device",
|
||||||
|
|
|
@ -281,6 +281,11 @@ export const SETTINGS = {
|
||||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
default: [],
|
default: [],
|
||||||
},
|
},
|
||||||
|
"use_system_theme": {
|
||||||
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||||
|
default: true,
|
||||||
|
displayName: _td("Match system dark mode setting"),
|
||||||
|
},
|
||||||
"webRtcAllowPeerToPeer": {
|
"webRtcAllowPeerToPeer": {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||||
displayName: _td('Allow Peer-to-Peer for 1:1 calls'),
|
displayName: _td('Allow Peer-to-Peer for 1:1 calls'),
|
||||||
|
|
70
src/theme.js
70
src/theme.js
|
@ -19,8 +19,75 @@ import {_t} from "./languageHandler";
|
||||||
|
|
||||||
export const DEFAULT_THEME = "light";
|
export const DEFAULT_THEME = "light";
|
||||||
import Tinter from "./Tinter";
|
import Tinter from "./Tinter";
|
||||||
|
import dis from "./dispatcher";
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
|
|
||||||
|
export class ThemeWatcher {
|
||||||
|
static _instance = null;
|
||||||
|
|
||||||
|
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 = global.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
this._preferLight = global.matchMedia("(prefers-color-scheme: light)");
|
||||||
|
|
||||||
|
this._currentTheme = this.getEffectiveTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this._themeWatchRef = SettingsStore.watchSetting("theme", null, this._onChange);
|
||||||
|
this._systemThemeWatchRef = SettingsStore.watchSetting("use_system_theme", null, this._onChange);
|
||||||
|
this._preferDark.addEventListener('change', this._onChange);
|
||||||
|
this._preferLight.addEventListener('change', this._onChange);
|
||||||
|
this._dispatcherRef = dis.register(this._onAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this._preferDark.removeEventListener('change', this._onChange);
|
||||||
|
this._preferLight.removeEventListener('change', this._onChange);
|
||||||
|
SettingsStore.unwatchSetting(this._systemThemeWatchRef);
|
||||||
|
SettingsStore.unwatchSetting(this._themeWatchRef);
|
||||||
|
dis.unregister(this._dispatcherRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onChange = () => {
|
||||||
|
this.recheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAction = (payload) => {
|
||||||
|
if (payload.action === 'recheck_theme') {
|
||||||
|
// XXX forceTheme
|
||||||
|
this.recheck(payload.forceTheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: forceTheme param aded here as local echo appears to be unreliable
|
||||||
|
// https://github.com/vector-im/riot-web/issues/11443
|
||||||
|
recheck(forceTheme) {
|
||||||
|
const oldTheme = this._currentTheme;
|
||||||
|
this._currentTheme = forceTheme === undefined ? this.getEffectiveTheme() : forceTheme;
|
||||||
|
if (oldTheme !== this._currentTheme) {
|
||||||
|
setTheme(this._currentTheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEffectiveTheme() {
|
||||||
|
if (SettingsStore.getValue('use_system_theme')) {
|
||||||
|
if (this._preferDark.matches) return 'dark';
|
||||||
|
if (this._preferLight.matches) return 'light';
|
||||||
|
}
|
||||||
|
return SettingsStore.getValue('theme');
|
||||||
|
}
|
||||||
|
|
||||||
|
isSystemThemeSupported() {
|
||||||
|
return this._preferDark.matches || this._preferLight.matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function enumerateThemes() {
|
export function enumerateThemes() {
|
||||||
const BUILTIN_THEMES = {
|
const BUILTIN_THEMES = {
|
||||||
"light": _t("Light theme"),
|
"light": _t("Light theme"),
|
||||||
|
@ -83,7 +150,8 @@ export function getBaseTheme(theme) {
|
||||||
*/
|
*/
|
||||||
export function setTheme(theme) {
|
export function setTheme(theme) {
|
||||||
if (!theme) {
|
if (!theme) {
|
||||||
theme = SettingsStore.getValue("theme");
|
const themeWatcher = new ThemeWatcher();
|
||||||
|
theme = themeWatcher.getEffectiveTheme();
|
||||||
}
|
}
|
||||||
let stylesheetName = theme;
|
let stylesheetName = theme;
|
||||||
if (theme.startsWith("custom-")) {
|
if (theme.startsWith("custom-")) {
|
||||||
|
|
|
@ -400,7 +400,7 @@ export default class WidgetUtils {
|
||||||
return client.setAccountData('m.widgets', userWidgets);
|
return client.setAccountData('m.widgets', userWidgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
static makeAppConfig(appId, app, senderUserId, roomId) {
|
static makeAppConfig(appId, app, senderUserId, roomId, eventId) {
|
||||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
const myUserId = MatrixClientPeg.get().credentials.userId;
|
||||||
const user = MatrixClientPeg.get().getUser(myUserId);
|
const user = MatrixClientPeg.get().getUser(myUserId);
|
||||||
const params = {
|
const params = {
|
||||||
|
@ -419,6 +419,7 @@ export default class WidgetUtils {
|
||||||
app.creatorUserId = senderUserId;
|
app.creatorUserId = senderUserId;
|
||||||
|
|
||||||
app.id = appId;
|
app.id = appId;
|
||||||
|
app.eventId = eventId;
|
||||||
app.name = app.name || app.type;
|
app.name = app.name || app.type;
|
||||||
|
|
||||||
if (app.data) {
|
if (app.data) {
|
||||||
|
|
Loading…
Reference in New Issue