Skip to content

fix(mobile): long-pressing a thread row no longer navigates into the thread - #5901

Merged
juliusmarminge merged 1 commit into
mainfrom
fix-long-press-navigation
Aug 9, 2026
Merged

fix(mobile): long-pressing a thread row no longer navigates into the thread#5901
juliusmarminge merged 1 commit into
mainfrom
fix-long-press-navigation

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Aug 9, 2026

Copy link
Copy Markdown
Member

Fixes the bug phil5034 reported on Discord: long-pressing a thread row in the overview to open the context menu could also navigate into the thread. Long press now only opens the menu; taps still navigate.

Why it happened

Two stacked issues, both iOS-only in our setup (Android already injects a guard):

  1. A Pressable with only onPress fires on finger-up after any hold duration. The thread-row pressables have no onLongPress on iOS, so a long press released just under the ~500 ms native context-menu threshold read as a tap and navigated. Same class of bug as react-native-context-menu-view#60.

  2. The real double-fire: RN's Fabric touch handler is never cancelled when the menu opens. Our @react-native-menu/menu patch makes the native button touch-transparent (so row taps reach the Pressable) and hosts the UIContextMenuInteraction on the host component view — i.e. inside the RN view tree. RCTSurfaceTouchHandler.canBePreventedByGestureRecognizer: returns NO for any recognizer attached inside the RN hierarchy, and cancelsTouchesInView only cancels view-level delivery, not un-prevented gesture recognizers. So RN kept tracking the touch after the menu appeared; on finger-up Pressability fired onPress and navigated with the menu already showing. Documented ecosystem-wide in zeego#145.

The fix

Mirror the Android branch of ControlPillMenu on iOS: in shouldOpenOnLongPress mode, clone the child with a no-op onLongPress and delayLongPress: 350 (below the ~500 ms menu threshold). Once onLongPress dispatches, Pressability suppresses onPress on release (isPressCanceledByLongPress), which closes both holes — short taps still navigate, holds past 350 ms can only open the menu. A child's own onLongPress/delayLongPress are preserved if ever passed. Covers all four long-press menu call sites (v1 + v2 thread rows, both pending-task rows), which all pass a Pressable as the direct child.

Verification

Verified in the dev client on an iPhone 17 Pro simulator against a seeded showcase environment, driving real touch events:

  • 1.2 s long press → context menu (Settle/Snooze/Pin/Delete) opens, dismissing it lands back on the overview, no navigation
  • 0.6 s press (releasing right at the menu threshold — the raciest timing and the reported repro) → menu only, no navigation
  • Normal tap → still navigates into the thread

Typecheck and lint pass.

🤖 Generated with Claude Code


Note

Low Risk
Small, localized touch-handling change on iOS menu wrappers; behavior aligns with the existing Android branch and only affects long-press menu rows.

Overview
Fixes an iOS-only bug where long-pressing a thread row to open the context menu could also fire the row’s onPress and navigate into the thread.

ControlPillMenu (iOS) now mirrors the existing Android long-press path: when shouldOpenOnLongPress is set, it clones the direct child Pressable with a no-op onLongPress and delayLongPress: 350 (under the ~500ms native menu threshold). That lets React Native’s Pressability cancel onPress on finger-up after a hold, so opens the menu without tap-through. Short taps still navigate; existing child onLongPress / delayLongPress props are left unchanged if present.

Applies to all long-press menu usages (v1/v2 thread rows and pending-task rows) without changing those call sites.

Reviewed by Cursor Bugbot for commit 7ad735a. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix long-press on thread rows to prevent navigation on iOS

In ControlPill.tsx, when shouldOpenOnLongPress is enabled on iOS, the wrapped child is cloned to inject a no-op onLongPress handler and a 350ms delayLongPress if neither is already set. This prevents the child's tap/navigation from firing after a long-press that opens the menu.

Macroscope summarized 7ad735a.

…thread

On iOS the long-press context menu rows are a plain Pressable wrapped in
the patched MenuView: the native button is touch-transparent so the row
keeps handling taps, and the UIContextMenuInteraction lives on the host
component view. RN's Fabric touch handler refuses to be prevented by
recognizers inside the RN view tree (RCTSurfaceTouchHandler
canBePreventedByGestureRecognizer), so the touch is never cancelled when
the menu opens - on finger-up Pressability fired onPress and navigated
with the menu already showing. Releasing just under the ~500ms menu
threshold navigated too, since a Pressable without onLongPress fires
onPress after any hold duration.

Mirror the Android branch in ControlPillMenu: in long-press mode, clone
the child with a no-op onLongPress and delayLongPress of 350ms. Once
onLongPress dispatches, Pressability swallows the release, so holds past
350ms can only open the menu, never tap through.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d719e3ab-5f8e-4a5e-a5e5-4e0e26d8bec3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 11.3 KiB 11.3 KiB +10 B (+0.1%) 15.1 KiB
Codex Thread snapshot wire 5.5 KiB 5.5 KiB −2 B (−0.0%) 7.3 KiB
Codex Live turn WebSocket wire 5.9 KiB 5.9 KiB +12 B (+0.2%) 7.8 KiB
Codex Live turn WebSocket decoded 49.7 KiB 49.7 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 16 16 0 (0.0%) 21
Claude Total thread wire 11.3 KiB 11.3 KiB +6 B (+0.1%) 15.1 KiB
Claude Thread snapshot wire 5.5 KiB 5.5 KiB −2 B (−0.0%) 7.3 KiB
Claude Live turn WebSocket wire 5.9 KiB 5.9 KiB +8 B (+0.1%) 7.8 KiB
Claude Live turn WebSocket decoded 50.6 KiB 50.6 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 16 16 0 (0.0%) 21

Baseline: 83d769f · PR result: 7ad735a · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 94.6 KiB
  • Claude decoded thread snapshot: 95.4 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 7ad735a

Straightforward bug fix for a mobile touch interaction issue. The change is self-contained in ControlPillMenu, only affects long-press behavior, and preserves existing handlers. Well-commented and authored by the file's primary maintainer.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge
juliusmarminge merged commit f993fa1 into main Aug 9, 2026
17 checks passed
@juliusmarminge
juliusmarminge deleted the fix-long-press-navigation branch August 9, 2026 22:29
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 10, 2026
## What's Changed
* fix(web): thread title button no longer eats the drag area by @nathangerday in pingdotgg/t3code#5857
* fix(web): unify usage page chrome by @t3-code[bot] in pingdotgg/t3code#5823
* fix(shell): add ~/.local/bin to the Windows CLI resolver so native-installed providers are found by @arhxam in pingdotgg/t3code#5074
* fix(web): match settings search shortcut styling to command palette's by @UtkarshUsername in pingdotgg/t3code#5841
* fix(mobile): long-pressing a thread row no longer navigates into the thread by @juliusmarminge in pingdotgg/t3code#5901
* fix(server): usage no longer double-counts forked Codex sessions by @t3dotgg in pingdotgg/t3code#5887
* fix(server): sandbox user-provided SVGs by @t3dotgg in pingdotgg/t3code#5916
* fix(web): match usage titlebar text styling by @t3-code[bot] in pingdotgg/t3code#5897

## New Contributors
* @nathangerday made their first contribution in pingdotgg/t3code#5857

