You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(mobile): settings and draft links no longer hang the running iOS app - #27429
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.
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:
Pull requests tab → 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
After one Back · Pixel 9 · Light
Before fa4e4677c0
After dd245160d1
Diff0
DiffT (5% fuzz)
Final screen
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
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.
…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>
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.
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.
pingdotgg/t3code#26326: Both changes affect the shared app-link parsing and navigation-action path.
pingdotgg/t3code#24827: This PR continues the root-level app-link action flow introduced by this pull request.
pingdotgg/t3code#25769: Both changes use the root navigation state and target key when dispatching app-link actions.
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: 4
Check name
Status
Explanation
Title check
The title clearly and concisely identifies the mobile link-handling fix for Settings and draft links that hang the running iOS app.
Description check
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
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
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
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bugfixFix PR opened by an issue lead; enters the PR looppr:gate-failedA land gate failedsize:M30-99 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.
1 participant
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A Settings link (
t3code://settings/<page>, including the Subscription Usage widget'ssettings/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 mainfa4e4677c0on a pool iPhone Duo simulator (folded): with the app on the thread list,settings/aboutnever opens and the next tap times out on the main thread; the same from the Pull requests tab withsettings/appearance. A baresettingslink over an open Settings page also pushes a secondSettingsroute instead of going to the Settings tab.Change
These links parse to three routes, so React Navigation answers with a plain
RESETthat 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(inapps/mobile/src/lib/appLinking.ts, wired intoappLinking.getActionFromState) handles links while the app is running:settingsNavigationState): the live Home and Settings list keep their keys, and the linked page opens fresh so its params (tab=limits) apply again.RESETkeeps 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 realStackRouter,getStateFromPathandgetActionFromState. On main's link chain,settings/aboutandnew/draft/filesget a new root key and a new Home key, and a baresettingslink over an open About page leavesHome, Settings, SettingsAbout, Settings. A repeatedsettings/usage?tab=limitslink reopens Usage, and a draft page link keeps the open draft's key.vp run check:changedafter 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 withmain thread execution timed out.Thread list →

settings/about:Pull requests tab →

settings/appearance:Pixel 9, Android 16, 1080×2424, Light. The steps are: running thread list →
settings/about→ baresettings→ Back. Before, Back returns to About through the duplicateSettingsroute; after, it returns to Threads.fa4e4677c0dd245160d1fa4e4677c0dd245160d1Control, 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.fa4e4677c0dd245160d1Not verified:
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