Merge pull request #5453 from VickyKoblinski/es6-notifications

Leverages ES6 in Notifications
pull/5455/head
Matthew Hodgson 2017-10-27 09:15:22 +01:00 committed by GitHub
commit 3df1808fd0
1 changed files with 137 additions and 139 deletions

View File

@ -14,16 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict'; import React from 'react';
var React = require('react');
import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
import Promise from 'bluebird'; import Promise from 'bluebird';
var sdk = require('matrix-react-sdk'); import sdk from 'matrix-react-sdk';
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
var UserSettingsStore = require('matrix-react-sdk/lib/UserSettingsStore'); import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
var Modal = require('matrix-react-sdk/lib/Modal'); import UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
import Modal from 'matrix-react-sdk/lib/Modal';
var notifications = require('../../../notifications'); import {
NotificationUtils,
VectorPushRulesDefinitions,
PushRuleVectorState,
ContentRules
} from '../../../notifications';
// TODO: this "view" component still has far too much application logic in it, // TODO: this "view" component still has far too much application logic in it,
// which should be factored out to other files. // which should be factored out to other files.
@ -31,17 +34,13 @@ var notifications = require('../../../notifications');
// TODO: this component also does a lot of direct poking into this.state, which // TODO: this component also does a lot of direct poking into this.state, which
// is VERY NAUGHTY. // is VERY NAUGHTY.
var NotificationUtils = notifications.NotificationUtils;
var VectorPushRulesDefinitions = notifications.VectorPushRulesDefinitions;
var PushRuleVectorState = notifications.PushRuleVectorState;
var ContentRules = notifications.ContentRules;
/** /**
* Rules that Vector used to set in order to override the actions of default rules. * Rules that Vector used to set in order to override the actions of default rules.
* These are used to port peoples existing overrides to match the current API. * These are used to port peoples existing overrides to match the current API.
* These can be removed and forgotten once everyone has moved to the new client. * These can be removed and forgotten once everyone has moved to the new client.
*/ */
var LEGACY_RULES = { const LEGACY_RULES = {
"im.vector.rule.contains_display_name": ".m.rule.contains_display_name", "im.vector.rule.contains_display_name": ".m.rule.contains_display_name",
"im.vector.rule.room_one_to_one": ".m.rule.room_one_to_one", "im.vector.rule.room_one_to_one": ".m.rule.room_one_to_one",
"im.vector.rule.room_message": ".m.rule.message", "im.vector.rule.room_message": ".m.rule.message",
@ -51,7 +50,7 @@ var LEGACY_RULES = {
}; };
function portLegacyActions(actions) { function portLegacyActions(actions) {
var decoded = NotificationUtils.decodeActions(actions); const decoded = NotificationUtils.decodeActions(actions);
if (decoded !== null) { if (decoded !== null) {
return NotificationUtils.encodeActions(decoded); return NotificationUtils.encodeActions(decoded);
} else { } else {
@ -62,7 +61,7 @@ function portLegacyActions(actions) {
} }
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'Notififications', displayName: 'Notifications',
phases: { phases: {
LOADING: "LOADING", // The component is loading or sending data to the hs LOADING: "LOADING", // The component is loading or sending data to the hs
@ -102,7 +101,7 @@ module.exports = React.createClass({
}, },
onEnableNotificationsChange: function(event) { onEnableNotificationsChange: function(event) {
var self = this; const self = this;
this.setState({ this.setState({
phase: this.phases.LOADING phase: this.phases.LOADING
}); });
@ -122,20 +121,20 @@ module.exports = React.createClass({
}, },
onEnableEmailNotificationsChange: function(address, event) { onEnableEmailNotificationsChange: function(address, event) {
var emailPusherPromise; let emailPusherPromise;
if (event.target.checked) { if (event.target.checked) {
var data = {} const data = {}
data['brand'] = this.props.brand || 'Riot'; data['brand'] = this.props.brand || 'Riot';
emailPusherPromise = UserSettingsStore.addEmailPusher(address, data); emailPusherPromise = UserSettingsStore.addEmailPusher(address, data);
} else { } else {
var emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address); const emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address);
emailPusher.kind = null; emailPusher.kind = null;
emailPusherPromise = MatrixClientPeg.get().setPusher(emailPusher); emailPusherPromise = MatrixClientPeg.get().setPusher(emailPusher);
} }
emailPusherPromise.done(() => { emailPusherPromise.done(() => {
this._refreshFromServer(); this._refreshFromServer();
}, (error) => { }, (error) => {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Error saving email notification preferences', '', ErrorDialog, { Modal.createTrackedDialog('Error saving email notification preferences', '', ErrorDialog, {
title: _t('Error saving email notification preferences'), title: _t('Error saving email notification preferences'),
description: _t('An error occurred whilst saving your email notification preferences.'), description: _t('An error occurred whilst saving your email notification preferences.'),
@ -145,14 +144,14 @@ module.exports = React.createClass({
onNotifStateButtonClicked: function(event) { onNotifStateButtonClicked: function(event) {
// FIXME: use .bind() rather than className metadata here surely // FIXME: use .bind() rather than className metadata here surely
var vectorRuleId = event.target.className.split("-")[0]; const vectorRuleId = event.target.className.split("-")[0];
var newPushRuleVectorState = event.target.className.split("-")[1]; const newPushRuleVectorState = event.target.className.split("-")[1];
if ("_keywords" === vectorRuleId) { if ("_keywords" === vectorRuleId) {
this._setKeywordsPushRuleVectorState(newPushRuleVectorState) this._setKeywordsPushRuleVectorState(newPushRuleVectorState)
} }
else { else {
var rule = this.getRule(vectorRuleId); const rule = this.getRule(vectorRuleId);
if (rule) { if (rule) {
this._setPushRuleVectorState(rule, newPushRuleVectorState); this._setPushRuleVectorState(rule, newPushRuleVectorState);
} }
@ -160,12 +159,12 @@ module.exports = React.createClass({
}, },
onKeywordsClicked: function(event) { onKeywordsClicked: function(event) {
var self = this; const self = this;
// Compute the keywords list to display // Compute the keywords list to display
var keywords = []; let keywords = [];
for (var i in this.state.vectorContentRules.rules) { for (let i in this.state.vectorContentRules.rules) {
var rule = this.state.vectorContentRules.rules[i]; const rule = this.state.vectorContentRules.rules[i];
keywords.push(rule.pattern); keywords.push(rule.pattern);
} }
if (keywords.length) { if (keywords.length) {
@ -179,7 +178,7 @@ module.exports = React.createClass({
keywords = ""; keywords = "";
} }
var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog"); const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
Modal.createTrackedDialog('Keywords Dialog', '', TextInputDialog, { Modal.createTrackedDialog('Keywords Dialog', '', TextInputDialog, {
title: _t('Keywords'), title: _t('Keywords'),
description: _t('Enter keywords separated by a comma:'), description: _t('Enter keywords separated by a comma:'),
@ -188,8 +187,8 @@ module.exports = React.createClass({
onFinished: function onFinished(should_leave, newValue) { onFinished: function onFinished(should_leave, newValue) {
if (should_leave && newValue !== keywords) { if (should_leave && newValue !== keywords) {
var newKeywords = newValue.split(','); let newKeywords = newValue.split(',');
for (var i in newKeywords) { for (let i in newKeywords) {
newKeywords[i] = newKeywords[i].trim(); newKeywords[i] = newKeywords[i].trim();
} }
@ -208,8 +207,8 @@ module.exports = React.createClass({
}, },
getRule: function(vectorRuleId) { getRule: function(vectorRuleId) {
for (var i in this.state.vectorPushRules) { for (let i in this.state.vectorPushRules) {
var rule = this.state.vectorPushRules[i]; const rule = this.state.vectorPushRules[i];
if (rule.vectorRuleId === vectorRuleId) { if (rule.vectorRuleId === vectorRuleId) {
return rule; return rule;
} }
@ -223,13 +222,13 @@ module.exports = React.createClass({
phase: this.phases.LOADING phase: this.phases.LOADING
}); });
var self = this; const self = this;
var cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
var deferreds = []; const deferreds = [];
var ruleDefinition = VectorPushRulesDefinitions[rule.vectorRuleId]; const ruleDefinition = VectorPushRulesDefinitions[rule.vectorRuleId];
if (rule.rule) { if (rule.rule) {
var actions = ruleDefinition.vectorStateToActions[newPushRuleVectorState]; const actions = ruleDefinition.vectorStateToActions[newPushRuleVectorState];
if (!actions) { if (!actions) {
// The new state corresponds to disabling the rule. // The new state corresponds to disabling the rule.
@ -244,7 +243,7 @@ module.exports = React.createClass({
Promise.all(deferreds).done(function() { Promise.all(deferreds).done(function() {
self._refreshFromServer(); self._refreshFromServer();
}, function(error) { }, function(error) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to change settings: " + error); console.error("Failed to change settings: " + error);
Modal.createTrackedDialog('Failed to change settings', '', ErrorDialog, { Modal.createTrackedDialog('Failed to change settings', '', ErrorDialog, {
title: _t('Failed to change settings'), title: _t('Failed to change settings'),
@ -262,19 +261,19 @@ module.exports = React.createClass({
return; return;
} }
var self = this; const self = this;
var cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
this.setState({ this.setState({
phase: this.phases.LOADING phase: this.phases.LOADING
}); });
// Update all rules in self.state.vectorContentRules // Update all rules in self.state.vectorContentRules
var deferreds = []; const deferreds = [];
for (var i in this.state.vectorContentRules.rules) { for (let i in this.state.vectorContentRules.rules) {
var rule = this.state.vectorContentRules.rules[i]; const rule = this.state.vectorContentRules.rules[i];
var enabled, actions; let enabled, actions;
switch (newPushRuleVectorState) { switch (newPushRuleVectorState) {
case PushRuleVectorState.ON: case PushRuleVectorState.ON:
if (rule.actions.length !== 1) { if (rule.actions.length !== 1) {
@ -314,7 +313,7 @@ module.exports = React.createClass({
Promise.all(deferreds).done(function(resps) { Promise.all(deferreds).done(function(resps) {
self._refreshFromServer(); self._refreshFromServer();
}, function(error) { }, function(error) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Can't update user notification settings: " + error); console.error("Can't update user notification settings: " + error);
Modal.createTrackedDialog('Can\'t update user notifcation settings', '', ErrorDialog, { Modal.createTrackedDialog('Can\'t update user notifcation settings', '', ErrorDialog, {
title: _t('Can\'t update user notification settings'), title: _t('Can\'t update user notification settings'),
@ -329,14 +328,14 @@ module.exports = React.createClass({
phase: this.phases.LOADING phase: this.phases.LOADING
}); });
var self = this; const self = this;
var cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
var removeDeferreds = []; const removeDeferreds = [];
// Remove per-word push rules of keywords that are no more in the list // Remove per-word push rules of keywords that are no more in the list
var vectorContentRulesPatterns = []; const vectorContentRulesPatterns = [];
for (var i in self.state.vectorContentRules.rules) { for (let i in self.state.vectorContentRules.rules) {
var rule = self.state.vectorContentRules.rules[i]; const rule = self.state.vectorContentRules.rules[i];
vectorContentRulesPatterns.push(rule.pattern); vectorContentRulesPatterns.push(rule.pattern);
@ -347,16 +346,16 @@ module.exports = React.createClass({
// If the keyword is part of `externalContentRules`, remove the rule // If the keyword is part of `externalContentRules`, remove the rule
// before recreating it in the right Vector path // before recreating it in the right Vector path
for (var i in self.state.externalContentRules) { for (let i in self.state.externalContentRules) {
var rule = self.state.externalContentRules[i]; const rule = self.state.externalContentRules[i];
if (newKeywords.indexOf(rule.pattern) >= 0) { if (newKeywords.indexOf(rule.pattern) >= 0) {
removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id)); removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id));
} }
} }
var onError = function(error) { const onError = function(error) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to update keywords: " + error); console.error("Failed to update keywords: " + error);
Modal.createTrackedDialog('Failed to update keywords', '', ErrorDialog, { Modal.createTrackedDialog('Failed to update keywords', '', ErrorDialog, {
title: _t('Failed to update keywords'), title: _t('Failed to update keywords'),
@ -367,9 +366,9 @@ module.exports = React.createClass({
// Then, add the new ones // Then, add the new ones
Promise.all(removeDeferreds).done(function(resps) { Promise.all(removeDeferreds).done(function(resps) {
var deferreds = []; const deferreds = [];
var pushRuleVectorStateKind = self.state.vectorContentRules.vectorState; let pushRuleVectorStateKind = self.state.vectorContentRules.vectorState;
if (pushRuleVectorStateKind === PushRuleVectorState.OFF) { if (pushRuleVectorStateKind === PushRuleVectorState.OFF) {
// When the current global keywords rule is OFF, we need to look at // When the current global keywords rule is OFF, we need to look at
// the flavor of rules in 'vectorContentRules' to apply the same actions // the flavor of rules in 'vectorContentRules' to apply the same actions
@ -384,8 +383,8 @@ module.exports = React.createClass({
} }
} }
for (var i in newKeywords) { for (let i in newKeywords) {
var keyword = newKeywords[i]; const keyword = newKeywords[i];
if (vectorContentRulesPatterns.indexOf(keyword) < 0) { if (vectorContentRulesPatterns.indexOf(keyword) < 0) {
if (self.state.vectorContentRules.vectorState !== PushRuleVectorState.OFF) { if (self.state.vectorContentRules.vectorState !== PushRuleVectorState.OFF) {
@ -412,31 +411,31 @@ module.exports = React.createClass({
// Create a push rule but disabled // Create a push rule but disabled
_addDisabledPushRule: function(scope, kind, ruleId, body) { _addDisabledPushRule: function(scope, kind, ruleId, body) {
var cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
return cli.addPushRule(scope, kind, ruleId, body).then(function() { return cli.addPushRule(scope, kind, ruleId, body).then(() =>
return cli.setPushRuleEnabled(scope, kind, ruleId, false); cli.setPushRuleEnabled(scope, kind, ruleId, false)
}); );
}, },
// Check if any legacy im.vector rules need to be ported to the new API // Check if any legacy im.vector rules need to be ported to the new API
// for overriding the actions of default rules. // for overriding the actions of default rules.
_portRulesToNewAPI: function(rulesets) { _portRulesToNewAPI: function(rulesets) {
var self = this; const self = this;
var needsUpdate = []; const needsUpdate = [];
var cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
for (var kind in rulesets.global) { for (let kind in rulesets.global) {
var ruleset = rulesets.global[kind]; const ruleset = rulesets.global[kind];
for (var i = 0; i < ruleset.length; ++i) { for (let i = 0; i < ruleset.length; ++i) {
var rule = ruleset[i]; const rule = ruleset[i];
if (rule.rule_id in LEGACY_RULES) { if (rule.rule_id in LEGACY_RULES) {
console.log("Porting legacy rule", rule); console.log("Porting legacy rule", rule);
needsUpdate.push( function(kind, rule) { needsUpdate.push( function(kind, rule) {
return cli.setPushRuleActions( return cli.setPushRuleActions(
'global', kind, LEGACY_RULES[rule.rule_id], portLegacyActions(rule.actions) 'global', kind, LEGACY_RULES[rule.rule_id], portLegacyActions(rule.actions)
).then( function() { ).then(() =>
return cli.deletePushRule('global', kind, rule.rule_id); cli.deletePushRule('global', kind, rule.rule_id)
}).catch( (e) => { ).catch( (e) => {
console.warn(`Error when porting legacy rule: ${e}`); console.warn(`Error when porting legacy rule: ${e}`);
}); });
}(kind, rule)); }(kind, rule));
@ -447,9 +446,9 @@ module.exports = React.createClass({
if (needsUpdate.length > 0) { if (needsUpdate.length > 0) {
// If some of the rules need to be ported then wait for the porting // If some of the rules need to be ported then wait for the porting
// to happen and then fetch the rules again. // to happen and then fetch the rules again.
return Promise.all(needsUpdate).then( function() { return Promise.all(needsUpdate).then(() =>
return cli.getPushRules(); cli.getPushRules()
}); );
} else { } else {
// Otherwise return the rules that we already have. // Otherwise return the rules that we already have.
return rulesets; return rulesets;
@ -457,15 +456,14 @@ module.exports = React.createClass({
}, },
_refreshFromServer: function() { _refreshFromServer: function() {
var self = this; const self = this;
var pushRulesPromise = MatrixClientPeg.get().getPushRules().then(self._portRulesToNewAPI).then(function(rulesets) { const pushRulesPromise = MatrixClientPeg.get().getPushRules().then(self._portRulesToNewAPI).then(function(rulesets) {
//console.log("resolving pushRulesPromise");
/// XXX seriously? wtf is this? /// XXX seriously? wtf is this?
MatrixClientPeg.get().pushRules = rulesets; MatrixClientPeg.get().pushRules = rulesets;
// Get homeserver default rules and triage them by categories // Get homeserver default rules and triage them by categories
var rule_categories = { const rule_categories = {
// The master rule (all notifications disabling) // The master rule (all notifications disabling)
'.m.rule.master': 'master', '.m.rule.master': 'master',
@ -483,12 +481,12 @@ module.exports = React.createClass({
}; };
// HS default rules // HS default rules
var defaultRules = {master: [], vector: {}, others: []}; const defaultRules = {master: [], vector: {}, others: []};
for (var kind in rulesets.global) { for (let kind in rulesets.global) {
for (var i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) { for (let i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
var r = rulesets.global[kind][i]; const r = rulesets.global[kind][i];
var cat = rule_categories[r.rule_id]; const cat = rule_categories[r.rule_id];
r.kind = kind; r.kind = kind;
if (r.rule_id[0] === '.') { if (r.rule_id[0] === '.') {
@ -511,7 +509,7 @@ module.exports = React.createClass({
} }
// parse the keyword rules into our state // parse the keyword rules into our state
var contentRules = ContentRules.parseContentRules(rulesets); const contentRules = ContentRules.parseContentRules(rulesets);
self.state.vectorContentRules = { self.state.vectorContentRules = {
vectorState: contentRules.vectorState, vectorState: contentRules.vectorState,
rules: contentRules.rules, rules: contentRules.rules,
@ -522,7 +520,7 @@ module.exports = React.createClass({
self.state.vectorPushRules = []; self.state.vectorPushRules = [];
self.state.externalPushRules = []; self.state.externalPushRules = [];
var vectorRuleIds = [ const vectorRuleIds = [
'.m.rule.contains_display_name', '.m.rule.contains_display_name',
'.m.rule.contains_user_name', '.m.rule.contains_user_name',
'_keywords', '_keywords',
@ -533,8 +531,8 @@ module.exports = React.createClass({
'.m.rule.call', '.m.rule.call',
'.m.rule.suppress_notices' '.m.rule.suppress_notices'
]; ];
for (var i in vectorRuleIds) { for (let i in vectorRuleIds) {
var vectorRuleId = vectorRuleIds[i]; const vectorRuleId = vectorRuleIds[i];
if (vectorRuleId === '_keywords') { if (vectorRuleId === '_keywords') {
// keywords needs a special handling // keywords needs a special handling
@ -546,9 +544,8 @@ module.exports = React.createClass({
<span> <span>
{ _tJsx('Messages containing <span>keywords</span>', { _tJsx('Messages containing <span>keywords</span>',
/<span>(.*?)<\/span>/, /<span>(.*?)<\/span>/,
(sub) => { (sub) =>
return <span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>; <span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>
}
)} )}
</span> </span>
), ),
@ -556,10 +553,10 @@ module.exports = React.createClass({
}); });
} }
else { else {
var ruleDefinition = VectorPushRulesDefinitions[vectorRuleId]; const ruleDefinition = VectorPushRulesDefinitions[vectorRuleId];
var rule = defaultRules.vector[vectorRuleId]; const rule = defaultRules.vector[vectorRuleId];
var vectorState = ruleDefinition.ruleToVectorState(rule); const vectorState = ruleDefinition.ruleToVectorState(rule);
//console.log("Refreshing vectorPushRules for " + vectorRuleId +", "+ ruleDefinition.description +", " + rule +", " + vectorState); //console.log("Refreshing vectorPushRules for " + vectorRuleId +", "+ ruleDefinition.description +", " + rule +", " + vectorState);
@ -579,14 +576,14 @@ module.exports = React.createClass({
} }
// Build the rules not managed by Vector UI // Build the rules not managed by Vector UI
var otherRulesDescriptions = { const otherRulesDescriptions = {
'.m.rule.message': _t('Notify for all other messages/rooms'), '.m.rule.message': _t('Notify for all other messages/rooms'),
'.m.rule.fallback': _t('Notify me for anything else'), '.m.rule.fallback': _t('Notify me for anything else'),
}; };
for (var i in defaultRules.others) { for (let i in defaultRules.others) {
var rule = defaultRules.others[i]; const rule = defaultRules.others[i];
var ruleDescription = otherRulesDescriptions[rule.rule_id]; const ruleDescription = otherRulesDescriptions[rule.rule_id];
// Show enabled default rules that was modified by the user // Show enabled default rules that was modified by the user
if (ruleDescription && rule.enabled && !rule.default) { if (ruleDescription && rule.enabled && !rule.default) {
@ -596,8 +593,7 @@ module.exports = React.createClass({
} }
}); });
var pushersPromise = MatrixClientPeg.get().getPushers().then(function(resp) { const pushersPromise = MatrixClientPeg.get().getPushers().then(function(resp) {
//console.log("resolving pushersPromise");
self.setState({pushers: resp.pushers}); self.setState({pushers: resp.pushers});
}); });
@ -623,7 +619,7 @@ module.exports = React.createClass({
}, },
_updatePushRuleActions: function(rule, actions, enabled) { _updatePushRuleActions: function(rule, actions, enabled) {
var cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
return cli.setPushRuleActions( return cli.setPushRuleActions(
'global', rule.kind, rule.rule_id, actions 'global', rule.kind, rule.rule_id, actions
@ -669,9 +665,9 @@ module.exports = React.createClass({
}, },
renderNotifRulesTableRows: function() { renderNotifRulesTableRows: function() {
var rows = []; const rows = [];
for (var i in this.state.vectorPushRules) { for (let i in this.state.vectorPushRules) {
var rule = this.state.vectorPushRules[i]; const rule = this.state.vectorPushRules[i];
//console.log("rendering: " + rule.description + ", " + rule.vectorRuleId + ", " + rule.vectorState); //console.log("rendering: " + rule.description + ", " + rule.vectorRuleId + ", " + rule.vectorState);
rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState)); rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState));
} }
@ -697,30 +693,32 @@ module.exports = React.createClass({
}, },
render: function() { render: function() {
var self = this; const self = this;
var spinner; let spinner;
if (this.state.phase === this.phases.LOADING) { if (this.state.phase === this.phases.LOADING) {
var Loader = sdk.getComponent("elements.Spinner"); const Loader = sdk.getComponent("elements.Spinner");
spinner = <Loader />; spinner = <Loader />;
} }
let masterPushRuleDiv;
if (this.state.masterPushRule) { if (this.state.masterPushRule) {
var masterPushRuleDiv = ( masterPushRuleDiv = (
<div className="mx_UserNotifSettings_tableRow"> <div className="mx_UserNotifSettings_tableRow">
<div className="mx_UserNotifSettings_inputCell"> <div className="mx_UserNotifSettings_inputCell">
<input id="enableNotifications" <input id="enableNotifications"
ref="enableNotifications" ref="enableNotifications"
type="checkbox" type="checkbox"
checked={ !this.state.masterPushRule.enabled } checked={ !this.state.masterPushRule.enabled }
onChange={ this.onEnableNotificationsChange } /> onChange={ this.onEnableNotificationsChange }
</div> />
<div className="mx_UserNotifSettings_labelCell">
<label htmlFor="enableNotifications">
{ _t('Enable notifications for this account') }
</label>
</div>
</div> </div>
<div className="mx_UserNotifSettings_labelCell">
<label htmlFor="enableNotifications">
{ _t('Enable notifications for this account') }
</label>
</div>
</div>
); );
} }
@ -748,29 +746,29 @@ module.exports = React.createClass({
// This only supports the first email address in your profile for now // This only supports the first email address in your profile for now
emailNotificationsRow = this.emailNotificationsRow( emailNotificationsRow = this.emailNotificationsRow(
emailThreepids[0].address, emailThreepids[0].address,
_t('Enable email notifications') + ' (' + emailThreepids[0].address + ')' `${_t('Enable email notifications')} (${emailThreepids[0].address})`
); );
} }
// Build external push rules // Build external push rules
var externalRules = []; const externalRules = [];
for (var i in this.state.externalPushRules) { for (let i in this.state.externalPushRules) {
var rule = this.state.externalPushRules[i]; const rule = this.state.externalPushRules[i];
externalRules.push(<li>{ _t(rule.description) }</li>); externalRules.push(<li>{ _t(rule.description) }</li>);
} }
// Show keywords not displayed by the vector UI as a single external push rule // Show keywords not displayed by the vector UI as a single external push rule
var externalKeyWords = []; let externalKeywords = [];
for (var i in this.state.externalContentRules) { for (let i in this.state.externalContentRules) {
var rule = this.state.externalContentRules[i]; const rule = this.state.externalContentRules[i];
externalKeyWords.push(rule.pattern); externalKeywords.push(rule.pattern);
} }
if (externalKeyWords.length) { if (externalKeywords.length) {
externalKeyWords = externalKeyWords.join(", "); externalKeywords = externalKeywords.join(", ");
externalRules.push(<li>{ _t('Notifications on the following keywords follow rules which cant be displayed here:') } { externalKeyWords }</li>); externalRules.push(<li>{ _t('Notifications on the following keywords follow rules which cant be displayed here:') } { externalKeywords }</li>);
} }
var devicesSection; let devicesSection;
if (this.state.pushers === undefined) { if (this.state.pushers === undefined) {
devicesSection = <div className="error">{ _t('Unable to fetch notification target list') }</div> devicesSection = <div className="error">{ _t('Unable to fetch notification target list') }</div>
} else if (this.state.pushers.length == 0) { } else if (this.state.pushers.length == 0) {
@ -778,8 +776,8 @@ module.exports = React.createClass({
} else { } else {
// TODO: It would be great to be able to delete pushers from here too, // TODO: It would be great to be able to delete pushers from here too,
// and this wouldn't be hard to add. // and this wouldn't be hard to add.
var rows = []; const rows = [];
for (var i = 0; i < this.state.pushers.length; ++i) { for (let i = 0; i < this.state.pushers.length; ++i) {
rows.push(<tr key={ i }> rows.push(<tr key={ i }>
<td>{this.state.pushers[i].app_display_name}</td> <td>{this.state.pushers[i].app_display_name}</td>
<td>{this.state.pushers[i].device_display_name}</td> <td>{this.state.pushers[i].device_display_name}</td>
@ -798,7 +796,7 @@ module.exports = React.createClass({
</div>); </div>);
} }
var advancedSettings; let advancedSettings;
if (externalRules.length) { if (externalRules.length) {
advancedSettings = ( advancedSettings = (
<div> <div>