Skip to content

[APP-3658] Fix reopening long alt text scrolling the sheet offscreen on iOS - #12196

Draft
mozzius wants to merge 1 commit into
mainfrom
samuel/app-3658-alt-text-reopen-overshoot
Draft

mozzius wants to merge 1 commit into
mainfrom
samuel/app-3658-alt-text-reopen-overshoot

Conversation

@mozzius

@mozzius mozzius commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Fixes APP-3658.

Problem

On iOS, reopening the alt text editor with a long alt text scrolls the sheet past the end of its content. The longer the text, the further it goes. With 30 lines the sheet opens completely blank. It's a regression in 1.136.0.

Root cause

  1. A full-height sheet's content gets its first layout before the native canvas size exists. The native view is position: absolute with only left/right set, so that first layout shrinks to fit the content.
  2. In that pass, Yoga measures each flex: 1 wrapper's flex basis at the content height (1620pt for 30 lines) and keeps it. Yoga only recomputes a basis when that node itself is dirtied. This is facebook/yoga#2019, the same bug as APP-2687; the fix is pending in facebook/yoga#2020.
  3. SheetView then sets the canvas to 812pt, synchronously, before presenting. That only dirties the sheet node, so its children reuse the stale 1620 basis. flex: 1 doesn't shrink on native, so the content stays 1620pt tall. Short content still grows to fill the canvas, which is why only long alt text broke.
  4. The autofocused input raises the keyboard mid-present. Since [APP-2673] Fix the alt text sheet not scrolling when its input autofocuses #12121, the ScrollView's automaticallyAdjustKeyboardInsets is already on at that point, so RN sizes the keyboard inset from the 1620pt frame: 1153 instead of 335. The JS maxHeight from onPresentationSizeChange shrinks the content to 802 right after (a node's own style change does clear its basis), but nothing recomputes the inset.

Before #12121, RN skipped the inset entirely on that first keyboard show. That was APP-2673, and it hid all of this.

Native logging from a QA build, reopening 30 lines (the "chain" is the mounted views from the sheet down to the ScrollView):

updateCanvasSize height=812  sheet 1620 -> 812
  chain after: RCTViewComponentView:1620 > RCTScrollViewComponentView:1620   <- stale basis, never shrinks
keyboardWillChangeFrame  scrollView=1620
after keyboard: inset=1153

Fix

Full-height iOS sheets now get top: 0, bottom: 0 as well as left/right. That's the vertical twin of the APP-3602 width fallback. Their first layout then has a definite height, so Yoga never measures a content-sized basis, and the canvas size really does constrain the content before the sheet is presented.

  • It's JS-only, so it can go out as an OTA.
  • Auto-height sheets are unchanged. They still need the fit-to-content first layout to pick their detent.

The inset now comes out at 345 rather than exactly 335. Until the presented size lands, the seeded canvas (window height minus the top safe area, 812) is 10pt taller than the sheet (802). It isn't visible in practice. A native change that attaches the content only after the sheet's first layout pass makes it exact (335). I prototyped and verified that change, but left it out to keep this PR JS-only. It can be a follow-up if we want it.

This replaces the first version of this PR, which deferred Dialog.Input autofocus. That version was dropped when the branch was rebased onto main.

Testing

Tested on the iPhone 17 sim (iOS 26.5). The QA dev client had native logging and a launch-arg switch, so it could run the production native code paths.

Reopening 30 lines of alt text:

updateCanvasSize height=812  sheet 812 -> 812
  chain after: RCTViewComponentView:812 > RCTScrollViewComponentView:812
keyboardWillChangeFrame  scrollView=812
after keyboard: inset=345   (was 1153)
Before (main) After
30 lines reopened on main: blank sheet 30 lines reopened with the fix: caret on the last line above the keyboard
  • Reopening 30 lines: the caret is visible above the keyboard, and you can scroll to the image and to Save.
  • Reopening 8 lines.
  • First open with empty alt text: the keyboard comes up by itself and Save is reachable, so no APP-2673 regression.
  • Other full-height sheets still look and behave the same: Add App Password (still autofocuses), Edit profile, the GIF picker, the content language list, and Add to lists.
  • An auto-height sheet (a post's "…" menu) still sizes to its content.
  • A two-pass yoga-layout script reproduces the stale basis. With the insets, every wrapper goes 812 -> 802.
  • pnpm typecheck and the bottom-sheet tests pass.

Earlier comments on this PR are about the first version.

🤖 Generated with Claude Code

@linear-code

linear-code Bot commented Oct 26, 2026

Copy link
Copy Markdown

APP-3658

@github-actions

Copy link
Copy Markdown
Contributor
Size Old size New size Diff
Uncompressed 9.64 MB 9.64 MB 0 B (0.00%)
Gzip 2.83 MB 2.83 MB 0 B (0.00%)

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

The OTA deployment for this PR was successful! You may now apply it by either scanning the QR code or opening the deep link below in your browser:

QR code for the PR OTA deployment

bluesky://intent/apply-ota?channel=pull-request-12196&releaseVersion=1.137.0&iosBuildNumber=2217&androidBuildNumber=1668

@mozzius

mozzius commented Oct 26, 2026

Copy link
Copy Markdown
Member Author

Verified on the iPhone 17 sim (iOS 26.5) with an RN 0.88 dev client.

Reopening 30 lines of alt text, same instrumentation as the PR description:

ScrollView onLayout         height=1620
onPresentationSizeChange    height=802
ScrollView onLayout         height=802    <- clamped before the keyboard shows
keyboardWillShow            height=335
onScroll                    contentInset.bottom=335 (was 1153), stays 335

The caret lands on the last line just above the keyboard. You can scroll up to the image and down to Save.

Before After
30 lines reopened, before: blank sheet 30 lines reopened, after: caret on the last line above the keyboard

Other checks

  • 8 lines reopened: the whole sheet is visible, nothing scrolled.
  • First open with empty alt text (APP-2673 check): the keyboard comes up by itself and Save is reachable.
  • App passwords > Add App Password: still autofocuses, with the generated name selected.
  • Timing: keyboardWillShow fires about 37ms later than before. The keyboard still comes up alongside the sheet animation.
8 lines First open App password dialog
8 lines reopened first open, empty alt text app password dialog autofocus

@mozzius
mozzius marked this pull request as ready for review October 26, 2026 12:16
@claude

claude Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @mozzius's task in 22s —— View job


I didn't find any actionable defects in this PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
samuel/app-3658-alt-text-reopen-overshoot - social-app PR #12196 — 26ed3dbc Deployed Oct 26, 2026 by arcalinea
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.

2 participants