Skip to content

fix: follow gradual item resizes when maintaining scroll at end - #507

Open
focux wants to merge 1 commit into
LegendApp:mainfrom
focux:fix/follow-gradual-item-resize-at-end
Open

fix: follow gradual item resizes when maintaining scroll at end#507
focux wants to merge 1 commit into
LegendApp:mainfrom
focux:fix/follow-gradual-item-resize-at-end

Conversation

@focux

@focux focux commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Description

When an item in an end-anchored list (maintainScrollAtEnd + onItemLayout) resizes gradually — e.g. a Reanimated layout animation growing a chat row a few px per frame — the end anchor fails to follow: each step is under the 5px threshold in updateItemSizes, and when a delta does qualify, doMaintainScrollAtEnd defers to a rAF + animated scroll with a 500ms settling lock. Measured on a 240fps recording of our chat app: the growing row sits clipped below the viewport for ~500ms, then catches up in uneven 2–8px steps.

Two changes:

  1. 5px threshold → noise epsilon. The 5px dates to 0f53b8e; its load-bearing part was prevSizeKnown !== undefined (kept). Since ff3f8c7, isNativeLayoutNoise already rejects sub-pixel noise before this check, so 5px only swallows real resizes. The check now reuses that epsilon.
  2. Resize follows are immediate + non-animated. The item-resize call site passes { animated: false, immediate: true } — a measured resize is already the real layout, so follow it synchronously instead of racing a 500ms scroll animation against the growth. Omitted options preserve current behavior; the data-change path (checkResetContainers) is untouched.

Related: #492.

Tests

Options coverage in doMaintainScrollAtEnd (immediate skips rAF, animated: false overrides, defaults unchanged) and threshold coverage in updateItemSize (~2px known-item resize flags maintenance, sub-epsilon doesn't). 1516 pass / 0 fail, Biome clean.


Disclaimer: The fix was made by Claude Code using Fable and it fixes some issues we had on our chat list.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 28112f1b1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

state.maintainingScrollAtEnd = undefined;
if (state.pendingMaintainScrollAtEnd) {
doMaintainScrollAtEnd(ctx);
doMaintainScrollAtEnd(ctx, options);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the options of the coalesced maintain request

When an animated data-change maintain is in its 500 ms settling window and an item resize arrives, the latter only sets the boolean pendingMaintainScrollAtEnd, so this callback replays it with the first call's options (undefined). The resize therefore becomes another animated, frame-deferred maintain instead of the intended { animated: false, immediate: true }, retaining the delayed correction this change is meant to fix. Conversely, a data-change request queued behind an instant resize inherits the resize options and loses its configured animation; the pending state needs to retain or merge the options of the request being coalesced.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant