diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index bb5e3134ec581..97394a88515c8 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1549,7 +1549,7 @@ export interface CommentThread { onDidChangeInput: Event; onDidChangeRange: Event; onDidChangeLabel: Event; - onDidChangeCollasibleState: Event; + onDidChangeCollapsibleState: Event; onDidChangeState: Event; onDidChangeCanReply: Event; isDisposed: boolean; diff --git a/src/vs/workbench/api/browser/mainThreadComments.ts b/src/vs/workbench/api/browser/mainThreadComments.ts index 906c30767f7ef..7184b593f3a3c 100644 --- a/src/vs/workbench/api/browser/mainThreadComments.ts +++ b/src/vs/workbench/api/browser/mainThreadComments.ts @@ -110,11 +110,11 @@ export class MainThreadCommentThread implements languages.CommentThread { set collapsibleState(newState: languages.CommentThreadCollapsibleState | undefined) { this._collapsibleState = newState; - this._onDidChangeCollasibleState.fire(this._collapsibleState); + this._onDidChangeCollapsibleState.fire(this._collapsibleState); } - private readonly _onDidChangeCollasibleState = new Emitter(); - public onDidChangeCollasibleState = this._onDidChangeCollasibleState.event; + private readonly _onDidChangeCollapsibleState = new Emitter(); + public onDidChangeCollapsibleState = this._onDidChangeCollapsibleState.event; private _isDisposed: boolean; @@ -172,7 +172,7 @@ export class MainThreadCommentThread implements languages.CommentThread { dispose() { this._isDisposed = true; - this._onDidChangeCollasibleState.dispose(); + this._onDidChangeCollapsibleState.dispose(); this._onDidChangeComments.dispose(); this._onDidChangeInput.dispose(); this._onDidChangeLabel.dispose(); diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts index 614402762c17b..73cdeb596fd4f 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadRangeDecorator.ts @@ -3,9 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IRange } from 'vs/editor/common/core/range'; +import { CommentThread, CommentThreadCollapsibleState } from 'vs/editor/common/languages'; import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { ICommentInfo, ICommentService } from 'vs/workbench/contrib/comments/browser/commentService'; @@ -34,6 +35,8 @@ export class CommentThreadRangeDecorator extends Disposable { private decorationIds: string[] = []; private activeDecorationIds: string[] = []; private editor: ICodeEditor | undefined; + private threadCollapseStateListeners: IDisposable[] = []; + private currentThreadCollapseStateListener: IDisposable | undefined; constructor(commentService: ICommentService) { super(); @@ -55,19 +58,34 @@ export class CommentThreadRangeDecorator extends Disposable { this.activeDecorationOptions = ModelDecorationOptions.createDynamic(activeDecorationOptions); this._register(commentService.onDidChangeCurrentCommentThread(thread => { - if (!this.editor) { - return; - } - const newDecoration: CommentThreadRangeDecoration[] = []; - if (thread) { - const range = thread.range; - if (!((range.startLineNumber === range.endLineNumber) && (range.startColumn === range.endColumn))) { + this.updateCurrent(thread); + })); + this._register(commentService.onDidUpdateCommentThreads(() => { + this.updateCurrent(undefined); + })); + } + + private updateCurrent(thread: CommentThread | undefined) { + if (!this.editor) { + return; + } + this.currentThreadCollapseStateListener?.dispose(); + const newDecoration: CommentThreadRangeDecoration[] = []; + if (thread) { + const range = thread.range; + if (!((range.startLineNumber === range.endLineNumber) && (range.startColumn === range.endColumn))) { + if (thread.collapsibleState === CommentThreadCollapsibleState.Expanded) { + this.currentThreadCollapseStateListener = thread.onDidChangeCollapsibleState(state => { + if (state === CommentThreadCollapsibleState.Collapsed) { + this.updateCurrent(undefined); + } + }); newDecoration.push(new CommentThreadRangeDecoration(range, this.activeDecorationOptions)); } } - this.activeDecorationIds = this.editor.deltaDecorations(this.activeDecorationIds, newDecoration); - newDecoration.forEach((decoration, index) => decoration.id = this.decorationIds[index]); - })); + } + this.activeDecorationIds = this.editor.deltaDecorations(this.activeDecorationIds, newDecoration); + newDecoration.forEach((decoration, index) => decoration.id = this.decorationIds[index]); } public update(editor: ICodeEditor, commentInfos: ICommentInfo[]) { @@ -75,6 +93,7 @@ export class CommentThreadRangeDecorator extends Disposable { if (!model) { return; } + this.threadCollapseStateListeners.forEach(disposable => disposable.dispose()); this.editor = editor; const commentThreadRangeDecorations: CommentThreadRangeDecoration[] = []; @@ -83,12 +102,22 @@ export class CommentThreadRangeDecorator extends Disposable { if (thread.isDisposed) { return; } + const range = thread.range; // We only want to show a range decoration when there's the range spans either multiple lines // or, when is spans multiple characters on the sample line if ((range.startLineNumber === range.endLineNumber) && (range.startColumn === range.endColumn)) { return; } + + this.threadCollapseStateListeners.push(thread.onDidChangeCollapsibleState(() => { + this.update(editor, commentInfos); + })); + + if (thread.collapsibleState === CommentThreadCollapsibleState.Collapsed) { + return; + } + commentThreadRangeDecorations.push(new CommentThreadRangeDecoration(range, this.decorationOptions)); }); } @@ -96,4 +125,10 @@ export class CommentThreadRangeDecorator extends Disposable { this.decorationIds = editor.deltaDecorations(this.decorationIds, commentThreadRangeDecorations); commentThreadRangeDecorations.forEach((decoration, index) => decoration.id = this.decorationIds[index]); } + + override dispose() { + this.threadCollapseStateListeners.forEach(disposable => disposable.dispose()); + this.currentThreadCollapseStateListener?.dispose(); + super.dispose(); + } } diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts index c9c6c21571107..32b36c7f42fed 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadZoneWidget.ts @@ -342,7 +342,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget } })); - this._commentThreadDisposables.push(this._commentThread.onDidChangeCollasibleState(state => { + this._commentThreadDisposables.push(this._commentThread.onDidChangeCollapsibleState(state => { if (state === languages.CommentThreadCollapsibleState.Expanded && !this._isExpanded) { const lineNumber = this._commentThread.range.startLineNumber;