Merge pull request #5062 from matrix-org/travis/settings/ts
Convert SettingsStore to TypeScriptpull/21833/head
commit
3443761007
|
@ -25,6 +25,7 @@ import { PlatformPeg } from "../PlatformPeg";
|
||||||
import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
|
import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
|
||||||
import {IntegrationManagers} from "../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../integrations/IntegrationManagers";
|
||||||
import {ModalManager} from "../Modal";
|
import {ModalManager} from "../Modal";
|
||||||
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
@ -43,6 +44,7 @@ declare global {
|
||||||
mxPlatformPeg: PlatformPeg;
|
mxPlatformPeg: PlatformPeg;
|
||||||
mxIntegrationManagers: typeof IntegrationManagers;
|
mxIntegrationManagers: typeof IntegrationManagers;
|
||||||
singletonModalManager: ModalManager;
|
singletonModalManager: ModalManager;
|
||||||
|
mxSettingsStore: SettingsStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
// workaround for https://github.com/microsoft/TypeScript/issues/30933
|
// workaround for https://github.com/microsoft/TypeScript/issues/30933
|
||||||
|
|
|
@ -62,10 +62,11 @@ import Matrix from 'matrix-js-sdk';
|
||||||
import dis from './dispatcher/dispatcher';
|
import dis from './dispatcher/dispatcher';
|
||||||
import WidgetUtils from './utils/WidgetUtils';
|
import WidgetUtils from './utils/WidgetUtils';
|
||||||
import WidgetEchoStore from './stores/WidgetEchoStore';
|
import WidgetEchoStore from './stores/WidgetEchoStore';
|
||||||
import SettingsStore, { SettingLevel } from './settings/SettingsStore';
|
import SettingsStore from './settings/SettingsStore';
|
||||||
import {generateHumanReadableId} from "./utils/NamingUtils";
|
import {generateHumanReadableId} from "./utils/NamingUtils";
|
||||||
import {Jitsi} from "./widgets/Jitsi";
|
import {Jitsi} from "./widgets/Jitsi";
|
||||||
import {WidgetType} from "./widgets/WidgetType";
|
import {WidgetType} from "./widgets/WidgetType";
|
||||||
|
import {SettingLevel} from "./settings/SettingLevel";
|
||||||
|
|
||||||
global.mxCalls = {
|
global.mxCalls = {
|
||||||
//room_id: MatrixCall
|
//room_id: MatrixCall
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Matrix from 'matrix-js-sdk';
|
import * as Matrix from 'matrix-js-sdk';
|
||||||
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
|
import {SettingLevel} from "./settings/SettingLevel";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
hasAnyLabeledDevices: async function() {
|
hasAnyLabeledDevices: async function() {
|
||||||
|
|
|
@ -256,7 +256,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
|
||||||
deviceId: creds.deviceId,
|
deviceId: creds.deviceId,
|
||||||
pickleKey: creds.pickleKey,
|
pickleKey: creds.pickleKey,
|
||||||
timelineSupport: true,
|
timelineSupport: true,
|
||||||
forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer', false),
|
forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer'),
|
||||||
fallbackICEServerAllowed: !!SettingsStore.getValue('fallbackICEServerAllowed'),
|
fallbackICEServerAllowed: !!SettingsStore.getValue('fallbackICEServerAllowed'),
|
||||||
verificationMethods: [
|
verificationMethods: [
|
||||||
verificationMethods.SAS,
|
verificationMethods.SAS,
|
||||||
|
|
|
@ -27,10 +27,11 @@ import dis from './dispatcher/dispatcher';
|
||||||
import * as sdk from './index';
|
import * as sdk from './index';
|
||||||
import { _t } from './languageHandler';
|
import { _t } from './languageHandler';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
import {
|
import {
|
||||||
hideToast as hideNotificationsToast,
|
hideToast as hideNotificationsToast,
|
||||||
} from "./toasts/DesktopNotificationsToast";
|
} from "./toasts/DesktopNotificationsToast";
|
||||||
|
import {SettingLevel} from "./settings/SettingLevel";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispatches:
|
* Dispatches:
|
||||||
|
|
|
@ -20,9 +20,10 @@ import PropTypes from 'prop-types';
|
||||||
import dis from "../../../../dispatcher/dispatcher";
|
import dis from "../../../../dispatcher/dispatcher";
|
||||||
import { _t } from '../../../../languageHandler';
|
import { _t } from '../../../../languageHandler';
|
||||||
|
|
||||||
import SettingsStore, {SettingLevel} from "../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../settings/SettingsStore";
|
||||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||||
import {Action} from "../../../../dispatcher/actions";
|
import {Action} from "../../../../dispatcher/actions";
|
||||||
|
import {SettingLevel} from "../../../../settings/SettingLevel";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allows the user to disable the Event Index.
|
* Allows the user to disable the Event Index.
|
||||||
|
|
|
@ -19,11 +19,12 @@ import * as sdk from '../../../../index';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { _t } from '../../../../languageHandler';
|
import { _t } from '../../../../languageHandler';
|
||||||
import SdkConfig from '../../../../SdkConfig';
|
import SdkConfig from '../../../../SdkConfig';
|
||||||
import SettingsStore, {SettingLevel} from "../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../settings/SettingsStore";
|
||||||
|
|
||||||
import Modal from '../../../../Modal';
|
import Modal from '../../../../Modal';
|
||||||
import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils";
|
import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils";
|
||||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||||
|
import {SettingLevel} from "../../../../settings/SettingLevel";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allows the user to introspect the event index state and disable it.
|
* Allows the user to introspect the event index state and disable it.
|
||||||
|
|
|
@ -51,7 +51,7 @@ import { getHomePageUrl } from '../../utils/pages';
|
||||||
|
|
||||||
import createRoom from "../../createRoom";
|
import createRoom from "../../createRoom";
|
||||||
import {_t, _td, getCurrentLanguage} from '../../languageHandler';
|
import {_t, _td, getCurrentLanguage} from '../../languageHandler';
|
||||||
import SettingsStore, { SettingLevel } from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import ThemeController from "../../settings/controllers/ThemeController";
|
import ThemeController from "../../settings/controllers/ThemeController";
|
||||||
import { startAnyRegistrationFlow } from "../../Registration.js";
|
import { startAnyRegistrationFlow } from "../../Registration.js";
|
||||||
import { messageForSyncError } from '../../utils/ErrorUtils';
|
import { messageForSyncError } from '../../utils/ErrorUtils';
|
||||||
|
@ -75,6 +75,7 @@ import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificat
|
||||||
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
||||||
import ErrorDialog from "../views/dialogs/ErrorDialog";
|
import ErrorDialog from "../views/dialogs/ErrorDialog";
|
||||||
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
||||||
|
import { SettingLevel } from "../../settings/SettingLevel";
|
||||||
|
|
||||||
/** constants for MatrixChat.state.view */
|
/** constants for MatrixChat.state.view */
|
||||||
export enum Views {
|
export enum Views {
|
||||||
|
|
|
@ -48,7 +48,7 @@ import RightPanel from './RightPanel';
|
||||||
import RoomViewStore from '../../stores/RoomViewStore';
|
import RoomViewStore from '../../stores/RoomViewStore';
|
||||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
||||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||||
import RightPanelStore from "../../stores/RightPanelStore";
|
import RightPanelStore from "../../stores/RightPanelStore";
|
||||||
import {haveTileForEvent} from "../views/rooms/EventTile";
|
import {haveTileForEvent} from "../views/rooms/EventTile";
|
||||||
|
@ -56,6 +56,7 @@ import RoomContext from "../../contexts/RoomContext";
|
||||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||||
import { shieldStatusForRoom } from '../../utils/ShieldUtils';
|
import { shieldStatusForRoom } from '../../utils/ShieldUtils';
|
||||||
import {Action} from "../../dispatcher/actions";
|
import {Action} from "../../dispatcher/actions";
|
||||||
|
import {SettingLevel} from "../../settings/SettingLevel";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
let debuglog = function() {};
|
let debuglog = function() {};
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
||||||
import RedesignFeedbackDialog from "../views/dialogs/RedesignFeedbackDialog";
|
import RedesignFeedbackDialog from "../views/dialogs/RedesignFeedbackDialog";
|
||||||
import Modal from "../../Modal";
|
import Modal from "../../Modal";
|
||||||
import LogoutDialog from "../views/dialogs/LogoutDialog";
|
import LogoutDialog from "../views/dialogs/LogoutDialog";
|
||||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import {getCustomTheme} from "../../theme";
|
import {getCustomTheme} from "../../theme";
|
||||||
import {getHostingLink} from "../../utils/HostingLink";
|
import {getHostingLink} from "../../utils/HostingLink";
|
||||||
import {ButtonEvent} from "../views/elements/AccessibleButton";
|
import {ButtonEvent} from "../views/elements/AccessibleButton";
|
||||||
|
@ -37,6 +37,7 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||||
import BaseAvatar from '../views/avatars/BaseAvatar';
|
import BaseAvatar from '../views/avatars/BaseAvatar';
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
||||||
|
import { SettingLevel } from "../../settings/SettingLevel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
|
|
|
@ -16,10 +16,11 @@ limitations under the License.
|
||||||
|
|
||||||
import SdkConfig from "../../../SdkConfig";
|
import SdkConfig from "../../../SdkConfig";
|
||||||
import {getCurrentLanguage} from "../../../languageHandler";
|
import {getCurrentLanguage} from "../../../languageHandler";
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import PlatformPeg from "../../../PlatformPeg";
|
import PlatformPeg from "../../../PlatformPeg";
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
function onChange(newLang) {
|
function onChange(newLang) {
|
||||||
if (getCurrentLanguage() !== newLang) {
|
if (getCurrentLanguage() !== newLang) {
|
||||||
|
|
|
@ -19,8 +19,8 @@ import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {SettingLevel} from "../../../settings/SettingsStore";
|
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default createReactClass({
|
export default createReactClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
|
|
@ -17,10 +17,11 @@ limitations under the License.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
import WidgetUtils from "../../../utils/WidgetUtils";
|
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -35,12 +35,13 @@ import dis from '../../../dispatcher/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, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import {aboveLeftOf, ContextMenu, ContextMenuButton} from "../../structures/ContextMenu";
|
import {aboveLeftOf, ContextMenu, ContextMenuButton} from "../../structures/ContextMenu";
|
||||||
import PersistedElement from "./PersistedElement";
|
import PersistedElement from "./PersistedElement";
|
||||||
import {WidgetType} from "../../../widgets/WidgetType";
|
import {WidgetType} from "../../../widgets/WidgetType";
|
||||||
import {Capability} from "../../../widgets/WidgetApi";
|
import {Capability} from "../../../widgets/WidgetApi";
|
||||||
import {sleep} from "../../../utils/promise";
|
import {sleep} from "../../../utils/promise";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
||||||
const ENABLE_REACT_PERF = false;
|
const ENABLE_REACT_PERF = false;
|
||||||
|
|
|
@ -15,8 +15,9 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import Draggable, {ILocationState} from './Draggable';
|
import Draggable, {ILocationState} from './Draggable';
|
||||||
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// Current room
|
// Current room
|
||||||
|
|
|
@ -20,11 +20,12 @@ import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import ToggleSwitch from "./ToggleSwitch";
|
import ToggleSwitch from "./ToggleSwitch";
|
||||||
import StyledCheckbox from "./StyledCheckbox";
|
import StyledCheckbox from "./StyledCheckbox";
|
||||||
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// The setting must be a boolean
|
// The setting must be a boolean
|
||||||
name: string;
|
name: string;
|
||||||
level: string;
|
level: SettingLevel;
|
||||||
roomId?: string; // for per-room settings
|
roomId?: string; // for per-room settings
|
||||||
label?: string; // untranslated
|
label?: string; // untranslated
|
||||||
isExplicit?: boolean;
|
isExplicit?: boolean;
|
||||||
|
@ -52,8 +53,8 @@ export default class SettingsFlag extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private onChange = (checked: boolean): void => {
|
private onChange = async (checked: boolean) => {
|
||||||
this.save(checked);
|
await this.save(checked);
|
||||||
this.setState({ value: checked });
|
this.setState({ value: checked });
|
||||||
if (this.props.onChange) this.props.onChange(checked);
|
if (this.props.onChange) this.props.onChange(checked);
|
||||||
};
|
};
|
||||||
|
@ -62,8 +63,8 @@ export default class SettingsFlag extends React.Component<IProps, IState> {
|
||||||
this.onChange(e.target.checked);
|
this.onChange(e.target.checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
private save = (val?: boolean): void => {
|
private save = async (val?: boolean) => {
|
||||||
return SettingsStore.setValue(
|
await SettingsStore.setValue(
|
||||||
this.props.name,
|
this.props.name,
|
||||||
this.props.roomId,
|
this.props.roomId,
|
||||||
this.props.level,
|
this.props.level,
|
||||||
|
|
|
@ -20,7 +20,8 @@ import createReactClass from 'create-react-class';
|
||||||
|
|
||||||
import Tinter from '../../../Tinter';
|
import Tinter from '../../../Tinter';
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
const ROOM_COLORS = [
|
const ROOM_COLORS = [
|
||||||
// magic room default values courtesy of Ribot
|
// magic room default values courtesy of Ribot
|
||||||
|
|
|
@ -22,10 +22,11 @@ import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import { _t, _td } from '../../../languageHandler';
|
import { _t, _td } from '../../../languageHandler';
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
import {Action} from "../../../dispatcher/actions";
|
import {Action} from "../../../dispatcher/actions";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
|
|
||||||
export default createReactClass({
|
export default createReactClass({
|
||||||
|
|
|
@ -21,7 +21,8 @@ import * as sdk from "../../../index";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import Modal from "../../../Modal";
|
import Modal from "../../../Modal";
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class RoomRecoveryReminder extends React.PureComponent {
|
export default class RoomRecoveryReminder extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
||||||
|
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import {SettingLevel} from "../../../settings/SettingsStore";
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
|
const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,11 @@ import { _t } from '../../../languageHandler';
|
||||||
import SdkConfig from "../../../SdkConfig";
|
import SdkConfig from "../../../SdkConfig";
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
import {formatBytes, formatCountLong} from "../../../utils/FormattingUtils";
|
import {formatBytes, formatCountLong} from "../../../utils/FormattingUtils";
|
||||||
import EventIndexPeg from "../../../indexing/EventIndexPeg";
|
import EventIndexPeg from "../../../indexing/EventIndexPeg";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class EventIndexPanel extends React.Component {
|
export default class EventIndexPanel extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||||
import SettingsStore, {SettingLevel} from '../../../settings/SettingsStore';
|
import SettingsStore from '../../../settings/SettingsStore';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import {
|
import {
|
||||||
NotificationUtils,
|
NotificationUtils,
|
||||||
|
@ -31,6 +31,7 @@ import {
|
||||||
import SdkConfig from "../../../SdkConfig";
|
import SdkConfig from "../../../SdkConfig";
|
||||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
// TODO: this "view" component still has far too much application logic in it,
|
// TODO: this "view" component still has far too much application logic in it,
|
||||||
// which should be factored out to other files.
|
// which should be factored out to other files.
|
||||||
|
|
|
@ -18,7 +18,8 @@ import React from 'react';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class SetIntegrationManager extends React.Component {
|
export default class SetIntegrationManager extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||||
import Notifier from "../../../../../Notifier";
|
import Notifier from "../../../../../Notifier";
|
||||||
import SettingsStore from '../../../../../settings/SettingsStore';
|
import SettingsStore from '../../../../../settings/SettingsStore';
|
||||||
import { SettingLevel } from '../../../../../settings/SettingsStore';
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class NotificationsSettingsTab extends React.Component {
|
export default class NotificationsSettingsTab extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -20,9 +20,9 @@ import {_t} from "../../../../../languageHandler";
|
||||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||||
import * as sdk from "../../../../..";
|
import * as sdk from "../../../../..";
|
||||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
|
||||||
import Modal from "../../../../../Modal";
|
import Modal from "../../../../../Modal";
|
||||||
import QuestionDialog from "../../../dialogs/QuestionDialog";
|
import QuestionDialog from "../../../dialogs/QuestionDialog";
|
||||||
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class SecurityRoomSettingsTab extends React.Component {
|
export default class SecurityRoomSettingsTab extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {_t} from "../../../../../languageHandler";
|
import {_t} from "../../../../../languageHandler";
|
||||||
import SdkConfig from "../../../../../SdkConfig";
|
import SdkConfig from "../../../../../SdkConfig";
|
||||||
import SettingsStore, {SettingLevel} from "../../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||||
import { enumerateThemes } from "../../../../../theme";
|
import { enumerateThemes } from "../../../../../theme";
|
||||||
import ThemeWatcher from "../../../../../settings/watchers/ThemeWatcher";
|
import ThemeWatcher from "../../../../../settings/watchers/ThemeWatcher";
|
||||||
import Slider from "../../../elements/Slider";
|
import Slider from "../../../elements/Slider";
|
||||||
|
@ -35,6 +35,7 @@ import Field from '../../../elements/Field';
|
||||||
import EventTilePreview from '../../../elements/EventTilePreview';
|
import EventTilePreview from '../../../elements/EventTilePreview';
|
||||||
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import React from 'react';
|
||||||
import {_t} from "../../../../../languageHandler";
|
import {_t} from "../../../../../languageHandler";
|
||||||
import ProfileSettings from "../../ProfileSettings";
|
import ProfileSettings from "../../ProfileSettings";
|
||||||
import * as languageHandler from "../../../../../languageHandler";
|
import * as languageHandler from "../../../../../languageHandler";
|
||||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
|
||||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||||
import LanguageDropdown from "../../../elements/LanguageDropdown";
|
import LanguageDropdown from "../../../elements/LanguageDropdown";
|
||||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||||
|
@ -37,6 +36,7 @@ import IdentityAuthClient from "../../../../../IdentityAuthClient";
|
||||||
import {abbreviateUrl} from "../../../../../utils/UrlUtils";
|
import {abbreviateUrl} from "../../../../../utils/UrlUtils";
|
||||||
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
|
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
|
||||||
import Spinner from "../../../elements/Spinner";
|
import Spinner from "../../../elements/Spinner";
|
||||||
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class GeneralUserSettingsTab extends React.Component {
|
export default class GeneralUserSettingsTab extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -17,9 +17,10 @@ limitations under the License.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {_t} from "../../../../../languageHandler";
|
import {_t} from "../../../../../languageHandler";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import SettingsStore, {SettingLevel} from "../../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||||
import * as sdk from "../../../../../index";
|
import * as sdk from "../../../../../index";
|
||||||
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export class LabsSettingToggle extends React.Component {
|
export class LabsSettingToggle extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -17,12 +17,12 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {_t} from "../../../../../languageHandler";
|
import {_t} from "../../../../../languageHandler";
|
||||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
|
||||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||||
import Field from "../../../elements/Field";
|
import Field from "../../../elements/Field";
|
||||||
import * as sdk from "../../../../..";
|
import * as sdk from "../../../../..";
|
||||||
import PlatformPeg from "../../../../../PlatformPeg";
|
import PlatformPeg from "../../../../../PlatformPeg";
|
||||||
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class PreferencesUserSettingsTab extends React.Component {
|
export default class PreferencesUserSettingsTab extends React.Component {
|
||||||
static ROOM_LIST_SETTINGS = [
|
static ROOM_LIST_SETTINGS = [
|
||||||
|
|
|
@ -19,7 +19,6 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {_t} from "../../../../../languageHandler";
|
import {_t} from "../../../../../languageHandler";
|
||||||
import SdkConfig from "../../../../../SdkConfig";
|
import SdkConfig from "../../../../../SdkConfig";
|
||||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
|
||||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||||
import * as FormattingUtils from "../../../../../utils/FormattingUtils";
|
import * as FormattingUtils from "../../../../../utils/FormattingUtils";
|
||||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||||
|
@ -29,6 +28,7 @@ import * as sdk from "../../../../..";
|
||||||
import {sleep} from "../../../../../utils/promise";
|
import {sleep} from "../../../../../utils/promise";
|
||||||
import dis from "../../../../../dispatcher/dispatcher";
|
import dis from "../../../../../dispatcher/dispatcher";
|
||||||
import {privateShouldBeEncrypted} from "../../../../../createRoom";
|
import {privateShouldBeEncrypted} from "../../../../../createRoom";
|
||||||
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export class IgnoredUser extends React.Component {
|
export class IgnoredUser extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -21,10 +21,10 @@ import SdkConfig from "../../../../../SdkConfig";
|
||||||
import CallMediaHandler from "../../../../../CallMediaHandler";
|
import CallMediaHandler from "../../../../../CallMediaHandler";
|
||||||
import Field from "../../../elements/Field";
|
import Field from "../../../elements/Field";
|
||||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
|
||||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||||
import * as sdk from "../../../../../index";
|
import * as sdk from "../../../../../index";
|
||||||
import Modal from "../../../../../Modal";
|
import Modal from "../../../../../Modal";
|
||||||
|
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||||
|
|
||||||
export default class VoiceUserSettingsTab extends React.Component {
|
export default class VoiceUserSettingsTab extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -15,8 +15,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import {orderBy} from "lodash";
|
import {orderBy} from "lodash";
|
||||||
|
import { SettingLevel } from "../settings/SettingLevel";
|
||||||
|
|
||||||
interface ILegacyFormat {
|
interface ILegacyFormat {
|
||||||
[emoji: string]: [number, number]; // [count, date]
|
[emoji: string]: [number, number]; // [count, date]
|
||||||
|
|
|
@ -18,8 +18,9 @@ import PlatformPeg from "../PlatformPeg";
|
||||||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||||
import {EventTimeline, RoomMember} from 'matrix-js-sdk';
|
import {EventTimeline, RoomMember} from 'matrix-js-sdk';
|
||||||
import {sleep} from "../utils/promise";
|
import {sleep} from "../utils/promise";
|
||||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import {EventEmitter} from "events";
|
import {EventEmitter} from "events";
|
||||||
|
import {SettingLevel} from "../settings/SettingLevel";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Event indexing class that wraps the platform specific event indexing.
|
* Event indexing class that wraps the platform specific event indexing.
|
||||||
|
|
|
@ -21,7 +21,8 @@ limitations under the License.
|
||||||
|
|
||||||
import PlatformPeg from "../PlatformPeg";
|
import PlatformPeg from "../PlatformPeg";
|
||||||
import EventIndex from "../indexing/EventIndex";
|
import EventIndex from "../indexing/EventIndex";
|
||||||
import SettingsStore, {SettingLevel} from '../settings/SettingsStore';
|
import SettingsStore from '../settings/SettingsStore';
|
||||||
|
import {SettingLevel} from "../settings/SettingLevel";
|
||||||
|
|
||||||
const INDEX_VERSION = 1;
|
const INDEX_VERSION = 1;
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,12 @@ import request from 'browser-request';
|
||||||
import counterpart from 'counterpart';
|
import counterpart from 'counterpart';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
import PlatformPeg from "./PlatformPeg";
|
import PlatformPeg from "./PlatformPeg";
|
||||||
|
|
||||||
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
|
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
|
||||||
import webpackLangJsonUrl from "$webapp/i18n/languages.json";
|
import webpackLangJsonUrl from "$webapp/i18n/languages.json";
|
||||||
|
import { SettingLevel } from "./settings/SettingLevel";
|
||||||
|
|
||||||
const i18nFolder = 'i18n/';
|
const i18nFolder = 'i18n/';
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,10 @@ limitations under the License.
|
||||||
|
|
||||||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||||
import {ALL_RULE_TYPES, BanList} from "./BanList";
|
import {ALL_RULE_TYPES, BanList} from "./BanList";
|
||||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import {_t} from "../languageHandler";
|
import {_t} from "../languageHandler";
|
||||||
import dis from "../dispatcher/dispatcher";
|
import dis from "../dispatcher/dispatcher";
|
||||||
|
import {SettingLevel} from "../settings/SettingLevel";
|
||||||
|
|
||||||
// TODO: Move this and related files to the js-sdk or something once finalized.
|
// TODO: Move this and related files to the js-sdk or something once finalized.
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ export default async function sendBugReport(bugReportEndpoint: string, opts: IOp
|
||||||
}
|
}
|
||||||
|
|
||||||
// add labs options
|
// add labs options
|
||||||
const enabledLabs = SettingsStore.getLabsFeatures().filter(SettingsStore.isFeatureEnabled);
|
const enabledLabs = SettingsStore.getLabsFeatures().filter(f => SettingsStore.isFeatureEnabled(f));
|
||||||
if (enabledLabs.length) {
|
if (enabledLabs.length) {
|
||||||
body.append('enabled_labs', enabledLabs.join(', '));
|
body.append('enabled_labs', enabledLabs.join(', '));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the various setting levels supported by the SettingsStore.
|
||||||
|
*/
|
||||||
|
export enum SettingLevel {
|
||||||
|
// TODO: [TS] Follow naming convention
|
||||||
|
DEVICE = "device",
|
||||||
|
ROOM_DEVICE = "room-device",
|
||||||
|
ROOM_ACCOUNT = "room-account",
|
||||||
|
ACCOUNT = "account",
|
||||||
|
ROOM = "room",
|
||||||
|
CONFIG = "config",
|
||||||
|
DEFAULT = "default",
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2018, 2019 New Vector Ltd.
|
Copyright 2018, 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,9 +15,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MatrixClient} from 'matrix-js-sdk';
|
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||||
|
|
||||||
import {_td} from '../languageHandler';
|
import { _td } from '../languageHandler';
|
||||||
import {
|
import {
|
||||||
AudioNotificationsEnabledController,
|
AudioNotificationsEnabledController,
|
||||||
NotificationBodyEnabledController,
|
NotificationBodyEnabledController,
|
||||||
|
@ -28,75 +27,89 @@ import CustomStatusController from "./controllers/CustomStatusController";
|
||||||
import ThemeController from './controllers/ThemeController';
|
import ThemeController from './controllers/ThemeController';
|
||||||
import PushToMatrixClientController from './controllers/PushToMatrixClientController';
|
import PushToMatrixClientController from './controllers/PushToMatrixClientController';
|
||||||
import ReloadOnChangeController from "./controllers/ReloadOnChangeController";
|
import ReloadOnChangeController from "./controllers/ReloadOnChangeController";
|
||||||
import {RightPanelPhases} from "../stores/RightPanelStorePhases";
|
|
||||||
import FontSizeController from './controllers/FontSizeController';
|
import FontSizeController from './controllers/FontSizeController';
|
||||||
import SystemFontController from './controllers/SystemFontController';
|
import SystemFontController from './controllers/SystemFontController';
|
||||||
import UseSystemFontController from './controllers/UseSystemFontController';
|
import UseSystemFontController from './controllers/UseSystemFontController';
|
||||||
|
import { SettingLevel } from "./SettingLevel";
|
||||||
|
import SettingController from "./controllers/SettingController";
|
||||||
|
import { RightPanelPhases } from "../stores/RightPanelStorePhases";
|
||||||
|
|
||||||
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
|
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
|
||||||
const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config'];
|
const LEVELS_ROOM_SETTINGS = [
|
||||||
const LEVELS_ROOM_OR_ACCOUNT = ['room-account', 'account'];
|
SettingLevel.DEVICE,
|
||||||
const LEVELS_ROOM_SETTINGS_WITH_ROOM = ['device', 'room-device', 'room-account', 'account', 'config', 'room'];
|
SettingLevel.ROOM_DEVICE,
|
||||||
const LEVELS_ACCOUNT_SETTINGS = ['device', 'account', 'config'];
|
SettingLevel.ROOM_ACCOUNT,
|
||||||
const LEVELS_FEATURE = ['device', 'config'];
|
SettingLevel.ACCOUNT,
|
||||||
const LEVELS_DEVICE_ONLY_SETTINGS = ['device'];
|
SettingLevel.CONFIG,
|
||||||
const LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG = ['device', 'config'];
|
];
|
||||||
|
const LEVELS_ROOM_OR_ACCOUNT = [
|
||||||
|
SettingLevel.ROOM_ACCOUNT,
|
||||||
|
SettingLevel.ACCOUNT,
|
||||||
|
];
|
||||||
|
const LEVELS_ROOM_SETTINGS_WITH_ROOM = [
|
||||||
|
SettingLevel.DEVICE,
|
||||||
|
SettingLevel.ROOM_DEVICE,
|
||||||
|
SettingLevel.ROOM_ACCOUNT,
|
||||||
|
SettingLevel.ACCOUNT,
|
||||||
|
SettingLevel.CONFIG,
|
||||||
|
SettingLevel.ROOM,
|
||||||
|
];
|
||||||
|
const LEVELS_ACCOUNT_SETTINGS = [
|
||||||
|
SettingLevel.DEVICE,
|
||||||
|
SettingLevel.ACCOUNT,
|
||||||
|
SettingLevel.CONFIG,
|
||||||
|
];
|
||||||
|
const LEVELS_FEATURE = [
|
||||||
|
SettingLevel.DEVICE,
|
||||||
|
SettingLevel.CONFIG,
|
||||||
|
];
|
||||||
|
const LEVELS_DEVICE_ONLY_SETTINGS = [
|
||||||
|
SettingLevel.DEVICE,
|
||||||
|
];
|
||||||
|
const LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG = [
|
||||||
|
SettingLevel.DEVICE,
|
||||||
|
SettingLevel.CONFIG,
|
||||||
|
];
|
||||||
|
|
||||||
export const SETTINGS = {
|
export interface ISetting {
|
||||||
// EXAMPLE SETTING:
|
// Must be set to true for features. Default is 'false'.
|
||||||
// "my-setting": {
|
isFeature?: boolean;
|
||||||
// // Must be set to true for features. Default is 'false'.
|
|
||||||
// isFeature: false,
|
// Display names are strongly recommended for clarity.
|
||||||
//
|
// Display name can also be an object for different levels.
|
||||||
// // Display names are strongly recommended for clarity.
|
displayName?: string | {
|
||||||
// displayName: _td("Cool Name"),
|
// @ts-ignore - TS wants the key to be a string, but we know better
|
||||||
//
|
[level: SettingLevel]: string;
|
||||||
// // Display name can also be an object for different levels.
|
};
|
||||||
// //displayName: {
|
|
||||||
// // "device": _td("Name for when the setting is used at 'device'"),
|
// The supported levels are required. Preferably, use the preset arrays
|
||||||
// // "room": _td("Name for when the setting is used at 'room'"),
|
// at the top of this file to define this rather than a custom array.
|
||||||
// // "default": _td("The name for all other levels"),
|
supportedLevels?: SettingLevel[];
|
||||||
// //}
|
|
||||||
//
|
// Required. Can be any data type. The value specified here should match
|
||||||
// // The supported levels are required. Preferably, use the preset arrays
|
// the data being stored (ie: if a boolean is used, the setting should
|
||||||
// // at the top of this file to define this rather than a custom array.
|
// represent a boolean).
|
||||||
// supportedLevels: [
|
default: any;
|
||||||
// // The order does not matter.
|
|
||||||
//
|
// Optional settings controller. See SettingsController for more information.
|
||||||
// "device", // Affects the current device only
|
controller?: SettingController;
|
||||||
// "room-device", // Affects the current room on the current device
|
|
||||||
// "room-account", // Affects the current room for the current account
|
// Optional flag to make supportedLevels be respected as the order to handle
|
||||||
// "account", // Affects the current account
|
// settings. The first element is treated as "most preferred". The "default"
|
||||||
// "room", // Affects the current room (controlled by room admins)
|
// level is always appended to the end.
|
||||||
// "config", // Affects the current application
|
supportedLevelsAreOrdered?: boolean;
|
||||||
//
|
|
||||||
// // "default" is always supported and does not get listed here.
|
// Optional value to invert a boolean setting's value. The string given will
|
||||||
// ],
|
// be read as the setting's ID instead of the one provided as the key for the
|
||||||
//
|
// setting definition. By setting this, the returned value will automatically
|
||||||
// // Required. Can be any data type. The value specified here should match
|
// be inverted, except for when the default value is returned. Inversion will
|
||||||
// // the data being stored (ie: if a boolean is used, the setting should
|
// occur after the controller is asked for an override. This should be used by
|
||||||
// // represent a boolean).
|
// historical settings which we don't want existing user's values be wiped. Do
|
||||||
// default: {
|
// not use this for new settings.
|
||||||
// your: "value",
|
invertedSettingName?: string;
|
||||||
// },
|
}
|
||||||
//
|
|
||||||
// // Optional settings controller. See SettingsController for more information.
|
export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
// controller: new MySettingController(),
|
|
||||||
//
|
|
||||||
// // Optional flag to make supportedLevels be respected as the order to handle
|
|
||||||
// // settings. The first element is treated as "most preferred". The "default"
|
|
||||||
// // level is always appended to the end.
|
|
||||||
// supportedLevelsAreOrdered: false,
|
|
||||||
//
|
|
||||||
// // Optional value to invert a boolean setting's value. The string given will
|
|
||||||
// // be read as the setting's ID instead of the one provided as the key for the
|
|
||||||
// // setting definition. By setting this, the returned value will automatically
|
|
||||||
// // be inverted, except for when the default value is returned. Inversion will
|
|
||||||
// // occur after the controller is asked for an override. This should be used by
|
|
||||||
// // historical settings which we don't want existing user's values be wiped. Do
|
|
||||||
// // not use this for new settings.
|
|
||||||
// invertedSettingName: "my-negative-setting",
|
|
||||||
// },
|
|
||||||
"feature_new_spinner": {
|
"feature_new_spinner": {
|
||||||
isFeature: true,
|
isFeature: true,
|
||||||
displayName: _td("New spinner design"),
|
displayName: _td("New spinner design"),
|
||||||
|
@ -153,11 +166,11 @@ export const SETTINGS = {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"mjolnirRooms": {
|
"mjolnirRooms": {
|
||||||
supportedLevels: ['account'],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [],
|
default: [],
|
||||||
},
|
},
|
||||||
"mjolnirPersonalRoom": {
|
"mjolnirPersonalRoom": {
|
||||||
supportedLevels: ['account'],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
"feature_bridge_state": {
|
"feature_bridge_state": {
|
||||||
|
@ -354,24 +367,24 @@ export const SETTINGS = {
|
||||||
},
|
},
|
||||||
"breadcrumb_rooms": {
|
"breadcrumb_rooms": {
|
||||||
// not really a setting
|
// not really a setting
|
||||||
supportedLevels: ['account'],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [],
|
default: [],
|
||||||
},
|
},
|
||||||
"recent_emoji": {
|
"recent_emoji": {
|
||||||
// not really a setting
|
// not really a setting
|
||||||
supportedLevels: ['account'],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [],
|
default: [],
|
||||||
},
|
},
|
||||||
"room_directory_servers": {
|
"room_directory_servers": {
|
||||||
supportedLevels: ['account'],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [],
|
default: [],
|
||||||
},
|
},
|
||||||
"integrationProvisioning": {
|
"integrationProvisioning": {
|
||||||
supportedLevels: ['account'],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
"allowedWidgets": {
|
"allowedWidgets": {
|
||||||
supportedLevels: ['room-account'],
|
supportedLevels: [SettingLevel.ROOM_ACCOUNT],
|
||||||
default: {}, // none allowed
|
default: {}, // none allowed
|
||||||
},
|
},
|
||||||
"analyticsOptIn": {
|
"analyticsOptIn": {
|
||||||
|
@ -398,7 +411,7 @@ export const SETTINGS = {
|
||||||
"blacklistUnverifiedDevices": {
|
"blacklistUnverifiedDevices": {
|
||||||
// We specifically want to have room-device > device so that users may set a device default
|
// We specifically want to have room-device > device so that users may set a device default
|
||||||
// with a per-room override.
|
// with a per-room override.
|
||||||
supportedLevels: ['room-device', 'device'],
|
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.DEVICE],
|
||||||
supportedLevelsAreOrdered: true,
|
supportedLevelsAreOrdered: true,
|
||||||
displayName: {
|
displayName: {
|
||||||
"default": _td('Never send encrypted messages to unverified sessions from this session'),
|
"default": _td('Never send encrypted messages to unverified sessions from this session'),
|
||||||
|
@ -416,7 +429,7 @@ export const SETTINGS = {
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
"urlPreviewsEnabled_e2ee": {
|
"urlPreviewsEnabled_e2ee": {
|
||||||
supportedLevels: ['room-device', 'room-account'],
|
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.ROOM_ACCOUNT],
|
||||||
displayName: {
|
displayName: {
|
||||||
"room-account": _td("Enable URL previews for this room (only affects you)"),
|
"room-account": _td("Enable URL previews for this room (only affects you)"),
|
||||||
},
|
},
|
||||||
|
@ -455,7 +468,7 @@ export const SETTINGS = {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"PinnedEvents.isOpen": {
|
"PinnedEvents.isOpen": {
|
||||||
supportedLevels: ['room-device'],
|
supportedLevels: [SettingLevel.ROOM_DEVICE],
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"promptBeforeInviteUnknownUsers": {
|
"promptBeforeInviteUnknownUsers": {
|
||||||
|
@ -565,7 +578,8 @@ export const SETTINGS = {
|
||||||
"ircDisplayNameWidth": {
|
"ircDisplayNameWidth": {
|
||||||
// We specifically want to have room-device > device so that users may set a device default
|
// We specifically want to have room-device > device so that users may set a device default
|
||||||
// with a per-room override.
|
// with a per-room override.
|
||||||
supportedLevels: ['room-device', 'device'],
|
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.DEVICE],
|
||||||
|
supportedLevelsAreOrdered: true,
|
||||||
displayName: _td("IRC display name width"),
|
displayName: _td("IRC display name width"),
|
||||||
default: 80,
|
default: 80,
|
||||||
},
|
},
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -22,27 +22,14 @@ import RoomAccountSettingsHandler from "./handlers/RoomAccountSettingsHandler";
|
||||||
import AccountSettingsHandler from "./handlers/AccountSettingsHandler";
|
import AccountSettingsHandler from "./handlers/AccountSettingsHandler";
|
||||||
import RoomSettingsHandler from "./handlers/RoomSettingsHandler";
|
import RoomSettingsHandler from "./handlers/RoomSettingsHandler";
|
||||||
import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler";
|
import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler";
|
||||||
import {_t} from '../languageHandler';
|
import { _t } from '../languageHandler';
|
||||||
import SdkConfig from "../SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
import dis from '../dispatcher/dispatcher';
|
import dis from '../dispatcher/dispatcher';
|
||||||
import {SETTINGS} from "./Settings";
|
import { ISetting, SETTINGS } from "./Settings";
|
||||||
import LocalEchoWrapper from "./handlers/LocalEchoWrapper";
|
import LocalEchoWrapper from "./handlers/LocalEchoWrapper";
|
||||||
import {WatchManager} from "./WatchManager";
|
import { WatchManager } from "./WatchManager";
|
||||||
|
import { SettingLevel } from "./SettingLevel";
|
||||||
/**
|
import SettingsHandler from "./handlers/SettingsHandler";
|
||||||
* Represents the various setting levels supported by the SettingsStore.
|
|
||||||
*/
|
|
||||||
export const SettingLevel = {
|
|
||||||
// Note: This enum is not used in this class or in the Settings file
|
|
||||||
// This should always be used elsewhere in the project.
|
|
||||||
DEVICE: "device",
|
|
||||||
ROOM_DEVICE: "room-device",
|
|
||||||
ROOM_ACCOUNT: "room-account",
|
|
||||||
ACCOUNT: "account",
|
|
||||||
ROOM: "room",
|
|
||||||
CONFIG: "config",
|
|
||||||
DEFAULT: "default",
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultWatchManager = new WatchManager();
|
const defaultWatchManager = new WatchManager();
|
||||||
|
|
||||||
|
@ -61,13 +48,13 @@ for (const key of Object.keys(SETTINGS)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const LEVEL_HANDLERS = {
|
const LEVEL_HANDLERS = {
|
||||||
"device": new DeviceSettingsHandler(featureNames, defaultWatchManager),
|
[SettingLevel.DEVICE]: new DeviceSettingsHandler(featureNames, defaultWatchManager),
|
||||||
"room-device": new RoomDeviceSettingsHandler(defaultWatchManager),
|
[SettingLevel.ROOM_DEVICE]: new RoomDeviceSettingsHandler(defaultWatchManager),
|
||||||
"room-account": new RoomAccountSettingsHandler(defaultWatchManager),
|
[SettingLevel.ROOM_ACCOUNT]: new RoomAccountSettingsHandler(defaultWatchManager),
|
||||||
"account": new AccountSettingsHandler(defaultWatchManager),
|
[SettingLevel.ACCOUNT]: new AccountSettingsHandler(defaultWatchManager),
|
||||||
"room": new RoomSettingsHandler(defaultWatchManager),
|
[SettingLevel.ROOM]: new RoomSettingsHandler(defaultWatchManager),
|
||||||
"config": new ConfigSettingsHandler(),
|
[SettingLevel.CONFIG]: new ConfigSettingsHandler(),
|
||||||
"default": new DefaultSettingsHandler(defaultSettings, invertedDefaultSettings),
|
[SettingLevel.DEFAULT]: new DefaultSettingsHandler(defaultSettings, invertedDefaultSettings),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrap all the handlers with local echo
|
// Wrap all the handlers with local echo
|
||||||
|
@ -76,20 +63,41 @@ for (const key of Object.keys(LEVEL_HANDLERS)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const LEVEL_ORDER = [
|
const LEVEL_ORDER = [
|
||||||
'device', 'room-device', 'room-account', 'account', 'room', 'config', 'default',
|
SettingLevel.DEVICE,
|
||||||
|
SettingLevel.ROOM_DEVICE,
|
||||||
|
SettingLevel.ROOM_ACCOUNT,
|
||||||
|
SettingLevel.ACCOUNT,
|
||||||
|
SettingLevel.ROOM,
|
||||||
|
SettingLevel.CONFIG,
|
||||||
|
SettingLevel.DEFAULT,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export type CallbackFn = (
|
||||||
|
settingName: string,
|
||||||
|
roomId: string,
|
||||||
|
atLevel: SettingLevel,
|
||||||
|
newValAtLevel: any,
|
||||||
|
newVal: any,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
interface IHandlerMap {
|
||||||
|
// @ts-ignore - TS wants this to be a string key but we know better
|
||||||
|
[level: SettingLevel]: SettingsHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LabsFeatureState = "labs" | "disable" | "enable" | string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls and manages application settings by providing varying levels at which the
|
* Controls and manages application settings by providing varying levels at which the
|
||||||
* setting value may be specified. The levels are then used to determine what the setting
|
* setting value may be specified. The levels are then used to determine what the setting
|
||||||
* value should be given a set of circumstances. The levels, in priority order, are:
|
* value should be given a set of circumstances. The levels, in priority order, are:
|
||||||
* - "device" - Values are determined by the current device
|
* - SettingLevel.DEVICE - Values are determined by the current device
|
||||||
* - "room-device" - Values are determined by the current device for a particular room
|
* - SettingLevel.ROOM_DEVICE - Values are determined by the current device for a particular room
|
||||||
* - "room-account" - Values are determined by the current account for a particular room
|
* - SettingLevel.ROOM_ACCOUNT - Values are determined by the current account for a particular room
|
||||||
* - "account" - Values are determined by the current account
|
* - SettingLevel.ACCOUNT - Values are determined by the current account
|
||||||
* - "room" - Values are determined by a particular room (by the room admins)
|
* - SettingLevel.ROOM - Values are determined by a particular room (by the room admins)
|
||||||
* - "config" - Values are determined by the config.json
|
* - SettingLevel.CONFIG - Values are determined by the config.json
|
||||||
* - "default" - Values are determined by the hardcoded defaults
|
* - SettingLevel.DEFAULT - Values are determined by the hardcoded defaults
|
||||||
*
|
*
|
||||||
* Each level has a different method to storing the setting value. For implementation
|
* Each level has a different method to storing the setting value. For implementation
|
||||||
* specific details, please see the handlers. The "config" and "default" levels are
|
* specific details, please see the handlers. The "config" and "default" levels are
|
||||||
|
@ -110,11 +118,11 @@ export default class SettingsStore {
|
||||||
// We also maintain a list of monitors which are special watchers: they cause dispatches
|
// We also maintain a list of monitors which are special watchers: they cause dispatches
|
||||||
// when the setting changes. We track which rooms we're monitoring though to ensure we
|
// when the setting changes. We track which rooms we're monitoring though to ensure we
|
||||||
// don't duplicate updates on the bus.
|
// don't duplicate updates on the bus.
|
||||||
static _watchers = {}; // { callbackRef => { callbackFn } }
|
private static watchers = {}; // { callbackRef => { callbackFn } }
|
||||||
static _monitors = {}; // { settingName => { roomId => callbackRef } }
|
private static monitors = {}; // { settingName => { roomId => callbackRef } }
|
||||||
|
|
||||||
// Counter used for generation of watcher IDs
|
// Counter used for generation of watcher IDs
|
||||||
static _watcherCount = 1;
|
private static watcherCount = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watches for changes in a particular setting. This is done without any local echo
|
* Watches for changes in a particular setting. This is done without any local echo
|
||||||
|
@ -132,7 +140,7 @@ export default class SettingsStore {
|
||||||
* if the change in value is worthwhile enough to react upon.
|
* if the change in value is worthwhile enough to react upon.
|
||||||
* @returns {string} A reference to the watcher that was employed.
|
* @returns {string} A reference to the watcher that was employed.
|
||||||
*/
|
*/
|
||||||
static watchSetting(settingName, roomId, callbackFn) {
|
public static watchSetting(settingName: string, roomId: string, callbackFn: CallbackFn): string {
|
||||||
const setting = SETTINGS[settingName];
|
const setting = SETTINGS[settingName];
|
||||||
const originalSettingName = settingName;
|
const originalSettingName = settingName;
|
||||||
if (!setting) throw new Error(`${settingName} is not a setting`);
|
if (!setting) throw new Error(`${settingName} is not a setting`);
|
||||||
|
@ -141,14 +149,14 @@ export default class SettingsStore {
|
||||||
settingName = setting.invertedSettingName;
|
settingName = setting.invertedSettingName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const watcherId = `${new Date().getTime()}_${SettingsStore._watcherCount++}_${settingName}_${roomId}`;
|
const watcherId = `${new Date().getTime()}_${SettingsStore.watcherCount++}_${settingName}_${roomId}`;
|
||||||
|
|
||||||
const localizedCallback = (changedInRoomId, atLevel, newValAtLevel) => {
|
const localizedCallback = (changedInRoomId, atLevel, newValAtLevel) => {
|
||||||
const newValue = SettingsStore.getValue(originalSettingName);
|
const newValue = SettingsStore.getValue(originalSettingName);
|
||||||
callbackFn(originalSettingName, changedInRoomId, atLevel, newValAtLevel, newValue);
|
callbackFn(originalSettingName, changedInRoomId, atLevel, newValAtLevel, newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
SettingsStore._watchers[watcherId] = localizedCallback;
|
SettingsStore.watchers[watcherId] = localizedCallback;
|
||||||
defaultWatchManager.watchSetting(settingName, roomId, localizedCallback);
|
defaultWatchManager.watchSetting(settingName, roomId, localizedCallback);
|
||||||
|
|
||||||
return watcherId;
|
return watcherId;
|
||||||
|
@ -160,14 +168,14 @@ export default class SettingsStore {
|
||||||
* @param {string} watcherReference The watcher reference (received from #watchSetting)
|
* @param {string} watcherReference The watcher reference (received from #watchSetting)
|
||||||
* to cancel.
|
* to cancel.
|
||||||
*/
|
*/
|
||||||
static unwatchSetting(watcherReference) {
|
public static unwatchSetting(watcherReference: string) {
|
||||||
if (!SettingsStore._watchers[watcherReference]) {
|
if (!SettingsStore.watchers[watcherReference]) {
|
||||||
console.warn(`Ending non-existent watcher ID ${watcherReference}`);
|
console.warn(`Ending non-existent watcher ID ${watcherReference}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultWatchManager.unwatchSetting(SettingsStore._watchers[watcherReference]);
|
defaultWatchManager.unwatchSetting(SettingsStore.watchers[watcherReference]);
|
||||||
delete SettingsStore._watchers[watcherReference];
|
delete SettingsStore.watchers[watcherReference];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,13 +186,13 @@ export default class SettingsStore {
|
||||||
* @param {string} settingName The setting name to monitor.
|
* @param {string} settingName The setting name to monitor.
|
||||||
* @param {String} roomId The room ID to monitor for changes in. Use null for all rooms.
|
* @param {String} roomId The room ID to monitor for changes in. Use null for all rooms.
|
||||||
*/
|
*/
|
||||||
static monitorSetting(settingName, roomId) {
|
public static monitorSetting(settingName: string, roomId: string) {
|
||||||
roomId = roomId || null; // the thing wants null specifically to work, so appease it.
|
roomId = roomId || null; // the thing wants null specifically to work, so appease it.
|
||||||
|
|
||||||
if (!this._monitors[settingName]) this._monitors[settingName] = {};
|
if (!this.monitors[settingName]) this.monitors[settingName] = {};
|
||||||
|
|
||||||
const registerWatcher = () => {
|
const registerWatcher = () => {
|
||||||
this._monitors[settingName][roomId] = SettingsStore.watchSetting(
|
this.monitors[settingName][roomId] = SettingsStore.watchSetting(
|
||||||
settingName, roomId, (settingName, inRoomId, level, newValueAtLevel, newValue) => {
|
settingName, roomId, (settingName, inRoomId, level, newValueAtLevel, newValue) => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'setting_updated',
|
action: 'setting_updated',
|
||||||
|
@ -198,16 +206,16 @@ export default class SettingsStore {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasRoom = Object.keys(this._monitors[settingName]).find((r) => r === roomId || r === null);
|
const hasRoom = Object.keys(this.monitors[settingName]).find((r) => r === roomId || r === null);
|
||||||
if (!hasRoom) {
|
if (!hasRoom) {
|
||||||
registerWatcher();
|
registerWatcher();
|
||||||
} else {
|
} else {
|
||||||
if (roomId === null) {
|
if (roomId === null) {
|
||||||
// Unregister all existing watchers and register the new one
|
// Unregister all existing watchers and register the new one
|
||||||
for (const roomId of Object.keys(this._monitors[settingName])) {
|
for (const roomId of Object.keys(this.monitors[settingName])) {
|
||||||
SettingsStore.unwatchSetting(this._monitors[settingName][roomId]);
|
SettingsStore.unwatchSetting(this.monitors[settingName][roomId]);
|
||||||
}
|
}
|
||||||
this._monitors[settingName] = {};
|
this.monitors[settingName] = {};
|
||||||
registerWatcher();
|
registerWatcher();
|
||||||
} // else a watcher is already registered for the room, so don't bother registering it again
|
} // else a watcher is already registered for the room, so don't bother registering it again
|
||||||
}
|
}
|
||||||
|
@ -216,11 +224,11 @@ export default class SettingsStore {
|
||||||
/**
|
/**
|
||||||
* Gets the translated display name for a given setting
|
* Gets the translated display name for a given setting
|
||||||
* @param {string} settingName The setting to look up.
|
* @param {string} settingName The setting to look up.
|
||||||
* @param {"device"|"room-device"|"room-account"|"account"|"room"|"config"|"default"} atLevel
|
* @param {SettingLevel} atLevel
|
||||||
* The level to get the display name for; Defaults to 'default'.
|
* The level to get the display name for; Defaults to 'default'.
|
||||||
* @return {String} The display name for the setting, or null if not found.
|
* @return {String} The display name for the setting, or null if not found.
|
||||||
*/
|
*/
|
||||||
static getDisplayName(settingName, atLevel = "default") {
|
public static getDisplayName(settingName: string, atLevel = SettingLevel.DEFAULT) {
|
||||||
if (!SETTINGS[settingName] || !SETTINGS[settingName].displayName) return null;
|
if (!SETTINGS[settingName] || !SETTINGS[settingName].displayName) return null;
|
||||||
|
|
||||||
let displayName = SETTINGS[settingName].displayName;
|
let displayName = SETTINGS[settingName].displayName;
|
||||||
|
@ -229,20 +237,20 @@ export default class SettingsStore {
|
||||||
else displayName = displayName["default"];
|
else displayName = displayName["default"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return _t(displayName);
|
return _t(displayName as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all available labs feature names
|
* Returns a list of all available labs feature names
|
||||||
* @returns {string[]} The list of available feature names
|
* @returns {string[]} The list of available feature names
|
||||||
*/
|
*/
|
||||||
static getLabsFeatures() {
|
public static getLabsFeatures(): string[] {
|
||||||
const possibleFeatures = Object.keys(SETTINGS).filter((s) => SettingsStore.isFeature(s));
|
const possibleFeatures = Object.keys(SETTINGS).filter((s) => SettingsStore.isFeature(s));
|
||||||
|
|
||||||
const enableLabs = SdkConfig.get()["enableLabs"];
|
const enableLabs = SdkConfig.get()["enableLabs"];
|
||||||
if (enableLabs) return possibleFeatures;
|
if (enableLabs) return possibleFeatures;
|
||||||
|
|
||||||
return possibleFeatures.filter((s) => SettingsStore._getFeatureState(s) === "labs");
|
return possibleFeatures.filter((s) => SettingsStore.getFeatureState(s) === "labs");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -250,7 +258,7 @@ export default class SettingsStore {
|
||||||
* @param {string} settingName The setting to look up.
|
* @param {string} settingName The setting to look up.
|
||||||
* @return {boolean} True if the setting is a feature.
|
* @return {boolean} True if the setting is a feature.
|
||||||
*/
|
*/
|
||||||
static isFeature(settingName) {
|
public static isFeature(settingName: string) {
|
||||||
if (!SETTINGS[settingName]) return false;
|
if (!SETTINGS[settingName]) return false;
|
||||||
return SETTINGS[settingName].isFeature;
|
return SETTINGS[settingName].isFeature;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +270,7 @@ export default class SettingsStore {
|
||||||
* @param {String} roomId The optional room ID to validate in, may be null.
|
* @param {String} roomId The optional room ID to validate in, may be null.
|
||||||
* @return {boolean} True if the feature is enabled, false otherwise
|
* @return {boolean} True if the feature is enabled, false otherwise
|
||||||
*/
|
*/
|
||||||
static isFeatureEnabled(settingName, roomId = null) {
|
public static isFeatureEnabled(settingName: string, roomId: string = null) {
|
||||||
if (!SettingsStore.isFeature(settingName)) {
|
if (!SettingsStore.isFeature(settingName)) {
|
||||||
throw new Error("Setting " + settingName + " is not a feature");
|
throw new Error("Setting " + settingName + " is not a feature");
|
||||||
}
|
}
|
||||||
|
@ -276,7 +284,7 @@ export default class SettingsStore {
|
||||||
* @param {boolean} value True to enable the feature, false otherwise.
|
* @param {boolean} value True to enable the feature, false otherwise.
|
||||||
* @returns {Promise} Resolves when the setting has been set.
|
* @returns {Promise} Resolves when the setting has been set.
|
||||||
*/
|
*/
|
||||||
static setFeatureEnabled(settingName, value) {
|
public static setFeatureEnabled(settingName: string, value: any): Promise<void> {
|
||||||
// Verify that the setting is actually a setting
|
// Verify that the setting is actually a setting
|
||||||
if (!SETTINGS[settingName]) {
|
if (!SETTINGS[settingName]) {
|
||||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||||
|
@ -285,7 +293,7 @@ export default class SettingsStore {
|
||||||
throw new Error("Setting " + settingName + " is not a feature");
|
throw new Error("Setting " + settingName + " is not a feature");
|
||||||
}
|
}
|
||||||
|
|
||||||
return SettingsStore.setValue(settingName, null, "device", value);
|
return SettingsStore.setValue(settingName, null, SettingLevel.DEVICE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -296,7 +304,7 @@ export default class SettingsStore {
|
||||||
* @param {boolean} excludeDefault True to disable using the default value.
|
* @param {boolean} excludeDefault True to disable using the default value.
|
||||||
* @return {*} The value, or null if not found
|
* @return {*} The value, or null if not found
|
||||||
*/
|
*/
|
||||||
static getValue(settingName, roomId = null, excludeDefault = false) {
|
public static getValue(settingName: string, roomId: string = null, excludeDefault = false): any {
|
||||||
// Verify that the setting is actually a setting
|
// Verify that the setting is actually a setting
|
||||||
if (!SETTINGS[settingName]) {
|
if (!SETTINGS[settingName]) {
|
||||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||||
|
@ -310,7 +318,7 @@ export default class SettingsStore {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a setting's value at a particular level, ignoring all levels that are more specific.
|
* Gets a setting's value at a particular level, ignoring all levels that are more specific.
|
||||||
* @param {"device"|"room-device"|"room-account"|"account"|"room"|"config"|"default"} level The
|
* @param {SettingLevel|"config"|"default"} level The
|
||||||
* level to look at.
|
* level to look at.
|
||||||
* @param {string} settingName The name of the setting to read.
|
* @param {string} settingName The name of the setting to read.
|
||||||
* @param {String} roomId The room ID to read the setting value in, may be null.
|
* @param {String} roomId The room ID to read the setting value in, may be null.
|
||||||
|
@ -319,7 +327,13 @@ export default class SettingsStore {
|
||||||
* @param {boolean} excludeDefault True to disable using the default value.
|
* @param {boolean} excludeDefault True to disable using the default value.
|
||||||
* @return {*} The value, or null if not found.
|
* @return {*} The value, or null if not found.
|
||||||
*/
|
*/
|
||||||
static getValueAt(level, settingName, roomId = null, explicit = false, excludeDefault = false) {
|
public static getValueAt(
|
||||||
|
level: SettingLevel,
|
||||||
|
settingName: string,
|
||||||
|
roomId: string = null,
|
||||||
|
explicit = false,
|
||||||
|
excludeDefault = false,
|
||||||
|
): any {
|
||||||
// Verify that the setting is actually a setting
|
// Verify that the setting is actually a setting
|
||||||
const setting = SETTINGS[settingName];
|
const setting = SETTINGS[settingName];
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
|
@ -327,19 +341,19 @@ export default class SettingsStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
const levelOrder = (setting.supportedLevelsAreOrdered ? setting.supportedLevels : LEVEL_ORDER);
|
const levelOrder = (setting.supportedLevelsAreOrdered ? setting.supportedLevels : LEVEL_ORDER);
|
||||||
if (!levelOrder.includes("default")) levelOrder.push("default"); // always include default
|
if (!levelOrder.includes(SettingLevel.DEFAULT)) levelOrder.push(SettingLevel.DEFAULT); // always include default
|
||||||
|
|
||||||
const minIndex = levelOrder.indexOf(level);
|
const minIndex = levelOrder.indexOf(level);
|
||||||
if (minIndex === -1) throw new Error("Level " + level + " is not prioritized");
|
if (minIndex === -1) throw new Error("Level " + level + " is not prioritized");
|
||||||
|
|
||||||
if (SettingsStore.isFeature(settingName)) {
|
if (SettingsStore.isFeature(settingName)) {
|
||||||
const configValue = SettingsStore._getFeatureState(settingName);
|
const configValue = SettingsStore.getFeatureState(settingName);
|
||||||
if (configValue === "enable") return true;
|
if (configValue === "enable") return true;
|
||||||
if (configValue === "disable") return false;
|
if (configValue === "disable") return false;
|
||||||
// else let it fall through the default process
|
// else let it fall through the default process
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlers = SettingsStore._getHandlers(settingName);
|
const handlers = SettingsStore.getHandlers(settingName);
|
||||||
|
|
||||||
// Check if we need to invert the setting at all. Do this after we get the setting
|
// Check if we need to invert the setting at all. Do this after we get the setting
|
||||||
// handlers though, otherwise we'll fail to read the value.
|
// handlers though, otherwise we'll fail to read the value.
|
||||||
|
@ -351,10 +365,10 @@ export default class SettingsStore {
|
||||||
if (explicit) {
|
if (explicit) {
|
||||||
const handler = handlers[level];
|
const handler = handlers[level];
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
return SettingsStore._getFinalValue(setting, level, roomId, null, null);
|
return SettingsStore.getFinalValue(setting, level, roomId, null, null);
|
||||||
}
|
}
|
||||||
const value = handler.getValue(settingName, roomId);
|
const value = handler.getValue(settingName, roomId);
|
||||||
return SettingsStore._getFinalValue(setting, level, roomId, value, level);
|
return SettingsStore.getFinalValue(setting, level, roomId, value, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = minIndex; i < levelOrder.length; i++) {
|
for (let i = minIndex; i < levelOrder.length; i++) {
|
||||||
|
@ -364,10 +378,10 @@ export default class SettingsStore {
|
||||||
|
|
||||||
const value = handler.getValue(settingName, roomId);
|
const value = handler.getValue(settingName, roomId);
|
||||||
if (value === null || value === undefined) continue;
|
if (value === null || value === undefined) continue;
|
||||||
return SettingsStore._getFinalValue(setting, level, roomId, value, levelOrder[i]);
|
return SettingsStore.getFinalValue(setting, level, roomId, value, levelOrder[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SettingsStore._getFinalValue(setting, level, roomId, null, null);
|
return SettingsStore.getFinalValue(setting, level, roomId, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -376,7 +390,7 @@ export default class SettingsStore {
|
||||||
* @param {String} roomId The room ID to read the setting value in, may be null.
|
* @param {String} roomId The room ID to read the setting value in, may be null.
|
||||||
* @return {*} The default value
|
* @return {*} The default value
|
||||||
*/
|
*/
|
||||||
static getDefaultValue(settingName) {
|
public static getDefaultValue(settingName: string): any {
|
||||||
// Verify that the setting is actually a setting
|
// Verify that the setting is actually a setting
|
||||||
if (!SETTINGS[settingName]) {
|
if (!SETTINGS[settingName]) {
|
||||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||||
|
@ -385,7 +399,13 @@ export default class SettingsStore {
|
||||||
return SETTINGS[settingName].default;
|
return SETTINGS[settingName].default;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getFinalValue(setting, level, roomId, calculatedValue, calculatedAtLevel) {
|
private static getFinalValue(
|
||||||
|
setting: ISetting,
|
||||||
|
level: SettingLevel,
|
||||||
|
roomId: string,
|
||||||
|
calculatedValue: any,
|
||||||
|
calculatedAtLevel: SettingLevel,
|
||||||
|
): any {
|
||||||
let resultingValue = calculatedValue;
|
let resultingValue = calculatedValue;
|
||||||
|
|
||||||
if (setting.controller) {
|
if (setting.controller) {
|
||||||
|
@ -404,20 +424,21 @@ export default class SettingsStore {
|
||||||
* to indicate that the level should no longer have an override.
|
* to indicate that the level should no longer have an override.
|
||||||
* @param {string} settingName The name of the setting to change.
|
* @param {string} settingName The name of the setting to change.
|
||||||
* @param {String} roomId The room ID to change the value in, may be null.
|
* @param {String} roomId The room ID to change the value in, may be null.
|
||||||
* @param {"device"|"room-device"|"room-account"|"account"|"room"} level The level
|
* @param {SettingLevel} level The level
|
||||||
* to change the value at.
|
* to change the value at.
|
||||||
* @param {*} value The new value of the setting, may be null.
|
* @param {*} value The new value of the setting, may be null.
|
||||||
* @return {Promise} Resolves when the setting has been changed.
|
* @return {Promise} Resolves when the setting has been changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-enable valid-jsdoc */
|
/* eslint-enable valid-jsdoc */
|
||||||
static async setValue(settingName, roomId, level, value) {
|
public static async setValue(settingName: string, roomId: string, level: SettingLevel, value: any): Promise<void> {
|
||||||
// Verify that the setting is actually a setting
|
// Verify that the setting is actually a setting
|
||||||
const setting = SETTINGS[settingName];
|
const setting = SETTINGS[settingName];
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = SettingsStore._getHandler(settingName, level);
|
const handler = SettingsStore.getHandler(settingName, level);
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
throw new Error("Setting " + settingName + " does not have a handler for " + level);
|
throw new Error("Setting " + settingName + " does not have a handler for " + level);
|
||||||
}
|
}
|
||||||
|
@ -449,28 +470,28 @@ export default class SettingsStore {
|
||||||
* set for a particular room, otherwise it should be supplied.
|
* set for a particular room, otherwise it should be supplied.
|
||||||
* @param {string} settingName The name of the setting to check.
|
* @param {string} settingName The name of the setting to check.
|
||||||
* @param {String} roomId The room ID to check in, may be null.
|
* @param {String} roomId The room ID to check in, may be null.
|
||||||
* @param {"device"|"room-device"|"room-account"|"account"|"room"} level The level to
|
* @param {SettingLevel} level The level to
|
||||||
* check at.
|
* check at.
|
||||||
* @return {boolean} True if the user may set the setting, false otherwise.
|
* @return {boolean} True if the user may set the setting, false otherwise.
|
||||||
*/
|
*/
|
||||||
static canSetValue(settingName, roomId, level) {
|
public static canSetValue(settingName: string, roomId: string, level: SettingLevel): boolean {
|
||||||
// Verify that the setting is actually a setting
|
// Verify that the setting is actually a setting
|
||||||
if (!SETTINGS[settingName]) {
|
if (!SETTINGS[settingName]) {
|
||||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = SettingsStore._getHandler(settingName, level);
|
const handler = SettingsStore.getHandler(settingName, level);
|
||||||
if (!handler) return false;
|
if (!handler) return false;
|
||||||
return handler.canSetValue(settingName, roomId);
|
return handler.canSetValue(settingName, roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the given level is supported on this device.
|
* Determines if the given level is supported on this device.
|
||||||
* @param {"device"|"room-device"|"room-account"|"account"|"room"} level The level
|
* @param {SettingLevel} level The level
|
||||||
* to check the feasibility of.
|
* to check the feasibility of.
|
||||||
* @return {boolean} True if the level is supported, false otherwise.
|
* @return {boolean} True if the level is supported, false otherwise.
|
||||||
*/
|
*/
|
||||||
static isLevelSupported(level) {
|
public static isLevelSupported(level: SettingLevel): boolean {
|
||||||
if (!LEVEL_HANDLERS[level]) return false;
|
if (!LEVEL_HANDLERS[level]) return false;
|
||||||
return LEVEL_HANDLERS[level].isSupported();
|
return LEVEL_HANDLERS[level].isSupported();
|
||||||
}
|
}
|
||||||
|
@ -482,7 +503,7 @@ export default class SettingsStore {
|
||||||
* @param {string} realSettingName The setting name to try and read.
|
* @param {string} realSettingName The setting name to try and read.
|
||||||
* @param {string} roomId Optional room ID to test the setting in.
|
* @param {string} roomId Optional room ID to test the setting in.
|
||||||
*/
|
*/
|
||||||
static debugSetting(realSettingName, roomId) {
|
public static debugSetting(realSettingName: string, roomId: string) {
|
||||||
console.log(`--- DEBUG ${realSettingName}`);
|
console.log(`--- DEBUG ${realSettingName}`);
|
||||||
|
|
||||||
// Note: we intentionally use JSON.stringify here to avoid the console masking the
|
// Note: we intentionally use JSON.stringify here to avoid the console masking the
|
||||||
|
@ -570,13 +591,13 @@ export default class SettingsStore {
|
||||||
console.log(`--- END DEBUG`);
|
console.log(`--- END DEBUG`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getHandler(settingName, level) {
|
private static getHandler(settingName: string, level: SettingLevel): SettingsHandler {
|
||||||
const handlers = SettingsStore._getHandlers(settingName);
|
const handlers = SettingsStore.getHandlers(settingName);
|
||||||
if (!handlers[level]) return null;
|
if (!handlers[level]) return null;
|
||||||
return handlers[level];
|
return handlers[level];
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getHandlers(settingName) {
|
private static getHandlers(settingName: string): IHandlerMap {
|
||||||
if (!SETTINGS[settingName]) return {};
|
if (!SETTINGS[settingName]) return {};
|
||||||
|
|
||||||
const handlers = {};
|
const handlers = {};
|
||||||
|
@ -591,7 +612,7 @@ export default class SettingsStore {
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getFeatureState(settingName) {
|
private static getFeatureState(settingName: string): LabsFeatureState {
|
||||||
const featuresConfig = SdkConfig.get()['features'];
|
const featuresConfig = SdkConfig.get()['features'];
|
||||||
const enableLabs = SdkConfig.get()['enableLabs']; // we'll honour the old flag
|
const enableLabs = SdkConfig.get()['enableLabs']; // we'll honour the old flag
|
||||||
|
|
||||||
|
@ -611,4 +632,4 @@ export default class SettingsStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For debugging purposes
|
// For debugging purposes
|
||||||
global.mxSettingsStore = SettingsStore;
|
window.mxSettingsStore = SettingsStore;
|
|
@ -14,41 +14,52 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { SettingLevel } from "./SettingLevel";
|
||||||
|
|
||||||
|
export type CallbackFn = (changedInRoomId: string, atLevel: SettingLevel, newValAtLevel: any) => void;
|
||||||
|
|
||||||
|
const IRRELEVANT_ROOM = Symbol("any room");
|
||||||
|
|
||||||
|
interface RoomWatcherMap {
|
||||||
|
// @ts-ignore - TS wants string-only keys but we know better - https://github.com/Microsoft/TypeScript/issues/1863
|
||||||
|
[roomId: string | symbol]: CallbackFn[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generalized management class for dealing with watchers on a per-handler (per-level)
|
* Generalized management class for dealing with watchers on a per-handler (per-level)
|
||||||
* basis without duplicating code. Handlers are expected to push updates through this
|
* basis without duplicating code. Handlers are expected to push updates through this
|
||||||
* class, which are then proxied outwards to any applicable watchers.
|
* class, which are then proxied outwards to any applicable watchers.
|
||||||
*/
|
*/
|
||||||
export class WatchManager {
|
export class WatchManager {
|
||||||
_watchers = {}; // { settingName: { roomId: callbackFns[] } }
|
private watchers: {[settingName: string]: RoomWatcherMap} = {};
|
||||||
|
|
||||||
// Proxy for handlers to delegate changes to this manager
|
// Proxy for handlers to delegate changes to this manager
|
||||||
watchSetting(settingName, roomId, cb) {
|
public watchSetting(settingName: string, roomId: string | null, cb: CallbackFn) {
|
||||||
if (!this._watchers[settingName]) this._watchers[settingName] = {};
|
if (!this.watchers[settingName]) this.watchers[settingName] = {};
|
||||||
if (!this._watchers[settingName][roomId]) this._watchers[settingName][roomId] = [];
|
if (!this.watchers[settingName][roomId]) this.watchers[settingName][roomId] = [];
|
||||||
this._watchers[settingName][roomId].push(cb);
|
this.watchers[settingName][roomId].push(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proxy for handlers to delegate changes to this manager
|
// Proxy for handlers to delegate changes to this manager
|
||||||
unwatchSetting(cb) {
|
public unwatchSetting(cb: CallbackFn) {
|
||||||
for (const settingName of Object.keys(this._watchers)) {
|
for (const settingName of Object.keys(this.watchers)) {
|
||||||
for (const roomId of Object.keys(this._watchers[settingName])) {
|
for (const roomId of Object.keys(this.watchers[settingName])) {
|
||||||
let idx;
|
let idx;
|
||||||
while ((idx = this._watchers[settingName][roomId].indexOf(cb)) !== -1) {
|
while ((idx = this.watchers[settingName][roomId].indexOf(cb)) !== -1) {
|
||||||
this._watchers[settingName][roomId].splice(idx, 1);
|
this.watchers[settingName][roomId].splice(idx, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyUpdate(settingName, inRoomId, atLevel, newValueAtLevel) {
|
public notifyUpdate(settingName: string, inRoomId: string | null, atLevel: SettingLevel, newValueAtLevel: any) {
|
||||||
// Dev note: We could avoid raising changes for ultimately inconsequential changes, but
|
// Dev note: We could avoid raising changes for ultimately inconsequential changes, but
|
||||||
// we also don't have a reliable way to get the old value of a setting. Instead, we'll just
|
// we also don't have a reliable way to get the old value of a setting. Instead, we'll just
|
||||||
// let it fall through regardless and let the receiver dedupe if they want to.
|
// let it fall through regardless and let the receiver dedupe if they want to.
|
||||||
|
|
||||||
if (!this._watchers[settingName]) return;
|
if (!this.watchers[settingName]) return;
|
||||||
|
|
||||||
const roomWatchers = this._watchers[settingName];
|
const roomWatchers = this.watchers[settingName];
|
||||||
const callbacks = [];
|
const callbacks = [];
|
||||||
|
|
||||||
if (inRoomId !== null && roomWatchers[inRoomId]) {
|
if (inRoomId !== null && roomWatchers[inRoomId]) {
|
||||||
|
@ -59,8 +70,8 @@ export class WatchManager {
|
||||||
// Fire updates to all the individual room watchers too, as they probably
|
// Fire updates to all the individual room watchers too, as they probably
|
||||||
// care about the change higher up.
|
// care about the change higher up.
|
||||||
callbacks.push(...Object.values(roomWatchers).reduce((r, a) => [...r, ...a], []));
|
callbacks.push(...Object.values(roomWatchers).reduce((r, a) => [...r, ...a], []));
|
||||||
} else if (roomWatchers[null]) {
|
} else if (roomWatchers[IRRELEVANT_ROOM]) {
|
||||||
callbacks.push(...roomWatchers[null]);
|
callbacks.push(...roomWatchers[IRRELEVANT_ROOM]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const callback of callbacks) {
|
for (const callback of callbacks) {
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,9 +16,10 @@ limitations under the License.
|
||||||
|
|
||||||
import SettingController from "./SettingController";
|
import SettingController from "./SettingController";
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class CustomStatusController extends SettingController {
|
export default class CustomStatusController extends SettingController {
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
// Dispatch setting change so that some components that are still visible when the
|
// Dispatch setting change so that some components that are still visible when the
|
||||||
// Settings page is open (such as RoomTiles) can reflect the change.
|
// Settings page is open (such as RoomTiles) can reflect the change.
|
||||||
dis.dispatch({
|
dis.dispatch({
|
|
@ -18,13 +18,14 @@ import SettingController from "./SettingController";
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
import { UpdateFontSizePayload } from "../../dispatcher/payloads/UpdateFontSizePayload";
|
import { UpdateFontSizePayload } from "../../dispatcher/payloads/UpdateFontSizePayload";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class FontSizeController extends SettingController {
|
export default class FontSizeController extends SettingController {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
// Dispatch font size change so that everything open responds to the change.
|
// Dispatch font size change so that everything open responds to the change.
|
||||||
dis.dispatch<UpdateFontSizePayload>({
|
dis.dispatch<UpdateFontSizePayload>({
|
||||||
action: Action.UpdateFontSize,
|
action: Action.UpdateFontSize,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +17,14 @@ limitations under the License.
|
||||||
|
|
||||||
import SettingController from "./SettingController";
|
import SettingController from "./SettingController";
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
// XXX: This feels wrong.
|
// XXX: This feels wrong.
|
||||||
import {PushProcessor} from "matrix-js-sdk/src/pushprocessor";
|
import {PushProcessor} from "matrix-js-sdk/src/pushprocessor";
|
||||||
|
|
||||||
// .m.rule.master being enabled means all events match that push rule
|
// .m.rule.master being enabled means all events match that push rule
|
||||||
// default action on this rule is dont_notify, but it could be something else
|
// default action on this rule is dont_notify, but it could be something else
|
||||||
function isPushNotifyDisabled() {
|
function isPushNotifyDisabled(): boolean {
|
||||||
// Return the value of the master push rule as a default
|
// Return the value of the master push rule as a default
|
||||||
const processor = new PushProcessor(MatrixClientPeg.get());
|
const processor = new PushProcessor(MatrixClientPeg.get());
|
||||||
const masterRule = processor.getPushRuleById(".m.rule.master");
|
const masterRule = processor.getPushRuleById(".m.rule.master");
|
||||||
|
@ -36,14 +38,20 @@ function isPushNotifyDisabled() {
|
||||||
return masterRule.enabled && !masterRule.actions.includes("notify");
|
return masterRule.enabled && !masterRule.actions.includes("notify");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNotifier() {
|
function getNotifier(): any { // TODO: [TS] Formal type that doesn't cause a cyclical reference.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
let Notifier = require('../../Notifier'); // avoids cyclical references
|
let Notifier = require('../../Notifier'); // avoids cyclical references
|
||||||
if (Notifier.default) Notifier = Notifier.default; // correct for webpack require() weirdness
|
if (Notifier.default) Notifier = Notifier.default; // correct for webpack require() weirdness
|
||||||
return Notifier;
|
return Notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotificationsEnabledController extends SettingController {
|
export class NotificationsEnabledController extends SettingController {
|
||||||
getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
|
public getValueOverride(
|
||||||
|
level: SettingLevel,
|
||||||
|
roomId: string,
|
||||||
|
calculatedValue: any,
|
||||||
|
calculatedAtLevel: SettingLevel,
|
||||||
|
): any {
|
||||||
if (!getNotifier().isPossible()) return false;
|
if (!getNotifier().isPossible()) return false;
|
||||||
|
|
||||||
if (calculatedValue === null || calculatedAtLevel === "default") {
|
if (calculatedValue === null || calculatedAtLevel === "default") {
|
||||||
|
@ -53,7 +61,7 @@ export class NotificationsEnabledController extends SettingController {
|
||||||
return calculatedValue;
|
return calculatedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
if (getNotifier().supportsDesktopNotifications()) {
|
if (getNotifier().supportsDesktopNotifications()) {
|
||||||
getNotifier().setEnabled(newValue);
|
getNotifier().setEnabled(newValue);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +69,7 @@ export class NotificationsEnabledController extends SettingController {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotificationBodyEnabledController extends SettingController {
|
export class NotificationBodyEnabledController extends SettingController {
|
||||||
getValueOverride(level, roomId, calculatedValue) {
|
public getValueOverride(level: SettingLevel, roomId: string, calculatedValue: any): any {
|
||||||
if (!getNotifier().isPossible()) return false;
|
if (!getNotifier().isPossible()) return false;
|
||||||
|
|
||||||
if (calculatedValue === null) {
|
if (calculatedValue === null) {
|
||||||
|
@ -73,7 +81,7 @@ export class NotificationBodyEnabledController extends SettingController {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AudioNotificationsEnabledController extends SettingController {
|
export class AudioNotificationsEnabledController extends SettingController {
|
||||||
getValueOverride(level, roomId, calculatedValue) {
|
public getValueOverride(level: SettingLevel, roomId: string, calculatedValue: any): any {
|
||||||
if (!getNotifier().isPossible()) return false;
|
if (!getNotifier().isPossible()) return false;
|
||||||
|
|
||||||
// Note: Audio notifications are *not* enabled by default.
|
// Note: Audio notifications are *not* enabled by default.
|
|
@ -15,23 +15,20 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
import SettingController from "./SettingController";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the value changes, call a setter function on the matrix client with the new value
|
* When the value changes, call a setter function on the matrix client with the new value
|
||||||
*/
|
*/
|
||||||
export default class PushToMatrixClientController {
|
export default class PushToMatrixClientController extends SettingController {
|
||||||
constructor(setter, inverse) {
|
constructor(private setter: Function, private inverse: boolean) {
|
||||||
this._setter = setter;
|
super();
|
||||||
this._inverse = inverse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
return null; // no override
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(level, roomId, newValue) {
|
|
||||||
// XXX does this work? This surely isn't necessarily the effective value,
|
// XXX does this work? This surely isn't necessarily the effective value,
|
||||||
// but it's what NotificationsEnabledController does...
|
// but it's what NotificationsEnabledController does...
|
||||||
this._setter.call(MatrixClientPeg.get(), this._inverse ? !newValue : newValue);
|
this.setter.call(MatrixClientPeg.get(), this.inverse ? !newValue : newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,9 +16,10 @@ limitations under the License.
|
||||||
|
|
||||||
import SettingController from "./SettingController";
|
import SettingController from "./SettingController";
|
||||||
import PlatformPeg from "../../PlatformPeg";
|
import PlatformPeg from "../../PlatformPeg";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class ReloadOnChangeController extends SettingController {
|
export default class ReloadOnChangeController extends SettingController {
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
PlatformPeg.get().reload();
|
PlatformPeg.get().reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,6 +15,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a controller for individual settings to alter the reading behaviour
|
* Represents a controller for individual settings to alter the reading behaviour
|
||||||
* based upon environmental conditions, or to react to changes and therefore update
|
* based upon environmental conditions, or to react to changes and therefore update
|
||||||
|
@ -22,7 +25,7 @@ limitations under the License.
|
||||||
* This is not intended to replace the functionality of a SettingsHandler, it is only
|
* This is not intended to replace the functionality of a SettingsHandler, it is only
|
||||||
* intended to handle environmental factors for specific settings.
|
* intended to handle environmental factors for specific settings.
|
||||||
*/
|
*/
|
||||||
export default class SettingController {
|
export default abstract class SettingController {
|
||||||
/**
|
/**
|
||||||
* Gets the overridden value for the setting, if any. This must return null if the
|
* Gets the overridden value for the setting, if any. This must return null if the
|
||||||
* value is not to be overridden, otherwise it must return the new value.
|
* value is not to be overridden, otherwise it must return the new value.
|
||||||
|
@ -30,11 +33,16 @@ export default class SettingController {
|
||||||
* @param {String} roomId The room ID, may be null.
|
* @param {String} roomId The room ID, may be null.
|
||||||
* @param {*} calculatedValue The value that the handlers think the setting should be,
|
* @param {*} calculatedValue The value that the handlers think the setting should be,
|
||||||
* may be null.
|
* may be null.
|
||||||
* @param {string} calculatedAtLevel The level for which the calculated value was
|
* @param {SettingLevel} calculatedAtLevel The level for which the calculated value was
|
||||||
* calculated at. May be null.
|
* calculated at. May be null.
|
||||||
* @return {*} The value that should be used, or null if no override is applicable.
|
* @return {*} The value that should be used, or null if no override is applicable.
|
||||||
*/
|
*/
|
||||||
getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
|
public getValueOverride(
|
||||||
|
level: SettingLevel,
|
||||||
|
roomId: string,
|
||||||
|
calculatedValue: any,
|
||||||
|
calculatedAtLevel: SettingLevel,
|
||||||
|
): any {
|
||||||
return null; // no override
|
return null; // no override
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +52,7 @@ export default class SettingController {
|
||||||
* @param {String} roomId The room ID, may be null.
|
* @param {String} roomId The room ID, may be null.
|
||||||
* @param {*} newValue The new value for the setting, may be null.
|
* @param {*} newValue The new value for the setting, may be null.
|
||||||
*/
|
*/
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
// do nothing by default
|
// do nothing by default
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,13 +19,14 @@ import SettingsStore from "../SettingsStore";
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class SystemFontController extends SettingController {
|
export default class SystemFontController extends SettingController {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
// Dispatch font size change so that everything open responds to the change.
|
// Dispatch font size change so that everything open responds to the change.
|
||||||
dis.dispatch<UpdateSystemFontPayload>({
|
dis.dispatch<UpdateSystemFontPayload>({
|
||||||
action: Action.UpdateSystemFont,
|
action: Action.UpdateSystemFont,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
|
||||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -17,11 +17,17 @@ limitations under the License.
|
||||||
|
|
||||||
import SettingController from "./SettingController";
|
import SettingController from "./SettingController";
|
||||||
import {DEFAULT_THEME, enumerateThemes} from "../../theme";
|
import {DEFAULT_THEME, enumerateThemes} from "../../theme";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class ThemeController extends SettingController {
|
export default class ThemeController extends SettingController {
|
||||||
static isLogin = false;
|
public static isLogin = false;
|
||||||
|
|
||||||
getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
|
public getValueOverride(
|
||||||
|
level: SettingLevel,
|
||||||
|
roomId: string,
|
||||||
|
calculatedValue: any,
|
||||||
|
calculatedAtLevel: SettingLevel,
|
||||||
|
): any {
|
||||||
if (!calculatedValue) return null; // Don't override null themes
|
if (!calculatedValue) return null; // Don't override null themes
|
||||||
|
|
||||||
if (ThemeController.isLogin) return 'light';
|
if (ThemeController.isLogin) return 'light';
|
|
@ -19,13 +19,14 @@ import SettingsStore from "../SettingsStore";
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class UseSystemFontController extends SettingController {
|
export default class UseSystemFontController extends SettingController {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(level, roomId, newValue) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
// Dispatch font size change so that everything open responds to the change.
|
// Dispatch font size change so that everything open responds to the change.
|
||||||
dis.dispatch<UpdateSystemFontPayload>({
|
dis.dispatch<UpdateSystemFontPayload>({
|
||||||
action: Action.UpdateSystemFont,
|
action: Action.UpdateSystemFont,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -17,14 +17,16 @@ limitations under the License.
|
||||||
|
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
|
||||||
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
||||||
|
import {SettingLevel} from "../SettingLevel";
|
||||||
|
import { WatchManager } from "../WatchManager";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
const BREADCRUMBS_LEGACY_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms";
|
const BREADCRUMBS_LEGACY_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms";
|
||||||
const BREADCRUMBS_EVENT_TYPE = "im.vector.setting.breadcrumbs";
|
const BREADCRUMBS_EVENT_TYPE = "im.vector.setting.breadcrumbs";
|
||||||
const BREADCRUMBS_EVENT_TYPES = [BREADCRUMBS_LEGACY_EVENT_TYPE, BREADCRUMBS_EVENT_TYPE];
|
const BREADCRUMBS_EVENT_TYPES = [BREADCRUMBS_LEGACY_EVENT_TYPE, BREADCRUMBS_EVENT_TYPE];
|
||||||
const RECENT_EMOJI_EVENT_TYPE = "io.element.recent_emoji";
|
const RECENT_EMOJI_EVENT_TYPE = "io.element.recent_emoji";
|
||||||
|
|
||||||
const INTEG_PROVISIONING_EVENT_TYPE = "im.vector.setting.integration_provisioning";
|
const INTEG_PROVISIONING_EVENT_TYPE = "im.vector.setting.integration_provisioning";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,22 +34,19 @@ const INTEG_PROVISIONING_EVENT_TYPE = "im.vector.setting.integration_provisionin
|
||||||
* This handler does not make use of the roomId parameter.
|
* This handler does not make use of the roomId parameter.
|
||||||
*/
|
*/
|
||||||
export default class AccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
export default class AccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||||
constructor(watchManager) {
|
constructor(private watchers: WatchManager) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._watchers = watchManager;
|
|
||||||
this._onAccountData = this._onAccountData.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initMatrixClient(oldClient, newClient) {
|
public initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||||
if (oldClient) {
|
if (oldClient) {
|
||||||
oldClient.removeListener("accountData", this._onAccountData);
|
oldClient.removeListener("accountData", this.onAccountData);
|
||||||
}
|
}
|
||||||
|
|
||||||
newClient.on("accountData", this._onAccountData);
|
newClient.on("accountData", this.onAccountData);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAccountData(event, prevEvent) {
|
private onAccountData = (event: MatrixEvent, prevEvent: MatrixEvent) => {
|
||||||
if (event.getType() === "org.matrix.preview_urls") {
|
if (event.getType() === "org.matrix.preview_urls") {
|
||||||
let val = event.getContent()['disable'];
|
let val = event.getContent()['disable'];
|
||||||
if (typeof(val) !== "boolean") {
|
if (typeof(val) !== "boolean") {
|
||||||
|
@ -56,30 +55,30 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
val = !val;
|
val = !val;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._watchers.notifyUpdate("urlPreviewsEnabled", null, SettingLevel.ACCOUNT, val);
|
this.watchers.notifyUpdate("urlPreviewsEnabled", null, SettingLevel.ACCOUNT, val);
|
||||||
} else if (event.getType() === "im.vector.web.settings") {
|
} else if (event.getType() === "im.vector.web.settings") {
|
||||||
// Figure out what changed and fire those updates
|
// Figure out what changed and fire those updates
|
||||||
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
||||||
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
||||||
for (const settingName of changedSettings) {
|
for (const settingName of changedSettings) {
|
||||||
const val = event.getContent()[settingName];
|
const val = event.getContent()[settingName];
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.ACCOUNT, val);
|
this.watchers.notifyUpdate(settingName, null, SettingLevel.ACCOUNT, val);
|
||||||
}
|
}
|
||||||
} else if (BREADCRUMBS_EVENT_TYPES.includes(event.getType())) {
|
} else if (BREADCRUMBS_EVENT_TYPES.includes(event.getType())) {
|
||||||
this._notifyBreadcrumbsUpdate(event);
|
this.notifyBreadcrumbsUpdate(event);
|
||||||
} else if (event.getType() === INTEG_PROVISIONING_EVENT_TYPE) {
|
} else if (event.getType() === INTEG_PROVISIONING_EVENT_TYPE) {
|
||||||
const val = event.getContent()['enabled'];
|
const val = event.getContent()['enabled'];
|
||||||
this._watchers.notifyUpdate("integrationProvisioning", null, SettingLevel.ACCOUNT, val);
|
this.watchers.notifyUpdate("integrationProvisioning", null, SettingLevel.ACCOUNT, val);
|
||||||
} else if (event.getType() === RECENT_EMOJI_EVENT_TYPE) {
|
} else if (event.getType() === RECENT_EMOJI_EVENT_TYPE) {
|
||||||
const val = event.getContent()['enabled'];
|
const val = event.getContent()['enabled'];
|
||||||
this._watchers.notifyUpdate("recent_emoji", null, SettingLevel.ACCOUNT, val);
|
this.watchers.notifyUpdate("recent_emoji", null, SettingLevel.ACCOUNT, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
// Special case URL previews
|
// Special case URL previews
|
||||||
if (settingName === "urlPreviewsEnabled") {
|
if (settingName === "urlPreviewsEnabled") {
|
||||||
const content = this._getSettings("org.matrix.preview_urls") || {};
|
const content = this.getSettings("org.matrix.preview_urls") || {};
|
||||||
|
|
||||||
// Check to make sure that we actually got a boolean
|
// Check to make sure that we actually got a boolean
|
||||||
if (typeof(content['disable']) !== "boolean") return null;
|
if (typeof(content['disable']) !== "boolean") return null;
|
||||||
|
@ -88,9 +87,9 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
|
|
||||||
// Special case for breadcrumbs
|
// Special case for breadcrumbs
|
||||||
if (settingName === "breadcrumb_rooms") {
|
if (settingName === "breadcrumb_rooms") {
|
||||||
let content = this._getSettings(BREADCRUMBS_EVENT_TYPE);
|
let content = this.getSettings(BREADCRUMBS_EVENT_TYPE);
|
||||||
if (!content || !content['recent_rooms']) {
|
if (!content || !content['recent_rooms']) {
|
||||||
content = this._getSettings(BREADCRUMBS_LEGACY_EVENT_TYPE);
|
content = this.getSettings(BREADCRUMBS_LEGACY_EVENT_TYPE);
|
||||||
|
|
||||||
// This is a bit of a hack, but it makes things slightly easier
|
// This is a bit of a hack, but it makes things slightly easier
|
||||||
if (content) content['recent_rooms'] = content['rooms'];
|
if (content) content['recent_rooms'] = content['rooms'];
|
||||||
|
@ -101,17 +100,17 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
|
|
||||||
// Special case recent emoji
|
// Special case recent emoji
|
||||||
if (settingName === "recent_emoji") {
|
if (settingName === "recent_emoji") {
|
||||||
const content = this._getSettings(RECENT_EMOJI_EVENT_TYPE);
|
const content = this.getSettings(RECENT_EMOJI_EVENT_TYPE);
|
||||||
return content ? content["recent_emoji"] : null;
|
return content ? content["recent_emoji"] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case integration manager provisioning
|
// Special case integration manager provisioning
|
||||||
if (settingName === "integrationProvisioning") {
|
if (settingName === "integrationProvisioning") {
|
||||||
const content = this._getSettings(INTEG_PROVISIONING_EVENT_TYPE);
|
const content = this.getSettings(INTEG_PROVISIONING_EVENT_TYPE);
|
||||||
return content ? content['enabled'] : null;
|
return content ? content['enabled'] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = this._getSettings() || {};
|
const settings = this.getSettings() || {};
|
||||||
let preferredValue = settings[settingName];
|
let preferredValue = settings[settingName];
|
||||||
|
|
||||||
if (preferredValue === null || preferredValue === undefined) {
|
if (preferredValue === null || preferredValue === undefined) {
|
||||||
|
@ -124,10 +123,10 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
return preferredValue;
|
return preferredValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
// Special case URL previews
|
// Special case URL previews
|
||||||
if (settingName === "urlPreviewsEnabled") {
|
if (settingName === "urlPreviewsEnabled") {
|
||||||
const content = this._getSettings("org.matrix.preview_urls") || {};
|
const content = this.getSettings("org.matrix.preview_urls") || {};
|
||||||
content['disable'] = !newValue;
|
content['disable'] = !newValue;
|
||||||
return MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", content);
|
return MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", content);
|
||||||
}
|
}
|
||||||
|
@ -135,9 +134,9 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
// Special case for breadcrumbs
|
// Special case for breadcrumbs
|
||||||
if (settingName === "breadcrumb_rooms") {
|
if (settingName === "breadcrumb_rooms") {
|
||||||
// We read the value first just to make sure we preserve whatever random keys might be present.
|
// We read the value first just to make sure we preserve whatever random keys might be present.
|
||||||
let content = this._getSettings(BREADCRUMBS_EVENT_TYPE);
|
let content = this.getSettings(BREADCRUMBS_EVENT_TYPE);
|
||||||
if (!content || !content['recent_rooms']) {
|
if (!content || !content['recent_rooms']) {
|
||||||
content = this._getSettings(BREADCRUMBS_LEGACY_EVENT_TYPE);
|
content = this.getSettings(BREADCRUMBS_LEGACY_EVENT_TYPE);
|
||||||
}
|
}
|
||||||
if (!content) content = {}; // If we still don't have content, make some
|
if (!content) content = {}; // If we still don't have content, make some
|
||||||
|
|
||||||
|
@ -147,33 +146,33 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
|
|
||||||
// Special case recent emoji
|
// Special case recent emoji
|
||||||
if (settingName === "recent_emoji") {
|
if (settingName === "recent_emoji") {
|
||||||
const content = this._getSettings(RECENT_EMOJI_EVENT_TYPE) || {};
|
const content = this.getSettings(RECENT_EMOJI_EVENT_TYPE) || {};
|
||||||
content["recent_emoji"] = newValue;
|
content["recent_emoji"] = newValue;
|
||||||
return MatrixClientPeg.get().setAccountData(RECENT_EMOJI_EVENT_TYPE, content);
|
return MatrixClientPeg.get().setAccountData(RECENT_EMOJI_EVENT_TYPE, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case integration manager provisioning
|
// Special case integration manager provisioning
|
||||||
if (settingName === "integrationProvisioning") {
|
if (settingName === "integrationProvisioning") {
|
||||||
const content = this._getSettings(INTEG_PROVISIONING_EVENT_TYPE) || {};
|
const content = this.getSettings(INTEG_PROVISIONING_EVENT_TYPE) || {};
|
||||||
content['enabled'] = newValue;
|
content['enabled'] = newValue;
|
||||||
return MatrixClientPeg.get().setAccountData(INTEG_PROVISIONING_EVENT_TYPE, content);
|
return MatrixClientPeg.get().setAccountData(INTEG_PROVISIONING_EVENT_TYPE, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = this._getSettings() || {};
|
const content = this.getSettings() || {};
|
||||||
content[settingName] = newValue;
|
content[settingName] = newValue;
|
||||||
return MatrixClientPeg.get().setAccountData("im.vector.web.settings", content);
|
return MatrixClientPeg.get().setAccountData("im.vector.web.settings", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
return true; // It's their account, so they should be able to
|
return true; // It's their account, so they should be able to
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
return cli !== undefined && cli !== null;
|
return cli !== undefined && cli !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSettings(eventType = "im.vector.web.settings") {
|
private getSettings(eventType = "im.vector.web.settings"): any { // TODO: [TS] Types on return
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
if (!cli) return null;
|
if (!cli) return null;
|
||||||
|
|
||||||
|
@ -182,11 +181,11 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
return objectClone(event.getContent()); // clone to prevent mutation
|
return objectClone(event.getContent()); // clone to prevent mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifyBreadcrumbsUpdate(event) {
|
private notifyBreadcrumbsUpdate(event: MatrixEvent) {
|
||||||
let val = [];
|
let val = [];
|
||||||
if (event.getType() === BREADCRUMBS_LEGACY_EVENT_TYPE) {
|
if (event.getType() === BREADCRUMBS_LEGACY_EVENT_TYPE) {
|
||||||
// This seems fishy - try and get the event for the new rooms
|
// This seems fishy - try and get the event for the new rooms
|
||||||
const newType = this._getSettings(BREADCRUMBS_EVENT_TYPE);
|
const newType = this.getSettings(BREADCRUMBS_EVENT_TYPE);
|
||||||
if (newType) val = newType['recent_rooms'];
|
if (newType) val = newType['recent_rooms'];
|
||||||
else val = event.getContent()['rooms'];
|
else val = event.getContent()['rooms'];
|
||||||
} else if (event.getType() === BREADCRUMBS_EVENT_TYPE) {
|
} else if (event.getType() === BREADCRUMBS_EVENT_TYPE) {
|
||||||
|
@ -194,6 +193,6 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
} else {
|
} else {
|
||||||
return; // for sanity, not because we expect to be here.
|
return; // for sanity, not because we expect to be here.
|
||||||
}
|
}
|
||||||
this._watchers.notifyUpdate("breadcrumb_rooms", null, SettingLevel.ACCOUNT, val || []);
|
this.watchers.notifyUpdate("breadcrumb_rooms", null, SettingLevel.ACCOUNT, val || []);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -24,7 +24,7 @@ import {isNullOrUndefined} from "matrix-js-sdk/src/utils";
|
||||||
* roomId parameter.
|
* roomId parameter.
|
||||||
*/
|
*/
|
||||||
export default class ConfigSettingsHandler extends SettingsHandler {
|
export default class ConfigSettingsHandler extends SettingsHandler {
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
const config = SdkConfig.get() || {};
|
const config = SdkConfig.get() || {};
|
||||||
|
|
||||||
// Special case themes
|
// Special case themes
|
||||||
|
@ -37,15 +37,15 @@ export default class ConfigSettingsHandler extends SettingsHandler {
|
||||||
return settingsConfig[settingName];
|
return settingsConfig[settingName];
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public async setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
throw new Error("Cannot change settings at the config level");
|
throw new Error("Cannot change settings at the config level");
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
return true; // SdkConfig is always there
|
return true; // SdkConfig is always there
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -27,29 +27,27 @@ export default class DefaultSettingsHandler extends SettingsHandler {
|
||||||
* @param {object} defaults The default setting values, keyed by setting name.
|
* @param {object} defaults The default setting values, keyed by setting name.
|
||||||
* @param {object} invertedDefaults The default inverted setting values, keyed by setting name.
|
* @param {object} invertedDefaults The default inverted setting values, keyed by setting name.
|
||||||
*/
|
*/
|
||||||
constructor(defaults, invertedDefaults) {
|
constructor(private defaults: Record<string, any>, private invertedDefaults: Record<string, any>) {
|
||||||
super();
|
super();
|
||||||
this._defaults = defaults;
|
|
||||||
this._invertedDefaults = invertedDefaults;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
let value = this._defaults[settingName];
|
let value = this.defaults[settingName];
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
value = this._invertedDefaults[settingName];
|
value = this.invertedDefaults[settingName];
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public async setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
throw new Error("Cannot set values on the default level handler");
|
throw new Error("Cannot set values on the default level handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,7 +18,8 @@ limitations under the License.
|
||||||
|
|
||||||
import SettingsHandler from "./SettingsHandler";
|
import SettingsHandler from "./SettingsHandler";
|
||||||
import {MatrixClientPeg} from "../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../MatrixClientPeg";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import {SettingLevel} from "../SettingLevel";
|
||||||
|
import { CallbackFn, WatchManager } from "../WatchManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets and sets settings at the "device" level for the current device.
|
* Gets and sets settings at the "device" level for the current device.
|
||||||
|
@ -29,17 +30,15 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
||||||
/**
|
/**
|
||||||
* Creates a new device settings handler
|
* Creates a new device settings handler
|
||||||
* @param {string[]} featureNames The names of known features.
|
* @param {string[]} featureNames The names of known features.
|
||||||
* @param {WatchManager} watchManager The watch manager to notify updates to
|
* @param {WatchManager} watchers The watch manager to notify updates to
|
||||||
*/
|
*/
|
||||||
constructor(featureNames, watchManager) {
|
constructor(private featureNames: string[], private watchers: WatchManager) {
|
||||||
super();
|
super();
|
||||||
this._featureNames = featureNames;
|
|
||||||
this._watchers = watchManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
if (this._featureNames.includes(settingName)) {
|
if (this.featureNames.includes(settingName)) {
|
||||||
return this._readFeature(settingName);
|
return this.readFeature(settingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case notifications
|
// Special case notifications
|
||||||
|
@ -68,28 +67,28 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
||||||
return val['value'];
|
return val['value'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = this._getSettings() || {};
|
const settings = this.getSettings() || {};
|
||||||
return settings[settingName];
|
return settings[settingName];
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
if (this._featureNames.includes(settingName)) {
|
if (this.featureNames.includes(settingName)) {
|
||||||
this._writeFeature(settingName, newValue);
|
this.writeFeature(settingName, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case notifications
|
// Special case notifications
|
||||||
if (settingName === "notificationsEnabled") {
|
if (settingName === "notificationsEnabled") {
|
||||||
localStorage.setItem("notifications_enabled", newValue);
|
localStorage.setItem("notifications_enabled", newValue);
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} else if (settingName === "notificationBodyEnabled") {
|
} else if (settingName === "notificationBodyEnabled") {
|
||||||
localStorage.setItem("notifications_body_enabled", newValue);
|
localStorage.setItem("notifications_body_enabled", newValue);
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} else if (settingName === "audioNotificationsEnabled") {
|
} else if (settingName === "audioNotificationsEnabled") {
|
||||||
localStorage.setItem("audio_notifications_enabled", newValue);
|
localStorage.setItem("audio_notifications_enabled", newValue);
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,35 +102,35 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
||||||
"lastRightPanelPhaseForGroup",
|
"lastRightPanelPhaseForGroup",
|
||||||
].includes(settingName)) {
|
].includes(settingName)) {
|
||||||
localStorage.setItem(`mx_${settingName}`, JSON.stringify({value: newValue}));
|
localStorage.setItem(`mx_${settingName}`, JSON.stringify({value: newValue}));
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = this._getSettings() || {};
|
const settings = this.getSettings() || {};
|
||||||
settings[settingName] = newValue;
|
settings[settingName] = newValue;
|
||||||
localStorage.setItem("mx_local_settings", JSON.stringify(settings));
|
localStorage.setItem("mx_local_settings", JSON.stringify(settings));
|
||||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
return true; // It's their device, so they should be able to
|
return true; // It's their device, so they should be able to
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
return localStorage !== undefined && localStorage !== null;
|
return localStorage !== undefined && localStorage !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
watchSetting(settingName, roomId, cb) {
|
public watchSetting(settingName: string, roomId: string, cb: CallbackFn) {
|
||||||
this._watchers.watchSetting(settingName, roomId, cb);
|
this.watchers.watchSetting(settingName, roomId, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
unwatchSetting(cb) {
|
public unwatchSetting(cb: CallbackFn) {
|
||||||
this._watchers.unwatchSetting(cb);
|
this.watchers.unwatchSetting(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSettings() {
|
private getSettings(): any { // TODO: [TS] Type return
|
||||||
const value = localStorage.getItem("mx_local_settings");
|
const value = localStorage.getItem("mx_local_settings");
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
return JSON.parse(value);
|
return JSON.parse(value);
|
||||||
|
@ -140,7 +139,7 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
||||||
// Note: features intentionally don't use the same key as settings to avoid conflicts
|
// Note: features intentionally don't use the same key as settings to avoid conflicts
|
||||||
// and to be backwards compatible.
|
// and to be backwards compatible.
|
||||||
|
|
||||||
_readFeature(featureName) {
|
private readFeature(featureName: string): boolean | null {
|
||||||
if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest()) {
|
if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest()) {
|
||||||
// Guests should not have any labs features enabled.
|
// Guests should not have any labs features enabled.
|
||||||
return false;
|
return false;
|
||||||
|
@ -153,8 +152,8 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_writeFeature(featureName, enabled) {
|
private writeFeature(featureName: string, enabled: boolean | null) {
|
||||||
localStorage.setItem("mx_labs_feature_" + featureName, enabled);
|
localStorage.setItem("mx_labs_feature_" + featureName, `${enabled}`);
|
||||||
this._watchers.notifyUpdate(featureName, null, SettingLevel.DEVICE, enabled);
|
this.watchers.notifyUpdate(featureName, null, SettingLevel.DEVICE, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -23,47 +23,48 @@ import SettingsHandler from "./SettingsHandler";
|
||||||
* handler as much as possible to ensure values are not stale.
|
* handler as much as possible to ensure values are not stale.
|
||||||
*/
|
*/
|
||||||
export default class LocalEchoWrapper extends SettingsHandler {
|
export default class LocalEchoWrapper extends SettingsHandler {
|
||||||
|
private cache: {
|
||||||
|
[settingName: string]: {
|
||||||
|
[roomId: string]: any;
|
||||||
|
};
|
||||||
|
} = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new local echo wrapper
|
* Creates a new local echo wrapper
|
||||||
* @param {SettingsHandler} handler The handler to wrap
|
* @param {SettingsHandler} handler The handler to wrap
|
||||||
*/
|
*/
|
||||||
constructor(handler) {
|
constructor(private handler: SettingsHandler) {
|
||||||
super();
|
super();
|
||||||
this._handler = handler;
|
|
||||||
this._cache = {
|
|
||||||
// settingName: { roomId: value }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
const cacheRoomId = roomId ? roomId : "UNDEFINED"; // avoid weird keys
|
const cacheRoomId = roomId ? roomId : "UNDEFINED"; // avoid weird keys
|
||||||
const bySetting = this._cache[settingName];
|
const bySetting = this.cache[settingName];
|
||||||
if (bySetting && bySetting.hasOwnProperty(cacheRoomId)) {
|
if (bySetting && bySetting.hasOwnProperty(cacheRoomId)) {
|
||||||
return bySetting[cacheRoomId];
|
return bySetting[cacheRoomId];
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._handler.getValue(settingName, roomId);
|
return this.handler.getValue(settingName, roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
if (!this._cache[settingName]) this._cache[settingName] = {};
|
if (!this.cache[settingName]) this.cache[settingName] = {};
|
||||||
const bySetting = this._cache[settingName];
|
const bySetting = this.cache[settingName];
|
||||||
|
|
||||||
const cacheRoomId = roomId ? roomId : "UNDEFINED"; // avoid weird keys
|
const cacheRoomId = roomId ? roomId : "UNDEFINED"; // avoid weird keys
|
||||||
bySetting[cacheRoomId] = newValue;
|
bySetting[cacheRoomId] = newValue;
|
||||||
|
|
||||||
const handlerPromise = this._handler.setValue(settingName, roomId, newValue);
|
const handlerPromise = this.handler.setValue(settingName, roomId, newValue);
|
||||||
return Promise.resolve(handlerPromise).finally(() => {
|
return Promise.resolve(handlerPromise).finally(() => {
|
||||||
delete bySetting[cacheRoomId];
|
delete bySetting[cacheRoomId];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
canSetValue(settingName, roomId) {
|
return this.handler.canSetValue(settingName, roomId);
|
||||||
return this._handler.canSetValue(settingName, roomId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
return this._handler.isSupported();
|
return this.handler.isSupported();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import SettingsHandler from "./SettingsHandler";
|
import SettingsHandler from "./SettingsHandler";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
|
||||||
// Dev note: This whole class exists in the event someone logs out and back in - we want
|
// Dev note: This whole class exists in the event someone logs out and back in - we want
|
||||||
// to make sure the right MatrixClient is listening for changes.
|
// to make sure the right MatrixClient is listening for changes.
|
||||||
|
@ -23,30 +24,30 @@ import SettingsHandler from "./SettingsHandler";
|
||||||
* Represents the base class for settings handlers which need access to a MatrixClient.
|
* Represents the base class for settings handlers which need access to a MatrixClient.
|
||||||
* This class performs no logic and should be overridden.
|
* This class performs no logic and should be overridden.
|
||||||
*/
|
*/
|
||||||
export default class MatrixClientBackedSettingsHandler extends SettingsHandler {
|
export default abstract class MatrixClientBackedSettingsHandler extends SettingsHandler {
|
||||||
static _matrixClient;
|
private static _matrixClient: MatrixClient;
|
||||||
static _instances = [];
|
private static instances: MatrixClientBackedSettingsHandler[] = [];
|
||||||
|
|
||||||
static set matrixClient(client) {
|
public static set matrixClient(client: MatrixClient) {
|
||||||
const oldClient = MatrixClientBackedSettingsHandler._matrixClient;
|
const oldClient = MatrixClientBackedSettingsHandler._matrixClient;
|
||||||
MatrixClientBackedSettingsHandler._matrixClient = client;
|
MatrixClientBackedSettingsHandler._matrixClient = client;
|
||||||
|
|
||||||
for (const instance of MatrixClientBackedSettingsHandler._instances) {
|
for (const instance of MatrixClientBackedSettingsHandler.instances) {
|
||||||
instance.initMatrixClient(oldClient, client);
|
instance.initMatrixClient(oldClient, client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
protected constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
MatrixClientBackedSettingsHandler._instances.push(this);
|
MatrixClientBackedSettingsHandler.instances.push(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get client() {
|
public get client(): MatrixClient {
|
||||||
return MatrixClientBackedSettingsHandler._matrixClient;
|
return MatrixClientBackedSettingsHandler._matrixClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
initMatrixClient() {
|
protected initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||||
console.warn("initMatrixClient not overridden");
|
console.warn("initMatrixClient not overridden");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -15,10 +15,14 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import { objectClone, objectKeyChanges } from "../../utils/objects";
|
||||||
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
import { WatchManager } from "../WatchManager";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
|
||||||
const ALLOWED_WIDGETS_EVENT_TYPE = "im.vector.setting.allowed_widgets";
|
const ALLOWED_WIDGETS_EVENT_TYPE = "im.vector.setting.allowed_widgets";
|
||||||
|
|
||||||
|
@ -26,22 +30,19 @@ const ALLOWED_WIDGETS_EVENT_TYPE = "im.vector.setting.allowed_widgets";
|
||||||
* Gets and sets settings at the "room-account" level for the current user.
|
* Gets and sets settings at the "room-account" level for the current user.
|
||||||
*/
|
*/
|
||||||
export default class RoomAccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
export default class RoomAccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||||
constructor(watchManager) {
|
constructor(private watchers: WatchManager) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._watchers = watchManager;
|
|
||||||
this._onAccountData = this._onAccountData.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initMatrixClient(oldClient, newClient) {
|
protected initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||||
if (oldClient) {
|
if (oldClient) {
|
||||||
oldClient.removeListener("Room.accountData", this._onAccountData);
|
oldClient.removeListener("Room.accountData", this.onAccountData);
|
||||||
}
|
}
|
||||||
|
|
||||||
newClient.on("Room.accountData", this._onAccountData);
|
newClient.on("Room.accountData", this.onAccountData);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAccountData(event, room, prevEvent) {
|
private onAccountData = (event: MatrixEvent, room: Room, prevEvent: MatrixEvent) => {
|
||||||
const roomId = room.roomId;
|
const roomId = room.roomId;
|
||||||
|
|
||||||
if (event.getType() === "org.matrix.room.preview_urls") {
|
if (event.getType() === "org.matrix.room.preview_urls") {
|
||||||
|
@ -52,29 +53,29 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
|
||||||
val = !val;
|
val = !val;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM_ACCOUNT, val);
|
this.watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM_ACCOUNT, val);
|
||||||
} else if (event.getType() === "org.matrix.room.color_scheme") {
|
} else if (event.getType() === "org.matrix.room.color_scheme") {
|
||||||
this._watchers.notifyUpdate("roomColor", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
|
this.watchers.notifyUpdate("roomColor", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
|
||||||
} else if (event.getType() === "im.vector.web.settings") {
|
} else if (event.getType() === "im.vector.web.settings") {
|
||||||
// Figure out what changed and fire those updates
|
// Figure out what changed and fire those updates
|
||||||
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
||||||
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
||||||
for (const settingName of changedSettings) {
|
for (const settingName of changedSettings) {
|
||||||
const val = event.getContent()[settingName];
|
const val = event.getContent()[settingName];
|
||||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_ACCOUNT, val);
|
this.watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_ACCOUNT, val);
|
||||||
}
|
}
|
||||||
} else if (event.getType() === ALLOWED_WIDGETS_EVENT_TYPE) {
|
} else if (event.getType() === ALLOWED_WIDGETS_EVENT_TYPE) {
|
||||||
this._watchers.notifyUpdate("allowedWidgets", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
|
this.watchers.notifyUpdate("allowedWidgets", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
// Special case URL previews
|
// Special case URL previews
|
||||||
if (settingName === "urlPreviewsEnabled") {
|
if (settingName === "urlPreviewsEnabled") {
|
||||||
const content = this._getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
const content = this.getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
||||||
|
|
||||||
// Check to make sure that we actually got a boolean
|
// Check to make sure that we actually got a boolean
|
||||||
if (typeof(content['disable']) !== "boolean") return null;
|
if (typeof (content['disable']) !== "boolean") return null;
|
||||||
return !content['disable'];
|
return !content['disable'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,22 +84,22 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
|
||||||
// The event content should already be in an appropriate format, we just need
|
// The event content should already be in an appropriate format, we just need
|
||||||
// to get the right value.
|
// to get the right value.
|
||||||
// don't fallback to {} because thats truthy and would imply there is an event specifying tint
|
// don't fallback to {} because thats truthy and would imply there is an event specifying tint
|
||||||
return this._getSettings(roomId, "org.matrix.room.color_scheme");
|
return this.getSettings(roomId, "org.matrix.room.color_scheme");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case allowed widgets
|
// Special case allowed widgets
|
||||||
if (settingName === "allowedWidgets") {
|
if (settingName === "allowedWidgets") {
|
||||||
return this._getSettings(roomId, ALLOWED_WIDGETS_EVENT_TYPE);
|
return this.getSettings(roomId, ALLOWED_WIDGETS_EVENT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = this._getSettings(roomId) || {};
|
const settings = this.getSettings(roomId) || {};
|
||||||
return settings[settingName];
|
return settings[settingName];
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
// Special case URL previews
|
// Special case URL previews
|
||||||
if (settingName === "urlPreviewsEnabled") {
|
if (settingName === "urlPreviewsEnabled") {
|
||||||
const content = this._getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
const content = this.getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
||||||
content['disable'] = !newValue;
|
content['disable'] = !newValue;
|
||||||
return MatrixClientPeg.get().setRoomAccountData(roomId, "org.matrix.room.preview_urls", content);
|
return MatrixClientPeg.get().setRoomAccountData(roomId, "org.matrix.room.preview_urls", content);
|
||||||
}
|
}
|
||||||
|
@ -114,24 +115,24 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
|
||||||
return MatrixClientPeg.get().setRoomAccountData(roomId, ALLOWED_WIDGETS_EVENT_TYPE, newValue);
|
return MatrixClientPeg.get().setRoomAccountData(roomId, ALLOWED_WIDGETS_EVENT_TYPE, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = this._getSettings(roomId) || {};
|
const content = this.getSettings(roomId) || {};
|
||||||
content[settingName] = newValue;
|
content[settingName] = newValue;
|
||||||
return MatrixClientPeg.get().setRoomAccountData(roomId, "im.vector.web.settings", content);
|
return MatrixClientPeg.get().setRoomAccountData(roomId, "im.vector.web.settings", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||||
|
|
||||||
// If they have the room, they can set their own account data
|
// If they have the room, they can set their own account data
|
||||||
return room !== undefined && room !== null;
|
return room !== undefined && room !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
return cli !== undefined && cli !== null;
|
return cli !== undefined && cli !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSettings(roomId, eventType = "im.vector.web.settings") {
|
private getSettings(roomId: string, eventType = "im.vector.web.settings"): any { // TODO: [TS] Type return
|
||||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||||
if (!room) return null;
|
if (!room) return null;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,71 +16,70 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import SettingsHandler from "./SettingsHandler";
|
import SettingsHandler from "./SettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
import { WatchManager } from "../WatchManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets and sets settings at the "room-device" level for the current device in a particular
|
* Gets and sets settings at the "room-device" level for the current device in a particular
|
||||||
* room.
|
* room.
|
||||||
*/
|
*/
|
||||||
export default class RoomDeviceSettingsHandler extends SettingsHandler {
|
export default class RoomDeviceSettingsHandler extends SettingsHandler {
|
||||||
constructor(watchManager) {
|
constructor(private watchers: WatchManager) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._watchers = watchManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
// Special case blacklist setting to use legacy values
|
// Special case blacklist setting to use legacy values
|
||||||
if (settingName === "blacklistUnverifiedDevices") {
|
if (settingName === "blacklistUnverifiedDevices") {
|
||||||
const value = this._read("mx_local_settings");
|
const value = this.read("mx_local_settings");
|
||||||
if (value && value['blacklistUnverifiedDevicesPerRoom']) {
|
if (value && value['blacklistUnverifiedDevicesPerRoom']) {
|
||||||
return value['blacklistUnverifiedDevicesPerRoom'][roomId];
|
return value['blacklistUnverifiedDevicesPerRoom'][roomId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = this._read(this._getKey(settingName, roomId));
|
const value = this.read(this.getKey(settingName, roomId));
|
||||||
if (value) return value.value;
|
if (value) return value.value;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
// Special case blacklist setting for legacy structure
|
// Special case blacklist setting for legacy structure
|
||||||
if (settingName === "blacklistUnverifiedDevices") {
|
if (settingName === "blacklistUnverifiedDevices") {
|
||||||
let value = this._read("mx_local_settings");
|
let value = this.read("mx_local_settings");
|
||||||
if (!value) value = {};
|
if (!value) value = {};
|
||||||
if (!value["blacklistUnverifiedDevicesPerRoom"]) value["blacklistUnverifiedDevicesPerRoom"] = {};
|
if (!value["blacklistUnverifiedDevicesPerRoom"]) value["blacklistUnverifiedDevicesPerRoom"] = {};
|
||||||
value["blacklistUnverifiedDevicesPerRoom"][roomId] = newValue;
|
value["blacklistUnverifiedDevicesPerRoom"][roomId] = newValue;
|
||||||
localStorage.setItem("mx_local_settings", JSON.stringify(value));
|
localStorage.setItem("mx_local_settings", JSON.stringify(value));
|
||||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newValue === null) {
|
if (newValue === null) {
|
||||||
localStorage.removeItem(this._getKey(settingName, roomId));
|
localStorage.removeItem(this.getKey(settingName, roomId));
|
||||||
} else {
|
} else {
|
||||||
newValue = JSON.stringify({value: newValue});
|
newValue = JSON.stringify({value: newValue});
|
||||||
localStorage.setItem(this._getKey(settingName, roomId), newValue);
|
localStorage.setItem(this.getKey(settingName, roomId), newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
|
this.watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
return true; // It's their device, so they should be able to
|
return true; // It's their device, so they should be able to
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
return localStorage !== undefined && localStorage !== null;
|
return localStorage !== undefined && localStorage !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_read(key) {
|
private read(key: string): any {
|
||||||
const rawValue = localStorage.getItem(key);
|
const rawValue = localStorage.getItem(key);
|
||||||
if (!rawValue) return null;
|
if (!rawValue) return null;
|
||||||
return JSON.parse(rawValue);
|
return JSON.parse(rawValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getKey(settingName, roomId) {
|
private getKey(settingName: string, roomId: string): string {
|
||||||
return "mx_setting_" + settingName + "_" + roomId;
|
return "mx_setting_" + settingName + "_" + roomId;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -15,31 +15,32 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import { objectClone, objectKeyChanges } from "../../utils/objects";
|
||||||
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
import { WatchManager } from "../WatchManager";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import { RoomState } from "matrix-js-sdk/src/models/room-state";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets and sets settings at the "room" level.
|
* Gets and sets settings at the "room" level.
|
||||||
*/
|
*/
|
||||||
export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandler {
|
export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||||
constructor(watchManager) {
|
constructor(private watchers: WatchManager) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._watchers = watchManager;
|
|
||||||
this._onEvent = this._onEvent.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initMatrixClient(oldClient, newClient) {
|
protected initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||||
if (oldClient) {
|
if (oldClient) {
|
||||||
oldClient.removeListener("RoomState.events", this._onEvent);
|
oldClient.removeListener("RoomState.events", this.onEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
newClient.on("RoomState.events", this._onEvent);
|
newClient.on("RoomState.events", this.onEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onEvent(event, state, prevEvent) {
|
private onEvent = (event: MatrixEvent, state: RoomState, prevEvent: MatrixEvent) => {
|
||||||
const roomId = event.getRoomId();
|
const roomId = event.getRoomId();
|
||||||
const room = this.client.getRoom(roomId);
|
const room = this.client.getRoom(roomId);
|
||||||
|
|
||||||
|
@ -60,45 +61,45 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
|
||||||
val = !val;
|
val = !val;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM, val);
|
this.watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM, val);
|
||||||
} else if (event.getType() === "im.vector.web.settings") {
|
} else if (event.getType() === "im.vector.web.settings") {
|
||||||
// Figure out what changed and fire those updates
|
// Figure out what changed and fire those updates
|
||||||
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
||||||
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
||||||
for (const settingName of changedSettings) {
|
for (const settingName of changedSettings) {
|
||||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM, event.getContent()[settingName]);
|
this.watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM, event.getContent()[settingName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
getValue(settingName, roomId) {
|
public getValue(settingName: string, roomId: string): any {
|
||||||
// Special case URL previews
|
// Special case URL previews
|
||||||
if (settingName === "urlPreviewsEnabled") {
|
if (settingName === "urlPreviewsEnabled") {
|
||||||
const content = this._getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
const content = this.getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
||||||
|
|
||||||
// Check to make sure that we actually got a boolean
|
// Check to make sure that we actually got a boolean
|
||||||
if (typeof(content['disable']) !== "boolean") return null;
|
if (typeof (content['disable']) !== "boolean") return null;
|
||||||
return !content['disable'];
|
return !content['disable'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = this._getSettings(roomId) || {};
|
const settings = this.getSettings(roomId) || {};
|
||||||
return settings[settingName];
|
return settings[settingName];
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(settingName, roomId, newValue) {
|
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||||
// Special case URL previews
|
// Special case URL previews
|
||||||
if (settingName === "urlPreviewsEnabled") {
|
if (settingName === "urlPreviewsEnabled") {
|
||||||
const content = this._getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
const content = this.getSettings(roomId, "org.matrix.room.preview_urls") || {};
|
||||||
content['disable'] = !newValue;
|
content['disable'] = !newValue;
|
||||||
return MatrixClientPeg.get().sendStateEvent(roomId, "org.matrix.room.preview_urls", content);
|
return MatrixClientPeg.get().sendStateEvent(roomId, "org.matrix.room.preview_urls", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = this._getSettings(roomId) || {};
|
const content = this.getSettings(roomId) || {};
|
||||||
content[settingName] = newValue;
|
content[settingName] = newValue;
|
||||||
return MatrixClientPeg.get().sendStateEvent(roomId, "im.vector.web.settings", content, "");
|
return MatrixClientPeg.get().sendStateEvent(roomId, "im.vector.web.settings", content, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetValue(settingName, roomId) {
|
public canSetValue(settingName: string, roomId: string): boolean {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const room = cli.getRoom(roomId);
|
const room = cli.getRoom(roomId);
|
||||||
|
|
||||||
|
@ -109,12 +110,12 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
|
||||||
return room.currentState.maySendStateEvent(eventType, cli.getUserId());
|
return room.currentState.maySendStateEvent(eventType, cli.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported() {
|
public isSupported(): boolean {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
return cli !== undefined && cli !== null;
|
return cli !== undefined && cli !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSettings(roomId, eventType = "im.vector.web.settings") {
|
private getSettings(roomId: string, eventType = "im.vector.web.settings"): any {
|
||||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||||
if (!room) return null;
|
if (!room) return null;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Travis Ralston
|
Copyright 2017 Travis Ralston
|
||||||
Copyright 2019 New Vector Ltd.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
* Represents the base class for all level handlers. This class performs no logic
|
* Represents the base class for all level handlers. This class performs no logic
|
||||||
* and should be overridden.
|
* and should be overridden.
|
||||||
*/
|
*/
|
||||||
export default class SettingsHandler {
|
export default abstract class SettingsHandler {
|
||||||
/**
|
/**
|
||||||
* Gets the value for a particular setting at this level for a particular room.
|
* Gets the value for a particular setting at this level for a particular room.
|
||||||
* If no room is applicable, the roomId may be null. The roomId may not be
|
* If no room is applicable, the roomId may be null. The roomId may not be
|
||||||
|
@ -28,10 +28,7 @@ export default class SettingsHandler {
|
||||||
* @param {String} roomId The room ID to read from, may be null.
|
* @param {String} roomId The room ID to read from, may be null.
|
||||||
* @returns {*} The setting value, or null if not found.
|
* @returns {*} The setting value, or null if not found.
|
||||||
*/
|
*/
|
||||||
getValue(settingName, roomId) {
|
public abstract getValue(settingName: string, roomId: string): any;
|
||||||
console.error("Invalid operation: getValue was not overridden");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value for a particular setting at this level for a particular room.
|
* Sets the value for a particular setting at this level for a particular room.
|
||||||
|
@ -44,10 +41,7 @@ export default class SettingsHandler {
|
||||||
* @param {*} newValue The new value for the setting, may be null.
|
* @param {*} newValue The new value for the setting, may be null.
|
||||||
* @returns {Promise} Resolves when the setting has been saved.
|
* @returns {Promise} Resolves when the setting has been saved.
|
||||||
*/
|
*/
|
||||||
setValue(settingName, roomId, newValue) {
|
public abstract setValue(settingName: string, roomId: string, newValue: any): Promise<void>;
|
||||||
console.error("Invalid operation: setValue was not overridden");
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the current user is able to set the value of the given setting
|
* Determines if the current user is able to set the value of the given setting
|
||||||
|
@ -56,15 +50,11 @@ export default class SettingsHandler {
|
||||||
* @param {String} roomId The room ID to check in, may be null
|
* @param {String} roomId The room ID to check in, may be null
|
||||||
* @returns {boolean} True if the setting can be set by the user, false otherwise.
|
* @returns {boolean} True if the setting can be set by the user, false otherwise.
|
||||||
*/
|
*/
|
||||||
canSetValue(settingName, roomId) {
|
public abstract canSetValue(settingName: string, roomId: string): boolean;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if this level is supported on this device.
|
* Determines if this level is supported on this device.
|
||||||
* @returns {boolean} True if this level is supported on the current device.
|
* @returns {boolean} True if this level is supported on the current device.
|
||||||
*/
|
*/
|
||||||
isSupported() {
|
public abstract isSupported(): boolean;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -15,10 +15,11 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import dis from '../../dispatcher/dispatcher';
|
import dis from '../../dispatcher/dispatcher';
|
||||||
import SettingsStore, {SettingLevel} from '../SettingsStore';
|
import SettingsStore from '../SettingsStore';
|
||||||
import IWatcher from "./Watcher";
|
import IWatcher from "./Watcher";
|
||||||
import { toPx } from '../../utils/units';
|
import { toPx } from '../../utils/units';
|
||||||
import { Action } from '../../dispatcher/actions';
|
import { Action } from '../../dispatcher/actions';
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export class FontWatcher implements IWatcher {
|
export class FontWatcher implements IWatcher {
|
||||||
public static readonly MIN_SIZE = 8;
|
public static readonly MIN_SIZE = 8;
|
||||||
|
|
|
@ -15,17 +15,15 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import SettingsStore, { SettingLevel } from '../SettingsStore';
|
import SettingsStore from '../SettingsStore';
|
||||||
import dis from '../../dispatcher/dispatcher';
|
import dis from '../../dispatcher/dispatcher';
|
||||||
import { Action } from '../../dispatcher/actions';
|
import { Action } from '../../dispatcher/actions';
|
||||||
import ThemeController from "../controllers/ThemeController";
|
import ThemeController from "../controllers/ThemeController";
|
||||||
import { setTheme } from "../../theme";
|
import { setTheme } from "../../theme";
|
||||||
import { ActionPayload } from '../../dispatcher/payloads';
|
import { ActionPayload } from '../../dispatcher/payloads';
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
|
||||||
export default class ThemeWatcher {
|
export default class ThemeWatcher {
|
||||||
// XXX: I think this is unused.
|
|
||||||
static _instance = null;
|
|
||||||
|
|
||||||
private themeWatchRef: string;
|
private themeWatchRef: string;
|
||||||
private systemThemeWatchRef: string;
|
private systemThemeWatchRef: string;
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
|
|
|
@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import SettingsStore, { SettingLevel } from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { ActionPayload } from "../dispatcher/payloads";
|
import { ActionPayload } from "../dispatcher/payloads";
|
||||||
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
||||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||||
import { arrayHasDiff } from "../utils/arrays";
|
import { arrayHasDiff } from "../utils/arrays";
|
||||||
import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
|
import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
|
||||||
|
import { SettingLevel } from "../settings/SettingLevel";
|
||||||
|
|
||||||
const MAX_ROOMS = 20; // arbitrary
|
const MAX_ROOMS = 20; // arbitrary
|
||||||
const AUTOJOIN_WAIT_THRESHOLD_MS = 90000; // 90s, the time we wait for an autojoined room to show up
|
const AUTOJOIN_WAIT_THRESHOLD_MS = 90000; // 90s, the time we wait for an autojoined room to show up
|
||||||
|
|
|
@ -17,10 +17,11 @@ limitations under the License.
|
||||||
import dis from '../dispatcher/dispatcher';
|
import dis from '../dispatcher/dispatcher';
|
||||||
import {pendingVerificationRequestForUser} from '../verification';
|
import {pendingVerificationRequestForUser} from '../verification';
|
||||||
import {Store} from 'flux/utils';
|
import {Store} from 'flux/utils';
|
||||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import {RightPanelPhases, RIGHT_PANEL_PHASES_NO_ARGS} from "./RightPanelStorePhases";
|
import {RightPanelPhases, RIGHT_PANEL_PHASES_NO_ARGS} from "./RightPanelStorePhases";
|
||||||
import {ActionPayload} from "../dispatcher/payloads";
|
import {ActionPayload} from "../dispatcher/payloads";
|
||||||
import {Action} from '../dispatcher/actions';
|
import {Action} from '../dispatcher/actions';
|
||||||
|
import { SettingLevel } from "../settings/SettingLevel";
|
||||||
|
|
||||||
interface RightPanelStoreState {
|
interface RightPanelStoreState {
|
||||||
// Whether or not to show the right panel at all. We split out rooms and groups
|
// Whether or not to show the right panel at all. We split out rooms and groups
|
||||||
|
|
Loading…
Reference in New Issue