mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(ui-tui): clear sticky prompt when follow snaps to bottom
Renderer-driven follow-to-bottom was restoring the viewport to the tail without notifying ScrollBox subscribers, so StickyPromptTracker could stay stale-visible. Notify on render-time scroll/sticky changes and treat near-bottom as bottom for prompt hiding.
This commit is contained in:
parent
c8ff70fe03
commit
aa47812edf
4 changed files with 15 additions and 2 deletions
|
|
@ -257,6 +257,7 @@ function ScrollBox({ children, ref, stickyScroll, ...style }: PropsWithChildren<
|
|||
|
||||
if (el) {
|
||||
el.scrollTop ??= 0
|
||||
el.notifyScrollChange = notify
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ export type DOMElement = {
|
|||
scrollViewportHeight?: number
|
||||
scrollViewportTop?: number
|
||||
stickyScroll?: boolean
|
||||
notifyScrollChange?: () => void
|
||||
// Set by ScrollBox.scrollToElement; render-node-to-output reads
|
||||
// el.yogaNode.getComputedTop() (FRESH — same Yoga pass as scrollHeight)
|
||||
// and sets scrollTop = top + offset, then clears this. Unlike an
|
||||
|
|
|
|||
|
|
@ -761,6 +761,7 @@ function renderNodeToOutput(
|
|||
// active text selection by the same delta (native terminal behavior:
|
||||
// view keeps scrolling, highlight walks up with the text).
|
||||
const scrollTopBeforeFollow = node.scrollTop ?? 0
|
||||
const stickyBeforeFollow = node.stickyScroll
|
||||
|
||||
const sticky = node.stickyScroll ?? Boolean(node.attributes['stickyScroll'])
|
||||
|
||||
|
|
@ -863,6 +864,10 @@ function renderNodeToOutput(
|
|||
scrollDrainNode = node
|
||||
}
|
||||
|
||||
if ((node.scrollTop ?? 0) !== scrollTopBeforeFollow || node.stickyScroll !== stickyBeforeFollow) {
|
||||
node.notifyScrollChange?.()
|
||||
}
|
||||
|
||||
scrollTop = clamped
|
||||
|
||||
if (content && contentYoga) {
|
||||
|
|
|
|||
|
|
@ -256,15 +256,21 @@ export function StickyPromptTracker({ messages, offsets, scrollRef, onChange }:
|
|||
}
|
||||
|
||||
const top = Math.max(0, s.getScrollTop() + s.getPendingDelta())
|
||||
const vp = Math.max(0, s.getViewportHeight())
|
||||
const total = Math.max(vp, s.getScrollHeight())
|
||||
const atBottom = s.isSticky() || top + vp >= total - 2
|
||||
|
||||
return s.isSticky() ? -1 - top : top
|
||||
return atBottom ? -1 - top : top
|
||||
},
|
||||
() => NaN
|
||||
)
|
||||
|
||||
const s = scrollRef.current
|
||||
const top = Math.max(0, (s?.getScrollTop() ?? 0) + (s?.getPendingDelta() ?? 0))
|
||||
const text = stickyPromptFromViewport(messages, offsets, top, s?.isSticky() ?? true)
|
||||
const vp = Math.max(0, s?.getViewportHeight() ?? 0)
|
||||
const total = Math.max(vp, s?.getScrollHeight() ?? vp)
|
||||
const atBottom = (s?.isSticky() ?? true) || top + vp >= total - 2
|
||||
const text = stickyPromptFromViewport(messages, offsets, top, atBottom)
|
||||
|
||||
useEffect(() => onChange(text), [onChange, text])
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue