Merge pull request #159 from matrix-org/rav/move_ghostmarker_to_messagepanel
Move the ghost-read-marker logic to MessagePanelpull/21833/head
commit
4c149480c9
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var sdk = require('../../index');
|
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({
|
module.exports = React.createClass({
|
||||||
displayName: 'MessagePanel',
|
displayName: 'MessagePanel',
|
||||||
|
@ -35,10 +35,6 @@ module.exports = React.createClass({
|
||||||
// event after which we should show a read marker
|
// event after which we should show a read marker
|
||||||
readMarkerEventId: React.PropTypes.string,
|
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
|
// the userid of our user. This is used to suppress the read marker
|
||||||
// for pending messages.
|
// for pending messages.
|
||||||
ourUserId: React.PropTypes.string,
|
ourUserId: React.PropTypes.string,
|
||||||
|
@ -63,6 +59,17 @@ module.exports = React.createClass({
|
||||||
onFillRequest: React.PropTypes.func,
|
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 */
|
/* get the DOM node representing the given event */
|
||||||
getNodeForEventId: function(eventId) {
|
getNodeForEventId: function(eventId) {
|
||||||
if (!this.eventNodes) {
|
if (!this.eventNodes) {
|
||||||
|
@ -158,11 +165,16 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventId = mxEv.getId();
|
var eventId = mxEv.getId();
|
||||||
if (eventId == this.props.readMarkerGhostEventId) {
|
|
||||||
ghostIndex = eventsToShow.length;
|
|
||||||
}
|
|
||||||
if (eventId == this.props.readMarkerEventId) {
|
if (eventId == this.props.readMarkerEventId) {
|
||||||
readMarkerIndex = eventsToShow.length;
|
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
|
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++) {
|
for (var i = 0; i < eventsToShow.length; i++) {
|
||||||
var mxEv = eventsToShow[i];
|
var mxEv = eventsToShow[i];
|
||||||
var wantTile = true;
|
var wantTile = true;
|
||||||
|
@ -183,6 +198,7 @@ module.exports = React.createClass({
|
||||||
// us sending a message and receiving the synthesized receipt.
|
// us sending a message and receiving the synthesized receipt.
|
||||||
if (mxEv.sender && mxEv.sender.userId != this.props.ourUserId) {
|
if (mxEv.sender && mxEv.sender.userId != this.props.ourUserId) {
|
||||||
ret.push(this._getReadMarkerTile());
|
ret.push(this._getReadMarkerTile());
|
||||||
|
readMarkerVisible = true;
|
||||||
}
|
}
|
||||||
} else if (i == ghostIndex) {
|
} else if (i == ghostIndex) {
|
||||||
ret.push(this._getReadMarkerGhostTile());
|
ret.push(this._getReadMarkerGhostTile());
|
||||||
|
@ -198,6 +214,7 @@ module.exports = React.createClass({
|
||||||
prevEvent = mxEv;
|
prevEvent = mxEv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.currentReadMarkerEventId = readMarkerVisible ? this.props.readMarkerEventId : null;
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -259,17 +276,27 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_getReadMarkerGhostTile: function() {
|
_getReadMarkerGhostTile: function() {
|
||||||
var hr;
|
// reset the ghostEventId when the animation finishes, so that
|
||||||
hr = <hr className="mx_RoomView_myReadMarker"
|
// we can make a new one (and so that we don't run the
|
||||||
|
// animation code every time we render)
|
||||||
|
var completeFunc = () => {
|
||||||
|
this.currentGhostEventId = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var hr = <hr className="mx_RoomView_myReadMarker"
|
||||||
style={{opacity: 1, width: '99%'}}
|
style={{opacity: 1, width: '99%'}}
|
||||||
ref={function(n) {
|
ref={function(n) {
|
||||||
Velocity(n, {opacity: '0', width: '10%'},
|
Velocity(n, {opacity: '0', width: '10%'},
|
||||||
{duration: 400, easing: 'easeInSine',
|
{duration: 400, easing: 'easeInSine',
|
||||||
delay: 1000});
|
delay: 1000, complete: completeFunc});
|
||||||
}}
|
}}
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
|
// 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 (
|
return (
|
||||||
<li key="_readuptoghost"
|
<li key={"_readuptoghost_"+this.currentGhostEventId}
|
||||||
className="mx_RoomView_myReadMarker_container">
|
className="mx_RoomView_myReadMarker_container">
|
||||||
{hr}
|
{hr}
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -82,7 +82,6 @@ module.exports = React.createClass({
|
||||||
timelineLoading: true, // track whether our room timeline is loading
|
timelineLoading: true, // track whether our room timeline is loading
|
||||||
canBackPaginate: true,
|
canBackPaginate: true,
|
||||||
readMarkerEventId: this._getCurrentReadReceipt(),
|
readMarkerEventId: this._getCurrentReadReceipt(),
|
||||||
readMarkerGhostEventId: null,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -200,7 +199,6 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
readMarkerEventId: newReadMarker,
|
readMarkerEventId: newReadMarker,
|
||||||
readMarkerGhostEventId: oldReadMarker,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -441,7 +439,6 @@ module.exports = React.createClass({
|
||||||
events={ this.state.events }
|
events={ this.state.events }
|
||||||
highlightedEventId={ this.props.highlightedEventId }
|
highlightedEventId={ this.props.highlightedEventId }
|
||||||
readMarkerEventId={ this.state.readMarkerEventId }
|
readMarkerEventId={ this.state.readMarkerEventId }
|
||||||
readMarkerGhostEventId={ this.state.readMarkerGhostEventId }
|
|
||||||
suppressFirstDateSeparator={ this.state.canBackPaginate }
|
suppressFirstDateSeparator={ this.state.canBackPaginate }
|
||||||
ourUserId={ MatrixClientPeg.get().credentials.userId }
|
ourUserId={ MatrixClientPeg.get().credentials.userId }
|
||||||
stickyBottom={ stickyBottom }
|
stickyBottom={ stickyBottom }
|
||||||
|
|
Loading…
Reference in New Issue