Skip to content

fix(mobile): settings and draft links no longer hang the running iOS app - #27429

Open
juliusmarminge wants to merge 7 commits into
mainfrom
fix/issue-27396
Open

juliusmarminge wants to merge 7 commits into
mainfrom
fix/issue-27396

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Problem

A Settings link (t3code://settings/<page>, including the Subscription Usage widget's settings/usage?tab=limits) or a draft page link (new/draft/files, …) that reaches the running iOS app rebuilds the whole workspace. On a folded iPhone Duo the collapsed split view never finishes that transition: the app freezes until iOS kills it. Reproduced on main fa4e4677c0 on a pool iPhone Duo simulator (folded): with the app on the thread list, settings/about never opens and the next tap times out on the main thread; the same from the Pull requests tab with settings/appearance. A bare settings link over an open Settings page also pushes a second Settings route instead of going to the Settings tab.

Change

These links parse to three routes, so React Navigation answers with a plain RESET that the root stack rehydrates under a new key, with new keys for every route. The workspace navigators key their base screen on the root key, so the whole workspace is replaced.

runningAppLinkAction (in apps/mobile/src/lib/appLinking.ts, wired into appLinking.getActionFromState) handles links while the app is running:

  • A Settings link opens the Settings tab the way the Settings button does (settingsNavigationState): the live Home and Settings list keep their keys, and the linked page opens fresh so its params (tab=limits) apply again.
  • Any other root RESET keeps the live root key and reuses the keys of Home and of the leading routes the link repeats with the same params; only the linked page gets a new key.

Cold-start links, thread and pull request links, pairing links, and single-page links are unchanged.

Scope and approval

Fixes #27396

Verification

  • vp test run apps/mobile/src/lib/appLinking.test.ts: 38 passed. The five new tests in "links that arrive while the app runs" drive the real StackRouter, getStateFromPath and getActionFromState. On main's link chain, settings/about and new/draft/files get a new root key and a new Home key, and a bare settings link over an open About page leaves Home, Settings, SettingsAbout, Settings. A repeated settings/usage?tab=limits link reopens Usage, and a draft page link keeps the open draft's key.
  • vp run check:changed after merging main: format, lint, knip, typecheck, tests and React compiler pass.

Before, folded iPhone Duo simulator, iOS 27.2, 466×678, Light, main fa4e4677c0. Each strip shows the app before the link, then two later frames: seconds after the link, and after a tap on the rail. The page never opens, and the next tap fails with main thread execution timed out.

Thread list → settings/about:
Before: folded iPhone Duo stays frozen on the thread list after settings/about

Pull requests tab → settings/appearance:
Before: folded iPhone Duo stays frozen on the Pull requests tab after settings/appearance

Pixel 9, Android 16, 1080×2424, Light. The steps are: running thread list → settings/about → bare settings → Back. Before, Back returns to About through the duplicate Settings route; after, it returns to Threads.

Pixel 9 · Light Before fa4e4677c0 After dd245160d1
Recording Before: Pixel 9, Back after a bare settings link returns to About After: Pixel 9, Back after a bare settings link returns to Threads
After one Back · Pixel 9 · Light Before fa4e4677c0 After dd245160d1 Diff0 DiffT (5% fuzz)
Final screen Before: About After: Threads Zero-threshold diff, Pixel 9 after Back 5 percent fuzz diff, Pixel 9 after Back

Control, iPhone 17 Pro, iOS 27.2, 402×874, Light (card stack, which never hung). Running thread list → settings/about → Back. About opens and Back reaches Settings on both sides. The only differences are the clock and status bar.

iPhone 17 Pro · Light Before fa4e4677c0 After dd245160d1 Diff0 DiffT (5% fuzz)
Recording Before: iPhone 17 Pro opens About After: iPhone 17 Pro opens About
About Before: About on iPhone 17 Pro After: About on iPhone 17 Pro Zero-threshold diff, iPhone 17 Pro About 5 percent fuzz diff, iPhone 17 Pro About

Not verified:

  • The after side on the folded iPhone Duo. The pool simulator's "Open in T3 Code Dev?" launch prompt stopped accepting input on two hosts, so the dev client could not load for the after captures. The evidence that the hang is gone is the key-preservation tests: the hang needs a new root key, and the fix no longer produces one.
  • The draft Files link on a device.
  • cannot-verify ios-device: the physical iPhone Duo watchdog kill (0x8BADF00D).

Model and harness: Claude Opus 5.5 (Claude Code) as lead, test writer and implementer; reviewers GPT-6.1-sol (Codex) and Claude Opus 5.5.

🤖 Generated with Claude Code

juliusmarminge and others added 5 commits October 30, 2026 06:23
…g the workspace

These tests reproduce #27396: a settings/<page> or new/draft/<page> link
arriving while the app runs resets the root stack under new keys, and a
bare settings link over an open Settings page pushes a second Settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…orkspace

A Settings or draft-page link that arrived while the app ran fell through to
React Navigation's RESET of an unkeyed partial state. The root stack rehydrated
it under a new key, so the workspace navigator (keyed on the root) was replaced
and a collapsed iOS split view hung. A bare `settings` link over an open
Settings page also pushed a second Settings route.

With a live root, Settings-tab links now reset to the same state the Settings
button dispatches, and any other root RESET keeps the root's key and the live
keys of Home and of the leading routes the link repeats.

Fixes #27396

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The linked page now always opens fresh, so a second usage-widget tap
reapplies tab=limits; only the routes under it keep their keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 30, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at fd41f19

Macroscope's review found this PR approvable — Running-app settings and draft links preserve workspace navigation identity rather than rebuilding it, addressing the iOS hang. The change is confined to navigation handling, with existing cold-start and specialized link behavior retained.

No code changes detected at bdec362. Prior analysis still applies.

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

@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 5f562d8 and bdec362.

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.

Walkthrough

Running-app deep links now preserve applicable routes in the live root navigation state. Settings links use a targeted reset, and other reset actions reuse matching live routes. Tests cover settings links, draft-page links, repeated settings links, and bare settings links.

Changes: Running-app links

Layer / File(s) Summary
Build actions from the live navigation state
apps/mobile/src/lib/appLinking.ts
runningAppLinkAction creates a targeted reset for settings links. For other reset actions, it reuses matching live routes and targets the live root key.
Apply and test running-app actions
apps/mobile/src/App.tsx, apps/mobile/src/lib/appLinking.test.ts
getActionFromState passes the live root state and default action to runningAppLinkAction. Tests cover route preservation, draft names, repeated settings links, and bare settings links.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

Suggested labels: 📱 Native Change

Suggested reviewers: maria-rcks

Merge Risk: Minimal · previous review 5f562

This change keeps the live navigation root for running-app Settings and draft links, which should stop the reported hang. It was not verified on a folded iPhone Duo or a physical device, so check that before relying on the fix. No concrete merge-blocking risk was found.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title clearly and concisely identifies the mobile link-handling fix for Settings and draft links that hang the running iOS app.
Description check Passed The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the affected links, implementation, linked issue, test results, visual evidence, and unver…
Linked Issues check Passed Issue [#27396] requires running-app Settings and draft links to avoid replacing the live workspace, and bare settings links to open the Settings tab. App.tsx passes the live root and React Navigat…
Out of Scope Changes check Passed The reviewed production changes are limited to running-app link action selection in App.tsx and appLinking.ts. The test changes directly verify the linked issue behavior and key preservation. No u…
Full details: Description check

Explanation

The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the affected links, implementation, linked issue, test results, visual evidence, and unverified cases.

Full details: Linked Issues check

Explanation

Issue [#27396] requires running-app Settings and draft links to avoid replacing the live workspace, and bare settings links to open the Settings tab. App.tsx passes the live root and React Navigation fallback to runningAppLinkAction. appLinking.ts preserves the root key and matching leading route keys for reset links. Settings links use settingsNavigationState, preserve the live Home and Settings routes, and reopen the linked page with its parameters. With no live root, the existing fallback remains unchanged. Tests cover Settings, draft, repeated Usage, draft-key reuse, and bare settings links through the real router and link parsers.

Full details: Out of Scope Changes check

Explanation

The reviewed production changes are limited to running-app link action selection in App.tsx and appLinking.ts. The test changes directly verify the linked issue behavior and key preservation. No unrelated production behavior or unrelated file changes appear in the reviewed pull request diff.

Finishing Touches

Generate docstrings

  • 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
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between fd41f19 and 5f562d8.

Files selected for processing: 3

  • apps/mobile/src/App.tsx
  • apps/mobile/src/lib/appLinking.test.ts
  • apps/mobile/src/lib/appLinking.ts

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

@juliusmarminge juliusmarminge added bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed labels Nov 9, 2026

Copy link
Copy Markdown
Member Author

The automated pipeline stopped on this pull request and will not merge it:

someone else pushed to fix/issue-27396 (head is now fd41f19); the pipeline does not build on commits it did not review

It stays open for a person to finish or close.

@juliusmarminge

Copy link
Copy Markdown
Member Author

The automated pipeline stopped on this pull request and will not merge it:

the capture step could not show the problem on the base commit, so there is nothing to prove fixed.

Both commits opened settings/about externally while the app was running. Head also received a bare settings link and displayed Settings without a visible Back button. The folded About screen covered the tab bar, preventing the scripted Chats interaction. Manual fallback failed before pairing was confirmed. No completed equivalent interaction demonstrated the reported freeze or its absence.

It stays open for a person to finish or close.

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

bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed size:M 30-99 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.

[Bug]: Settings and draft links sent to the running iOS app hang it on a folded iPhone Duo until iOS kills it

1 participant