Use a global WatchManager for settings

Fixes https://github.com/vector-im/riot-web/issues/8936

Watchers are now managed by the SettingsStore itself through a global/default watch manager. As per the included documentation, the watch manager dispatches updates to callbacks which are redirected by the SettingsStore for consumer safety.
This commit is contained in:
Travis Ralston
2019-02-26 12:52:59 -07:00
parent 426bdafe22
commit 93673eff12
13 changed files with 111 additions and 174 deletions
@@ -16,18 +16,18 @@ limitations under the License.
*/
import MatrixClientPeg from '../../MatrixClientPeg';
import {WatchManager} from "../WatchManager";
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
import {SettingLevel} from "../SettingsStore";
/**
* 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 AccountSettingsHandler extends MatrixClientBackedSettingsHandler {
constructor() {
constructor(watchManager) {
super();
this._watchers = new WatchManager();
this._watchers = watchManager;
this._onAccountData = this._onAccountData.bind(this);
}
@@ -48,11 +48,12 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
val = !val;
}
this._watchers.notifyUpdate("urlPreviewsEnabled", null, 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())) {
this._watchers.notifyUpdate(settingName, null, event.getContent()[settingName]);
const val = event.getContent()[settingName];
this._watchers.notifyUpdate(settingName, null, SettingLevel.ACCOUNT, val);
}
}
}
@@ -102,14 +103,6 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
return cli !== undefined && cli !== null;
}
watchSetting(settingName, roomId, cb) {
this._watchers.watchSetting(settingName, roomId, cb);
}
unwatchSetting(cb) {
this._watchers.unwatchSetting(cb);
}
_getSettings(eventType = "im.vector.web.settings") {
const cli = MatrixClientPeg.get();
if (!cli) return null;
@@ -47,12 +47,4 @@ export default class ConfigSettingsHandler extends SettingsHandler {
isSupported() {
return true; // SdkConfig is always there
}
watchSetting(settingName, roomId, cb) {
// no-op: no changes possible
}
unwatchSetting(cb) {
// no-op: no changes possible
}
}
@@ -52,12 +52,4 @@ export default class DefaultSettingsHandler extends SettingsHandler {
isSupported() {
return true;
}
watchSetting(settingName, roomId, cb) {
// no-op: no changes possible
}
unwatchSetting(cb) {
// no-op: no changes possible
}
}
@@ -18,7 +18,7 @@ limitations under the License.
import Promise from 'bluebird';
import SettingsHandler from "./SettingsHandler";
import MatrixClientPeg from "../../MatrixClientPeg";
import {WatchManager} from "../WatchManager";
import {SettingLevel} from "../SettingsStore";
/**
* Gets and sets settings at the "device" level for the current device.
@@ -29,11 +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 = new WatchManager();
this._watchers = watchManager;
}
getValue(settingName, roomId) {
@@ -69,22 +70,22 @@ export default class DeviceSettingsHandler extends SettingsHandler {
// Special case notifications
if (settingName === "notificationsEnabled") {
localStorage.setItem("notifications_enabled", newValue);
this._watchers.notifyUpdate(settingName, null, 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, 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, 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, newValue);
this._watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
return Promise.resolve();
}
@@ -67,12 +67,4 @@ export default class LocalEchoWrapper extends SettingsHandler {
isSupported() {
return this._handler.isSupported();
}
watchSetting(settingName, roomId, cb) {
this._handler.watchSetting(settingName, roomId, cb);
}
unwatchSetting(cb) {
this._handler.unwatchSetting(cb);
}
}
@@ -17,16 +17,16 @@ limitations under the License.
import MatrixClientPeg from '../../MatrixClientPeg';
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
import {WatchManager} from "../WatchManager";
import {SettingLevel} from "../SettingsStore";
/**
* Gets and sets settings at the "room-account" level for the current user.
*/
export default class RoomAccountSettingsHandler extends MatrixClientBackedSettingsHandler {
constructor() {
constructor(watchManager) {
super();
this._watchers = new WatchManager();
this._watchers = watchManager;
this._onAccountData = this._onAccountData.bind(this);
}
@@ -49,13 +49,14 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
val = !val;
}
this._watchers.notifyUpdate("urlPreviewsEnabled", roomId, val);
this._watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM_ACCOUNT, val);
} else if (event.getType() === "org.matrix.room.color_scheme") {
this._watchers.notifyUpdate("roomColor", roomId, event.getContent());
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())) {
this._watchers.notifyUpdate(settingName, roomId, event.getContent()[settingName]);
const val = event.getContent()[settingName];
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_ACCOUNT, val);
}
}
}
@@ -113,14 +114,6 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
return cli !== undefined && cli !== null;
}
watchSetting(settingName, roomId, cb) {
this._watchers.watchSetting(settingName, roomId, cb);
}
unwatchSetting(cb) {
this._watchers.unwatchSetting(cb);
}
_getSettings(roomId, eventType = "im.vector.web.settings") {
const room = MatrixClientPeg.get().getRoom(roomId);
if (!room) return null;
@@ -17,17 +17,17 @@ limitations under the License.
import Promise from 'bluebird';
import SettingsHandler from "./SettingsHandler";
import {WatchManager} from "../WatchManager";
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() {
constructor(watchManager) {
super();
this._watchers = new WatchManager();
this._watchers = watchManager;
}
getValue(settingName, roomId) {
@@ -52,7 +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, newValue);
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
return Promise.resolve();
}
@@ -63,7 +63,7 @@ export default class RoomDeviceSettingsHandler extends SettingsHandler {
localStorage.setItem(this._getKey(settingName, roomId), newValue);
}
this._watchers.notifyUpdate(settingName, roomId, newValue);
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM_DEVICE, newValue);
return Promise.resolve();
}
@@ -75,14 +75,6 @@ export default class RoomDeviceSettingsHandler extends SettingsHandler {
return localStorage !== undefined && localStorage !== null;
}
watchSetting(settingName, roomId, cb) {
this._watchers.watchSetting(settingName, roomId, cb);
}
unwatchSetting(cb) {
this._watchers.unwatchSetting(cb);
}
_read(key) {
const rawValue = localStorage.getItem(key);
if (!rawValue) return null;
+5 -13
View File
@@ -17,16 +17,16 @@ limitations under the License.
import MatrixClientPeg from '../../MatrixClientPeg';
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
import {WatchManager} from "../WatchManager";
import {SettingLevel} from "../SettingsStore";
/**
* Gets and sets settings at the "room" level.
*/
export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandler {
constructor() {
constructor(watchManager) {
super();
this._watchers = new WatchManager();
this._watchers = watchManager;
this._onEvent = this._onEvent.bind(this);
}
@@ -49,11 +49,11 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
val = !val;
}
this._watchers.notifyUpdate("urlPreviewsEnabled", roomId, 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, event.getContent()[settingName]);
this._watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM, event.getContent()[settingName]);
}
}
}
@@ -101,14 +101,6 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
return cli !== undefined && cli !== null;
}
watchSetting(settingName, roomId, cb) {
this._watchers.watchSetting(settingName, roomId, cb);
}
unwatchSetting(cb) {
this._watchers.unwatchSetting(cb);
}
_getSettings(roomId, eventType = "im.vector.web.settings") {
const room = MatrixClientPeg.get().getRoom(roomId);
if (!room) return null;
-23
View File
@@ -69,27 +69,4 @@ export default class SettingsHandler {
isSupported() {
return false;
}
/**
* Watches for a setting change within this handler. The caller should preserve
* a reference to the callback so that it may be unwatched. The caller should
* additionally provide a unique callback for multiple watchers on the same setting.
* @param {string} settingName The setting name to watch for changes in.
* @param {String} roomId The room ID to watch for changes in.
* @param {function} cb A function taking two arguments: the room ID the setting changed
* in and the new value for the setting at this level in the given room.
*/
watchSetting(settingName, roomId, cb) {
throw new Error("Invalid operation: watchSetting was not overridden");
}
/**
* Unwatches a previously watched setting. If the callback is not associated with
* a watcher, this is a no-op.
* @param {function} cb A callback function previously supplied to watchSetting
* which should no longer be used.
*/
unwatchSetting(cb) {
throw new Error("Invalid operation: unwatchSetting was not overridden");
}
}