Skip to content

Commit de71112

Browse files
authored
Fix checkbox state when toggling on large directory (#8516)
1 parent 5186f71 commit de71112

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

src/view/treeNodes/treeUtils.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as vscode from 'vscode';
7+
import { DirectoryTreeNode } from './directoryTreeNode';
78
import { FileChangeNode } from './fileChangeNode';
89
import { TreeNode } from './treeNode';
910

@@ -14,16 +15,26 @@ export namespace TreeUtils {
1415
const checkedNodes: FileChangeNode[] = [];
1516
const uncheckedNodes: FileChangeNode[] = [];
1617

18+
// The first item is the one the user actually clicked.
19+
// Only collect missing descendants if a directory was clicked directly.
20+
const firstNode = checkboxUpdates.items[0]?.[0];
21+
22+
const eventNodes = new Set<TreeNode>(checkboxUpdates.items.map(([node]) => node));
23+
1724
checkboxUpdates.items.forEach(checkboxUpdate => {
1825
const node = checkboxUpdate[0];
1926
const newState = checkboxUpdate[1];
2027

2128
if (node instanceof FileChangeNode) {
22-
if (newState == vscode.TreeItemCheckboxState.Checked) {
29+
if (newState === vscode.TreeItemCheckboxState.Checked) {
2330
checkedNodes.push(node);
2431
} else {
2532
uncheckedNodes.push(node);
2633
}
34+
} else if (firstNode instanceof DirectoryTreeNode && node === firstNode) {
35+
// VS Code auto-propagates to rendered children, but unrendered children
36+
// (due to virtual scrolling) won't be in the event. Collect those missing ones.
37+
collectMissingDescendants(firstNode, newState, checkedNodes, uncheckedNodes, eventNodes);
2738
}
2839

2940
node.updateFromCheckboxChanged(newState);
@@ -56,4 +67,32 @@ export namespace TreeUtils {
5667
prModel.markFiles(filenames, true, 'unviewed');
5768
}
5869
}
70+
71+
/**
72+
* Collect descendant FileChangeNodes that are NOT already in the event.
73+
* These are children VS Code missed because they weren't rendered (virtual scrolling).
74+
*/
75+
function collectMissingDescendants(
76+
dirNode: DirectoryTreeNode,
77+
newState: vscode.TreeItemCheckboxState,
78+
checkedNodes: FileChangeNode[],
79+
uncheckedNodes: FileChangeNode[],
80+
eventNodes: Set<TreeNode>
81+
): void {
82+
for (const child of dirNode._children) {
83+
if (eventNodes.has(child)) {
84+
continue;
85+
}
86+
if (child instanceof FileChangeNode) {
87+
if (newState === vscode.TreeItemCheckboxState.Checked) {
88+
checkedNodes.push(child);
89+
} else {
90+
uncheckedNodes.push(child);
91+
}
92+
child.updateFromCheckboxChanged(newState);
93+
} else if (child instanceof DirectoryTreeNode) {
94+
collectMissingDescendants(child, newState, checkedNodes, uncheckedNodes, eventNodes);
95+
}
96+
}
97+
}
5998
}

0 commit comments

Comments
 (0)