Summary
长会话中打开右上角轮次列表,点击某个轮次标题后列表关闭,但聊天视图不滚动到对应轮次。左右箭头按钮的逐轮跳转正常工作,说明底层导航能力存在但轮次列表点击无法触发。
Area
Web UI / Flow Chat
Environment
- BitFun 版本:0.2.10
- 操作系统:Windows 11 x64
Reproduction
- 在任意会话中进行多轮对话(5 轮以上)
- 点击 Flow Chat 右上角的轮次列表按钮(List 图标)
- 展开的轮次列表中点击任意一个非当前轮次的标题
- 实际结果: 轮次列表面板关闭,但聊天视图停留在当前位置,未跳转
- 期望结果: 轮次列表面板关闭,聊天视图滚动到选中轮次
Root Cause Analysis
问题链路如下:
1. 入口 — FlowChatHeader.tsx handleTurnSelect
const handleTurnSelect = (turnId: string) => {
if (!onJumpToTurn) return;
onJumpToTurn(turnId);
setIsTurnListOpen(false); // 无条件关闭,不检查跳转是否成功
};
2. 跳转实现 — ModernFlowChatContainer.tsx handleJumpToTurn
const handleJumpToTurn = useCallback((turnId: string) => {
if (!turnId) return;
// ...
const accepted = virtualListRef.current?.pinTurnToTop(turnId, {
behavior: 'smooth',
pinMode,
}) ?? false; // 可能返回 false
setPendingHeaderTurnId(accepted ? turnId : null);
}, [activeSession?.dialogTurns, turnSummaries]);
3. 根因
pinTurnToTop 是虚拟滚动列表 VirtualMessageList 的方法。当它返回 false(列表未完全就绪、turnId 在虚拟化 items 中暂时不可用、reconcile 未完成等),跳转静默失败。
但 handleTurnSelect 在调用 onJumpToTurn 后立即且无条件执行 setIsTurnListOpen(false)——无论跳转是否成功。用户看到的就是点击后列表关闭、但视图停留在原地。
4. 同类问题参考
今天合入的 PR #1279(Code Editor 范围导航)是同一类时序问题:操作在底层组件就绪前触发,动作静默丢失。该 PR 的解决方案是引入 PendingNavigationRequest 状态机,追踪待处理请求并等 viewport 就绪后重试。
Suggested Fix
参考 PR #1279 的思路:
方案 A(推荐,Header + Container 配合):
- Container 层:
handleJumpToTurn 失败时记录 pending turn ID,监听 virtualItems 变化,当 pending turn 在渲染范围内时重新执行跳转,成功后清除 pending
- Header 层:不在
handleTurnSelect 中直接关闭面板,改为依赖已有的 useEffect(() => setIsTurnListOpen(false), [currentTurn])。如果 currentTurn 不变(跳转失败),面板保持打开
方案 B(仅 Header 兜底):
handleTurnSelect 不无条件关闭面板,等待 onJumpToTurn 的确认后再关闭
- 或让
onJumpToTurn 返回成功/失败状态
Relevant Code
src/web-ui/src/flow_chat/components/modern/FlowChatHeader.tsx — handleTurnSelect
src/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.tsx — handleJumpToTurn
src/web-ui/src/flow_chat/components/modern/useFlowChatNavigation.ts — 轮次导航事件
src/web-ui/src/flow_chat/components/modern/VirtualMessageList.tsx — pinTurnToTop 实现
另外提一句:TurnHistoryPanel.tsx(侧面板的历史轮次视图)也完全没有点击跳转功能,只有回滚按钮。如果打算一起修可以考虑。
Summary
长会话中打开右上角轮次列表,点击某个轮次标题后列表关闭,但聊天视图不滚动到对应轮次。左右箭头按钮的逐轮跳转正常工作,说明底层导航能力存在但轮次列表点击无法触发。
Area
Web UI / Flow Chat
Environment
Reproduction
Root Cause Analysis
问题链路如下:
1. 入口 —
FlowChatHeader.tsxhandleTurnSelect2. 跳转实现 —
ModernFlowChatContainer.tsxhandleJumpToTurn3. 根因
pinTurnToTop是虚拟滚动列表VirtualMessageList的方法。当它返回false(列表未完全就绪、turnId 在虚拟化 items 中暂时不可用、reconcile 未完成等),跳转静默失败。但
handleTurnSelect在调用onJumpToTurn后立即且无条件执行setIsTurnListOpen(false)——无论跳转是否成功。用户看到的就是点击后列表关闭、但视图停留在原地。4. 同类问题参考
今天合入的 PR #1279(Code Editor 范围导航)是同一类时序问题:操作在底层组件就绪前触发,动作静默丢失。该 PR 的解决方案是引入
PendingNavigationRequest状态机,追踪待处理请求并等 viewport 就绪后重试。Suggested Fix
参考 PR #1279 的思路:
方案 A(推荐,Header + Container 配合):
handleJumpToTurn失败时记录 pending turn ID,监听virtualItems变化,当 pending turn 在渲染范围内时重新执行跳转,成功后清除 pendinghandleTurnSelect中直接关闭面板,改为依赖已有的useEffect(() => setIsTurnListOpen(false), [currentTurn])。如果currentTurn不变(跳转失败),面板保持打开方案 B(仅 Header 兜底):
handleTurnSelect不无条件关闭面板,等待onJumpToTurn的确认后再关闭onJumpToTurn返回成功/失败状态Relevant Code
src/web-ui/src/flow_chat/components/modern/FlowChatHeader.tsx—handleTurnSelectsrc/web-ui/src/flow_chat/components/modern/ModernFlowChatContainer.tsx—handleJumpToTurnsrc/web-ui/src/flow_chat/components/modern/useFlowChatNavigation.ts— 轮次导航事件src/web-ui/src/flow_chat/components/modern/VirtualMessageList.tsx—pinTurnToTop实现另外提一句:
TurnHistoryPanel.tsx(侧面板的历史轮次视图)也完全没有点击跳转功能,只有回滚按钮。如果打算一起修可以考虑。