VS Code Minimap: the canvas painter (2/4)

Merged
TE
11d ago
+381-0

Part 2 of 4 of the VS Code Minimap. Land order: #25275 (setting), this PR (the painter), #25185 (the minimap), then #25280 (the placeholder looks). Stacked on #25275; review only its two commits (paint.ts and its test, +373).

Leo's words

minimap? i dont see any command for the vscode minimap

the mini map VS Code code thing ... Although I don't know if that actually, like, causes potential lag.

What this adds

webviews/src/agent-session/acpmux/chatMinimap/paint.ts draws the whole chat small into one canvas, from the transcript's existing layout (tops/heights). Nothing is measured, no text is drawn, and it never touches the DOM.

  • Kinds: a prompt is a bar at the right, where its bubble sits. A reply is text-like lines at the left. A tool group is a narrower muted block.
  • Bounded draws: each kind is one path and one fill, and rows on the same device pixel line merge. A draw is therefore bounded by the canvas's height, not by the number of rows.
  • Scale: a short chat draws at 1/8 scale from the top, as VS Code does; a long one fits the track.
  • Change check: firstChangedRow lets the minimap skip a draw when no row moved.

The minimap that uses it lands in #25185.

Tests

Review fixes (gpt-6-astra), in the second commit. Each has a test that fails on the first commit:

  • A streaming reply is never painted. minimapKind gives a reply with row.streaming no kind, so its place is always the minimap's placeholder and no caller repaints it per token.
  • Line jitter is seeded by the row's id, not its index, so rows inserted or removed above a reply leave its lines alone.
  • firstChangedRow compares row ids and map kinds, so a same-shaped row swapped in, or a reply that stops streaming, repaints.
  • streamingRow moved here from #25185, keeping that PR under the size cap. It finds the live reply from the transcript's rowsChange: the rows before the first change are the last render's objects, so only changed rows are read, however many queued or late rows follow the reply. The same rows (a scroll frame) read nothing.

webviews/test/chat-minimap-paint.test.ts (new; it can't run on base, which has no painter):

  • the row kinds and their mapping;
  • the scale and the view box;
  • a 20,000-row chat draws at most one rectangle per kind per device line, and fewer than 1.5Ɨ a 2,000-row one, always with 3 fills;
  • firstChangedRow.

Risk

None at runtime: nothing imports it until #25185.

Agent session: huge-blue

šŸ¤– Generated with Claude Code