Implement kick/ban/[un]mute buttons on member list dialogs.

This commit is contained in:
Kegan Dougal 2015-07-21 11:26:02 +01:00
parent 3657029fc7
commit 2e2cecdd4f
2 changed files with 196 additions and 6 deletions
skins/base/views/molecules
src/controllers/molecules

View File

@ -67,6 +67,23 @@ module.exports = React.createClass({
if (this.state.active >= 0) { if (this.state.active >= 0) {
activeAgo = this.getDuration(this.state.active); activeAgo = this.getDuration(this.state.active);
} }
var kickButton, banButton, muteButton;
if (this.state.can.kick) {
kickButton = <div className="mx_MemberInfo_button" onClick={this.onKick}>
Kick
</div>;
}
if (this.state.can.ban) {
banButton = <div className="mx_MemberInfo_button" onClick={this.onBan}>
Ban
</div>;
}
if (this.state.can.mute) {
var muteLabel = this.state.muted ? "Unmute" : "Mute";
muteButton = <div className="mx_MemberInfo_button" onClick={this.onMuteToggle}>
{muteLabel}
</div>;
}
return ( return (
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
@ -81,6 +98,9 @@ module.exports = React.createClass({
<div className="mx_MemberInfo_field">Presence: {this.state.presence}</div> <div className="mx_MemberInfo_field">Presence: {this.state.presence}</div>
<div className="mx_MemberInfo_field">Last active: {activeAgo}</div> <div className="mx_MemberInfo_field">Last active: {activeAgo}</div>
<div className="mx_MemberInfo_button" onClick={this.onChatClick}>Start chat</div> <div className="mx_MemberInfo_button" onClick={this.onChatClick}>Start chat</div>
{muteButton}
{kickButton}
{banButton}
</div> </div>
); );
} }

View File

@ -18,15 +18,25 @@ limitations under the License.
* State vars: * State vars:
* 'presence' : string (online|offline|unavailable etc) * 'presence' : string (online|offline|unavailable etc)
* 'active' : number (ms ago; can be -1) * 'active' : number (ms ago; can be -1)
* 'can': {
* kick: boolean,
* ban: boolean,
* mute: boolean
* },
* 'muted': boolean
*/ */
'use strict'; 'use strict';
var MatrixClientPeg = require("../../MatrixClientPeg"); var MatrixClientPeg = require("../../MatrixClientPeg");
var dis = require("../../dispatcher"); var dis = require("../../dispatcher");
var Modal = require("../../Modal");
var ComponentBroker = require('../../ComponentBroker');
var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog");
module.exports = { module.exports = {
componentDidMount: function() { componentDidMount: function() {
var self = this; var self = this;
// listen for presence changes
function updateUserState(event, user) { function updateUserState(event, user) {
if (!self.props.member) { return; } if (!self.props.member) { return; }
@ -40,20 +50,116 @@ module.exports = {
MatrixClientPeg.get().on("User.presence", updateUserState); MatrixClientPeg.get().on("User.presence", updateUserState);
this.userPresenceFn = updateUserState; this.userPresenceFn = updateUserState;
if (this.props.member) { // listen for power level changes
var usr = MatrixClientPeg.get().getUser(this.props.member.userId); function updatePowerLevel(event, member) {
if (!usr) { if (!self.props.member) { return; }
if (member.roomId !== self.props.member.roomId) {
return; return;
} }
// only interested in changes to us or them
var myUserId = MatrixClientPeg.get().credentials.userId;
if ([myUserId, self.props.member.userId].indexOf(member.userId) === -1) {
return;
}
self.setState({
can: self._calculateOpsPermissions(),
muted: self._isMuted(self.props.member)
});
}
MatrixClientPeg.get().on("RoomMember.powerLevel", updatePowerLevel);
this.updatePowerLevelFn = updatePowerLevel;
// work out the current state
if (this.props.member) {
var usr = MatrixClientPeg.get().getUser(this.props.member.userId) || {};
this.setState({ this.setState({
presence: usr.presence, presence: usr.presence || "offline",
active: usr.lastActiveAgo active: usr.lastActiveAgo || -1,
can: this._calculateOpsPermissions(),
muted: this._isMuted(this.props.member)
}); });
} }
}, },
componentWillUnmount: function() { componentWillUnmount: function() {
MatrixClientPeg.get().removeListener("User.presence", this.userPresenceFn); MatrixClientPeg.get().removeListener("User.presence", this.userPresenceFn);
MatrixClientPeg.get().removeListener(
"RoomMember.powerLevel", this.updatePowerLevelFn
);
},
onKick: function() {
var roomId = this.props.member.roomId;
var target = this.props.member.userId;
var self = this;
MatrixClientPeg.get().kick(roomId, target).done(function() {
// NO-OP; rely on the m.room.member event coming down else we could
// get out of sync if we force setState here!
console.log("Kick success");
}, function(err) {
Modal.createDialog(ErrorDialog, {
title: "Kick error",
description: err.message
});
});
},
onBan: function() {
var roomId = this.props.member.roomId;
var target = this.props.member.userId;
var self = this;
MatrixClientPeg.get().ban(roomId, target).done(function() {
// NO-OP; rely on the m.room.member event coming down else we could
// get out of sync if we force setState here!
console.log("Ban success");
}, function(err) {
Modal.createDialog(ErrorDialog, {
title: "Ban error",
description: err.message
});
});
},
onMuteToggle: function() {
var roomId = this.props.member.roomId;
var target = this.props.member.userId;
var self = this;
var room = MatrixClientPeg.get().getRoom(roomId);
if (!room) {
return;
}
var powerLevelEvent = room.currentState.getStateEvents(
"m.room.power_levels", ""
);
if (!powerLevelEvent) {
return;
}
var isMuted = this.state.muted;
var powerLevels = powerLevelEvent.getContent();
var levelToSend = (
(powerLevels.events ? powerLevels.events["m.room.message"] : null) ||
powerLevels.events_default
);
var level;
if (isMuted) { // unmute
level = levelToSend;
}
else { // mute
level = levelToSend - 1;
}
MatrixClientPeg.get().setPowerLevel(roomId, target, level, powerLevelEvent).done(
function() {
// NO-OP; rely on the m.room.member event coming down else we could
// get out of sync if we force setState here!
console.log("Mute toggle success");
}, function(err) {
Modal.createDialog(ErrorDialog, {
title: "Mute error",
description: err.message
});
});
}, },
onChatClick: function() { onChatClick: function() {
@ -108,8 +214,72 @@ module.exports = {
getInitialState: function() { getInitialState: function() {
return { return {
presence: "offline", presence: "offline",
active: -1 active: -1,
can: {
kick: false,
ban: false,
mute: false
},
muted: false
} }
},
_isMuted: function(member) {
var room = MatrixClientPeg.get().getRoom(member.roomId);
if (!room) {
return false;
}
var powerLevels = room.currentState.getStateEvents(
"m.room.power_levels", ""
);
if (!powerLevels) {
return false;
}
powerLevels = powerLevels.getContent();
var levelToSend = (
(powerLevels.events ? powerLevels.events["m.room.message"] : null) ||
powerLevels.events_default
);
return member.powerLevel < levelToSend;
},
_calculateOpsPermissions: function() {
var can = {
kick: false,
ban: false,
mute: false
};
var them = this.props.member;
var room = MatrixClientPeg.get().getRoom(this.props.member.roomId);
if (!room) {
console.error("No room found");
return can;
}
var myUserId = MatrixClientPeg.get().credentials.userId;
var me = room.getMember(myUserId);
var powerLevels = room.currentState.getStateEvents(
"m.room.power_levels", ""
);
if (powerLevels) {
powerLevels = powerLevels.getContent();
}
else {
console.log("No power level event found in %s", room.roomId);
return can; // no power level event, don't allow anything.
}
var canAffectUser = them.powerLevel < me.powerLevel;
if (!canAffectUser) {
console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel);
return can;
}
var editPowerLevel = (
(powerLevels.events ? powerLevels.events["m.room.power_levels"] : null) ||
powerLevels.state_default
);
can.kick = me.powerLevel >= powerLevels.kick;
can.ban = me.powerLevel >= powerLevels.ban;
can.mute = me.powerLevel >= editPowerLevel;
return can;
} }
}; };