**Full Changelog**: pingdotgg/t3code@v0.0.33-nightly.20260809.1047...v0.0.33-nightly.20260810.1054

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.33-nightly.20260810.1054
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 10, 2026
## What's Changed
* fix(mobile): reconnects no longer shift the thread list by @t3dotgg in pingdotgg/t3code#5372
* feat(web): drag pinned threads into your own order by @t3dotgg in pingdotgg/t3code#5581
* chore(ci): vouch StiensWout by @t3-code[bot] in pingdotgg/t3code#5637
* feat(desktop): remember recently used sites in the Browser panel by @chrisdeeming in pingdotgg/t3code#5270
* chore: vouch chrisdeeming by @t3-code[bot] in pingdotgg/t3code#5641
* feat(web): make sidebar artwork theme-aware by @maria-rcks in pingdotgg/t3code#5636
* fix(web): reconnect the composer seam for remote non-Git projects by @caezium in pingdotgg/t3code#5633
* fix(web): show Stop button while input is pending by @ipanasenko in pingdotgg/t3code#5554
* feat(web): fold plan mode and token-by-token output into Legacy features by @t3dotgg in pingdotgg/t3code#5664
* feat: sidebar v2 is now the default sidebar by @t3dotgg in pingdotgg/t3code#5672
* fix(server): stop PR status lookups amplifying GitHub rate limits by @t3dotgg in pingdotgg/t3code#5673
* fix(web): delay transient reconnect warnings by @t3-code[bot] in pingdotgg/t3code#5670
* fix(web): inherit terminal size in simple typography by @chrisdeeming in pingdotgg/t3code#5628
* fix(server): stop the reaper from silently killing live background subagents by @t3dotgg in pingdotgg/t3code#5677
* fix(desktop): zoom shortcuts no longer die when the preview browser has focus by @t3dotgg in pingdotgg/t3code#5691
* feat(mobile): one sheet for model and thread settings by @t3dotgg in pingdotgg/t3code#5625
* feat(usage): usage page reading provider transcripts across environments by @t3dotgg in pingdotgg/t3code#5684
* fix(web): usage chart no longer makes Claude look like the bigger spender by @t3dotgg in pingdotgg/t3code#5697
* fix(web): persist diff view mode by @leorivastech in pingdotgg/t3code#5731
* feat(web): show how many subagents are running at a glance by @t3dotgg in pingdotgg/t3code#5745
* fix(web): add missing cursor-pointer styling to dropdowns and interactive buttons by @naMqe-h in pingdotgg/t3code#5716
* fix(server): stop Claude resume handshakes from completing turns that never ran by @gfsaaser24 in pingdotgg/t3code#5710
* chore: vouch gfsaaser24 by @t3dotgg in pingdotgg/t3code#5761
* chore: vouch saphid by @t3dotgg in pingdotgg/t3code#5763
* fix(server): stop Codex threads with queued follow-ups by @t3dotgg in pingdotgg/t3code#5762
* fix(web): usage page loses the cost quality panel, gains a back button by @t3dotgg in pingdotgg/t3code#5756
* feat(server): agents can now open the images you paste into chat by @t3dotgg in pingdotgg/t3code#5757
* fix(web): pinned reorder no longer reshuffles while writes land by @t3dotgg in pingdotgg/t3code#5767
* feat(web): overhaul project settings into a real settings page by @t3dotgg in pingdotgg/t3code#5768
* fix(web): usage totals no longer jump while devices report in by @t3dotgg in pingdotgg/t3code#5772
* fix(server): settle no longer leaves monitors and dev servers running by @t3dotgg in pingdotgg/t3code#5774
* feat: pick worktree or current checkout per project by @t3dotgg in pingdotgg/t3code#5766
* fix(web): sidebar rows show the branch again, not a truncated plan step by @t3dotgg in pingdotgg/t3code#5776
* feat(server): vp run migrate-dev-db seeds worktree dev dbs with real data by @t3dotgg in pingdotgg/t3code#5773
* feat(web): keep unsent drafts one click away in the sidebar by @t3dotgg in pingdotgg/t3code#5777
* feat(web): project icons can be chosen manually by @t3dotgg in pingdotgg/t3code#5775
* fix(server): one greedy agent process no longer takes down the whole server by @t3dotgg in pingdotgg/t3code#5788
* ci: label-gated hosted-web preview deploys by @t3dotgg in pingdotgg/t3code#5465
* Add cross-platform mobile usage dashboard by @juliusmarminge in pingdotgg/t3code#5743
* fix(web): preserve desktop route during Clerk auth by @wobsoriano in pingdotgg/t3code#5770
* fix(web): match create theme and import theme buttons to the standard outline style by @UtkarshUsername in pingdotgg/t3code#5860
* fix(server): favicon resolution no longer pins the event loop by @murenovich in pingdotgg/t3code#5538
* fix(shared): bound the file-link label so bracket runs stop rescanning by @tsouth89 in pingdotgg/t3code#5782
* fix(web): thread title button no longer eats the drag area by @nathangerday in pingdotgg/t3code#5857
* fix(web): unify usage page chrome by @t3-code[bot] in pingdotgg/t3code#5823
* fix(shell): add ~/.local/bin to the Windows CLI resolver so native-installed providers are found by @arhxam in pingdotgg/t3code#5074
* fix(web): match settings search shortcut styling to command palette's by @UtkarshUsername in pingdotgg/t3code#5841
* fix(mobile): long-pressing a thread row no longer navigates into the thread by @juliusmarminge in pingdotgg/t3code#5901
* fix(server): usage no longer double-counts forked Codex sessions by @t3dotgg in pingdotgg/t3code#5887
* fix(server): sandbox user-provided SVGs by @t3dotgg in pingdotgg/t3code#5916
* fix(web): match usage titlebar text styling by @t3-code[bot] in pingdotgg/t3code#5897
* Move project settings to contextual project routes by @juliusmarminge in pingdotgg/t3code#5923
* Retain thread sidebar data when navigating to /settings so back navigation is instant by @juliusmarminge in pingdotgg/t3code#5930
* Automate production mobile EAS releases by @juliusmarminge in pingdotgg/t3code#5609
* Add settings and usage breadcrumbs by @juliusmarminge in pingdotgg/t3code#5929
* fix(web): correct model picker trigger padding by @Chrono-byte in pingdotgg/t3code#5935
* fix(web): show worktree icon in sidebar v2 by @tris203 in pingdotgg/t3code#5909
* fix(web): enable restore defaults after theme mix changes by @Lucenx9 in pingdotgg/t3code#5928
* fix(web): trait menu closes after you pick a level by @t3dotgg in pingdotgg/t3code#5879
* fix(web): align project name with headline by @carterwsmith in pingdotgg/t3code#5864
* fix(web): update pills use readable theme foregrounds by @chrisdeeming in pingdotgg/t3code#5938
* fix(web): use themed confirmation dialogs by @StiensWout in pingdotgg/t3code#5624
* fix(web): use import/export-appropriate icons for theme buttons by @UtkarshUsername in pingdotgg/t3code#5964
* fix(mobile): detect PowerShell cmdlet errors in work log rows by @myacoub91 in pingdotgg/t3code#5726
* fix(mobile): stop Android user bubbles with code blocks from overlapping by @Brechard in pingdotgg/t3code#5659
* fix(mobile): parse EAS fingerprint JSON by @juliusmarminge in pingdotgg/t3code#5991

## New Contributors
* @chrisdeeming made their first contribution in pingdotgg/t3code#5270
* @wobsoriano made their first contribution in pingdotgg/t3code#5770
* @murenovich made their first contribution in pingdotgg/t3code#5538
* @tsouth89 made their first contribution in pingdotgg/t3code#5782
* @nathangerday made their first contribution in pingdotgg/t3code#5857
* @carterwsmith made their first contribution in pingdotgg/t3code#5864
* @myacoub91 made their first contribution in pingdotgg/t3code#5726

**Full Changelog**: pingdotgg/t3code@v0.0.32...v0.0.33

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant