Merge pull request #420 from matrix-org/dbkr/make_notif_silder_work
Make the notification slider work
This commit is contained in:
commit
e29be619c9
3 changed files with 192 additions and 51 deletions
161
src/RoomNotifs.js
Normal file
161
src/RoomNotifs.js
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import MatrixClientPeg from './MatrixClientPeg';
|
||||||
|
import PushProcessor from 'matrix-js-sdk/lib/pushprocessor';
|
||||||
|
import q from 'q';
|
||||||
|
|
||||||
|
export const ALL_MESSAGES_LOUD = 'all_messages_loud';
|
||||||
|
export const ALL_MESSAGES = 'all_messages';
|
||||||
|
export const MENTIONS_ONLY = 'mentions_only';
|
||||||
|
export const MUTE = 'mute';
|
||||||
|
|
||||||
|
export function getRoomNotifsState(roomId) {
|
||||||
|
if (MatrixClientPeg.get().isGuest()) return RoomNotifs.ALL_MESSAGES;
|
||||||
|
|
||||||
|
// look through the override rules for a rule affecting this room:
|
||||||
|
// if one exists, it will take precedence.
|
||||||
|
const muteRule = findOverrideMuteRule(roomId);
|
||||||
|
if (muteRule) {
|
||||||
|
return MUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for everything else, look at the room rule.
|
||||||
|
const roomRule = MatrixClientPeg.get().getRoomPushRule('global', roomId);
|
||||||
|
|
||||||
|
// XXX: We have to assume the default is to notify for all messages
|
||||||
|
// (in particular this will be 'wrong' for one to one rooms because
|
||||||
|
// they will notify loudly for all messages)
|
||||||
|
if (!roomRule || !roomRule.enabled) return ALL_MESSAGES;
|
||||||
|
|
||||||
|
// a mute at the room level will still allow mentions
|
||||||
|
// to notify
|
||||||
|
if (isMuteRule(roomRule)) return MENTIONS_ONLY;
|
||||||
|
|
||||||
|
const actionsObject = PushProcessor.actionListToActionsObject(roomRule.actions);
|
||||||
|
if (actionsObject.tweaks.sound) return ALL_MESSAGES_LOUD;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRoomNotifsState(roomId, newState) {
|
||||||
|
if (newState == MUTE) {
|
||||||
|
return setRoomNotifsStateMuted(roomId);
|
||||||
|
} else {
|
||||||
|
return setRoomNotifsStateUnmuted(roomId, newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRoomNotifsStateMuted(roomId) {
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
// delete the room rule
|
||||||
|
const roomRule = cli.getRoomPushRule('global', roomId);
|
||||||
|
if (roomRule) {
|
||||||
|
promises.push(cli.deletePushRule('global', 'room', roomRule.rule_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add/replace an override rule to squelch everything in this room
|
||||||
|
// NB. We use the room ID as the name of this rule too, although this
|
||||||
|
// is an override rule, not a room rule: it still pertains to this room
|
||||||
|
// though, so using the room ID as the rule ID is logical and prevents
|
||||||
|
// duplicate copies of the rule.
|
||||||
|
promises.push(cli.addPushRule('global', 'override', roomId, {
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
kind: 'event_match',
|
||||||
|
key: 'room_id',
|
||||||
|
pattern: roomId,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
'dont_notify',
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
|
||||||
|
return q.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRoomNotifsStateUnmuted(roomId, newState) {
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
const overrideMuteRule = findOverrideMuteRule(roomId);
|
||||||
|
if (overrideMuteRule) {
|
||||||
|
promises.push(cli.deletePushRule('global', 'override', overrideMuteRule.rule_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newState == 'all_messages') {
|
||||||
|
promises.push(cli.deletePushRule('global', 'room', roomId));
|
||||||
|
} else if (newState == 'mentions_only') {
|
||||||
|
promises.push(cli.addPushRule('global', 'room', roomId, {
|
||||||
|
actions: [
|
||||||
|
'dont_notify',
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
// https://matrix.org/jira/browse/SPEC-400
|
||||||
|
promises.push(cli.setPushRuleEnabled('global', 'room', roomId, true));
|
||||||
|
} else if ('all_messages_loud') {
|
||||||
|
promises.push(cli.addPushRule('global', 'room', roomId, {
|
||||||
|
actions: [
|
||||||
|
'notify',
|
||||||
|
{
|
||||||
|
set_tweak: 'sound',
|
||||||
|
value: 'default',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
// https://matrix.org/jira/browse/SPEC-400
|
||||||
|
promises.push(cli.setPushRuleEnabled('global', 'room', roomId, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return q.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findOverrideMuteRule(roomId) {
|
||||||
|
for (const rule of MatrixClientPeg.get().pushRules['global'].override) {
|
||||||
|
if (isRuleForRoom(roomId, rule)) {
|
||||||
|
if (isMuteRule(rule) && rule.enabled) {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRuleForRoom(roomId, rule) {
|
||||||
|
if (rule.conditions.length !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const cond = rule.conditions[0];
|
||||||
|
if (
|
||||||
|
cond.kind == 'event_match' &&
|
||||||
|
cond.key == 'room_id' &&
|
||||||
|
cond.pattern == roomId
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMuteRule(rule) {
|
||||||
|
return (
|
||||||
|
rule.actions.length == 1 &&
|
||||||
|
rule.actions[0] == 'dont_notify'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -47,16 +47,6 @@ module.exports = React.createClass({
|
||||||
tags[tagName] = ['yep'];
|
tags[tagName] = ['yep'];
|
||||||
});
|
});
|
||||||
|
|
||||||
var areNotifsMuted = false;
|
|
||||||
if (!MatrixClientPeg.get().isGuest()) {
|
|
||||||
var roomPushRule = MatrixClientPeg.get().getRoomPushRule("global", this.props.room.roomId);
|
|
||||||
if (roomPushRule) {
|
|
||||||
if (0 <= roomPushRule.actions.indexOf("dont_notify")) {
|
|
||||||
areNotifsMuted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: this._yankValueFromEvent("m.room.name", "name"),
|
name: this._yankValueFromEvent("m.room.name", "name"),
|
||||||
topic: this._yankValueFromEvent("m.room.topic", "topic"),
|
topic: this._yankValueFromEvent("m.room.topic", "topic"),
|
||||||
|
@ -66,7 +56,6 @@ module.exports = React.createClass({
|
||||||
power_levels_changed: false,
|
power_levels_changed: false,
|
||||||
tags_changed: false,
|
tags_changed: false,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
areNotifsMuted: areNotifsMuted,
|
|
||||||
// isRoomPublished is loaded async in componentWillMount so when the component
|
// isRoomPublished is loaded async in componentWillMount so when the component
|
||||||
// inits, the saved value will always be undefined, however getInitialState()
|
// inits, the saved value will always be undefined, however getInitialState()
|
||||||
// is also called from the saving code so we must return the correct value here
|
// is also called from the saving code so we must return the correct value here
|
||||||
|
@ -188,12 +177,6 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this.state.areNotifsMuted !== originalState.areNotifsMuted) {
|
|
||||||
promises.push(MatrixClientPeg.get().setRoomMutePushRule(
|
|
||||||
"global", roomId, this.state.areNotifsMuted
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// power levels
|
// power levels
|
||||||
var powerLevels = this._getPowerLevels();
|
var powerLevels = this._getPowerLevels();
|
||||||
if (powerLevels) {
|
if (powerLevels) {
|
||||||
|
@ -647,12 +630,6 @@ module.exports = React.createClass({
|
||||||
{ tagsSection }
|
{ tagsSection }
|
||||||
|
|
||||||
<div className="mx_RoomSettings_toggles">
|
<div className="mx_RoomSettings_toggles">
|
||||||
<label>
|
|
||||||
<input type="checkbox" disabled={ cli.isGuest() }
|
|
||||||
onChange={this._onToggle.bind(this, "areNotifsMuted", true, false)}
|
|
||||||
defaultChecked={this.state.areNotifsMuted}/>
|
|
||||||
'Mention only' notifications for this room
|
|
||||||
</label>
|
|
||||||
<div className="mx_RoomSettings_settings">
|
<div className="mx_RoomSettings_settings">
|
||||||
<h3>Who can access this room?</h3>
|
<h3>Who can access this room?</h3>
|
||||||
{ inviteGuestWarning }
|
{ inviteGuestWarning }
|
||||||
|
|
|
@ -22,6 +22,7 @@ var dis = require("../../../dispatcher");
|
||||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var ContextualMenu = require('../../structures/ContextualMenu');
|
var ContextualMenu = require('../../structures/ContextualMenu');
|
||||||
|
var RoomNotifs = require('../../../RoomNotifs');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'RoomTile',
|
displayName: 'RoomTile',
|
||||||
|
@ -43,43 +44,41 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
var areNotifsMuted = false;
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
if (!cli.isGuest()) {
|
|
||||||
var roomPushRule = cli.getRoomPushRule("global", this.props.room.roomId);
|
|
||||||
if (roomPushRule) {
|
|
||||||
if (0 <= roomPushRule.actions.indexOf("dont_notify")) {
|
|
||||||
areNotifsMuted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return({
|
return({
|
||||||
hover : false,
|
hover : false,
|
||||||
badgeHover : false,
|
badgeHover : false,
|
||||||
notificationTagMenu: false,
|
notificationTagMenu: false,
|
||||||
roomTagMenu: false,
|
roomTagMenu: false,
|
||||||
areNotifsMuted: areNotifsMuted,
|
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onAction: function(payload) {
|
_shouldShowNotifBadge: function() {
|
||||||
switch (payload.action) {
|
const showBadgeInStates = [RoomNotifs.ALL_MESSAGES, RoomNotifs.ALL_MESSAGES_LOUD];
|
||||||
case 'notification_change':
|
return showBadgeInStates.indexOf(this.state.notifState) > -1;
|
||||||
// Is the notification about this room?
|
},
|
||||||
if (payload.roomId === this.props.room.roomId) {
|
|
||||||
this.setState( { areNotifsMuted : payload.areNotifsMuted });
|
_shouldShowMentionBadge: function() {
|
||||||
}
|
return this.state.notifState != RoomNotifs.MUTE;
|
||||||
break;
|
},
|
||||||
|
|
||||||
|
onAccountData: function(accountDataEvent) {
|
||||||
|
if (accountDataEvent.getType() == 'm.push_rules') {
|
||||||
|
this.setState({
|
||||||
|
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentWillMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
MatrixClientPeg.get().on("accountData", this.onAccountData);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
dis.unregister(this.dispatcherRef);
|
var cli = MatrixClientPeg.get();
|
||||||
|
if (cli) {
|
||||||
|
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick: function() {
|
onClick: function() {
|
||||||
|
@ -179,15 +178,19 @@ module.exports = React.createClass({
|
||||||
var notificationCount = this.props.room.getUnreadNotificationCount();
|
var notificationCount = this.props.room.getUnreadNotificationCount();
|
||||||
// var highlightCount = this.props.room.getUnreadNotificationCount("highlight");
|
// var highlightCount = this.props.room.getUnreadNotificationCount("highlight");
|
||||||
|
|
||||||
|
const notifBadges = notificationCount > 0 && this._shouldShowNotifBadge();
|
||||||
|
const mentionBadges = this.props.highlight && this._shouldShowMentionBadge();
|
||||||
|
const badges = notifBadges || mentionBadges;
|
||||||
|
|
||||||
var classes = classNames({
|
var classes = classNames({
|
||||||
'mx_RoomTile': true,
|
'mx_RoomTile': true,
|
||||||
'mx_RoomTile_selected': this.props.selected,
|
'mx_RoomTile_selected': this.props.selected,
|
||||||
'mx_RoomTile_unread': this.props.unread,
|
'mx_RoomTile_unread': this.props.unread,
|
||||||
'mx_RoomTile_unreadNotify': notificationCount > 0 && !this.state.areNotifsMuted,
|
'mx_RoomTile_unreadNotify': notifBadges,
|
||||||
'mx_RoomTile_highlight': this.props.highlight,
|
'mx_RoomTile_highlight': mentionBadges,
|
||||||
'mx_RoomTile_invited': (me && me.membership == 'invite'),
|
'mx_RoomTile_invited': (me && me.membership == 'invite'),
|
||||||
'mx_RoomTile_notificationTagMenu': this.state.notificationTagMenu,
|
'mx_RoomTile_notificationTagMenu': this.state.notificationTagMenu,
|
||||||
'mx_RoomTile_noBadges': !(this.props.highlight || (notificationCount > 0 && !this.state.areNotifsMuted))
|
'mx_RoomTile_noBadges': !badges,
|
||||||
});
|
});
|
||||||
|
|
||||||
var avatarClasses = classNames({
|
var avatarClasses = classNames({
|
||||||
|
@ -214,7 +217,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
if (this.state.badgeHover || this.state.notificationTagMenu) {
|
if (this.state.badgeHover || this.state.notificationTagMenu) {
|
||||||
badgeContent = "\u00B7\u00B7\u00B7";
|
badgeContent = "\u00B7\u00B7\u00B7";
|
||||||
} else if (this.props.highlight || (notificationCount > 0 && !this.state.areNotifsMuted)) {
|
} else if (badges) {
|
||||||
var limitedCount = (notificationCount > 99) ? '99+' : notificationCount;
|
var limitedCount = (notificationCount > 99) ? '99+' : notificationCount;
|
||||||
badgeContent = notificationCount ? limitedCount : '!';
|
badgeContent = notificationCount ? limitedCount : '!';
|
||||||
} else {
|
} else {
|
||||||
|
@ -230,7 +233,7 @@ module.exports = React.createClass({
|
||||||
var nameClasses = classNames({
|
var nameClasses = classNames({
|
||||||
'mx_RoomTile_name': true,
|
'mx_RoomTile_name': true,
|
||||||
'mx_RoomTile_invite': this.props.isInvite,
|
'mx_RoomTile_invite': this.props.isInvite,
|
||||||
'mx_RoomTile_badgeShown': this.props.highlight || (notificationCount > 0 && !this.state.areNotifsMuted) || this.state.badgeHover || this.state.notificationTagMenu,
|
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.notificationTagMenu,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.props.selected) {
|
if (this.props.selected) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue