mirror of
https://github.com/block/buzz.git
synced 2026-11-09 19:02:00 +00:00
On iPhone, opening Control Center or the app switcher while the composer is focused can leave the keyboard up over a collapsed composer. The orphaned keyboard then stays put while you navigate, for example back from a thread to its channel, and it clips the composer pill. ### Cause iOS reports a zero keyboard inset while the app is inactive and restores the keyboard natively when the app returns. The composer treated any inset drop as a user dismissal: it collapsed, unfocused and removed its text field. When the keyboard came back, it was attached to no Flutter field, so nothing could dismiss it. Flutter's own report of the native side is [flutter/flutter#189051](https://github.com/flutter/flutter/issues/189051). ### Change The composer's keyboard observer ignores metrics while the app is not resumed. iOS reports `resumed` with the inset still at zero and brings the keyboard back a few hundred milliseconds later, so when a keyboard that was up hasn't returned at resume, the composer waits a one-second grace before treating it as dismissed. Any nonzero inset in that window cancels the wait. A restored keyboard leaves the composer expanded and focused; a keyboard that really stayed down still collapses the composer once the grace passes. ### Validation - Extended the existing "returns to the compact capsule when the keyboard drops" widget journey with both inactive cases in the order iOS reports them: resumed at zero with the keyboard returning about 400 ms later (composer stays focused), and resumed with the keyboard staying down (composer collapses after the grace). It fails without the fix and against the first revision of this PR. - Full mobile check and test suite pass. - iOS 27 simulator (iPhone 17 Pro, debug build of the first revision): focused the composer, typed, switched to Settings and back, opened and closed Control Center, sent a message, and left the channel. The composer stayed focused through each interruption, sending kept focus, and leaving dismissed the keyboard. Limitation: the simulator keeps the keyboard inset through these interruptions, so it reproduces neither the original bug nor the resume grace; the on-device inset drop is from the reporter's screen recording and the Flutter issue. Human app testing is waived under the mobile testing exception; the simulator pass above is the automated full-app run. buzz-review-completed 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Tom Brow <tomb@squareup.com> Co-authored-by: Tom Brow <tomb@squareup.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>