From de4773ba935bfc06391fb819e39680a41de9d31b Mon Sep 17 00:00:00 2001 From: David Baker <dave@matrix.org> Date: Fri, 17 Feb 2017 15:50:30 +0000 Subject: [PATCH 1/5] Show when you've been kicked or banned Update the room state when you've been kicked or banned, and show a message in the preview bar, including the reason. --- src/components/structures/RoomView.js | 11 +++++ src/components/views/rooms/RoomPreviewBar.js | 50 +++++++++++++++++--- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 662d322fb4..5bf192dfc6 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -159,6 +159,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().on("Room.name", this.onRoomName); MatrixClientPeg.get().on("Room.accountData", this.onRoomAccountData); MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember); + MatrixClientPeg.get().on("RoomMember.membership", this.onRoomMemberMembership); MatrixClientPeg.get().on("accountData", this.onAccountData); this.tabComplete = new TabComplete({ @@ -347,6 +348,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); MatrixClientPeg.get().removeListener("Room.accountData", this.onRoomAccountData); MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember); + MatrixClientPeg.get().removeListener("RoomMember.membership", this.onRoomMemberMembership); MatrixClientPeg.get().removeListener("accountData", this.onAccountData); } @@ -612,6 +614,12 @@ module.exports = React.createClass({ this._updateRoomMembers(); }, + onRoomMemberMembership: function(ev, member, oldMembership) { + if (member.userId == MatrixClientPeg.get().credentials.userId) { + this.forceUpdate(); + } + }, + // rate limited because a power level change will emit an event for every // member in the room. _updateRoomMembers: new rate_limited_func(function() { @@ -1456,6 +1464,7 @@ module.exports = React.createClass({ /> <div className="mx_RoomView_auxPanel"> <RoomPreviewBar onJoinClick={ this.onJoinButtonClicked } + onForgetClick={ this.onForgetClick } onRejectClick={ this.onRejectThreepidInviteButtonClicked } canPreview={ false } error={ this.state.roomLoadError } roomAlias={room_alias} @@ -1498,6 +1507,7 @@ module.exports = React.createClass({ /> <div className="mx_RoomView_auxPanel"> <RoomPreviewBar onJoinClick={ this.onJoinButtonClicked } + onForgetClick={ this.onForgetClick } onRejectClick={ this.onRejectButtonClicked } inviterName={ inviterName } canPreview={ false } @@ -1573,6 +1583,7 @@ module.exports = React.createClass({ } aux = ( <RoomPreviewBar onJoinClick={this.onJoinButtonClicked} + onForgetClick={ this.onForgetClick } onRejectClick={this.onRejectThreepidInviteButtonClicked} spinner={this.state.joining} inviterName={inviterName} diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 51ae0fe965..61515e07ca 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -79,6 +80,12 @@ module.exports = React.createClass({ } }, + _roomNameElement: function(fallback) { + fallback = fallback || 'a room'; + const name = this.props.room ? this.props.room.name : (this.props.room_alias || ""); + return name ? <b>{ name }</b> : fallback; + }, + render: function() { var joinBlock, previewBlock; @@ -89,6 +96,16 @@ module.exports = React.createClass({ </div>); } + const myMember = this.props.room ? this.props.room.currentState.members[ + MatrixClientPeg.get().credentials.userId + ] : null; + const kicked = ( + myMember && + myMember.membership == 'leave' && + myMember.events.member.getSender() != MatrixClientPeg.get().credentials.userId + ); + const banned = myMember && myMember.membership == 'ban'; + if (this.props.inviterName) { var emailMatchBlock; if (this.props.invitedEmail) { @@ -122,8 +139,31 @@ module.exports = React.createClass({ </div> ); - } - else if (this.props.error) { + } else if (kicked || banned) { + const verb = kicked ? 'kicked' : 'banned'; + const roomName = this._roomNameElement('this room'); + const kicker = MatrixClientPeg.get().getUser( + myMember.events.member.getSender() + ); + let reason; + if (myMember.events.member.getContent().reason) { + reason = <div>Reason: {myMember.events.member.getContent().reason}</div> + } + let rejoinBlock; + if (!banned) { + rejoinBlock = <a onClick={ this.props.onJoinClick }><b>Rejoin</b></a>; + } + joinBlock = ( + <div> + <div className="mx_RoomPreviewBar_join_text"> + You have been {verb} from {roomName} by {kicker.displayName}.<br /> + {reason} + <a onClick={ this.props.onForgetClick }><b>Forget</b></a><br /> + {rejoinBlock} + </div> + </div> + ); + } else if (this.props.error) { var name = this.props.roomAlias || "This room"; var error; if (this.props.error.errcode == 'M_NOT_FOUND') { @@ -138,10 +178,8 @@ module.exports = React.createClass({ </div> </div> ); - } - else { - var name = this.props.room ? this.props.room.name : (this.props.room_alias || ""); - name = name ? <b>{ name }</b> : "a room"; + } else { + const name = this._roomNameElement(); joinBlock = ( <div> <div className="mx_RoomPreviewBar_join_text"> From 9f9de46b10cefa674f4677eb9e239f47acac42ac Mon Sep 17 00:00:00 2001 From: David Baker <dave@matrix.org> Date: Fri, 17 Feb 2017 16:09:25 +0000 Subject: [PATCH 2/5] Add onForgetClick proptype --- src/components/views/rooms/RoomPreviewBar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 61515e07ca..b6d3cf2f50 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -27,6 +27,7 @@ module.exports = React.createClass({ propTypes: { onJoinClick: React.PropTypes.func, onRejectClick: React.PropTypes.func, + onForgetClick: React.PropTypes.func, // if inviterName is specified, the preview bar will shown an invite to the room. // You should also specify onRejectClick if specifiying inviterName From a3aea6ba2d75bc4e3d8468036fc25fdc36320ea4 Mon Sep 17 00:00:00 2001 From: David Baker <dave@matrix.org> Date: Fri, 17 Feb 2017 16:11:20 +0000 Subject: [PATCH 3/5] Swap rejoin / forget --- src/components/views/rooms/RoomPreviewBar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index b6d3cf2f50..4eaa1cea71 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -152,15 +152,15 @@ module.exports = React.createClass({ } let rejoinBlock; if (!banned) { - rejoinBlock = <a onClick={ this.props.onJoinClick }><b>Rejoin</b></a>; + rejoinBlock = <div><a onClick={ this.props.onJoinClick }><b>Rejoin</b></a></div>; } joinBlock = ( <div> <div className="mx_RoomPreviewBar_join_text"> You have been {verb} from {roomName} by {kicker.displayName}.<br /> {reason} - <a onClick={ this.props.onForgetClick }><b>Forget</b></a><br /> {rejoinBlock} + <a onClick={ this.props.onForgetClick }><b>Forget</b></a> </div> </div> ); From 1f5fdf794583d7474d8bafa0ec1e90b0288cafff Mon Sep 17 00:00:00 2001 From: David Baker <dave@matrix.org> Date: Fri, 17 Feb 2017 16:14:51 +0000 Subject: [PATCH 4/5] Get a member object, not the user object --- src/components/views/rooms/RoomPreviewBar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 4eaa1cea71..3476c47f09 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -143,7 +143,7 @@ module.exports = React.createClass({ } else if (kicked || banned) { const verb = kicked ? 'kicked' : 'banned'; const roomName = this._roomNameElement('this room'); - const kicker = MatrixClientPeg.get().getUser( + const kicker = this.props.room.currentState.getMember( myMember.events.member.getSender() ); let reason; @@ -157,7 +157,7 @@ module.exports = React.createClass({ joinBlock = ( <div> <div className="mx_RoomPreviewBar_join_text"> - You have been {verb} from {roomName} by {kicker.displayName}.<br /> + You have been {verb} from {roomName} by {kicker.name}.<br /> {reason} {rejoinBlock} <a onClick={ this.props.onForgetClick }><b>Forget</b></a> From b18473ccb28b7da707580b6ae43f8e38be7aa540 Mon Sep 17 00:00:00 2001 From: David Baker <dave@matrix.org> Date: Fri, 17 Feb 2017 16:35:18 +0000 Subject: [PATCH 5/5] Handle there being no member event when banned Here, and also in MemberEventListSummary where this also broke. --- src/components/views/elements/MemberEventListSummary.js | 2 +- src/components/views/rooms/RoomPreviewBar.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 1a73b5a50e..510d861730 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -381,7 +381,7 @@ module.exports = React.createClass({ // Initialise a user's events if (!userEvents[userId]) { userEvents[userId] = []; - avatarMembers.push(e.target); + if (e.target) avatarMembers.push(e.target); } userEvents[userId].push({ mxEvent: e, diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 3476c47f09..43c3b05295 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -143,9 +143,11 @@ module.exports = React.createClass({ } else if (kicked || banned) { const verb = kicked ? 'kicked' : 'banned'; const roomName = this._roomNameElement('this room'); - const kicker = this.props.room.currentState.getMember( + const kickerMember = this.props.room.currentState.getMember( myMember.events.member.getSender() ); + const kickerName = kickerMember ? + kickerMember.name : myMember.events.member.getSender(); let reason; if (myMember.events.member.getContent().reason) { reason = <div>Reason: {myMember.events.member.getContent().reason}</div> @@ -157,7 +159,7 @@ module.exports = React.createClass({ joinBlock = ( <div> <div className="mx_RoomPreviewBar_join_text"> - You have been {verb} from {roomName} by {kicker.name}.<br /> + You have been {verb} from {roomName} by {kickerName}.<br /> {reason} {rejoinBlock} <a onClick={ this.props.onForgetClick }><b>Forget</b></a>