Skip to content

Review tab overhaul: in-app PR review (sync, comments, threads) + diff/editor tab improvements - #142

Draft
big-guy wants to merge 63 commits into
ness-dev:mainfrom
big-guy:review-tab-improvements
Draft

Review tab overhaul: in-app PR review (sync, comments, threads) + diff/editor tab improvements#142
big-guy wants to merge 63 commits into
ness-dev:mainfrom
big-guy:review-tab-improvements

Conversation

@big-guy

@big-guy big-guy commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

This isn't quite ready yet. This currently allows you to add comments, create replies, view others comments and mark files as viewed, but they're only synced to GitHub when you click 'Sync'. The intention is to make this happen as you go, but this was a simple way to control/test the GitHub interaction separate from the local UI changes.

Large set of improvements to the in-app Review tab, a new GitHub PR review sync, and assorted diff/editor tab enhancements.

Review tab

  • Two-row toolbar — commit selector (with diff stat), Split/Unified + whitespace toggles, and Copy/Sync/Send actions on top; reviewer status, comment dropdown, and files reviewed/remaining on the second row.
  • View modes — Unified / Split / Full (d / s / f), whitespace toggle; side-by-side is honored even in narrow panes.
  • Keyboard shortcutsj/k (and /) file nav, [/] unreviewed nav, r mark viewed, s/d split/unified, c comment on hovered line, ? help popup — all gated on the review tab being active.
  • Inline comments — markdown bodies (with sanitized HTML via rehype-raw/sanitize), author avatar + @handle + relative time linking to GitHub; long comments collapse with a Show more toggle (dynamic-height zones); reply threads render inset under their parent; drafts tinted amber, published blue.
  • Navigation — comment-count dropdown, jump-to-first-comment on the file header, expand-all toggle.
  • Reviewer status — avatar cluster ring-colored by review state; click an avatar for that reviewer's top-level comment (markdown).

GitHub PR review sync (Sync button)

  • Pushes local comments as a draft pending review (not published); pulls published + your draft comments back and merges viewed state (mark-only — never unmarks a file viewed on GitHub).
  • Reply to comments (REST in_reply_to) and resolve threads (resolveReviewThread); Harness never unresolves — resolved state always comes from GitHub.
  • Auto pull-only sync when a review opens; Sync disabled unless the selection is "All commits".

Diff / editor tabs

  • Diff tab is view-only with Unified/Split/Full modes; Edit opens the dedicated editor tab; working-tree diffs labeled "Uncommitted".
  • Clicking a committed file in Changed Files opens the Review tab on that file; section counts in the Changed Files headers.
  • Editor: reliable Cmd/Ctrl+S, warn before closing a tab with unsaved changes, and an external-vs-in-app editor choice (⌘-click) from Changed Files.
  • Distinct Diff/File tab icons; review tabs use a ClipboardCheck icon.

Notes

  • Viewed state is additive (un-viewing isn't propagated back to GitHub).
  • Replies publish immediately on sync (in_reply_to creates a published comment, not a pending-review draft).

🤖 Generated with Claude Code

@big-guy big-guy self-assigned this Jun 1, 2026
@big-guy
big-guy force-pushed the review-tab-improvements branch 4 times, most recently from bfb44fe to 01a0eaa Compare June 2, 2026 17:37
big-guy and others added 25 commits June 4, 2026 17:52
Add syncPRReview in github.ts plus the review:sync IPC handler, the
reviewSync backend method, and the shared ReviewSync* types. Sync pushes
local line comments as a DRAFT pending review (addPullRequestReview /
addPullRequestReviewThread, anchored RIGHT-side), marks locally-reviewed
files as viewed (mark-only, never unmark), then pulls the canonical
comment set (published + the user's pending drafts) and unions GitHub's
per-file viewerViewedState back in. A pull-only mode fetches comments
without pushing (used by auto-sync on review open). Best-effort: rejected
comments are counted failed and kept local; resolves token + upstream
repo + PR number like pr:merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review tab (ReviewPane/ReviewDiffPane/ReviewFileTree):
- Two-row toolbar: commit selector (with diff stat), Split/Unified +
  whitespace toggles, Copy/Sync/Send actions on top; reviewer status,
  comment dropdown, and files reviewed/remaining on the second row.
- Split/Unified (s/d) and whitespace toggles; honor side-by-side in narrow
  panes (useInlineViewWhenSpaceIsLimited). All review shortcuts
  (j/k/[/]/r/s/d/c/?) live in one handler, gated on the tab being active.
- Inline comments: markdown bodies, author avatar + @handle + relative
  time linking to GitHub, prominent styling, view-zones redrawn on editor
  (re)mount. 'c' comments the hovered line (or file-level). Comment
  dropdown + jump-to-first-comment button; jump scrolls reliably.
- Sync button (drafts), status dot, disabled off "All commits"; auto
  pull-only sync on open. Reviewer avatars show state + top-level review
  (markdown) on click. Refresh on git changes.
- "Viewed" button moved right; ClipboardCheck tab icon.

Diff/editor tabs:
- Diff tab view-only with Unified/Split/Full modes; Edit opens the editor
  tab; "Uncommitted" label; whitespace toggle. Committed files in Changed
  Files open the Review tab on that file. Section counts in Changed Files
  headers.
- Editor: reliable Cmd/Ctrl+S (onKeyDown), Save moved left with unsaved
  badge, FileInput/FileOutput markdown toggle, warn before closing a tab
  with unsaved changes (dirty-tabs registry).
- Distinct Diff/File tab icons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…or in-app

Relabel the per-file editor icon "Open file in external editor"; ⌘-click
opens the file in the in-Harness editor tab instead (handleOpenFile,
threaded through RightColumn → ChangedFilesPanel → FileRow).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…height

Comment view zones are now sized to their rendered content via a
ResizeObserver (no more fixed 4-line clip). A comment taller than ~4 lines
clamps its body with a fade + "Show more"; clicking the comment (or the
toggle) expands it to full size, and the zone grows to fit. The observed
height depends only on the comment content, so there's no layout feedback
loop. Observers are disconnected on zone teardown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comments (and the reviewer popover) are GitHub-authored markdown that can
contain raw HTML. Add rehype-raw to parse it and rehype-sanitize (GitHub
schema) to strip anything unsafe, since the content comes from arbitrary
PR participants. Also add an UnfoldVertical/FoldVertical toggle on the diff
file header (left of Viewed) that expands/collapses all comments in the
file via a forceExpanded prop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The comment's click-to-expand handler caught bubbled clicks from rendered
HTML controls, so opening/closing a <details> also collapsed the comment.
Bail out of the toggle when the click originates inside an interactive
element (a/button/summary/details/input/textarea/select/label).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A draft comment pulled back from the pending review can return with a
null/0 line, so it rendered at the top of the file and — because its line
differed from the local copy — failed to dedupe, leaving both. Recover the
pulled comment's line from the matching local comment (same file + body)
before dedup, so it shows at the right line and replaces the local copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The REST pending-review-comments endpoint returns a null line for drafts,
so synced comments rendered at line 0 (top of file) and — never matching
the local copy — failed to dedupe, so each sync re-pushed a new draft.
That accumulation (comments → view zones → ResizeObservers) is also what
slowed the UI.

Fetch pending/draft review comments via GraphQL where originalLine is
populated, and collapse identical duplicates (file+line+body+author) so
prior accidental dupes don't pile up. Drop the now-unused pendingReviewId.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Carry a draft flag through ReviewSync*/ReviewComment (true for pending-
review comments and local-only ones, false for published). Drafts render
with an amber accent/background + a "Draft" badge; published comments keep
the blue accent — so it's clear what's still pending vs live on the PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…back loop

Each comment view zone has a ResizeObserver that resizes the Monaco zone to
fit its content. The onDidLayoutChange handler rewrote every sticky
wrapper's width on each editor layout change — which resized the very
elements those observers watch, retriggering them → changeViewZones →
layout change → loop, thrashing the renderer (the freeze while syncing).
Drop the width rewrite; the comment is capped at 760px and left-pinned, so
the width set once at zone creation is sufficient.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Carry the reply linkage through sync — in_reply_to_id (REST published) and
replyTo.databaseId (GraphQL drafts) → ReviewSyncComment.inReplyToId. Group
a file's comments into threads (a reply keys to its parent's remoteId, a
root to its own) and render each thread as one view zone: the root comment
followed by its replies, each inset 16px and touching the comment above so
the reply relationship reads visually. The InlineComment's own margin moved
to the thread container.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reply: a thread footer has a Reply control (lucide Reply) that opens a
textarea; submitting creates a local reply (inReplyToId = thread root) that
renders inset in the thread and, on sync, posts via REST in_reply_to.

Resolve: non-draft threads show a Resolve control (lucide CheckCheck) that
queues the thread's node id; the next sync calls resolveReviewThread. We
never unresolve — resolved state always comes from GitHub (pulled via
reviewThreads.isResolved), and resolved threads render dimmed with a
"Resolved" label. Carries threadId/resolved through ReviewSync*/
ReviewComment and resolveThreadIds through the sync input.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
j/k (↑/↓) stay as next/previous file. Shift+J / Shift+↓ now jump to the
next unreviewed file (Shift+K / Shift+↑ previous). ] / [ are repurposed to
cycle the next/previous comment thread in the current file (reveals the
line via onRevealLine). Shortcuts popup updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h tooltip

The diff file header truncated the end of long paths (hiding the filename).
Switch to the RTL truncation trick so the start is cut and the filename
stays visible, and add a tooltip showing the full path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
defineHarnessTheme() (which builds the Monaco theme from the CSS variables)
only ran once at boot, so open diff/file editors kept their original colors
when the app theme changed, and the base was hardcoded vs-dark (wrong for
light themes). Pick the base from the resolved background luminance, and
add a MutationObserver on :root data-theme/style that re-derives the theme
on change (setTheme re-applies to all editors).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…able)

Send to Agent used text-fg on bg-accent, and the comment/reply submit
buttons used color:var(--color-fg) on the accent — unreadable in light
themes. Switch to text-app / var(--color-app) (the app-bg color), which
inverts cleanly against the accent in both light and dark, matching the
convention used by the other accent buttons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Register a GitHub-Light-based light theme: white app bg, #f6f8fa panels,
#24292e text, GitHub blue (#0366d6) accent, with Primer-ish success/
warning/danger. Adds the THEME_OPTIONS entry and the [data-theme=
"hub-delight"] CSS variable block; it shows up in the light-theme picker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each comment's ResizeObserver called changeViewZones(layoutZone) directly,
and that relayout nudged other comment wrappers, firing their observers —
an N×N cascade (worse with many comments) that hogged the main thread and
made the UI lag on startup. Funnel desired heights into a map and apply
them all in a single rAF/changeViewZones; the per-zone guard plus the batch
let heights settle in a frame or two instead of cascading. rAF + pending
map are cleared on zone teardown and unmount.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The light/dark theme pickers are dimmed-but-clickable in the opposite mode,
so clicking a light theme while in Dark just set a preference and looked
like a no-op. Now selecting a theme also switches the mode to that theme's
mode (when in the opposite mode), so a click always takes effect. System
mode is left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The light-theme setter validates the requested id against
AVAILABLE_THEMES (main/persistence.ts) and silently returns false +
never dispatches when it's not listed. hub-delight was only added to
the renderer THEME_OPTIONS, so selecting it in light mode did nothing.
Add it to AVAILABLE_THEMES and THEME_APP_BG (#ffffff) so validation
passes and the first-paint window bg matches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a `reviewDiffMode` setting ('match' | 'light' | 'dark', default
'match') that pins the review tab's Monaco editors to the configured
light or dark Harness palette independent of the app theme — so the
chrome can stay dark/system while the diffs render light.

Monaco's theme is global, so this redefines the single 'harness' theme
from a hidden [data-theme] probe carrying the target palette; the
non-Monaco chrome and terminals are unaffected. A cycling appearance
button (Monitor/Sun/Moon) sits next to the whitespace toggle in the
review toolbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Word-wrap lived in each file's per-file diff header; move it up to the
review-level toolbar next to the whitespace toggle so it sits with the
other view controls (split/unified, whitespace, diff theme) and isn't
duplicated per file. The per-file header drops the button and its
now-unused onWordWrapChange prop; the wordWrap value still flows to the
Monaco editor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A small Copy button to the left of the file path copies the file's full
repo-relative path to the clipboard, flipping to a check for ~1.2s as
confirmation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
big-guy and others added 14 commits June 4, 2026 17:52
The code minimap was already off; the colored strip on the right edge of
each diff was Monaco's diff overview ruler. Disable it
(renderOverviewRuler + overviewRulerLanes: 0) for a cleaner stacked
review.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The auto-height mode set handleMouseWheel: false to make vertical wheel
bubble to the outer container, but that disabled both axes — long lines
could no longer be scrolled horizontally. Drop it and rely on
alwaysConsumeMouseWheel: false instead: the editor is sized to exactly
its content so it has no vertical scroll room (vertical wheel bubbles
up), while horizontal wheel still scrolls the diff.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A freshly-mounted auto-height diff editor briefly paints the full
modified text — un-tokenized and before hideUnchangedRegions collapses
it — before the diff settles, a visible flash when expanding a collapsed
section. Mount the editor hidden (opacity 0, set synchronously so the
first paint is hidden) and fade it in once onDidUpdateDiff fires (plus a
frame for tokenization), with a 300ms fallback reveal so identical/error/
binary diffs can't get stuck invisible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deleted files and diffs over 600 changed lines now render a click-to-show
row ("Diff not shown for deleted files by default" / "Large diffs are not
shown by default") instead of the full diff, keeping the stacked view
light. The diff isn't even fetched until revealed; clicking loads and
renders it normally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stacked sections now mount their Monaco editor when within ~800px of the
viewport and dispose it once more than ~2000px away, so memory tracks
what's on screen rather than how far you've scrolled. The hysteresis band
prevents thrash-cycling at the edge. The diff fetch still happens once
(latched hasBeenNear) so cached sides survive unmount/remount with no
refetch, the measured content height holds the placeholder so the scroll
doesn't jump, and comment view-zone roots are torn down on unmount and
re-rendered on remount.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Clicking a committed file in the Changed Files panel highlighted it in
the review file tree but didn't move the diff. Route the cross-component
file request through scrollToFile, with a `files` dep + nonce guard so it
also works when the request arrives before the file list has rendered
(review tab just opened) and only auto-scrolls once per request.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Long / deeply-nested paths were truncated with no way to read them. The
tree's scroll area now scrolls both axes (overflow-auto), and rows size to
their content (w-max min-w-full) with whitespace-nowrap instead of
truncating — so a long path extends into a horizontal scroll while short
rows still fill the panel width.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The commit selector scopes which commits the file list reflects, so it
reads better sitting directly above the file browser than tucked in the
top toolbar. Move it into the file-tree column header; the top bar now
holds just the view menu, Send, and Sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- First row, left→right: PR description, keyboard shortcuts, comment
  list, reviewers, view menu (hamburger).
- Reviewed count and total diff stat move up to the first row, just left
  of Send to Agent / Sync.
- Reviewed indicator is now a compact "m/n reviewed" (files reviewed /
  total), green when complete.
- The comment-list button drops the "comment(s)" word — just the count.
- The second status row is gone; the progress bar stays under the toolbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The commit selector now spans the full width of the file browser column
above it: the button is w-full with the commit label flex-filling and
truncating, and the chevron pinned to the right edge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Select a range of lines in a diff and press `c` to comment on the whole
span. The comment carries a startLine (GitHub `start_line`); the view
zone anchors at the end line and the covered lines get a tinted
highlight. The input and comment cards show the range ("Lines X–Y" /
"L10–14").

Plumbed end-to-end: ReviewComment + ReviewSyncComment gain startLine; the
`c` handler reads the editor's multi-line selection; push maps it to
GitHub's startLine/startSide on both the per-thread and batch review
mutations; pull reads start_line / originalStartLine (REST + the pending
GraphQL path) so ranges round-trip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each Monaco diff only searches itself (and far sections aren't mounted),
so add a review-level find bar. Cmd/Ctrl+F (captured so it beats Monaco's
per-editor find) opens it; matches are computed case-insensitively over
every file's modified content, fetched and cached on first search. Enter
/ Shift+Enter and the up/down buttons walk matches with an "i/n" counter.

Navigating a match reuses revealTarget, now upgraded to a real per-line
reveal in the auto-height stacked view: it scrolls the outer container to
the line's pixel offset (getTopForLineNumber, so collapsed regions + view
zones are accounted for) and briefly flashes the line — which also fixes
comment-list jumps that previously only scrolled to the file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The stacked all-files view mounted/disposed many Monaco diff editors as
you scrolled (each createDiffEditor is heavy, plus automaticLayout
polling and the virtualization mount/unmount hysteresis), making large
reviews sluggish. Go back to one Monaco editor at a time — the file the
reviewer selects — while keeping everything added since: multi-line
comments, copy-path, open-in-editor, and the Cmd+F search across all
files.

ReviewDiffPane drops the IntersectionObserver virtualization, the
auto-height host, per-file collapse, and the deleted/large
click-to-reveal placeholders; the editor fills the pane and owns its own
scroll again, and reveal uses revealLineInCenter. ReviewPane renders a
single ReviewDiffPane for the selected file and restores the
selectedFileObj/fileComments memos. Find is unchanged except that
navigating to a match now switches the selected file first, then reveals
the line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tailwind v4 / Lightning CSS minifies hex literals in the generated CSS
(`#ffffff` -> `#fff`), so reading a `--color-*` token back with
getComputedStyle can yield 3/4-digit shorthand. Monaco's token color map
validates with a strict 6/8-hex regex and throws `Illegal value for token
color: #fff` — and since the standalone theme service folds
`editor.background` into a token rule, a minified white app background
(Hub Delight) crashes the editor on theme switch. The same shorthand also
leaked into the Settings "Copy as JSON" output.

Add normalizeThemeColor() and apply it everywhere a color is derived from a
theme: monaco-setup readVar (fixes the crash), XTerminal terminal theme,
Settings copy-as-JSON (emits canonical long-form hex), and effectiveAppBg.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@big-guy
big-guy force-pushed the review-tab-improvements branch from 48c2c2d to dab78eb Compare June 5, 2026 01:24
big-guy and others added 15 commits June 5, 2026 00:06
Add a ListTree toggle button after the comments dropdown that hides the
file-tree column (and its resize handle), giving the diff the full width.

Also fix the comment count rendering one step larger than the rest of the
toolbar — the CommentDropdown button had no text-* class so the number
inherited the default size; pin it to text-xs to match the reviewed count
and diff stats.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mousedown on the comment "+" in the glyph margin and drag across lines to
select a span, then release to open a range comment — a GitHub-style
gesture that doesn't require text-selecting the diff first. The covered
lines highlight live during the drag (each gets the + plus the
comment-range tint); a single-line drag still falls back to a one-line
comment.

Implemented in MonacoDiffEditor via a new optional onReferenceRange prop
so the "reference line in Claude" callers (DiffView/FileView) are
unaffected — they pass no range handler and keep click-only behavior.
Because the drag starts on the glyph margin rather than content, Monaco
never begins its own text selection, so the gutter gesture stays
independent of the c-shortcut's selection path. ReviewDiffPane maps the
range to the same commentStartLine/commentLine state the c shortcut uses,
so it round-trips to GitHub's start_line unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Change the default openReview binding from Cmd+Alt+R to a bare F6.

Fix the Quake terminal (Ctrl+`) not opening in a review/diff/file tab
until the user had clicked into the Monaco editor. The Quake check
requires keyboard focus inside [data-tab-content], but focus sat on
<body> until something focusable grabbed it. Two fixes:

- WorkspaceView: the tab-content wrapper is now focusable (tabIndex=-1)
  and grabs focus on mousedown-capture, so clicking anywhere in a tab
  (file list, gutter, empty toolbar) keeps focus in-tab. Focusable
  targets still win via the click's default action.
- ReviewPane: focuses its root when the tab becomes active, so the
  hotkey works even before the first click.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebind next/previous unreviewed file from Shift+J/K (and Shift+Arrow)
to plain n / m. Add f to hide/show the file browser — handled in
ReviewPane since the tree is unmounted while collapsed and can't
restore itself. Updated the ? shortcuts popup to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- a: open + focus the comment-list dropdown; ↑/↓ navigate, Enter/Space
  select (reveals the comment's file+line), Esc closes. Nav uses a
  capture-phase listener so Arrow keys beat the file-nav handler.
- q: toggle whitespace rendering.
- w: toggle word wrap.
Updated the ? shortcuts popup to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The "PR description" button now toggles a pane docked at the bottom of
the file-browser column instead of a modal overlay. Off by default,
capped at 45% of the column height with its own scroll. Add g to
show/hide it. Updated the ? shortcuts popup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The left column now stays mounted whenever the file tree OR the PR
description is showing. When the file browser is collapsed, the PR
description fills the column (flex-1); otherwise it docks under the
tree capped at 45% height. The resize handle persists with the column.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The view-zone sync effect listed the comment callbacks in its deps, but
the parent passes onAddComment as an inline arrow (fresh identity every
render). Any background re-render (PR poll, file watcher, sync) re-ran
the effect, tore down the view zones, and remounted InlineCommentInput —
wiping the in-progress draft. Hold the callbacks in refs and drop them
from the effect deps so the input stays mounted while typing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The +adds/−dels total now sits beside the commit selector in the file
browser column instead of in the top controls bar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When a review has an associated PR, add a control group between the
reviewed count and Send-to-Agent:
- CheckCheck button approves the PR (enabled only once all files are
  reviewed, m == n); errors surface in its tooltip.
- "Submit…" dropdown: radio (Approve / Request changes / Comment) + a
  top-level comment box + Cancel/Submit. Backed by a new general
  submitPRReview(event, body) IPC path; approvePR now delegates to it.

PR description pane: show the author avatar + name, target branch, and
milestone (when present) under a now word-wrapped title; drop the close
button (toggle via the toolbar button / g). The toolbar PR-description
button now shows #<number>.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…view

Both the CheckCheck approve and the "Submit…" review now push staged
draft comments + viewed state to the PR first (whole-branch reviews),
so the review lands with its line comments rather than after them. If
the flush fails, the submit/approve is aborted and the error surfaces
(button tooltip / menu). runSync now reports success for this gating.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment view zones sized their sticky wrapper once at creation, so they
stayed narrow after the diff got wider (file browser collapsed, window
resized). Re-apply the editor's contentWidth to every wrapper on
onDidLayoutChange, guarded on a last-applied ref so unchanged layouts are
a no-op — that guard is what keeps the resize off the per-zone height
ResizeObserver feedback loop the old code sidestepped by never resizing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A Crosshair button sits next to the filter input. Clicking it scrolls the
currently open diff file's row into view and flashes it briefly. It first
clears any active filter and expands collapsed ancestor folders so the row
is rendered, then a nonce-keyed effect (which re-runs as those changes land)
does the scroll-into-view + flash. Disabled when no file is open.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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