diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 5ccc58f7bf2..74306ee05d9 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1733,6 +1733,7 @@ export interface CommentThread { onDidChangeState: Event; onDidChangeCanReply: Event; isDisposed: boolean; + isTemplate: boolean; } /** diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index 7d28c674abf..10b7cd6b704 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -136,6 +136,10 @@ export class MainThreadCommentThread implements languages.CommentThread { this._onDidChangeState.fire(this._state); } + public get isTemplate(): boolean { + return this._isTemplate; + } + private readonly _onDidChangeState = new Emitter(); public onDidChangeState = this._onDidChangeState.event; @@ -146,7 +150,8 @@ export class MainThreadCommentThread implements languages.CommentThread { public threadId: string, public resource: string, private _range: T, - private _canReply: boolean + private _canReply: boolean, + private _isTemplate: boolean ) { this._isDisposed = false; } @@ -162,6 +167,7 @@ export class MainThreadCommentThread implements languages.CommentThread { if (modified('collapseState')) { this._collapsibleState = changes.collapseState; } if (modified('canReply')) { this.canReply = changes.canReply!; } if (modified('state')) { this.state = changes.state!; } + if (modified('isTemplate')) { this._isTemplate = changes.isTemplate!; } } dispose() { @@ -244,6 +250,7 @@ export class MainThreadCommentController { threadId: string, resource: UriComponents, range: IRange | ICellRange, + isTemplate: boolean ): languages.CommentThread { let thread = new MainThreadCommentThread( commentThreadHandle, @@ -252,7 +259,8 @@ export class MainThreadCommentController { threadId, URI.revive(resource).toString(), range, - true + true, + isTemplate ); this._threads.set(commentThreadHandle, thread); @@ -523,7 +531,8 @@ export class MainThreadComments extends Disposable implements MainThreadComments threadId: string, resource: UriComponents, range: IRange | ICellRange, - extensionId: ExtensionIdentifier + extensionId: ExtensionIdentifier, + isTemplate: boolean ): languages.CommentThread | undefined { let provider = this._commentControllers.get(handle); @@ -531,7 +540,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments return undefined; } - return provider.createCommentThread(extensionId.value, commentThreadHandle, threadId, resource, range); + return provider.createCommentThread(extensionId.value, commentThreadHandle, threadId, resource, range, isTemplate); } $updateCommentThread(handle: number, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 1e9997195f2..9fa08b4b6c3 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -122,13 +122,14 @@ export type CommentThreadChanges = Partial<{ collapseState: languages.CommentThreadCollapsibleState; canReply: boolean; state: languages.CommentThreadState; + isTemplate: boolean; }>; export interface MainThreadCommentsShape extends IDisposable { $registerCommentController(handle: number, id: string, label: string): void; $unregisterCommentController(handle: number): void; $updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void; - $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange, extensionId: ExtensionIdentifier): languages.CommentThread | undefined; + $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange, extensionId: ExtensionIdentifier, isTemplate: boolean): languages.CommentThread | undefined; $updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, changes: CommentThreadChanges): void; $deleteCommentThread(handle: number, commentThreadHandle: number): void; $updateCommentingRanges(handle: number): void; diff --git a/src/vs/workbench/api/common/extHostComments.ts b/src/vs/workbench/api/common/extHostComments.ts index 2940cff74f4..0a5314e916f 100644 --- a/src/vs/workbench/api/common/extHostComments.ts +++ b/src/vs/workbench/api/common/extHostComments.ts @@ -224,6 +224,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo collapsibleState: vscode.CommentThreadCollapsibleState; canReply: boolean; state: vscode.CommentThreadState; + isTemplate: boolean; }>; class ExtHostCommentThread implements vscode.CommentThread { @@ -362,7 +363,8 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo private _uri: vscode.Uri, private _range: vscode.Range, private _comments: vscode.Comment[], - public readonly extensionDescription: IExtensionDescription + public readonly extensionDescription: IExtensionDescription, + private _isTemplate: boolean ) { this._acceptInputDisposables.value = new DisposableStore(); @@ -376,7 +378,8 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo this._id, this._uri, extHostTypeConverter.Range.from(this._range), - extensionDescription.identifier + extensionDescription.identifier, + this._isTemplate ); this._localDisposables = []; @@ -421,12 +424,19 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo }; } + private updateIsTemplate() { + if (this._isTemplate) { + this._isTemplate = false; + this.modifications.isTemplate = false; + } + } @debounce(100) eventuallyUpdateCommentThread(): void { if (this._isDiposed) { return; } + this.updateIsTemplate(); if (!this._acceptInputDisposables.value) { this._acceptInputDisposables.value = new DisposableStore(); @@ -462,6 +472,9 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo if (modified('state')) { formattedModifications.state = convertToState(this._state); } + if (modified('isTemplate')) { + formattedModifications.isTemplate = this._isTemplate; + } this.modifications = {}; proxy.$updateCommentThread( @@ -582,18 +595,18 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo createCommentThread(resource: vscode.Uri, range: vscode.Range, comments: vscode.Comment[]): ExtHostCommentThread; createCommentThread(arg0: vscode.Uri | string, arg1: vscode.Uri | vscode.Range, arg2: vscode.Range | vscode.Comment[], arg3?: vscode.Comment[]): vscode.CommentThread { if (typeof arg0 === 'string') { - const commentThread = new ExtHostCommentThread(this.id, this.handle, arg0, arg1 as vscode.Uri, arg2 as vscode.Range, arg3 as vscode.Comment[], this._extension); + const commentThread = new ExtHostCommentThread(this.id, this.handle, arg0, arg1 as vscode.Uri, arg2 as vscode.Range, arg3 as vscode.Comment[], this._extension, false); this._threads.set(commentThread.handle, commentThread); return commentThread; } else { - const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, arg0 as vscode.Uri, arg1 as vscode.Range, arg2 as vscode.Comment[], this._extension); + const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, arg0 as vscode.Uri, arg1 as vscode.Range, arg2 as vscode.Comment[], this._extension, false); this._threads.set(commentThread.handle, commentThread); return commentThread; } } $createCommentThreadTemplate(uriComponents: UriComponents, range: IRange): ExtHostCommentThread { - const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), [], this._extension); + const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), [], this._extension, true); commentThread.collapsibleState = languages.CommentThreadCollapsibleState.Expanded; this._threads.set(commentThread.handle, commentThread); return commentThread; diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 5759d2f3783..df84a908765 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -185,7 +185,7 @@ export class CommentThreadWidget extends // If there are no existing comments, place focus on the text area. This must be done after show, which also moves focus. // if this._commentThread.comments is undefined, it doesn't finish initialization yet, so we don't focus the editor immediately. if (this._commentThread.canReply && this._commentReply) { - this._commentReply?.focusIfNeeded(); + this._commentReply.focusIfNeeded(); } this._bindCommentThreadListeners(); diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index c6a047179b0..c2b4beebee5 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -313,6 +313,11 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget this.show({ lineNumber: lineNumber, column: 1 }, 2); } + // If this is a new comment thread awaiting user input then we need to reveal it. + if (this._commentThread.canReply && this._commentThread.isTemplate && (!this._commentThread.comments || (this._commentThread.comments.length === 0))) { + this.reveal(); + } + this.bindCommentThreadListeners(); }