fix(app): stabilize native composer sizing after edits (#4946)

* fix(app): stabilize native composer sizing after edits

* test(app): verify workspace composer space after keyboard dismissal

* test(app): start the hold-to-delete regression mid-draft

From the end of the draft the pre-fix input also returns to baseline. Placing the cursor
eight lines into the draft before the first hold-delete leaves the old build at the
capped height with the placeholder visible, and the fixed build at one line.
This commit is contained in:
Mohamed Boudra
2026-09-16 15:51:22 +02:00
committed by GitHub
parent a78949d1d4
commit 0e8a71a5fe
11 changed files with 137 additions and 41 deletions
+17 -9
View File
@@ -160,15 +160,23 @@ motion settles; never drive it per frame.
The translated dock's height is not the composer's available height. Bound the
composer against the stationary space below the header through
`composer/viewport`, including its controls and attachments. Reserve the
keyboard destination at move start on the UI thread. Keep the last nonzero
reservation when the keyboard closes so an unchanged draft does not expand.
Viewport changes and subsequent keyboard openings recalculate the capacity.
Waiting for a settled JS update lets a long draft disappear behind the header
during opening. This is a boundary-time layout change, not an animated
layout prop. Keep the input's native intrinsic sizing and internal scrolling.
New workspace also needs its setup fields to scroll when the form exceeds this
space. The Android regression must check both the header and IME boundaries;
checking only the bottom controls allowed this regression through previously.
keyboard destination at move start on the UI thread. Waiting for a settled JS
update lets a long draft disappear behind the header during opening. This is a
boundary-time layout change, not an animated layout prop. Keep the input's
native intrinsic sizing and internal scrolling. Keep the editing input's
`defaultValue` current on every edit: Fabric re-measures the Android input from
the JS text whenever its frame changed, so a stale prop inflates or collapses
the input (see `packages/app/src/components/ui/text-input/text-input.native.tsx`).
What the closed keyboard leaves behind is the viewport's `keyboardReserve`
policy. A docked chat composer retains its last reservation so an unchanged
capped draft does not expand over the stream; subsequent keyboard openings
recalculate it. New workspace releases it: its setup fields scroll inside the
same constrained space while the keyboard is open, so keeping the reservation
after it closes leaves the form clipped and the composer small with the screen
empty above them. The Android regression must check both the header and IME
boundaries; checking only the bottom controls allowed this regression through
previously.
Move the stream and composer together through `KeyboardDock`. Do not translate
them independently.