mirror of
https://github.com/element-hq/element-web
synced 2024-11-27 19:56:47 +03:00
Merge pull request #5062 from matrix-org/travis/settings/ts
Convert SettingsStore to TypeScript
This commit is contained in:
commit
3443761007
64 changed files with 569 additions and 452 deletions
2
src/@types/global.d.ts
vendored
2
src/@types/global.d.ts
vendored
|
@ -25,6 +25,7 @@ import { PlatformPeg } from "../PlatformPeg";
|
|||
import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
|
||||
import {IntegrationManagers} from "../integrations/IntegrationManagers";
|
||||
import {ModalManager} from "../Modal";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -43,6 +44,7 @@ declare global {
|
|||
mxPlatformPeg: PlatformPeg;
|
||||
mxIntegrationManagers: typeof IntegrationManagers;
|
||||
singletonModalManager: ModalManager;
|
||||
mxSettingsStore: SettingsStore;
|
||||
}
|
||||
|
||||
// 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 WidgetUtils from './utils/WidgetUtils';
|
||||
import WidgetEchoStore from './stores/WidgetEchoStore';
|
||||
import SettingsStore, { SettingLevel } from './settings/SettingsStore';
|
||||
import SettingsStore from './settings/SettingsStore';
|
||||
import {generateHumanReadableId} from "./utils/NamingUtils";
|
||||
import {Jitsi} from "./widgets/Jitsi";
|
||||
import {WidgetType} from "./widgets/WidgetType";
|
||||
import {SettingLevel} from "./settings/SettingLevel";
|
||||
|
||||
global.mxCalls = {
|
||||
//room_id: MatrixCall
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
*/
|
||||
|
||||
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 {
|
||||
hasAnyLabeledDevices: async function() {
|
||||
|
|
|
@ -256,7 +256,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
|
|||
deviceId: creds.deviceId,
|
||||
pickleKey: creds.pickleKey,
|
||||
timelineSupport: true,
|
||||
forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer', false),
|
||||
forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer'),
|
||||
fallbackICEServerAllowed: !!SettingsStore.getValue('fallbackICEServerAllowed'),
|
||||
verificationMethods: [
|
||||
verificationMethods.SAS,
|
||||
|
|
|
@ -27,10 +27,11 @@ import dis from './dispatcher/dispatcher';
|
|||
import * as sdk from './index';
|
||||
import { _t } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import {
|
||||
hideToast as hideNotificationsToast,
|
||||
} from "./toasts/DesktopNotificationsToast";
|
||||
import {SettingLevel} from "./settings/SettingLevel";
|
||||
|
||||
/*
|
||||
* Dispatches:
|
||||
|
|
|
@ -20,9 +20,10 @@ import PropTypes from 'prop-types';
|
|||
import dis from "../../../../dispatcher/dispatcher";
|
||||
import { _t } from '../../../../languageHandler';
|
||||
|
||||
import SettingsStore, {SettingLevel} from "../../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../../settings/SettingsStore";
|
||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||
import {Action} from "../../../../dispatcher/actions";
|
||||
import {SettingLevel} from "../../../../settings/SettingLevel";
|
||||
|
||||
/*
|
||||
* Allows the user to disable the Event Index.
|
||||
|
|
|
@ -19,11 +19,12 @@ import * as sdk from '../../../../index';
|
|||
import PropTypes from 'prop-types';
|
||||
import { _t } from '../../../../languageHandler';
|
||||
import SdkConfig from '../../../../SdkConfig';
|
||||
import SettingsStore, {SettingLevel} from "../../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../../settings/SettingsStore";
|
||||
|
||||
import Modal from '../../../../Modal';
|
||||
import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils";
|
||||
import EventIndexPeg from "../../../../indexing/EventIndexPeg";
|
||||
import {SettingLevel} from "../../../../settings/SettingLevel";
|
||||
|
||||
/*
|
||||
* 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 {_t, _td, getCurrentLanguage} from '../../languageHandler';
|
||||
import SettingsStore, { SettingLevel } from "../../settings/SettingsStore";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import ThemeController from "../../settings/controllers/ThemeController";
|
||||
import { startAnyRegistrationFlow } from "../../Registration.js";
|
||||
import { messageForSyncError } from '../../utils/ErrorUtils';
|
||||
|
@ -75,6 +75,7 @@ import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificat
|
|||
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
||||
import ErrorDialog from "../views/dialogs/ErrorDialog";
|
||||
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
||||
import { SettingLevel } from "../../settings/SettingLevel";
|
||||
|
||||
/** constants for MatrixChat.state.view */
|
||||
export enum Views {
|
||||
|
|
|
@ -48,7 +48,7 @@ import RightPanel from './RightPanel';
|
|||
import RoomViewStore from '../../stores/RoomViewStore';
|
||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import {haveTileForEvent} from "../views/rooms/EventTile";
|
||||
|
@ -56,6 +56,7 @@ import RoomContext from "../../contexts/RoomContext";
|
|||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import { shieldStatusForRoom } from '../../utils/ShieldUtils';
|
||||
import {Action} from "../../dispatcher/actions";
|
||||
import {SettingLevel} from "../../settings/SettingLevel";
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function() {};
|
||||
|
|
|
@ -26,7 +26,7 @@ import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
|||
import RedesignFeedbackDialog from "../views/dialogs/RedesignFeedbackDialog";
|
||||
import Modal from "../../Modal";
|
||||
import LogoutDialog from "../views/dialogs/LogoutDialog";
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import {getCustomTheme} from "../../theme";
|
||||
import {getHostingLink} from "../../utils/HostingLink";
|
||||
import {ButtonEvent} from "../views/elements/AccessibleButton";
|
||||
|
@ -37,6 +37,7 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
|||
import BaseAvatar from '../views/avatars/BaseAvatar';
|
||||
import classNames from "classnames";
|
||||
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
||||
import { SettingLevel } from "../../settings/SettingLevel";
|
||||
|
||||
interface IProps {
|
||||
isMinimized: boolean;
|
||||
|
|
|
@ -16,10 +16,11 @@ limitations under the License.
|
|||
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import {getCurrentLanguage} from "../../../languageHandler";
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import PlatformPeg from "../../../PlatformPeg";
|
||||
import * as sdk from '../../../index';
|
||||
import React from 'react';
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
function onChange(newLang) {
|
||||
if (getCurrentLanguage() !== newLang) {
|
||||
|
|
|
@ -19,8 +19,8 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
export default createReactClass({
|
||||
propTypes: {
|
||||
|
|
|
@ -17,10 +17,11 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {_t} from "../../../languageHandler";
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import * as sdk from "../../../index";
|
||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -35,12 +35,13 @@ import dis from '../../../dispatcher/dispatcher';
|
|||
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
||||
import classNames from 'classnames';
|
||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import {aboveLeftOf, ContextMenu, ContextMenuButton} from "../../structures/ContextMenu";
|
||||
import PersistedElement from "./PersistedElement";
|
||||
import {WidgetType} from "../../../widgets/WidgetType";
|
||||
import {Capability} from "../../../widgets/WidgetApi";
|
||||
import {sleep} from "../../../utils/promise";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
||||
const ENABLE_REACT_PERF = false;
|
||||
|
|
|
@ -15,8 +15,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import Draggable, {ILocationState} from './Draggable';
|
||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||
|
||||
interface IProps {
|
||||
// Current room
|
||||
|
|
|
@ -20,11 +20,12 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
import { _t } from '../../../languageHandler';
|
||||
import ToggleSwitch from "./ToggleSwitch";
|
||||
import StyledCheckbox from "./StyledCheckbox";
|
||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||
|
||||
interface IProps {
|
||||
// The setting must be a boolean
|
||||
name: string;
|
||||
level: string;
|
||||
level: SettingLevel;
|
||||
roomId?: string; // for per-room settings
|
||||
label?: string; // untranslated
|
||||
isExplicit?: boolean;
|
||||
|
@ -52,8 +53,8 @@ export default class SettingsFlag extends React.Component<IProps, IState> {
|
|||
};
|
||||
}
|
||||
|
||||
private onChange = (checked: boolean): void => {
|
||||
this.save(checked);
|
||||
private onChange = async (checked: boolean) => {
|
||||
await this.save(checked);
|
||||
this.setState({ value: 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);
|
||||
};
|
||||
|
||||
private save = (val?: boolean): void => {
|
||||
return SettingsStore.setValue(
|
||||
private save = async (val?: boolean) => {
|
||||
await SettingsStore.setValue(
|
||||
this.props.name,
|
||||
this.props.roomId,
|
||||
this.props.level,
|
||||
|
|
|
@ -20,7 +20,8 @@ import createReactClass from 'create-react-class';
|
|||
|
||||
import Tinter from '../../../Tinter';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
const ROOM_COLORS = [
|
||||
// magic room default values courtesy of Ribot
|
||||
|
|
|
@ -22,10 +22,11 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from "../../../index";
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
|
||||
export default createReactClass({
|
||||
|
|
|
@ -21,7 +21,8 @@ import * as sdk from "../../../index";
|
|||
import { _t } from "../../../languageHandler";
|
||||
import Modal from "../../../Modal";
|
||||
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 {
|
||||
static propTypes = {
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
|
||||
import * as sdk from '../../../index';
|
||||
import {_t} from "../../../languageHandler";
|
||||
import {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
|
||||
|
||||
|
|
|
@ -20,10 +20,11 @@ import { _t } from '../../../languageHandler';
|
|||
import SdkConfig from "../../../SdkConfig";
|
||||
import * as sdk from '../../../index';
|
||||
import Modal from '../../../Modal';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import {formatBytes, formatCountLong} from "../../../utils/FormattingUtils";
|
||||
import EventIndexPeg from "../../../indexing/EventIndexPeg";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
export default class EventIndexPanel extends React.Component {
|
||||
constructor() {
|
||||
|
|
|
@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
|
|||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import SettingsStore, {SettingLevel} from '../../../settings/SettingsStore';
|
||||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
import Modal from '../../../Modal';
|
||||
import {
|
||||
NotificationUtils,
|
||||
|
@ -31,6 +31,7 @@ import {
|
|||
import SdkConfig from "../../../SdkConfig";
|
||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
|
||||
// TODO: this "view" component still has far too much application logic in it,
|
||||
// which should be factored out to other files.
|
||||
|
|
|
@ -18,7 +18,8 @@ import React from 'react';
|
|||
import {_t} from "../../../languageHandler";
|
||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||
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 {
|
||||
constructor() {
|
||||
|
|
|
@ -21,7 +21,7 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
|||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import Notifier from "../../../../../Notifier";
|
||||
import SettingsStore from '../../../../../settings/SettingsStore';
|
||||
import { SettingLevel } from '../../../../../settings/SettingsStore';
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export default class NotificationsSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -20,9 +20,9 @@ import {_t} from "../../../../../languageHandler";
|
|||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as sdk from "../../../../..";
|
||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import Modal from "../../../../../Modal";
|
||||
import QuestionDialog from "../../../dialogs/QuestionDialog";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export default class SecurityRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import SdkConfig from "../../../../../SdkConfig";
|
||||
import SettingsStore, {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import { enumerateThemes } from "../../../../../theme";
|
||||
import ThemeWatcher from "../../../../../settings/watchers/ThemeWatcher";
|
||||
import Slider from "../../../elements/Slider";
|
||||
|
@ -35,6 +35,7 @@ import Field from '../../../elements/Field';
|
|||
import EventTilePreview from '../../../elements/EventTilePreview';
|
||||
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
||||
import classNames from 'classnames';
|
||||
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
||||
|
||||
interface IProps {
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import React from 'react';
|
|||
import {_t} from "../../../../../languageHandler";
|
||||
import ProfileSettings from "../../ProfileSettings";
|
||||
import * as languageHandler from "../../../../../languageHandler";
|
||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import LanguageDropdown from "../../../elements/LanguageDropdown";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
|
@ -37,6 +36,7 @@ import IdentityAuthClient from "../../../../../IdentityAuthClient";
|
|||
import {abbreviateUrl} from "../../../../../utils/UrlUtils";
|
||||
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
|
||||
import Spinner from "../../../elements/Spinner";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export default class GeneralUserSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -17,9 +17,10 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import PropTypes from "prop-types";
|
||||
import SettingsStore, {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||
import * as sdk from "../../../../../index";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export class LabsSettingToggle extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -17,12 +17,12 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import Field from "../../../elements/Field";
|
||||
import * as sdk from "../../../../..";
|
||||
import PlatformPeg from "../../../../../PlatformPeg";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export default class PreferencesUserSettingsTab extends React.Component {
|
||||
static ROOM_LIST_SETTINGS = [
|
||||
|
|
|
@ -19,7 +19,6 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import SdkConfig from "../../../../../SdkConfig";
|
||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as FormattingUtils from "../../../../../utils/FormattingUtils";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
|
@ -29,6 +28,7 @@ import * as sdk from "../../../../..";
|
|||
import {sleep} from "../../../../../utils/promise";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
import {privateShouldBeEncrypted} from "../../../../../createRoom";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export class IgnoredUser extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -21,10 +21,10 @@ import SdkConfig from "../../../../../SdkConfig";
|
|||
import CallMediaHandler from "../../../../../CallMediaHandler";
|
||||
import Field from "../../../elements/Field";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import {SettingLevel} from "../../../../../settings/SettingsStore";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as sdk from "../../../../../index";
|
||||
import Modal from "../../../../../Modal";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
|
||||
export default class VoiceUserSettingsTab extends React.Component {
|
||||
constructor() {
|
||||
|
|
|
@ -15,8 +15,9 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import {orderBy} from "lodash";
|
||||
import { SettingLevel } from "../settings/SettingLevel";
|
||||
|
||||
interface ILegacyFormat {
|
||||
[emoji: string]: [number, number]; // [count, date]
|
||||
|
|
|
@ -18,8 +18,9 @@ import PlatformPeg from "../PlatformPeg";
|
|||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||
import {EventTimeline, RoomMember} from 'matrix-js-sdk';
|
||||
import {sleep} from "../utils/promise";
|
||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import {EventEmitter} from "events";
|
||||
import {SettingLevel} from "../settings/SettingLevel";
|
||||
|
||||
/*
|
||||
* Event indexing class that wraps the platform specific event indexing.
|
||||
|
|
|
@ -21,7 +21,8 @@ limitations under the License.
|
|||
|
||||
import PlatformPeg from "../PlatformPeg";
|
||||
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;
|
||||
|
||||
|
|
|
@ -21,11 +21,12 @@ import request from 'browser-request';
|
|||
import counterpart from 'counterpart';
|
||||
import React from 'react';
|
||||
|
||||
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import PlatformPeg from "./PlatformPeg";
|
||||
|
||||
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
|
||||
import webpackLangJsonUrl from "$webapp/i18n/languages.json";
|
||||
import { SettingLevel } from "./settings/SettingLevel";
|
||||
|
||||
const i18nFolder = 'i18n/';
|
||||
|
||||
|
|
|
@ -16,9 +16,10 @@ limitations under the License.
|
|||
|
||||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||
import {ALL_RULE_TYPES, BanList} from "./BanList";
|
||||
import SettingsStore, {SettingLevel} from "../settings/SettingsStore";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import {_t} from "../languageHandler";
|
||||
import dis from "../dispatcher/dispatcher";
|
||||
import {SettingLevel} from "../settings/SettingLevel";
|
||||
|
||||
// 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
|
||||
const enabledLabs = SettingsStore.getLabsFeatures().filter(SettingsStore.isFeatureEnabled);
|
||||
const enabledLabs = SettingsStore.getLabsFeatures().filter(f => SettingsStore.isFeatureEnabled(f));
|
||||
if (enabledLabs.length) {
|
||||
body.append('enabled_labs', enabledLabs.join(', '));
|
||||
}
|
||||
|
|
29
src/settings/SettingLevel.ts
Normal file
29
src/settings/SettingLevel.ts
Normal file
|
@ -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 2018, 2019 New Vector Ltd.
|
||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2018, 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -16,9 +15,9 @@ See the License for the specific language governing permissions and
|
|||
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 {
|
||||
AudioNotificationsEnabledController,
|
||||
NotificationBodyEnabledController,
|
||||
|
@ -28,75 +27,89 @@ import CustomStatusController from "./controllers/CustomStatusController";
|
|||
import ThemeController from './controllers/ThemeController';
|
||||
import PushToMatrixClientController from './controllers/PushToMatrixClientController';
|
||||
import ReloadOnChangeController from "./controllers/ReloadOnChangeController";
|
||||
import {RightPanelPhases} from "../stores/RightPanelStorePhases";
|
||||
import FontSizeController from './controllers/FontSizeController';
|
||||
import SystemFontController from './controllers/SystemFontController';
|
||||
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
|
||||
const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config'];
|
||||
const LEVELS_ROOM_OR_ACCOUNT = ['room-account', 'account'];
|
||||
const LEVELS_ROOM_SETTINGS_WITH_ROOM = ['device', 'room-device', 'room-account', 'account', 'config', 'room'];
|
||||
const LEVELS_ACCOUNT_SETTINGS = ['device', 'account', 'config'];
|
||||
const LEVELS_FEATURE = ['device', 'config'];
|
||||
const LEVELS_DEVICE_ONLY_SETTINGS = ['device'];
|
||||
const LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG = ['device', 'config'];
|
||||
const LEVELS_ROOM_SETTINGS = [
|
||||
SettingLevel.DEVICE,
|
||||
SettingLevel.ROOM_DEVICE,
|
||||
SettingLevel.ROOM_ACCOUNT,
|
||||
SettingLevel.ACCOUNT,
|
||||
SettingLevel.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 = {
|
||||
// EXAMPLE SETTING:
|
||||
// "my-setting": {
|
||||
// // Must be set to true for features. Default is 'false'.
|
||||
// isFeature: false,
|
||||
//
|
||||
// // Display names are strongly recommended for clarity.
|
||||
// displayName: _td("Cool Name"),
|
||||
//
|
||||
// // Display name can also be an object for different levels.
|
||||
// //displayName: {
|
||||
// // "device": _td("Name for when the setting is used at 'device'"),
|
||||
// // "room": _td("Name for when the setting is used at 'room'"),
|
||||
// // "default": _td("The name for all other levels"),
|
||||
// //}
|
||||
//
|
||||
// // The supported levels are required. Preferably, use the preset arrays
|
||||
// // at the top of this file to define this rather than a custom array.
|
||||
// supportedLevels: [
|
||||
// // The order does not matter.
|
||||
//
|
||||
// "device", // Affects the current device only
|
||||
// "room-device", // Affects the current room on the current device
|
||||
// "room-account", // Affects the current room for the current account
|
||||
// "account", // Affects the current account
|
||||
// "room", // Affects the current room (controlled by room admins)
|
||||
// "config", // Affects the current application
|
||||
//
|
||||
// // "default" is always supported and does not get listed here.
|
||||
// ],
|
||||
//
|
||||
// // Required. Can be any data type. The value specified here should match
|
||||
// // the data being stored (ie: if a boolean is used, the setting should
|
||||
// // represent a boolean).
|
||||
// default: {
|
||||
// your: "value",
|
||||
// },
|
||||
//
|
||||
// // Optional settings controller. See SettingsController for more information.
|
||||
// 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",
|
||||
// },
|
||||
export interface ISetting {
|
||||
// Must be set to true for features. Default is 'false'.
|
||||
isFeature?: boolean;
|
||||
|
||||
// Display names are strongly recommended for clarity.
|
||||
// Display name can also be an object for different levels.
|
||||
displayName?: string | {
|
||||
// @ts-ignore - TS wants the key to be a string, but we know better
|
||||
[level: SettingLevel]: string;
|
||||
};
|
||||
|
||||
// The supported levels are required. Preferably, use the preset arrays
|
||||
// at the top of this file to define this rather than a custom array.
|
||||
supportedLevels?: SettingLevel[];
|
||||
|
||||
// Required. Can be any data type. The value specified here should match
|
||||
// the data being stored (ie: if a boolean is used, the setting should
|
||||
// represent a boolean).
|
||||
default: any;
|
||||
|
||||
// Optional settings controller. See SettingsController for more information.
|
||||
controller?: SettingController;
|
||||
|
||||
// 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?: boolean;
|
||||
|
||||
// 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?: string;
|
||||
}
|
||||
|
||||
export const SETTINGS: {[setting: string]: ISetting} = {
|
||||
"feature_new_spinner": {
|
||||
isFeature: true,
|
||||
displayName: _td("New spinner design"),
|
||||
|
@ -153,11 +166,11 @@ export const SETTINGS = {
|
|||
default: false,
|
||||
},
|
||||
"mjolnirRooms": {
|
||||
supportedLevels: ['account'],
|
||||
supportedLevels: [SettingLevel.ACCOUNT],
|
||||
default: [],
|
||||
},
|
||||
"mjolnirPersonalRoom": {
|
||||
supportedLevels: ['account'],
|
||||
supportedLevels: [SettingLevel.ACCOUNT],
|
||||
default: null,
|
||||
},
|
||||
"feature_bridge_state": {
|
||||
|
@ -354,24 +367,24 @@ export const SETTINGS = {
|
|||
},
|
||||
"breadcrumb_rooms": {
|
||||
// not really a setting
|
||||
supportedLevels: ['account'],
|
||||
supportedLevels: [SettingLevel.ACCOUNT],
|
||||
default: [],
|
||||
},
|
||||
"recent_emoji": {
|
||||
// not really a setting
|
||||
supportedLevels: ['account'],
|
||||
supportedLevels: [SettingLevel.ACCOUNT],
|
||||
default: [],
|
||||
},
|
||||
"room_directory_servers": {
|
||||
supportedLevels: ['account'],
|
||||
supportedLevels: [SettingLevel.ACCOUNT],
|
||||
default: [],
|
||||
},
|
||||
"integrationProvisioning": {
|
||||
supportedLevels: ['account'],
|
||||
supportedLevels: [SettingLevel.ACCOUNT],
|
||||
default: true,
|
||||
},
|
||||
"allowedWidgets": {
|
||||
supportedLevels: ['room-account'],
|
||||
supportedLevels: [SettingLevel.ROOM_ACCOUNT],
|
||||
default: {}, // none allowed
|
||||
},
|
||||
"analyticsOptIn": {
|
||||
|
@ -398,7 +411,7 @@ export const SETTINGS = {
|
|||
"blacklistUnverifiedDevices": {
|
||||
// We specifically want to have room-device > device so that users may set a device default
|
||||
// with a per-room override.
|
||||
supportedLevels: ['room-device', 'device'],
|
||||
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.DEVICE],
|
||||
supportedLevelsAreOrdered: true,
|
||||
displayName: {
|
||||
"default": _td('Never send encrypted messages to unverified sessions from this session'),
|
||||
|
@ -416,7 +429,7 @@ export const SETTINGS = {
|
|||
default: true,
|
||||
},
|
||||
"urlPreviewsEnabled_e2ee": {
|
||||
supportedLevels: ['room-device', 'room-account'],
|
||||
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.ROOM_ACCOUNT],
|
||||
displayName: {
|
||||
"room-account": _td("Enable URL previews for this room (only affects you)"),
|
||||
},
|
||||
|
@ -455,7 +468,7 @@ export const SETTINGS = {
|
|||
default: false,
|
||||
},
|
||||
"PinnedEvents.isOpen": {
|
||||
supportedLevels: ['room-device'],
|
||||
supportedLevels: [SettingLevel.ROOM_DEVICE],
|
||||
default: false,
|
||||
},
|
||||
"promptBeforeInviteUnknownUsers": {
|
||||
|
@ -565,7 +578,8 @@ export const SETTINGS = {
|
|||
"ircDisplayNameWidth": {
|
||||
// We specifically want to have room-device > device so that users may set a device default
|
||||
// with a per-room override.
|
||||
supportedLevels: ['room-device', 'device'],
|
||||
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.DEVICE],
|
||||
supportedLevelsAreOrdered: true,
|
||||
displayName: _td("IRC display name width"),
|
||||
default: 80,
|
||||
},
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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 RoomSettingsHandler from "./handlers/RoomSettingsHandler";
|
||||
import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler";
|
||||
import {_t} from '../languageHandler';
|
||||
import { _t } from '../languageHandler';
|
||||
import SdkConfig from "../SdkConfig";
|
||||
import dis from '../dispatcher/dispatcher';
|
||||
import {SETTINGS} from "./Settings";
|
||||
import { ISetting, SETTINGS } from "./Settings";
|
||||
import LocalEchoWrapper from "./handlers/LocalEchoWrapper";
|
||||
import {WatchManager} from "./WatchManager";
|
||||
|
||||
/**
|
||||
* 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",
|
||||
};
|
||||
import { WatchManager } from "./WatchManager";
|
||||
import { SettingLevel } from "./SettingLevel";
|
||||
import SettingsHandler from "./handlers/SettingsHandler";
|
||||
|
||||
const defaultWatchManager = new WatchManager();
|
||||
|
||||
|
@ -61,13 +48,13 @@ for (const key of Object.keys(SETTINGS)) {
|
|||
}
|
||||
|
||||
const LEVEL_HANDLERS = {
|
||||
"device": new DeviceSettingsHandler(featureNames, defaultWatchManager),
|
||||
"room-device": new RoomDeviceSettingsHandler(defaultWatchManager),
|
||||
"room-account": new RoomAccountSettingsHandler(defaultWatchManager),
|
||||
"account": new AccountSettingsHandler(defaultWatchManager),
|
||||
"room": new RoomSettingsHandler(defaultWatchManager),
|
||||
"config": new ConfigSettingsHandler(),
|
||||
"default": new DefaultSettingsHandler(defaultSettings, invertedDefaultSettings),
|
||||
[SettingLevel.DEVICE]: new DeviceSettingsHandler(featureNames, defaultWatchManager),
|
||||
[SettingLevel.ROOM_DEVICE]: new RoomDeviceSettingsHandler(defaultWatchManager),
|
||||
[SettingLevel.ROOM_ACCOUNT]: new RoomAccountSettingsHandler(defaultWatchManager),
|
||||
[SettingLevel.ACCOUNT]: new AccountSettingsHandler(defaultWatchManager),
|
||||
[SettingLevel.ROOM]: new RoomSettingsHandler(defaultWatchManager),
|
||||
[SettingLevel.CONFIG]: new ConfigSettingsHandler(),
|
||||
[SettingLevel.DEFAULT]: new DefaultSettingsHandler(defaultSettings, invertedDefaultSettings),
|
||||
};
|
||||
|
||||
// Wrap all the handlers with local echo
|
||||
|
@ -76,20 +63,41 @@ for (const key of Object.keys(LEVEL_HANDLERS)) {
|
|||
}
|
||||
|
||||
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
|
||||
* 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:
|
||||
* - "device" - Values are determined by the current device
|
||||
* - "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
|
||||
* - "account" - Values are determined by the current account
|
||||
* - "room" - Values are determined by a particular room (by the room admins)
|
||||
* - "config" - Values are determined by the config.json
|
||||
* - "default" - Values are determined by the hardcoded defaults
|
||||
* - SettingLevel.DEVICE - Values are determined by the current device
|
||||
* - SettingLevel.ROOM_DEVICE - Values are determined by the current device for a particular room
|
||||
* - SettingLevel.ROOM_ACCOUNT - Values are determined by the current account for a particular room
|
||||
* - SettingLevel.ACCOUNT - Values are determined by the current account
|
||||
* - SettingLevel.ROOM - Values are determined by a particular room (by the room admins)
|
||||
* - SettingLevel.CONFIG - Values are determined by the config.json
|
||||
* - SettingLevel.DEFAULT - Values are determined by the hardcoded defaults
|
||||
*
|
||||
* 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
|
||||
|
@ -110,11 +118,11 @@ export default class SettingsStore {
|
|||
// 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
|
||||
// don't duplicate updates on the bus.
|
||||
static _watchers = {}; // { callbackRef => { callbackFn } }
|
||||
static _monitors = {}; // { settingName => { roomId => callbackRef } }
|
||||
private static watchers = {}; // { callbackRef => { callbackFn } }
|
||||
private static monitors = {}; // { settingName => { roomId => callbackRef } }
|
||||
|
||||
// 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
|
||||
|
@ -132,7 +140,7 @@ export default class SettingsStore {
|
|||
* if the change in value is worthwhile enough to react upon.
|
||||
* @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 originalSettingName = settingName;
|
||||
if (!setting) throw new Error(`${settingName} is not a setting`);
|
||||
|
@ -141,14 +149,14 @@ export default class SettingsStore {
|
|||
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 newValue = SettingsStore.getValue(originalSettingName);
|
||||
callbackFn(originalSettingName, changedInRoomId, atLevel, newValAtLevel, newValue);
|
||||
};
|
||||
|
||||
SettingsStore._watchers[watcherId] = localizedCallback;
|
||||
SettingsStore.watchers[watcherId] = localizedCallback;
|
||||
defaultWatchManager.watchSetting(settingName, roomId, localizedCallback);
|
||||
|
||||
return watcherId;
|
||||
|
@ -160,14 +168,14 @@ export default class SettingsStore {
|
|||
* @param {string} watcherReference The watcher reference (received from #watchSetting)
|
||||
* to cancel.
|
||||
*/
|
||||
static unwatchSetting(watcherReference) {
|
||||
if (!SettingsStore._watchers[watcherReference]) {
|
||||
public static unwatchSetting(watcherReference: string) {
|
||||
if (!SettingsStore.watchers[watcherReference]) {
|
||||
console.warn(`Ending non-existent watcher ID ${watcherReference}`);
|
||||
return;
|
||||
}
|
||||
|
||||
defaultWatchManager.unwatchSetting(SettingsStore._watchers[watcherReference]);
|
||||
delete SettingsStore._watchers[watcherReference];
|
||||
defaultWatchManager.unwatchSetting(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} 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.
|
||||
|
||||
if (!this._monitors[settingName]) this._monitors[settingName] = {};
|
||||
if (!this.monitors[settingName]) this.monitors[settingName] = {};
|
||||
|
||||
const registerWatcher = () => {
|
||||
this._monitors[settingName][roomId] = SettingsStore.watchSetting(
|
||||
this.monitors[settingName][roomId] = SettingsStore.watchSetting(
|
||||
settingName, roomId, (settingName, inRoomId, level, newValueAtLevel, newValue) => {
|
||||
dis.dispatch({
|
||||
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) {
|
||||
registerWatcher();
|
||||
} else {
|
||||
if (roomId === null) {
|
||||
// Unregister all existing watchers and register the new one
|
||||
for (const roomId of Object.keys(this._monitors[settingName])) {
|
||||
SettingsStore.unwatchSetting(this._monitors[settingName][roomId]);
|
||||
for (const roomId of Object.keys(this.monitors[settingName])) {
|
||||
SettingsStore.unwatchSetting(this.monitors[settingName][roomId]);
|
||||
}
|
||||
this._monitors[settingName] = {};
|
||||
this.monitors[settingName] = {};
|
||||
registerWatcher();
|
||||
} // 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
|
||||
* @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'.
|
||||
* @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;
|
||||
|
||||
let displayName = SETTINGS[settingName].displayName;
|
||||
|
@ -229,20 +237,20 @@ export default class SettingsStore {
|
|||
else displayName = displayName["default"];
|
||||
}
|
||||
|
||||
return _t(displayName);
|
||||
return _t(displayName as string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all available labs 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 enableLabs = SdkConfig.get()["enableLabs"];
|
||||
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.
|
||||
* @return {boolean} True if the setting is a feature.
|
||||
*/
|
||||
static isFeature(settingName) {
|
||||
public static isFeature(settingName: string) {
|
||||
if (!SETTINGS[settingName]) return false;
|
||||
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.
|
||||
* @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)) {
|
||||
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.
|
||||
* @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
|
||||
if (!SETTINGS[settingName]) {
|
||||
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");
|
||||
}
|
||||
|
||||
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.
|
||||
* @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
|
||||
if (!SETTINGS[settingName]) {
|
||||
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.
|
||||
* @param {"device"|"room-device"|"room-account"|"account"|"room"|"config"|"default"} level The
|
||||
* @param {SettingLevel|"config"|"default"} level The
|
||||
* level to look at.
|
||||
* @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.
|
||||
|
@ -319,7 +327,13 @@ export default class SettingsStore {
|
|||
* @param {boolean} excludeDefault True to disable using the default value.
|
||||
* @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
|
||||
const setting = SETTINGS[settingName];
|
||||
if (!setting) {
|
||||
|
@ -327,19 +341,19 @@ export default class SettingsStore {
|
|||
}
|
||||
|
||||
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);
|
||||
if (minIndex === -1) throw new Error("Level " + level + " is not prioritized");
|
||||
|
||||
if (SettingsStore.isFeature(settingName)) {
|
||||
const configValue = SettingsStore._getFeatureState(settingName);
|
||||
const configValue = SettingsStore.getFeatureState(settingName);
|
||||
if (configValue === "enable") return true;
|
||||
if (configValue === "disable") return false;
|
||||
// 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
|
||||
// handlers though, otherwise we'll fail to read the value.
|
||||
|
@ -351,10 +365,10 @@ export default class SettingsStore {
|
|||
if (explicit) {
|
||||
const handler = handlers[level];
|
||||
if (!handler) {
|
||||
return SettingsStore._getFinalValue(setting, level, roomId, null, null);
|
||||
return SettingsStore.getFinalValue(setting, level, roomId, null, null);
|
||||
}
|
||||
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++) {
|
||||
|
@ -364,10 +378,10 @@ export default class SettingsStore {
|
|||
|
||||
const value = handler.getValue(settingName, roomId);
|
||||
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.
|
||||
* @return {*} The default value
|
||||
*/
|
||||
static getDefaultValue(settingName) {
|
||||
public static getDefaultValue(settingName: string): any {
|
||||
// Verify that the setting is actually a setting
|
||||
if (!SETTINGS[settingName]) {
|
||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||
|
@ -385,7 +399,13 @@ export default class SettingsStore {
|
|||
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;
|
||||
|
||||
if (setting.controller) {
|
||||
|
@ -404,20 +424,21 @@ export default class SettingsStore {
|
|||
* to indicate that the level should no longer have an override.
|
||||
* @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 {"device"|"room-device"|"room-account"|"account"|"room"} level The level
|
||||
* @param {SettingLevel} level The level
|
||||
* to change the value at.
|
||||
* @param {*} value The new value of the setting, may be null.
|
||||
* @return {Promise} Resolves when the setting has been changed.
|
||||
*/
|
||||
|
||||
/* 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
|
||||
const setting = SETTINGS[settingName];
|
||||
if (!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) {
|
||||
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.
|
||||
* @param {string} settingName The name of the setting to check.
|
||||
* @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.
|
||||
* @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
|
||||
if (!SETTINGS[settingName]) {
|
||||
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;
|
||||
return handler.canSetValue(settingName, roomId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @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;
|
||||
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} roomId Optional room ID to test the setting in.
|
||||
*/
|
||||
static debugSetting(realSettingName, roomId) {
|
||||
public static debugSetting(realSettingName: string, roomId: string) {
|
||||
console.log(`--- DEBUG ${realSettingName}`);
|
||||
|
||||
// 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`);
|
||||
}
|
||||
|
||||
static _getHandler(settingName, level) {
|
||||
const handlers = SettingsStore._getHandlers(settingName);
|
||||
private static getHandler(settingName: string, level: SettingLevel): SettingsHandler {
|
||||
const handlers = SettingsStore.getHandlers(settingName);
|
||||
if (!handlers[level]) return null;
|
||||
return handlers[level];
|
||||
}
|
||||
|
||||
static _getHandlers(settingName) {
|
||||
private static getHandlers(settingName: string): IHandlerMap {
|
||||
if (!SETTINGS[settingName]) return {};
|
||||
|
||||
const handlers = {};
|
||||
|
@ -591,7 +612,7 @@ export default class SettingsStore {
|
|||
return handlers;
|
||||
}
|
||||
|
||||
static _getFeatureState(settingName) {
|
||||
private static getFeatureState(settingName: string): LabsFeatureState {
|
||||
const featuresConfig = SdkConfig.get()['features'];
|
||||
const enableLabs = SdkConfig.get()['enableLabs']; // we'll honour the old flag
|
||||
|
||||
|
@ -611,4 +632,4 @@ export default class SettingsStore {
|
|||
}
|
||||
|
||||
// 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.
|
||||
*/
|
||||
|
||||
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)
|
||||
* basis without duplicating code. Handlers are expected to push updates through this
|
||||
* class, which are then proxied outwards to any applicable watchers.
|
||||
*/
|
||||
export class WatchManager {
|
||||
_watchers = {}; // { settingName: { roomId: callbackFns[] } }
|
||||
private watchers: {[settingName: string]: RoomWatcherMap} = {};
|
||||
|
||||
// Proxy for handlers to delegate changes to this manager
|
||||
watchSetting(settingName, roomId, cb) {
|
||||
if (!this._watchers[settingName]) this._watchers[settingName] = {};
|
||||
if (!this._watchers[settingName][roomId]) this._watchers[settingName][roomId] = [];
|
||||
this._watchers[settingName][roomId].push(cb);
|
||||
public watchSetting(settingName: string, roomId: string | null, cb: CallbackFn) {
|
||||
if (!this.watchers[settingName]) this.watchers[settingName] = {};
|
||||
if (!this.watchers[settingName][roomId]) this.watchers[settingName][roomId] = [];
|
||||
this.watchers[settingName][roomId].push(cb);
|
||||
}
|
||||
|
||||
// Proxy for handlers to delegate changes to this manager
|
||||
unwatchSetting(cb) {
|
||||
for (const settingName of Object.keys(this._watchers)) {
|
||||
for (const roomId of Object.keys(this._watchers[settingName])) {
|
||||
public unwatchSetting(cb: CallbackFn) {
|
||||
for (const settingName of Object.keys(this.watchers)) {
|
||||
for (const roomId of Object.keys(this.watchers[settingName])) {
|
||||
let idx;
|
||||
while ((idx = this._watchers[settingName][roomId].indexOf(cb)) !== -1) {
|
||||
this._watchers[settingName][roomId].splice(idx, 1);
|
||||
while ((idx = this.watchers[settingName][roomId].indexOf(cb)) !== -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
|
||||
// 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.
|
||||
|
||||
if (!this._watchers[settingName]) return;
|
||||
if (!this.watchers[settingName]) return;
|
||||
|
||||
const roomWatchers = this._watchers[settingName];
|
||||
const roomWatchers = this.watchers[settingName];
|
||||
const callbacks = [];
|
||||
|
||||
if (inRoomId !== null && roomWatchers[inRoomId]) {
|
||||
|
@ -59,8 +70,8 @@ export class WatchManager {
|
|||
// Fire updates to all the individual room watchers too, as they probably
|
||||
// care about the change higher up.
|
||||
callbacks.push(...Object.values(roomWatchers).reduce((r, a) => [...r, ...a], []));
|
||||
} else if (roomWatchers[null]) {
|
||||
callbacks.push(...roomWatchers[null]);
|
||||
} else if (roomWatchers[IRRELEVANT_ROOM]) {
|
||||
callbacks.push(...roomWatchers[IRRELEVANT_ROOM]);
|
||||
}
|
||||
|
||||
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");
|
||||
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 dis from "../../dispatcher/dispatcher";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
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
|
||||
// Settings page is open (such as RoomTiles) can reflect the change.
|
||||
dis.dispatch({
|
|
@ -18,13 +18,14 @@ import SettingController from "./SettingController";
|
|||
import dis from "../../dispatcher/dispatcher";
|
||||
import { UpdateFontSizePayload } from "../../dispatcher/payloads/UpdateFontSizePayload";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
export default class FontSizeController extends SettingController {
|
||||
constructor() {
|
||||
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.
|
||||
dis.dispatch<UpdateFontSizePayload>({
|
||||
action: Action.UpdateFontSize,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
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.
|
||||
|
@ -16,13 +17,14 @@ limitations under the License.
|
|||
|
||||
import SettingController from "./SettingController";
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
// XXX: This feels wrong.
|
||||
import {PushProcessor} from "matrix-js-sdk/src/pushprocessor";
|
||||
|
||||
// .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
|
||||
function isPushNotifyDisabled() {
|
||||
function isPushNotifyDisabled(): boolean {
|
||||
// Return the value of the master push rule as a default
|
||||
const processor = new PushProcessor(MatrixClientPeg.get());
|
||||
const masterRule = processor.getPushRuleById(".m.rule.master");
|
||||
|
@ -36,14 +38,20 @@ function isPushNotifyDisabled() {
|
|||
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
|
||||
if (Notifier.default) Notifier = Notifier.default; // correct for webpack require() weirdness
|
||||
return Notifier;
|
||||
}
|
||||
|
||||
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 (calculatedValue === null || calculatedAtLevel === "default") {
|
||||
|
@ -53,7 +61,7 @@ export class NotificationsEnabledController extends SettingController {
|
|||
return calculatedValue;
|
||||
}
|
||||
|
||||
onChange(level, roomId, newValue) {
|
||||
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||
if (getNotifier().supportsDesktopNotifications()) {
|
||||
getNotifier().setEnabled(newValue);
|
||||
}
|
||||
|
@ -61,7 +69,7 @@ export class NotificationsEnabledController 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 (calculatedValue === null) {
|
||||
|
@ -73,7 +81,7 @@ export class NotificationBodyEnabledController 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;
|
||||
|
||||
// Note: Audio notifications are *not* enabled by default.
|
|
@ -15,23 +15,20 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
export default class PushToMatrixClientController {
|
||||
constructor(setter, inverse) {
|
||||
this._setter = setter;
|
||||
this._inverse = inverse;
|
||||
export default class PushToMatrixClientController extends SettingController {
|
||||
constructor(private setter: Function, private inverse: boolean) {
|
||||
super();
|
||||
}
|
||||
|
||||
getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
|
||||
return null; // no override
|
||||
}
|
||||
|
||||
onChange(level, roomId, newValue) {
|
||||
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||
// XXX does this work? This surely isn't necessarily the effective value,
|
||||
// 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");
|
||||
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 PlatformPeg from "../../PlatformPeg";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
export default class ReloadOnChangeController extends SettingController {
|
||||
onChange(level, roomId, newValue) {
|
||||
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||
PlatformPeg.get().reload();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
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.
|
||||
|
@ -14,6 +15,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
/**
|
||||
* Represents a controller for individual settings to alter the reading behaviour
|
||||
* 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
|
||||
* 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
|
||||
* 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 {*} calculatedValue The value that the handlers think the setting should be,
|
||||
* 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.
|
||||
* @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
|
||||
}
|
||||
|
||||
|
@ -44,7 +52,7 @@ export default class SettingController {
|
|||
* @param {String} roomId The room ID, 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
|
||||
}
|
||||
}
|
|
@ -19,13 +19,14 @@ import SettingsStore from "../SettingsStore";
|
|||
import dis from "../../dispatcher/dispatcher";
|
||||
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
export default class SystemFontController extends SettingController {
|
||||
constructor() {
|
||||
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.
|
||||
dis.dispatch<UpdateSystemFontPayload>({
|
||||
action: Action.UpdateSystemFont,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -17,11 +17,17 @@ limitations under the License.
|
|||
|
||||
import SettingController from "./SettingController";
|
||||
import {DEFAULT_THEME, enumerateThemes} from "../../theme";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
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 (ThemeController.isLogin) return 'light';
|
|
@ -19,13 +19,14 @@ import SettingsStore from "../SettingsStore";
|
|||
import dis from "../../dispatcher/dispatcher";
|
||||
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
export default class UseSystemFontController extends SettingController {
|
||||
constructor() {
|
||||
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.
|
||||
dis.dispatch<UpdateSystemFontPayload>({
|
||||
action: Action.UpdateSystemFont,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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 MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
import {SettingLevel} from "../SettingsStore";
|
||||
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_EVENT_TYPE = "im.vector.setting.breadcrumbs";
|
||||
const BREADCRUMBS_EVENT_TYPES = [BREADCRUMBS_LEGACY_EVENT_TYPE, BREADCRUMBS_EVENT_TYPE];
|
||||
const RECENT_EMOJI_EVENT_TYPE = "io.element.recent_emoji";
|
||||
|
||||
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.
|
||||
*/
|
||||
export default class AccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||
constructor(watchManager) {
|
||||
constructor(private watchers: WatchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
this._onAccountData = this._onAccountData.bind(this);
|
||||
}
|
||||
|
||||
initMatrixClient(oldClient, newClient) {
|
||||
public initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||
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") {
|
||||
let val = event.getContent()['disable'];
|
||||
if (typeof(val) !== "boolean") {
|
||||
|
@ -56,30 +55,30 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
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") {
|
||||
// Figure out what changed and fire those updates
|
||||
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
||||
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
||||
for (const settingName of changedSettings) {
|
||||
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())) {
|
||||
this._notifyBreadcrumbsUpdate(event);
|
||||
this.notifyBreadcrumbsUpdate(event);
|
||||
} else if (event.getType() === INTEG_PROVISIONING_EVENT_TYPE) {
|
||||
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) {
|
||||
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
|
||||
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
|
||||
if (typeof(content['disable']) !== "boolean") return null;
|
||||
|
@ -88,9 +87,9 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
|
||||
// Special case for breadcrumbs
|
||||
if (settingName === "breadcrumb_rooms") {
|
||||
let content = this._getSettings(BREADCRUMBS_EVENT_TYPE);
|
||||
let content = this.getSettings(BREADCRUMBS_EVENT_TYPE);
|
||||
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
|
||||
if (content) content['recent_rooms'] = content['rooms'];
|
||||
|
@ -101,17 +100,17 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
|
||||
// Special case 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;
|
||||
}
|
||||
|
||||
// Special case integration manager provisioning
|
||||
if (settingName === "integrationProvisioning") {
|
||||
const content = this._getSettings(INTEG_PROVISIONING_EVENT_TYPE);
|
||||
const content = this.getSettings(INTEG_PROVISIONING_EVENT_TYPE);
|
||||
return content ? content['enabled'] : null;
|
||||
}
|
||||
|
||||
const settings = this._getSettings() || {};
|
||||
const settings = this.getSettings() || {};
|
||||
let preferredValue = settings[settingName];
|
||||
|
||||
if (preferredValue === null || preferredValue === undefined) {
|
||||
|
@ -124,10 +123,10 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
return preferredValue;
|
||||
}
|
||||
|
||||
setValue(settingName, roomId, newValue) {
|
||||
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||
// Special case URL previews
|
||||
if (settingName === "urlPreviewsEnabled") {
|
||||
const content = this._getSettings("org.matrix.preview_urls") || {};
|
||||
const content = this.getSettings("org.matrix.preview_urls") || {};
|
||||
content['disable'] = !newValue;
|
||||
return MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", content);
|
||||
}
|
||||
|
@ -135,9 +134,9 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
// Special case for breadcrumbs
|
||||
if (settingName === "breadcrumb_rooms") {
|
||||
// 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']) {
|
||||
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
|
||||
|
||||
|
@ -147,33 +146,33 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
|
||||
// Special case 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;
|
||||
return MatrixClientPeg.get().setAccountData(RECENT_EMOJI_EVENT_TYPE, content);
|
||||
}
|
||||
|
||||
// Special case integration manager provisioning
|
||||
if (settingName === "integrationProvisioning") {
|
||||
const content = this._getSettings(INTEG_PROVISIONING_EVENT_TYPE) || {};
|
||||
const content = this.getSettings(INTEG_PROVISIONING_EVENT_TYPE) || {};
|
||||
content['enabled'] = newValue;
|
||||
return MatrixClientPeg.get().setAccountData(INTEG_PROVISIONING_EVENT_TYPE, content);
|
||||
}
|
||||
|
||||
const content = this._getSettings() || {};
|
||||
const content = this.getSettings() || {};
|
||||
content[settingName] = newValue;
|
||||
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
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
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();
|
||||
if (!cli) return null;
|
||||
|
||||
|
@ -182,11 +181,11 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
return objectClone(event.getContent()); // clone to prevent mutation
|
||||
}
|
||||
|
||||
_notifyBreadcrumbsUpdate(event) {
|
||||
private notifyBreadcrumbsUpdate(event: MatrixEvent) {
|
||||
let val = [];
|
||||
if (event.getType() === BREADCRUMBS_LEGACY_EVENT_TYPE) {
|
||||
// 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'];
|
||||
else val = event.getContent()['rooms'];
|
||||
} else if (event.getType() === BREADCRUMBS_EVENT_TYPE) {
|
||||
|
@ -194,6 +193,6 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
|||
} else {
|
||||
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 2019 New Vector Ltd
|
||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -24,7 +24,7 @@ import {isNullOrUndefined} from "matrix-js-sdk/src/utils";
|
|||
* roomId parameter.
|
||||
*/
|
||||
export default class ConfigSettingsHandler extends SettingsHandler {
|
||||
getValue(settingName, roomId) {
|
||||
public getValue(settingName: string, roomId: string): any {
|
||||
const config = SdkConfig.get() || {};
|
||||
|
||||
// Special case themes
|
||||
|
@ -37,15 +37,15 @@ export default class ConfigSettingsHandler extends SettingsHandler {
|
|||
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");
|
||||
}
|
||||
|
||||
canSetValue(settingName, roomId) {
|
||||
public canSetValue(settingName: string, roomId: string): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
return true; // SdkConfig is always there
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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} 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();
|
||||
this._defaults = defaults;
|
||||
this._invertedDefaults = invertedDefaults;
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
let value = this._defaults[settingName];
|
||||
public getValue(settingName: string, roomId: string): any {
|
||||
let value = this.defaults[settingName];
|
||||
if (value === undefined) {
|
||||
value = this._invertedDefaults[settingName];
|
||||
value = this.invertedDefaults[settingName];
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
canSetValue(settingName, roomId) {
|
||||
public canSetValue(settingName: string, roomId: string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -18,7 +18,8 @@ limitations under the License.
|
|||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
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.
|
||||
|
@ -29,17 +30,15 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
/**
|
||||
* Creates a new device settings handler
|
||||
* @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();
|
||||
this._featureNames = featureNames;
|
||||
this._watchers = watchManager;
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
if (this._featureNames.includes(settingName)) {
|
||||
return this._readFeature(settingName);
|
||||
public getValue(settingName: string, roomId: string): any {
|
||||
if (this.featureNames.includes(settingName)) {
|
||||
return this.readFeature(settingName);
|
||||
}
|
||||
|
||||
// Special case notifications
|
||||
|
@ -68,28 +67,28 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
return val['value'];
|
||||
}
|
||||
|
||||
const settings = this._getSettings() || {};
|
||||
const settings = this.getSettings() || {};
|
||||
return settings[settingName];
|
||||
}
|
||||
|
||||
setValue(settingName, roomId, newValue) {
|
||||
if (this._featureNames.includes(settingName)) {
|
||||
this._writeFeature(settingName, newValue);
|
||||
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||
if (this.featureNames.includes(settingName)) {
|
||||
this.writeFeature(settingName, newValue);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Special case notifications
|
||||
if (settingName === "notificationsEnabled") {
|
||||
localStorage.setItem("notifications_enabled", newValue);
|
||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||
return Promise.resolve();
|
||||
} else if (settingName === "notificationBodyEnabled") {
|
||||
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();
|
||||
} else if (settingName === "audioNotificationsEnabled") {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -103,35 +102,35 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
"lastRightPanelPhaseForGroup",
|
||||
].includes(settingName)) {
|
||||
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();
|
||||
}
|
||||
|
||||
const settings = this._getSettings() || {};
|
||||
const settings = this.getSettings() || {};
|
||||
settings[settingName] = newValue;
|
||||
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();
|
||||
}
|
||||
|
||||
canSetValue(settingName, roomId) {
|
||||
public canSetValue(settingName: string, roomId: string): boolean {
|
||||
return true; // It's their device, so they should be able to
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
return localStorage !== undefined && localStorage !== null;
|
||||
}
|
||||
|
||||
watchSetting(settingName, roomId, cb) {
|
||||
this._watchers.watchSetting(settingName, roomId, cb);
|
||||
public watchSetting(settingName: string, roomId: string, cb: CallbackFn) {
|
||||
this.watchers.watchSetting(settingName, roomId, cb);
|
||||
}
|
||||
|
||||
unwatchSetting(cb) {
|
||||
this._watchers.unwatchSetting(cb);
|
||||
public unwatchSetting(cb: CallbackFn) {
|
||||
this.watchers.unwatchSetting(cb);
|
||||
}
|
||||
|
||||
_getSettings() {
|
||||
private getSettings(): any { // TODO: [TS] Type return
|
||||
const value = localStorage.getItem("mx_local_settings");
|
||||
if (!value) return null;
|
||||
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
|
||||
// and to be backwards compatible.
|
||||
|
||||
_readFeature(featureName) {
|
||||
private readFeature(featureName: string): boolean | null {
|
||||
if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest()) {
|
||||
// Guests should not have any labs features enabled.
|
||||
return false;
|
||||
|
@ -153,8 +152,8 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
_writeFeature(featureName, enabled) {
|
||||
localStorage.setItem("mx_labs_feature_" + featureName, enabled);
|
||||
this._watchers.notifyUpdate(featureName, null, SettingLevel.DEVICE, enabled);
|
||||
private writeFeature(featureName: string, enabled: boolean | null) {
|
||||
localStorage.setItem("mx_labs_feature_" + featureName, `${enabled}`);
|
||||
this.watchers.notifyUpdate(featureName, null, SettingLevel.DEVICE, enabled);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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.
|
||||
*/
|
||||
export default class LocalEchoWrapper extends SettingsHandler {
|
||||
private cache: {
|
||||
[settingName: string]: {
|
||||
[roomId: string]: any;
|
||||
};
|
||||
} = {};
|
||||
|
||||
/**
|
||||
* Creates a new local echo wrapper
|
||||
* @param {SettingsHandler} handler The handler to wrap
|
||||
*/
|
||||
constructor(handler) {
|
||||
constructor(private handler: SettingsHandler) {
|
||||
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 bySetting = this._cache[settingName];
|
||||
const bySetting = this.cache[settingName];
|
||||
if (bySetting && bySetting.hasOwnProperty(cacheRoomId)) {
|
||||
return bySetting[cacheRoomId];
|
||||
}
|
||||
|
||||
return this._handler.getValue(settingName, roomId);
|
||||
return this.handler.getValue(settingName, roomId);
|
||||
}
|
||||
|
||||
setValue(settingName, roomId, newValue) {
|
||||
if (!this._cache[settingName]) this._cache[settingName] = {};
|
||||
const bySetting = this._cache[settingName];
|
||||
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||
if (!this.cache[settingName]) this.cache[settingName] = {};
|
||||
const bySetting = this.cache[settingName];
|
||||
|
||||
const cacheRoomId = roomId ? roomId : "UNDEFINED"; // avoid weird keys
|
||||
bySetting[cacheRoomId] = newValue;
|
||||
|
||||
const handlerPromise = this._handler.setValue(settingName, roomId, newValue);
|
||||
const handlerPromise = this.handler.setValue(settingName, roomId, newValue);
|
||||
return Promise.resolve(handlerPromise).finally(() => {
|
||||
delete bySetting[cacheRoomId];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
canSetValue(settingName, roomId) {
|
||||
return this._handler.canSetValue(settingName, roomId);
|
||||
public canSetValue(settingName: string, roomId: string): boolean {
|
||||
return this.handler.canSetValue(settingName, roomId);
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
return this._handler.isSupported();
|
||||
public isSupported(): boolean {
|
||||
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");
|
||||
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 { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
|
||||
// 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.
|
||||
|
@ -23,30 +24,30 @@ import SettingsHandler from "./SettingsHandler";
|
|||
* Represents the base class for settings handlers which need access to a MatrixClient.
|
||||
* This class performs no logic and should be overridden.
|
||||
*/
|
||||
export default class MatrixClientBackedSettingsHandler extends SettingsHandler {
|
||||
static _matrixClient;
|
||||
static _instances = [];
|
||||
export default abstract class MatrixClientBackedSettingsHandler extends SettingsHandler {
|
||||
private static _matrixClient: MatrixClient;
|
||||
private static instances: MatrixClientBackedSettingsHandler[] = [];
|
||||
|
||||
static set matrixClient(client) {
|
||||
public static set matrixClient(client: MatrixClient) {
|
||||
const oldClient = MatrixClientBackedSettingsHandler._matrixClient;
|
||||
MatrixClientBackedSettingsHandler._matrixClient = client;
|
||||
|
||||
for (const instance of MatrixClientBackedSettingsHandler._instances) {
|
||||
for (const instance of MatrixClientBackedSettingsHandler.instances) {
|
||||
instance.initMatrixClient(oldClient, client);
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
protected constructor() {
|
||||
super();
|
||||
|
||||
MatrixClientBackedSettingsHandler._instances.push(this);
|
||||
MatrixClientBackedSettingsHandler.instances.push(this);
|
||||
}
|
||||
|
||||
get client() {
|
||||
public get client(): MatrixClient {
|
||||
return MatrixClientBackedSettingsHandler._matrixClient;
|
||||
}
|
||||
|
||||
initMatrixClient() {
|
||||
protected initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||
console.warn("initMatrixClient not overridden");
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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.
|
||||
*/
|
||||
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
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";
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
export default class RoomAccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||
constructor(watchManager) {
|
||||
constructor(private watchers: WatchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
this._onAccountData = this._onAccountData.bind(this);
|
||||
}
|
||||
|
||||
initMatrixClient(oldClient, newClient) {
|
||||
protected initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||
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;
|
||||
|
||||
if (event.getType() === "org.matrix.room.preview_urls") {
|
||||
|
@ -52,29 +53,29 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
|
|||
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") {
|
||||
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") {
|
||||
// Figure out what changed and fire those updates
|
||||
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
||||
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
||||
for (const settingName of changedSettings) {
|
||||
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) {
|
||||
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
|
||||
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
|
||||
if (typeof(content['disable']) !== "boolean") return null;
|
||||
if (typeof (content['disable']) !== "boolean") return null;
|
||||
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
|
||||
// to get the right value.
|
||||
// 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
|
||||
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];
|
||||
}
|
||||
|
||||
setValue(settingName, roomId, newValue) {
|
||||
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||
// Special case URL previews
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
const content = this._getSettings(roomId) || {};
|
||||
const content = this.getSettings(roomId) || {};
|
||||
content[settingName] = newValue;
|
||||
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);
|
||||
|
||||
// If they have the room, they can set their own account data
|
||||
return room !== undefined && room !== null;
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
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);
|
||||
if (!room) return null;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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 {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
|
||||
* room.
|
||||
*/
|
||||
export default class RoomDeviceSettingsHandler extends SettingsHandler {
|
||||
constructor(watchManager) {
|
||||
constructor(private watchers: WatchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
public getValue(settingName: string, roomId: string): any {
|
||||
// Special case blacklist setting to use legacy values
|
||||
if (settingName === "blacklistUnverifiedDevices") {
|
||||
const value = this._read("mx_local_settings");
|
||||
const value = this.read("mx_local_settings");
|
||||
if (value && value['blacklistUnverifiedDevicesPerRoom']) {
|
||||
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;
|
||||
return null;
|
||||
}
|
||||
|
||||
setValue(settingName, roomId, newValue) {
|
||||
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||
// Special case blacklist setting for legacy structure
|
||||
if (settingName === "blacklistUnverifiedDevices") {
|
||||
let value = this._read("mx_local_settings");
|
||||
let value = this.read("mx_local_settings");
|
||||
if (!value) value = {};
|
||||
if (!value["blacklistUnverifiedDevicesPerRoom"]) value["blacklistUnverifiedDevicesPerRoom"] = {};
|
||||
value["blacklistUnverifiedDevicesPerRoom"][roomId] = newValue;
|
||||
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();
|
||||
}
|
||||
|
||||
if (newValue === null) {
|
||||
localStorage.removeItem(this._getKey(settingName, roomId));
|
||||
localStorage.removeItem(this.getKey(settingName, roomId));
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
|
||||
canSetValue(settingName, roomId) {
|
||||
public canSetValue(settingName: string, roomId: string): boolean {
|
||||
return true; // It's their device, so they should be able to
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
return localStorage !== undefined && localStorage !== null;
|
||||
}
|
||||
|
||||
_read(key) {
|
||||
private read(key: string): any {
|
||||
const rawValue = localStorage.getItem(key);
|
||||
if (!rawValue) return null;
|
||||
return JSON.parse(rawValue);
|
||||
}
|
||||
|
||||
_getKey(settingName, roomId) {
|
||||
private getKey(settingName: string, roomId: string): string {
|
||||
return "mx_setting_" + settingName + "_" + roomId;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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.
|
||||
*/
|
||||
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||
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.
|
||||
*/
|
||||
export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||
constructor(watchManager) {
|
||||
constructor(private watchers: WatchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
this._onEvent = this._onEvent.bind(this);
|
||||
}
|
||||
|
||||
initMatrixClient(oldClient, newClient) {
|
||||
protected initMatrixClient(oldClient: MatrixClient, newClient: MatrixClient) {
|
||||
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 room = this.client.getRoom(roomId);
|
||||
|
||||
|
@ -60,45 +61,45 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
|
|||
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") {
|
||||
// Figure out what changed and fire those updates
|
||||
const prevContent = prevEvent ? prevEvent.getContent() : {};
|
||||
const changedSettings = objectKeyChanges(prevContent, event.getContent());
|
||||
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
|
||||
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
|
||||
if (typeof(content['disable']) !== "boolean") return null;
|
||||
if (typeof (content['disable']) !== "boolean") return null;
|
||||
return !content['disable'];
|
||||
}
|
||||
|
||||
const settings = this._getSettings(roomId) || {};
|
||||
const settings = this.getSettings(roomId) || {};
|
||||
return settings[settingName];
|
||||
}
|
||||
|
||||
setValue(settingName, roomId, newValue) {
|
||||
public setValue(settingName: string, roomId: string, newValue: any): Promise<void> {
|
||||
// Special case URL previews
|
||||
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;
|
||||
return MatrixClientPeg.get().sendStateEvent(roomId, "org.matrix.room.preview_urls", content);
|
||||
}
|
||||
|
||||
const content = this._getSettings(roomId) || {};
|
||||
const content = this.getSettings(roomId) || {};
|
||||
content[settingName] = newValue;
|
||||
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 room = cli.getRoom(roomId);
|
||||
|
||||
|
@ -109,12 +110,12 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
|
|||
return room.currentState.maySendStateEvent(eventType, cli.getUserId());
|
||||
}
|
||||
|
||||
isSupported() {
|
||||
public isSupported(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
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);
|
||||
if (!room) return null;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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");
|
||||
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
|
||||
* 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.
|
||||
* 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.
|
||||
* @returns {*} The setting value, or null if not found.
|
||||
*/
|
||||
getValue(settingName, roomId) {
|
||||
console.error("Invalid operation: getValue was not overridden");
|
||||
return null;
|
||||
}
|
||||
public abstract getValue(settingName: string, roomId: string): any;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @returns {Promise} Resolves when the setting has been saved.
|
||||
*/
|
||||
setValue(settingName, roomId, newValue) {
|
||||
console.error("Invalid operation: setValue was not overridden");
|
||||
return Promise.reject();
|
||||
}
|
||||
public abstract setValue(settingName: string, roomId: string, newValue: any): Promise<void>;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @returns {boolean} True if the setting can be set by the user, false otherwise.
|
||||
*/
|
||||
canSetValue(settingName, roomId) {
|
||||
return false;
|
||||
}
|
||||
public abstract canSetValue(settingName: string, roomId: string): boolean;
|
||||
|
||||
/**
|
||||
* Determines if this level is supported on this device.
|
||||
* @returns {boolean} True if this level is supported on the current device.
|
||||
*/
|
||||
isSupported() {
|
||||
return false;
|
||||
}
|
||||
public abstract isSupported(): boolean;
|
||||
}
|
|
@ -15,10 +15,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import SettingsStore, {SettingLevel} from '../SettingsStore';
|
||||
import SettingsStore from '../SettingsStore';
|
||||
import IWatcher from "./Watcher";
|
||||
import { toPx } from '../../utils/units';
|
||||
import { Action } from '../../dispatcher/actions';
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
export class FontWatcher implements IWatcher {
|
||||
public static readonly MIN_SIZE = 8;
|
||||
|
|
|
@ -15,17 +15,15 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsStore, { SettingLevel } from '../SettingsStore';
|
||||
import SettingsStore from '../SettingsStore';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import { Action } from '../../dispatcher/actions';
|
||||
import ThemeController from "../controllers/ThemeController";
|
||||
import { setTheme } from "../../theme";
|
||||
import { ActionPayload } from '../../dispatcher/payloads';
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
|
||||
export default class ThemeWatcher {
|
||||
// XXX: I think this is unused.
|
||||
static _instance = null;
|
||||
|
||||
private themeWatchRef: string;
|
||||
private systemThemeWatchRef: string;
|
||||
private dispatcherRef: string;
|
||||
|
|
|
@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
|
|||
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 { ActionPayload } from "../dispatcher/payloads";
|
||||
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||
import { arrayHasDiff } from "../utils/arrays";
|
||||
import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
|
||||
import { SettingLevel } from "../settings/SettingLevel";
|
||||
|
||||
const MAX_ROOMS = 20; // arbitrary
|
||||
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 {pendingVerificationRequestForUser} from '../verification';
|
||||
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 {ActionPayload} from "../dispatcher/payloads";
|
||||
import {Action} from '../dispatcher/actions';
|
||||
import { SettingLevel } from "../settings/SettingLevel";
|
||||
|
||||
interface RightPanelStoreState {
|
||||
// Whether or not to show the right panel at all. We split out rooms and groups
|
||||
|
|
Loading…
Reference in a new issue