From cd241a4a170cbd6e971e8945175a8acdfaac347e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 8 Nov 2016 16:34:02 +0000 Subject: [PATCH 01/28] Truncate consecutive member events This is needed for the IRC bridge to be able to do full membership list syncing without cluttering the message panel. --- src/components/structures/MessagePanel.js | 51 +++++++++++++++++++ .../views/elements/TruncatedList.js | 26 ++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 31ef15b6dc..29b2f773dc 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -20,6 +20,7 @@ var dis = require("../../dispatcher"); var sdk = require('../../index'); var MatrixClientPeg = require('../../MatrixClientPeg') +var TruncatedList = require('../views/elements/TruncatedList.js'); /* (almost) stateless UI component which builds the event tiles in the room timeline. */ @@ -286,6 +287,56 @@ module.exports = React.createClass({ var last = (i == lastShownEventIndex); + // Wrap consecutive member events in a TruncatedList + if (mxEv.getType() === 'm.room.member') { + // Prevent message continuations between truncations + prevEvent = null; + + let collapsedEvents = [mxEv]; + i++; + for (;i < this.props.events.length; i++) { + let collapsedMxEv = this.props.events[i]; + + if (collapsedMxEv.getType() !== 'm.room.member') { + i--; + break; + } + collapsedEvents.push(collapsedMxEv); + } + let ePrev = null; + collapsedEvents = collapsedEvents.map( + (e) => { + let ret = this._getTilesForEvent(ePrev, e); + ePrev = e; + return ret; + } + ).reduce((a,b) => a.concat(b)); + + let overflowElement = (overflowCount, totalCount, toggleTruncate, isExpanded) => { + if (isExpanded) { + return ( +
+ collapse ^ +
+ ); + } + else { + return ( +
+ and {overflowCount} more... +
+ ); + } + } + ret.push( + + {collapsedEvents} + + ); + + wantTile = false; + } + if (wantTile) { // make sure we unpack the array returned by _getTilesForEvent, // otherwise react will auto-generate keys and we will end up diff --git a/src/components/views/elements/TruncatedList.js b/src/components/views/elements/TruncatedList.js index 3e174848d3..e49c296515 100644 --- a/src/components/views/elements/TruncatedList.js +++ b/src/components/views/elements/TruncatedList.js @@ -28,10 +28,16 @@ module.exports = React.createClass({ createOverflowElement: React.PropTypes.func }, + getInitialState: function() { + return { + enabled: true, + }; + }, + getDefaultProps: function() { return { truncateAt: 2, - createOverflowElement: function(overflowCount, totalCount) { + createOverflowElement: function(overflowCount, totalCount, toggleTruncate, isExpanded) { return (
And {overflowCount} more...
); @@ -39,6 +45,12 @@ module.exports = React.createClass({ }; }, + toggleTruncate: function() { + this.setState({ + enabled: !this.state.enabled + }); + }, + render: function() { var childsJsx = this.props.children; var overflowJsx; @@ -48,20 +60,26 @@ module.exports = React.createClass({ var childCount = childArray.length; - if (this.props.truncateAt >= 0) { + if (this.state.enabled && this.props.truncateAt >= 0) { var overflowCount = childCount - this.props.truncateAt; if (overflowCount > 1) { overflowJsx = this.props.createOverflowElement( - overflowCount, childCount + overflowCount, childCount, this.toggleTruncate ); - + // cut out the overflow elements childArray.splice(childCount - overflowCount, overflowCount); childsJsx = childArray; // use what is left } } + if (!this.state.enabled) { + overflowJsx = this.props.createOverflowElement( + 0, childCount, this.toggleTruncate, true + ); + } + return (
{childsJsx} From 2f02c4b84eca965d9a3854a9f80fa3df3b316657 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 9 Nov 2016 16:03:35 +0000 Subject: [PATCH 02/28] WIP nicer join/part folding --- src/components/structures/MessagePanel.js | 61 +++-- .../views/elements/MemberEventListSummary.js | 228 ++++++++++++++++++ 2 files changed, 255 insertions(+), 34 deletions(-) create mode 100644 src/components/views/elements/MemberEventListSummary.js diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 29b2f773dc..3b6547561e 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -20,7 +20,7 @@ var dis = require("../../dispatcher"); var sdk = require('../../index'); var MatrixClientPeg = require('../../MatrixClientPeg') -var TruncatedList = require('../views/elements/TruncatedList.js'); +var MemberEventListSummary = require('../views/elements/MemberEventListSummary.js'); /* (almost) stateless UI component which builds the event tiles in the room timeline. */ @@ -287,54 +287,47 @@ module.exports = React.createClass({ var last = (i == lastShownEventIndex); - // Wrap consecutive member events in a TruncatedList - if (mxEv.getType() === 'm.room.member') { + 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); + + // Wrap consecutive member events in a ListSummary + if (isMembershipChange(mxEv)) { // Prevent message continuations between truncations prevEvent = null; - let collapsedEvents = [mxEv]; + let summarisedEvents = [mxEv]; i++; for (;i < this.props.events.length; i++) { let collapsedMxEv = this.props.events[i]; - if (collapsedMxEv.getType() !== 'm.room.member') { + if (!isMembershipChange(collapsedMxEv)) { i--; break; } - collapsedEvents.push(collapsedMxEv); + summarisedEvents.push(collapsedMxEv); } let ePrev = null; - collapsedEvents = collapsedEvents.map( - (e) => { - let ret = this._getTilesForEvent(ePrev, e); - ePrev = e; - return ret; + let renderEvents = (events) => { + if (events.length === 0) { + return null; } - ).reduce((a,b) => a.concat(b)); - - let overflowElement = (overflowCount, totalCount, toggleTruncate, isExpanded) => { - if (isExpanded) { - return ( -
- collapse ^ -
- ); - } - else { - return ( -
- and {overflowCount} more... -
- ); - } - } + return events.map( + (e) => { + let ret = this._getTilesForEvent(ePrev, e); + ePrev = e; + return ret; + } + ).reduce((a,b) => a.concat(b)); + }; ret.push( - - {collapsedEvents} - + ); - - wantTile = false; + continue; } if (wantTile) { diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js new file mode 100644 index 0000000000..d0072fc71d --- /dev/null +++ b/src/components/views/elements/MemberEventListSummary.js @@ -0,0 +1,228 @@ +/* +Copyright 2016 OpenMarket Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const React = require('react'); +const MemberAvatar = require('../avatars/MemberAvatar.js'); +const dispatcher = require("../../../dispatcher"); + +module.exports = React.createClass({ + displayName: 'MemberEventListSummary', + + propTypes: { + // An array of member events to summarise + events: React.PropTypes.array, + // The maximum number of names to show in either the join or leave summaries + summaryLength: React.PropTypes.number, + // The maximum number of avatars to display in the summary + avatarsMaxLength: React.PropTypes.number, + // The minimum number of events needed to trigger summarisation + threshold: React.PropTypes.number, + // The function to render events if they are not being summarised + renderEvents: React.PropTypes.function, + }, + + getInitialState: function() { + return { + expanded: false, + }; + }, + + getDefaultProps: function() { + return { + summaryLength: 3, + threshold: 3, + avatarsMaxLength: 5 + }; + }, + + toggleSummary: function() { + this.setState({ + expanded: !this.state.expanded, + }); + }, + + getEventSenderName: function(ev) { + if (!ev) { + return 'undefined'; + } + return ev.sender.name || ev.event.content.displayname || ev.getSender(); + }, + + renderNameList: function(events) { + if (events.length === 0) { + return null; + } + let originalNumber = events.length; + events = events.slice(0, this.props.summaryLength); + let lastEvent = events.pop(); + + let names = events.map((ev) => { + return this.getEventSenderName(ev); + }).join(', '); + + if (names.length === 0) { + return this.getEventSenderName(lastEvent); + } + + // Special case the last name. ' and ' might be included later + // So you have two cases: + if (originalNumber <= this.props.summaryLength) { + // name1, name2 and name3 + names += ' and '; + } else { + // name1, name2, name3 [and 100 others] + names += ', '; + } + return names + this.getEventSenderName(lastEvent); + }, + + renderSummary: function(joinEvents, leaveEvents) { + let joiners = this.renderNameList(joinEvents); + let remainingJoiners = joinEvents.length - this.props.summaryLength; + + let leavers = this.renderNameList(leaveEvents); + let remainingLeavers = leaveEvents.length - this.props.summaryLength; + + let joinSummary = null; + + if (joiners) { + joinSummary = ( + + {joiners} {remainingJoiners > 0 ? 'and ' + remainingJoiners + ' others ':''}joined the room + + ); + } + + let leaveSummary = ''; + + if (leavers) { + leaveSummary = ( + + {leavers} {remainingLeavers > 0 ? 'and ' + remainingLeavers + ' others ':''}left the room + + ); + } + + return ( + + {joinSummary}{joinSummary && leaveSummary?'; ':''} + {leaveSummary} + + ); + }, + + + + renderAvatars: function(events) { + + let avatars = events.slice(0, this.props.avatarsMaxLength).map((e) => { + let onClickAvatar = () => { + dispatcher.dispatch({ + action: 'view_user', + member: e.sender, + }); + }; + return ( + + ); + }); + + return ( + + {avatars} + + ); + }, + + render: function() { + let summary = null; + + // 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; + } + ); + + let joinAndLeft = (eventsToRender.length - filteredEvents.length) / 2; + if (joinAndLeft <= 0 || joinAndLeft % 1 !== 0) { + joinAndLeft = null; + } + + let joinEvents = filteredEvents.filter((ev) => { + return ev.event.content.membership === 'join'; + }); + + let leaveEvents = filteredEvents.filter((ev) => { + return ev.event.content.membership === 'leave'; + }); + + let fewEvents = eventsToRender.length < this.props.threshold; + console.log(eventsToRender.length, joinEvents.length, leaveEvents.length, this.state.expanded, fewEvents); + + let expanded = this.state.expanded || fewEvents; + let expandedEvents = null; + + if (expanded) { + expandedEvents = this.props.renderEvents(eventsToRender); + } + + let avatars = this.renderAvatars(joinEvents.concat(leaveEvents)); + + let toggleButton = null; + let summaryContainer = null; + if (!fewEvents) { + summary = this.renderSummary(joinEvents, leaveEvents); + toggleButton = ( + {expanded?'collapse':'expand'} + ); + + summaryContainer = ( +
+
+ + {avatars} + + + {summary}{joinAndLeft? '. ' + joinAndLeft + ' others joined and left' : ''} +   + {toggleButton} +
+
+ ); + } + + return ( +
+ {summaryContainer} + {expandedEvents} +
+ ); + }, +}); From 04a934f73895032a680712c2ba342525afca8e79 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 9 Nov 2016 16:24:56 +0000 Subject: [PATCH 03/28] Trying to get rid of the date separator problem --- src/components/structures/MessagePanel.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 3b6547561e..3b0dbc03ac 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -294,8 +294,6 @@ module.exports = React.createClass({ // Wrap consecutive member events in a ListSummary if (isMembershipChange(mxEv)) { - // Prevent message continuations between truncations - prevEvent = null; let summarisedEvents = [mxEv]; i++; @@ -308,15 +306,15 @@ module.exports = React.createClass({ } summarisedEvents.push(collapsedMxEv); } - let ePrev = null; + let renderEvents = (events) => { if (events.length === 0) { return null; } return events.map( (e) => { - let ret = this._getTilesForEvent(ePrev, e); - ePrev = e; + // e, e to prevent date seperators + let ret = this._getTilesForEvent(e, e); return ret; } ).reduce((a,b) => a.concat(b)); @@ -327,6 +325,8 @@ module.exports = React.createClass({ renderEvents={renderEvents} /> ); + // Use the first member event to create scroll token + ret.push(
  • ); continue; } From 5f0b891d47dbf3313c7fd89e1aed20e07196dcdb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 9 Nov 2016 17:44:43 +0000 Subject: [PATCH 04/28] Add date seperator to the expanded events netsplits across midnight is not handled, and @richvdh suggested splitting the list in two --- src/components/structures/MessagePanel.js | 12 +++++------- .../views/elements/MemberEventListSummary.js | 3 ++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 3b0dbc03ac..b7e8a22669 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -294,7 +294,6 @@ 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++) { @@ -306,15 +305,14 @@ module.exports = React.createClass({ } summarisedEvents.push(collapsedMxEv); } - - let renderEvents = (events) => { + let renderEvents = (pEvent, events) => { if (events.length === 0) { return null; } return events.map( (e) => { - // e, e to prevent date seperators - let ret = this._getTilesForEvent(e, e); + let ret = this._getTilesForEvent(pEvent, e); + pEvent = e; return ret; } ).reduce((a,b) => a.concat(b)); @@ -322,11 +320,11 @@ module.exports = React.createClass({ ret.push( ); - // Use the first member event to create scroll token - ret.push(
  • ); + prevEvent = mxEv; continue; } diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index d0072fc71d..c563a7d420 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -31,6 +31,7 @@ module.exports = React.createClass({ threshold: React.PropTypes.number, // The function to render events if they are not being summarised renderEvents: React.PropTypes.function, + previousEvent: React.PropTypes.object, }, getInitialState: function() { @@ -190,7 +191,7 @@ module.exports = React.createClass({ let expandedEvents = null; if (expanded) { - expandedEvents = this.props.renderEvents(eventsToRender); + expandedEvents = this.props.renderEvents(this.props.previousEvent, eventsToRender); } let avatars = this.renderAvatars(joinEvents.concat(leaveEvents)); From f5bc8d1fe05a82b653e82539c419952fbc9ecbd9 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 10:42:33 +0000 Subject: [PATCH 05/28] Removed logs, updated phrasing on 'others joined' Now it's: 1 user joined and left >1 others joined and left --- src/components/views/elements/MemberEventListSummary.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index c563a7d420..26696ccf40 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -185,8 +185,6 @@ module.exports = React.createClass({ }); let fewEvents = eventsToRender.length < this.props.threshold; - console.log(eventsToRender.length, joinEvents.length, leaveEvents.length, this.state.expanded, fewEvents); - let expanded = this.state.expanded || fewEvents; let expandedEvents = null; @@ -204,6 +202,8 @@ module.exports = React.createClass({ {expanded?'collapse':'expand'} ); + let noun = (joinAndLeft === 1 ? 'user' : 'others'); + summaryContainer = (
    @@ -211,7 +211,7 @@ module.exports = React.createClass({ {avatars} - {summary}{joinAndLeft? '. ' + joinAndLeft + ' others joined and left' : ''} + {summary}{joinAndLeft? '. ' + joinAndLeft + ' ' + noun + ' joined and left' : ''}   {toggleButton}
    From 79c01fa1a492e1af57b7eee191c5edcef6bbc3de Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 11:03:43 +0000 Subject: [PATCH 06/28] Remove empty lines --- .../views/elements/MemberEventListSummary.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 26696ccf40..d753fcc007 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -92,12 +92,9 @@ module.exports = React.createClass({ renderSummary: function(joinEvents, leaveEvents) { let joiners = this.renderNameList(joinEvents); let remainingJoiners = joinEvents.length - this.props.summaryLength; - let leavers = this.renderNameList(leaveEvents); let remainingLeavers = leaveEvents.length - this.props.summaryLength; - let joinSummary = null; - if (joiners) { joinSummary = ( @@ -105,9 +102,7 @@ module.exports = React.createClass({ ); } - let leaveSummary = ''; - if (leavers) { leaveSummary = ( @@ -115,7 +110,6 @@ module.exports = React.createClass({ ); } - return ( {joinSummary}{joinSummary && leaveSummary?'; ':''} @@ -124,10 +118,7 @@ module.exports = React.createClass({ ); }, - - renderAvatars: function(events) { - let avatars = events.slice(0, this.props.avatarsMaxLength).map((e) => { let onClickAvatar = () => { dispatcher.dispatch({ @@ -201,7 +192,6 @@ module.exports = React.createClass({ toggleButton = ( {expanded?'collapse':'expand'} ); - let noun = (joinAndLeft === 1 ? 'user' : 'others'); summaryContainer = ( From d01bb0b78f647249470d3930d9f06712a6854093 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 13:01:48 +0000 Subject: [PATCH 07/28] Use sdk.getComponent --- src/components/structures/MessagePanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index b7e8a22669..cf25ff88a2 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -20,7 +20,6 @@ var dis = require("../../dispatcher"); var sdk = require('../../index'); var MatrixClientPeg = require('../../MatrixClientPeg') -var MemberEventListSummary = require('../views/elements/MemberEventListSummary.js'); /* (almost) stateless UI component which builds the event tiles in the room timeline. */ @@ -230,6 +229,7 @@ module.exports = React.createClass({ _getEventTiles: function() { var EventTile = sdk.getComponent('rooms.EventTile'); + const MemberEventListSummary = sdk.getComponent('views.elements.MemberEventListSummary'); this.eventNodes = {}; From 0ec5eebfc9e8e2116f77fa926b8dd9bfe31b9197 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 13:03:17 +0000 Subject: [PATCH 08/28] Hoist isMembershipChange out of for loop --- src/components/structures/MessagePanel.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index cf25ff88a2..5e79232e75 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -276,6 +276,11 @@ module.exports = React.createClass({ this.currentGhostEventId = null; } + 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); + for (i = 0; i < this.props.events.length; i++) { var mxEv = this.props.events[i]; var wantTile = true; @@ -287,11 +292,6 @@ module.exports = React.createClass({ var last = (i == lastShownEventIndex); - 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); - // Wrap consecutive member events in a ListSummary if (isMembershipChange(mxEv)) { let summarisedEvents = [mxEv]; From 764959ec1cb80a1918a8b66edb5e1f260c75eb98 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 13:14:04 +0000 Subject: [PATCH 09/28] Comment on i after membershipchanges --- src/components/structures/MessagePanel.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 5e79232e75..64b3fecaab 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -305,6 +305,9 @@ module.exports = React.createClass({ } summarisedEvents.push(collapsedMxEv); } + // At this point, i = this.props.events.length OR i = the index of the first event + // to NOT be a MembershipChange after a sequence of MembershipChanges + let renderEvents = (pEvent, events) => { if (events.length === 0) { return null; From 566034cf2b0b519b00c98623e429e374b81d955e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 13:25:48 +0000 Subject: [PATCH 10/28] Render children EventTiles before passing to summary element --- src/components/structures/MessagePanel.js | 11 ++++++----- .../views/elements/MemberEventListSummary.js | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 64b3fecaab..71eb422c83 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -320,12 +320,13 @@ module.exports = React.createClass({ } ).reduce((a,b) => a.concat(b)); }; + + let eventTiles = renderEvents(prevEvent, summarisedEvents); + ret.push( - + + {eventTiles} + ); prevEvent = mxEv; continue; diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index d753fcc007..c0034bf264 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -180,7 +180,7 @@ module.exports = React.createClass({ let expandedEvents = null; if (expanded) { - expandedEvents = this.props.renderEvents(this.props.previousEvent, eventsToRender); + expandedEvents = this.props.children; } let avatars = this.renderAvatars(joinEvents.concat(leaveEvents)); From e2936376b6508e38794f36bf480517989ac8c979 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 13:26:27 +0000 Subject: [PATCH 11/28] Unnecessary props --- src/components/views/elements/MemberEventListSummary.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index c0034bf264..da34a4cdc9 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -29,9 +29,6 @@ module.exports = React.createClass({ avatarsMaxLength: React.PropTypes.number, // The minimum number of events needed to trigger summarisation threshold: React.PropTypes.number, - // The function to render events if they are not being summarised - renderEvents: React.PropTypes.function, - previousEvent: React.PropTypes.object, }, getInitialState: function() { From dcbb31279fa9a08aa1c78da1b44ce3eea0ff0d73 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 14:08:11 +0000 Subject: [PATCH 12/28] Prefer import React, set prevEvent to last MemberhsipChange --- src/components/structures/MessagePanel.js | 3 ++- src/components/views/elements/MemberEventListSummary.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 71eb422c83..e5cb38b267 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -328,7 +328,8 @@ module.exports = React.createClass({ {eventTiles} ); - prevEvent = mxEv; + // Set previous event to last MembershipChange + prevEvent = this.props.events[i - 1]; continue; } diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index da34a4cdc9..b7ce3ea915 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const React = require('react'); +import React from 'react'; const MemberAvatar = require('../avatars/MemberAvatar.js'); const dispatcher = require("../../../dispatcher"); From 84220178271db50785b0b70d6b48d049a25380eb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 14:09:40 +0000 Subject: [PATCH 13/28] events are required --- src/components/views/elements/MemberEventListSummary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index b7ce3ea915..98855af851 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -22,7 +22,7 @@ module.exports = React.createClass({ propTypes: { // An array of member events to summarise - events: React.PropTypes.array, + events: React.PropTypes.array.isRequired, // The maximum number of names to show in either the join or leave summaries summaryLength: React.PropTypes.number, // The maximum number of avatars to display in the summary From 370f5f0a11c8c09aab9f45742224d4f0f1507e4e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 14:12:05 +0000 Subject: [PATCH 14/28] Use _ prefix for private methods --- .../views/elements/MemberEventListSummary.js | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 98855af851..f8c19093c2 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -45,20 +45,20 @@ module.exports = React.createClass({ }; }, - toggleSummary: function() { + _toggleSummary: function() { this.setState({ expanded: !this.state.expanded, }); }, - getEventSenderName: function(ev) { + _getEventSenderName: function(ev) { if (!ev) { return 'undefined'; } return ev.sender.name || ev.event.content.displayname || ev.getSender(); }, - renderNameList: function(events) { + _renderNameList: function(events) { if (events.length === 0) { return null; } @@ -67,11 +67,11 @@ module.exports = React.createClass({ let lastEvent = events.pop(); let names = events.map((ev) => { - return this.getEventSenderName(ev); + return this._getEventSenderName(ev); }).join(', '); if (names.length === 0) { - return this.getEventSenderName(lastEvent); + return this._getEventSenderName(lastEvent); } // Special case the last name. ' and ' might be included later @@ -83,13 +83,13 @@ module.exports = React.createClass({ // name1, name2, name3 [and 100 others] names += ', '; } - return names + this.getEventSenderName(lastEvent); + return names + this._getEventSenderName(lastEvent); }, - renderSummary: function(joinEvents, leaveEvents) { - let joiners = this.renderNameList(joinEvents); + _renderSummary: function(joinEvents, leaveEvents) { + let joiners = this._renderNameList(joinEvents); let remainingJoiners = joinEvents.length - this.props.summaryLength; - let leavers = this.renderNameList(leaveEvents); + let leavers = this._renderNameList(leaveEvents); let remainingLeavers = leaveEvents.length - this.props.summaryLength; let joinSummary = null; if (joiners) { @@ -115,7 +115,7 @@ module.exports = React.createClass({ ); }, - renderAvatars: function(events) { + _renderAvatars: function(events) { let avatars = events.slice(0, this.props.avatarsMaxLength).map((e) => { let onClickAvatar = () => { dispatcher.dispatch({ @@ -180,14 +180,14 @@ module.exports = React.createClass({ expandedEvents = this.props.children; } - let avatars = this.renderAvatars(joinEvents.concat(leaveEvents)); + let avatars = this._renderAvatars(joinEvents.concat(leaveEvents)); let toggleButton = null; let summaryContainer = null; if (!fewEvents) { - summary = this.renderSummary(joinEvents, leaveEvents); + summary = this._renderSummary(joinEvents, leaveEvents); toggleButton = ( - {expanded?'collapse':'expand'} + {expanded?'collapse':'expand'} ); let noun = (joinAndLeft === 1 ? 'user' : 'others'); From d6b74becfc8baf57fd908812e5edb65616c6d6f8 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 14:12:45 +0000 Subject: [PATCH 15/28] Children are required --- src/components/views/elements/MemberEventListSummary.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index f8c19093c2..e141a32671 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -23,6 +23,8 @@ module.exports = React.createClass({ propTypes: { // An array of member events to summarise events: React.PropTypes.array.isRequired, + // An array of EventTiles to render when expanded + children: React.PropTypes.array.isRequired, // The maximum number of names to show in either the join or leave summaries summaryLength: React.PropTypes.number, // The maximum number of avatars to display in the summary From 6b2aa43b712e0fb247571916de24f494e4d0789b Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 14:33:41 +0000 Subject: [PATCH 16/28] Factor out "and others" --- .../views/elements/MemberEventListSummary.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index e141a32671..af067dba4b 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -85,19 +85,22 @@ module.exports = React.createClass({ // name1, name2, name3 [and 100 others] names += ', '; } - return names + this._getEventSenderName(lastEvent); + + let remaining = originalNumber - this.props.summaryLength; + let remainingDesc = (remaining > 0 ? 'and ' + remaining + ' others ':''); + + return names + this._getEventSenderName(lastEvent) + remainingDesc; }, _renderSummary: function(joinEvents, leaveEvents) { let joiners = this._renderNameList(joinEvents); - let remainingJoiners = joinEvents.length - this.props.summaryLength; let leavers = this._renderNameList(leaveEvents); - let remainingLeavers = leaveEvents.length - this.props.summaryLength; + let joinSummary = null; if (joiners) { joinSummary = ( - {joiners} {remainingJoiners > 0 ? 'and ' + remainingJoiners + ' others ':''}joined the room + {joiners} joined the room ); } @@ -105,7 +108,7 @@ module.exports = React.createClass({ if (leavers) { leaveSummary = ( - {leavers} {remainingLeavers > 0 ? 'and ' + remainingLeavers + ' others ':''}left the room + {leavers} left the room ); } From d8bc4d9a6f35f4214feaffb9af63cc0b0f6e2630 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 15:18:59 +0000 Subject: [PATCH 17/28] Factor out avatar click leads to view_user --- src/components/views/avatars/MemberAvatar.js | 20 ++++++++++++++++--- .../views/elements/MemberEventListSummary.js | 8 -------- src/components/views/rooms/EventTile.js | 9 +-------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js index 6e1670604e..5062a35e21 100644 --- a/src/components/views/avatars/MemberAvatar.js +++ b/src/components/views/avatars/MemberAvatar.js @@ -19,6 +19,7 @@ limitations under the License. var React = require('react'); var Avatar = require('../../../Avatar'); var sdk = require("../../../index"); +const dispatcher = require("../../../dispatcher"); module.exports = React.createClass({ displayName: 'MemberAvatar', @@ -27,14 +28,17 @@ module.exports = React.createClass({ member: React.PropTypes.object.isRequired, width: React.PropTypes.number, height: React.PropTypes.number, - resizeMethod: React.PropTypes.string + resizeMethod: React.PropTypes.string, + // Whether the onClick of the avatar should dispatch 'view_user' + viewUserOnClick: React.PropTypes.boolean }, getDefaultProps: function() { return { width: 40, height: 40, - resizeMethod: 'crop' + resizeMethod: 'crop', + viewUserOnClick: false } }, @@ -65,9 +69,19 @@ module.exports = React.createClass({ var {member, ...otherProps} = this.props; + var onClick = null; + if (this.props.viewUserOnClick) { + onClick = () => { + dispatcher.dispatch({ + action: 'view_user', + member: this.props.member, + }); + } + } + return ( + idName={member.userId} url={this.state.imageUrl} onClick={onClick}/> ); } }); diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index af067dba4b..334d461e48 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -15,7 +15,6 @@ limitations under the License. */ import React from 'react'; const MemberAvatar = require('../avatars/MemberAvatar.js'); -const dispatcher = require("../../../dispatcher"); module.exports = React.createClass({ displayName: 'MemberEventListSummary', @@ -122,19 +121,12 @@ module.exports = React.createClass({ _renderAvatars: function(events) { let avatars = events.slice(0, this.props.avatarsMaxLength).map((e) => { - let onClickAvatar = () => { - dispatcher.dispatch({ - action: 'view_user', - member: e.sender, - }); - }; return ( ); }); diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index fb97d863cd..f4167b32f6 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -348,13 +348,6 @@ module.exports = React.createClass({ ; }, - onMemberAvatarClick: function(event) { - dispatcher.dispatch({ - action: 'view_user', - member: this.props.mxEvent.sender, - }); - }, - onSenderProfileClick: function(event) { var mxEvent = this.props.mxEvent; dispatcher.dispatch({ @@ -443,7 +436,7 @@ module.exports = React.createClass({
    ); From 1a4df38500b511f4101c83ec85708065ddbe0085 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 15:20:53 +0000 Subject: [PATCH 18/28] remove href --- src/components/views/elements/MemberEventListSummary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 334d461e48..0ecdecb4ee 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -184,7 +184,7 @@ module.exports = React.createClass({ if (!fewEvents) { summary = this._renderSummary(joinEvents, leaveEvents); toggleButton = ( - {expanded?'collapse':'expand'} + {expanded?'collapse':'expand'} ); let noun = (joinAndLeft === 1 ? 'user' : 'others'); From f71ac939463eb28e0cd264695711fb9f64fbe1cd Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 15:38:20 +0000 Subject: [PATCH 19/28] Prefer null to falsy, use correct plural --- src/components/views/elements/MemberEventListSummary.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 0ecdecb4ee..109dd0e740 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -103,7 +103,7 @@ module.exports = React.createClass({ ); } - let leaveSummary = ''; + let leaveSummary = null; if (leavers) { leaveSummary = ( @@ -186,7 +186,8 @@ module.exports = React.createClass({ toggleButton = ( {expanded?'collapse':'expand'} ); - let noun = (joinAndLeft === 1 ? 'user' : 'others'); + let plural = (joinEvents.length + leaveEvents.length > 0) ? 'others' : 'users'; + let noun = (joinAndLeft === 1 ? 'user' : plural); summaryContainer = (
    From ac460122cca6d17d0ab3b25c1a4c1792d5c24533 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 15:51:27 +0000 Subject: [PATCH 20/28] revert now redundant TruncatedList edits --- .../views/elements/TruncatedList.js | 26 +++---------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/src/components/views/elements/TruncatedList.js b/src/components/views/elements/TruncatedList.js index e49c296515..3e174848d3 100644 --- a/src/components/views/elements/TruncatedList.js +++ b/src/components/views/elements/TruncatedList.js @@ -28,16 +28,10 @@ module.exports = React.createClass({ createOverflowElement: React.PropTypes.func }, - getInitialState: function() { - return { - enabled: true, - }; - }, - getDefaultProps: function() { return { truncateAt: 2, - createOverflowElement: function(overflowCount, totalCount, toggleTruncate, isExpanded) { + createOverflowElement: function(overflowCount, totalCount) { return (
    And {overflowCount} more...
    ); @@ -45,12 +39,6 @@ module.exports = React.createClass({ }; }, - toggleTruncate: function() { - this.setState({ - enabled: !this.state.enabled - }); - }, - render: function() { var childsJsx = this.props.children; var overflowJsx; @@ -60,26 +48,20 @@ module.exports = React.createClass({ var childCount = childArray.length; - if (this.state.enabled && this.props.truncateAt >= 0) { + if (this.props.truncateAt >= 0) { var overflowCount = childCount - this.props.truncateAt; if (overflowCount > 1) { overflowJsx = this.props.createOverflowElement( - overflowCount, childCount, this.toggleTruncate + overflowCount, childCount ); - + // cut out the overflow elements childArray.splice(childCount - overflowCount, overflowCount); childsJsx = childArray; // use what is left } } - if (!this.state.enabled) { - overflowJsx = this.props.createOverflowElement( - 0, childCount, this.toggleTruncate, true - ); - } - return (
    {childsJsx} From e05aeb35a1398bc8997604dc2af729c8ef2b2371 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:03:24 +0000 Subject: [PATCH 21/28] npm run reskindex --- src/component-index.js | 2 ++ src/components/views/elements/MemberEventListSummary.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/component-index.js b/src/component-index.js index 50a02e0862..bc3d698cac 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -105,6 +105,8 @@ import views$elements$EditableTextContainer from './components/views/elements/Ed views$elements$EditableTextContainer && (module.exports.components['views.elements.EditableTextContainer'] = views$elements$EditableTextContainer); import views$elements$EmojiText from './components/views/elements/EmojiText'; views$elements$EmojiText && (module.exports.components['views.elements.EmojiText'] = views$elements$EmojiText); +import views$elements$MemberEventListSummary from './components/views/elements/MemberEventListSummary'; +views$elements$MemberEventListSummary && (module.exports.components['views.elements.MemberEventListSummary'] = views$elements$MemberEventListSummary); import views$elements$PowerSelector from './components/views/elements/PowerSelector'; views$elements$PowerSelector && (module.exports.components['views.elements.PowerSelector'] = views$elements$PowerSelector); import views$elements$ProgressBar from './components/views/elements/ProgressBar'; diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 109dd0e740..53b715d623 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -86,7 +86,7 @@ module.exports = React.createClass({ } let remaining = originalNumber - this.props.summaryLength; - let remainingDesc = (remaining > 0 ? 'and ' + remaining + ' others ':''); + let remainingDesc = (remaining > 0 ? ' and ' + remaining + ' others ':''); return names + this._getEventSenderName(lastEvent) + remainingDesc; }, From b11dd9542fb55334d9509332a5c1d3a8a4290551 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:09:18 +0000 Subject: [PATCH 22/28] Add class to expand link for pointer and colour --- src/components/views/elements/MemberEventListSummary.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 53b715d623..da44d0063f 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -184,7 +184,9 @@ module.exports = React.createClass({ if (!fewEvents) { summary = this._renderSummary(joinEvents, leaveEvents); toggleButton = ( - {expanded?'collapse':'expand'} + + {expanded ? 'collapse' : 'expand'} + ); let plural = (joinEvents.length + leaveEvents.length > 0) ? 'others' : 'users'; let noun = (joinAndLeft === 1 ? 'user' : plural); From d2d7ebc97910e1ea47b8cd14b41af6527d719c25 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:22:16 +0000 Subject: [PATCH 23/28] correct comment --- src/components/structures/MessagePanel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index e5cb38b267..ed65314890 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -305,8 +305,8 @@ module.exports = React.createClass({ } summarisedEvents.push(collapsedMxEv); } - // At this point, i = this.props.events.length OR i = the index of the first event - // to NOT be a MembershipChange after a sequence of MembershipChanges + // At this point, i = this.props.events.length OR i = the index of the last + // MembershipChange in a sequence of MembershipChanges let renderEvents = (pEvent, events) => { if (events.length === 0) { From 3ec7940d12efa149c9be548c2adb104faa2eb6e1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:26:36 +0000 Subject: [PATCH 24/28] Inline renderEvents --- src/components/structures/MessagePanel.js | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index ed65314890..298372a4d8 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -308,28 +308,23 @@ module.exports = React.createClass({ // At this point, i = this.props.events.length OR i = the index of the last // MembershipChange in a sequence of MembershipChanges - let renderEvents = (pEvent, events) => { - if (events.length === 0) { - return null; + let eventTiles = summarisedEvents.map( + (e) => { + let ret = this._getTilesForEvent(prevEvent, e); + prevEvent = e; + return ret; } - return events.map( - (e) => { - let ret = this._getTilesForEvent(pEvent, e); - pEvent = e; - return ret; - } - ).reduce((a,b) => a.concat(b)); - }; + ).reduce((a,b) => a.concat(b)); - let eventTiles = renderEvents(prevEvent, summarisedEvents); + if (eventTiles.length === 0) { + eventTiles = null; + } ret.push( {eventTiles} ); - // Set previous event to last MembershipChange - prevEvent = this.props.events[i - 1]; continue; } From 87e8f0e4dac5cd61a46de184fde4ea17db222a87 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:27:59 +0000 Subject: [PATCH 25/28] trailing commas --- src/components/views/avatars/MemberAvatar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js index 5062a35e21..68730ed3ea 100644 --- a/src/components/views/avatars/MemberAvatar.js +++ b/src/components/views/avatars/MemberAvatar.js @@ -30,7 +30,7 @@ module.exports = React.createClass({ height: React.PropTypes.number, resizeMethod: React.PropTypes.string, // Whether the onClick of the avatar should dispatch 'view_user' - viewUserOnClick: React.PropTypes.boolean + viewUserOnClick: React.PropTypes.boolean, }, getDefaultProps: function() { @@ -38,7 +38,7 @@ module.exports = React.createClass({ width: 40, height: 40, resizeMethod: 'crop', - viewUserOnClick: false + viewUserOnClick: false, } }, From 0695037f5f3f783e1944f151685ef86566e0579c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:30:35 +0000 Subject: [PATCH 26/28] pass in prop onClick by default --- src/components/views/avatars/MemberAvatar.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js index 68730ed3ea..7f9630d416 100644 --- a/src/components/views/avatars/MemberAvatar.js +++ b/src/components/views/avatars/MemberAvatar.js @@ -29,7 +29,9 @@ module.exports = React.createClass({ width: React.PropTypes.number, height: React.PropTypes.number, resizeMethod: React.PropTypes.string, - // Whether the onClick of the avatar should dispatch 'view_user' + // The onClick to give the avatar + onClick: React.PropTypes.function, + // Whether the onClick of the avatar should be overriden to dispatch 'view_user' viewUserOnClick: React.PropTypes.boolean, }, @@ -67,9 +69,8 @@ module.exports = React.createClass({ render: function() { var BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); - var {member, ...otherProps} = this.props; + var {member, onClick, ...otherProps} = this.props; - var onClick = null; if (this.props.viewUserOnClick) { onClick = () => { dispatcher.dispatch({ From 3d7f6919cf36d6edb60e6ccb16ed909e5c40fe1c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 17:36:22 +0000 Subject: [PATCH 27/28] Refactor renderNameList (thanks, @richvdh) --- .../views/elements/MemberEventListSummary.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index da44d0063f..a80d4fea81 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -75,20 +75,20 @@ module.exports = React.createClass({ return this._getEventSenderName(lastEvent); } - // Special case the last name. ' and ' might be included later - // So you have two cases: - if (originalNumber <= this.props.summaryLength) { - // name1, name2 and name3 - names += ' and '; - } else { - // name1, name2, name3 [and 100 others] - names += ', '; + let lastName = this._getEventSenderName(lastEvent); + if (names.length === 0) { + // special-case for a single event + return lastName; } let remaining = originalNumber - this.props.summaryLength; - let remainingDesc = (remaining > 0 ? ' and ' + remaining + ' others ':''); - - return names + this._getEventSenderName(lastEvent) + remainingDesc; + if (remaining > 0) { + // name1, name2, name3, and 100 others + return names + ', ' + lastName + ', and ' + remaining + ' others'; + } else { + // name1, name2 and name3 + return names + ' and ' + lastName; + } }, _renderSummary: function(joinEvents, leaveEvents) { From d3a548773ae5f35fedbd650ba5a5bb282e97e89e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 10 Nov 2016 18:01:34 +0000 Subject: [PATCH 28/28] Remove redundant lines --- src/components/views/elements/MemberEventListSummary.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index a80d4fea81..f50f56ffb4 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -71,10 +71,6 @@ module.exports = React.createClass({ return this._getEventSenderName(ev); }).join(', '); - if (names.length === 0) { - return this._getEventSenderName(lastEvent); - } - let lastName = this._getEventSenderName(lastEvent); if (names.length === 0) { // special-case for a single event