Skip to content

fix(web): 修复历史消息加载时的滚动位置恢复问题#167

Closed
0x7551 wants to merge 7 commits intotiann:mainfrom
0x7551:fix/scroll-position-restoration
Closed

fix(web): 修复历史消息加载时的滚动位置恢复问题#167
0x7551 wants to merge 7 commits intotiann:mainfrom
0x7551:fix/scroll-position-restoration

Conversation

@0x7551
Copy link
Copy Markdown
Contributor

@0x7551 0x7551 commented Feb 9, 2026

问题描述

在加载历史消息时,自动滚动功能会干扰滚动位置的恢复,导致用户无法正确定位到之前的阅读位置。

修复内容

  1. 防止 autoScroll 在历史加载时干扰滚动位置
  2. 等待 DOM 更新完成后再恢复滚动位置
  3. 确保滚动位置恢复的时机正确

测试

  • ✅ 手动测试历史消息加载场景
  • ✅ 验证滚动位置正确恢复

via HAPI

从 PR #156 拆分出来,专注于滚动位置修复。

tfq and others added 7 commits January 30, 2026 22:24
Add MesloLGLDZ Nerd Font as a built-in web font to ensure Powerlevel10k
and other Nerd Font-dependent prompts render correctly in the web terminal,
even on devices without local Nerd Fonts installed (e.g., mobile phones).

Changes:
- Add MesloLGLDZNerdFontMono-Regular.woff2 to web/public/fonts/
- Load font via FontFace API with BASE_URL support for subpath deployments
- Merge font loading and terminal creation in same useEffect to ensure
  font is ready before terminal renders

Fixes tiann#121

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Load MesloLGLDZ Nerd Font from jsDelivr CDN instead of bundling the 1.2MB
font file. This reduces the bundle size significantly while still ensuring
Nerd Font icons display correctly on all devices.

CDN URL: https://cdn.jsdelivr.net/gh/mshaugh/nerdfont-webfonts@v3.3.0/build/fonts/MesloLGLDZNerdFontMono-Regular.woff2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…l position

When loading older messages, the assistant-ui library's autoScroll feature
was interfering with our manual scroll position restoration, causing the
viewport to jump to the top instead of maintaining position.

Root cause: ThreadPrimitive.Viewport's autoScroll triggers scrollToBottom()
on content resize when autoScroll=true and isAtBottom=true. This conflicts
with our useLayoutEffect scroll position restoration.

Fix: Temporarily disable autoScroll during history load:
1. Set autoScrollEnabled=false when handleLoadMore starts
2. Restore scroll position in useLayoutEffect as before
3. Re-enable autoScroll after position is restored
4. Handle error cases to ensure autoScroll is always re-enabled

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Add detailed logging to understand why scroll position jumps to top
when loading older messages instead of maintaining position.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
The previous implementation tried to restore scroll position immediately
when messagesVersion changed, but the new messages hadn't been rendered
to DOM yet, causing delta to be 0 and scroll position to remain at top.

Fix: Use requestAnimationFrame to wait for DOM update and check if
scrollHeight has actually changed before restoring position.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Remove temporary debug logging added during development.
The fix is working correctly - scroll position is now properly
maintained when loading older messages.

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
viewport.scrollTop = pending.scrollTop + delta
pendingScrollRef.current = null
loadLockRef.current = false
// Re-enable autoScroll after scroll position is restored
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MAJOR] [Behavior] 恢复滚动后无条件开启 autoScroll

Why this is a problem: setAutoScrollEnabled(true) 在恢复历史滚动后直接启用,会覆盖“离底部自动关闭”的逻辑,用户阅读历史时收到新消息会被强制滚到底部。

Suggested fix:

const distanceFromBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight
const isNearBottom = distanceFromBottom < 120
setAutoScrollEnabled(isNearBottom)

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] 历史消息恢复后无条件开启 autoScroll,会覆盖“离底部自动关闭”逻辑,用户阅读历史时新消息可能被强制滚到底部,位置丢失。证据 web/src/components/AssistantChat/HappyThread.tsx:271
    Suggested fix:
    const distanceFromBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight
    const isNearBottom = distanceFromBottom < 120
    setAutoScrollEnabled(isNearBottom)

Summary

  • 1 个行为回归风险:autoScroll 状态恢复策略可能打断历史阅读位置

Testing

  • Not run (automation)

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.

1 participant