fix(messaging): stop older-message loads from force-scrolling to bottom - #4477
Conversation
The channel/DM "scroll to bottom on entry" effects in useMessagingView depend on the messages array so a still-in-flight initial fetch can still trigger the scroll after channel/tab switch — but that also made them re-fire on every other messages-array change, including loadMoreChannelMessages/loadMoreDirectMessages prepending an older page during infinite scroll. Every scroll-up-to-load-more was immediately yanked back to the bottom. Gate the forced scroll to fire once per channel/tab (or DM/tab) entry via a ref that only resets when selectedChannel/selectedDMNode or activeTab changes, so later messages-array updates (older-page loads, new poll messages) no longer re-trigger it. Fixes #4476 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XzheBuAewE6kNeeEa21v7z
|
Claude finished @Yeraze's task —— View job PR Review — fix(messaging): stop older-message loads from force-scrolling to bottom
SummaryThis is a well-targeted, minimal fix for a real UX bug (#4476). The root cause analysis is accurate and the approach is sound. Here's a detailed review: Correctness ✅The fix correctly identifies the problem: GATED EFFECTs #1 and #4 had The two-effect pattern is correct: One effect resets Code Quality ✅The implementation is minimal and well-commented. The inline comment block at
The parallel treatment of One Subtle Issue: Potential Timing Race
|
Summary
Fixes #4476 — scrolling up in a Meshtastic channel (or DM conversation) to load older messages immediately snapped the view back to the bottom, every time, making it impossible to actually read history.
Root cause: in
src/hooks/useMessagingView.ts, the "scroll to bottom on channel/DM entry" effects (GATED EFFECT #1andGATED EFFECT #4) depend onchannelMessages/messagesso a still-in-flight initial fetch can still trigger the entry scroll after a channel/tab switch. But that dependency also makes the effects re-fire on every messages-array change — includingloadMoreChannelMessages/loadMoreDirectMessagesprepending an older page during infinite scroll. Those loaders already restore scroll position correctly viarequestAnimationFrame, but ~100–150ms later the entry-scroll effect fires again and unconditionally setsscrollTop = scrollHeight, undoing it.src/hooks/useMessagingView.ts— gate both entry-scroll effects behind a ref (pendingChannelScrollRef/pendingDMScrollRef) that's only reset whenselectedChannel/selectedDMNodeoractiveTabactually changes. Later messages-array updates from pagination or new poll messages no longer re-trigger the forced scroll; the existing "auto-scroll on new message only if already near bottom" effects are untouched and still handle the live-update case.Test plan
npx vitest run src/hooks/useMessagingView.test.ts— 10/10 passnpx vitest run src/hooks/— 427/427 passnpm run typecheck— cleannpm run lint:ci— clean (no FAIL lines outside.claude/worktrees)Generated by Claude Code