Skip to content

fix(mobile): tapping an Android switch no longer presses its row - #15121

Open
atharvadeosthale wants to merge 1 commit into
pingdotgg:mainfrom
atharvadeosthale:fix/mobile-android-switch-taps
Open

atharvadeosthale wants to merge 1 commit into
pingdotgg:mainfrom
atharvadeosthale:fix/mobile-android-switch-taps

Conversation

@atharvadeosthale

Copy link
Copy Markdown

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

ThemedSwitch renders an Expo UI Jetpack Compose switch on Android in place of React Native's Switch. RN's Switch claims the JS touch responder (onStartShouldSetResponder returns true, termination refused), so a surrounding Pressable never fires. The Compose wrapper didn't, so the row's Pressable took the responder. Once a React Native view holds the responder, RN's JSResponderHandler makes it intercept every non-UP touch event, and the native Compose switch underneath gets ACTION_CANCEL. That's why the row reacts and the switch doesn't.

MaterialSwitch now claims the responder the same way RN's Switch does, on the Compose Host. Host is an ExpoView (LinearLayout), not a ReactInterceptingViewGroup, so holding the responder doesn't make it steal the gesture from the switch. Claiming it on the wrapper View instead 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 Switch and 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 Switch already 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):

  • Before (installed release build): tapping the MacBook switch in Settings → Environments opened the details page. On the details page, each switch tap expanded or collapsed the Label/URL editor.
  • After (dev build of this branch, against an isolated dev server): finger-like taps (adb input swipe with 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 lint and the mobile tsc --noEmit pass.

Not checked: saved T3 Connect rows (no relay environment in my test setup) and iOS (code path unchanged).

Before: tapping the switch expands the editor After: the same tap only toggles the switch
Before: details page after tapping the switch After: details page after tapping the switch

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.

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>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Oct 3, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 3, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 3f11a37

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:

  • Diff unchanged. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 3, 2026 — with ChatGPT Codex Connector
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 3, 2026 09:44

Dismissing prior approval to re-evaluate 3f11a37

@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Review in Change Stack →

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
  • Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ea24bb7a-491f-4da5-8e05-72833abcf971
📥 Commits

Reviewing files that changed from the base of the PR and between e8545b2 and 3f11a37.

📒 Files selected for processing (1)
  • apps/mobile/src/components/MaterialSwitch.android.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The Android Material switch now claims touch start and refuses responder termination. It passes these handlers to the Compose Host.

Changes

Android Material Switch

Layer / File(s) Summary
Compose Host touch handling
apps/mobile/src/components/MaterialSwitch.android.tsx
The switch defines touch responder handlers and passes them to the Compose Host.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 3f11a

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)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning #14958’s main tap requirement is implemented: MaterialSwitch.android.tsx claims the responder on the Compose Host, and the PR reports that switch taps toggle without triggering the row. Disabled a… Provide an accessible connection label for the direct-connection switch. Check the linked cloud-row switch call site for the same requirement.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the Android switch fix and its effect on row taps.
Description check ✅ Passed The description covers the problem, implementation, scope and approval context, and focused verification. It includes before-and-after screenshots and recordings, reports test results, and identifies …
Out of Scope Changes check ✅ Passed The only change adds responder handling to the Android switch. This directly supports #14958, and the PR reports that it prevents the containing row from handling switch taps. No unrelated changes are…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files.
Full details: Linked Issues check

Explanation

#14958’s main tap requirement is implemented: MaterialSwitch.android.tsx claims the responder on the Compose Host, and the PR reports that switch taps toggle without triggering the row. Disabled and unsupported states remain handled in ConnectionEnvironmentRow.tsx. However, #14958 also requires each switch to have its own accessible connection label. The direct-connection ThemedSwitch call in ConnectionEnvironmentRow.tsx supplies no accessibilityLabel, and ThemedSwitch passes that missing value to MaterialSwitch.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Android connection switch taps expand the row instead of enabling the environment

2 participants