From c4efd003093985773447836c7587b1c233f85459 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 22 May 2018 11:37:02 -0700 Subject: [PATCH] show diff view editor for outdated comments. --- extensions/git-extended/package.json | 4 + extensions/git-extended/src/commands.ts | 15 ++++ .../git-extended/src/review/reviewManager.ts | 9 +- src/vs/editor/common/modes.ts | 1 + src/vs/monaco.d.ts | 1 + src/vs/vscode.proposed.d.ts | 1 + src/vs/workbench/api/node/extHostComments.ts | 23 ++--- .../electron-browser/commentsPanel.ts | 84 ++++++++++++++----- 8 files changed, 107 insertions(+), 31 deletions(-) diff --git a/extensions/git-extended/package.json b/extensions/git-extended/package.json index 12d1ee7beb2..94dc7cd2625 100644 --- a/extensions/git-extended/package.json +++ b/extensions/git-extended/package.json @@ -84,6 +84,10 @@ "command": "pr.openDescription", "title": "View Pull Request Description" }, + { + "command": "pr.viewChanges", + "title": "View Changes" + }, { "command": "review.openFile", "title": "Open File", diff --git a/extensions/git-extended/src/commands.ts b/extensions/git-extended/src/commands.ts index 29618fe10aa..82ea406934e 100644 --- a/extensions/git-extended/src/commands.ts +++ b/extensions/git-extended/src/commands.ts @@ -9,6 +9,7 @@ import { PullRequestModel } from './common/models/pullRequestModel'; import { FileChangeTreeItem } from './common/treeItems'; import { ReviewManager } from './review/reviewManager'; import { PullRequestOverviewPanel } from './common/pullRequestOverview'; +import { fromGitUri, toGitUri } from './common/uri'; export function registerCommands(context: vscode.ExtensionContext) { // initialize resources @@ -50,4 +51,18 @@ export function registerCommands(context: vscode.ExtensionContext) { // Create and show a new webview PullRequestOverviewPanel.createOrShow(context.extensionPath, pr); })); + + context.subscriptions.push(vscode.commands.registerCommand('pr.viewChanges', async (fileChange: FileChangeTreeItem) => { + // Show the file change in a diff view. + let { path, ref, commit } = fromGitUri(fileChange.filePath); + let previousCommit = `${commit}^`; + let previousFileUri = fileChange.filePath.with({ + query: JSON.stringify({ + path: path, + ref: ref, + commit: previousCommit + }) + }); + return vscode.commands.executeCommand('vscode.diff', previousFileUri, fileChange.filePath, `${fileChange.fileName} from ${commit}`); + })); } diff --git a/extensions/git-extended/src/review/reviewManager.ts b/extensions/git-extended/src/review/reviewManager.ts index bfdff5bd652..e38a0139e67 100644 --- a/extensions/git-extended/src/review/reviewManager.ts +++ b/extensions/git-extended/src/review/reviewManager.ts @@ -397,7 +397,14 @@ export class ReviewManager implements vscode.DecorationProvider { commentId: comment.id, body: new vscode.MarkdownString(comment.body), userName: comment.user.login, - gravatar: comment.user.avatar_url + gravatar: comment.user.avatar_url, + command: { + title: 'View Changes', + command: 'pr.viewChanges', + arguments: [ + fileChange + ] + } }; }), collapsibleState: collapsibleState diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 5dff5d36ee1..980fabbd20c 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -985,6 +985,7 @@ export interface Comment { readonly body: IMarkdownString; readonly userName: string; readonly gravatar: string; + readonly command?: Command; } export interface CommentThreadChangedEvent { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index b820ddf2526..793a8c6ba34 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -5180,6 +5180,7 @@ declare namespace monaco.languages { readonly body: IMarkdownString; readonly userName: string; readonly gravatar: string; + readonly command?: Command; } export interface CommentThreadChangedEvent { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 2371001c5ee..67104fa6e17 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -554,6 +554,7 @@ declare module 'vscode' { body: MarkdownString; userName: string; gravatar: string; + command?: Command; } export interface CommentThreadChangedEvent { diff --git a/src/vs/workbench/api/node/extHostComments.ts b/src/vs/workbench/api/node/extHostComments.ts index 802bd12caa7..a6a85ba54e0 100644 --- a/src/vs/workbench/api/node/extHostComments.ts +++ b/src/vs/workbench/api/node/extHostComments.ts @@ -75,7 +75,7 @@ export class ExtHostComments implements ExtHostCommentsShape { return asWinJsPromise(token => { let provider = this._documentProviders.get(handle); return provider.createNewCommentThread(data.document, ran, text, token); - }).then(commentThread => commentThread ? convertToCommentThread(commentThread) : null); + }).then(commentThread => commentThread ? convertToCommentThread(commentThread, this._commandsConverter) : null); } $replyToCommentThread(handle: number, uri: UriComponents, range: IRange, thread: modes.CommentThread, text: string): TPromise { @@ -89,7 +89,7 @@ export class ExtHostComments implements ExtHostCommentsShape { return asWinJsPromise(token => { let provider = this._documentProviders.get(handle); return provider.replyToCommentThread(data.document, ran, convertFromCommentThread(thread), text, token); - }).then(commentThread => commentThread ? convertToCommentThread(commentThread) : null); + }).then(commentThread => commentThread ? convertToCommentThread(commentThread, this._commandsConverter) : null); } $provideDocumentComments(handle: number, uri: UriComponents): TPromise { @@ -114,7 +114,7 @@ export class ExtHostComments implements ExtHostCommentsShape { return asWinJsPromise(token => { return provider.provideWorkspaceComments(token); }).then(comments => - comments.map(x => convertToCommentThread(x) + comments.map(x => convertToCommentThread(x, this._commandsConverter) )); } @@ -123,9 +123,9 @@ export class ExtHostComments implements ExtHostCommentsShape { this._proxy.$onDidCommentThreadsChange(handle, { owner: handle, - changed: event.changed.map(x => convertToCommentThread(x)), - added: event.added.map(x => convertToCommentThread(x)), - removed: event.removed.map(x => convertToCommentThread(x)) + changed: event.changed.map(x => convertToCommentThread(x, this._commandsConverter)), + added: event.added.map(x => convertToCommentThread(x, this._commandsConverter)), + removed: event.removed.map(x => convertToCommentThread(x, this._commandsConverter)) }); }); } @@ -134,17 +134,17 @@ export class ExtHostComments implements ExtHostCommentsShape { function convertCommentInfo(owner: number, vscodeCommentInfo: vscode.CommentInfo, commandsConverter: CommandsConverter): modes.CommentInfo { return { owner: owner, - threads: vscodeCommentInfo.threads.map(x => convertToCommentThread(x)), + threads: vscodeCommentInfo.threads.map(x => convertToCommentThread(x, commandsConverter)), commentingRanges: vscodeCommentInfo.commentingRanges ? vscodeCommentInfo.commentingRanges.map(range => extHostTypeConverter.Range.from(range)) : [] }; } -function convertToCommentThread(vscodeCommentThread: vscode.CommentThread): modes.CommentThread { +function convertToCommentThread(vscodeCommentThread: vscode.CommentThread, commandsConverter: CommandsConverter): modes.CommentThread { return { threadId: vscodeCommentThread.threadId, resource: vscodeCommentThread.resource.toString(), range: extHostTypeConverter.Range.from(vscodeCommentThread.range), - comments: vscodeCommentThread.comments.map(convertToComment), + comments: vscodeCommentThread.comments.map(comment => convertToComment(comment, commandsConverter)), collapsibleState: vscodeCommentThread.collapsibleState }; } @@ -168,11 +168,12 @@ function convertFromComment(comment: modes.Comment): vscode.Comment { }; } -function convertToComment(vscodeComment: vscode.Comment): modes.Comment { +function convertToComment(vscodeComment: vscode.Comment, commandsConverter: CommandsConverter): modes.Comment { return { commentId: vscodeComment.commentId, body: extHostTypeConverter.MarkdownString.from(vscodeComment.body), userName: vscodeComment.userName, - gravatar: vscodeComment.gravatar + gravatar: vscodeComment.gravatar, + command: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : null }; } diff --git a/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts b/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts index 1814173ed34..06b56fae144 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts @@ -9,7 +9,7 @@ import { IAction } from 'vs/base/common/actions'; import { debounceEvent } from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { CollapseAllAction, DefaultAccessibilityProvider, DefaultController, DefaultDragAndDrop } from 'vs/base/parts/tree/browser/treeDefaults'; -import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { CommentThread, CommentThreadChangedEvent } from 'vs/editor/common/modes'; import { localize } from 'vs/nls'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -23,6 +23,10 @@ import { CommentsDataFilter, CommentsDataSource, CommentsModelRenderer } from 'v import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { ICommentService } from 'vs/workbench/services/comments/electron-browser/commentService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { ICommandService } from '../../../../platform/commands/common/commands'; +import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { TextDiffEditor } from '../../../browser/parts/editor/textDiffEditor'; +import { DiffEditorWidget } from '../../../../editor/browser/widget/diffEditorWidget'; export const COMMENTS_PANEL_ID = 'workbench.panel.comments'; export const COMMENTS_PANEL_TITLE = 'Comments'; @@ -39,6 +43,7 @@ export class CommentsPanel extends Panel { @IInstantiationService private instantiationService: IInstantiationService, @ICommentService private commentService: ICommentService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @ICommandService private commandService: ICommandService, @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, @IActivityService private activityService: IActivityService @@ -151,24 +156,65 @@ export class CommentsPanel extends Panel { } }); }); - Promise.all([this.editorService.openEditor({ - resource: element.resource, - options: { - pinned: pinned, - preserveFocus: preserveFocus, - selection: range - } - }, sideBySide), setCommentsForFile]).then(vals => { - let editor = vals[0]; - const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].threadId : element.threadId; - const commentToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].comment.commentId : element.comment.commentId; - const control = editor.getControl(); - if (threadToReveal && isCodeEditor(control)) { - const controller = ReviewController.get(control); - controller.revealCommentThread(threadToReveal, commentToReveal); - } - setCommentsForFile = null; - }); + + const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].threadId : element.threadId; + const commentToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].comment : element.comment; + + if (commentToReveal.command) { + Promise.all([ + this.commandService.executeCommand(commentToReveal.command.id, ...commentToReveal.command.arguments), + setCommentsForFile + ]).then(_ => { + let activeInput = this.editorService.getActiveEditorInput(); + if (activeInput && activeInput instanceof DiffEditorInput) { + let activeEditor = this.editorService.getActiveEditor(); + const control = activeEditor.getControl() as DiffEditorWidget; + const originalEditorControl = control.getOriginalEditor(); + const modifiedEditorControl = control.getModifiedEditor(); + + let controller; + if (activeInput.originalInput.getResource().toString() === element.resource.toString()) { + controller = ReviewController.get(originalEditorControl); + } else if (activeInput.modifiedInput.getResource().toString() === element.resource.toString()) { + controller = ReviewController.get(modifiedEditorControl); + } + + if (controller) { + controller.revealCommentThread(threadToReveal, commentToReveal.commentId); + } + } else { + let currentActiveResource = activeInput ? activeInput.getResource() : void 0; + if (currentActiveResource && currentActiveResource.toString() === element.resource.toString()) { + const control = this.editorService.getActiveEditor().getControl(); + if (threadToReveal && isCodeEditor(control)) { + const controller = ReviewController.get(control); + controller.revealCommentThread(threadToReveal, commentToReveal.commentId); + } + } + } + + return true; + }); + } else { + Promise.all([this.editorService.openEditor({ + resource: element.resource, + options: { + pinned: pinned, + preserveFocus: preserveFocus, + selection: range + } + }, sideBySide), setCommentsForFile]).then(vals => { + let editor = vals[0]; + const control = editor.getControl(); + if (threadToReveal && isCodeEditor(control)) { + const controller = ReviewController.get(control); + console.log(commentToReveal.command); + controller.revealCommentThread(threadToReveal, commentToReveal.commentId); + } + setCommentsForFile = null; + }); + } + return true; } -- GitLab