fix(tui): stabilize live progress rendering

This commit is contained in:
Brooklyn Nicholson 2026-04-26 15:23:43 -05:00
parent d4dde6b5f2
commit a7831b63db
28 changed files with 619 additions and 154 deletions

View file

@ -38,6 +38,7 @@ export type ScrollBoxHandle = {
* padding). Used for drag-to-scroll edge detection.
*/
getViewportTop: () => number
getLastManualScrollAt: () => number
/**
* True when scroll is pinned to the bottom. Set by scrollToBottom, the
* initial stickyScroll attribute, and by the renderer when positional
@ -94,6 +95,7 @@ function ScrollBox({ children, ref, stickyScroll, ...style }: PropsWithChildren<
// forces a React render: sticky is attribute-observed, no DOM-only path.
const [, forceRender] = useState(0)
const listenersRef = useRef(new Set<() => void>())
const manualScrollAtRef = useRef(0)
const renderQueuedRef = useRef(false)
const notify = () => {
@ -130,6 +132,7 @@ function ScrollBox({ children, ref, stickyScroll, ...style }: PropsWithChildren<
}
el.stickyScroll = false
manualScrollAtRef.current = Date.now()
el.scrollAnchor = undefined
el.pendingScrollDelta = (el.pendingScrollDelta ?? 0) + Math.floor(dy)
scrollMutated(el)
@ -148,6 +151,7 @@ function ScrollBox({ children, ref, stickyScroll, ...style }: PropsWithChildren<
// Explicit false overrides the DOM attribute so manual scroll
// breaks stickiness. Render code checks ?? precedence.
el.stickyScroll = false
manualScrollAtRef.current = Date.now()
el.pendingScrollDelta = undefined
el.scrollAnchor = undefined
el.scrollTop = Math.max(0, Math.floor(y))
@ -161,6 +165,7 @@ function ScrollBox({ children, ref, stickyScroll, ...style }: PropsWithChildren<
}
box.stickyScroll = false
manualScrollAtRef.current = Date.now()
box.pendingScrollDelta = undefined
box.scrollAnchor = {
el,
@ -205,6 +210,9 @@ function ScrollBox({ children, ref, stickyScroll, ...style }: PropsWithChildren<
getViewportTop() {
return domRef.current?.scrollViewportTop ?? 0
},
getLastManualScrollAt() {
return manualScrollAtRef.current
},
isSticky() {
const el = domRef.current