fix(mobile): tapping an Android switch no longer presses its row - #15121
atharvadeosthale wants to merge 1 commit into
Conversation
On Android, ThemedSwitch renders a Jetpack Compose switch in place of React Native's Switch. RN's Switch claims the JS touch responder so a surrounding Pressable never fires; the Compose wrapper did not. Tapping an environment switch therefore opened or expanded its row, and a real finger tap usually left the switch unchanged because the row's view intercepted the touch and cancelled the native switch. Claim the responder on the Compose Host, which does not intercept touches the way a React Native View does, so the switch gets the whole gesture and the row never sees it. Fixes pingdotgg#14958 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a small, self-contained Android touch-handling bug fix in one existing component. It changes only responder ownership around the native switch, leaving other platforms and surrounding row behavior unchanged. Notes:
You can add or adjust custom eligibility rules. Learn more. |
Dismissing prior approval to re-evaluate 3f11a37
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (1)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe Android Material switch now claims touch start and refuses responder termination. It passes these handlers to the Compose ChangesAndroid Material Switch
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Medium Suggested reviewers: Merge Risk: ⚪ Minimal · up to The Android switch claims taps to prevent them from activating the surrounding row. Source inspection found that this does not prevent ancestor scrolling, so no material merge risk remains. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Linked Issues checkExplanation
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Problem
On Android, tapping an environment's connection switch presses the row around it instead. In Settings → Environments the tap opens the environment's details page, and on the details page it expands or collapses the Label/URL editor. With a real finger the switch itself usually stays off, so a saved environment can't be turned on from its switch. Fixes #14958.
Change
ThemedSwitchrenders an Expo UI Jetpack Compose switch on Android in place of React Native'sSwitch. RN'sSwitchclaims the JS touch responder (onStartShouldSetResponderreturnstrue, termination refused), so a surroundingPressablenever fires. The Compose wrapper didn't, so the row'sPressabletook the responder. Once a React Native view holds the responder, RN'sJSResponderHandlermakes it intercept every non-UP touch event, and the native Compose switch underneath getsACTION_CANCEL. That's why the row reacts and the switch doesn't.MaterialSwitchnow claims the responder the same way RN'sSwitchdoes, on the ComposeHost.Hostis anExpoView(LinearLayout), not aReactInterceptingViewGroup, so holding the responder doesn't make it steal the gesture from the switch. Claiming it on the wrapperViewinstead would cancel the switch the same way the row does; I checked that on device and the tap then did nothing at all.Fixing it in the switch component covers every Android switch inside a pressable row: local environment rows (Settings list, details, Connections), saved T3 Connect rows, and the Add Project GitHub row. The rows don't need restructuring. iOS keeps React Native's
Switchand is unchanged. Disabled switches stay disabled.Scope and approval
Triaged bug: #14958 (triage comment). The triage suggests moving each switch outside its row's pressable. This change gives the Android switch the touch contract that iOS's React Native
Switchalready has instead, so the row still never sees a tap on the switch (including long-press removal on cloud rows), and no call site has to change.Verification
On a OnePlus 11 (Android 16):
adb input swipewith a few pixels of movement, so MOVE events arrive as with a real finger) turn the switch off and on in the list and on the details page, and nothing navigates or expands. Tapping the row still opens details, and tapping the label on the details page still expands the editor.vp lintand the mobiletsc --noEmitpass.Not checked: saved T3 Connect rows (no relay environment in my test setup) and iOS (code path unchanged).
Before, release app: a list tap turns the switch on and opens details, then each details tap toggles the editor.
before-release-app.mp4
After, this branch: switch taps toggle in place in the list and on details, while row and label taps still open details and expand the editor.
after-fixed.mp4
Made with Claude Opus 5.5 in Claude Code, driven from T3 Code.