Merge pull request #279 from matrix-org/rav/more_timeline_optimsisations

Reduce number of renders on received events
This commit is contained in:
Richard van der Hoff 2016-04-20 00:01:58 +01:00
commit 0d9526fcec

View File

@ -244,8 +244,8 @@ var TimelinePanel = React.createClass({
this.setState({ this.setState({
[paginatingKey]: false, [paginatingKey]: false,
[canPaginateKey]: r, [canPaginateKey]: r,
events: this._getEvents(),
}); });
this._reloadEvents();
return r; return r;
}); });
}, },
@ -296,19 +296,6 @@ var TimelinePanel = React.createClass({
return; return;
} }
// when a new event arrives when the user is not watching the window, but the
// window is in its auto-scroll mode, make sure the read marker is visible.
//
// We ignore events we have sent ourselves; we don't want to see the
// read-marker when a remote echo of an event we have just sent takes
// more than the timeout on userCurrentlyActive.
//
var myUserId = MatrixClientPeg.get().credentials.userId;
var sender = ev.sender ? ev.sender.userId : null;
if (sender != myUserId && !UserActivity.userCurrentlyActive()) {
this.setState({readMarkerVisible: true});
}
// tell the timeline window to try to advance itself, but not to make // tell the timeline window to try to advance itself, but not to make
// an http request to do so. // an http request to do so.
// //
@ -318,8 +305,43 @@ var TimelinePanel = React.createClass({
// timeline window. // timeline window.
// //
// see https://github.com/vector-im/vector-web/issues/1035 // see https://github.com/vector-im/vector-web/issues/1035
this._timelineWindow.paginate(EventTimeline.FORWARDS, 1, false) this._timelineWindow.paginate(EventTimeline.FORWARDS, 1, false).done(() => {
.done(this._reloadEvents); if (this.unmounted) { return; }
var events = this._timelineWindow.getEvents();
var lastEv = events[events.length-1];
// if we're at the end of the live timeline, append the pending events
if (!this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
events.push(... this.props.room.getPendingEvents());
}
var updatedState = {events: events};
// when a new event arrives when the user is not watching the
// window, but the window is in its auto-scroll mode, make sure the
// read marker is visible.
//
// We ignore events we have sent ourselves; we don't want to see the
// read-marker when a remote echo of an event we have just sent takes
// more than the timeout on userCurrentlyActive.
//
var myUserId = MatrixClientPeg.get().credentials.userId;
var sender = ev.sender ? ev.sender.userId : null;
var callback = null;
if (sender != myUserId && !UserActivity.userCurrentlyActive()) {
updatedState.readMarkerVisible = true;
} else if(lastEv && this.getReadMarkerPosition() === 0) {
// we know we're stuckAtBottom, so we can advance the RM
// immediately, to save a later render cycle
this._setReadMarker(lastEv.getId(), lastEv.getTs(), true);
updatedState.readMarkerVisible = false;
updatedState.readMarkerEventId = lastEv.getId();
callback = this.props.onReadMarkerUpdated;
}
this.setState(updatedState, callback);
});
}, },
onRoomTimelineReset: function(room) { onRoomTimelineReset: function(room) {
@ -741,6 +763,13 @@ var TimelinePanel = React.createClass({
// the results if so. // the results if so.
if (this.unmounted) return; if (this.unmounted) return;
this.setState({
events: this._getEvents(),
});
},
// get the list of events from the timeline window and the pending event list
_getEvents: function() {
var events = this._timelineWindow.getEvents(); var events = this._timelineWindow.getEvents();
// if we're at the end of the live timeline, append the pending events // if we're at the end of the live timeline, append the pending events
@ -748,9 +777,7 @@ var TimelinePanel = React.createClass({
events.push(... this.props.room.getPendingEvents()); events.push(... this.props.room.getPendingEvents());
} }
this.setState({ return events;
events: events,
});
}, },
_indexForEventId: function(evId) { _indexForEventId: function(evId) {
@ -816,7 +843,7 @@ var TimelinePanel = React.createClass({
return this.props.room.getEventReadUpTo(myUserId, ignoreSynthesized); return this.props.room.getEventReadUpTo(myUserId, ignoreSynthesized);
}, },
_setReadMarker: function(eventId, eventTs) { _setReadMarker: function(eventId, eventTs, inhibitSetState) {
if (TimelinePanel.roomReadMarkerMap[this.props.room.roomId] == eventId) { if (TimelinePanel.roomReadMarkerMap[this.props.room.roomId] == eventId) {
// don't update the state (and cause a re-render) if there is // don't update the state (and cause a re-render) if there is
// no change to the RM. // no change to the RM.
@ -831,6 +858,10 @@ var TimelinePanel = React.createClass({
// above or below the visible timeline, we stash the timestamp. // above or below the visible timeline, we stash the timestamp.
TimelinePanel.roomReadMarkerTsMap[this.props.room.roomId] = eventTs; TimelinePanel.roomReadMarkerTsMap[this.props.room.roomId] = eventTs;
if (inhibitSetState) {
return;
}
// run the render cycle before calling the callback, so that // run the render cycle before calling the callback, so that
// getReadMarkerPosition() returns the right thing. // getReadMarkerPosition() returns the right thing.
this.setState({ this.setState({