diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index be6663be67..b6944a3d4e 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -26,12 +26,16 @@ limitations under the License.
* 'isTargetMod': boolean
*/
var React = require('react');
+var classNames = require('classnames');
var MatrixClientPeg = require("../../../MatrixClientPeg");
var dis = require("../../../dispatcher");
var Modal = require("../../../Modal");
var sdk = require('../../../index');
var UserSettingsStore = require('../../../UserSettingsStore');
var createRoom = require('../../../createRoom');
+var DMRoomMap = require('../../../utils/DMRoomMap');
+var Unread = require('../../../Unread');
+var Receipt = require('../../../utils/Receipt');
module.exports = React.createClass({
displayName: 'MemberInfo',
@@ -60,7 +64,6 @@ module.exports = React.createClass({
updating: 0,
devicesLoading: true,
devices: null,
- existingOneToOneRoomId: null,
}
},
@@ -72,14 +75,20 @@ module.exports = React.createClass({
this._enableDevices = MatrixClientPeg.get().isCryptoEnabled() &&
UserSettingsStore.isFeatureEnabled("e2e_encryption");
- this.setState({
- existingOneToOneRoomId: this.getExistingOneToOneRoomId()
- });
+ const cli = MatrixClientPeg.get();
+ cli.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
+ cli.on("Room", this.onRoom);
+ cli.on("deleteRoom", this.onDeleteRoom);
+ cli.on("Room.timeline", this.onRoomTimeline);
+ cli.on("Room.name", this.onRoomName);
+ cli.on("Room.receipt", this.onRoomReceipt);
+ cli.on("RoomState.events", this.onRoomStateEvents);
+ cli.on("RoomMember.name", this.onRoomMemberName);
+ cli.on("accountData", this.onAccountData);
},
componentDidMount: function() {
this._updateStateForNewMember(this.props.member);
- MatrixClientPeg.get().on("deviceVerificationChanged", this.onDeviceVerificationChanged);
},
componentWillReceiveProps: function(newProps) {
@@ -92,65 +101,20 @@ module.exports = React.createClass({
var client = MatrixClientPeg.get();
if (client) {
client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
+ client.removeListener("Room", this.onRoom);
+ client.removeListener("deleteRoom", this.onDeleteRoom);
+ client.removeListener("Room.timeline", this.onRoomTimeline);
+ client.removeListener("Room.name", this.onRoomName);
+ client.removeListener("Room.receipt", this.onRoomReceipt);
+ client.removeListener("RoomState.events", this.onRoomStateEvents);
+ client.removeListener("RoomMember.name", this.onRoomMemberName);
+ client.removeListener("accountData", this.onAccountData);
}
if (this._cancelDeviceList) {
this._cancelDeviceList();
}
},
- getExistingOneToOneRoomId: function() {
- const rooms = MatrixClientPeg.get().getRooms();
- const userIds = [
- this.props.member.userId,
- MatrixClientPeg.get().credentials.userId
- ];
- let existingRoomId = null;
- let invitedRoomId = null;
-
- // roomId can be null here because of a hack in MatrixChat.onUserClick where we
- // abuse this to view users rather than room members.
- let currentMembers;
- if (this.props.member.roomId) {
- const currentRoom = MatrixClientPeg.get().getRoom(this.props.member.roomId);
- currentMembers = currentRoom.getJoinedMembers();
- }
-
- // reuse the first private 1:1 we find
- existingRoomId = null;
-
- for (let i = 0; i < rooms.length; i++) {
- // don't try to reuse public 1:1 rooms
- const join_rules = rooms[i].currentState.getStateEvents("m.room.join_rules", '');
- if (join_rules && join_rules.getContent().join_rule === 'public') continue;
-
- const members = rooms[i].getJoinedMembers();
- if (members.length === 2 &&
- userIds.indexOf(members[0].userId) !== -1 &&
- userIds.indexOf(members[1].userId) !== -1)
- {
- existingRoomId = rooms[i].roomId;
- break;
- }
-
- const invited = rooms[i].getMembersWithMembership('invite');
- if (members.length === 1 &&
- invited.length === 1 &&
- userIds.indexOf(members[0].userId) !== -1 &&
- userIds.indexOf(invited[0].userId) !== -1 &&
- invitedRoomId === null)
- {
- invitedRoomId = rooms[i].roomId;
- // keep looking: we'll use this one if there's nothing better
- }
- }
-
- if (existingRoomId === null) {
- existingRoomId = invitedRoomId;
- }
-
- return existingRoomId;
- },
-
onDeviceVerificationChanged: function(userId, device) {
if (!this._enableDevices) {
return;
@@ -164,6 +128,45 @@ module.exports = React.createClass({
}
},
+ onRoom: function(room) {
+ this.forceUpdate();
+ },
+
+ onDeleteRoom: function(roomId) {
+ this.forceUpdate();
+ },
+
+ onRoomTimeline: function(ev, room, toStartOfTimeline) {
+ if (toStartOfTimeline) return;
+ this.forceUpdate();
+ },
+
+ onRoomName: function(room) {
+ this.forceUpdate();
+ },
+
+ onRoomReceipt: function(receiptEvent, room) {
+ // because if we read a notification, it will affect notification count
+ // only bother updating if there's a receipt from us
+ if (Receipt.findReadReceiptFromUserId(receiptEvent, MatrixClientPeg.get().credentials.userId)) {
+ this.forceUpdate();
+ }
+ },
+
+ onRoomStateEvents: function(ev, state) {
+ this.forceUpdate();
+ },
+
+ onRoomMemberName: function(ev, member) {
+ this.forceUpdate();
+ },
+
+ onAccountData: function(ev) {
+ if (ev.getType() == 'm.direct') {
+ this.forceUpdate();
+ }
+ },
+
_updateStateForNewMember: function(member) {
var newState = this._calculateOpsPermissions(member);
newState.devicesLoading = true;
@@ -416,33 +419,16 @@ module.exports = React.createClass({
}
},
- onChatClick: function() {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
-
- // TODO: keep existingOneToOneRoomId updated if we see any room member changes anywhere
-
- const useExistingOneToOneRoom = this.state.existingOneToOneRoomId && (this.state.existingOneToOneRoomId !== this.props.member.roomId);
-
- // check if there are any existing rooms with just us and them (1:1)
- // If so, just view that room. If not, create a private room with them.
- if (useExistingOneToOneRoom) {
- dis.dispatch({
- action: 'view_room',
- room_id: this.state.existingOneToOneRoomId,
- });
+ onNewDMClick: function() {
+ this.setState({ updating: this.state.updating + 1 });
+ createRoom({
+ createOpts: {
+ invite: [this.props.member.userId],
+ },
+ }).finally(() => {
this.props.onFinished();
- }
- else {
- this.setState({ updating: this.state.updating + 1 });
- createRoom({
- createOpts: {
- invite: [this.props.member.userId],
- },
- }).finally(() => {
- this.props.onFinished();
- this.setState({ updating: this.state.updating - 1 });
- }).done();
- }
+ this.setState({ updating: this.state.updating - 1 });
+ }).done();
},
onLeaveClick: function() {
@@ -583,24 +569,50 @@ module.exports = React.createClass({
render: function() {
var startChat, kickButton, banButton, muteButton, giveModButton, spinner;
if (this.props.member.userId !== MatrixClientPeg.get().credentials.userId) {
- // FIXME: we're referring to a vector component from react-sdk
- var BottomLeftMenuTile = sdk.getComponent('rooms.BottomLeftMenuTile');
+ const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
+ const dmRooms = dmRoomMap.getDMRoomsForUserId(this.props.member.userId);
- var label;
- if (this.state.existingOneToOneRoomId) {
- if (this.state.existingOneToOneRoomId == this.props.member.roomId) {
- label = "Start new direct chat";
- }
- else {
- label = "Go to direct chat";
+ const RoomTile = sdk.getComponent("rooms.RoomTile");
+
+ const tiles = [];
+ for (const roomId of dmRooms) {
+ const room = MatrixClientPeg.get().getRoom(roomId);
+ if (room) {
+ const me = room.getMember(MatrixClientPeg.get().credentials.userId);
+ const highlight = (
+ room.getUnreadNotificationCount('highlight') > 0 ||
+ me.membership == "invite"
+ );
+ tiles.push(
+