diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index ee9d5f1ff4..1e0db2321d 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -229,6 +229,7 @@ module.exports = React.createClass({
_getEventTiles: function() {
var EventTile = sdk.getComponent('rooms.EventTile');
+ var DateSeparator = sdk.getComponent('messages.DateSeparator');
const MemberEventListSummary = sdk.getComponent('views.elements.MemberEventListSummary');
this.eventNodes = {};
@@ -278,8 +279,8 @@ module.exports = React.createClass({
var isMembershipChange = (e) =>
e.getType() === 'm.room.member'
- && ['join', 'leave'].indexOf(e.event.content.membership) !== -1
- && (!e.event.prev_content || e.event.content.membership !== e.event.prev_content.membership);
+ && ['join', 'leave'].indexOf(e.getContent().membership) !== -1
+ && (!e.getPrevContent() || e.getContent().membership !== e.getPrevContent().membership);
for (i = 0; i < this.props.events.length; i++) {
var mxEv = this.props.events[i];
@@ -294,23 +295,32 @@ module.exports = React.createClass({
// Wrap consecutive member events in a ListSummary
if (isMembershipChange(mxEv)) {
- let summarisedEvents = [mxEv];
- i++;
- for (;i < this.props.events.length; i++) {
- let collapsedMxEv = this.props.events[i];
+ let ts1 = mxEv.getTs();
- if (!isMembershipChange(collapsedMxEv)) {
- i--;
+ if (this._wantsDateSeparator(prevEvent, ts1)) {
+ let dateSeparator =
;
+ ret.push(dateSeparator);
+ }
+
+ let summarisedEvents = [mxEv];
+ for (;i + 1 < this.props.events.length; i++) {
+ let collapsedMxEv = this.props.events[i + 1];
+
+ if (!isMembershipChange(collapsedMxEv) ||
+ this._wantsDateSeparator(this.props.events[i], collapsedMxEv.getTs())) {
break;
}
summarisedEvents.push(collapsedMxEv);
}
- // At this point, i = this.props.events.length OR i = the index of the last
- // MembershipChange in a sequence of MembershipChanges
+ // At this point, i = the index of the last event in the summary sequence
let eventTiles = summarisedEvents.map(
(e) => {
- let ret = this._getTilesForEvent(prevEvent, e);
+ // In order to prevent DateSeparators from appearing in the expanded form
+ // of MemberEventListSummary, render each member event as if the previous
+ // one was itself. This way, the timestamp of the previous event === the
+ // timestamp of the current event, and no DateSeperator is inserted.
+ let ret = this._getTilesForEvent(e, e);
prevEvent = e;
return ret;
}
diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js
index 161c37ef55..1f6736138d 100644
--- a/src/components/views/avatars/MemberAvatar.js
+++ b/src/components/views/avatars/MemberAvatar.js
@@ -69,9 +69,9 @@ module.exports = React.createClass({
render: function() {
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
- var {member, onClick, ...otherProps} = this.props;
+ var {member, onClick, viewUserOnClick, ...otherProps} = this.props;
- if (this.props.viewUserOnClick) {
+ if (viewUserOnClick) {
onClick = () => {
dispatcher.dispatch({
action: 'view_user',
diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js
index f50f56ffb4..4a4e8bfd1e 100644
--- a/src/components/views/elements/MemberEventListSummary.js
+++ b/src/components/views/elements/MemberEventListSummary.js
@@ -107,10 +107,20 @@ module.exports = React.createClass({
);
}
+
+ // The joinEvents and leaveEvents are representative of the net movement
+ // per-user, and so it is possible that the total net movement is nil,
+ // whilst there are some events in the expanded list. If the total net
+ // movement is nil, then neither joinSummary nor leaveSummary will be
+ // truthy, so return null.
+ if (!joinSummary && !leaveSummary) {
+ return null;
+ }
+
return (
{joinSummary}{joinSummary && leaveSummary?'; ':''}
- {leaveSummary}
+ {leaveSummary}.
);
},
@@ -140,15 +150,24 @@ module.exports = React.createClass({
// Reorder events so that joins come before leaves
let eventsToRender = this.props.events;
- // Filter out those who joined, then left
- let filteredEvents = eventsToRender.filter(
- (e) => {
- return eventsToRender.filter(
- (e2) => {
- return e.getSender() === e2.getSender()
- && e.event.content.membership !== e2.event.content.membership;
- }
- ).length === 0;
+ // Create an array of events that are not "cancelled-out" by another
+ // A join of sender S is cancelled out by a leave of sender S etc.
+ let filteredEvents = [];
+ let senders = new Set(eventsToRender.map((e) => e.getSender()));
+ senders.forEach(
+ (userId) => {
+ // Only push the last event if it isn't the same membership as the first
+
+ let userEvents = eventsToRender.filter((e) => {
+ return e.getSender() === userId;
+ });
+
+ let firstEvent = userEvents[0];
+ let lastEvent = userEvents[userEvents.length - 1];
+
+ if (firstEvent.getContent().membership !== lastEvent.getContent().membership) {
+ filteredEvents.push(lastEvent);
+ }
}
);
@@ -194,7 +213,7 @@ module.exports = React.createClass({
{avatars}
- {summary}{joinAndLeft? '. ' + joinAndLeft + ' ' + noun + ' joined and left' : ''}
+ {summary}{joinAndLeft ? joinAndLeft + ' ' + noun + ' joined and left' : ''}
{toggleButton}