feat: support multiple choice branches#45
feat: support multiple choice branches#45Chzxxuanzheng wants to merge 5 commits intoasispts:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds multi-branch selection support to the Git graph view by switching the branch selector to a checkbox-based dropdown and updating the loadCommits query to accept multiple branches.
Changes:
- Refactor dropdown UI: extract
AbstractDropdownand introduceCheckboxDropdownfor multi-select. - Update webview state + messaging from
currentBranch: string/branchName: stringtocurrentBranches: string[]/branchNames: string[]. - Update backend
loadCommitsquery to accept multiple branches and pass them through togit log; adjust related tests and types.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/backend/queries/loadCommits/list.test.ts | Updates query inputs to branchNames and adds a local SHOW_ALL sentinel for readability. |
| src/webview/main.ts | Switches branch selector to CheckboxDropdown, tracks currentBranches, and sends branchNames in loadCommits requests. |
| src/webview/global.d.ts | Updates webview persisted state typing to currentBranches. |
| src/webview/dropdown.ts | Introduces AbstractDropdown + new CheckboxDropdown implementation. |
| src/extension/messageHandler.ts | Passes branchNames through from webview to backend query. |
| src/backend/types/queries.types.ts | Updates loadCommits query request type to branchNames: string[]. |
| src/backend/queries/loadCommits.ts | Updates log retrieval to support multiple branches and the “show all” sentinel behavior. |
Comments suppressed due to low confidence (1)
src/backend/queries/loadCommits.ts:119
- In
loadCommits, the destructuring renamesbranchNamestobranchName, but the value is astring[]. This makes the code harder to read and easier to misuse (it’s later passed togetLogas an array). Rename the local variable tobranchNames(or similar) to match its type and meaning.
const {
branchNames: branchName,
maxCommits,
showRemoteBranches,
hard,
dateType,
showUncommittedChanges
} = input;
const [rawCommits, refData] = await Promise.all([
getLog(git, branchName, maxCommits + 1, showRemoteBranches, dateType),
getRefs(git, showRemoteBranches)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR adds multi-select branch filtering to the GitGraph webview by introducing a checkbox-based dropdown UI and updating the loadCommits query contract to accept multiple branch names.
Changes:
- Refactor dropdown implementation to support multi-select via
CheckboxDropdown(extracted from sharedAbstractDropdown). - Switch webview state/query flow from
currentBranch: string/branchNametocurrentBranches: string[]/branchNames. - Update and extend tests for the new branch-selection behavior and multi-branch commit querying.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/webview/setup.ts | Updates the test DOM scaffold for the commit table structure. |
| tests/webview/rendering.test.ts | Adds UI tests for multi-select branch dropdown behavior. |
| tests/backend/queries/loadCommits/list.test.ts | Updates query tests for branchNames and adds a multi-branch test. |
| src/webview/main.ts | Switches branch selection/state/querying to multi-select (branchNames). |
| src/webview/global.d.ts | Updates persisted webview state typing to currentBranches. |
| src/webview/dropdown.ts | Introduces AbstractDropdown + CheckboxDropdown for multi-select UI. |
| src/extension/messageHandler.ts | Forwards branchNames to backend loadCommits query. |
| src/backend/types/queries.types.ts | Updates loadCommits request type to branchNames: string[]. |
| src/backend/queries/loadCommits.ts | Implements multi-branch git log invocation logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (branches.length === 1 && branches[0] === "") { | ||
| args.push("--branches", "--tags"); | ||
| if (showRemoteBranches) args.push("--remotes"); | ||
| } else { | ||
| args.push(...branches); |
There was a problem hiding this comment.
@Chzxxuanzheng This is a valid concern. When someone passes ["", "main"], the input will go directly into the else branch. I think the best solution is to use a discriminated union so that the input is normalized before reaching the backend.
| (values, change) => { | ||
| // special handling show all | ||
|
|
||
| if (values.length === 0) { | ||
| // no selected, should add show all / current branch to selected | ||
| let defaultBranch: string; | ||
| if (this.config.showCurrentBranchByDefault && this.gitBranchHead) | ||
| defaultBranch = this.gitBranchHead; | ||
| else defaultBranch = SHOW_ALL; | ||
| this.branchDropdown.setSelected(defaultBranch); | ||
| values = [defaultBranch]; | ||
| } else if (change === SHOW_ALL && values.includes(SHOW_ALL)) { | ||
| // when selected show all, should clear other selections and keep show all selected | ||
| const options = [{ name: l10n.showAll, value: SHOW_ALL }]; | ||
| for (const branch of this.gitBranches) { | ||
| options.push({ | ||
| name: branch.startsWith("remotes/") ? branch.substring(8) : branch, | ||
| value: branch | ||
| }); | ||
| } | ||
| this.branchDropdown.setOptions(options, [SHOW_ALL]); | ||
| values = [SHOW_ALL]; | ||
| } else if (change !== SHOW_ALL && values.includes(SHOW_ALL)) { | ||
| // when selected another, should remove show all from selected | ||
| this.branchDropdown.setUnSelected(SHOW_ALL); | ||
| values = values.filter((v) => v !== SHOW_ALL); | ||
| } |
There was a problem hiding this comment.
I don't think main.ts should care about the component behavior
| if (!this.options.some((i) => i.value === value)) | ||
| throw new Error( | ||
| `unknown option: "${value}", available options: ${this.options.map((i) => `"${i.value}"`).join(", ")}` | ||
| ); |
There was a problem hiding this comment.
| if (!this.options.some((i) => i.value === value)) | |
| throw new Error( | |
| `unknown option: "${value}", available options: ${this.options.map((i) => `"${i.value}"`).join(", ")}` | |
| ); | |
| if (!this.options.some((i) => i.value === value)) { | |
| console.error(`CheckboxDropdown.setSelected: unknown option "${value}"`); | |
| return; | |
| } |
The exception will crash the UI.
There was a problem hiding this comment.
emm...I think adding a global error popup would be better. If we just use console, the user won't notice anything unless they open the DevTools. However, I'm worried that adding too much might make the PR go out of scope.
| if (!this.options.some((i) => i.value === value)) | ||
| throw new Error( | ||
| `unknown option: "${value}", available options: ${this.options.map((i) => `"${i.value}"`).join(", ")}` | ||
| ); |
There was a problem hiding this comment.
| if (!this.options.some((i) => i.value === value)) | |
| throw new Error( | |
| `unknown option: "${value}", available options: ${this.options.map((i) => `"${i.value}"`).join(", ")}` | |
| ); | |
| if (!this.options.some((i) => i.value === value)) { | |
| console.error(`CheckboxDropdown.setUnSelected: unknown option "${value}"`); | |
| return; | |
| } |
| expect(resultBranch1And2.commits.length).toBeGreaterThan(0); | ||
| expect(branch1And2Messages).toContain("commit on branch1"); | ||
| expect(branch1And2Messages).toContain("commit on branch2"); | ||
| expect(resultAllBranches.commits.length).toBeGreaterThanOrEqual( | ||
| resultBranch1And2.commits.length | ||
| ); | ||
| expect(resultBranch1And2.moreCommitsAvailable).toBe(false); |
There was a problem hiding this comment.
The test does not confirm that commits from unselected branches never appear.
| const SHOW_ALL = ""; | ||
|
|
There was a problem hiding this comment.
We now have two sources of truth to maintain. Just remove this one.
There was a problem hiding this comment.
Is there a share file that can be imported by webview and backend? I think replace "" with SHOW_ALL is a better
Add the supporting of multiple choice branches
Modification
AbstractDropdownclass fromDropdown, and add a new classCheckboxDropdownextendsAbstractDropdown.SHOW_ALLinstead of""to improve the readability.branchDropdowntoCheckboxDropdowninstance to support multiple choicecurrentBranch: stringtocurrentBranches: string[]to support multiple choiceIssue
The choice bar will overflow if the choice branches is too many. This because the old
.dropdownCurrentValuedon't consider the text overflow.The goal of the PR is add supporting about multiple choice branches, rather fix the bug of CSS. So I may open a PR, which goal is fix the CSS, later