fix(mobile): pull request project filter lists each repository once per environment#23121

closed3
main
GitHub fork: fix/mobile-pr-filter-duplicate-projects
opened8d agobyTtris203
View on GitHubTwo-way sync enabledPR last imported 14h ago

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 pullRequestFilterProjects and its tests, without behaviour changes, from apps/web to packages/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.
  • toSorted became .sort on the freshly mapped array, because Hermes does not implement Array#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.ts in packages/client-runtime: 6 passed. These are the existing #9948 tests, moved. The one test that used web's findScopedProject now asserts the resulting choices directly.
  • vp test run src/features/pull-requests/pullRequestList.test.ts in apps/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 typecheck passes in apps/mobile, packages/client-runtime and apps/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 laptop and desktop, with empty state except for fixture projects: laptop had two checkouts of pingdotgg/t3code plus precognition.nvim, and desktop had one checkout of pingdotgg/t3code. PRs → Filter → Project:
    • Before (upstream PullRequestsScreen.tsx): three identical t3code rows.
    • After: t3code · desktop, t3code · laptop, precognition.nvim. Choosing an entry applies the project filter.
BeforeAfter
beforeafter

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

25 successful · 12 skipped
All checks passed
58be215
Synced from GitHub

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.

Synced from GitHub

Review in Change Stack →

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 resume to resume automatic reviews.
  • @coderabbitai review to 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
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.tsx
  • apps/mobile/src/features/pull-requests/pullRequestList.test.ts
  • apps/mobile/src/features/pull-requests/pullRequestList.ts
  • apps/web/src/components/pullRequest/usePullRequestListView.ts
  • packages/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.ts
FilterProject now 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.ts
Mobile 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)

mermaid
1sequenceDiagram
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 nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main change: the mobile pull request project filter now lists each repository once per environment.
Description checkPassedThe 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 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 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.