implement scrolling to a token (best effort)
This commit is contained in:
parent
805539fdc7
commit
46f5f872c4
1 changed files with 20 additions and 21 deletions
|
@ -546,38 +546,35 @@ module.exports = React.createClass({
|
||||||
/* Scroll the panel to bring the DOM node with the scroll token
|
/* Scroll the panel to bring the DOM node with the scroll token
|
||||||
* `scrollToken` into view.
|
* `scrollToken` into view.
|
||||||
*
|
*
|
||||||
* offsetBase gives the reference point for the bottomOffset. 0 means the
|
* offsetBase gives the reference point for the pixelOffset. 0 means the
|
||||||
* top of the container, 1 means the bottom, and fractional values mean
|
* top of the container, 1 means the bottom, and fractional values mean
|
||||||
* somewhere in the middle. If omitted, it defaults to 0.
|
* somewhere in the middle. If omitted, it defaults to 0.
|
||||||
*
|
*
|
||||||
* bottomOffset gives the number of pixels *above* the offsetBase that the
|
* pixelOffset gives the number of pixels *above* the offsetBase that the
|
||||||
* node (specifically, the bottom of it) will be positioned. If omitted, it
|
* node (specifically, the bottom of it) will be positioned. If omitted, it
|
||||||
* defaults to 0.
|
* defaults to 0.
|
||||||
*/
|
*/
|
||||||
scrollToToken: function(scrollToken, bottomOffset, offsetBase) {
|
scrollToToken: function(scrollToken, pixelOffset, offsetBase) {
|
||||||
bottomOffset = bottomOffset || 0;
|
pixelOffset = pixelOffset || 0;
|
||||||
offsetBase = offsetBase || 0;
|
offsetBase = offsetBase || 0;
|
||||||
|
|
||||||
// convert bottomOffset so that it is based on the bottom of the
|
// set the trackedScrollToken so we can get the node through _getTrackedNode
|
||||||
// container.
|
|
||||||
const scrollNode = this._getScrollNode();
|
|
||||||
const viewportBottom = scrollNode.scrollHeight - (scrollNode.scrollTop + scrollNode.clientHeight);
|
|
||||||
bottomOffset += viewportBottom + scrollNode.clientHeight * (1-offsetBase);
|
|
||||||
|
|
||||||
// save the desired scroll state. It's important we do this here rather
|
|
||||||
// than as a result of the scroll event, because (a) we might not *get*
|
|
||||||
// a scroll event, and (b) it might not currently be possible to set
|
|
||||||
// the requested scroll state (eg, because we hit the end of the
|
|
||||||
// timeline and need to do more pagination); we want to save the
|
|
||||||
// *desired* scroll state rather than what we end up achieving.
|
|
||||||
this.scrollState = {
|
this.scrollState = {
|
||||||
stuckAtBottom: false,
|
stuckAtBottom: false,
|
||||||
trackedScrollToken: scrollToken,
|
trackedScrollToken: scrollToken,
|
||||||
bottomOffset: bottomOffset,
|
|
||||||
};
|
};
|
||||||
|
const trackedNode = this._getTrackedNode();
|
||||||
// ... then make it so.
|
const scrollNode = this._getScrollNode();
|
||||||
this._restoreSavedScrollState();
|
if (trackedNode) {
|
||||||
|
// set the scrollTop to the position we want.
|
||||||
|
// note though, that this might not succeed if the combination of offsetBase and pixelOffset
|
||||||
|
// would position the trackedNode towards the top of the viewport.
|
||||||
|
// This because when setting the scrollTop only 10 or so events might be loaded,
|
||||||
|
// not giving enough content below the trackedNode to scroll downwards
|
||||||
|
// enough so it ends up in the top of the viewport.
|
||||||
|
scrollNode.scrollTop = (trackedNode.offsetTop - (scrollNode.clientHeight * offsetBase)) + pixelOffset;
|
||||||
|
this._saveScrollState();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_saveScrollState: function() {
|
_saveScrollState: function() {
|
||||||
|
@ -615,11 +612,13 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
const scrollToken = node.dataset.scrollTokens.split(',')[0];
|
const scrollToken = node.dataset.scrollTokens.split(',')[0];
|
||||||
debuglog("saving anchored scroll state to message", node && node.innerText, scrollToken);
|
debuglog("saving anchored scroll state to message", node && node.innerText, scrollToken);
|
||||||
|
const bottomOffset = this._topFromBottom(node);
|
||||||
this.scrollState = {
|
this.scrollState = {
|
||||||
stuckAtBottom: false,
|
stuckAtBottom: false,
|
||||||
trackedNode: node,
|
trackedNode: node,
|
||||||
trackedScrollToken: scrollToken,
|
trackedScrollToken: scrollToken,
|
||||||
bottomOffset: this._topFromBottom(node),
|
bottomOffset: bottomOffset,
|
||||||
|
pixelOffset: bottomOffset - viewportBottom, //needed for restoring the scroll position when coming back to the room
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue