fix(mobile): pull request project filter lists each repository once per environment#23121
Problem
On mobile, the Pull Requests screen's Project filter lists every project instance it knows about. With two environments connected, a repository present on both shows up as two identical entries (for example t3code, t3code), and each extra checkout or worktree of that repository on one environment adds another identical row. There is no way to tell which entry belongs to which environment.
Web fixed the same problem in #9948 with pullRequestFilterProjects, but the mobile screen never adopted it.
Change
- Move
pullRequestFilterProjectsand its tests, without behaviour changes, fromapps/webtopackages/client-runtime(@t3tools/client-runtime/pull-request-project-filter), so web and mobile share one implementation. Web imports it from the new location. - Mobile builds its choices with
pullRequestProjectChoices(apps/mobile/src/features/pull-requests/pullRequestList.ts). Like web, it lists only environments whose config advertises pull requests, and it runs the result through the shared helper: one entry per repository per environment, the saved worktree selection stays as that repository's entry, and clashing titles get the environment label, then path, then id as a suffix. - A saved project whose environment stops advertising pull requests, or has not loaded its config yet, stays in the menu as the selected entry. Before this change mobile kept such a scope in force while still listing it, so it stays visible and clearable rather than restricting the list silently.
toSortedbecame.sorton the freshly mapped array, because Hermes does not implementArray#toSorted(t3code/no-hermes-unsupported-apis).
Scope and approval
This is a small, focused fix for an obvious bug: the filter shows indistinguishable duplicate choices. It applies the behaviour maintainers already accepted for web in #9948 to the mobile client, without changing any rules.
Verification
vp test run src/pullRequestProjectFilter.test.tsinpackages/client-runtime: 6 passed. These are the existing #9948 tests, moved. The one test that used web'sfindScopedProjectnow asserts the resulting choices directly.vp test run src/features/pull-requests/pullRequestList.test.tsinapps/mobile: 17 passed, including new cases for one entry per serving environment and for a saved scope whose environment stops serving or has not loaded.pnpm run typecheckpasses inapps/mobile,packages/client-runtimeandapps/web.vp run check:changed upstream/main: format, lint, knip, typecheck and tests pass.- Manual check on an Android emulator (Pixel 9, API 37) with the dev client. Two isolated dev servers were paired at the same time, labelled
laptopanddesktop, with empty state except for fixture projects:laptophad two checkouts ofpingdotgg/t3codeplusprecognition.nvim, anddesktophad one checkout ofpingdotgg/t3code. PRs → Filter → Project:- Before (upstream
PullRequestsScreen.tsx): three identicalt3coderows. - After:
t3code · desktop,t3code · laptop,precognition.nvim. Choosing an entry applies the project filter.
- Before (upstream
| Before | After |
|---|---|
Not checked: iOS (no macOS host here). The choices are built in PullRequestsScreen before the menu renders, so iOS receives the same list.
Claude Opus 5.5 in Claude Code, running in T3 Code. Reviewed with GPT-6.1-Sol (xhigh) via T3 Code.
Checks
Approvability
Verdict: Approved at bc98b85
Macroscope's review found this PR approvable — This is a focused mobile pull-request filter fix that reuses the established web deduplication logic, preserves saved selections, and adds targeted tests. The shared helper relocation and package export are additive, with no schema, deployment, security, or static-analysis configuration impact.
No code changes detected at 0859e48. Prior analysis still applies.
You can add or adjust custom eligibility rules. Learn more.
Note
Reviews paused
It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.
- Last reviewed commit: 58be215ce5ad0f7cb79fe11d7dc6fa7490e1dbf5
Use the following commands to manage reviews:
@coderabbitai resumeto resume automatic reviews.@coderabbitai reviewto trigger a single review.
Use the checkboxes below for quick actions:
- ▶️ Resume reviews
- 🔍 Trigger review
No actionable comments were generated in the recent review.
External image Recent review info
-
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: main
- File: .coderabbit.config.ts
- Commit: e66ffcc
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Advanced
- Run ID:
dbf32f49-dadb-4b45-bab9-6bbd26bb627d
External image Commits
Reviewing files that changed from the base of the PR and between 0859e4816c77596caa8ff1e1aec7e39d5eea6148 and 58be215ce5ad0f7cb79fe11d7dc6fa7490e1dbf5.
External image Files selected for processing: 5
apps/mobile/src/features/pull-requests/PullRequestsScreen.tsxapps/mobile/src/features/pull-requests/pullRequestList.test.tsapps/mobile/src/features/pull-requests/pullRequestList.tsapps/web/src/components/pullRequest/usePullRequestListView.tspackages/client-runtime/package.json
External image Files with no reviewable changes: 1
- apps/web/src/components/pullRequest/usePullRequestListView.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
Walkthrough
The pull request exports a shared project filter from client-runtime. Mobile uses it to build project choices based on environment capability and retain selected scopes. Web imports the shared filter through the package export. Tests cover these behaviors.
Changes: Shared pull request filtering
Layer / File(s) Summary Define and export the shared filter
packages/client-runtime/src/pullRequestProjectFilter.ts,packages/client-runtime/package.json,apps/web/src/components/pullRequest/usePullRequestListView.ts,packages/client-runtime/src/pullRequestProjectFilter.test.tsFilterProjectnow defines the required project properties. The package exports the filter, and the web view imports it from that export. The saved-selection test checks that the selected worktree remains available across environments.Build capability-aware mobile choices
apps/mobile/src/features/pull-requests/pullRequestList.ts,apps/mobile/src/features/pull-requests/PullRequestsScreen.tsx,apps/mobile/src/features/pull-requests/pullRequestList.test.tsMobile excludes scratch projects and environments that do not serve pull requests, while retaining the selected project. Tests cover repository deduplication, environment labels, and saved scopes. Priority: External image Normal
Estimated code review effort: 3 (Moderate) | ~20 minutes
Sequence Diagram(s)
mermaid1 sequenceDiagram 2 participant PullRequestsScreen 3 participant pullRequestProjectChoices 4 participant pullRequestFilterProjects 5 PullRequestsScreen->>pullRequestProjectChoices: Provide projects, environment, labels, and capability predicate 6 pullRequestProjectChoices->>pullRequestFilterProjects: Pass eligible projects and selected project 7 pullRequestFilterProjects-->>PullRequestsScreen: Return formatted project choices Suggested reviewers:
flamboh,juliusmarminge
Merge Risk: External image Minimal · up to 58be2
The shared filter and mobile choices have no established merge-blocking issue in the supplied evidence; merge after normal checks.
Pre-merge checks: Passed 4
Check name Status Explanation Title check Passed The title clearly and concisely describes the main change: the mobile pull request project filter now lists each repository once per environment. Description check Passed The description is complete and matches the repository template. It explains the problem, implementation, scope justification, focused tests, type checks, manual Android verification, screenshots, and… Linked Issues check Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request. Full details: Description check
Explanation
The description is complete and matches the repository template. It explains the problem, implementation, scope justification, focused tests, type checks, manual Android verification, screenshots, and the iOS limitation.
Finishing Touches
🧪 Generate unit tests (beta)
- 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 3 commits
- fix(mobile): pull request project filter lists each repository once per environment2cb0462
- fix(mobile): pull request project filter lists only environments that serve pull requestsfbc868e
- fix(mobile): a saved pull request project scope stays visible when its environment stops serving pull requests58be215
Note
Claude Opus 5.5 responding on behalf of @tris203
Superseded by #25219, which landed this fix on main. Closing in favour of it.