Skip to content

fix: scroll to bottom of conversation on thread switch#157

Closed
HUQIANTAO wants to merge 1 commit into
KunAgent:masterfrom
HUQIANTAO:fix/scroll-to-bottom-on-thread-switch-clean
Closed

fix: scroll to bottom of conversation on thread switch#157
HUQIANTAO wants to merge 1 commit into
KunAgent:masterfrom
HUQIANTAO:fix/scroll-to-bottom-on-thread-switch-clean

Conversation

@HUQIANTAO

Copy link
Copy Markdown

Problem

When switching between conversations via the sidebar, the message timeline does not scroll to the latest messages. Instead, the viewport lands somewhere in the middle of the conversation, leaving the user disoriented.

Root Cause

A race condition in the useTimelineScroll hook between two useEffect blocks in src/renderer/src/components/chat/use-timeline-scroll.ts:

  1. Hard reset effect (triggered by activeThreadId change): calls endRef.current?.scrollIntoView() synchronously. At this point visibleTurnCount React state is still stale from the previous conversation — only a subset of turns are rendered in the DOM.

  2. Re-derive visible count effect (also triggered by activeThreadId change): calls setVisibleTurnCount(deriveTimelineVisibleTurnCount(...)), which queues an async state update that re-renders with more turns prepended above the viewport.

Because the scroll fires before the visible turn count reconciles, the content area grows taller after the scroll, pushing the scroll position away from the bottom.

Fix

Defer the scrollIntoView call using a double requestAnimationFrame, ensuring it runs after visibleTurnCount has been re-derived and the additional turns have been painted:

// Before
endRef.current?.scrollIntoView({ behavior: 'auto', block: 'end' })

// After — double-rAF defers until after the next paint
scrollFrameRef.current = window.requestAnimationFrame(() => {
  scrollFrameRef.current = window.requestAnimationFrame(() => {
    scrollFrameRef.current = null
    endRef.current?.scrollIntoView({ behavior: 'auto', block: 'end' })
  })
})

Files Changed

  • src/renderer/src/components/chat/use-timeline-scroll.ts — defer scroll in thread-switch effect (+9, -1)

Testing

  1. Open a conversation with a long message history
  2. Scroll up manually, then click a different conversation in the sidebar — viewport should jump to the latest messages
  3. Switch back and forth between multiple conversations — each time the view should start at the bottom
  4. Verify that existing scroll behavior still works: stick-to-bottom during streaming, lazy-load earlier turns on scroll-up, and prepend-position preservation

Double-rAF defer scrollIntoView until after visibleTurnCount re-derives
and the extra turns have been painted, preventing the scroll position
from getting stuck mid-content on thread switch.
@XingYu-Zhong

Copy link
Copy Markdown
Collaborator

目前先不建议直接合入,这条 PR 也会先关闭。

具体原因:

  • 这条改动本身看起来是一个小修复,但当前 base branch 是 master
  • 按现在仓库的提交节奏,这类 GUI / renderer 改动不应该直接进 master,而应该先进入 develop
  • 所以当前问题不一定是代码逻辑本身,而是目标分支不对。

建议怎么改:

  • 请把 base branch 改到 develop
  • 改完后如果 diff 仍然干净、没有新的冲突,可以重新提交 / reopen,再继续 review。

这次先关闭,避免继续挂在错误的目标分支上。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants