fix(chat): 打开主 Agent 会话默认贴底并完整显示最后一条
最后一条 final answer 的完整内容是懒加载(AnswerBlock useInView+fetchDetail), 在 activity 数组稳定后才撑开高度,而滚动 layout effect 只依赖 activity 引用、 不会因高度变化重触发,导致打开后最后一条被顶到屏幕外。新增 ResizeObserver 观测 transcript 容器:用户仍贴底时,任何高度变化(transcript 挂载/详情展开/markdown 撑高) 都重新贴底;手动上滚则不再拽回。planner/worker 会话同样受益。 Claude-Session: https://claude.ai/code/session_01RVrPtpngE9T9DRJHosf6MB
This commit is contained in:
1 parent
a98081eea9
commit
39c540edfc
1 file changed
+20
@@ -1004,6 +1004,26 @@ export function SessionsTab({ taskId }: { taskId: string }) {
|
||||
const vp = viewport();
|
||||
if (vp) vp.scrollTop = vp.scrollHeight;
|
||||
}, [activity, viewport]);
|
||||
// Lazy detail loads (AnswerBlock / ToolBlock / Markdown) grow the content AFTER the
|
||||
// activity array settles, WITHOUT changing its reference — so the layout effects
|
||||
// above never re-fire and a freshly opened session would leave its last message
|
||||
// scrolled partly off-screen (the final answer expands from a one-line summary to
|
||||
// full markdown below the fold). A ResizeObserver re-pins to the bottom on any
|
||||
// height change while the user is still at the bottom, so opening the main agent
|
||||
// lands on the last message fully shown. contentRef's div is always mounted, so the
|
||||
// observer catches the transcript mounting + each detail expanding.
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: activeId intentionally rebinds the observer to the new session's content.
|
||||
React.useEffect(() => {
|
||||
const el = contentRef.current;
|
||||
if (!el || typeof ResizeObserver === "undefined") return;
|
||||
const ro = new ResizeObserver(() => {
|
||||
if (!atBottomRef.current) return;
|
||||
const vp = viewport();
|
||||
if (vp) vp.scrollTop = vp.scrollHeight;
|
||||
});
|
||||
ro.observe(el);
|
||||
return () => ro.disconnect();
|
||||
}, [activeId, viewport]);
|
||||
|
||||
function stop() {
|
||||
if (stopping) return;
|
||||
|
||||
Reference in new issue
Block a user