mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 20:38:55 +03:00
Initial support for notification settings
Signed-off-by: Travis Ralston <travpc@gmail.com>
This commit is contained in:
parent
8351ec7e73
commit
7ce4316cc8
16 changed files with 194 additions and 105 deletions
|
@ -25,6 +25,7 @@ import dis from './dispatcher';
|
|||
import sdk from './index';
|
||||
import { _t } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
||||
|
||||
/*
|
||||
* Dispatches:
|
||||
|
@ -138,10 +139,8 @@ const Notifier = {
|
|||
|
||||
// make sure that we persist the current setting audio_enabled setting
|
||||
// before changing anything
|
||||
if (global.localStorage) {
|
||||
if (global.localStorage.getItem('audio_notifications_enabled') === null) {
|
||||
this.setAudioEnabled(this.isEnabled());
|
||||
}
|
||||
if (SettingsStore.isLevelSupported(SettingLevel.DEVICE)) {
|
||||
SettingsStore.setValue("audioNotificationsEnabled", null, SettingLevel.DEVICE, this.isEnabled());
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
|
@ -149,6 +148,7 @@ const Notifier = {
|
|||
plaf.requestNotificationPermission().done((result) => {
|
||||
if (result !== 'granted') {
|
||||
// The permission request was dismissed or denied
|
||||
// TODO: Support alternative branding in messaging
|
||||
const description = result === 'denied'
|
||||
? _t('Riot does not have permission to send you notifications - please check your browser settings')
|
||||
: _t('Riot was not given permission to send notifications - please try again');
|
||||
|
@ -160,10 +160,6 @@ const Notifier = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (global.localStorage) {
|
||||
global.localStorage.setItem('notifications_enabled', 'true');
|
||||
}
|
||||
|
||||
if (callback) callback();
|
||||
dis.dispatch({
|
||||
action: "notifier_enabled",
|
||||
|
@ -174,8 +170,6 @@ const Notifier = {
|
|||
// disabled again in the future, we will show the banner again.
|
||||
this.setToolbarHidden(false);
|
||||
} else {
|
||||
if (!global.localStorage) return;
|
||||
global.localStorage.setItem('notifications_enabled', 'false');
|
||||
dis.dispatch({
|
||||
action: "notifier_enabled",
|
||||
value: false,
|
||||
|
@ -184,44 +178,24 @@ const Notifier = {
|
|||
},
|
||||
|
||||
isEnabled: function() {
|
||||
return this.isPossible() && SettingsStore.getValue("notificationsEnabled");
|
||||
},
|
||||
|
||||
isPossible: function() {
|
||||
const plaf = PlatformPeg.get();
|
||||
if (!plaf) return false;
|
||||
if (!plaf.supportsNotifications()) return false;
|
||||
if (!plaf.maySendNotifications()) return false;
|
||||
|
||||
if (!global.localStorage) return true;
|
||||
|
||||
const enabled = global.localStorage.getItem('notifications_enabled');
|
||||
if (enabled === null) return true;
|
||||
return enabled === 'true';
|
||||
},
|
||||
|
||||
setBodyEnabled: function(enable) {
|
||||
if (!global.localStorage) return;
|
||||
global.localStorage.setItem('notifications_body_enabled', enable ? 'true' : 'false');
|
||||
return true; // possible, but not necessarily enabled
|
||||
},
|
||||
|
||||
isBodyEnabled: function() {
|
||||
if (!global.localStorage) return true;
|
||||
const enabled = global.localStorage.getItem('notifications_body_enabled');
|
||||
// default to true if the popups are enabled
|
||||
if (enabled === null) return this.isEnabled();
|
||||
return enabled === 'true';
|
||||
return this.isEnabled() && SettingsStore.getValue("notificationBodyEnabled");
|
||||
},
|
||||
|
||||
setAudioEnabled: function(enable) {
|
||||
if (!global.localStorage) return;
|
||||
global.localStorage.setItem('audio_notifications_enabled',
|
||||
enable ? 'true' : 'false');
|
||||
},
|
||||
|
||||
isAudioEnabled: function(enable) {
|
||||
if (!global.localStorage) return true;
|
||||
const enabled = global.localStorage.getItem(
|
||||
'audio_notifications_enabled');
|
||||
// default to true if the popups are enabled
|
||||
if (enabled === null) return this.isEnabled();
|
||||
return enabled === 'true';
|
||||
isAudioEnabled: function() {
|
||||
return this.isEnabled() && SettingsStore.getValue("audioNotificationsEnabled");
|
||||
},
|
||||
|
||||
setToolbarHidden: function(hidden, persistent = true) {
|
||||
|
@ -237,17 +211,15 @@ const Notifier = {
|
|||
});
|
||||
|
||||
// update the info to localStorage for persistent settings
|
||||
if (persistent && global.localStorage) {
|
||||
global.localStorage.setItem('notifications_hidden', hidden);
|
||||
if (persistent && SettingsStore.isLevelSupported(SettingLevel.DEVICE)) {
|
||||
return SettingsStore.setValue("notificationToolbarHidden", null, SettingLevel.DEVICE, hidden);
|
||||
}
|
||||
},
|
||||
|
||||
isToolbarHidden: function() {
|
||||
// Check localStorage for any such meta data
|
||||
if (global.localStorage) {
|
||||
if (global.localStorage.getItem('notifications_hidden') === 'true') {
|
||||
return true;
|
||||
}
|
||||
if (SettingsStore.isLevelSupported(SettingLevel.DEVICE)) {
|
||||
return SettingsStore.getValue("notificationToolbarHidden");
|
||||
}
|
||||
|
||||
return this.toolbarHidden;
|
||||
|
|
|
@ -17,9 +17,6 @@ limitations under the License.
|
|||
|
||||
import Promise from 'bluebird';
|
||||
import MatrixClientPeg from './MatrixClientPeg';
|
||||
import Notifier from './Notifier';
|
||||
import { _t, _td } from './languageHandler';
|
||||
import SdkConfig from './SdkConfig';
|
||||
|
||||
/*
|
||||
* TODO: Make things use this. This is all WIP - see UserSettings.js for usage.
|
||||
|
@ -48,42 +45,6 @@ export default {
|
|||
// TODO
|
||||
},
|
||||
|
||||
// TODO: {Travis} Granular setting
|
||||
getEnableNotifications: function() {
|
||||
return Notifier.isEnabled();
|
||||
},
|
||||
|
||||
// TODO: {Travis} Granular setting
|
||||
setEnableNotifications: function(enable) {
|
||||
if (!Notifier.supportsDesktopNotifications()) {
|
||||
return;
|
||||
}
|
||||
Notifier.setEnabled(enable);
|
||||
},
|
||||
|
||||
// TODO: {Travis} Granular setting
|
||||
getEnableNotificationBody: function() {
|
||||
return Notifier.isBodyEnabled();
|
||||
},
|
||||
|
||||
// TODO: {Travis} Granular setting
|
||||
setEnableNotificationBody: function(enable) {
|
||||
if (!Notifier.supportsDesktopNotifications()) {
|
||||
return;
|
||||
}
|
||||
Notifier.setBodyEnabled(enable);
|
||||
},
|
||||
|
||||
// TODO: {Travis} Granular setting
|
||||
getEnableAudioNotifications: function() {
|
||||
return Notifier.isAudioEnabled();
|
||||
},
|
||||
|
||||
// TODO: {Travis} Granular setting
|
||||
setEnableAudioNotifications: function(enable) {
|
||||
Notifier.setAudioEnabled(enable);
|
||||
},
|
||||
|
||||
changePassword: function(oldPassword, newPassword) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
|
|
|
@ -415,10 +415,6 @@ module.exports = React.createClass({
|
|||
dis.dispatch({action: 'password_changed'});
|
||||
},
|
||||
|
||||
onEnableNotificationsChange: function(event) {
|
||||
UserSettingsStore.setEnableNotifications(event.target.checked);
|
||||
},
|
||||
|
||||
_onAddEmailEditFinished: function(value, shouldSubmit) {
|
||||
if (!shouldSubmit) return;
|
||||
this._addEmail();
|
||||
|
|
|
@ -62,6 +62,9 @@ export const SETTINGS = {
|
|||
// default: {
|
||||
// your: "value",
|
||||
// },
|
||||
//
|
||||
// // Optional settings controller. See SettingsController for more information.
|
||||
// controller: new MySettingController(),
|
||||
// },
|
||||
"feature_groups": {
|
||||
isFeature: true,
|
||||
|
@ -213,4 +216,23 @@ export const SETTINGS = {
|
|||
secondary_color: null, // Hex string, eg: #000000
|
||||
},
|
||||
},
|
||||
"notificationsEnabled": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: false,
|
||||
//controller: new NotificationsEnabledController(),
|
||||
},
|
||||
"notificationBodyEnabled": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: false,
|
||||
//controller: new NotificationBodyEnabledController(),
|
||||
},
|
||||
"audioNotificationsEnabled": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: false,
|
||||
//controller: new AudioNotificationsEnabledController(),
|
||||
},
|
||||
"notificationToolbarHidden": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: false,
|
||||
},
|
||||
};
|
|
@ -15,17 +15,17 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
import DeviceSettingsHandler from "./DeviceSettingsHandler";
|
||||
import RoomDeviceSettingsHandler from "./RoomDeviceSettingsHandler";
|
||||
import DefaultSettingsHandler from "./DefaultSettingsHandler";
|
||||
import RoomAccountSettingsHandler from "./RoomAccountSettingsHandler";
|
||||
import AccountSettingsHandler from "./AccountSettingsHandler";
|
||||
import RoomSettingsHandler from "./RoomSettingsHandler";
|
||||
import ConfigSettingsHandler from "./ConfigSettingsHandler";
|
||||
import DeviceSettingsHandler from "./handlers/DeviceSettingsHandler";
|
||||
import RoomDeviceSettingsHandler from "./handlers/RoomDeviceSettingsHandler";
|
||||
import DefaultSettingsHandler from "./handlers/DefaultSettingsHandler";
|
||||
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 SdkConfig from "../SdkConfig";
|
||||
import {SETTINGS} from "./Settings";
|
||||
import LocalEchoWrapper from "./LocalEchoWrapper";
|
||||
import LocalEchoWrapper from "./handlers/LocalEchoWrapper";
|
||||
|
||||
/**
|
||||
* Represents the various setting levels supported by the SettingsStore.
|
||||
|
@ -208,8 +208,9 @@ export default class SettingsStore {
|
|||
|
||||
if (explicit) {
|
||||
let handler = handlers[level];
|
||||
if (!handler) return null;
|
||||
return handler.getValue(settingName, roomId);
|
||||
if (!handler) return SettingsStore._tryControllerOverride(settingName, level, roomId, null);
|
||||
const value = handler.getValue(settingName, roomId);
|
||||
return SettingsStore._tryControllerOverride(settingName, level, roomId, value);
|
||||
}
|
||||
|
||||
for (let i = minIndex; i < LEVEL_ORDER.length; i++) {
|
||||
|
@ -219,10 +220,19 @@ export default class SettingsStore {
|
|||
|
||||
const value = handler.getValue(settingName, roomId);
|
||||
if (value === null || value === undefined) continue;
|
||||
return value;
|
||||
return SettingsStore._tryControllerOverride(settingName, level, roomId, value);
|
||||
}
|
||||
|
||||
return null;
|
||||
return SettingsStore._tryControllerOverride(settingName, level, roomId, null);
|
||||
}
|
||||
|
||||
static _tryControllerOverride(settingName, level, roomId, calculatedValue) {
|
||||
const controller = SETTINGS[settingName].controller;
|
||||
if (!controller) return calculatedValue;
|
||||
|
||||
const actualValue = controller.getValueOverride(level, roomId, calculatedValue);
|
||||
if (actualValue !== undefined && actualValue !== null) return actualValue;
|
||||
return calculatedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,7 +261,11 @@ export default class SettingsStore {
|
|||
throw new Error("User cannot set " + settingName + " at " + level + " in " + roomId);
|
||||
}
|
||||
|
||||
return handler.setValue(settingName, roomId, value);
|
||||
return handler.setValue(settingName, roomId, value).finally((() => {
|
||||
const controller = SETTINGS[settingName].controller;
|
||||
if (!controller) return;
|
||||
controller.onChange(level, roomId, value);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
49
src/settings/controllers/NotificationControllers.js
Normal file
49
src/settings/controllers/NotificationControllers.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
|
||||
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 SettingController from "./SettingController";
|
||||
|
||||
// export class NotificationsEnabledController extends SettingController {
|
||||
// getValueOverride(level, roomId, calculatedValue) {
|
||||
// const Notifier = require('../../Notifier'); // avoids cyclical references
|
||||
//
|
||||
// return calculatedValue && Notifier.isPossible();
|
||||
// }
|
||||
//
|
||||
// onChange(level, roomId, newValue) {
|
||||
// const Notifier = require('../../Notifier'); // avoids cyclical references
|
||||
//
|
||||
// if (Notifier.supportsDesktopNotifications()) {
|
||||
// Notifier.setBodyEnabled(newValue);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// export class NotificationBodyEnabledController extends SettingController {
|
||||
// getValueOverride(level, roomId, calculatedValue) {
|
||||
// const Notifier = require('../../Notifier'); // avoids cyclical references
|
||||
//
|
||||
// return calculatedValue && Notifier.isEnabled();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// export class AudioNotificationsEnabledController extends SettingController {
|
||||
// getValueOverride(level, roomId, calculatedValue) {
|
||||
// const Notifier = require('../../Notifier'); // avoids cyclical references
|
||||
//
|
||||
// return calculatedValue && Notifier.isEnabled();
|
||||
// }
|
||||
// }
|
49
src/settings/controllers/SettingController.js
Normal file
49
src/settings/controllers/SettingController.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2017 Travis Ralston
|
||||
|
||||
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 a controller for individual settings to alter the reading behaviour
|
||||
* based upon environmental conditions, or to react to changes and therefore update
|
||||
* the working environment.
|
||||
*
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param {string} level The level at which the value was requested at.
|
||||
* @param {String} roomId The room ID, may be null.
|
||||
* @param {*} calculatedValue The value that the handlers think the setting should be,
|
||||
* may be null.
|
||||
* @return {*} The value that should be used, or null if no override is applicable.
|
||||
*/
|
||||
getValueOverride(level, roomId, calculatedValue) {
|
||||
return null; // no override
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the setting value has been changed.
|
||||
* @param {string} level The level at which the setting has been modified.
|
||||
* @param {String} roomId The room ID, may be null.
|
||||
* @param {*} newValue The new value for the setting, may be null.
|
||||
*/
|
||||
onChange(level, roomId, newValue) {
|
||||
// do nothing by default
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "account" level for the current user.
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import Promise from 'bluebird';
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "config" level. This handler does not make use of the
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import Promise from 'bluebird';
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from "../MatrixClientPeg";
|
||||
import MatrixClientPeg from "../../MatrixClientPeg";
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "device" level for the current device.
|
||||
|
@ -38,6 +38,17 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
return this._readFeature(settingName);
|
||||
}
|
||||
|
||||
// Special case notifications
|
||||
if (settingName === "notificationsEnabled") {
|
||||
return localStorage.getItem("notifications_enabled") === "true";
|
||||
} else if (settingName === "notificationBodyEnabled") {
|
||||
return localStorage.getItem("notifications_body_enabled") === "true";
|
||||
} else if (settingName === "audioNotificationsEnabled") {
|
||||
return localStorage.getItem("audio_notifications_enabled") === "true";
|
||||
} else if (settingName === "notificationToolbarHidden") {
|
||||
return localStorage.getItem("notifications_hidden") === "true";
|
||||
}
|
||||
|
||||
return this._getSettings()[settingName];
|
||||
}
|
||||
|
||||
|
@ -47,6 +58,21 @@ export default class DeviceSettingsHandler extends SettingsHandler {
|
|||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Special case notifications
|
||||
if (settingName === "notificationsEnabled") {
|
||||
localStorage.setItem("notifications_enabled", newValue);
|
||||
return Promise.resolve();
|
||||
} else if (settingName === "notificationBodyEnabled") {
|
||||
localStorage.setItem("notifications_body_enabled", newValue);
|
||||
return Promise.resolve();
|
||||
} else if (settingName === "audioNotificationsEnabled") {
|
||||
localStorage.setItem("audio_notifications_enabled", newValue);
|
||||
return Promise.resolve();
|
||||
} else if (settingName === "notificationToolbarHidden") {
|
||||
localStorage.setItem("notifications_hidden", newValue);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const settings = this._getSettings();
|
||||
settings[settingName] = newValue;
|
||||
localStorage.setItem("mx_local_settings", JSON.stringify(settings));
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "room-account" level for the current user.
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import SettingsHandler from "./SettingsHandler";
|
||||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
||||
|
||||
/**
|
||||
* Gets and sets settings at the "room" level.
|
Loading…
Reference in a new issue