From db09d3d9e46f1013e9fe193394df632f6a9fd9e6 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Mon, 15 Feb 2016 09:50:12 +0000 Subject: [PATCH] Move ghost-read-marker logic to MessagePanel --- src/components/structures/MessagePanel.js | 51 +++++++++++++++++----- src/components/structures/TimelinePanel.js | 3 -- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index f6c5cfc898..75ca902fc3 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -17,7 +17,7 @@ limitations under the License. var React = require('react'); var sdk = require('../../index'); -/* stateless UI component which builds the event tiles in the room timeline. +/* (almost) stateless UI component which builds the event tiles in the room timeline. */ module.exports = React.createClass({ displayName: 'MessagePanel', @@ -35,10 +35,6 @@ module.exports = React.createClass({ // event after which we should show a read marker readMarkerEventId: React.PropTypes.string, - // event after which we should show an animating disappearance of a - // read marker - readMarkerGhostEventId: React.PropTypes.string, - // the userid of our user. This is used to suppress the read marker // for pending messages. ourUserId: React.PropTypes.string, @@ -63,6 +59,17 @@ module.exports = React.createClass({ onFillRequest: React.PropTypes.func, }, + componentWillMount: function() { + // the event after which we put a visible unread marker on the last + // render cycle; null if readMarkerVisible was false or the RM was + // suppressed (eg because it was at the end of the timeline) + this.currentReadMarkerEventId = null; + + // the event after which we are showing a disappearing read marker + // animation + this.currentGhostEventId = null; + }, + /* get the DOM node representing the given event */ getNodeForEventId: function(eventId) { if (!this.eventNodes) { @@ -158,11 +165,16 @@ module.exports = React.createClass({ } var eventId = mxEv.getId(); - if (eventId == this.props.readMarkerGhostEventId) { - ghostIndex = eventsToShow.length; - } if (eventId == this.props.readMarkerEventId) { readMarkerIndex = eventsToShow.length; + } else if (eventId == this.currentReadMarkerEventId && !this.currentGhostEventId) { + // there is currently a read-up-to marker at this point, but no + // more. Show an animation of it disappearing. + ghostIndex = eventsToShow.length; + this.currentGhostEventId = eventId; + } else if (eventId == this.currentGhostEventId) { + // if we're showing an animation, continue to show it. + ghostIndex = eventsToShow.length; } } @@ -170,6 +182,9 @@ module.exports = React.createClass({ var prevEvent = null; // the last event we showed + // assume there is no read marker until proven otherwise + var readMarkerVisible = false; + for (var i = 0; i < eventsToShow.length; i++) { var mxEv = eventsToShow[i]; var wantTile = true; @@ -183,6 +198,7 @@ module.exports = React.createClass({ // us sending a message and receiving the synthesized receipt. if (mxEv.sender && mxEv.sender.userId != this.props.ourUserId) { ret.push(this._getReadMarkerTile()); + readMarkerVisible = true; } } else if (i == ghostIndex) { ret.push(this._getReadMarkerGhostTile()); @@ -198,6 +214,7 @@ module.exports = React.createClass({ prevEvent = mxEv; } + this.currentReadMarkerEventId = readMarkerVisible ? this.props.readMarkerEventId : null; return ret; }, @@ -259,17 +276,27 @@ module.exports = React.createClass({ }, _getReadMarkerGhostTile: function() { - var hr; - hr =
{ + this.currentGhostEventId = null; + }; + + var hr =
; + + // give it a key which depends on the event id. That will ensure that + // we get a new DOM node (restarting the animation) when the ghost + // moves to a different event. return ( -
  • {hr}
  • diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 4b050bfed8..14da1e9ab8 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -82,7 +82,6 @@ module.exports = React.createClass({ timelineLoading: true, // track whether our room timeline is loading canBackPaginate: true, readMarkerEventId: this._getCurrentReadReceipt(), - readMarkerGhostEventId: null, }; }, @@ -200,7 +199,6 @@ module.exports = React.createClass({ this.setState({ readMarkerEventId: newReadMarker, - readMarkerGhostEventId: oldReadMarker, }); }, @@ -441,7 +439,6 @@ module.exports = React.createClass({ events={ this.state.events } highlightedEventId={ this.props.highlightedEventId } readMarkerEventId={ this.state.readMarkerEventId } - readMarkerGhostEventId={ this.state.readMarkerGhostEventId } suppressFirstDateSeparator={ this.state.canBackPaginate } ourUserId={ MatrixClientPeg.get().credentials.userId } stickyBottom={ stickyBottom }