fix(tui): recompute virtual tail after width resize

Avoid preserving a frozen virtual transcript range when wrapped rows shrink enough that the old tail window no longer covers the viewport.
This commit is contained in:
Brooklyn Nicholson
2026-05-23 14:49:26 -05:00
parent 521c870a05
commit 2a75bec607
2 changed files with 68 additions and 5 deletions
+21 -2
View File
@@ -248,8 +248,26 @@ export function useVirtualHistory(
// During a freeze, drop the frozen range if items shrank past its start
// (/clear, compaction) — clamping would collapse to an empty mount and
// flash blank. Fall through to the normal path in that case.
const frozenRange =
freezeRenders.current > 0 && prevRange.current && prevRange.current[0] < n ? prevRange.current : null
const frozenRangeCandidate =
freezeRenders.current > 0 && prevRange.current && prevRange.current[0] < n
? ([prevRange.current[0], Math.min(prevRange.current[1], n)] as const)
: null
// Width grows can shrink wrapped rows enough that the old tail window no
// longer covers the viewport. In that case freezing preserves stale spacers
// and visually cuts off the last message, so recompute immediately.
const frozenRange = (() => {
if (!frozenRangeCandidate || vp <= 0) {
return frozenRangeCandidate
}
const visibleTop = sticky && !recentManual ? Math.max(0, total - vp) : target
const visibleBottom = visibleTop + vp
const rangeTop = offsets[frozenRangeCandidate[0]] ?? 0
const rangeBottom = offsets[frozenRangeCandidate[1]] ?? total
return rangeTop <= visibleTop && rangeBottom >= visibleBottom ? frozenRangeCandidate : null
})()
let start = 0
let end = n
@@ -464,6 +482,7 @@ export function useVirtualHistory(
if (skipMeasurement.current) {
skipMeasurement.current = false
bumpMeasuredHeightVersion(n => n + 1)
} else {
for (let i = effStart; i < effEnd; i++) {
const k = items[i]?.key