feat(desktop): add cmd+f search to the v2 changes pane

Merged
AV
4mo ago
+869-39

Summary

Adds find-in-pane (⌘F / Ctrl+Shift+F) to the v2 workspace Changes pane (DiffPane).

Because the pane's CodeView (@pierre/diffs) virtualizes rows, a DOM-based text search would only ever see the mounted viewport. Search is therefore split into two layers:

  • Data-driven matches — a new collectDiffSearchMatches util walks each file's parsed hunks (context/deletion/addition lines with per-side line numbers) to build the complete, scroll-stable match list across the whole changeset, honoring the expandUnchanged setting.
  • DOM painting — CSS Custom Highlights are painted over whatever rows are currently mounted and repainted (via MutationObserver) as the virtualizer swaps rows in and out; painting never mutates the match list.

Details:

  • New FIND_IN_CHANGES hotkey in the registry, gated on pane focus like the terminal/file-viewer/chat find hotkeys that share the binding.
  • Next/previous navigation uses the virtualizer's scrollTo({type: "line", …}), so it reaches unmounted rows; matches in collapsed files auto-expand the file before scrolling.
  • Search state resets when the pane identity changes (same-kind v2 panes reuse one React instance across tabs) and closes when the pane loses focus.
  • Reuses the existing MarkdownSearch find-bar UI and findTextRanges DOM walker; extracted the ::highlight() style injection from useTextSearch into a shared syncHighlightStyles helper used by both hooks.

Scope notes: matches cover diff code lines only (comment threads and file headers are slotted light DOM, excluded from both counting and painting); lines revealed via manual context expansion are highlighted visually but not counted.

Test Plan

  • bun test collectDiffSearchMatches.test.ts — 8 cases covering addition/deletion/context numbering, occurrence counting, case sensitivity, expandUnchanged, and match ordering against real parseDiffFromFile output
  • bun run lint clean; tsc clean for all touched files
  • Manual: ⌘F in Changes pane — match count stays stable while scrolling; Enter/Shift+Enter cycle across files, expand collapsed files, and jump to off-screen matches

Open in Stage

Summary by cubic

Add Cmd+F (or Ctrl+Shift+F) search to the v2 Changes pane with full diff coverage and inline highlights. Highlights no longer span across rows, keeping the match counter accurate during scroll and navigation.

  • New Features

    • FIND_IN_CHANGES hotkey opens a MarkdownSearch find bar in the Changes pane.
    • Searches across the whole diff using @pierre/diffs hunks; respects expandUnchanged.
    • Uses CSS Custom Highlights over virtualized rows; match count stays stable.
    • Next/previous jumps to off-screen lines and auto-expands collapsed files; closes on blur and resets on pane change.
  • Refactors

    • Extracted syncHighlightStyles for shared ::highlight() CSS injection and updated useTextSearch to use it.
    • Added collectDiffSearchMatches with tests for numbering, occurrences, case sensitivity, ordering, expandUnchanged, and a two-hunk gap-fill case.

Summary by CodeRabbit

  • New Features
    • Added “Find in Changes” search within diff views, including match counting, next/previous navigation, repeated matches, and optional expansion of unchanged content.
    • Introduced a platform-specific hotkey to toggle the diff search, and improved search highlighting across virtualized rows and shadow-root content.
    • Enhanced text search highlight rendering by synchronizing highlight style elements with the active DOM/roots.
  • Tests
    • Added Bun tests covering diff match extraction, ordering, line references, case sensitivity, and unchanged-context behavior.