diff --git a/skins/base/views/molecules/MemberInfo.js b/skins/base/views/molecules/MemberInfo.js
index 3a81185ba9..036a3fd62d 100644
--- a/skins/base/views/molecules/MemberInfo.js
+++ b/skins/base/views/molecules/MemberInfo.js
@@ -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 =
+ Kick
+
;
+ }
+ if (this.state.can.ban) {
+ banButton =
+ Ban
+
;
+ }
+ if (this.state.can.mute) {
+ var muteLabel = this.state.muted ? "Unmute" : "Mute";
+ muteButton =
+ {muteLabel}
+
;
+ }
return (
@@ -81,6 +98,9 @@ module.exports = React.createClass({
Presence: {this.state.presence}
Last active: {activeAgo}
Start chat
+ {muteButton}
+ {kickButton}
+ {banButton}
);
}
diff --git a/src/controllers/molecules/MemberInfo.js b/src/controllers/molecules/MemberInfo.js
index 96f8bb8ca8..fd04df4d55 100644
--- a/src/controllers/molecules/MemberInfo.js
+++ b/src/controllers/molecules/MemberInfo.js
@@ -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;
}
};