Repository navigation
fix(zero-swift): line up clamped jumps, re-pick the anchor row, and page onto the screen above a permalink - #81
Merged
Conversation
…age onto the screen above a permalink Three more cases where VirtualList and VirtualListView were left wrong until the next scroll, on iOS and macOS. Stacked on the fix for content shrinking at the bottom, which changes the same code in VirtualizerCore. - A jump to a loaded row near the end of the loaded rows, with nothing seen below them, was clamped there and released, and the row was never lined up as rows loaded below. A jump clamped short of the list's own end now scrolls on to its row as rows load, until it lines up, the list's end clamps it, or the user scrolls. It's still released, so paging carries on. Upstream releases it; UPSTREAM.md records the divergence. - The reference row manual anchoring keeps in place was picked only at a scroll. After a scroll up into the space above the loaded rows, that was their first row, below the viewport, and the page loading above pushed it down the screen, so a row above it changing height moved the rows above it. It's now picked again whenever the rows are in place, as native anchoring does. Upstream picks it only at a scroll; UPSTREAM.md records the divergence. - Scrolled up past the rows of a list opened at a permalink, the page before them shares none of their rows, so carrySpace kept the space as it was: the reserve such a list keeps above its rows, which put the page where the old rows were, below the viewport. The list paged on to its start and back, blank. A page that shares no row with the last one now goes where the space estimated its rows, from the space as it was. How a permalink opens is unchanged. Amp-Thread-ID: https://ampcode.com/threads/T-01a19fc4-5fb6-711a-b937-d8c57793372f Co-authored-by: tmm <tmm@tmm.dev>
tmm
force-pushed
the
swift-virtual-jump-anchor-fixes
branch
from
November 3, 2026 07:34
03c688c to
d957eba
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #80. Both change
VirtualizerCorearound the same paths (carrySpace,land,afterUpdate), so this PR targets #80's branch,swift-virtual-bottom-fixes. Merge #80 first, and GitHub retargets this one tomain.Three more cases where
VirtualListandVirtualListViewwere left wrong until the next scroll, on iOS and macOS, from the same bug hunt. Two of them (4 and 5) are deliberate divergences from upstream, which behaves the same way;UPSTREAM.mdrecords both and why.4. A clamped jump to a loaded row is never lined up.
scrollToItemto a loaded row near the end of the loaded rows, with nothing seen below them, landed short. For example,.centeron the second-to-last loaded row put it at 355 of a 400pt viewport. It stayed there when the rows below loaded.landreleases a jump once its window settles, clamped or not, so paging isn't held up. Nothing scrolls into the room the rows loading below make.#landatf89c468releases it the same way. We diverge because the row the app asked for should end up where it asked.5. The anchor row goes stale after paging up into space. After a fast scroll up past the loaded rows, a row on screen changing height (an image loading, text reflowing) moved the rows above it instead of the ones below.
measureAndCompensatepicks the reference again: the first row reaching below the viewport's top, as native scroll anchoring picks it on each layout.#refreshAnchorhas the same timing. We diverge because native anchoring, which this stands in for, re-picks every layout.6. A blank screen scrolling up past the rows of a list opened at a permalink. Scrolled up past the loaded rows in one go, the screen stayed blank while the list loaded pages back to its start and forward again. On a real
VirtualListViewit was 10 blank frames, and the list ended at its first row.carrySpacefound no row in common and left the space as it was: the reserve of space a list opened away from its start keeps above its rows. That put the new page where the old rows were, below the viewport.Tests. Each new
LayoutHostTeststest fails without the fix:Verified locally:
swift teston macOS: everything passes, including the fling tests (flingKeepsGoing,flingsUpFromAPermalink).VirtualListViewand on the SwiftUIVirtualListon macOS, with a scratch test. Without the fix the row lands at 355 instead of 200, and the list goes blank and ends at its start.It found one rare, older failure that this PR doesn't address. A window at the list's start ends above the viewport and the page after it starts below it, so paging switches between them without settling. It shows on #80's tree too.