Skip to content

Add settings to control the icons used in Issues and PR tree views #6798

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,36 @@
"default": false,
"description": "%githubPullRequests.showPullRequestNumberInTree.description%"
},
"githubPullRequests.treeViewIconMode": {
"type": "string",
"enum": [
"author",
"state",
"generic"
],
"enumDescriptions": [
"%githubPullRequests.treeViewIconMode.author%",
"%githubPullRequests.treeViewIconMode.state%",
"%githubPullRequests.treeViewIconMode.generic%"
],
"default": "author",
"description": "%githubPullRequests.treeViewIconMode.description%"
},
"githubIssues.treeViewIconMode": {
"type": "string",
"enum": [
"author",
"state",
"generic"
],
"enumDescriptions": [
"%githubIssues.treeViewIconMode.author%",
"%githubIssues.treeViewIconMode.state%",
"%githubIssues.treeViewIconMode.generic%"
],
"default": "author",
"description": "%githubIssues.treeViewIconMode.description%"
},
"githubIssues.alwaysPromptForNewIssueRepo": {
"type": "boolean",
"default": false,
Expand Down
8 changes: 8 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@
"githubPullRequests.showPullRequestNumberInTree.description": "Shows the pull request number in the tree view.",
"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.",
"githubPullRequests.labelCreated.label.description": "Each string element is value of label that you want to add",
"githubPullRequests.treeViewIconMode.description": "Which icon to use in the pull request tree view",
"githubPullRequests.treeViewIconMode.author": "Show the pull request author avatar",
"githubPullRequests.treeViewIconMode.state": "Show the pull request type (draft or not) and state (open/closed/merged) as a colored icon",
"githubPullRequests.treeViewIconMode.generic": "Show a GitHub icon",
"githubIssues.treeViewIconMode.description": "Which icon to use in the issues tree view",
"githubIssues.treeViewIconMode.author": "Show the issue author avatar",
"githubIssues.treeViewIconMode.state": "Show the issue state (open/closed) as a colored icon",
"githubIssues.treeViewIconMode.generic": "Show an issues icon regardless of state",
"githubIssues.alwaysPromptForNewIssueRepo.description": "Enabling will always prompt which repository to create an issue in instead of basing off the current open file.",
"view.github.pull.requests.name": "GitHub",
"view.github.pull.request.name": "GitHub Pull Request",
Expand Down
3 changes: 3 additions & 0 deletions src/common/settingKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export const EXPERIMENTAL_NOTIFICATIONS = 'experimental.notificationsView';
export const EXPERIMENTAL_NOTIFICATIONS_PAGE_SIZE = 'experimental.notificationsViewPageSize';
export const EXPERIMENTAL_NOTIFICATIONS_SCORE = 'experimental.notificationsScore';

export const TREE_VIEW_ICON_MODE = 'treeViewIconMode';
export type TreeViewIconMode = 'author' | 'state' | 'generic';

// git
export const GIT = 'git';
export const PULL_BEFORE_CHECKOUT = 'pullBeforeCheckout';
Expand Down
29 changes: 25 additions & 4 deletions src/issues/issuesView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import * as path from 'path';
import * as vscode from 'vscode';
import { commands, contexts } from '../common/executeCommands';
import { ISSUES_SETTINGS_NAMESPACE, TREE_VIEW_ICON_MODE, TreeViewIconMode } from '../common/settingKeys';
import { DataUri } from '../common/uri';
import { groupBy } from '../common/utils';
import { FolderRepositoryManager, ReposManagerState } from '../github/folderRepositoryManager';
Expand Down Expand Up @@ -59,6 +60,14 @@ export class IssuesTreeData
this._onDidChangeTreeData.fire();
}),
);

context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration(`${ISSUES_SETTINGS_NAMESPACE}.${TREE_VIEW_ICON_MODE}`)) {
this._onDidChangeTreeData.fire();
}
}),
);
}

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

