Reimplement _saveScrollState

The actual fix to https://github.com/vector-im/riot-web/issues/3175 is this change to `_saveScrollState`, which is to pick the trackedScrollToken based on which node is intersected by the bottom of the scroll panel. This is opposed to the previous logic that picked based on which node was the first from the bottom to be above the bottom of the viewport.

In the case where the viewport bottom does not intersect any events, the topmost event is used.
This commit is contained in:
Luke Barnard 2017-04-04 11:55:53 +01:00
parent 8e5a83a056
commit 94fe9999db
2 changed files with 22 additions and 11 deletions

View file

@ -589,24 +589,35 @@ module.exports = React.createClass({
var itemlist = this.refs.itemlist;
var wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
var messages = itemlist.children;
let newScrollState = null;
for (var i = messages.length-1; i >= 0; --i) {
var node = messages[i];
if (!node.dataset.scrollToken) continue;
var boundingRect = node.getBoundingClientRect();
if (boundingRect.bottom < wrapperRect.bottom) {
this.scrollState = {
newScrollState = {
stuckAtBottom: false,
trackedScrollToken: node.dataset.scrollToken,
pixelOffset: wrapperRect.bottom - boundingRect.bottom,
};
// If the bottom of the panel intersects the ClientRect of node, use this node
// as the scrollToken.
// If this is false for the entire for-loop, we default to the last node
// (which is why newScrollState is set on every iteration).
if (boundingRect.top < wrapperRect.bottom &&
wrapperRect.bottom < boundingRect.bottom) {
// Use this node as the scrollToken
break;
}
}
// This is only false if there were no nodes with `node.dataset.scrollToken` set.
if (newScrollState) {
this.scrollState = newScrollState;
debuglog("ScrollPanel: saved scroll state", this.scrollState);
return;
}
}
} else {
debuglog("ScrollPanel: unable to save scroll state: found no children in the viewport");
}
},
_restoreSavedScrollState: function() {

View file

@ -263,7 +263,7 @@ var TimelinePanel = React.createClass({
}
);
let count = backwards ? marker : this.state.events.length - marker;
let count = backwards ? marker + 1 : this.state.events.length - marker;
if (count > 0) {
debuglog("TimelinePanel: Unpaginating", count, "in direction", dir);