Skip to content

Comments

feat(staged): implement standalone diff viewer app with staged-changes mode#243

Merged
baxen merged 8 commits intomainfrom
staged-again
Feb 24, 2026
Merged

feat(staged): implement standalone diff viewer app with staged-changes mode#243
baxen merged 8 commits intomainfrom
staged-again

Conversation

@baxen
Copy link
Collaborator

@baxen baxen commented Feb 24, 2026

Summary

  • Implement a standalone Tauri diff viewer app (apps/staged) with a single-page layout, custom folder picker, and theme selector
  • Add staged-changes mode with a segmented control to toggle between staged and full diff views, plus a draggable titlebar for native window feel
  • Upgrade empty state with a custom icon (Mark's icon), descriptive message, and animated git tree visualization
  • Extend git-diff crate with support for staged diff operations and new diff types

Test plan

  • Verify the app launches and displays diffs correctly for a selected git repository
  • Test switching between staged-changes and full diff modes via the segmented control
  • Confirm the empty state shows the custom icon and git tree animation when no diffs are present
  • Verify the folder picker and theme selector function correctly
  • Test the draggable titlebar on macOS

🤖 Generated with Claude Code

baxen and others added 5 commits February 23, 2026 14:16
Build the first working version of the Staged app — a focused,
standalone diff viewer that opens on any git repository.

Backend (Rust/Tauri):
- Add git-diff crate dependency for shared diff computation
- Implement Tauri commands: get_repo_info, list_recent_commits,
  list_diff_files, get_file_diff, get_file_at_ref, get_launch_args,
  open_repo_dialog
- CLI arg parsing: repo path as positional arg, --staged/-s,
  --branch/-b, --commit/-c <sha>, --all/-a flags
- Folder picker dialog for switching repositories

Frontend (Svelte):
- HomePage: repo info bar, mode picker cards (All Changes, Full Branch,
  Commit), commit history picker
- DiffPage: full-page diff view using shared @builderbot/diff-viewer
  components with file tree sidebar and inline commenting
- commands.ts: typed invoke wrappers with DiffSpec builders
  (specUncommitted, specBranch, specCommit, specRange)
- App.svelte: simple view router (home <-> diff) with CLI arg
  auto-navigation
- Dark theme CSS variables matching Mark's design system

The app uses DiffSpec directly (base/head GitRef pairs) rather than
Mark's branch-id-based abstraction, making it work on any repo
without a database.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…selector

Replace the two-page home→diff flow with a single-page layout that shows
the diff viewer immediately. Add a spotlight-style folder picker with
filesystem browsing and recent repo discovery (using macOS mdfind), and
a searchable theme picker with adaptive theming derived from syntax colors.

- Add Rust commands: set_repo_path, list_directory, search_directories,
  get_home_dir, find_recent_repos (with Spotlight integration)
- New FolderPickerModal with breadcrumb nav, search, keyboard shortcuts
- New ThemePicker dropdown with light/dark indicators and search
- New preferences store with Tauri persistent storage and adaptive themes
- Titlebar: macOS traffic lights (left), diff mode selector (center),
  repo/theme controls (right)
- Remove HomePage.svelte and DiffPage.svelte (merged into App.svelte)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le titlebar

Three UX improvements to the Staged diff viewer:

1. Draggable titlebar: The center section of the titlebar now participates
   in the drag region, so you can move the window by dragging anywhere on
   the titlebar outside of interactive controls.

2. Staged changes mode: Add a new "Staged" diff mode that shows only
   git-staged (indexed) changes using `git diff --cached`. This adds an
   `Index` variant to the GitRef enum, with full support in the git-diff
   crate (list_diff_files via CLI, get_file_diff via libgit2's
   diff_tree_to_index, and file content loading from the index).

3. Segmented control: Replace the separate mode buttons with a connected
   segmented control (pill-shaped group with shared background). The
   active segment gets an elevated background with a subtle shadow,
   making the mutual exclusivity of the options immediately obvious.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…imation

Replace the plain "No changes" text with a polished empty state inspired
by Mark's splash screen. The new empty state features:

- Framed icon (CircleDashed) in an elevated card matching Mark's icon-frame
- Heading "No changes found" with a hint to use the toolbar
- Animated git tree visualization as a subtle background (20% opacity)
- Fade-in entrance animation

Copies GitTreeAnimation.svelte from Mark into the staged app — a canvas-
based procedural git tree that continuously generates commits, branches,
and merges with color-coded event pulses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the generic CircleDashed lucide icon with the actual Mark app
icon (branch path in a rounded rect) for the empty state. This matches
Mark's splash screen rendering — the MarkIcon SVG component at 52px
inside a 104x104 icon frame with 26px border radius and deeper shadow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
baxen and others added 3 commits February 23, 2026 19:10
The titlebar was nearly impossible to drag because -webkit-app-region: drag
was being overridden by no-drag on almost every child element (segmented
control, file count, repo/theme buttons), leaving only the 72px traffic-
light spacer as a grab target.

Switch to Mark's approach: a single pointerdown handler on the titlebar
that calls getCurrentWindow().startDragging() when the click target isn't
an interactive element (button, a, input, [role="button"]). This makes
every pixel of empty space in the titlebar draggable — the gaps between
buttons, padding, and flex spacers all participate in the drag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The programmatic window dragging added in ad0ddfd calls
getCurrentWindow().startDragging() but the staged app's capabilities
file was missing the required core:window:allow-start-dragging permission,
causing an "Unhandled Promise Rejection" error on every drag attempt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The staged app's svelte-check was failing because the diff-viewer
package imports sanitize-html without a corresponding type declaration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@baxen baxen merged commit 8499825 into main Feb 24, 2026
6 checks passed
@baxen baxen deleted the staged-again branch February 24, 2026 06:23
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