Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Improved scrolling & pagination #2676

Merged
merged 13 commits into from
Mar 1, 2019
Merged

Conversation

bwindels
Copy link
Contributor

@bwindels bwindels commented Feb 21, 2019

Based off #2671
element-hq/element-web#8565

The main point of this PR is to observe the timeline for size changes, and restore the scroll position to keep the last tile aligned to the bottom of the viewport. Observing the timeline for size changes uses ResizeObserver where available (for now Chrome >= 64), completely preventing scroll jank (as ResizeObserver triggers between layout and paint), and falls back to IntersectionObserver (Edge & Firefox) which can still be a bit janky depending on how fast you scroll (the callback is called a lot less frequent than ResizeObserver), but still feels better than not restoring the scroll position on resize at all.

Apart from that it also tries to improve the block-shrinking behaviour (setting a min-height on the timeline when showing typing notifications, to prevent jumping when they are hidden again), but clearing it on timeline resets (this was the cause of the white wall of doom), and clear it not immediately when scrolling up, which also caused jumping.

I also removed the fix for element-hq/element-web#528, it makes the code harder to understand, it's for a 3 years old version of Chrome, and richvdh thought the workaround might make other things less reliable. (Discussion here)

@bwindels bwindels assigned turt2live and unassigned turt2live Feb 22, 2019
@bwindels bwindels removed the notready label Feb 22, 2019
@bwindels bwindels requested a review from a team February 22, 2019 17:36
@bwindels
Copy link
Contributor Author

Need to fix unit test, but otherwise should be ready for review.

(only where supported, polyfill doesn't give good results)
as they are an order of magnitude faster in most browsers,
getBoundingClientRect() tends to cause relayout.
before we would clear it as soon as you were 1px away from
the bottom of the timeline, which would still create jumping as
the whitespace would around 36px. To play it safe, we only clear it
after moving 200px from the bottom.

Also include "local echo" scroll events, caused by setting scrollTop
this is not nearly as smooth as using ResizeObserver, as the
callback rate is a lot lower, but seems to be quite a bit better
than what we have right now, without the 7% cpu hog that
the requestAnimationFrame polling fallback has.
@bwindels bwindels removed the request for review from a team February 26, 2019 14:37
@bwindels
Copy link
Contributor Author

There is a remaining issue with this PR, where while repeatedly scrolling to the top, it gets stuck at the top back-filling until you scroll down again. Moving it out of review because of this.

as we're approaching from the last node, if we're scrolled up,
the first node we encounter would be below the bottom of the viewport

change the logic to stop at the first node that has its top
above the viewport bottom.

When completely scrolled up, this was causing nodes way below
the viewport to be selected as the reference for the pixelOffset,
and when pagination came in, it would immediately try to apply
the big negative pixelOffset, scrolling to a negative scrollTop,
thus going to the top again, and triggering another pagination,
entering in an infinite pagination loop until you scrolled down.
karma seems to be giving priority to a location where an old version is installed.
@bwindels
Copy link
Contributor Author

bwindels commented Feb 28, 2019

FTR: should not be part of 1.0.2-rc, so ready to review, but don't merge for now.

@bwindels bwindels requested a review from a team February 28, 2019 12:20
@jryans jryans self-assigned this Feb 28, 2019
Copy link
Collaborator

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! It seems great to me. 😁

I tested it locally in Firefox as well to check how it feels as well as the perf impact. Overall it does seem smoother than before, and I haven't noticed any constant perf impact so far.

@@ -935,6 +935,11 @@ var TimelinePanel = React.createClass({
{windowLimit: this.props.timelineCap});

const onLoaded = () => {
// clear the timeline min-height when
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a low line length for comments! 😉

for (let i = 0; i < 1000; ++i) {
threshold.push(i / 1000);
}
threshold.push(1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could also do i <= 1000 in the loop, if you like.

@jryans jryans assigned bwindels and unassigned jryans Feb 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants