fix(mobile): deliver the first tab selection after Duo folding#22980

merged2
duo/reflow
duo/tab-sync
opened2d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 2d ago

After a pose change, a Screens mount transaction could clear the pending user-selection flag before UIKit delivered the selection event. Vendor Screens t3.31 with upstream fixes #4862 and #4890. Extend Reanimated screen recognition to v5 containers so returning to a cleared tab does not delay removing its old detail and crash.

Verified on a clean Duo native client: first tap in both directions after folding, details in both tabs, next-row navigation, cancelled back swipe, and Back to list. Native event logs confirmed JS received the first selection. Mobile typecheck and focused tests passed.

The vendored tarball's source is published as t3-v5.0.0-t3.31 and lands on the fork with pingdotgg/react-native-screens#3. This layer contains no search-observer swizzle; that is #23146.

Implemented with Claude Opus 5.5 in Claude Code; integrated and reviewed with GPT-6.1 in Codex.

Motion verification

Fresh, real-time 30 fps recordings from the exact commits labeled in the videos, using fingerprint-matched debug native clients. Black cards mark cuts between displays.

Before

Before — PR 22979

After

After — PR 22979

These recordings demonstrate stale detail removal and the second-tap crash fix. They do not reproduce the approximately 150 ms first-tap race: automated taps landed 1–6 seconds after unfolding, so this video is not proof of that timing fix.

Unfold-after-sheets assertion

Unfolding after using folded sheets hit a React Native touch-handler double-detach assertion in one of two runs at both ee9cd8c1b4a and fe16f614bef. Screens t3.35 in #23149 fixes it: the touch handler is attached and detached only when that changes something.

Unfold-after-sheets assertion, before t3.35

Restack

Restacked onto main a12d6ed942 on 2026-10-21. The commits are unchanged apart from lockfile peer strings. The recordings above show the pre-restack commits they name.

Checks

All checks passed
Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire—5.0 KiB—6.8 KiB✅
CodexThread snapshot wire—3.8 KiB—4.9 KiB✅
CodexLive turn WebSocket wire—1.2 KiB—2.0 KiB✅
CodexLive turn WebSocket decoded—20.9 KiB—29.3 KiB✅
CodexLive turn messages—2—8✅
ClaudeTotal thread wire—5.0 KiB—6.8 KiB✅
ClaudeThread snapshot wire—3.8 KiB—4.9 KiB✅
ClaudeLive turn WebSocket wire—1.2 KiB—2.0 KiB✅
ClaudeLive turn WebSocket decoded—21.2 KiB—29.3 KiB✅
ClaudeLive turn messages—1—8✅

Baseline: unavailable · PR result: 3f0e621 · 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: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

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

Synced from GitHub

Approvability

Verdict: Approved at e5cb117

Macroscope's review found this PR approvable — This is a focused mobile navigation bug fix that updates the vendored Screens fork and applies a small Reanimated compatibility patch for existing v5 stack, split, and tab containers. The runtime impact is limited to correcting tab-event delivery and screen-removal timing on existing navigation paths; no product defaults or static-analysis suppressions are changed.

No code changes detected at 3f0e621. Prior analysis still applies.

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

Synced from GitHub

Review in Change Stack →

Important

Review skipped

We couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting @coderabbitai full review.

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 64c354e6-c910-41c8-bcf4-197930666cd2
📥 Commits

Reviewing files that changed from the base of the PR and between 26a1604154b086a2dae6713060011e7e0165cf5d and e5cb1170aa94552bd1d6fb956d81c2bde8eb0164.

⛔ Files ignored due to path filters: 1
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing: 6
  • apps/mobile/deps/react-native-screens-5.0.0-t3.30.tgz
  • apps/mobile/deps/react-native-screens-5.0.0-t3.31.tgz
  • apps/mobile/package.json
  • docs/operations/mobile-screens-fork.md
  • patches/react-native-reanimated@4.7.1.patch
  • pnpm-workspace.yaml

Limit details: You’ve used all 10 included reviews currently available.

📝 Walkthrough

The mobile package and operations documentation now reference T3 Screens v5.0.0-t3.31. A registered Reanimated patch recognizes four additional React Native Screens component names.

Changes: Screens fork update

Layer / File(s)Summary
Screens v5 and Reanimated integration
patches/react-native-reanimated@4.7.1.patch, pnpm-workspace.yaml, apps/mobile/package.json, docs/operations/mobile-screens-fork.md
The package archive and documentation reference t3.31. The registered Reanimated patch recognizes RNSStackScreen, RNSSplitScreen, RNSTabsScreenIOS, and RNSTabsScreenAndroid.

Priority: ➖ Normal

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

Change: Bug fix

Suggested reviewers: t3dotgg

Merge Risk: ⚪ Minimal · up to e5cb1

The dependency and navigation integration changes are consistent, with no established merge-blocking risk.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly identifies the mobile fix for delivering the first tab selection after Duo folding. It is concise and matches the primary change.
Description checkPassedThe description explains the problem, the Screens and Reanimated changes, the related scope, verification steps, observed results, limitations, recordings, and agent usage. It does not use the templat…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the problem, the Screens and Reanimated changes, the related scope, verification steps, observed results, limitations, recordings, and agent usage. It does not use the template headings explicitly, and maintainer approval is not stated clearly, but the required information is mostly complete and directly relevant.

✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Added 2 commits

  • fix(mobile): returning to a tab clears its old detail instead of crashing3f0e621
  • fix(mobile): the first tab tap after folding the Duo reaches the apped4b4a8