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

pull/1/head
Kegan Dougal 2015-07-21 11:26:02 +01:00
parent 3657029fc7
commit 2e2cecdd4f
2 changed files with 196 additions and 6 deletions

View File

@ -67,6 +67,23 @@ module.exports = React.createClass({
if (this.state.active >= 0) {
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 (
<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">Last active: {activeAgo}</div>
<div className="mx_MemberInfo_button" onClick={this.onChatClick}>Start chat</div>
{muteButton}
{kickButton}
{banButton}
</div>
);
}

View File

@ -18,15 +18,25 @@ limitations under the License.
* State vars:
* 'presence' : string (online|offline|unavailable etc)
* 'active' : number (ms ago; can be -1)
* 'can': {
* kick: boolean,
* ban: boolean,
* mute: boolean
* },
* 'muted': boolean
*/
'use strict';
var MatrixClientPeg = require("../../MatrixClientPeg");
var dis = require("../../dispatcher");
var Modal = require("../../Modal");
var ComponentBroker = require('../../ComponentBroker');
var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog");
module.exports = {
componentDidMount: function() {
var self = this;
// listen for presence changes
function updateUserState(event, user) {
if (!self.props.member) { return; }
@ -40,20 +50,116 @@ module.exports = {
MatrixClientPeg.get().on("User.presence", updateUserState);
this.userPresenceFn = updateUserState;
if (this.props.member) {
var usr = MatrixClientPeg.get().getUser(this.props.member.userId);
if (!usr) {
// listen for power level changes
function updatePowerLevel(event, member) {
if (!self.props.member) { return; }
if (member.roomId !== self.props.member.roomId) {
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({
presence: usr.presence,
active: usr.lastActiveAgo
presence: usr.presence || "offline",
active: usr.lastActiveAgo || -1,
can: this._calculateOpsPermissions(),
muted: this._isMuted(this.props.member)
});
}
},
componentWillUnmount: function() {
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() {
@ -108,8 +214,72 @@ module.exports = {
getInitialState: function() {
return {
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;
}
};