Skip to content

Pull request view in the right panel - #292

Merged
stippi merged 12 commits into
mainfrom
feature/pr-view
Oct 30, 2026
Merged

stippi merged 12 commits into
mainfrom
feature/pr-view

Conversation

@stippi

@stippi stippi commented Oct 30, 2026

Copy link
Copy Markdown
Owner

A GitHub pull request page in the right panel, modelled closely on T3 Code's pull request view, including how it stays fast. Design and architecture: docs/pull-request-view.md.

What it does

A new PR tab next to Review / Files / Browser:

  • List of the project's pull requests: grouped (Authored / Review requested / Others), sorted (merge readiness, blocked on me, recent, size, …), filtered and searched (label:, author:, draft:, review:, checks:). Pages load as the end scrolls into view, line counts are read for visible rows only. Holding Shift shows quick actions (close / merge / ready / reopen) that update the row at once and roll back on failure. Sort, filters and the merge method are remembered.
  • Detail with the session's own pull request first: state, editable title, branches, stats, behind-by with Update branch, the primary action (merge with method / ready for review / auto-merge) with a two-click confirm, and a ⋯ menu (refresh, draft / ready, close / reopen, auto-merge, merge method, maintainer edits, open on GitHub, copy link / number, delete branch). The header condenses while a tab is scrolled.
  • Summary: reviewers and labels with pickers, the description (editable, with reactions), checks, and the conversation with bot / resolved filters, order and paging; comment cards with reactions (optimistic), editing, threads with reply / resolve / load more.
  • Timeline: opened, commits (click scopes the Code tab to the commit), grouped comments, verdicts, review threads, merged / closed.
  • Code: diff pages with syntax highlighting, files in reading order (sources by import dependency, tests next to their source, generated last), Viewed ticks (optimistic, batched, shift-click ranges), inline review threads, threads not on the diff, line / range comments as pending review comments, commit scope.
  • Composer: comment (also close / reopen with comment) and review (comment / approve / request changes with the pending comments).
  • Add to agent on comments, threads, failing checks and diff lines hands them to the session's composer.

How it is built

  • crates/github (new, Layer 0): token from GH_TOKEN / gh auth token, then plain HTTPS. GraphQL documents ported from T3 Code, REST for diffs, contents, review submission, labels and reviewers. Quota reserve with background / interactive priority, host pauses after rate limits, ETag revalidation of checks (304s cost no quota), aliased batches, at most 8 requests in flight. Everything sits behind a Transport seam; tests use the scripted FakeTransport.
  • code_assistant_core::pull_requests: per-part caches with TTLs, shared in-flight reads, stale-while-revalidate with app-scoped PullRequestChanged events, last good value on failure, disk snapshots for a cold start, invalidation after writes. SessionService::pull_request_* exposes every read and write.
  • ui_gpui/src/diff/: the diff model, chunking, highlighting and row rendering moved out of the tool cards and are now shared by the Review view, the tool cards and the PR Code tab; git::patch parses unified diffs.
  • ui_gpui/.../right_panel/pull_request/: the panel.

