feat(github): show every open pull request by default (#506)

The list opened filtered to pull requests assigned to the user, which is empty on most repositories. A search already used in the project is still restored.
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-31 08:04:13 +08:00
1 джерело 059fd8a69b
коміт c0c9553550
5 files changed
+29 -24

No files matched your search

+5 -5
Переглянути файл
@@ -1,7 +1,7 @@
/**
* IntelliJ's pull request search history (`GHPRListPersistentSearchHistory`), per project:
* the last 10 searches (newest first) and the last search used, which the list restores.
* On first run the list shows the Quick Filter "Assigned to you" (`initialSearch`).
* On first run the list shows the Quick Filter "Open" (`initialSearch`).
*/
import { useProject } from "@/platform/project";
import { DEFAULT_SEARCH, filterCount, normalizeSearch, sameSearch, type PrSearchValue } from "./model";
@@ -30,7 +30,7 @@ function save(key: string, value: unknown) {
/**
* `history` with `v` first (moved up when already there). Searches without filters and
* `defaultSearch` are not kept (the list passes its first-run filter, "Assigned to you").
* `defaultSearch` are not kept (the list passes its first-run filter, "Open").
*/
export function withSearch(
history: readonly PrSearchValue[],
@@ -63,7 +63,7 @@ export function saveLastSearch(v: PrSearchValue, root = projectRoot()) {
if (root) save(lastKey(root), v);
}
/** The list's search when the tool window opens: the last one, else "Assigned to you". */
export function initialSearch(currentUserLogin: string, root = projectRoot()): PrSearchValue {
return loadLastSearch(root) ?? { state: "OPEN", assignee: currentUserLogin };
/** The list's search when the tool window opens: the last one, else every open pull request. */
export function initialSearch(root = projectRoot()): PrSearchValue {
return loadLastSearch(root) ?? { state: "OPEN" };
}
+3 -3
Переглянути файл
@@ -45,15 +45,15 @@ function useApplySearch(login: string | undefined): (v: PrSearchValue) => void {
const recorder = useRef<SearchHistoryRecorder | null>(null);
useEffect(() => {
if (!login) return;
const defaultSearch = defaultFilter(login);
const defaultSearch = defaultFilter();
const r = createSearchHistoryRecorder({
defaultSearch,
saveLast: (v) => saveLastSearch(v),
remember: (v) => rememberSearch(v, undefined, defaultSearch),
});
recorder.current = r;
r.onChange(initialSearch(login));
void setListSearch(initialSearch(login));
r.onChange(initialSearch());
void setListSearch(initialSearch());
return () => {
r.dispose();
if (recorder.current === r) recorder.current = null;
+17 -12
Переглянути файл
@@ -224,7 +224,7 @@ describe("ListPanel", () => {
});
};
it("starts with Assigned to you and renders the rows", async () => {
it("starts with every open pull request and renders the rows", async () => {
pages = [
[
pr(7, {
@@ -244,7 +244,7 @@ describe("ListPanel", () => {
],
];
await mount();
expect(queries[0]).toBe("type:pr repo:org/app is:open assignee:me");
expect(queries[0]).toBe("type:pr repo:org/app is:open");
const rows = screen.getAllByRole("option");
expect(rows).toHaveLength(2);
const first = within(rows[0]!);
@@ -259,7 +259,7 @@ describe("ListPanel", () => {
expect(within(rows[1]!).getByText("MERGED")).toBeTruthy();
expect(within(rows[1]!).getByText(/^#8 · created /).textContent).not.toContain(", by");
expect(rows[1]!.querySelector("[data-unread]")).toBeNull();
expect(loadLastSearch()).toEqual({ state: "OPEN", assignee: "me" });
expect(loadLastSearch()).toEqual({ state: "OPEN" });
});
it("opens the context menu with IntelliJ's items on the clicked row", async () => {
@@ -303,28 +303,33 @@ describe("ListPanel", () => {
const field = screen.getByRole("textbox", { name: "Search pull requests" });
fireEvent.change(field, { target: { value: "crash" } });
await act(async () => fireEvent.keyDown(field, { key: "Enter" }));
expect(queries[1]).toBe("type:pr repo:org/app (crash) is:open assignee:me");
expect(loadSearchHistory()).toEqual([{ state: "OPEN", assignee: "me", searchQuery: "crash" }]);
expect(queries[1]).toBe("type:pr repo:org/app (crash) is:open");
expect(loadSearchHistory()).toEqual([{ state: "OPEN", searchQuery: "crash" }]);
});
it("resets a chip with its ✕ and with Delete, and shows the quick filter badge", async () => {
pages = [[], [], []];
it("resets a chip with its ✕ and shows the quick filter badge", async () => {
pages = [[], []];
await mount();
expect(document.querySelector("[data-badge]")).toBeTruthy();
const assignee = screen.getByText("me").closest("button")!;
await act(async () => fireEvent.keyDown(assignee, { key: "Delete" }));
expect(queries[1]).toBe("type:pr repo:org/app is:open");
await act(async () => fireEvent.click(screen.getByRole("button", { name: "Reset State" })));
expect(queries[2]).toBe("type:pr repo:org/app");
expect(queries[1]).toBe("type:pr repo:org/app");
expect(document.querySelector("[data-badge]")).toBeNull();
expect(screen.getByText("State")).toBeTruthy();
});
it("resets a chip with Delete", async () => {
pages = [[], []];
await mount();
const state = screen.getByText("Open").closest("button")!;
await act(async () => fireEvent.keyDown(state, { key: "Delete" }));
expect(queries[1]).toBe("type:pr repo:org/app");
});
it("chooses a chip value from its popup", async () => {
pages = [[], []];
await mount();
await act(async () => fireEvent.click(screen.getByText("Sort")));
await act(async () => fireEvent.click(screen.getByText("Least recently updated")));
expect(queries[1]).toBe("type:pr repo:org/app is:open assignee:me sort:updated-asc");
expect(queries[1]).toBe("type:pr repo:org/app is:open sort:updated-asc");
});
});
+2 -2
Переглянути файл
@@ -39,8 +39,8 @@ export function quickFilters(login: string): QuickFilter[] {
];
}
/** The list's first-run filter and the one the history never keeps: "Assigned to you". */
export const defaultFilter = (login: string): PrSearchValue => ({ state: "OPEN", assignee: login });
/** The list's first-run filter and the one the history never keeps: every open pull request. */
export const defaultFilter = (): PrSearchValue => ({ state: "OPEN" });
/** A quick filter is checked only when the search is exactly it. */
export const isQuickFilterSelected = (search: PrSearchValue, q: QuickFilter) => sameSearch(search, q.filter);
+2 -2
Переглянути файл
@@ -162,8 +162,8 @@ describe("tool window", () => {
expect(screen.getByRole("tab", { name: /app/ })).toBeTruthy();
expect(screen.getByRole("textbox", { name: "Search pull requests" })).toBeTruthy();
const body = JSON.parse(ghApi.mock.calls[0]![0].body!) as { variables: { query: string; pageSize: number } };
// First run: "Assigned to you".
expect(body.variables).toMatchObject({ query: "type:pr repo:org/app is:open assignee:me", pageSize: 50 });
// First run: every open pull request.
expect(body.variables).toMatchObject({ query: "type:pr repo:org/app is:open", pageSize: 50 });
await act(async () => openPullRequestTab(4));
expect(screen.getByRole("tab", { name: /#4/ })).toBeTruthy();
});