Repro: composer inflates and collapses message list on iOS device unlock - #3802
Closed
amit-hinge wants to merge 1 commit into
Closed
amit-hinge wants to merge 1 commit into
amit-hinge wants to merge 1 commit into
Conversation
Wraps MessageComposer in an RN KeyboardAvoidingView (behavior="padding"), nested inside Channel's own KeyboardCompatibleView which is also in padding mode. On a physical iOS device, locking the screen while the composer is focused makes iOS emit a burst of keyboardWillShow/keyboardDidShow events with all coordinates zeroed. KeyboardCompatibleView is unaffected because it unsubscribes its keyboard listeners on AppState background, but RN's KeyboardAvoidingView has no AppState handling and processes every bogus frame, growing unboundedly and collapsing the message list until the real keyboard event arrives.
6 tasks
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.
π― Goal
Not intended to be merged β this is a minimal reproduction to accompany the message-list flicker issue we reported in our shared support channel (follow-up for @isekovanic).
On a physical iOS device, locking the screen while the composer is focused causes the message list to collapse and snap back β a visible flicker. Our earlier theory (the
connection.changedβresyncChannel()reconnect path) was wrong; we instrumented that on device and it doesn't fire during most reproductions. The actual trigger is nested keyboard avoidance, which this PR isolates inSampleApp.π Implementation details
Two-line change to
examples/SampleApp/src/screens/ChannelScreen.tsx: wrap<MessageComposer />in an RNKeyboardAvoidingViewwithbehavior="padding", nested insideChannel's ownKeyboardCompatibleView(also padding mode). This mirrors the setup in our app, where the composer subtree carries its ownKeyboardAvoidingViewon iOS.Mechanism:
keyboardWillShow/keyboardDidShowevents with allendCoordinateszeroed (screenY: 0, height: 0, duration: 0) β typically 2β5 pairs within ~100ms.KeyboardCompatibleViewis unaffected:_handleAppStateChangecallsunsetKeyboardListeners()on background, so it isn't subscribed during that window.KeyboardAvoidingViewhas noAppStatehandling, stays subscribed, and processes every bogus frame.await AccessibilityInfo.prefersCrossFadeTransitions(). That setting is off by default β it is a sub-setting of Reduce Motion, only appearing under Settings β Accessibility β Motion once Reduce Motion is enabled β so for the vast majority of users the guard never fires and the bogus frame reaches the height math. WithscreenY = 0,relativeHeightcollapses toframe.y + frame.height, i.e. the view's own bottom edge.paddingBottom, the view grows,onLayoutreports the larger frame, and the next bogus event computes a larger padding. Compounding loop.Measured in our app (composer height per event):
with the message list squeezed
366 β 302 β 238 β 174 β 110 β 46 β 0in lockstep. The per-event increment (64px) exactly matched theKeyboardAvoidingView's own measuredframe.height. The real keyboard event then snaps everything back.Our fix (applied locally as a
patch-packagepatch on React Native) was to make that guard unconditional:Verified on device: guard fires, no composer growth, no flicker.
Possible SDK-side hardening, if you think it's worthwhile: apply the same unconditional rejection in
KeyboardCompatibleView._relativeKeyboardHeight. It's currently shielded byunsetKeyboardListeners(), so this is defence-in-depth rather than a live bug β but ascreenYof 0 is never a legitimate keyboard frame, and anyone nesting aKeyboardAvoidingViewin their composer hits this. A docs note that nested padding-mode keyboard avoidance insideChannelis hazardous on iOS (not just Android) might also help.π¨ UI Changes
No intentional UI change β the repro makes the message list visibly collapse and recover on unlock.
π§ͺ Testing
SampleAppon a physical iOS device β that is where we verified this repro. We have not tried this particular repro on the Simulator, but in our own app the same flicker only ever appeared on a physical device and never on the Simulator, so a real device may well be required.Reproduced on iOS 26.6 with SampleApp defaults (
MessageList, offline support enabled), so it is independent ofMessageFlashListand of offline support. Originally found onstream-chat-expo9.7.5 / RN 0.86.2.βοΈ Checklist
developbranchRepro only β please don't merge.