Skip to content

Commit 49d4f13

Browse files
committed
Add settings to control the icons used in Issues and PR tree views
Implements the feature request #6641. Both tree views support an icon mode of `author` (default), `state`, or `generic`. `author` follows the existing logic prior to this setting, where we attempt to fetch a rounded avatar. PRs fall back to a GitHub icon and Issues fall back to state-specific icon. `state` will always use a state-specific icon that matches the Issue/PR type and state. `generic` will always use the GitHub icon for a PR and an uncolored issues theme icon for Issues.
1 parent a5865ba commit 49d4f13

File tree

5 files changed

+94
-10
lines changed

5 files changed

+94
-10
lines changed

package.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,36 @@
659659
"default": false,
660660
"description": "%githubPullRequests.showPullRequestNumberInTree.description%"
661661
},
662+
"githubPullRequests.treeViewIconMode": {
663+
"type": "string",
664+
"enum": [
665+
"author",
666+
"state",
667+
"generic"
668+
],
669+
"enumDescriptions": [
670+
"%githubPullRequests.treeViewIconMode.author%",
671+
"%githubPullRequests.treeViewIconMode.state%",
672+
"%githubPullRequests.treeViewIconMode.generic%"
673+
],
674+
"default": "author",
675+
"description": "%githubPullRequests.treeViewIconMode.description%"
676+
},
677+
"githubIssues.treeViewIconMode": {
678+
"type": "string",
679+
"enum": [
680+
"author",
681+
"state",
682+
"generic"
683+
],
684+
"enumDescriptions": [
685+
"%githubIssues.treeViewIconMode.author%",
686+
"%githubIssues.treeViewIconMode.state%",
687+
"%githubIssues.treeViewIconMode.generic%"
688+
],
689+
"default": "author",
690+
"description": "%githubIssues.treeViewIconMode.description%"
691+
},
662692
"githubIssues.alwaysPromptForNewIssueRepo": {
663693
"type": "boolean",
664694
"default": false,

package.nls.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@
142142
"githubPullRequests.showPullRequestNumberInTree.description": "Shows the pull request number in the tree view.",
143143
"githubPullRequests.labelCreated.description": "Group of labels that you want to add to the pull request automatically. Labels that don't exist in the repository won't be added.",
144144
"githubPullRequests.labelCreated.label.description": "Each string element is value of label that you want to add",
145+
"githubPullRequests.treeViewIconMode.description": "Which icon to use in the pull request tree view",
146+
"githubPullRequests.treeViewIconMode.author": "Show the pull request author avatar",
147+
"githubPullRequests.treeViewIconMode.state": "Show the pull request type (draft or not) and state (open/closed/merged) as a colored icon",
148+
"githubPullRequests.treeViewIconMode.generic": "Show a GitHub icon",
149+
"githubIssues.treeViewIconMode.description": "Which icon to use in the issues tree view",
150+
"githubIssues.treeViewIconMode.author": "Show the issue author avatar",
151+
"githubIssues.treeViewIconMode.state": "Show the issue state (open/closed) as a colored icon",
152+
"githubIssues.treeViewIconMode.generic": "Show an issues icon regardless of state",
145153
"githubIssues.alwaysPromptForNewIssueRepo.description": "Enabling will always prompt which repository to create an issue in instead of basing off the current open file.",
146154
"view.github.pull.requests.name": "GitHub",
147155
"view.github.pull.request.name": "GitHub Pull Request",

src/common/settingKeys.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ export const EXPERIMENTAL_NOTIFICATIONS = 'experimental.notificationsView';
5858
export const EXPERIMENTAL_NOTIFICATIONS_PAGE_SIZE = 'experimental.notificationsViewPageSize';
5959
export const EXPERIMENTAL_NOTIFICATIONS_SCORE = 'experimental.notificationsScore';
6060

61+
export const TREE_VIEW_ICON_MODE = 'treeViewIconMode';
62+
export type TreeViewIconMode = 'author' | 'state' | 'generic';
63+
6164
// git
6265
export const GIT = 'git';
6366
export const PULL_BEFORE_CHECKOUT = 'pullBeforeCheckout';

src/issues/issuesView.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as path from 'path';
77
import * as vscode from 'vscode';
88
import { commands, contexts } from '../common/executeCommands';
9+
import { ISSUES_SETTINGS_NAMESPACE, TREE_VIEW_ICON_MODE, TreeViewIconMode } from '../common/settingKeys';
910
import { DataUri } from '../common/uri';
1011
import { groupBy } from '../common/utils';
1112
import { FolderRepositoryManager, ReposManagerState } from '../github/folderRepositoryManager';
@@ -59,6 +60,14 @@ export class IssuesTreeData
5960
this._onDidChangeTreeData.fire();
6061
}),
6162
);
63+
64+
context.subscriptions.push(
65+
vscode.workspace.onDidChangeConfiguration((e) => {
66+
if (e.affectsConfiguration(`${ISSUES_SETTINGS_NAMESPACE}.${TREE_VIEW_ICON_MODE}`)) {
67+
this._onDidChangeTreeData.fire();
68+
}
69+
}),
70+
);
6271
}
6372

6473
private getFolderRepoItem(element: FolderRepositoryManager): vscode.TreeItem {
@@ -77,10 +86,22 @@ export class IssuesTreeData
7786

7887
private async getIssueTreeItem(element: IssueItem): Promise<vscode.TreeItem> {
7988
const treeItem = new vscode.TreeItem(element.title, vscode.TreeItemCollapsibleState.None);
80-
treeItem.iconPath = (await DataUri.avatarCirclesAsImageDataUris(this.context, [element.author], 16, 16))[0] ??
81-
(element.isOpen
82-
? new vscode.ThemeIcon('issues', new vscode.ThemeColor('issues.open'))
83-
: new vscode.ThemeIcon('issue-closed', new vscode.ThemeColor('issues.closed')));
89+
90+
const iconMode = vscode.workspace.getConfiguration(ISSUES_SETTINGS_NAMESPACE).get<TreeViewIconMode>(TREE_VIEW_ICON_MODE, 'author');
91+
let iconPath: vscode.Uri | vscode.ThemeIcon = element.isOpen
92+
? new vscode.ThemeIcon('issues', new vscode.ThemeColor('issues.open'))
93+
: new vscode.ThemeIcon('issue-closed', new vscode.ThemeColor('issues.closed'));
94+
95+
if (iconMode === 'author') {
96+
const authorAvatar = (await DataUri.avatarCirclesAsImageDataUris(this.context, [element.author], 16, 16))[0];
97+
if (authorAvatar) {
98+
iconPath = authorAvatar;
99+
}
100+
} else if (iconMode === 'generic') {
101+
iconPath = new vscode.ThemeIcon('issues');
102+
}
103+
104+
treeItem.iconPath = iconPath;
84105

85106
treeItem.command = {
86107
command: 'issue.openDescription',

src/view/treeNodes/pullRequestNode.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { Repository } from '../../api/api';
88
import { getCommentingRanges } from '../../common/commentingRanges';
99
import { InMemFileChange, SlimFileChange } from '../../common/file';
1010
import Logger from '../../common/logger';
11-
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE, SHOW_PULL_REQUEST_NUMBER_IN_TREE } from '../../common/settingKeys';
11+
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE, SHOW_PULL_REQUEST_NUMBER_IN_TREE, TREE_VIEW_ICON_MODE, TreeViewIconMode } from '../../common/settingKeys';
1212
import { createPRNodeUri, DataUri, fromPRUri, Schemes } from '../../common/uri';
1313
import { FolderRepositoryManager } from '../../github/folderRepositoryManager';
14+
import { GithubItemStateEnum } from '../../github/interface';
1415
import { NotificationProvider } from '../../github/notifications';
1516
import { IResolvedPullRequestModel, PullRequestModel } from '../../github/pullRequestModel';
1617
import { InMemFileChangeModel, RemoteFileChangeModel } from '../fileChangeModel';
@@ -129,7 +130,7 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2
129130

130131
protected registerConfigurationChange() {
131132
this._register(vscode.workspace.onDidChangeConfiguration(e => {
132-
if (e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${SHOW_PULL_REQUEST_NUMBER_IN_TREE}`)) {
133+
if (e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${SHOW_PULL_REQUEST_NUMBER_IN_TREE}`) || e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${TREE_VIEW_ICON_MODE}`)) {
133134
this.refresh();
134135
}
135136
}));
@@ -262,7 +263,7 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2
262263
async getTreeItem(): Promise<vscode.TreeItem> {
263264
const currentBranchIsForThisPR = this.pullRequestModel.equals(this._folderReposManager.activePullRequest);
264265

265-
const { title, number, author, isDraft, html_url } = this.pullRequestModel;
266+
const { title, number, author, isDraft, html_url, state } = this.pullRequestModel;
266267
const labelTitle = this.pullRequestModel.title.length > 50 ? `${this.pullRequestModel.title.substring(0, 50)}...` : this.pullRequestModel.title;
267268
const { login } = author;
268269

@@ -279,14 +280,36 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2
279280
labelPrefix += `#${formattedPRNumber}: `;
280281
}
281282

282-
const label = `${labelPrefix}${isDraft ? '[DRAFT] ' : ''}${labelTitle}`;
283+
const iconMode = vscode.workspace.getConfiguration(PR_SETTINGS_NAMESPACE).get<TreeViewIconMode>(TREE_VIEW_ICON_MODE, 'author');
284+
285+
const label = `${labelPrefix}${isDraft && iconMode !== 'state' ? '[DRAFT] ' : ''}${labelTitle}`;
283286
const description = `by @${login}`;
284287
const command = {
285288
title: vscode.l10n.t('View Pull Request Description'),
286289
command: 'pr.openDescription',
287290
arguments: [this],
288291
};
289292

293+
let iconPath: vscode.Uri | vscode.ThemeIcon = new vscode.ThemeIcon('github');
294+
if (iconMode === 'author') {
295+
const authorAvatar = (await DataUri.avatarCirclesAsImageDataUris(this._folderReposManager.context, [this.pullRequestModel.author], 16, 16))[0];
296+
if (authorAvatar) {
297+
iconPath = authorAvatar;
298+
}
299+
} else if (iconMode === 'state') {
300+
iconPath = new vscode.ThemeIcon(
301+
state === GithubItemStateEnum.Closed ? 'git-pull-request-closed'
302+
: state === GithubItemStateEnum.Merged ? 'git-merge'
303+
: isDraft ? 'git-pull-request-draft'
304+
: 'git-pull-request',
305+
new vscode.ThemeColor(
306+
state === GithubItemStateEnum.Closed ? 'pullRequests.closed'
307+
: state === GithubItemStateEnum.Merged ? 'pullRequests.merged'
308+
: isDraft ? 'pullRequests.draft'
309+
: 'pullRequests.open'
310+
));
311+
}
312+
290313
return {
291314
label,
292315
id: `${this.parent instanceof TreeNode ? (this.parent.id ?? this.parent.label) : ''}${html_url}${this._isLocal ? this.pullRequestModel.localBranchName : ''}`, // unique id stable across checkout status
@@ -298,8 +321,7 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2
298321
(currentBranchIsForThisPR ? ':active' : ':nonactive') +
299322
(hasNotification ? ':notification' : '') +
300323
(((this.pullRequestModel.item.isRemoteHeadDeleted && !this._isLocal) || !this._folderReposManager.isPullRequestAssociatedWithOpenRepository(this.pullRequestModel)) ? '' : ':hasHeadRef'),
301-
iconPath: (await DataUri.avatarCirclesAsImageDataUris(this._folderReposManager.context, [this.pullRequestModel.author], 16, 16))[0]
302-
?? new vscode.ThemeIcon('github'),
324+
iconPath,
303325
accessibilityInformation: {
304326
label: `${isDraft ? 'Draft ' : ''}Pull request number ${formattedPRNumber}: ${title} by ${login}`
305327
},

0 commit comments

Comments
 (0)