Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 7dc619d

Browse files
authored
fix: sync active file after review filtering
Generated-By: PostHog Code Task-Id: f774fb55-18e5-4248-acb9-3f9bf3e7d3ee
1 parent b0fd582 commit 7dc619d

4 files changed

Lines changed: 86 additions & 34 deletions

File tree

packages/ui/src/features/code-review/commentFileFilter.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,52 @@ export function filterReviewItemsByFilePaths(
6262
return filteredItems;
6363
}
6464

65+
export function filterReviewItemsByViewedState(
66+
items: ReviewListItem[],
67+
currentSignatures: ReadonlyMap<string, string>,
68+
viewedRecord: Readonly<Record<string, string>>,
69+
): ReviewListItem[] {
70+
const filteredItems: ReviewListItem[] = [];
71+
let pendingSectionItems: ReviewListItem[] = [];
72+
73+
for (const item of items) {
74+
if (!item.filePaths) {
75+
pendingSectionItems = [item];
76+
continue;
77+
}
78+
79+
const signature = item.scrollKey
80+
? currentSignatures.get(item.scrollKey)
81+
: undefined;
82+
if (
83+
signature !== undefined &&
84+
item.scrollKey !== undefined &&
85+
viewedRecord[item.scrollKey] === signature
86+
) {
87+
continue;
88+
}
89+
90+
filteredItems.push(...pendingSectionItems, item);
91+
pendingSectionItems = [];
92+
}
93+
94+
return filteredItems;
95+
}
96+
97+
export function resolveVisibleActiveFilePath(
98+
items: ReviewListItem[],
99+
activeFilePath: string | null,
100+
): string | null {
101+
if (
102+
activeFilePath &&
103+
items.some((item) => item.filePaths?.includes(activeFilePath))
104+
) {
105+
return activeFilePath;
106+
}
107+
108+
return items.find((item) => item.scrollKey)?.scrollKey ?? null;
109+
}
110+
65111
export function deriveCommentFileFilterState({
66112
items,
67113
requestedFilter,

packages/ui/src/features/code-review/components/ReviewShell.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ import {
1616
import { VList, type VListHandle } from "virtua";
1717
import {
1818
deriveCommentFileFilterState,
19+
filterReviewItemsByViewedState,
1920
getEmptyReviewMessage,
2021
type ReviewListItem,
22+
resolveVisibleActiveFilePath,
2123
} from "../commentFileFilter";
2224
import {
2325
REVIEW_LIST_BUFFER_PX,
@@ -29,7 +31,6 @@ import { useReviewNavigationStore } from "../reviewNavigationStore";
2931
import type { ReviewShellProps } from "../reviewShellParts";
3032
import {
3133
buildItemIndex,
32-
filterReviewItemsByViewedState,
3334
findActiveScrollKey,
3435
findRenderedScrollAnchor,
3536
isFileViewed,
@@ -272,8 +273,28 @@ export function ReviewShell({
272273
const setActiveFilePath = useReviewNavigationStore(
273274
(s) => s.setActiveFilePath,
274275
);
276+
const activeFilePath = useReviewNavigationStore(
277+
(s) => s.activeFilePaths[taskId] ?? null,
278+
);
275279
const clearTask = useReviewNavigationStore((s) => s.clearTask);
276280

281+
useEffect(() => {
282+
if (!hideViewedFiles || !activeFilePath) return;
283+
const nextActiveFilePath = resolveVisibleActiveFilePath(
284+
filteredItems,
285+
activeFilePath,
286+
);
287+
if (nextActiveFilePath === activeFilePath) return;
288+
lastActiveRef.current = nextActiveFilePath;
289+
setActiveFilePath(taskId, nextActiveFilePath);
290+
}, [
291+
activeFilePath,
292+
filteredItems,
293+
hideViewedFiles,
294+
setActiveFilePath,
295+
taskId,
296+
]);
297+
277298
useEffect(() => {
278299
return () => {
279300
if (navigationFrameRef.current !== null) {

packages/ui/src/features/code-review/reviewShellParts.test.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ vi.mock("../../primitives/FileIcon", () => ({
1717
import {
1818
deriveCommentFileFilterState,
1919
filterReviewItemsByFilePaths,
20+
filterReviewItemsByViewedState,
2021
getCommentedFilePaths,
2122
type ReviewListItem,
23+
resolveVisibleActiveFilePath,
2224
} from "./commentFileFilter";
2325
import {
2426
DeferredDiffPlaceholder,
2527
DiffFileHeader,
26-
filterReviewItemsByViewedState,
2728
findActiveScrollKey,
2829
findRenderedScrollAnchor,
2930
} from "./reviewShellParts";
@@ -200,6 +201,22 @@ describe("commented file filtering", () => {
200201
).toEqual(["section:changes", "unstaged:b.ts"]);
201202
});
202203

204+
it("selects the first visible file when the active file is filtered out", () => {
205+
const items: ReviewListItem[] = [
206+
{ key: "section:changes", node: <span>Changes</span> },
207+
{
208+
key: "b.ts",
209+
scrollKey: "b.ts",
210+
filePaths: ["b.ts", "old-b.ts"],
211+
node: <span>B</span>,
212+
},
213+
];
214+
215+
expect(resolveVisibleActiveFilePath(items, "a.ts")).toBe("b.ts");
216+
expect(resolveVisibleActiveFilePath(items, "old-b.ts")).toBe("old-b.ts");
217+
expect(resolveVisibleActiveFilePath([], "a.ts")).toBeNull();
218+
});
219+
203220
it("collects paths for all and unresolved comment threads", () => {
204221
const commentedPaths = getCommentedFilePaths(
205222
new Map([

packages/ui/src/features/code-review/reviewShellParts.tsx

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -301,38 +301,6 @@ export function isFileViewed(
301301
return storedSig === currentSig;
302302
}
303303

304-
export function filterReviewItemsByViewedState(
305-
items: ReviewListItem[],
306-
currentSignatures: ReadonlyMap<string, string>,
307-
viewedRecord: Readonly<Record<string, string>>,
308-
): ReviewListItem[] {
309-
const filteredItems: ReviewListItem[] = [];
310-
let pendingSectionItems: ReviewListItem[] = [];
311-
312-
for (const item of items) {
313-
if (!item.filePaths) {
314-
pendingSectionItems = [item];
315-
continue;
316-
}
317-
318-
const signature = item.scrollKey
319-
? currentSignatures.get(item.scrollKey)
320-
: undefined;
321-
if (
322-
signature !== undefined &&
323-
item.scrollKey !== undefined &&
324-
isFileViewed(viewedRecord[item.scrollKey], signature)
325-
) {
326-
continue;
327-
}
328-
329-
filteredItems.push(...pendingSectionItems, item);
330-
pendingSectionItems = [];
331-
}
332-
333-
return filteredItems;
334-
}
335-
336304
function ViewedCheckbox({ viewedKey }: { viewedKey: string }) {
337305
const ctx = useReviewViewedContext();
338306
if (!ctx) return null;

0 commit comments

Comments
 (0)