Fix masonry visibility so viewport-overlapping items are not omitted#2374
Open
momomuchu wants to merge 1 commit into
Open
Fix masonry visibility so viewport-overlapping items are not omitted#2374momomuchu wants to merge 1 commit into
momomuchu wants to merge 1 commit into
Conversation
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.
Fix masonry visibility so viewport-overlapping items are not omitted
Bug
In a masonry
FlashList, items that overlap the viewport can be omitted from render. Reported case: item 25, whose layout overlaps the viewport range 3600..4100, was not rendered.Root cause
The base
RVLayoutManager.getVisibleLayoutsusesbinarySearchVisibleIndex, which (per its own docstring) assumes the layouts array is pre-sorted by the relevant dimension. That holds for linear and grid layouts, but not for masonry: masonry assigns items round-robin to the shortest column, solayouts[i].yis not monotonic in index. A later index can sit at a smallerythan an earlier one. The binary search then skips over items that are actually on screen.Fix
Override
getVisibleLayoutson the masonry layout manager to compute visibility by actual layout overlap (layout.yandlayout.y + heightagainst the viewport) instead of the sorted-array binary search. It returns a contiguousConsecutiveNumbersrange from the first to the last visible masonry index, matching the existing render-stack contract shape.The override lives only on the masonry subclass. Linear and grid layout managers extend the base class directly and are unaffected.
Tests
Added
src/__tests__/MasonryLayoutManager.test.ts:Reverting only the source change makes the RED test fail with the exact reported symptom (
missingVisibleIndices: [25]), so the test has teeth.Note on over-render
getVisibleLayoutsmust return a contiguousConsecutiveNumbersrange, so on masonry it returns the span from the first to the last visible index. When columns are reasonably balanced this includes at most a couple of off-screen indices. In a pathological case (one item far taller than its neighbors, so a visible item sits many indices away from another visible item) the span can include more off-screen indices, up to O(n) in the worst construction. That over-render is inherent to the contiguous return type, not new to this change: it is the minimum span that still contains every visible index. The key property is that no visible item is ever omitted. The previous binary-search behavior omitted the visible item in exactly that tall-item case (the bug being fixed here), so this is a strict correctness improvement, and the contiguous-range contract shape is unchanged.If a maintainer prefers to cap the rendered span for very large masonry lists, a per-column visible-index computation would be a natural follow-up, but it is out of scope for this correctness fix.
Fixes #2270