From f0e317265ca981b5dc91db40335e1abe9910c1f5 Mon Sep 17 00:00:00 2001 From: patrick-mns Date: Fri, 17 Jul 2026 15:21:13 -0300 Subject: [PATCH] fix(review): scope the changes panel to the selected folder Run git diff with --relative so the changes panel and the +N/-N badge report only the selected folder's subtree instead of the whole repo, and refresh the panel whenever the active folder or workspace changes. Drop the now-redundant folder chip from the panel header. Co-Authored-By: Claude Opus 4.8 --- frontend/src/App.tsx | 12 +++++++++--- frontend/src/components/ReviewChip.tsx | 15 ++------------- frontend/src/utils/theme-styles.ts | 5 ----- src/backend/review.rs | 12 +++++++++--- src/commands/settings.rs | 4 +++- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d2c037d..6f270d3 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -113,6 +113,7 @@ const { t } = useI18n(); const { status: reviewStatus, gitRevertFile, gitRevertAll, + refresh: refreshReview, } = useReview(); const { switching, pickWorkspace } = useWorkspace(); const { loadCurrentWorkspace, currentWorkspace, activeRoot } = useStore(); @@ -120,7 +121,14 @@ const { t } = useI18n(); // The changes panel is scoped to a single active folder (backend workspace_root): // activeRoot when set, otherwise the workspace's first folder. const activeFolderPath = activeRoot || currentWorkspace?.folders?.[0] || ''; - const activeFolderName = activeFolderPath.split('/').pop() || activeFolderPath.split('\\').pop() || ''; + + // Re-fetch the diff whenever the folder or workspace changes. The backend + // updates its workspace_root before either value settles, so by now + // get_review_status reads the newly-selected folder. Without this the panel + // keeps showing the previous folder's (or workspace's) changes. + useEffect(() => { + refreshReview(); + }, [refreshReview, activeFolderPath, currentWorkspace?.id]); const handleDeleteSessionConfirm = async () => { const id = confirmDeleteSession; @@ -264,8 +272,6 @@ const { t } = useI18n(); {panelContent === 'review' ? ( setRightPanel(null)} onRevert={gitRevertFile} onRevertAll={gitRevertAll} diff --git a/frontend/src/components/ReviewChip.tsx b/frontend/src/components/ReviewChip.tsx index 44e201d..14b7e2d 100644 --- a/frontend/src/components/ReviewChip.tsx +++ b/frontend/src/components/ReviewChip.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useState } from 'react'; import { reviewPanelStyles } from '@/utils/theme-styles'; -import { CheckCircle, X, GitFork, CaretDown, FolderOpen } from '@phosphor-icons/react'; +import { CheckCircle, X, GitFork, CaretDown } from '@phosphor-icons/react'; import { theme } from '@/theme'; import type { ReviewFileInfo } from '@/hooks/useReview'; import { computeDiff } from '@/utils/diff'; @@ -160,9 +160,6 @@ function FileCard({ file, onRevert }: FileCardProps) { interface ReviewPanelProps { gitFiles: ReviewFileInfo[]; - /** Active folder the diff is scoped to — shown so the source is unambiguous. */ - folderName?: string; - folderPath?: string; onClose: () => void; onRevert: (path: string) => void; onRevertAll: () => void; @@ -170,23 +167,15 @@ interface ReviewPanelProps { export function ReviewPanel({ gitFiles, - folderName, - folderPath, onClose, onRevert, onRevertAll, }: ReviewPanelProps) { return (
- {/* Header — title + which folder these changes come from */} + {/* Header */}
Changes - {folderName && ( - - - {folderName} - - )}
diff --git a/frontend/src/utils/theme-styles.ts b/frontend/src/utils/theme-styles.ts index 6407ff6..de0e104 100644 --- a/frontend/src/utils/theme-styles.ts +++ b/frontend/src/utils/theme-styles.ts @@ -259,11 +259,6 @@ export const reviewPanelStyles: Record = { flexShrink: 0, }, headTitle: { flex: 1, color: theme.text, fontSize: 13, fontWeight: 600 }, - headFolder: { - display: 'flex', alignItems: 'center', gap: 4, minWidth: 0, - color: theme.dim, fontSize: 11.5, - }, - headFolderName: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, closeBtn: { // Uses .close-btn from primitives.css — same as BgTasks }, diff --git a/src/backend/review.rs b/src/backend/review.rs index 8b92c96..078c209 100644 --- a/src/backend/review.rs +++ b/src/backend/review.rs @@ -128,10 +128,14 @@ pub fn git_diff_files(workspace_root: &Path) -> Result, Stri use crate::backend::cmd::no_window_cmd; // 1. Get list of changed files vs HEAD (staged + unstaged, no untracked). + // `--relative` scopes the diff to `workspace_root` — the selected folder — + // excluding changes elsewhere in the repo and emitting folder-relative + // paths. Without it, `git diff` reports the whole repository even when run + // from a subfolder, so the panel would show changes outside the folder. // On failure (not a git repo, or no commits yet) treat the tracked set // as empty and still surface untracked files in step 3. let name_output = no_window_cmd("git") - .args(["diff", "HEAD", "--name-only"]) + .args(["diff", "HEAD", "--name-only", "--relative"]) .current_dir(workspace_root) .output() .map_err(|e| format!("git failed: {e}"))?; @@ -148,9 +152,11 @@ pub fn git_diff_files(workspace_root: &Path) -> Result, Stri // 2. For each file, get unified diff and also the original/current content let mut files = Vec::new(); for name in &names { - // Original content (from HEAD) + // Original content (from HEAD). `name` is folder-relative (see + // `--relative` above), so prefix `./` to resolve it against the cwd + // rather than the repo root. let original = no_window_cmd("git") - .args(["show", &format!("HEAD:{}", name)]) + .args(["show", &format!("HEAD:./{}", name)]) .current_dir(workspace_root) .output() .ok() diff --git a/src/commands/settings.rs b/src/commands/settings.rs index b01fba2..6715f02 100755 --- a/src/commands/settings.rs +++ b/src/commands/settings.rs @@ -523,8 +523,10 @@ pub async fn get_git_context(state: State<'_, AppState>) -> Result