Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/view/treeNodes/directoryTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class DirectoryTreeNode extends TreeNode implements vscode.TreeItem {
if (!child.allChildrenViewed()) {
return false;
}
} else if (child.checkboxState.state !== vscode.TreeItemCheckboxState.Checked) {
} else if (!child.checkboxState || child.checkboxState.state !== vscode.TreeItemCheckboxState.Checked) {
return false;
Comment on lines 124 to 128
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allChildrenViewed() now treats a file with checkboxState === undefined as “not viewed”, which causes directory nodes to still show an unchecked checkbox even when their children are intentionally non-checkable (e.g., files under commit nodes). In that scenario the directory checkbox becomes misleading and may not trigger any bulk mark/unmark behavior because there are no checkable descendants. Consider hiding the directory checkbox entirely (set this.checkboxState = undefined) when any descendant lacks checkboxState (or when there are zero checkable leaf nodes).

Copilot uses AI. Check for mistakes.
}
}
Expand Down
23 changes: 19 additions & 4 deletions src/view/treeNodes/fileChangeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class FileChangeNode extends TreeNode implements vscode.TreeItem {
public command: vscode.Command;
public opts: vscode.TextDocumentShowOptions;

public checkboxState: { state: vscode.TreeItemCheckboxState; tooltip?: string; accessibilityInformation: vscode.AccessibilityInformation };
public checkboxState?: { state: vscode.TreeItemCheckboxState; tooltip?: string; accessibilityInformation: vscode.AccessibilityInformation };

get status(): GitChangeType {
return this.changeModel.status;
Expand Down Expand Up @@ -155,13 +155,28 @@ export class FileChangeNode extends TreeNode implements vscode.TreeItem {
}
}

/**
* Check if this file node is under a commit node in the tree hierarchy.
* Files under commit nodes should not have checkboxes.
*/
private isUnderCommitNode(): boolean {
// If the file's sha is different from the PR's head sha, it's from an older commit
// and should not have a checkbox
return this.changeModel.sha !== undefined && this.changeModel.sha !== this.pullRequest.head?.sha;
Comment on lines +163 to +165
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isUnderCommitNode() doesn’t actually check whether the node is under a commit node; it only hides checkboxes when changeModel.sha !== pullRequest.head.sha. As a result, files shown under the current/head commit in the Commits section will still render “Mark as Viewed” checkboxes, which contradicts the PR goal of hiding checkboxes for files under commit nodes. Consider detecting commit ancestry via the parent chain (e.g., walk getParent() and check for the commit node’s contextValue === 'commit'), or pass an explicit showCheckbox/isCommitChild flag when constructing file nodes under CommitNode.

Suggested change
// If the file's sha is different from the PR's head sha, it's from an older commit
// and should not have a checkbox
return this.changeModel.sha !== undefined && this.changeModel.sha !== this.pullRequest.head?.sha;
let parent: TreeNodeParent | undefined = this.getParent();
while (parent) {
if (parent.contextValue === 'commit') {
return true;
}
parent = parent.getParent();
}
return false;

Copilot uses AI. Check for mistakes.
}

updateViewed(viewed: ViewedState) {
this.changeModel.updateViewed(viewed);
this.contextValue = `${Schemes.FileChange}:${GitChangeType[this.changeModel.status]}:${viewed === ViewedState.VIEWED ? 'viewed' : 'unviewed'
}`;
this.checkboxState = viewed === ViewedState.VIEWED ?
{ state: vscode.TreeItemCheckboxState.Checked, tooltip: vscode.l10n.t('Mark File as Unviewed'), accessibilityInformation: { label: vscode.l10n.t('Mark file {0} as unviewed', this.label ?? '') } } :
{ state: vscode.TreeItemCheckboxState.Unchecked, tooltip: vscode.l10n.t('Mark File as Viewed'), accessibilityInformation: { label: vscode.l10n.t('Mark file {0} as viewed', this.label ?? '') } };
// Don't show checkboxes for files under commit nodes
if (!this.isUnderCommitNode()) {
this.checkboxState = viewed === ViewedState.VIEWED ?
{ state: vscode.TreeItemCheckboxState.Checked, tooltip: vscode.l10n.t('Mark File as Unviewed'), accessibilityInformation: { label: vscode.l10n.t('Mark file {0} as unviewed', this.label ?? '') } } :
{ state: vscode.TreeItemCheckboxState.Unchecked, tooltip: vscode.l10n.t('Mark File as Viewed'), accessibilityInformation: { label: vscode.l10n.t('Mark file {0} as viewed', this.label ?? '') } };
} else {
this.checkboxState = undefined;
}
this.pullRequestManager.setFileViewedContext();
}

Expand Down
5 changes: 3 additions & 2 deletions src/view/treeNodes/treeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ export namespace TreeUtils {
continue;
}
if (!checkedNodes.includes(selected) && !uncheckedNodes.includes(selected)) {
if (selected.checkboxState.state === vscode.TreeItemCheckboxState.Unchecked) {
// Only process files that have checkboxes (files without checkboxState, like those under commits, are skipped)
if (selected.checkboxState?.state === vscode.TreeItemCheckboxState.Unchecked) {
checkedNodes.push(selected);
} else {
} else if (selected.checkboxState?.state === vscode.TreeItemCheckboxState.Checked) {
uncheckedNodes.push(selected);
}
}
Expand Down
Loading