Changed along the way

  • The lifecycle sweep reads session pull requests in batched GraphQL summaries instead of one gh pr view process per session.
  • Diff highlighters are reused across files: a debug build spent ~57 ms per file side compiling tree-sitter queries. Review gets this too; the PR Code tab shows plain rows at once and highlights nearest-first (feat: architecture panel — a living overview of the project's components #272: first rows 79 ms after the tab opens, was 3–4 s).
  • The dark theme's border / input colours were darker than our background, so hairlines, outline buttons, inputs and checkbox boxes barely showed anywhere in the app; they now use the title bar's border colour.

Not yet (follow-up)

Split diff layout, file tree, whitespace / wrap toggles, expanding context, a real Check out into a worktree session, stacks, workflow approvals for fork PRs, several PR tabs. T3's Guide tab is deliberately left out.

Testing

  • cargo test for github (127), git, code_assistant_core (962) and ui_gpui (505, including end-to-end tests of the panel against a real SessionService with scripted GitHub); clippy and fmt clean.
  • Tried in the running app (isolated config / data dir) against this repository's real pull requests: list, detail, all three tabs, ⋯ menu, composer. Merge and other mutations have only run against the fake, not against real GitHub.

stippi added 10 commits October 30, 2026 08:58
Moves the diff model, chunking, syntax highlighting and row rendering out of
the tool cards into ui_gpui's diff module, and adds a unified-diff parser to
the git crate. PreparedFileDiff now comes from two whole files (Review) or
from a parsed patch, highlighting each hunk on its own; chunks can be cut at
break points so later rows (review threads) can follow a given line.
Ported from T3 Code's GitHub provider: token from GH_TOKEN or gh, REST and
GraphQL over one transport seam, quota reserve and host pauses, ETag
revalidation of checks, aliased batches, and every read and write the pull
request view needs. Tests run against a scripted fake transport.

docs/pull-request-view.md describes the whole feature.
code_assistant_core's pull_requests module keeps GitHub reads in per-part
caches (TTLs, shared in-flight reads, stale-while-revalidate, last good on
failure, disk snapshots for a cold start) and invalidates them after writes.
SessionService exposes every read and write; changes reach frontends as
app-scoped PullRequestChanged / PullRequestListChanged events.

The lifecycle sweep and the after-run refresh read session pull requests in
batched GraphQL summaries instead of one gh pr view per session.
The PR tab lists a repository's pull requests (grouped, sorted, filtered and
searched like T3 Code's list) and opens one in a detail page: header with
state, title editing, branches and stats, the primary merge action with a
two-click confirm, the ⋯ menu, and Summary / Timeline / Code tabs. GPUI gets
an HTTP client so avatars load with img(url). Loading through the session
service follows in the next step.
PullRequestData holds what the detail page knows about a pull request and
re-reads a part when the core announces a change; checks are polled while the
tab is shown. Summary shows reviewers, labels, the description and the
conversation, Timeline the events on a rail, and Code the diff pages with
files in reading order, files-viewed ticks applied at once and written in
batches, inline review threads and pending review comments. A floating
composer posts comments and submits reviews.
Summary and Timeline open at the top (a splice into an empty list moved
the scroll position past the new rows); the composer no longer passes
clicks to the diff below; the Viewed box is visible in the dark theme;
hunk separators collapse the section's whitespace; diff rows get a thin
edge bar for added and removed lines; the list's search field and buttons
and the header hairlines use visible borders.
Code tab: highlighters are reused across files (a debug build spent ~57 ms
per side compiling the grammar's queries), pages show plain rows at once and
are highlighted file by file nearest the viewport first, and opening a pull
request prefetches its first diff page and files-viewed state. #272's 27
files now show in 24 ms after the fetch instead of 3.9 s.

List: pages load as the end scrolls into view, line counts are read for
visible rows, sort / filters / merge method are remembered, Shift reveals
quick actions, and actions update rows at once with rollback on failure.
The header condenses while a tab is scrolled; relative times refresh.

Summary / Timeline: reactions on the description, remembered comment filter
and order, pinned section headers, Add to agent on comments, threads and
failing checks (a text attachment in the composer), and open-on-GitHub
links on timeline cards.
The diff cache was keyed by the head sha of the held detail, so the first
diff page prefetched alongside the detail (head still unknown) was stored
under another key than the Code tab read later, and the tab fetched it
again. Diffs are keyed without the head now; a detail read that sees a new
head drops the pull request's diffs instead.
The stock dark border and input colours sit below our #2c2c2c background,
so hairlines, outline buttons, unfocused inputs and checkbox boxes all but
vanished app-wide. They now use the title bar's border colour; the pull
request view drops its own hairline() helper and its hand-drawn Viewed
checkbox again.
A commit clicked in the Timeline emitted OpenCommit, but nothing listened;
the detail page now opens the Code tab scoped to that commit.

The header condensed as soon as the tab was scrolled 24 px. When the content
was only a little longer than the view (a short pull request, its first file
folded), condensing gave the list more room than it could scroll, the list
clamped its scroll, the header expanded and the two states alternated every
frame. It now condenses only when the tab can stay scrolled past the fold in
the taller view, and stays condensed until the tab is back at its top.
lru 0.12 has two new unsound advisories; github and code_assistant_core move
to lru 0.19. ratatui's fork still brings 0.12 and only uses get_or_insert
and resize on values that cannot panic on drop, so deny.toml ignores the two
advisories for it with that reason.

The comment editor submitted from its preview on ⌘↵ only; it takes the
platform's secondary modifier now (Ctrl on Linux and Windows), and the tests
send secondary-enter instead of cmd-enter.
- The header's head branch and checkout command copy themselves with a
  tooltip and a short tick; before, the whole base ← head line copied the
  head silently, which looked like a dead link.
- Running checks turn like the session spinner instead of standing still.
- Requested reviewers show their avatars: the detail query selects them for
  users and bots, with GitHub's login avatar as the fallback the author
  already had.
@stippi
stippi merged commit c06a7b0 into main Oct 30, 2026
6 checks passed
@stippi
stippi deleted the feature/pr-view branch October 30, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant