Merge branch 'develop' into matthew/low_bandwidth
This commit is contained in:
commit
d81804e0fe
589 changed files with 37701 additions and 15344 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2018 New Vector Ltd
|
||||
Copyright 2018, 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -21,8 +21,8 @@ import {
|
|||
NotificationBodyEnabledController,
|
||||
NotificationsEnabledController,
|
||||
} from "./controllers/NotificationControllers";
|
||||
import LazyLoadingController from "./controllers/LazyLoadingController";
|
||||
import CustomStatusController from "./controllers/CustomStatusController";
|
||||
import ThemeController from './controllers/ThemeController';
|
||||
|
||||
// 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'];
|
||||
|
@ -93,12 +93,6 @@ export const SETTINGS = {
|
|||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"feature_tabbed_settings": {
|
||||
isFeature: true,
|
||||
displayName: _td("Tabbed settings"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"feature_custom_status": {
|
||||
isFeature: true,
|
||||
displayName: _td("Custom user status messages"),
|
||||
|
@ -106,16 +100,15 @@ export const SETTINGS = {
|
|||
default: false,
|
||||
controller: new CustomStatusController(),
|
||||
},
|
||||
"feature_lazyloading": {
|
||||
"feature_room_breadcrumbs": {
|
||||
isFeature: true,
|
||||
displayName: _td("Increase performance by only loading room members on first view"),
|
||||
displayName: _td("Show recent room avatars above the room list"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
controller: new LazyLoadingController(),
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
"feature_keybackup": {
|
||||
"feature_custom_tags": {
|
||||
isFeature: true,
|
||||
displayName: _td("Backup of encryption keys to server"),
|
||||
displayName: _td("Group & filter rooms by custom tags (refresh to apply changes)"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
|
@ -125,9 +118,15 @@ export const SETTINGS = {
|
|||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"feature_sas": {
|
||||
"feature_message_editing": {
|
||||
isFeature: true,
|
||||
displayName: _td("Two-way device verification using short text"),
|
||||
displayName: _td("Edit messages after they have been sent (refresh to apply changes)"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
"feature_reactions": {
|
||||
isFeature: true,
|
||||
displayName: _td("React to messages with emoji (refresh to apply changes)"),
|
||||
supportedLevels: LEVELS_FEATURE,
|
||||
default: false,
|
||||
},
|
||||
|
@ -168,7 +167,7 @@ export const SETTINGS = {
|
|||
},
|
||||
"showReadReceipts": {
|
||||
supportedLevels: LEVELS_ROOM_SETTINGS,
|
||||
displayName: _td('Show read receipts'),
|
||||
displayName: _td('Show read receipts sent by other users'),
|
||||
default: true,
|
||||
invertedSettingName: 'hideReadReceipts',
|
||||
},
|
||||
|
@ -245,12 +244,13 @@ export const SETTINGS = {
|
|||
invertedSettingName: 'TagPanel.disableTagPanel',
|
||||
},
|
||||
"theme": {
|
||||
supportedLevels: ['config'],
|
||||
default: "dharma",
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
default: "light",
|
||||
controller: new ThemeController(),
|
||||
},
|
||||
"webRtcForcePeerToPeer": {
|
||||
"webRtcAllowPeerToPeer": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
displayName: _td('Disable Peer-to-Peer for 1:1 calls'),
|
||||
displayName: _td('Allow Peer-to-Peer for 1:1 calls'),
|
||||
default: true,
|
||||
invertedSettingName: 'webRtcForceTURN',
|
||||
},
|
||||
|
@ -270,6 +270,10 @@ export const SETTINGS = {
|
|||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
default: "en",
|
||||
},
|
||||
"breadcrumb_rooms": {
|
||||
supportedLevels: ['account'],
|
||||
default: [],
|
||||
},
|
||||
"analyticsOptIn": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
displayName: _td('Send analytics data'),
|
||||
|
@ -333,16 +337,6 @@ export const SETTINGS = {
|
|||
default: true,
|
||||
controller: new AudioNotificationsEnabledController(),
|
||||
},
|
||||
"pinMentionedRooms": {
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
displayName: _td("Pin rooms I'm mentioned in to the top of the room list"),
|
||||
default: false,
|
||||
},
|
||||
"pinUnreadRooms": {
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
displayName: _td("Pin unread rooms to the top of the room list"),
|
||||
default: false,
|
||||
},
|
||||
"enableWidgetScreenshots": {
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
displayName: _td('Enable widget screenshots on supported widgets'),
|
||||
|
@ -362,6 +356,23 @@ export const SETTINGS = {
|
|||
displayName: _td('Show developer tools'),
|
||||
default: false,
|
||||
},
|
||||
"widgetOpenIDPermissions": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: {
|
||||
allow: [],
|
||||
deny: [],
|
||||
},
|
||||
},
|
||||
"RoomList.orderByImportance": {
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
displayName: _td('Order rooms in the room list by most important first instead of most recent'),
|
||||
default: true,
|
||||
},
|
||||
"showHiddenEventsInTimeline": {
|
||||
displayName: _td("Show hidden events in timeline"),
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: false,
|
||||
},
|
||||
"lowBandwidth": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
displayName: _td('Low Bandwidth Mode'),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -23,8 +24,10 @@ import RoomSettingsHandler from "./handlers/RoomSettingsHandler";
|
|||
import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler";
|
||||
import {_t} from '../languageHandler';
|
||||
import SdkConfig from "../SdkConfig";
|
||||
import dis from '../dispatcher';
|
||||
import {SETTINGS} from "./Settings";
|
||||
import LocalEchoWrapper from "./handlers/LocalEchoWrapper";
|
||||
import {WatchManager} from "./WatchManager";
|
||||
|
||||
/**
|
||||
* Represents the various setting levels supported by the SettingsStore.
|
||||
|
@ -41,6 +44,8 @@ export const SettingLevel = {
|
|||
DEFAULT: "default",
|
||||
};
|
||||
|
||||
const defaultWatchManager = new WatchManager();
|
||||
|
||||
// Convert the settings to easier to manage objects for the handlers
|
||||
const defaultSettings = {};
|
||||
const invertedDefaultSettings = {};
|
||||
|
@ -56,11 +61,11 @@ for (const key of Object.keys(SETTINGS)) {
|
|||
}
|
||||
|
||||
const LEVEL_HANDLERS = {
|
||||
"device": new DeviceSettingsHandler(featureNames),
|
||||
"room-device": new RoomDeviceSettingsHandler(),
|
||||
"room-account": new RoomAccountSettingsHandler(),
|
||||
"account": new AccountSettingsHandler(),
|
||||
"room": new RoomSettingsHandler(),
|
||||
"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),
|
||||
};
|
||||
|
@ -98,6 +103,109 @@ const LEVEL_ORDER = [
|
|||
* be enabled).
|
||||
*/
|
||||
export default class SettingsStore {
|
||||
// We support watching settings for changes, and do this by tracking which callbacks have
|
||||
// been given to us. We end up returning the callbackRef to the caller so they can unsubscribe
|
||||
// at a later point.
|
||||
//
|
||||
// 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 } }
|
||||
|
||||
/**
|
||||
* Watches for changes in a particular setting. This is done without any local echo
|
||||
* wrapping and fires whenever a change is detected in a setting's value, at any level.
|
||||
* Watching is intended to be used in scenarios where the app needs to react to changes
|
||||
* made by other devices. It is otherwise expected that callers will be able to use the
|
||||
* Controller system or track their own changes to settings. Callers should retain the
|
||||
* returned reference to later unsubscribe from updates.
|
||||
* @param {string} settingName The setting name to watch
|
||||
* @param {String} roomId The room ID to watch for changes in. May be null for 'all'.
|
||||
* @param {function} callbackFn A function to be called when a setting change is
|
||||
* detected. Five arguments can be expected: the setting name, the room ID (may be null),
|
||||
* the level the change happened at, the new value at the given level, and finally the new
|
||||
* value for the setting regardless of level. The callback is responsible for determining
|
||||
* 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) {
|
||||
const setting = SETTINGS[settingName];
|
||||
const originalSettingName = settingName;
|
||||
if (!setting) throw new Error(`${settingName} is not a setting`);
|
||||
|
||||
if (setting.invertedSettingName) {
|
||||
settingName = setting.invertedSettingName;
|
||||
}
|
||||
|
||||
const watcherId = `${new Date().getTime()}_${settingName}_${roomId}`;
|
||||
|
||||
const localizedCallback = (changedInRoomId, atLevel, newValAtLevel) => {
|
||||
const newValue = SettingsStore.getValue(originalSettingName);
|
||||
callbackFn(originalSettingName, changedInRoomId, atLevel, newValAtLevel, newValue);
|
||||
};
|
||||
|
||||
console.log(`Starting watcher for ${settingName}@${roomId || '<null room>'}`);
|
||||
SettingsStore._watchers[watcherId] = localizedCallback;
|
||||
defaultWatchManager.watchSetting(settingName, roomId, localizedCallback);
|
||||
|
||||
return watcherId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the SettingsStore from watching a setting. This is a no-op if the watcher
|
||||
* provided is not found.
|
||||
* @param {string} watcherReference The watcher reference (received from #watchSetting)
|
||||
* to cancel.
|
||||
*/
|
||||
static unwatchSetting(watcherReference) {
|
||||
if (!SettingsStore._watchers[watcherReference]) return;
|
||||
|
||||
defaultWatchManager.unwatchSetting(SettingsStore._watchers[watcherReference]);
|
||||
delete SettingsStore._watchers[watcherReference];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a monitor for a setting. This behaves similar to #watchSetting except instead
|
||||
* of making a call to a callback, it forwards all changes to the dispatcher. Callers can
|
||||
* expect to listen for the 'setting_updated' action with an object containing settingName,
|
||||
* roomId, level, newValueAtLevel, and newValue.
|
||||
* @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) {
|
||||
if (!this._monitors[settingName]) this._monitors[settingName] = {};
|
||||
|
||||
const registerWatcher = () => {
|
||||
this._monitors[settingName][roomId] = SettingsStore.watchSetting(
|
||||
settingName, roomId, (settingName, inRoomId, level, newValueAtLevel, newValue) => {
|
||||
dis.dispatch({
|
||||
action: 'setting_updated',
|
||||
settingName,
|
||||
roomId: inRoomId,
|
||||
level,
|
||||
newValueAtLevel,
|
||||
newValue,
|
||||
});
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
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]);
|
||||
}
|
||||
this._monitors[settingName] = {};
|
||||
registerWatcher();
|
||||
} // else a watcher is already registered for the room, so don't bother registering it again
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the translated display name for a given setting
|
||||
* @param {string} settingName The setting to look up.
|
||||
|
|
61
src/settings/WatchManager.js
Normal file
61
src/settings/WatchManager.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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[] } }
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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])) {
|
||||
let idx;
|
||||
while ((idx = this._watchers[settingName][roomId].indexOf(cb)) !== -1) {
|
||||
this._watchers[settingName][roomId].splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notifyUpdate(settingName, inRoomId, atLevel, newValueAtLevel) {
|
||||
// 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;
|
||||
|
||||
const roomWatchers = this._watchers[settingName];
|
||||
const callbacks = [];
|
||||
|
||||
if (inRoomId !== null && roomWatchers[inRoomId]) callbacks.push(...roomWatchers[inRoomId]);
|
||||
if (roomWatchers[null]) callbacks.push(...roomWatchers[null]);
|
||||
|
||||
for (const callback of callbacks) {
|
||||
callback(inRoomId, atLevel, newValueAtLevel);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2018 New Vector
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -15,15 +15,19 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import SettingController from "./SettingController";
|
||||
import MatrixClientPeg from "../../MatrixClientPeg";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
|
||||
export default class LazyLoadingController extends SettingController {
|
||||
async onChange(level, roomId, newValue) {
|
||||
if (!PlatformPeg.get()) return;
|
||||
const SUPPORTED_THEMES = [
|
||||
"light",
|
||||
"dark",
|
||||
];
|
||||
|
||||
MatrixClientPeg.get().stopClient();
|
||||
await MatrixClientPeg.get().store.deleteAllData();
|
||||
PlatformPeg.get().reload();
|
||||
export default class ThemeController extends SettingController {
|
||||
getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) {
|
||||
// Override in case some no longer supported theme is stored here
|
||||
if (!SUPPORTED_THEMES.includes(calculatedValue)) {
|
||||
return "light";
|
||||
}
|
||||
|
||||
return null; // no override
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,14 +15,54 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
import {SettingLevel} from "../SettingsStore";
|
||||
|
||||
const BREADCRUMBS_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms";
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "account" level for the current user.
|
||||
* This handler does not make use of the roomId parameter.
|
||||
*/
|
||||
export default class AccountSettingHandler extends SettingsHandler {
|
||||
export default class AccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||
constructor(watchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
this._onAccountData = this._onAccountData.bind(this);
|
||||
}
|
||||
|
||||
initMatrixClient(oldClient, newClient) {
|
||||
if (oldClient) {
|
||||
oldClient.removeListener("accountData", this._onAccountData);
|
||||
}
|
||||
|
||||
newClient.on("accountData", this._onAccountData);
|
||||
}
|
||||
|
||||
_onAccountData(event) {
|
||||
if (event.getType() === "org.matrix.preview_urls") {
|
||||
let val = event.getContent()['disable'];
|
||||
if (typeof(val) !== "boolean") {
|
||||
val = null;
|
||||
} else {
|
||||
val = !val;
|
||||
}
|
||||
|
||||
this._watchers.notifyUpdate("urlPreviewsEnabled", null, SettingLevel.ACCOUNT, val);
|
||||
} else if (event.getType() === "im.vector.web.settings") {
|
||||
// We can't really discern what changed, so trigger updates for everything
|
||||
for (const settingName of Object.keys(event.getContent())) {
|
||||
const val = event.getContent()[settingName];
|
||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.ACCOUNT, val);
|
||||
}
|
||||
} else if (event.getType() === BREADCRUMBS_EVENT_TYPE) {
|
||||
const val = event.getContent()['rooms'] || [];
|
||||
this._watchers.notifyUpdate("breadcrumb_rooms", null, SettingLevel.ACCOUNT, val);
|
||||
}
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
// Special case URL previews
|
||||
if (settingName === "urlPreviewsEnabled") {
|
||||
|
@ -32,6 +73,12 @@ export default class AccountSettingHandler extends SettingsHandler {
|
|||
return !content['disable'];
|
||||
}
|
||||
|
||||
// Special case for breadcrumbs
|
||||
if (settingName === "breadcrumb_rooms") {
|
||||
const content = this._getSettings(BREADCRUMBS_EVENT_TYPE) || {};
|
||||
return content['rooms'] || [];
|
||||
}
|
||||
|
||||
const settings = this._getSettings() || {};
|
||||
let preferredValue = settings[settingName];
|
||||
|
||||
|
@ -53,6 +100,13 @@ export default class AccountSettingHandler extends SettingsHandler {
|
|||
return MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", content);
|
||||
}
|
||||
|
||||
// Special case for breadcrumbs
|
||||
if (settingName === "breadcrumb_rooms") {
|
||||
const content = this._getSettings(BREADCRUMBS_EVENT_TYPE) || {};
|
||||
content['rooms'] = newValue;
|
||||
return MatrixClientPeg.get().setAccountData(BREADCRUMBS_EVENT_TYPE, content);
|
||||
}
|
||||
|
||||
const content = this._getSettings() || {};
|
||||
content[settingName] = newValue;
|
||||
return MatrixClientPeg.get().setAccountData("im.vector.web.settings", content);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -27,7 +28,7 @@ export default class ConfigSettingsHandler extends SettingsHandler {
|
|||
|
||||
// Special case themes
|
||||
if (settingName === "theme") {
|
||||
return "dharma"; // config["default_theme"];
|
||||
return config["default_theme"];
|
||||
}
|
||||
|
||||
const settingsConfig = config["settingDefaults"];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -17,6 +18,7 @@ limitations under the License.
|
|||
import Promise from 'bluebird';
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from "../../MatrixClientPeg";
|
||||
import {SettingLevel} from "../SettingsStore";
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "device" level for the current device.
|
||||
|
@ -27,10 +29,12 @@ 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
|
||||
*/
|
||||
constructor(featureNames) {
|
||||
constructor(featureNames, watchManager) {
|
||||
super();
|
||||
this._featureNames = featureNames;
|
||||
this._watchers = watchManager;
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
|
@ -66,18 +70,22 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
// Special case notifications
|
||||
if (settingName === "notificationsEnabled") {
|
||||
localStorage.setItem("notifications_enabled", 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);
|
||||
return Promise.resolve();
|
||||
} else if (settingName === "audioNotificationsEnabled") {
|
||||
localStorage.setItem("audio_notifications_enabled", newValue);
|
||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const settings = this._getSettings() || {};
|
||||
settings[settingName] = newValue;
|
||||
localStorage.setItem("mx_local_settings", JSON.stringify(settings));
|
||||
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
@ -90,6 +98,14 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
return localStorage !== undefined && localStorage !== null;
|
||||
}
|
||||
|
||||
watchSetting(settingName, roomId, cb) {
|
||||
this._watchers.watchSetting(settingName, roomId, cb);
|
||||
}
|
||||
|
||||
unwatchSetting(cb) {
|
||||
this._watchers.unwatchSetting(cb);
|
||||
}
|
||||
|
||||
_getSettings() {
|
||||
const value = localStorage.getItem("mx_local_settings");
|
||||
if (!value) return null;
|
||||
|
@ -111,5 +127,6 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
|
||||
_writeFeature(featureName, enabled) {
|
||||
localStorage.setItem("mx_labs_feature_" + featureName, enabled);
|
||||
this._watchers.notifyUpdate(featureName, null, SettingLevel.DEVICE, enabled);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
48
src/settings/handlers/MatrixClientBackedSettingsHandler.js
Normal file
48
src/settings/handlers/MatrixClientBackedSettingsHandler.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* 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 = [];
|
||||
|
||||
static set matrixClient(client) {
|
||||
const oldClient = MatrixClientBackedSettingsHandler._matrixClient;
|
||||
MatrixClientBackedSettingsHandler._matrixClient = client;
|
||||
|
||||
for (const instance of MatrixClientBackedSettingsHandler._instances) {
|
||||
instance.initMatrixClient(oldClient, client);
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
MatrixClientBackedSettingsHandler._instances.push(this);
|
||||
}
|
||||
|
||||
initMatrixClient() {
|
||||
console.warn("initMatrixClient not overridden");
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,13 +15,52 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
import {SettingLevel} from "../SettingsStore";
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "room-account" level for the current user.
|
||||
*/
|
||||
export default class RoomAccountSettingsHandler extends SettingsHandler {
|
||||
export default class RoomAccountSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||
constructor(watchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
this._onAccountData = this._onAccountData.bind(this);
|
||||
}
|
||||
|
||||
initMatrixClient(oldClient, newClient) {
|
||||
if (oldClient) {
|
||||
oldClient.removeListener("Room.accountData", this._onAccountData);
|
||||
}
|
||||
|
||||
newClient.on("Room.accountData", this._onAccountData);
|
||||
}
|
||||
|
||||
_onAccountData(event, room) {
|
||||
const roomId = room.roomId;
|
||||
|
||||
if (event.getType() === "org.matrix.room.preview_urls") {
|
||||
let val = event.getContent()['disable'];
|
||||
if (typeof (val) !== "boolean") {
|
||||
val = null;
|
||||
} else {
|
||||
val = !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());
|
||||
} else if (event.getType() === "im.vector.web.settings") {
|
||||
// We can't really discern what changed, so trigger updates for everything
|
||||
for (const settingName of Object.keys(event.getContent())) {
|
||||
const val = event.getContent()[settingName];
|
||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_ACCOUNT, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
// Special case URL previews
|
||||
if (settingName === "urlPreviewsEnabled") {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -16,12 +17,19 @@ limitations under the License.
|
|||
|
||||
import Promise from 'bluebird';
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import {SettingLevel} from "../SettingsStore";
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
// Special case blacklist setting to use legacy values
|
||||
if (settingName === "blacklistUnverifiedDevices") {
|
||||
|
@ -44,6 +52,7 @@ export default class RoomDeviceSettingsHandler extends SettingsHandler {
|
|||
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);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
@ -54,6 +63,7 @@ export default class RoomDeviceSettingsHandler extends SettingsHandler {
|
|||
localStorage.setItem(this._getKey(settingName, roomId), newValue);
|
||||
}
|
||||
|
||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,13 +15,49 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||
import {SettingLevel} from "../SettingsStore";
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "room" level.
|
||||
*/
|
||||
export default class RoomSettingsHandler extends SettingsHandler {
|
||||
export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandler {
|
||||
constructor(watchManager) {
|
||||
super();
|
||||
|
||||
this._watchers = watchManager;
|
||||
this._onEvent = this._onEvent.bind(this);
|
||||
}
|
||||
|
||||
initMatrixClient(oldClient, newClient) {
|
||||
if (oldClient) {
|
||||
oldClient.removeListener("RoomState.events", this._onEvent);
|
||||
}
|
||||
|
||||
newClient.on("RoomState.events", this._onEvent);
|
||||
}
|
||||
|
||||
_onEvent(event) {
|
||||
const roomId = event.getRoomId();
|
||||
|
||||
if (event.getType() === "org.matrix.room.preview_urls") {
|
||||
let val = event.getContent()['disable'];
|
||||
if (typeof (val) !== "boolean") {
|
||||
val = null;
|
||||
} else {
|
||||
val = !val;
|
||||
}
|
||||
|
||||
this._watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM, val);
|
||||
} else if (event.getType() === "im.vector.web.settings") {
|
||||
// We can't really discern what changed, so trigger updates for everything
|
||||
for (const settingName of Object.keys(event.getContent())) {
|
||||
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM, event.getContent()[settingName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getValue(settingName, roomId) {
|
||||
// Special case URL previews
|
||||
if (settingName === "urlPreviewsEnabled") {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue