fix: prevent scroll snap-back during mobile momentum scrolling

ResizeObserver and media load callbacks were using isNearBottomRef
(5000px threshold) to decide whether to auto-scroll to bottom. On
mobile, inertial flick scrolling hadn't moved far enough to clear
that threshold before the observer fired, snapping the user back.

Now these callbacks check actual scroll distance at fire time with
a tight 150px threshold — only auto-scrolls if truly at the bottom.
This commit is contained in:
Jannis Braun
2026-03-23 15:04:44 +01:00
parent 2c372a5d34
commit 05a4b23d88
@@ -159,8 +159,14 @@ export function MessageList({ channelId, jumpToMessageId, onJumpComplete }: Mess
if (!content || !container) return; if (!content || !container) return;
const observer = new ResizeObserver(() => { const observer = new ResizeObserver(() => {
if (isNearBottomRef.current && containerRef.current) { const c = containerRef.current;
containerRef.current.scrollTop = containerRef.current.scrollHeight; if (!c) return;
// Use a tight threshold (150px) checked at fire time instead of the
// generous 5000px isNearBottomRef — prevents snapping the user back
// to bottom during momentum/inertial scrolling on mobile.
const dist = c.scrollHeight - c.scrollTop - c.clientHeight;
if (dist < 150) {
c.scrollTop = c.scrollHeight;
} }
}); });
observer.observe(content); observer.observe(content);
@@ -175,8 +181,11 @@ export function MessageList({ channelId, jumpToMessageId, onJumpComplete }: Mess
if (!content) return; if (!content) return;
const handleMediaLoad = () => { const handleMediaLoad = () => {
if (isNearBottomRef.current && containerRef.current) { const c = containerRef.current;
containerRef.current.scrollTop = containerRef.current.scrollHeight; if (!c) return;
const dist = c.scrollHeight - c.scrollTop - c.clientHeight;
if (dist < 150) {
c.scrollTop = c.scrollHeight;
} }
}; };