diff --git a/ui-tui/src/app/useSessionLifecycle.ts b/ui-tui/src/app/useSessionLifecycle.ts index e4da3e1bf8..acd10135e1 100644 --- a/ui-tui/src/app/useSessionLifecycle.ts +++ b/ui-tui/src/app/useSessionLifecycle.ts @@ -186,7 +186,7 @@ export function useSessionLifecycle(opts: UseSessionLifecycleOptions) { status: 'ready', usage: usageFrom(r.info ?? null) }) - queueMicrotask(() => scrollRef.current?.scrollToBottom()) + setTimeout(() => scrollRef.current?.scrollToBottom(), 0) }) .catch((e: Error) => { sys(`error: ${e.message}`) diff --git a/ui-tui/src/hooks/useVirtualHistory.ts b/ui-tui/src/hooks/useVirtualHistory.ts index d33971fede..efa2642df3 100644 --- a/ui-tui/src/hooks/useVirtualHistory.ts +++ b/ui-tui/src/hooks/useVirtualHistory.ts @@ -38,6 +38,7 @@ export function useVirtualHistory( const refs = useRef(new Map void>()) const [ver, setVer] = useState(0) const [hasScrollRef, setHasScrollRef] = useState(false) + const metrics = useRef({ sticky: true, top: 0, vp: 0 }) useLayoutEffect(() => { setHasScrollRef(Boolean(scrollRef.current)) @@ -141,10 +142,29 @@ export function useVirtualHistory( } } + const s = scrollRef.current + + if (s) { + const next = { + sticky: s.isSticky(), + top: Math.max(0, s.getScrollTop() + s.getPendingDelta()), + vp: Math.max(0, s.getViewportHeight()) + } + + if ( + next.sticky !== metrics.current.sticky || + next.top !== metrics.current.top || + next.vp !== metrics.current.vp + ) { + metrics.current = next + dirty = true + } + } + if (dirty) { setVer(v => v + 1) } - }, [end, items, start]) + }, [end, hasScrollRef, items, scrollRef, start]) return { bottomSpacer: Math.max(0, total - (offsets[end] ?? total)),