Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a reaction makes the chat "scroll up" (then you have to scroll to see new messages) #3753

Closed
WofWca opened this issue Apr 6, 2024 · 9 comments · Fixed by #4120
Closed
Assignees
Labels
bug Something isn't working

Comments

@WofWca
Copy link
Collaborator

WofWca commented Apr 6, 2024

  • Operating System (Linux/Mac/Windows/iOS/Android): Windows, Linux

  • Delta Chat Version: 1.44.0, 828f472

  • Expected behavior: The scroll position remains at the very bottom of the chat

  • Actual behavior: The chat becomes "scrolled up", gets "unlocked" from the bottom position

  • Steps to reproduce the problem:

    1. Open a chat with someone, scroll to bottom
    2. Let them add a reaction, or add one yourself
    3. Wait for a new message to arrive
  • Screenshots:

    DeltaChat_xPvyZE4PNu.mp4
  • Logs: [none]

I think there should be a proper "declarative" fix. For example, I have noticed that in Chromium if you scroll to the bottom of the page and then increase the height of an element that is somewhere above, out of view, then the scroll height of the page will change, but the scroll position will remain at the bottom, unlike if the element was in view.

Update: oh lord oh please don't tell me this has to be fixed through scroll locking

loadChat: this.scheduler.lockedQueuedEffect(
'scroll',

@Simon-Laux Simon-Laux added the bug Something isn't working label Apr 8, 2024
@WofWca
Copy link
Collaborator Author

WofWca commented Apr 9, 2024

I'm noticing that our code is very similar to Signal, and Signal doesn't have this issue.

@Jikstra
Copy link
Contributor

Jikstra commented Apr 9, 2024

You can debug it by adding a display: none; to .styles_module_reactions

EDIT: Adding margin-bottom: -1px; to .styles_module_reactions fixes it i think. Why this happens? Not so sure...

@WofWca
Copy link
Collaborator Author

WofWca commented Apr 9, 2024

EDIT: Adding margin-bottom: -1px; to .styles_module_reactions fixes it i think. Why this happens? Not so sure...

Hmm idk. Didn't work for me

@WofWca
Copy link
Collaborator Author

WofWca commented Apr 9, 2024

What did work is this one simple trick (scientists hate me):

https://github.com/signalapp/Signal-Desktop/blob/29c404266863491a3b26a73b24602d36d7a3ac46/stylesheets/_modules.scss#L5573-L5587

Basically we gotta put overflow-anchor: none; on all of the messages except the one we want to stay in place (which in this case would be the last message).

Edit: though idk, it's not 100% reliable. If I react to one message then it works, if I react to another it doesn't...
Edit2: ohhh I see. We gotta ensure that all of the elements within the scrollable element except the one we're interested in, have overflow-anchor: none;, because that way they can get selected as anchors themselves. For me it was a .daymarker message that didn't have overflow-anchor: none;

@farooqkz farooqkz self-assigned this May 14, 2024
WofWca added a commit that referenced this issue Jul 5, 2024
Closes #3753

TODO:
- [ ] The biggest issue I noticed is that when the chat
    is scrolled to bottom and a new message appears, it causes
    a "scroll" event (which doesn't feel like it should be the case,
    since the all we did is just changed the scroll anchor),
    which causes the reaction bar to disappear if it was open
    (see `hideReactionsBar`).
    Personally I think it is ok to get rid of this feature
    at least temporarily, because this scrolling thing
    is far more annoying that that feature is good

Otherwise I haven't noticed things that you could call issues.

This removes `scrollToBottom` JS on each new message,
which is now unnecessary. However, the old code used `ifClose: true`,
which would still scroll the chat if it was scrolled up less than
7 pixels up. The new implementation still has similar behavior as
the new scroll anchor is not at the very bottom
of the scrollable area, so the chat will still show the new message
as long as the bottom edge of the previous oldest message
was still visible when the new one arrived.
WofWca added a commit that referenced this issue Jul 5, 2024
Closes #3753

TODO:
- [ ] The biggest issue I noticed is that when the chat
    is scrolled to bottom and a new message appears, it causes
    a "scroll" event (which doesn't feel like it should be the case,
    since the all we did is just changed the scroll anchor),
    which causes the reaction bar to disappear if it was open
    (see `hideReactionsBar`).

Otherwise I haven't noticed things that you could call issues.

This removes `scrollToBottom` JS on each new message,
which is now unnecessary. However, the old code used `ifClose: true`,
which would still scroll the chat if it was scrolled up less than
7 pixels up. The new implementation still has similar behavior as
the new scroll anchor is not at the very bottom
of the scrollable area, so the chat will still show the new message
as long as the bottom edge of the previous oldest message
was still visible when the new one arrived.
WofWca added a commit that referenced this issue Jul 5, 2024
Closes #3753

TODO:
- [ ] The biggest issue I noticed is that when the chat
    is scrolled to bottom and a new message appears, it causes
    a "scroll" event (which doesn't feel like it should be the case,
    since the all we did is just changed the scroll anchor),
    which causes the reaction bar to disappear if it was open
    (see `hideReactionsBar`).
    Personally I think it is ok to get rid of this feature
    at least temporarily, because this scrolling thing
    is far more annoying that that feature is good

Otherwise I haven't noticed things that you could call issues.

This removes `scrollToBottom` JS on each new message,
which is now unnecessary. However, the old code used `ifClose: true`,
which would still scroll the chat if it was scrolled up less than
7 pixels up. The new implementation still has similar behavior as
the new scroll anchor is not at the very bottom
of the scrollable area, so the chat will still show the new message
as long as the bottom edge of the previous oldest message
was still visible when the new one arrived.
WofWca added a commit that referenced this issue Jul 6, 2024
Closes #3753

This removes `scrollToBottom` JS on each new message,
which is now unnecessary. However, the old code used `ifClose: true`,
which would still scroll the chat if it was scrolled up less than
7 pixels up. The new implementation still has similar behavior as
the new scroll anchor is not at the very bottom
of the scrollable area, so the chat will still show the new message
as long as the bottom edge of the previous oldest message
was still visible when the new one arrived.
WofWca added a commit that referenced this issue Jul 6, 2024
Closes #3753

This removes `scrollToBottom` JS on each new message,
which is now unnecessary. However, the old code used `ifClose: true`,
which would still scroll the chat if it was scrolled up less than
7 pixels up. The new implementation still has similar behavior as
the new scroll anchor is not at the very bottom
of the scrollable area, so the chat will still show the new message
as long as the bottom edge of the previous oldest message
was still visible when the new one arrived.
@WofWca
Copy link
Collaborator Author

WofWca commented Jul 7, 2024

I left some extra ideas in #4012. Another quite simple one I have is to have an IntersectionObserver set "visible" class on all the visible messages, and ensure that only the last visible one has overflow-anchor: auto.
Or we could apply this only to the last message - if it is in view, then turn off anchoring for all the messages. Otherwise have default anchoring.

@r10s
Copy link
Member

r10s commented Jul 9, 2024

just some thoughts as i was queried:

how is the state "keep scroll down" detected?

iirc, there is somethings as "if the scroll position is not more than X pixels from the bottom, and a new message arrives, scroll down - otherwise the user has scrolled up manually and we stay to not disturb the user reading"

if now the added reactions enlarges the view by more than X pixels, the calculation may fail. so, making sure, the threshold is large enough may already help. or, maybe better, recalculate.

@WofWca
Copy link
Collaborator Author

WofWca commented Jul 9, 2024

"if the scroll position is not more than X pixels from the bottom, and a new message arrives, scroll down - otherwise the user has scrolled up manually and we stay to not disturb the user reading"

Yes, this is what's happening

} else if (scrollTo.type === 'scrollToBottom' && !isReactionsBarShown) {
if (scrollTo.ifClose === true) {

Though it is not triggered when a reaction is added.

@WofWca
Copy link
Collaborator Author

WofWca commented Jul 15, 2024

Would anybody be against simply adjusting CSS such that reactions are more terse and don't cause height to change?
Until we figure out a better approach.

@WofWca WofWca self-assigned this Sep 8, 2024
@WofWca
Copy link
Collaborator Author

WofWca commented Sep 8, 2024

OK, display: flex; flex-direction: column-reverse; on #message-list really looks promising. It solves nearly all scrolling problems, including #3763.

But for some reason when more messages are fetched, the scroll position jumps god knows where. However, I think this is not a problem with the approach, but something with our code. We really have a ton of scroll-related code, I'm trying to pinpoint what causes this.
An important thing I found is that the scroll position doesn't jump if I

window.fetchMoreTop = fetchMoreTop
window.fetchMoreBottom = fetchMoreBottom

And then call those functions manually from the console. The messages get loaded both above and below just fine, and the scroll position is preserved just fine.

Update: no, it's not Delta Chat scrolling code. It appears to be a Chromium bug. It manifests itself when an element is inserted while you're scrolling. In that case the position does not get preserved. But it only applies when display: flex; flex-direction: column-reverse;. In regular cases scroll anchoring works even when you scroll.
To test, go to this page and insert the following in the console:

messages = document.querySelector('.scroller-content')
messages.parentElement.style.height = '600px';
function insertBottom() {
  messages.appendChild(messages.lastElementChild.cloneNode(true));
}
function insertTop() {
  messages.prepend(messages.firstElementChild.cloneNode(true));
}
// insertTop()
// insertBottom()
setInterval(() => {
  insertTop();
  insertTop();
  insertTop();
  setTimeout(() => {
    insertBottom()
    insertBottom()
    insertBottom()
  }, 17);
}, 300)

Then select some element's text to better see it and try scrolling back and forth around it. You'll see that it shifts (which is bad). It doesn't shift if you don't scroll (which is how it's supposed to work), and it doesn't shift if you remove display: flex; flex-direction: column-reverse; while you scroll.

If you do the same on Firefox (Gecko), there is no such issue. Works like a charm.

A suggestion I have to only insert new messages while we're not scrolling. In addition, disabling smooth scrolling could work.

Update 2: I created a Chromium bug report

Update 3: I uploaded this MR #4116 if anyone wants to check how far I got by now.

WofWca added a commit that referenced this issue Sep 9, 2024
Closes #3753
Closes #3763

WIP because see #3753 (comment)

Uploading this purely for journaling purposes for now.
WofWca added a commit that referenced this issue Sep 10, 2024
...resulting in new messages not getting scrolled into view
when they arrive.

This simply removes height changes between messages with / without
a reaction.

Closes #3753
WofWca added a commit that referenced this issue Sep 10, 2024
...resulting in new messages not getting scrolled into view
when they arrive.

This simply removes height changes between messages with / without
a reaction.

Closes #3753
WofWca added a commit that referenced this issue Sep 11, 2024
...resulting in new messages not getting scrolled into view
when they arrive.

This simply removes height changes between messages with / without
a reaction.

Closes #3753
WofWca added a commit that referenced this issue Sep 11, 2024
...resulting in new messages not getting scrolled into view
when they arrive.

This simply removes height changes between messages with / without
a reaction.

Closes #3753
WofWca added a commit that referenced this issue Sep 18, 2024
...resulting in new messages not getting scrolled into view
when they arrive.

This simply removes height changes between messages with / without
a reaction.

Closes #3753
WofWca added a commit that referenced this issue Sep 18, 2024
...resulting in new messages not getting scrolled into view
when they arrive.

This simply removes height changes between messages with / without
a reaction.

Closes #3753
@WofWca WofWca closed this as completed in 60e52c7 Sep 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment