2016-01-11 17:24:04 +01:00
|
|
|
|
/*
|
2016-01-18 18:07:33 +01:00
|
|
|
|
Copyright 2016 OpenMarket Ltd
|
2016-01-11 17:24:04 +01:00
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
var React = require('react');
|
2016-01-12 15:12:58 +01:00
|
|
|
|
var q = require("q");
|
2016-01-11 17:24:04 +01:00
|
|
|
|
var sdk = require('matrix-react-sdk');
|
|
|
|
|
|
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|
|
|
|
|
var UserSettingsStore = require('matrix-react-sdk/lib/UserSettingsStore');
|
2016-01-12 15:12:58 +01:00
|
|
|
|
var Modal = require('matrix-react-sdk/lib/Modal');
|
2016-01-11 17:24:04 +01:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Enum for state of a push rule as defined by the Vector UI.
|
|
|
|
|
|
* @readonly
|
|
|
|
|
|
* @enum {string}
|
|
|
|
|
|
*/
|
2016-01-15 10:51:42 +01:00
|
|
|
|
var PushRuleVectorState = {
|
2016-01-11 17:24:04 +01:00
|
|
|
|
/** The user will receive push notification for this rule */
|
|
|
|
|
|
ON: "on",
|
|
|
|
|
|
/** The user will receive push notification for this rule with sound and
|
|
|
|
|
|
highlight if this is legitimate */
|
2016-01-13 16:48:22 +01:00
|
|
|
|
LOUD: "loud",
|
2016-01-11 17:24:04 +01:00
|
|
|
|
/** The push rule is disabled */
|
|
|
|
|
|
OFF: "off"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2016-02-26 20:51:16 +00:00
|
|
|
|
|
2016-02-29 16:56:33 +00:00
|
|
|
|
var ACTION_NOTIFY = [
|
|
|
|
|
|
"notify",
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak": "highlight",
|
|
|
|
|
|
"value": false
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
2016-02-26 20:51:16 +00:00
|
|
|
|
|
|
|
|
|
|
var ACTION_NOTIFY_DEFAULT_SOUND = [
|
|
|
|
|
|
"notify",
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak": "sound",
|
|
|
|
|
|
"value": "default"
|
2016-02-29 16:56:33 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak": "highlight",
|
|
|
|
|
|
"value": false
|
2016-02-26 20:51:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
var ACTION_NOTIFY_RING_SOUND = [
|
|
|
|
|
|
"notify",
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak": "sound",
|
|
|
|
|
|
"value": "ring"
|
2016-02-29 16:56:33 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak": "highlight",
|
|
|
|
|
|
"value": false
|
2016-02-26 20:51:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
var ACTION_HIGHLIGHT_DEFAULT_SOUND = [
|
|
|
|
|
|
"notify",
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak": "sound",
|
|
|
|
|
|
"value": "default"
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"set_tweak":"highlight"
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
var ACTION_DONT_NOTIFY = [ "dont_notify" ];
|
|
|
|
|
|
|
|
|
|
|
|
var ACTION_DISABLED = null;
|
|
|
|
|
|
|
2016-01-18 16:20:33 +01:00
|
|
|
|
/**
|
|
|
|
|
|
* The descriptions of rules managed by the Vector UI.
|
|
|
|
|
|
* Each rule is described so that if the server does not have it in its default
|
|
|
|
|
|
* rules or if the user wants to use actions ('PushRuleVectorState') that are
|
|
|
|
|
|
* different from the hs one, the code will create a new rule that will override
|
|
|
|
|
|
* the hs one.
|
|
|
|
|
|
*/
|
|
|
|
|
|
var VectorPushRulesDefinitions = {
|
|
|
|
|
|
|
|
|
|
|
|
// Messages containing user's display name
|
|
|
|
|
|
// (skip contains_user_name which is too geeky)
|
2016-02-26 20:51:16 +00:00
|
|
|
|
".m.rule.contains_display_name": {
|
2016-01-22 14:12:29 +00:00
|
|
|
|
kind: "underride",
|
2016-01-18 16:20:33 +01:00
|
|
|
|
description: "Messages containing my name",
|
2016-02-26 20:51:16 +00:00
|
|
|
|
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
|
|
|
|
|
|
on: ACTION_NOTIFY,
|
2016-02-29 16:56:33 +00:00
|
|
|
|
loud: ACTION_HIGHLIGHT_DEFAULT_SOUND,
|
2016-02-26 20:51:16 +00:00
|
|
|
|
off: ACTION_DISABLED
|
|
|
|
|
|
}
|
2016-01-18 16:20:33 +01:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Messages just sent to the user in a 1:1 room
|
2016-02-26 20:51:16 +00:00
|
|
|
|
".m.rule.room_one_to_one": {
|
2016-01-22 14:12:29 +00:00
|
|
|
|
kind: "underride",
|
2016-01-18 19:57:17 +00:00
|
|
|
|
description: "Messages in one-to-one chats",
|
2016-01-18 16:20:33 +01:00
|
|
|
|
vectorStateToActions: {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
on: ACTION_NOTIFY,
|
|
|
|
|
|
loud: ACTION_NOTIFY_DEFAULT_SOUND,
|
|
|
|
|
|
off: ACTION_DONT_NOTIFY
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Messages just sent to a group chat room
|
2016-01-22 09:30:31 +01:00
|
|
|
|
// 1:1 room messages are catched by the .m.rule.room_one_to_one rule if any defined
|
|
|
|
|
|
// By opposition, all other room messages are from group chat rooms.
|
2016-02-29 16:56:33 +00:00
|
|
|
|
".m.rule.message": {
|
2016-01-22 14:12:29 +00:00
|
|
|
|
kind: "underride",
|
2016-01-18 19:57:17 +00:00
|
|
|
|
description: "Messages in group chats",
|
2016-01-18 16:20:33 +01:00
|
|
|
|
vectorStateToActions: {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
on: ACTION_NOTIFY,
|
|
|
|
|
|
loud: ACTION_NOTIFY_DEFAULT_SOUND,
|
|
|
|
|
|
off: ACTION_DONT_NOTIFY
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Invitation for the user
|
2016-02-26 20:51:16 +00:00
|
|
|
|
".m.rule.invite_for_me": {
|
2016-01-22 14:12:29 +00:00
|
|
|
|
kind: "underride",
|
2016-01-18 16:20:33 +01:00
|
|
|
|
description: "When I'm invited to a room",
|
|
|
|
|
|
vectorStateToActions: {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
on: ACTION_NOTIFY,
|
|
|
|
|
|
loud: ACTION_NOTIFY_DEFAULT_SOUND,
|
|
|
|
|
|
off: ACTION_DISABLED
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// Incoming call
|
2016-02-26 20:51:16 +00:00
|
|
|
|
".m.rule.call": {
|
2016-01-22 14:12:29 +00:00
|
|
|
|
kind: "underride",
|
2016-01-18 16:20:33 +01:00
|
|
|
|
description: "Call invitation",
|
|
|
|
|
|
vectorStateToActions: {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
on: ACTION_NOTIFY,
|
|
|
|
|
|
loud: ACTION_NOTIFY_RING_SOUND,
|
|
|
|
|
|
off: ACTION_DISABLED
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2016-01-21 16:16:44 +01:00
|
|
|
|
|
|
|
|
|
|
// Notifications from bots
|
2016-02-26 20:51:16 +00:00
|
|
|
|
".m.rule.suppress_notices": {
|
2016-01-22 14:12:29 +00:00
|
|
|
|
kind: "override",
|
2016-01-21 16:16:44 +01:00
|
|
|
|
description: "Messages sent by bot",
|
|
|
|
|
|
vectorStateToActions: {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
// .m.rule.suppress_notices is a "negative" rule, we have to invert its enabled value for vector UI
|
|
|
|
|
|
on: ACTION_DISABLED,
|
|
|
|
|
|
loud: ACTION_NOTIFY_DEFAULT_SOUND,
|
|
|
|
|
|
off: ACTION_DONT_NOTIFY,
|
2016-01-21 16:16:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-01-18 16:20:33 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
module.exports = React.createClass({
|
|
|
|
|
|
displayName: 'Notififications',
|
|
|
|
|
|
|
|
|
|
|
|
phases: {
|
|
|
|
|
|
LOADING: "LOADING", // The component is loading or sending data to the hs
|
|
|
|
|
|
DISPLAY: "DISPLAY", // The component is ready and display data
|
|
|
|
|
|
ERROR: "ERROR" // There was an error
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getInitialState: function() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
phase: this.phases.LOADING,
|
2016-01-14 11:03:51 +01:00
|
|
|
|
masterPushRule: undefined, // The master rule ('.m.rule.master')
|
2016-01-12 15:12:58 +01:00
|
|
|
|
vectorPushRules: [], // HS default push rules displayed in Vector UI
|
|
|
|
|
|
vectorContentRules: { // Keyword push rules displayed in Vector UI
|
2016-01-15 10:51:42 +01:00
|
|
|
|
vectorState: PushRuleVectorState.ON,
|
2016-01-12 15:12:58 +01:00
|
|
|
|
rules: []
|
|
|
|
|
|
},
|
2016-01-15 16:45:27 +01:00
|
|
|
|
externalPushRules: [], // Push rules (except content rule) that have been defined outside Vector UI
|
2016-01-12 15:12:58 +01:00
|
|
|
|
externalContentRules: [] // Keyword push rules that have been defined outside Vector UI
|
2016-01-11 17:24:04 +01:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
componentWillMount: function() {
|
|
|
|
|
|
this._refreshFromServer();
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
onEnableNotificationsChange: function(event) {
|
2016-01-14 11:03:51 +01:00
|
|
|
|
var self = this;
|
|
|
|
|
|
this.setState({
|
|
|
|
|
|
phase: this.phases.LOADING
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
MatrixClientPeg.get().setPushRuleEnabled('global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !event.target.checked).done(function() {
|
|
|
|
|
|
self._refreshFromServer();
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
onEnableDesktopNotificationsChange: function(event) {
|
2016-01-11 17:24:04 +01:00
|
|
|
|
UserSettingsStore.setEnableNotifications(event.target.checked);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
onNotifStateButtonClicked: function(event) {
|
|
|
|
|
|
var vectorRuleId = event.target.className.split("-")[0];
|
2016-01-15 10:51:42 +01:00
|
|
|
|
var newPushRuleVectorState = event.target.className.split("-")[1];
|
2016-01-11 17:24:04 +01:00
|
|
|
|
|
2016-01-18 16:31:18 +01:00
|
|
|
|
if ("_keywords" === vectorRuleId) {
|
2016-01-15 14:28:50 +01:00
|
|
|
|
this._setKeywordsPushRuleVectorState(newPushRuleVectorState)
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
var rule = this.getRule(vectorRuleId);
|
2016-01-15 11:29:03 +01:00
|
|
|
|
if (rule) {
|
2016-01-15 14:28:50 +01:00
|
|
|
|
this._setPushRuleVectorState(rule, newPushRuleVectorState);
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-01-11 17:24:04 +01:00
|
|
|
|
},
|
|
|
|
|
|
|
2016-01-13 09:11:56 +01:00
|
|
|
|
onKeywordsClicked: function(event) {
|
2016-01-13 11:46:13 +01:00
|
|
|
|
var self = this;
|
|
|
|
|
|
|
2016-01-13 16:36:57 +01:00
|
|
|
|
// Compute the keywords list to display
|
|
|
|
|
|
var keywords = [];
|
|
|
|
|
|
for (var i in this.state.vectorContentRules.rules) {
|
|
|
|
|
|
var rule = this.state.vectorContentRules.rules[i];
|
|
|
|
|
|
keywords.push(rule.pattern);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (keywords.length) {
|
2016-01-14 11:15:59 +01:00
|
|
|
|
// As keeping the order of per-word push rules hs side is a bit tricky to code,
|
|
|
|
|
|
// display the keywords in alphabetical order to the user
|
|
|
|
|
|
keywords.sort();
|
|
|
|
|
|
|
2016-01-13 16:36:57 +01:00
|
|
|
|
keywords = keywords.join(", ");
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
keywords = "";
|
|
|
|
|
|
}
|
2016-01-13 11:46:13 +01:00
|
|
|
|
|
2016-01-13 16:36:57 +01:00
|
|
|
|
var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
|
|
|
|
|
Modal.createDialog(TextInputDialog, {
|
|
|
|
|
|
title: "Keywords",
|
|
|
|
|
|
description: "Enter keywords separated by a comma:",
|
|
|
|
|
|
value: keywords,
|
|
|
|
|
|
onFinished: function onFinished(should_leave, newValue) {
|
|
|
|
|
|
|
|
|
|
|
|
if (should_leave && newValue !== keywords) {
|
|
|
|
|
|
var newKeywords = newValue.split(',');
|
2016-01-13 11:46:13 +01:00
|
|
|
|
for (var i in newKeywords) {
|
|
|
|
|
|
newKeywords[i] = newKeywords[i].trim();
|
|
|
|
|
|
}
|
2016-01-13 15:47:00 +01:00
|
|
|
|
|
|
|
|
|
|
// Remove duplicates and empty
|
|
|
|
|
|
newKeywords = newKeywords.reduce(function(array, keyword){
|
|
|
|
|
|
if (keyword !== "" && array.indexOf(keyword) < 0) {
|
|
|
|
|
|
array.push(keyword);
|
|
|
|
|
|
}
|
|
|
|
|
|
return array;
|
|
|
|
|
|
},[]);
|
2016-01-15 11:29:03 +01:00
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
self._setKeywords(newKeywords);
|
2016-01-13 09:11:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
getRule: function(vectorRuleId) {
|
|
|
|
|
|
for (var i in this.state.vectorPushRules) {
|
|
|
|
|
|
var rule = this.state.vectorPushRules[i];
|
|
|
|
|
|
if (rule.vectorRuleId === vectorRuleId) {
|
|
|
|
|
|
return rule;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2016-01-13 11:46:13 +01:00
|
|
|
|
|
2016-01-15 10:51:42 +01:00
|
|
|
|
_actionsFor: function(pushRuleVectorState) {
|
|
|
|
|
|
if (pushRuleVectorState === PushRuleVectorState.ON) {
|
2016-02-29 16:56:33 +00:00
|
|
|
|
return ACTION_NOTIFY;
|
2016-01-13 11:46:13 +01:00
|
|
|
|
}
|
2016-01-15 10:51:42 +01:00
|
|
|
|
else if (pushRuleVectorState === PushRuleVectorState.LOUD) {
|
2016-02-29 16:56:33 +00:00
|
|
|
|
return ACTION_HIGHLIGHT_DEFAULT_SOUND;
|
2016-01-13 11:46:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2016-01-13 17:56:59 +01:00
|
|
|
|
|
2016-01-18 18:24:53 +01:00
|
|
|
|
// Determine whether a content rule is in the PushRuleVectorState.ON category or in PushRuleVectorState.LOUD
|
|
|
|
|
|
// regardless of its enabled state. Returns undefined if it does not match these categories.
|
|
|
|
|
|
_contentRuleVectorStateKind: function(rule) {
|
2016-01-13 17:56:59 +01:00
|
|
|
|
var stateKind;
|
|
|
|
|
|
|
|
|
|
|
|
// Count tweaks to determine if it is a ON or LOUD rule
|
|
|
|
|
|
var tweaks = 0;
|
|
|
|
|
|
for (var j in rule.actions) {
|
|
|
|
|
|
var action = rule.actions[j];
|
|
|
|
|
|
if (action.set_tweak === 'sound' ||
|
|
|
|
|
|
(action.set_tweak === 'highlight' && action.value)) {
|
|
|
|
|
|
tweaks++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
switch (tweaks) {
|
|
|
|
|
|
case 0:
|
2016-01-15 10:51:42 +01:00
|
|
|
|
stateKind = PushRuleVectorState.ON;
|
2016-01-13 17:56:59 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
2016-01-15 10:51:42 +01:00
|
|
|
|
stateKind = PushRuleVectorState.LOUD;
|
2016-01-13 17:56:59 +01:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return stateKind;
|
|
|
|
|
|
},
|
2016-01-15 11:29:03 +01:00
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
_setPushRuleVectorState: function(rule, newPushRuleVectorState) {
|
2016-01-15 11:29:03 +01:00
|
|
|
|
if (rule && rule.vectorState !== newPushRuleVectorState) {
|
|
|
|
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
|
|
phase: this.phases.LOADING
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var self = this;
|
2016-01-18 16:20:33 +01:00
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
|
|
var deferreds = [];
|
|
|
|
|
|
var ruleDefinition = VectorPushRulesDefinitions[rule.vectorRuleId];
|
|
|
|
|
|
|
|
|
|
|
|
if (rule.rule) {
|
2016-02-29 16:56:33 +00:00
|
|
|
|
var actions = ruleDefinition.vectorStateToActions[newPushRuleVectorState];
|
2016-01-21 16:16:44 +01:00
|
|
|
|
|
2016-02-29 16:56:33 +00:00
|
|
|
|
if (actions === ACTION_DISABLED) {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
// The new state corresponds to disabling the rule.
|
|
|
|
|
|
deferreds.push(cli.setPushRuleEnabled('global', rule.rule.kind, rule.rule.rule_id, false));
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
// The new state corresponds to enabling the rule and setting specific actions
|
|
|
|
|
|
deferreds.push(this._updatePushRuleActions(rule.rule, actions, true));
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-02-26 20:51:16 +00:00
|
|
|
|
|
2016-01-18 16:20:33 +01:00
|
|
|
|
q.all(deferreds).done(function() {
|
2016-01-15 11:29:03 +01:00
|
|
|
|
self._refreshFromServer();
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}, function(error) {
|
|
|
|
|
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
|
|
|
|
Modal.createDialog(ErrorDialog, {
|
|
|
|
|
|
title: "Can't change settings",
|
|
|
|
|
|
description: error.toString(),
|
|
|
|
|
|
onFinished: self._refreshFromServer
|
|
|
|
|
|
});
|
2016-01-15 11:29:03 +01:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
_setKeywordsPushRuleVectorState: function(newPushRuleVectorState) {
|
2016-01-15 11:29:03 +01:00
|
|
|
|
// Is there really a change?
|
|
|
|
|
|
if (this.state.vectorContentRules.vectorState === newPushRuleVectorState
|
|
|
|
|
|
|| this.state.vectorContentRules.rules.length === 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
|
|
phase: this.phases.LOADING
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Update all rules in self.state.vectorContentRules
|
|
|
|
|
|
var deferreds = [];
|
|
|
|
|
|
for (var i in this.state.vectorContentRules.rules) {
|
|
|
|
|
|
var rule = this.state.vectorContentRules.rules[i];
|
|
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
var enabled, actions;
|
2016-01-15 11:29:03 +01:00
|
|
|
|
switch (newPushRuleVectorState) {
|
|
|
|
|
|
case PushRuleVectorState.ON:
|
|
|
|
|
|
if (rule.actions.length !== 1) {
|
|
|
|
|
|
actions = this._actionsFor(PushRuleVectorState.ON);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.state.vectorContentRules.vectorState === PushRuleVectorState.OFF) {
|
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case PushRuleVectorState.LOUD:
|
|
|
|
|
|
if (rule.actions.length !== 3) {
|
|
|
|
|
|
actions = this._actionsFor(PushRuleVectorState.LOUD);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.state.vectorContentRules.vectorState === PushRuleVectorState.OFF) {
|
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case PushRuleVectorState.OFF:
|
|
|
|
|
|
enabled = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (actions) {
|
|
|
|
|
|
// Note that the workaround in _updatePushRuleActions will automatically
|
|
|
|
|
|
// enable the rule
|
|
|
|
|
|
deferreds.push(this._updatePushRuleActions(rule, actions, enabled));
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (enabled != undefined) {
|
|
|
|
|
|
deferreds.push(cli.setPushRuleEnabled('global', rule.kind, rule.rule_id, enabled));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
q.all(deferreds).done(function(resps) {
|
|
|
|
|
|
self._refreshFromServer();
|
|
|
|
|
|
}, function(error) {
|
|
|
|
|
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
|
|
|
|
Modal.createDialog(ErrorDialog, {
|
|
|
|
|
|
title: "Can't update user notification settings",
|
|
|
|
|
|
description: error.toString(),
|
|
|
|
|
|
onFinished: self._refreshFromServer
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
_setKeywords: function(newKeywords) {
|
2016-01-15 11:29:03 +01:00
|
|
|
|
this.setState({
|
|
|
|
|
|
phase: this.phases.LOADING
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
|
|
var removeDeferreds = [];
|
|
|
|
|
|
|
|
|
|
|
|
// Remove per-word push rules of keywords that are no more in the list
|
|
|
|
|
|
var vectorContentRulesPatterns = [];
|
|
|
|
|
|
for (var i in self.state.vectorContentRules.rules) {
|
|
|
|
|
|
var rule = self.state.vectorContentRules.rules[i];
|
|
|
|
|
|
|
|
|
|
|
|
vectorContentRulesPatterns.push(rule.pattern);
|
|
|
|
|
|
|
|
|
|
|
|
if (newKeywords.indexOf(rule.pattern) < 0) {
|
|
|
|
|
|
removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the keyword is part of `externalContentRules`, remove the rule
|
|
|
|
|
|
// before recreating it in the right Vector path
|
|
|
|
|
|
for (var i in self.state.externalContentRules) {
|
|
|
|
|
|
var rule = self.state.externalContentRules[i];
|
|
|
|
|
|
|
|
|
|
|
|
if (newKeywords.indexOf(rule.pattern) >= 0) {
|
|
|
|
|
|
removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var onError = function(error) {
|
|
|
|
|
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
|
|
|
|
Modal.createDialog(ErrorDialog, {
|
|
|
|
|
|
title: "Can't update keywords",
|
|
|
|
|
|
description: error.toString(),
|
|
|
|
|
|
onFinished: self._refreshFromServer
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Then, add the new ones
|
|
|
|
|
|
q.all(removeDeferreds).done(function(resps) {
|
|
|
|
|
|
var deferreds = [];
|
2016-01-15 14:28:50 +01:00
|
|
|
|
|
|
|
|
|
|
var pushRuleVectorStateKind = self.state.vectorContentRules.vectorState;
|
|
|
|
|
|
if (pushRuleVectorStateKind === PushRuleVectorState.OFF) {
|
|
|
|
|
|
// When the current global keywords rule is OFF, we need to look at
|
|
|
|
|
|
// the flavor of rules in 'vectorContentRules' to apply the same actions
|
|
|
|
|
|
// when creating the new rule.
|
|
|
|
|
|
// Thus, this new rule will join the 'vectorContentRules' set.
|
|
|
|
|
|
if (self.state.vectorContentRules.rules.length) {
|
2016-01-18 18:24:53 +01:00
|
|
|
|
pushRuleVectorStateKind = self._contentRuleVectorStateKind(self.state.vectorContentRules.rules[0]);
|
2016-01-15 14:28:50 +01:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
// ON is default
|
|
|
|
|
|
pushRuleVectorStateKind = PushRuleVectorState.ON;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-15 11:29:03 +01:00
|
|
|
|
for (var i in newKeywords) {
|
|
|
|
|
|
var keyword = newKeywords[i];
|
|
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
if (vectorContentRulesPatterns.indexOf(keyword) < 0) {
|
|
|
|
|
|
if (self.state.vectorContentRules.vectorState !== PushRuleVectorState.OFF) {
|
|
|
|
|
|
deferreds.push(cli.addPushRule
|
|
|
|
|
|
('global', 'content', keyword, {
|
|
|
|
|
|
actions: self._actionsFor(pushRuleVectorStateKind),
|
|
|
|
|
|
pattern: keyword
|
|
|
|
|
|
}));
|
2016-01-15 11:29:03 +01:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
2016-01-15 14:28:50 +01:00
|
|
|
|
deferreds.push(self._addDisabledPushRule('global', 'content', keyword, {
|
|
|
|
|
|
actions: self._actionsFor(pushRuleVectorStateKind),
|
|
|
|
|
|
pattern: keyword
|
|
|
|
|
|
}));
|
2016-01-15 11:29:03 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
q.all(deferreds).done(function(resps) {
|
|
|
|
|
|
self._refreshFromServer();
|
|
|
|
|
|
}, onError);
|
|
|
|
|
|
}, onError);
|
|
|
|
|
|
},
|
2016-01-11 17:24:04 +01:00
|
|
|
|
|
2016-01-15 14:28:50 +01:00
|
|
|
|
// Create a push rule but disabled
|
|
|
|
|
|
_addDisabledPushRule: function(scope, kind, ruleId, body) {
|
|
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
|
|
var deferred = q.defer();
|
|
|
|
|
|
|
|
|
|
|
|
cli.addPushRule(scope, kind, ruleId, body).done(function() {
|
|
|
|
|
|
cli.setPushRuleEnabled(scope, kind, ruleId, false).done(function() {
|
|
|
|
|
|
deferred.resolve();
|
|
|
|
|
|
}, function(err) {
|
|
|
|
|
|
deferred.reject(err);
|
|
|
|
|
|
});
|
|
|
|
|
|
}, function(err) {
|
|
|
|
|
|
deferred.reject(err);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return deferred.promise;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2016-01-18 16:20:33 +01:00
|
|
|
|
// Add a push rule server side according to the 'VectorPushRulesDefinitions' spec
|
|
|
|
|
|
_addOverridingVectorPushRule: function(vectorRuleId, vectorState) {
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
|
|
// Create the rule as predefined
|
|
|
|
|
|
var ruleDefinition = VectorPushRulesDefinitions[vectorRuleId];
|
|
|
|
|
|
var body = {
|
|
|
|
|
|
conditions: ruleDefinition.conditions,
|
|
|
|
|
|
actions: ruleDefinition.vectorStateToActions[vectorState]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-22 14:12:29 +00:00
|
|
|
|
return MatrixClientPeg.get().addPushRule('global', ruleDefinition.kind, vectorRuleId, body);
|
2016-01-18 16:20:33 +01:00
|
|
|
|
},
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
_refreshFromServer: function() {
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
MatrixClientPeg.get().getPushRules().done(function(rulesets) {
|
|
|
|
|
|
MatrixClientPeg.get().pushRules = rulesets;
|
|
|
|
|
|
|
2016-01-15 16:45:27 +01:00
|
|
|
|
// Get homeserver default rules and triage them by categories
|
2016-01-11 17:24:04 +01:00
|
|
|
|
var rule_categories = {
|
2016-01-15 16:45:27 +01:00
|
|
|
|
// The master rule (all notifications disabling)
|
2016-01-11 17:24:04 +01:00
|
|
|
|
'.m.rule.master': 'master',
|
|
|
|
|
|
|
2016-01-18 16:20:33 +01:00
|
|
|
|
// The default push rules displayed by Vector UI
|
2016-01-15 16:45:27 +01:00
|
|
|
|
// XXX: .m.rule.contains_user_name is not managed (not a fancy rule for Vector?)
|
2016-01-11 17:24:04 +01:00
|
|
|
|
'.m.rule.contains_display_name': 'vector',
|
|
|
|
|
|
'.m.rule.room_one_to_one': 'vector',
|
2016-01-22 09:30:31 +01:00
|
|
|
|
'.m.rule.message': 'vector',
|
2016-01-11 17:24:04 +01:00
|
|
|
|
'.m.rule.invite_for_me': 'vector',
|
2016-01-21 16:37:17 +01:00
|
|
|
|
//'.m.rule.member_event': 'vector',
|
2016-01-21 16:16:44 +01:00
|
|
|
|
'.m.rule.call': 'vector',
|
|
|
|
|
|
'.m.rule.suppress_notices': 'vector'
|
2016-01-15 16:45:27 +01:00
|
|
|
|
|
|
|
|
|
|
// Others go to others
|
2016-01-11 17:24:04 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2016-01-12 15:12:58 +01:00
|
|
|
|
// HS default rules
|
2016-01-15 16:45:27 +01:00
|
|
|
|
var defaultRules = {master: [], vector: {}, others: []};
|
2016-01-12 15:12:58 +01:00
|
|
|
|
// Content/keyword rules
|
2016-01-13 16:48:22 +01:00
|
|
|
|
var contentRules = {on: [], on_but_disabled:[], loud: [], loud_but_disabled: [], other: []};
|
2016-01-12 15:12:58 +01:00
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
for (var kind in rulesets.global) {
|
|
|
|
|
|
for (var i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
|
|
|
|
|
|
var r = rulesets.global[kind][i];
|
|
|
|
|
|
var cat = rule_categories[r.rule_id];
|
|
|
|
|
|
r.kind = kind;
|
|
|
|
|
|
if (r.rule_id[0] === '.') {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
if (cat === 'vector') {
|
|
|
|
|
|
defaultRules.vector[r.rule_id] = r;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (cat === 'master') {
|
|
|
|
|
|
defaultRules.master.push(r);
|
2016-01-15 16:45:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
defaultRules['others'].push(r);
|
2016-01-11 17:24:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-01-12 15:12:58 +01:00
|
|
|
|
else if (kind === 'content') {
|
2016-01-18 18:24:53 +01:00
|
|
|
|
switch (self._contentRuleVectorStateKind(r)) {
|
2016-01-15 10:51:42 +01:00
|
|
|
|
case PushRuleVectorState.ON:
|
2016-01-12 16:46:27 +01:00
|
|
|
|
if (r.enabled) {
|
|
|
|
|
|
contentRules.on.push(r);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
contentRules.on_but_disabled.push(r);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2016-01-15 10:51:42 +01:00
|
|
|
|
case PushRuleVectorState.LOUD:
|
2016-01-12 16:46:27 +01:00
|
|
|
|
if (r.enabled) {
|
2016-01-13 16:48:22 +01:00
|
|
|
|
contentRules.loud.push(r);
|
2016-01-12 16:46:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
2016-01-13 16:48:22 +01:00
|
|
|
|
contentRules.loud_but_disabled.push(r);
|
2016-01-12 16:46:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
contentRules.other.push(r);
|
|
|
|
|
|
break;
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-01-11 17:24:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-15 10:51:42 +01:00
|
|
|
|
// Decide which content rules to display in Vector UI.
|
2016-01-12 15:12:58 +01:00
|
|
|
|
// Vector displays a single global rule for a list of keywords
|
|
|
|
|
|
// whereas Matrix has a push rule per keyword.
|
2016-01-13 16:48:22 +01:00
|
|
|
|
// Vector can set the unique rule in ON, LOUD or OFF state.
|
2016-01-12 15:12:58 +01:00
|
|
|
|
// Matrix has enabled/disabled plus a combination of (highlight, sound) tweaks.
|
|
|
|
|
|
|
|
|
|
|
|
// The code below determines which set of user's content push rules can be
|
|
|
|
|
|
// displayed by the vector UI.
|
2016-01-15 10:51:42 +01:00
|
|
|
|
// Push rules that does not fit, ie defined by another Matrix client, ends
|
2016-01-12 15:12:58 +01:00
|
|
|
|
// in self.state.externalContentRules.
|
|
|
|
|
|
// There is priority in the determination of which set will be the displayed one.
|
2016-01-13 16:48:22 +01:00
|
|
|
|
// The set with rules that have LOUD tweaks is the first choice. Then, the ones
|
2016-01-12 15:12:58 +01:00
|
|
|
|
// with ON tweaks (no tweaks).
|
2016-01-13 16:48:22 +01:00
|
|
|
|
if (contentRules.loud.length) {
|
2016-01-12 15:12:58 +01:00
|
|
|
|
self.state.vectorContentRules = {
|
2016-01-15 10:51:42 +01:00
|
|
|
|
vectorState: PushRuleVectorState.LOUD,
|
2016-01-13 16:48:22 +01:00
|
|
|
|
rules: contentRules.loud
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
2016-01-13 16:48:22 +01:00
|
|
|
|
self.state.externalContentRules = [].concat(contentRules.loud_but_disabled, contentRules.on, contentRules.on_but_disabled, contentRules.other);
|
2016-01-12 16:46:27 +01:00
|
|
|
|
}
|
2016-01-13 16:48:22 +01:00
|
|
|
|
else if (contentRules.loud_but_disabled.length) {
|
2016-01-12 16:46:27 +01:00
|
|
|
|
self.state.vectorContentRules = {
|
2016-01-15 10:51:42 +01:00
|
|
|
|
vectorState: PushRuleVectorState.OFF,
|
2016-01-13 16:48:22 +01:00
|
|
|
|
rules: contentRules.loud_but_disabled
|
2016-01-12 16:46:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
self.state.externalContentRules = [].concat(contentRules.on, contentRules.on_but_disabled, contentRules.other);
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
else if (contentRules.on.length) {
|
|
|
|
|
|
self.state.vectorContentRules = {
|
2016-01-15 10:51:42 +01:00
|
|
|
|
vectorState: PushRuleVectorState.ON,
|
2016-01-12 15:12:58 +01:00
|
|
|
|
rules: contentRules.on
|
|
|
|
|
|
}
|
2016-01-12 16:46:27 +01:00
|
|
|
|
self.state.externalContentRules = [].concat(contentRules.on_but_disabled, contentRules.other);
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
2016-01-12 16:46:27 +01:00
|
|
|
|
else if (contentRules.on_but_disabled.length) {
|
2016-01-12 15:12:58 +01:00
|
|
|
|
self.state.vectorContentRules = {
|
2016-01-15 10:51:42 +01:00
|
|
|
|
vectorState: PushRuleVectorState.OFF,
|
2016-01-12 16:46:27 +01:00
|
|
|
|
rules: contentRules.on_but_disabled
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
2016-01-12 16:46:27 +01:00
|
|
|
|
self.state.externalContentRules = contentRules.other;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
self.state.externalContentRules = contentRules.other;
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-14 11:03:51 +01:00
|
|
|
|
// Get the master rule if any defined by the hs
|
|
|
|
|
|
if (defaultRules.master.length > 0) {
|
|
|
|
|
|
self.state.masterPushRule = defaultRules.master[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-18 16:31:18 +01:00
|
|
|
|
// Build the rules displayed in the Vector UI matrix table
|
2016-01-11 17:24:04 +01:00
|
|
|
|
self.state.vectorPushRules = [];
|
|
|
|
|
|
|
2016-01-18 16:20:33 +01:00
|
|
|
|
var vectorRuleIds = [
|
2016-02-26 20:51:16 +00:00
|
|
|
|
'.m.rule.contains_display_name',
|
2016-01-18 16:31:18 +01:00
|
|
|
|
'_keywords',
|
2016-02-26 20:51:16 +00:00
|
|
|
|
'.m.rule.room_one_to_one',
|
2016-02-29 16:56:33 +00:00
|
|
|
|
'.m.rule.message',
|
2016-02-26 20:51:16 +00:00
|
|
|
|
'.m.rule.invite_for_me',
|
2016-01-21 16:37:17 +01:00
|
|
|
|
//'im.vector.rule.member_event',
|
2016-02-26 20:51:16 +00:00
|
|
|
|
'.m.rule.call',
|
2016-02-29 16:56:33 +00:00
|
|
|
|
'.m.rule.suppress_notices'
|
2016-01-18 16:20:33 +01:00
|
|
|
|
];
|
|
|
|
|
|
for (var i in vectorRuleIds) {
|
|
|
|
|
|
var vectorRuleId = vectorRuleIds[i];
|
|
|
|
|
|
var ruleDefinition = VectorPushRulesDefinitions[vectorRuleId];
|
|
|
|
|
|
|
2016-01-18 16:31:18 +01:00
|
|
|
|
if (vectorRuleId === '_keywords') {
|
|
|
|
|
|
// keywords needs a special handling
|
|
|
|
|
|
// For Vector UI, this is a single global push rule but translated in Matrix,
|
|
|
|
|
|
// it corresponds to all content push rules (stored in self.state.vectorContentRule)
|
|
|
|
|
|
self.state.vectorPushRules.push({
|
|
|
|
|
|
"vectorRuleId": "_keywords",
|
|
|
|
|
|
"description" : (<span>Messages containing <span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>keywords</span></span>),
|
|
|
|
|
|
"vectorState": self.state.vectorContentRules.vectorState
|
|
|
|
|
|
});
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
2016-01-18 16:31:18 +01:00
|
|
|
|
else {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
var rule = defaultRules.vector[vectorRuleId];
|
2016-01-18 16:20:33 +01:00
|
|
|
|
|
2016-01-21 16:16:44 +01:00
|
|
|
|
// Translate the rule actions and its enabled value into vector state
|
|
|
|
|
|
var vectorState;
|
|
|
|
|
|
if (rule) {
|
|
|
|
|
|
for (var stateKey in PushRuleVectorState) {
|
|
|
|
|
|
var state = PushRuleVectorState[stateKey];
|
|
|
|
|
|
var vectorStateToActions = ruleDefinition.vectorStateToActions[state];
|
|
|
|
|
|
|
2016-02-29 16:56:33 +00:00
|
|
|
|
if (vectorStateToActions === ACTION_DISABLED) {
|
2016-01-21 16:16:44 +01:00
|
|
|
|
// No defined actions means that this vector state expects a disabled default hs rule
|
2016-02-26 20:51:16 +00:00
|
|
|
|
if (rule.enabled === false) {
|
2016-01-21 16:16:44 +01:00
|
|
|
|
vectorState = state;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
// The actions must match to the ones expected by vector state
|
|
|
|
|
|
if (JSON.stringify(rule.actions) === JSON.stringify(vectorStateToActions)) {
|
2016-02-26 20:51:16 +00:00
|
|
|
|
// And the rule must be enabled.
|
|
|
|
|
|
if (rule.enabled === true) {
|
2016-01-21 16:16:44 +01:00
|
|
|
|
vectorState = state;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-01-18 16:31:18 +01:00
|
|
|
|
}
|
2016-01-21 16:16:44 +01:00
|
|
|
|
|
|
|
|
|
|
if (!vectorState) {
|
|
|
|
|
|
console.error("Cannot translate rule actions into Vector rule state. Rule: " + rule);
|
2016-02-26 20:51:16 +00:00
|
|
|
|
vectorState = PushRuleVectorState.OFF;
|
2016-01-18 16:31:18 +01:00
|
|
|
|
}
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
2016-01-21 16:16:44 +01:00
|
|
|
|
else {
|
|
|
|
|
|
vectorState = PushRuleVectorState.OFF;
|
|
|
|
|
|
}
|
2016-01-18 16:31:18 +01:00
|
|
|
|
|
|
|
|
|
|
self.state.vectorPushRules.push({
|
|
|
|
|
|
"vectorRuleId": vectorRuleId,
|
|
|
|
|
|
"description" : ruleDefinition.description,
|
|
|
|
|
|
"rule": rule,
|
|
|
|
|
|
"vectorState": vectorState,
|
2016-02-26 20:51:16 +00:00
|
|
|
|
});
|
2016-01-18 16:20:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-01-11 17:24:04 +01:00
|
|
|
|
|
2016-01-15 16:45:27 +01:00
|
|
|
|
// Build the rules not managed by Vector UI
|
|
|
|
|
|
var otherRulesDescriptions = {
|
|
|
|
|
|
'.m.rule.message': "Notify for all other messages/rooms",
|
|
|
|
|
|
'.m.rule.fallback': "Notify me for anything else"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
self.state.externalPushRules = [];
|
|
|
|
|
|
for (var i in defaultRules.others) {
|
|
|
|
|
|
var rule = defaultRules.others[i];
|
|
|
|
|
|
var ruleDescription = otherRulesDescriptions[rule.rule_id];
|
|
|
|
|
|
|
|
|
|
|
|
// Show enabled default rules that was modified by the user
|
|
|
|
|
|
if (ruleDescription && rule.enabled && !rule.default) {
|
|
|
|
|
|
rule.description = ruleDescription;
|
|
|
|
|
|
self.state.externalPushRules.push(rule);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
self.setState({
|
|
|
|
|
|
phase: self.phases.DISPLAY
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2016-01-12 17:26:41 +01:00
|
|
|
|
|
2016-01-13 17:10:26 +01:00
|
|
|
|
_updatePushRuleActions: function(rule, actions, enabled) {
|
2016-01-12 17:26:41 +01:00
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
|
|
var deferred = q.defer();
|
2016-01-13 17:10:26 +01:00
|
|
|
|
|
2016-02-26 20:51:16 +00:00
|
|
|
|
return cli.setPushRuleActions(
|
|
|
|
|
|
'global', rule.kind, rule.rule_id, actions
|
|
|
|
|
|
).then( function() {
|
|
|
|
|
|
// Then, if requested, enabled or disabled the rule
|
|
|
|
|
|
if (undefined != enabled) {
|
|
|
|
|
|
return cli.setPushRuleEnabled(
|
|
|
|
|
|
'global', rule.kind, rule.rule_id, enabled
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2016-01-12 17:26:41 +01:00
|
|
|
|
},
|
2016-02-26 20:51:16 +00:00
|
|
|
|
|
2016-01-18 16:20:33 +01:00
|
|
|
|
renderNotifRulesTableRow: function(title, className, pushRuleVectorState) {
|
2016-01-11 17:24:04 +01:00
|
|
|
|
return (
|
|
|
|
|
|
<tr key = {className}>
|
2016-01-11 17:32:37 +01:00
|
|
|
|
<th>
|
|
|
|
|
|
{title}
|
|
|
|
|
|
</th>
|
2016-01-11 17:24:04 +01:00
|
|
|
|
|
|
|
|
|
|
<th>
|
2016-01-15 10:51:42 +01:00
|
|
|
|
<input className= {className + "-" + PushRuleVectorState.ON}
|
2016-01-11 17:24:04 +01:00
|
|
|
|
type="radio"
|
2016-01-15 10:51:42 +01:00
|
|
|
|
checked={ pushRuleVectorState === PushRuleVectorState.ON }
|
2016-01-11 17:24:04 +01:00
|
|
|
|
onChange={ this.onNotifStateButtonClicked } />
|
|
|
|
|
|
</th>
|
|
|
|
|
|
|
|
|
|
|
|
<th>
|
2016-01-15 10:51:42 +01:00
|
|
|
|
<input className= {className + "-" + PushRuleVectorState.LOUD}
|
2016-01-11 17:24:04 +01:00
|
|
|
|
type="radio"
|
2016-01-15 10:51:42 +01:00
|
|
|
|
checked={ pushRuleVectorState === PushRuleVectorState.LOUD }
|
2016-01-11 17:24:04 +01:00
|
|
|
|
onChange={ this.onNotifStateButtonClicked } />
|
|
|
|
|
|
</th>
|
|
|
|
|
|
|
|
|
|
|
|
<th>
|
2016-01-15 10:51:42 +01:00
|
|
|
|
<input className= {className + "-" + PushRuleVectorState.OFF}
|
2016-01-11 17:24:04 +01:00
|
|
|
|
type="radio"
|
2016-01-15 10:51:42 +01:00
|
|
|
|
checked={ pushRuleVectorState === PushRuleVectorState.OFF }
|
2016-01-11 17:24:04 +01:00
|
|
|
|
onChange={ this.onNotifStateButtonClicked } />
|
|
|
|
|
|
</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
renderNotifRulesTableRows: function() {
|
|
|
|
|
|
var rows = [];
|
|
|
|
|
|
for (var i in this.state.vectorPushRules) {
|
|
|
|
|
|
var rule = this.state.vectorPushRules[i];
|
2016-01-18 16:20:33 +01:00
|
|
|
|
rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState));
|
2016-01-11 17:24:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
return rows;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
render: function() {
|
2016-01-13 11:46:13 +01:00
|
|
|
|
var self = this;
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
if (this.state.phase === this.phases.LOADING) {
|
2016-01-15 10:51:42 +01:00
|
|
|
|
var Loader = sdk.getComponent("elements.Spinner");
|
2016-01-11 17:24:04 +01:00
|
|
|
|
return (
|
|
|
|
|
|
<div className="mx_UserSettings_notifTable">
|
|
|
|
|
|
<Loader />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2016-01-12 15:12:58 +01:00
|
|
|
|
|
2016-01-14 11:03:51 +01:00
|
|
|
|
if (this.state.masterPushRule) {
|
|
|
|
|
|
var masterPushRuleDiv = (
|
|
|
|
|
|
<div className="mx_UserNotifSettings_tableRow">
|
|
|
|
|
|
<div className="mx_UserNotifSettings_inputCell">
|
|
|
|
|
|
<input id="enableNotifications"
|
|
|
|
|
|
ref="enableNotifications"
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
checked={ !this.state.masterPushRule.enabled }
|
|
|
|
|
|
onChange={ this.onEnableNotificationsChange } />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="mx_UserNotifSettings_labelCell">
|
|
|
|
|
|
<label htmlFor="enableNotifications">
|
|
|
|
|
|
Enable notifications
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// When enabled, the master rule inhibits all existing rules
|
2016-01-15 16:45:27 +01:00
|
|
|
|
// So do not show all notification settings
|
2016-01-14 11:03:51 +01:00
|
|
|
|
if (this.state.masterPushRule.enabled) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div>
|
|
|
|
|
|
{masterPushRuleDiv}
|
|
|
|
|
|
|
|
|
|
|
|
<div className="mx_UserSettings_notifTable">
|
|
|
|
|
|
All notifications are currently disabled for all devices.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-15 16:45:27 +01:00
|
|
|
|
// Build external push rules
|
|
|
|
|
|
var externalRules = [];
|
|
|
|
|
|
for (var i in this.state.externalPushRules) {
|
|
|
|
|
|
var rule = this.state.externalPushRules[i];
|
|
|
|
|
|
externalRules.push(<li>{ rule.description }</li>);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Show keywords not displayed by the vector UI as a single external push rule
|
2016-01-12 15:12:58 +01:00
|
|
|
|
var externalKeyWords = [];
|
|
|
|
|
|
for (var i in this.state.externalContentRules) {
|
|
|
|
|
|
var rule = this.state.externalContentRules[i];
|
|
|
|
|
|
externalKeyWords.push(rule.pattern);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (externalKeyWords.length) {
|
|
|
|
|
|
externalKeyWords = externalKeyWords.join(", ");
|
2016-01-15 16:45:27 +01:00
|
|
|
|
externalRules.push(<li>Notifications on the following keywords follow rules which can’t be displayed here: { externalKeyWords }</li>);
|
2016-01-12 15:12:58 +01:00
|
|
|
|
}
|
2016-01-15 16:45:27 +01:00
|
|
|
|
|
|
|
|
|
|
var advancedSettings;
|
|
|
|
|
|
if (externalRules.length) {
|
|
|
|
|
|
advancedSettings = (
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h3>Advanced notifications settings</h3>
|
2016-01-15 17:28:57 +01:00
|
|
|
|
There are advanced notifications which are not shown here.<br/>
|
|
|
|
|
|
You might have configured them in another client than Vector. You cannot tune them in Vector but they still apply.
|
2016-01-15 16:45:27 +01:00
|
|
|
|
<ul>
|
|
|
|
|
|
{ externalRules }
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
return (
|
2016-01-12 15:12:58 +01:00
|
|
|
|
<div>
|
2016-01-14 11:03:51 +01:00
|
|
|
|
|
|
|
|
|
|
{masterPushRuleDiv}
|
|
|
|
|
|
|
2016-01-12 15:12:58 +01:00
|
|
|
|
<div className="mx_UserSettings_notifTable">
|
|
|
|
|
|
|
|
|
|
|
|
<div className="mx_UserNotifSettings_tableRow">
|
|
|
|
|
|
<div className="mx_UserNotifSettings_inputCell">
|
2016-01-14 11:03:51 +01:00
|
|
|
|
<input id="enableDesktopNotifications"
|
|
|
|
|
|
ref="enableDesktopNotifications"
|
2016-01-12 15:12:58 +01:00
|
|
|
|
type="checkbox"
|
|
|
|
|
|
checked={ UserSettingsStore.getEnableNotifications() }
|
2016-01-14 11:03:51 +01:00
|
|
|
|
onChange={ this.onEnableDesktopNotificationsChange } />
|
2016-01-12 15:12:58 +01:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="mx_UserNotifSettings_labelCell">
|
2016-01-14 11:03:51 +01:00
|
|
|
|
<label htmlFor="enableDesktopNotifications">
|
2016-01-12 15:12:58 +01:00
|
|
|
|
Enable desktop notifications
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
2016-01-11 17:24:04 +01:00
|
|
|
|
</div>
|
2016-01-12 15:12:58 +01:00
|
|
|
|
|
2016-01-13 15:47:00 +01:00
|
|
|
|
<h3>General use</h3>
|
2016-01-12 15:12:58 +01:00
|
|
|
|
|
|
|
|
|
|
<div className="mx_UserNotifSettings_pushRulesTableWrapper">
|
|
|
|
|
|
<table className="mx_UserNotifSettings_pushRulesTable">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th width="55%"></th>
|
2016-01-13 16:48:22 +01:00
|
|
|
|
<th width="15%">On</th>
|
|
|
|
|
|
<th width="15%">Loud</th>
|
2016-01-12 15:12:58 +01:00
|
|
|
|
<th width="15%">Off</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
|
|
|
|
|
|
{ this.renderNotifRulesTableRows() }
|
|
|
|
|
|
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
2016-01-11 17:24:04 +01:00
|
|
|
|
</div>
|
2016-01-12 15:12:58 +01:00
|
|
|
|
|
2016-01-15 16:45:27 +01:00
|
|
|
|
{ advancedSettings }
|
|
|
|
|
|
|
2016-01-11 17:24:04 +01:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|