Skip to content

Commit 4b3c7ed

Browse files
committed
feat(code): use chosen diff source for badge
1 parent 0459081 commit 4b3c7ed

3 files changed

Lines changed: 118 additions & 38 deletions

File tree

apps/code/src/renderer/features/code-review/components/DiffStatsBadge.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { Tooltip } from "@components/ui/Tooltip";
2-
import { useGitQueries } from "@features/git-interaction/hooks/useGitQueries";
2+
import {
3+
useBranchChangedFiles,
4+
useGitQueries,
5+
usePrChangedFiles,
6+
} from "@features/git-interaction/hooks/useGitQueries";
37
import { computeDiffStats } from "@features/git-interaction/utils/diffStats";
48
import { useCwd } from "@features/sidebar/hooks/useCwd";
59
import { useCloudChangedFiles } from "@features/task-detail/hooks/useCloudChangedFiles";
@@ -14,22 +18,44 @@ import {
1418
import { useReviewNavigationStore } from "@renderer/features/code-review/stores/reviewNavigationStore";
1519
import type { Task } from "@shared/types";
1620
import { useMemo } from "react";
21+
import { useEffectiveDiffSource } from "../hooks/useEffectiveDiffSource";
1722

1823
interface DiffStatsBadgeProps {
1924
task: Task;
2025
}
2126

22-
function useChangedFileStats(task: Task) {
27+
interface DiffStatsValue {
28+
filesChanged: number;
29+
linesAdded: number;
30+
linesRemoved: number;
31+
}
32+
33+
function useChangedFileStats(task: Task): DiffStatsValue {
2334
const taskId = task.id;
2435
const workspace = useWorkspace(taskId);
2536
const isCloud =
2637
workspace?.mode === "cloud" || task.latest_run?.environment === "cloud";
2738
const repoPath = useCwd(taskId);
2839

40+
// Local working-tree stats — always available for local tasks; the basis
41+
// for the "local" source and the fallback when other queries aren't loaded.
2942
const { diffStats: localDiffStats } = useGitQueries(
3043
isCloud ? undefined : repoPath,
3144
);
3245

46+
// Source resolution + the branch/PR queries that back the non-local
47+
// sources. For cloud tasks these all run but return nothing useful — the
48+
// memo below short-circuits to cloud stats regardless.
49+
const { effectiveSource, repoSlug, linkedBranch, prUrl } =
50+
useEffectiveDiffSource(taskId);
51+
const { data: branchFiles } = useBranchChangedFiles(
52+
!isCloud && effectiveSource === "branch" ? repoSlug : null,
53+
!isCloud && effectiveSource === "branch" ? linkedBranch : null,
54+
);
55+
const { data: prFiles } = usePrChangedFiles(
56+
!isCloud && effectiveSource === "pr" ? prUrl : null,
57+
);
58+
3359
const { reviewFiles } = useCloudChangedFiles(taskId, task);
3460

3561
return useMemo(() => {
@@ -41,12 +67,25 @@ function useChangedFileStats(task: Task) {
4167
linesRemoved: stats.linesRemoved,
4268
};
4369
}
70+
if (effectiveSource === "branch" && branchFiles) {
71+
return computeDiffStats(branchFiles);
72+
}
73+
if (effectiveSource === "pr" && prFiles) {
74+
return computeDiffStats(prFiles);
75+
}
4476
return {
4577
filesChanged: localDiffStats.filesChanged,
4678
linesAdded: localDiffStats.linesAdded,
4779
linesRemoved: localDiffStats.linesRemoved,
4880
};
49-
}, [isCloud, reviewFiles, localDiffStats]);
81+
}, [
82+
isCloud,
83+
effectiveSource,
84+
branchFiles,
85+
prFiles,
86+
localDiffStats,
87+
reviewFiles,
88+
]);
5089
}
5190

5291
export function DiffStatsBadge({ task }: DiffStatsBadgeProps) {

apps/code/src/renderer/features/code-review/components/ReviewPage.tsx

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
1-
import { useDiffViewerStore } from "@features/code-editor/stores/diffViewerStore";
21
import {
32
useBranchChangedFiles,
4-
useGitQueries,
53
usePrChangedFiles,
64
} from "@features/git-interaction/hooks/useGitQueries";
7-
import { useLinkedBranchPrUrl } from "@features/git-interaction/hooks/useLinkedBranchPrUrl";
85
import { makeFileKey } from "@features/git-interaction/utils/fileKey";
96
import { usePanelLayoutStore } from "@features/panels/store/panelLayoutStore";
107
import { useCwd } from "@features/sidebar/hooks/useCwd";
11-
import { useWorkspace } from "@features/workspace/hooks/useWorkspace";
128
import type { parsePatchFiles } from "@pierre/diffs";
139
import { Flex, Text } from "@radix-ui/themes";
1410
import { useReviewNavigationStore } from "@renderer/features/code-review/stores/reviewNavigationStore";
1511
import { useTRPC } from "@renderer/trpc/client";
1612
import type { ChangedFile, Task } from "@shared/types";
1713
import { useQuery } from "@tanstack/react-query";
1814
import { useMemo } from "react";
15+
import { useEffectiveDiffSource } from "../hooks/useEffectiveDiffSource";
1916
import { useReviewDiffs } from "../hooks/useReviewDiffs";
2017
import type { DiffOptions } from "../types";
21-
import {
22-
type ResolvedDiffSource,
23-
resolveDiffSource,
24-
} from "../utils/resolveDiffSource";
18+
import type { ResolvedDiffSource } from "../utils/resolveDiffSource";
2519
import { InteractiveFileDiff } from "./InteractiveFileDiff";
2620
import { LazyDiff } from "./LazyDiff";
2721
import { RemoteDiffList } from "./RemoteDiffList";
@@ -44,36 +38,21 @@ interface ReviewPageProps {
4438
export function ReviewPage({ task }: ReviewPageProps) {
4539
const taskId = task.id;
4640
const repoPath = useCwd(taskId);
47-
const workspace = useWorkspace(taskId);
48-
const linkedBranch = workspace?.linkedBranch ?? null;
4941
const openFile = usePanelLayoutStore((s) => s.openFile);
5042

5143
const isReviewOpen = useReviewNavigationStore(
5244
(s) => (s.reviewModes[taskId] ?? "closed") !== "closed",
5345
);
5446

55-
const configuredSource = useDiffViewerStore(
56-
(s) => s.diffSource[taskId] ?? null,
57-
);
58-
5947
const {
60-
repoInfo,
61-
aheadOfDefault,
62-
defaultBranch,
63-
changedFiles: workspaceFiles,
64-
} = useGitQueries(repoPath);
65-
const prUrl = useLinkedBranchPrUrl(taskId);
66-
const hasLocalChanges = workspaceFiles.length > 0;
67-
const branchSourceAvailable = !!linkedBranch && aheadOfDefault > 0;
68-
const prSourceAvailable = !!prUrl;
69-
70-
const effectiveSource = resolveDiffSource({
71-
configured: configuredSource,
72-
hasLocalChanges,
48+
effectiveSource,
49+
prUrl,
7350
linkedBranch,
74-
aheadOfDefault,
51+
defaultBranch,
52+
repoSlug,
53+
branchSourceAvailable,
7554
prSourceAvailable,
76-
});
55+
} = useEffectiveDiffSource(taskId);
7756

7857
const isLocalActive = isReviewOpen && effectiveSource === "local";
7958

@@ -118,7 +97,7 @@ export function ReviewPage({ task }: ReviewPageProps) {
11897
<BranchReviewPage
11998
task={task}
12099
branch={linkedBranch as string}
121-
repoInfo={repoInfo ?? undefined}
100+
repoSlug={repoSlug}
122101
defaultBranch={defaultBranch}
123102
isReviewOpen={isReviewOpen}
124103
effectiveSource={effectiveSource}
@@ -207,7 +186,7 @@ export function ReviewPage({ task }: ReviewPageProps) {
207186
function BranchReviewPage({
208187
task,
209188
branch,
210-
repoInfo,
189+
repoSlug,
211190
defaultBranch,
212191
isReviewOpen,
213192
effectiveSource,
@@ -216,17 +195,14 @@ function BranchReviewPage({
216195
}: {
217196
task: Task;
218197
branch: string;
219-
repoInfo: { organization: string; repository: string } | undefined;
198+
repoSlug: string | null;
220199
defaultBranch: string | null;
221200
isReviewOpen: boolean;
222201
effectiveSource: ResolvedDiffSource;
223202
branchSourceAvailable: boolean;
224203
prSourceAvailable: boolean;
225204
}) {
226205
const taskId = task.id;
227-
const repoSlug = repoInfo
228-
? `${repoInfo.organization}/${repoInfo.repository}`
229-
: null;
230206

231207
const { data: files = EMPTY_BRANCH_FILES, isLoading } = useBranchChangedFiles(
232208
isReviewOpen ? repoSlug : null,
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { DiffSource } from "@features/code-editor/stores/diffViewerStore";
2+
import { useDiffViewerStore } from "@features/code-editor/stores/diffViewerStore";
3+
import { useGitQueries } from "@features/git-interaction/hooks/useGitQueries";
4+
import { useLinkedBranchPrUrl } from "@features/git-interaction/hooks/useLinkedBranchPrUrl";
5+
import { useCwd } from "@features/sidebar/hooks/useCwd";
6+
import { useWorkspace } from "@features/workspace/hooks/useWorkspace";
7+
import {
8+
type ResolvedDiffSource,
9+
resolveDiffSource,
10+
} from "../utils/resolveDiffSource";
11+
12+
export interface EffectiveDiffSource {
13+
effectiveSource: ResolvedDiffSource;
14+
configured: DiffSource | null;
15+
prUrl: string | null;
16+
linkedBranch: string | null;
17+
defaultBranch: string | null;
18+
repoSlug: string | null;
19+
branchSourceAvailable: boolean;
20+
prSourceAvailable: boolean;
21+
}
22+
23+
/**
24+
* Resolves which diff source should be shown for a local task, plus all the
25+
* context needed to actually fetch that source. Callers (review panel, diff
26+
* stats badge) share one source-of-truth so UI surfaces never disagree.
27+
*/
28+
export function useEffectiveDiffSource(taskId: string): EffectiveDiffSource {
29+
const repoPath = useCwd(taskId);
30+
const workspace = useWorkspace(taskId);
31+
const linkedBranch = workspace?.linkedBranch ?? null;
32+
33+
const configured = useDiffViewerStore((s) => s.diffSource[taskId] ?? null);
34+
35+
const { repoInfo, aheadOfDefault, defaultBranch, changedFiles } =
36+
useGitQueries(repoPath);
37+
const hasLocalChanges = changedFiles.length > 0;
38+
const branchSourceAvailable = !!linkedBranch && aheadOfDefault > 0;
39+
40+
const prUrl = useLinkedBranchPrUrl(taskId);
41+
const prSourceAvailable = !!prUrl;
42+
43+
const repoSlug = repoInfo
44+
? `${repoInfo.organization}/${repoInfo.repository}`
45+
: null;
46+
47+
const effectiveSource = resolveDiffSource({
48+
configured,
49+
hasLocalChanges,
50+
linkedBranch,
51+
aheadOfDefault,
52+
prSourceAvailable,
53+
});
54+
55+
return {
56+
effectiveSource,
57+
configured,
58+
prUrl,
59+
linkedBranch,
60+
defaultBranch,
61+
repoSlug,
62+
branchSourceAvailable,
63+
prSourceAvailable,
64+
};
65+
}

0 commit comments

Comments
 (0)