feat(vcs): select several repositories in the Git log Repository filter (#1107)

Clicking a repository in the Repository filter menu checks or unchecks it instead of replacing the selection, so the log shows any subset of the project's repositories; unchecking the last one shows all.
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-11-04 06:00:20 +08:00
1 джерело c347e331ab
коміт 19615e00b9
3 files changed
+23 -1

No files matched your search

+2 -1
Переглянути файл
@@ -59,6 +59,7 @@ import {
setLogBranches,
setLogFilters,
toggleCommitSelection,
toggleRepository,
updateLogOptions,
useGitLog,
} from "./logStore";
@@ -699,7 +700,7 @@ function FilterBar() {
repositories.map((repo) => ({
label: repoName(repo),
checked: filters.repositories?.includes(repo) ?? false,
run: () => setLogFilters({ repositories: [repo] }),
run: () => setLogFilters({ repositories: toggleRepository(filters.repositories, repo) }),
})),
),
onClear: () => setLogFilters({ repositories: [] }),
+15
Переглянути файл
@@ -26,6 +26,7 @@ import {
selectedCommits,
selectGitTab,
toggleCommitSelection,
toggleRepository,
useGitLog,
} from "../logStore";
import { useVcs } from "../store";
@@ -131,6 +132,20 @@ describe("multi-root Git log", () => {
off();
});
it("shows several repositories chosen one click at a time in the Repository filter", async () => {
log.mockImplementation(async (repo: string) => ({ status: "ok", data: [commit(repo)] }));
let repositories = toggleRepository(undefined, "/project/front");
repositories = toggleRepository(repositories, "/project/back");
expect(repositories).toEqual(["/project/front", "/project/back"]);
useGitLog.setState({ filters: { ...emptyFilters(), repositories } });
await reloadLog();
expect(new Set((useGitLog.getState().commits as RepoCommit[]).map((c) => c.repo))).toEqual(
new Set(["/project/front", "/project/back"]),
);
expect(toggleRepository(repositories, "/project/front")).toEqual(["/project/back"]);
expect(toggleRepository(["/project/back"], "/project/back")).toEqual([]);
});
it("groups identical local and remote names under distinct repository nodes", () => {
const roots = buildRepositoryBranchTree(
["front", "back"].map((name) => ({
+6
Переглянути файл
@@ -85,6 +85,12 @@ export const emptyFilters = (): LogFilters => ({
date: null,
});
/** The Repository filter after clicking `repo`: added when unchecked, removed when checked (none = all). */
export function toggleRepository(selected: readonly string[] | undefined, repo: string): string[] {
const cur = selected ?? [];
return cur.includes(repo) ? cur.filter((r) => r !== repo) : [...cur, repo];
}
/** Any filter other than the text field's toggles is set. */
export function hasFilters(f: LogFilters): boolean {
return !!(f.repositories?.length || f.branches.length || f.authors.length || f.text || f.path || f.date);