Before submitting
Area
apps/web
Steps to reproduce
- With Collapse composer on scroll on, open a thread and scroll a few turns up from the end.
- Switch to another thread while the agent in the first one keeps working and adds turns.
- Switch back. The thread reopens where I left it, above its end, as intended; the new turns below it haven't been rendered yet.
- Leave the composer empty and scroll the thread with the mouse wheel, up or down.
The same happens whenever a thread opens above its end before its last rows have rendered, for example through #14051.
Expected behavior
The composer rests to a single line on the first scroll, as it does when the thread was opened at its end.
Actual behavior
It stays fully expanded however much I scroll. Only when I reach the very end of the thread does it rest, and after that it collapses and expands normally.
Likely cause
From reading the code:
- The composer rests only while
timelineOverflows is true (shouldUseRestingComposerLayout in composerFooterLayout.ts).
timelineContentOverflowsViewport (timelineScrollAnchoring.ts) computes that from the bottom of the last row via getRowBottom, which needs state.sizeAtIndex(last).
- In LegendList,
sizeAtIndex returns sizesKnown.get(id): only rows that have been rendered and measured. When the thread opens above its end, the last row hasn't been rendered, getRowBottom returns null, and the function reports "fits", as its comment says ("Unknown row geometry … counts as fitting").
- The wheel still sets the scroll-collapse flag, because
canScrollCollapseComposer doesn't depend on timelineOverflows. That's why the composer rests the moment the last row renders at the end.
If the thread's latest rows have already rendered in this session (I was at its end and nothing was added since), LegendList knows the last row's size and resting works; that's why this only shows up after new turns or an above-the-end open.
Suggested fix
positionAtIndex(last) is known even when the size isn't: whenever the data changes, LegendList positions every row, using estimated sizes for rows it hasn't measured. getRowBottom could treat an unknown size as its lower bound (it already clamps the height to at least 1px) instead of returning null. Resting still needs a real scroll gesture, so a thread that genuinely fits is unaffected.
Related
This is not #14051: it happens when position restore works as intended, and #13602 doesn't touch it.
Impact
Minor bug or occasional failure
Version or commit
0.0.43-nightly.20260928.2375; code references are to main @ d2c9281 with @legendapp/list 3.3.5
Environment
Desktop app on Linux (NixOS, Wayland, niri)
Logs or stack traces
Screenshots, recordings, or supporting files
No response
Workaround
Scroll to the very end of the thread once.
Before submitting
Area
apps/web
Steps to reproduce
The same happens whenever a thread opens above its end before its last rows have rendered, for example through #14051.
Expected behavior
The composer rests to a single line on the first scroll, as it does when the thread was opened at its end.
Actual behavior
It stays fully expanded however much I scroll. Only when I reach the very end of the thread does it rest, and after that it collapses and expands normally.
Likely cause
From reading the code:
timelineOverflowsis true (shouldUseRestingComposerLayoutincomposerFooterLayout.ts).timelineContentOverflowsViewport(timelineScrollAnchoring.ts) computes that from the bottom of the last row viagetRowBottom, which needsstate.sizeAtIndex(last).sizeAtIndexreturnssizesKnown.get(id): only rows that have been rendered and measured. When the thread opens above its end, the last row hasn't been rendered,getRowBottomreturnsnull, and the function reports "fits", as its comment says ("Unknown row geometry … counts as fitting").canScrollCollapseComposerdoesn't depend ontimelineOverflows. That's why the composer rests the moment the last row renders at the end.If the thread's latest rows have already rendered in this session (I was at its end and nothing was added since), LegendList knows the last row's size and resting works; that's why this only shows up after new turns or an above-the-end open.
Suggested fix
positionAtIndex(last)is known even when the size isn't: whenever the data changes, LegendList positions every row, using estimated sizes for rows it hasn't measured.getRowBottomcould treat an unknown size as its lower bound (it already clamps the height to at least 1px) instead of returningnull. Resting still needs a real scroll gesture, so a thread that genuinely fits is unaffected.Related
This is not #14051: it happens when position restore works as intended, and #13602 doesn't touch it.
Impact
Minor bug or occasional failure
Version or commit
0.0.43-nightly.20260928.2375; code references are to main @ d2c9281 with
@legendapp/list3.3.5Environment
Desktop app on Linux (NixOS, Wayland, niri)
Logs or stack traces
Screenshots, recordings, or supporting files
No response
Workaround
Scroll to the very end of the thread once.