diff --git a/src/common/uri.ts b/src/common/uri.ts index 9aecf5f3e0..06a349e396 100644 --- a/src/common/uri.ts +++ b/src/common/uri.ts @@ -520,6 +520,34 @@ export function createPRNodeUri( }); } +export interface CommitsNodeUriParams { + prNumber: number; + commitsCount: number; +} + +export function createCommitsNodeUri(prNumber: number, commitsCount: number): vscode.Uri { + const params: CommitsNodeUriParams = { + prNumber, + commitsCount + }; + + return vscode.Uri.parse(`commitsnode:${prNumber}`).with({ + scheme: Schemes.CommitsNode, + query: JSON.stringify(params) + }); +} + +export function fromCommitsNodeUri(uri: vscode.Uri): CommitsNodeUriParams | undefined { + if (uri.scheme !== Schemes.CommitsNode) { + return undefined; + } + try { + return JSON.parse(uri.query) as CommitsNodeUriParams; + } catch (e) { + return undefined; + } +} + export interface NotificationUriParams { key: string; } @@ -726,7 +754,8 @@ export enum Schemes { Repo = 'repo', // New issue file for passing data Git = 'git', // File content from the git extension PRQuery = 'prquery', // PR query tree item - GitHubCommit = 'githubcommit' // file content from GitHub for a commit + GitHubCommit = 'githubcommit', // file content from GitHub for a commit + CommitsNode = 'commitsnode' // Commits tree node, for decorations } export function resolvePath(from: vscode.Uri, to: string) { diff --git a/src/extension.ts b/src/extension.ts index 1263e17588..457b22edd5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -42,6 +42,7 @@ import { NotificationsProvider } from './notifications/notificationsProvider'; import { ThemeWatcher } from './themeWatcher'; import { UriHandler } from './uriHandler'; import { CommentDecorationProvider } from './view/commentDecorationProvider'; +import { CommitsDecorationProvider } from './view/commitsDecorationProvider'; import { CompareChanges } from './view/compareChangesTreeDataProvider'; import { CreatePullRequestHelper } from './view/createPullRequestHelper'; import { FileTypeDecorationProvider } from './view/fileTypeDecorationProvider'; @@ -169,7 +170,7 @@ async function init( ); const treeDecorationProviders = new TreeDecorationProviders(reposManager); context.subscriptions.push(treeDecorationProviders); - treeDecorationProviders.registerProviders([new FileTypeDecorationProvider(), new CommentDecorationProvider(reposManager)]); + treeDecorationProviders.registerProviders([new FileTypeDecorationProvider(), new CommentDecorationProvider(reposManager), new CommitsDecorationProvider()]); const notificationsProvider = new NotificationsProvider(credentialStore, reposManager); context.subscriptions.push(notificationsProvider); diff --git a/src/view/commitsDecorationProvider.ts b/src/view/commitsDecorationProvider.ts new file mode 100644 index 0000000000..2e1294ccb7 --- /dev/null +++ b/src/view/commitsDecorationProvider.ts @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { TreeDecorationProvider } from './treeDecorationProviders'; +import { fromCommitsNodeUri, Schemes } from '../common/uri'; +import { FolderRepositoryManager } from '../github/folderRepositoryManager'; +import { PullRequestModel } from '../github/pullRequestModel'; + +export class CommitsDecorationProvider extends TreeDecorationProvider { + + constructor() { + super(); + } + + registerPullRequestPropertyChangedListeners(_folderManager: FolderRepositoryManager, _model: PullRequestModel): vscode.Disposable { + // No need to listen for changes since commit count doesn't change dynamically + return { dispose: () => { } }; + } + + provideFileDecoration( + uri: vscode.Uri, + _token: vscode.CancellationToken, + ): vscode.ProviderResult { + if (uri.scheme !== Schemes.CommitsNode) { + return undefined; + } + + const params = fromCommitsNodeUri(uri); + if (!params) { + return undefined; + } + + return { + badge: params.commitsCount.toString(), + tooltip: vscode.l10n.t('{0} commits', params.commitsCount) + }; + } + +} diff --git a/src/view/treeNodes/commitsCategoryNode.ts b/src/view/treeNodes/commitsCategoryNode.ts index 88adf29b8a..4ed44ed5f9 100644 --- a/src/view/treeNodes/commitsCategoryNode.ts +++ b/src/view/treeNodes/commitsCategoryNode.ts @@ -7,11 +7,13 @@ import * as vscode from 'vscode'; import { CommitNode } from './commitNode'; import { TreeNode, TreeNodeParent } from './treeNode'; import Logger, { PR_TREE } from '../../common/logger'; +import { createCommitsNodeUri } from '../../common/uri'; import { FolderRepositoryManager } from '../../github/folderRepositoryManager'; import { PullRequestModel } from '../../github/pullRequestModel'; export class CommitsNode extends TreeNode implements vscode.TreeItem { public collapsibleState: vscode.TreeItemCollapsibleState; + public resourceUri: vscode.Uri; private _folderRepoManager: FolderRepositoryManager; private _pr: PullRequestModel; @@ -25,6 +27,7 @@ export class CommitsNode extends TreeNode implements vscode.TreeItem { this._pr = pr; this._folderRepoManager = reposManager; this.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + this.resourceUri = createCommitsNodeUri(pr.number, pr.item.commits.length); this.childrenDisposables = []; this.childrenDisposables.push(this._pr.onDidChangeReviewThreads(() => {