private async getIssueTreeItem(element: IssueItem): Promise<vscode.TreeItem> {
const treeItem = new vscode.TreeItem(element.title, vscode.TreeItemCollapsibleState.None);
treeItem.iconPath = (await DataUri.avatarCirclesAsImageDataUris(this.context, [element.author], 16, 16))[0] ??
(element.isOpen
? new vscode.ThemeIcon('issues', new vscode.ThemeColor('issues.open'))
: new vscode.ThemeIcon('issue-closed', new vscode.ThemeColor('issues.closed')));

const iconMode = vscode.workspace.getConfiguration(ISSUES_SETTINGS_NAMESPACE).get<TreeViewIconMode>(TREE_VIEW_ICON_MODE, 'author');
let iconPath: vscode.Uri | vscode.ThemeIcon = element.isOpen
? new vscode.ThemeIcon('issues', new vscode.ThemeColor('issues.open'))
: new vscode.ThemeIcon('issue-closed', new vscode.ThemeColor('issues.closed'));

if (iconMode === 'author') {
const authorAvatar = (await DataUri.avatarCirclesAsImageDataUris(this.context, [element.author], 16, 16))[0];
if (authorAvatar) {
iconPath = authorAvatar;
}
} else if (iconMode === 'generic') {
iconPath = new vscode.ThemeIcon('issues');
}

treeItem.iconPath = iconPath;

treeItem.command = {
command: 'issue.openDescription',
Expand Down
34 changes: 28 additions & 6 deletions src/view/treeNodes/pullRequestNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import { Repository } from '../../api/api';
import { getCommentingRanges } from '../../common/commentingRanges';
import { InMemFileChange, SlimFileChange } from '../../common/file';
import Logger from '../../common/logger';
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE, SHOW_PULL_REQUEST_NUMBER_IN_TREE } from '../../common/settingKeys';
import { FILE_LIST_LAYOUT, PR_SETTINGS_NAMESPACE, SHOW_PULL_REQUEST_NUMBER_IN_TREE, TREE_VIEW_ICON_MODE, TreeViewIconMode } from '../../common/settingKeys';
import { createPRNodeUri, DataUri, fromPRUri, Schemes } from '../../common/uri';
import { FolderRepositoryManager } from '../../github/folderRepositoryManager';
import { GithubItemStateEnum } from '../../github/interface';
import { NotificationProvider } from '../../github/notifications';
import { IResolvedPullRequestModel, PullRequestModel } from '../../github/pullRequestModel';
import { InMemFileChangeModel, RemoteFileChangeModel } from '../fileChangeModel';
Expand Down Expand Up @@ -129,7 +130,7 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2

protected registerConfigurationChange() {
this._register(vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${SHOW_PULL_REQUEST_NUMBER_IN_TREE}`)) {
if (e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${SHOW_PULL_REQUEST_NUMBER_IN_TREE}`) || e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${TREE_VIEW_ICON_MODE}`)) {
this.refresh();
}
}));
Expand Down Expand Up @@ -262,7 +263,7 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2
async getTreeItem(): Promise<vscode.TreeItem> {
const currentBranchIsForThisPR = this.pullRequestModel.equals(this._folderReposManager.activePullRequest);

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

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

const label = `${labelPrefix}${isDraft ? '[DRAFT] ' : ''}${labelTitle}`;
const iconMode = vscode.workspace.getConfiguration(PR_SETTINGS_NAMESPACE).get<TreeViewIconMode>(TREE_VIEW_ICON_MODE, 'author');

const label = `${labelPrefix}${isDraft && iconMode !== 'state' ? '[DRAFT] ' : ''}${labelTitle}`;
const description = `by @${login}`;
const command = {
title: vscode.l10n.t('View Pull Request Description'),
command: 'pr.openDescription',
arguments: [this],
};

let iconPath: vscode.Uri | vscode.ThemeIcon = new vscode.ThemeIcon('github');
if (iconMode === 'author') {
const authorAvatar = (await DataUri.avatarCirclesAsImageDataUris(this._folderReposManager.context, [this.pullRequestModel.author], 16, 16))[0];
if (authorAvatar) {
iconPath = authorAvatar;
}
} else if (iconMode === 'state') {
iconPath = new vscode.ThemeIcon(
state === GithubItemStateEnum.Closed ? 'git-pull-request-closed'
: state === GithubItemStateEnum.Merged ? 'git-merge'
: isDraft ? 'git-pull-request-draft'
: 'git-pull-request',
new vscode.ThemeColor(
state === GithubItemStateEnum.Closed ? 'pullRequests.closed'
: state === GithubItemStateEnum.Merged ? 'pullRequests.merged'
: isDraft ? 'pullRequests.draft'
: 'pullRequests.open'
));
}

return {
label,
id: `${this.parent instanceof TreeNode ? (this.parent.id ?? this.parent.label) : ''}${html_url}${this._isLocal ? this.pullRequestModel.localBranchName : ''}`, // unique id stable across checkout status
Expand All @@ -298,8 +321,7 @@ export class PRNode extends TreeNode implements vscode.CommentingRangeProvider2
(currentBranchIsForThisPR ? ':active' : ':nonactive') +
(hasNotification ? ':notification' : '') +
(((this.pullRequestModel.item.isRemoteHeadDeleted && !this._isLocal) || !this._folderReposManager.isPullRequestAssociatedWithOpenRepository(this.pullRequestModel)) ? '' : ':hasHeadRef'),
iconPath: (await DataUri.avatarCirclesAsImageDataUris(this._folderReposManager.context, [this.pullRequestModel.author], 16, 16))[0]
?? new vscode.ThemeIcon('github'),
iconPath,
accessibilityInformation: {
label: `${isDraft ? 'Draft ' : ''}Pull request number ${formattedPRNumber}: ${title} by ${login}`
},
Expand Down