mirror of https://github.com/vector-im/riot-web
Merge branch 'vector' of github.com:matrix-org/matrix-react-sdk into erikj/room_editing
commit
89f6459915
|
@ -67,7 +67,35 @@ 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, giveModButton;
|
||||||
|
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>;
|
||||||
|
}
|
||||||
|
if (this.state.can.modifyLevel) {
|
||||||
|
var giveOpLabel = this.state.isTargetMod ? "Revoke Mod" : "Make Mod";
|
||||||
|
giveModButton = <div className="mx_MemberInfo_button" onClick={this.onModToggle}>
|
||||||
|
{giveOpLabel}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
var opLabel;
|
||||||
|
if (this.state.isTargetMod) {
|
||||||
|
var level = this.props.member.powerLevelNorm + "%";
|
||||||
|
opLabel = <div className="mx_MemberInfo_field">Moderator ({level})</div>
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mx_MemberInfo">
|
<div className="mx_MemberInfo">
|
||||||
<img className="mx_MemberInfo_chevron" src="img/chevron-right.png" width="9" height="16" />
|
<img className="mx_MemberInfo_chevron" src="img/chevron-right.png" width="9" height="16" />
|
||||||
|
@ -78,9 +106,14 @@ module.exports = React.createClass({
|
||||||
width="128" height="128" alt=""/>
|
width="128" height="128" alt=""/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_MemberInfo_field">{this.props.member.userId}</div>
|
<div className="mx_MemberInfo_field">{this.props.member.userId}</div>
|
||||||
|
{opLabel}
|
||||||
<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}
|
||||||
|
{giveModButton}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,27 @@ 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,
|
||||||
|
* modifyLevel: boolean
|
||||||
|
* },
|
||||||
|
* 'muted': boolean,
|
||||||
|
* 'isTargetMod': 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 +52,145 @@ 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;
|
||||||
}
|
}
|
||||||
this.setState({
|
// only interested in changes to us or them
|
||||||
presence: usr.presence,
|
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||||
active: usr.lastActiveAgo
|
if ([myUserId, self.props.member.userId].indexOf(member.userId) === -1) {
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
self.setState(self._calculateOpsPermissions());
|
||||||
|
}
|
||||||
|
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) || {};
|
||||||
|
var memberState = this._calculateOpsPermissions();
|
||||||
|
memberState.presence = usr.presence || "offline";
|
||||||
|
memberState.active = usr.lastActiveAgo || -1;
|
||||||
|
this.setState(memberState);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onModToggle: function() {
|
||||||
|
var roomId = this.props.member.roomId;
|
||||||
|
var target = this.props.member.userId;
|
||||||
|
var room = MatrixClientPeg.get().getRoom(roomId);
|
||||||
|
if (!room) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var powerLevelEvent = room.currentState.getStateEvents(
|
||||||
|
"m.room.power_levels", ""
|
||||||
|
);
|
||||||
|
if (!powerLevelEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var me = room.getMember(MatrixClientPeg.get().credentials.userId);
|
||||||
|
if (!me) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var defaultLevel = powerLevelEvent.getContent().users_default;
|
||||||
|
var modLevel = me.powerLevel - 1;
|
||||||
|
// toggle the level
|
||||||
|
var newLevel = this.state.isTargetMod ? defaultLevel : modLevel;
|
||||||
|
MatrixClientPeg.get().setPowerLevel(roomId, target, newLevel, 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("Mod toggle success");
|
||||||
|
}, function(err) {
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Mod error",
|
||||||
|
description: err.message
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onChatClick: function() {
|
onChatClick: function() {
|
||||||
|
@ -108,8 +245,77 @@ module.exports = {
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
presence: "offline",
|
presence: "offline",
|
||||||
active: -1
|
active: -1,
|
||||||
|
can: {
|
||||||
|
kick: false,
|
||||||
|
ban: false,
|
||||||
|
mute: false,
|
||||||
|
modifyLevel: false
|
||||||
|
},
|
||||||
|
muted: false,
|
||||||
|
isTargetMod: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_calculateOpsPermissions: function() {
|
||||||
|
var defaultPerms = {
|
||||||
|
can: {},
|
||||||
|
muted: false,
|
||||||
|
modifyLevel: false
|
||||||
|
};
|
||||||
|
var room = MatrixClientPeg.get().getRoom(this.props.member.roomId);
|
||||||
|
if (!room) {
|
||||||
|
return defaultPerms;
|
||||||
|
}
|
||||||
|
var powerLevels = room.currentState.getStateEvents(
|
||||||
|
"m.room.power_levels", ""
|
||||||
|
);
|
||||||
|
if (!powerLevels) {
|
||||||
|
return defaultPerms;
|
||||||
|
}
|
||||||
|
var me = room.getMember(MatrixClientPeg.get().credentials.userId);
|
||||||
|
var them = this.props.member;
|
||||||
|
return {
|
||||||
|
can: this._calculateCanPermissions(
|
||||||
|
me, them, powerLevels.getContent()
|
||||||
|
),
|
||||||
|
muted: this._isMuted(them, powerLevels.getContent()),
|
||||||
|
isTargetMod: them.powerLevel > powerLevels.getContent().users_default
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_calculateCanPermissions: function(me, them, powerLevels) {
|
||||||
|
var can = {
|
||||||
|
kick: false,
|
||||||
|
ban: false,
|
||||||
|
mute: false,
|
||||||
|
modifyLevel: false
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
can.modifyLevel = me.powerLevel > them.powerLevel;
|
||||||
|
return can;
|
||||||
|
},
|
||||||
|
|
||||||
|
_isMuted: function(member, powerLevelContent) {
|
||||||
|
if (!powerLevelContent || !member) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var levelToSend = (
|
||||||
|
(powerLevelContent.events ? powerLevelContent.events["m.room.message"] : null) ||
|
||||||
|
powerLevelContent.events_default
|
||||||
|
);
|
||||||
|
return member.powerLevel < levelToSend;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue