Skip to content

Commit 58ca4e0

Browse files
committed
feat(code): use chosen diff source for badge
1 parent 58ec2e3 commit 58ca4e0

4 files changed

Lines changed: 135 additions & 66 deletions

File tree

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

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { Tooltip } from "@components/ui/Tooltip";
2-
import { useGitQueries } from "@features/git-interaction/hooks/useGitQueries";
3-
import { computeDiffStats } from "@features/git-interaction/utils/diffStats";
4-
import { useCwd } from "@features/sidebar/hooks/useCwd";
2+
import {
3+
useBranchChangedFiles,
4+
usePrChangedFiles,
5+
} from "@features/git-interaction/hooks/useGitQueries";
6+
import {
7+
computeDiffStats,
8+
type DiffStats,
9+
} from "@features/git-interaction/utils/diffStats";
510
import { useCloudChangedFiles } from "@features/task-detail/hooks/useCloudChangedFiles";
611
import { useWorkspace } from "@features/workspace/hooks/useWorkspace";
712
import { GitDiff } from "@phosphor-icons/react";
@@ -14,51 +19,74 @@ import {
1419
import { useReviewNavigationStore } from "@renderer/features/code-review/stores/reviewNavigationStore";
1520
import type { Task } from "@shared/types";
1621
import { useMemo } from "react";
22+
import { useEffectiveDiffSource } from "../hooks/useEffectiveDiffSource";
1723

1824
interface DiffStatsBadgeProps {
1925
task: Task;
2026
}
2127

22-
function useChangedFileStats(task: Task) {
23-
const taskId = task.id;
24-
const workspace = useWorkspace(taskId);
28+
export function DiffStatsBadge({ task }: DiffStatsBadgeProps) {
29+
const workspace = useWorkspace(task.id);
2530
const isCloud =
2631
workspace?.mode === "cloud" || task.latest_run?.environment === "cloud";
27-
const repoPath = useCwd(taskId);
28-
29-
const { diffStats: localDiffStats } = useGitQueries(
30-
isCloud ? undefined : repoPath,
32+
return isCloud ? (
33+
<CloudDiffStatsBadge task={task} />
34+
) : (
35+
<LocalDiffStatsBadge task={task} />
3136
);
37+
}
38+
39+
function CloudDiffStatsBadge({ task }: { task: Task }) {
40+
const { reviewFiles } = useCloudChangedFiles(task.id, task);
41+
const stats = useMemo(() => computeDiffStats(reviewFiles), [reviewFiles]);
42+
return <DiffStatsButton taskId={task.id} stats={stats} />;
43+
}
3244

33-
const { reviewFiles } = useCloudChangedFiles(taskId, task);
45+
function LocalDiffStatsBadge({ task }: { task: Task }) {
46+
const taskId = task.id;
47+
const {
48+
effectiveSource,
49+
repoSlug,
50+
linkedBranch,
51+
prUrl,
52+
diffStats: localDiffStats,
53+
} = useEffectiveDiffSource(taskId);
3454

35-
return useMemo(() => {
36-
if (isCloud) {
37-
const stats = computeDiffStats(reviewFiles);
38-
return {
39-
filesChanged: stats.filesChanged,
40-
linesAdded: stats.linesAdded,
41-
linesRemoved: stats.linesRemoved,
42-
};
55+
const { data: branchFiles } = useBranchChangedFiles(
56+
effectiveSource === "branch" ? repoSlug : null,
57+
effectiveSource === "branch" ? linkedBranch : null,
58+
);
59+
const { data: prFiles } = usePrChangedFiles(
60+
effectiveSource === "pr" ? prUrl : null,
61+
);
62+
63+
const stats = useMemo<DiffStats>(() => {
64+
if (effectiveSource === "branch" && branchFiles) {
65+
return computeDiffStats(branchFiles);
66+
}
67+
if (effectiveSource === "pr" && prFiles) {
68+
return computeDiffStats(prFiles);
4369
}
44-
return {
45-
filesChanged: localDiffStats.filesChanged,
46-
linesAdded: localDiffStats.linesAdded,
47-
linesRemoved: localDiffStats.linesRemoved,
48-
};
49-
}, [isCloud, reviewFiles, localDiffStats]);
70+
return localDiffStats;
71+
}, [effectiveSource, branchFiles, prFiles, localDiffStats]);
72+
73+
return <DiffStatsButton taskId={taskId} stats={stats} />;
5074
}
5175

52-
export function DiffStatsBadge({ task }: DiffStatsBadgeProps) {
53-
const taskId = task.id;
54-
const { filesChanged, linesAdded, linesRemoved } = useChangedFileStats(task);
76+
function DiffStatsButton({
77+
taskId,
78+
stats,
79+
}: {
80+
taskId: string;
81+
stats: DiffStats;
82+
}) {
5583
const reviewMode = useReviewNavigationStore(
5684
(s) => s.reviewModes[taskId] ?? "closed",
5785
);
5886
const setReviewMode = useReviewNavigationStore((s) => s.setReviewMode);
5987

88+
const { filesChanged, linesAdded, linesRemoved } = stats;
6089
const hasChanges = filesChanged > 0;
61-
6290
const isOpen = reviewMode !== "closed";
6391

6492
const handleClick = () => {

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

@@ -123,7 +102,7 @@ export function ReviewPage({ task }: ReviewPageProps) {
123102
<BranchReviewPage
124103
task={task}
125104
branch={linkedBranch as string}
126-
repoInfo={repoInfo ?? undefined}
105+
repoSlug={repoSlug}
127106
defaultBranch={defaultBranch}
128107
isReviewOpen={isReviewOpen}
129108
effectiveSource={effectiveSource}
@@ -216,7 +195,7 @@ export function ReviewPage({ task }: ReviewPageProps) {
216195
function BranchReviewPage({
217196
task,
218197
branch,
219-
repoInfo,
198+
repoSlug,
220199
defaultBranch,
221200
isReviewOpen,
222201
effectiveSource,
@@ -225,17 +204,14 @@ function BranchReviewPage({
225204
}: {
226205
task: Task;
227206
branch: string;
228-
repoInfo: { organization: string; repository: string } | undefined;
207+
repoSlug: string | null;
229208
defaultBranch: string | null;
230209
isReviewOpen: boolean;
231210
effectiveSource: ResolvedDiffSource;
232211
branchSourceAvailable: boolean;
233212
prSourceAvailable: boolean;
234213
}) {
235214
const taskId = task.id;
236-
const repoSlug = repoInfo
237-
? `${repoInfo.organization}/${repoInfo.repository}`
238-
: null;
239215

240216
const { data: files = EMPTY_BRANCH_FILES, isLoading } = useBranchChangedFiles(
241217
isReviewOpen ? repoSlug : null,
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { useDiffViewerStore } from "@features/code-editor/stores/diffViewerStore";
2+
import { useGitQueries } from "@features/git-interaction/hooks/useGitQueries";
3+
import { useLinkedBranchPrUrl } from "@features/git-interaction/hooks/useLinkedBranchPrUrl";
4+
import type { DiffStats } from "@features/git-interaction/utils/diffStats";
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+
prUrl: string | null;
15+
linkedBranch: string | null;
16+
defaultBranch: string | null;
17+
repoSlug: string | null;
18+
branchSourceAvailable: boolean;
19+
prSourceAvailable: boolean;
20+
diffStats: DiffStats;
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, diffStats } =
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+
prUrl,
58+
linkedBranch,
59+
defaultBranch,
60+
repoSlug,
61+
branchSourceAvailable,
62+
prSourceAvailable,
63+
diffStats,
64+
};
65+
}

apps/code/src/renderer/features/git-interaction/hooks/useGitQueries.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ export function useBranchChangedFiles(
180180
{ repo: repo as string, branch: branch as string },
181181
{
182182
enabled: !!repo && !!branch,
183-
staleTime: pollFast ? 10_000 : 30_000,
184-
refetchInterval: pollFast ? 10_000 : 30_000,
183+
staleTime: pollFast ? 10_000 : 5 * 60_000,
184+
refetchInterval: pollFast ? 10_000 : false,
185185
retry: 1,
186186
},
187187
),

0 commit comments

Comments
 (0)