feat(mobile): add a native pull-request manager - #6398
Conversation
Phone and iPad can now browse, review, merge, and resolve conflicts in-app instead of bouncing to the browser, matching the desktop PR workspace with mobile navigation and git-control entry points. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review 2 blocking correctness issues found. Diff is too large for automated approval analysis. A human reviewer should evaluate this PR. You can customize Macroscope's approvability policy. Learn more. |
Follow diff continuation cursors, gate native navigation on environment capability, refresh list and detail after mutations, and keep Hermes-safe sorts. Co-authored-by: Cursor <cursoragent@cursor.com>
…pace Partial list failures, vanished host filters, and Azure-incapable Files/reviewer/verdict controls were offering actions the host cannot do. Empty Comment/Request-changes reviews could also send, and a paged diff could not refresh or retry. Co-authored-by: Cursor <cursoragent@cursor.com>
Opening a truncated file still showed the empty patch, Fix findings could run before review comments loaded, and a failed load-more hid its error behind already-visible rows. Co-authored-by: Cursor <cursoragent@cursor.com>
Expanded files mounted every line at once, and header-only adds, deletes, and renames never called diffFileContents because /dev/null and mode lines were dropped. Pull-to-refresh also left GitHub row sizes stale, and host/project filters survived an environment switch. Co-authored-by: Cursor <cursoragent@cursor.com>
| return; | ||
| } | ||
| if (canContinue) { | ||
| setPage({ key: filterKey, size: pageSize, cursors: nextCursors }); |
There was a problem hiding this comment.
🟠 High pull-requests/usePullRequestList.ts:240
When nextCursors exists for only some repositories, loadMore requests the next page with the same pageSize, so repositories without cursors return the same rows and older PRs from them are never loaded. Increase the page size while continuing with nextCursors.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/mobile/src/features/pull-requests/usePullRequestList.ts around line 240:
When `nextCursors` exists for only some repositories, `loadMore` requests the next page with the same `pageSize`, so repositories without cursors return the same rows and older PRs from them are never loaded. Increase the page size while continuing with `nextCursors`.
| const scopeKey = reference | ||
| ? `${reference.projectId}:${reference.repository}:${reference.number}` | ||
| : ""; |
There was a problem hiding this comment.
🟠 High pull-requests/PullRequestDiffScreen.tsx:71
Updating a mounted route between environments with the same project, repository, PR, and path leaves attemptedCursors populated from the previous environment, so matching cursors are skipped and pagination stops before the file is found. Include environmentId in scopeKey so the cursor-attempt state is reset for each environment.
| const scopeKey = reference | |
| ? `${reference.projectId}:${reference.repository}:${reference.number}` | |
| : ""; | |
| const scopeKey = reference | |
| ? `${environmentId}:${reference.projectId}:${reference.repository}:${reference.number}` | |
| : ""; |
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/mobile/src/features/pull-requests/PullRequestDiffScreen.tsx around lines 71-73:
Updating a mounted route between environments with the same project, repository, PR, and path leaves `attemptedCursors` populated from the previous environment, so matching cursors are skipped and pagination stops before the file is found. Include `environmentId` in `scopeKey` so the cursor-attempt state is reset for each environment.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 98ed285. Configure here.
| authoredQuery.refresh(); | ||
| reviewingQuery.refresh(); | ||
| refreshStats(); | ||
| }, [authoredQuery, baselineQuery, refreshList, refreshStats, reviewingQuery]); |
There was a problem hiding this comment.
Stats refresh clears then goes stale
Medium Severity
refreshStats clears statsByRow immediately and only calls firstStatsQuery.refresh(), then the merge effect walks later chunks from still-cached SWR data. Focus/refreshQueries therefore blanks +/- counts, and after load-more past the 500-ref chunk size later pages can keep pre-invalidate stats.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 98ed285. Configure here.


What Changed
Mobile now has the same in-app pull-request workspace desktop already has: a list, a detail view (Overview / Conversation / Files), comments, reviews, reviewers, merge/close/reopen, and conflict/finding handoffs into a new thread. Home, the sidebar, and a thread's git controls open that manager instead of the system browser.
This reuses the existing server, contracts, and
createPullRequestEnvironmentAtomsclient-runtime — no new wire protocol. The UI is mobile-native (grouped lists, sheets, confirmations) rather than a squeezed copy of the desktop right panel.Why
Desktop can manage a PR without leaving the app. Mobile still sent people to GitHub. That is the gap this fills.
I looked for an existing mobile manager on this repo (
PullRequestsScreen, native PR routes). Thread-row PR badges exist; the manager does not.UI Changes
New Pull Requests screen from the home/sidebar git-pull icon. Detail uses a segmented Overview / Conversation / Files layout with a bottom Merge / Resolve conflicts / Submit a review action.
Screenshots were not captured in this pass.
Checklist
Test plan
vp run --filter @t3tools/mobile typecheck; 50 focused tests)vp test runonapps/mobile/src/features/pull-requests/*.test.tsvp run --filter @t3tools/mobile typecheckModel: grok-4.6
Made with Cursor
Note
Add a native pull request manager to the mobile app
PullRequests,PullRequestDetail,PullRequestDiff,PullRequestComment,PullRequestReviewers) registered in Stack.tsx.useOpenNativePullRequestto route supported PR URLs to in-app screens, falling back to an external browser; replaces previoustryOpenExternalUrlcalls in thread git controls and the git overview sheet.usePullRequestDiffSlices.usePullRequestHandoffto check out a PR into a worktree and start a task thread directly from the detail view.pullRequestDiffLoaderLayeris now merged into the runtime snapshot loader composition, which changes how the runtime is composed for all environments.Macroscope summarized 98ed285.