Scrolling: Improving jumps on timeline pagination/scrolling
Matthew's summary of the problems: https://matrix.to/#/!maVEfftuKxhnPMcckU:matrix.org/$15500048623049743lQqLW:matrix.org?via=matrix.org&via=t2l.io&via=lant.uk
Related bugs:
- https://github.com/vector-im/riot-web/issues/6265
- https://github.com/vector-im/riot-web/issues/2646
- https://github.com/vector-im/riot-web/issues/6755
Update 19/3/2019
Going with a new algorithm, dubbed BACAT (Bottom-Aligned, Clipped-At-Top) scrolling, prototyped here: https://gist.github.com/bwindels/b3a3ba3fa3792f23962d894866fa7b0f
The motivation for the changes is having noticed that setting scrollTop while scrolling tends not work well on at least Chrome on macOs. Also see https://github.com/vector-im/riot-web/issues/528. The approach taken instead manually sets the height of the timeline in 200px increments, with the timeline being aligned to the bottom of the container element. The relatively tiny 200px height comes from the fact that we don't want the user to ever scroll off into pages of whitespace and we have no way of preventing overscroll, so by keeping it to 200px and putting a spinner 100px up from the top of the page, we avoid death by whitespace.
By changing the height of the container, we can compensate for anything that grew below the viewport to maintain what's currently visible in the viewport without jumping. For anything above the viewport growing or shrinking, we don't need to do anything as the timeline is bottom-aligned. We do need to update the height manually. To maintain scroll position after the portion above the viewport changes height, we need to set the scrollTop, as we cannot balance it out with more height changes. We do this 100ms after the user has stopped scrolling, so setting scrollTop has not nasty side-effects.
- [x] prototype of new algo.
- [x] initial impl. in riot
- [x] fix height not updating after unfilling
- [x] fix jump to bottom exception
- [x] fix shrink blocking for typing notifs
- [x] make sure permalinks still work
- [x] fix jump while filling backwards from cached messages on Chrome/macOS
- [x] fix negative margin of right panel resize handle overlapping with scrollbar
- [x] resizing right panel doesn't maintain scroll position
- [x] timeline stops filling in certain conditions
- [x] fix tests
- [ ] fix the search UX, which now is also aligned to the bottom which looks weird
- [ ] write e2e tests for the scroll panel, as we've removed the app tests for it as they completely broke.
- [ ] Matthew might have found another jump on macOs/Chrome.
- [ ] update some obsolete comments in ScrollPanel
Obsolete now: Update 5/3/2019:
The resize observer approach doesn't work reliably as it can race with the scroll event, so looks like manually restoring the scroll position from event tile when it can cause a jump is the better option. These things can cause jumps:
- flair (fixed in https://github.com/matrix-org/matrix-react-sdk/pull/2746)
- image thumbnails loading (checked, seems ok. Was already not causing jumps AFAICT, MImageBody gets height based on timeline width and image A/R, also before image is loaded).
- bugs calculating the new scrolloffset when backpaginating (checked, seems ok)
- bugs when thumbnails haven't specified an explicit width & height when sent, so we don't know how much room to leave for them. (check code, seems ok, also most clients send this, so it wouldn't explain why jumps are so common, but I guess we could still artificially send an event like this and test what happens).
- bugs when calculating the size that should be left for images (or videos or other variable-sized table cells)
- when URL previews pop into the timeline (checked, seems ok)
- when encrypted events are decrypted (or are added to the TL)
- when the 'decrypt link' turns into the 'download link' on encrypted attachments (fixed in https://github.com/matrix-org/matrix-react-sdk/pull/2766)
- when encrypted attachment thumbnails are added into the room (the presizing doesn't take the download link, which is actually an iframe, into account, iirc - or it assumes that it doesn't linewrap, which it might)
- when replies pop into the timeline (checked, seems ok)~~
One possible approach to have the timeline prevent jumping in a more reliable way I was thinking of is the following:
We observe the <ol> in the timeline that contains all the tiles, typing notif with a ResizeObserver. It is supported in Chrome, supposed to be supported by Firefox in the nearish future, and has a polyfill available based on mutation events (which we already use elsewhere in Riot). This will give us a JS hook when the size of the timeline changes, so handling anything that could resize the timeline (thumbnails loading, event being decrypted, pagination, ...).
On scroll, we also keep track of which event tile is the last one that is still in view and calculate the offset to the bottom of the viewport.
When the timeline resizes (through the ResizeObserver), we adjust the container scrollTop, so that the offset of the last event tile in view to the bottom of the viewport stays the same.
One added benefit is that it would make it easier to switch to native scrollbars for the timeline, because the timeline does need to be made aware of size changes (which are now tracked through an overlaying iframe with gemini scrollbars), so doing it with a standardized API that will hopefully become widely supported and has a polyfill that from the looks of it should be better performing (mutation events) than the gemini iframe approach seems like a good thing.
Prototype at https://gist.github.com/bwindels/4aa3a0495264498cca67b8563b580889
Also try to fix https://github.com/vector-im/riot-web/issues/8792
Also looking at https://github.com/vector-im/riot-web/issues/8653 as part of this
Also https://github.com/vector-im/riot-web/issues/8455
This is definitely a big improvement, but it's worth noting that it can still jump pretty badly on E2E rooms, especially if they contain code blocks. Theory is that if the JS falls behind the DOM events significantly due to GCs, things get out of sync and we still see jumps - so the more work JS is doing, the more likelihood of seeing a jump.
I was able to reproduce this pretty well during the security breach of Apr 11 when trying to rapidly scroll the E2E rooms we were using to coordinate response, which had lots of code blocks as people shared details.
(It's also possible that the bad GCs triggered by https://github.com/vector-im/riot-web/issues/11267 might make this worse).
separately, @madduck is seeing something that looks like a really bad instance of this (or a new regression in FF72 on Sid?) over at https://scratch.madduck.net/riot-web-scroll-jumping-around-screencast-by-martin.mp4
@ara4n correction, its FF 70. And I do have lots of extensions preventing things, like umatrix etc.
Any news on this? At the moment, I am ashamed to demo Riot to others because it's just unusable, not to mention that I'd like to search history myself every now and then…
I just tried this on FF71 without any plugins and while it's not as bad there, it still jumps across the place too often.
@madduck is there any chance of a screencapture showing what the jumps look like? even better if you can DM me FF profiler output too to try to correlate. what spec machine are you on? I haven't seen it at all recently on my massive accounts (but then again i'm on a top end MBP)
@ara4n I'll gladly provide that… the next time I encounter the problem. I just saw it again a few days ago, but of course now that I set up the screen recorder and profiler, scrolling works just fine and there is nothing to show or correlate. #heisenbug.
Lots of reports from mozilla of this being much worse than it should be:
jld When I'm scrolling through a channel in riot-web, sometimes the scroll position will jump back in the opposite direction for no obvious reason, which makes it hard to follow higher-traffic channels (like #developers:mozilla.org). Known bug?
B.J. Herbison jld , how are you scrolling? If it is by holding the left button and dragging the scroll bar then the jumps are because more content is loaded so the scroll bar is reevaluated. That's how I would prefer to scroll and find it very annoying.
jld This was while scrolling with the scroll wheel, so that shouldn't be affected by loading in more messages off-screen. But I've noticed that things like link previews seem to be dynamically inserted, so maybe there's something not quite right about how it compensates for that.
https://matrix.to/#/!pcfWjiETvnVuspPLPl:mozilla.org/$JfS6yiJd9u8LYsCGlEA_yNnbbP0VBh6WJYPReSXoDxc?via=mozilla.org&via=matrix.org&via=maunium.net
@bwindels I assume you're not still looking at this from last year. If this is wrong, feel free to take it.
Hitting Page Up apparently causes it to jump around a bunch
This is really becoming a problem in a community I'm trying to convert to Matrix. People are complaining, which is really harming adoption. Any ETA on having this regression fixed?
@madduck the latest PR was merged 9 hours previous to your comment. Please try riot.im/develop and if you find a problem case, document it here.
Indeed, I landed a potential improvement to prevent scroll jumps yesterday. Would be great to have feedback (especially for people on macOS) if you notice any difference.
@madduck I assume you are on macOS?
https://github.com/matrix-org/matrix-react-sdk/pull/4166 seems to have improved things, with jumps occuring less frequently. At least Matthew (on FF, mac) and Neil Alexander (on Safari) are still seeing jumps after back-pagination comes in though, although less frequently than before.
@bwindels no, I am on FF/Linux, and if matrix-org/matrix-react-sdk#4166 is already deployed on riot.im/develop. then it does not fix my problems.
@bwindels no, I am on FF/Linux, and if matrix-org/matrix-react-sdk#4166 is already deployed on
riot.im/develop. then it does not fix my problems.
Interesting @madduck, same config as I have. So no improvement at all?
@bwindels no improvements, no...
Just wanted to reiterate that scrolling behaviour is still awful for me on Riot Desktop 1.6.0 on Arch Linux.
Apart from the jumping around, the worst thing is that the scrollbar grip (the thing you grab) seems to stick to the top of the scrollbar as new events are loaded. This results in continual pagination deeper and deeper into the history, with no easy way of stopping.
I think the proper behaviour would be for the grip to move downwards from the top after each batch of new events is loaded and then stay there, forcing the user to again move the grip upwards if he wants to scroll even deeper. The point is that each deeper fetch should necessitate explicit user action instead of being automatic. I think #8455 might be talking about this problem?
This is an issue for me too on Mac (Riot Desktop v1.6.2). It's pretty frustrating. It has been this way for months.
This happens to me alot when scrolling through the history of a room. Example of a room: #element-web:matrix.org
@bwindels since you are assigned to this issue and given the priority of it, what is the status? From the comments I read that it might be hard to reproduce?
On my setup, I can easily reproduce (also on different operating systems). I am open to invest some time to get required information in order to proceed with this. We could also try to arrange some virtual meeting, so you can reproduce it on my setup.
This also happens on the Desktop app (tested on Linux). Using Element is extremely unsatisfying due to this issue.
Another ping @bwindels @turt2live @ara4n
My offer to help with debuggin this or whatever is needed (in case you cannot reproduce) still stands.
Also the mozilla label is a bit misleading, since it also happens on Firefox, but also on all other browsers, I guess.
@claell do you have browser and OS information you can give us to investigate? We'd also need to know exactly what you're doing to have it happen so we can reproduce it. Screen recordings help a lot.
The mozilla label has nothing to do with Firefox or browsers - it just means that Mozilla, one of our customers, is having the issue too.
Not sure why I've been pinged on this in any case.
@turt2live
@claell do you have browser and OS information you can give us to investigate? We'd also need to know exactly what you're doing to have it happen so we can reproduce it. Screen recordings help a lot.
Tested on Firefox (always used the currently most up to date version) on Windows and Manjaro (both the most current versions). Also happened to me with the element app on Manjaro, don't know about Windows. I also linked a room where this happens.
I basically just scroll throuh the backlog. So I for example go about 600 messages up (what arrived when I was last viewing) and then scroll down towards the most recent ones. While scrolling there are sometimes jumps (happens when scrolling with mouse wheel as well as when scrolling using the Page down key. This seem to happen when using the arrow to jump to the earliest unread message as well as when manually scrolling there before scrolling down. (I think this issue also appears when scrolling up, and not only when scrolling down, but I am not entirely sure about that).
Does that mean you didn't manage to reproduce the issue? If you can't, your system information might also be helpful.
I will see if I can do a screen recording. Before I'd like to get some reply first that somebody is currently actively working on this (or will be after posting the screen recording). Else I guess it won't be worth the effort if this issue is stalled for another half a year afterwards, since then the recording might be considered outdated by then.
The mozilla label has nothing to do with Firefox or browsers - it just means that Mozilla, one of our customers, is having the issue too.
Ah, got it.
Not sure why I've been pinged on this in any case.
I pinged you because you triaged this in the past. Since there has been no action in this issue from the assignee since about half a year and given the set priority and severity (!), I thought it is probably best to also ping people who triaged this in the past in case this is currently stalled.
@dkasak's description of the problem is exactly what I'm seeing. I came here to see if there were any open tickets about scroll jumping after finding it incredibly frustrating to attempt to browse the recent history in the big Matrix/Element rooms. Turns out that the problem was that I was using the scrollbar. After reading this issue, I tried using the page up and down keys, and it worked perfectly.
I had not tried to use the keys previously, because I first tried to use the up and down arrow keys, which is how I normally scroll through pages, and saw, to my dismay, that they did not work and so I incorrectly assumed that I had to use the scroll bar, which is completely unusable, without trying page up.
As an aside, I haven't looked if there's an issue open for this, but scroll jumping is also a problem on the "Explore rooms" page, and, unfortunately, only the scroll bar "works" there.
@pwinckles Page up and Page down keys cause similar problems for me, but glad to hear that it works for you.
When you say "scroll bar" do you really mean that? Have you tried using the mouse wheel to scroll?