Skip to content

Commit

Permalink
Fix rapid focus flickering (#212153)
Browse files Browse the repository at this point in the history
Fixes #211831
  • Loading branch information
alexr00 authored May 7, 2024
1 parent f8d3bd3 commit a812bde
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 72 deletions.
9 changes: 8 additions & 1 deletion src/vs/editor/common/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,13 @@ export interface CommentThread<T = IRange> {
isTemplate: boolean;
}

/**
* @internal
*/
export interface AddedCommentThread<T = IRange> extends CommentThread<T> {
editorId?: string;
}

/**
* @internal
*/
Expand Down Expand Up @@ -1971,7 +1978,7 @@ export interface CommentThreadChangedEvent<T> {
/**
* Added comment threads.
*/
readonly added: CommentThread<T>[];
readonly added: AddedCommentThread<T>[];

/**
* Removed comment threads.
Expand Down
18 changes: 11 additions & 7 deletions src/vs/workbench/api/browser/mainThreadComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ export class MainThreadCommentThread<T> implements languages.CommentThread<T> {
public resource: string,
private _range: T | undefined,
private _canReply: boolean,
private _isTemplate: boolean
private _isTemplate: boolean,
public editorId?: string
) {
this._isDisposed = false;
if (_isTemplate) {
Expand Down Expand Up @@ -291,7 +292,8 @@ export class MainThreadCommentController implements ICommentController {
threadId: string,
resource: UriComponents,
range: IRange | ICellRange | undefined,
isTemplate: boolean
isTemplate: boolean,
editorId?: string
): languages.CommentThread<IRange | ICellRange> {
const thread = new MainThreadCommentThread(
commentThreadHandle,
Expand All @@ -301,7 +303,8 @@ export class MainThreadCommentController implements ICommentController {
URI.revive(resource).toString(),
range,
true,
isTemplate
isTemplate,
editorId
);

this._threads.set(commentThreadHandle, thread);
Expand Down Expand Up @@ -479,8 +482,8 @@ export class MainThreadCommentController implements ICommentController {
return ret;
}

createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined): Promise<void> {
return this._proxy.$createCommentThreadTemplate(this.handle, resource, range);
createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined, editorId?: string): Promise<void> {
return this._proxy.$createCommentThreadTemplate(this.handle, resource, range, editorId);
}

async updateCommentThreadTemplate(threadHandle: number, range: IRange) {
Expand Down Expand Up @@ -580,15 +583,16 @@ export class MainThreadComments extends Disposable implements MainThreadComments
resource: UriComponents,
range: IRange | ICellRange | undefined,
extensionId: ExtensionIdentifier,
isTemplate: boolean
isTemplate: boolean,
editorId?: string
): languages.CommentThread<IRange | ICellRange> | undefined {
const provider = this._commentControllers.get(handle);

if (!provider) {
return undefined;
}

return provider.createCommentThread(extensionId.value, commentThreadHandle, threadId, resource, range, isTemplate);
return provider.createCommentThread(extensionId.value, commentThreadHandle, threadId, resource, range, isTemplate, editorId);
}

$updateCommentThread(handle: number,
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export interface MainThreadCommentsShape extends IDisposable {
$registerCommentController(handle: number, id: string, label: string, extensionId: string): void;
$unregisterCommentController(handle: number): void;
$updateCommentControllerFeatures(handle: number, features: CommentProviderFeatures): void;
$createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, extensionId: ExtensionIdentifier, isTemplate: boolean): languages.CommentThread<IRange | ICellRange> | undefined;
$createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange | ICellRange | undefined, extensionId: ExtensionIdentifier, isTemplate: boolean, editorId?: string): languages.CommentThread<IRange | ICellRange> | undefined;
$updateCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, changes: CommentThreadChanges): void;
$deleteCommentThread(handle: number, commentThreadHandle: number): void;
$updateCommentingRanges(handle: number, resourceHints?: languages.CommentingRangeResourceHint): void;
Expand Down Expand Up @@ -2458,7 +2458,7 @@ export interface ExtHostProgressShape {
}

export interface ExtHostCommentsShape {
$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange | undefined): Promise<void>;
$createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange | undefined, editorId?: string): Promise<void>;
$updateCommentThreadTemplate(commentControllerHandle: number, threadHandle: number, range: IRange): Promise<void>;
$deleteCommentThread(commentControllerHandle: number, commentThreadHandle: number): void;
$provideCommentingRanges(commentControllerHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<{ ranges: IRange[]; fileComments: boolean } | undefined>;
Expand Down
14 changes: 8 additions & 6 deletions src/vs/workbench/api/common/extHostComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
return commentController.value;
}

async $createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange | undefined): Promise<void> {
async $createCommentThreadTemplate(commentControllerHandle: number, uriComponents: UriComponents, range: IRange | undefined, editorId?: string): Promise<void> {
const commentController = this._commentControllers.get(commentControllerHandle);

if (!commentController) {
return;
}

commentController.$createCommentThreadTemplate(uriComponents, range);
commentController.$createCommentThreadTemplate(uriComponents, range, editorId);
}

async $setActiveComment(controllerHandle: number, commentInfo: { commentThreadHandle: number; uniqueIdInThread?: number }): Promise<void> {
Expand Down Expand Up @@ -409,7 +409,8 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
private _range: vscode.Range | undefined,
private _comments: vscode.Comment[],
public readonly extensionDescription: IExtensionDescription,
private _isTemplate: boolean
private _isTemplate: boolean,
editorId?: string
) {
this._acceptInputDisposables.value = new DisposableStore();

Expand All @@ -424,7 +425,8 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
this._uri,
extHostTypeConverter.Range.from(this._range),
extensionDescription.identifier,
this._isTemplate
this._isTemplate,
editorId
);

this._localDisposables = [];
Expand Down Expand Up @@ -680,8 +682,8 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo
}
}

$createCommentThreadTemplate(uriComponents: UriComponents, range: IRange | undefined): ExtHostCommentThread {
const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), [], this._extension, true);
$createCommentThreadTemplate(uriComponents: UriComponents, range: IRange | undefined, editorId?: string): ExtHostCommentThread {
const commentThread = new ExtHostCommentThread(this.id, this.handle, undefined, URI.revive(uriComponents), extHostTypeConverter.Range.to(range), [], this._extension, true, editorId);
commentThread.collapsibleState = languages.CommentThreadCollapsibleState.Expanded;
this._threads.set(commentThread.handle, commentThread);
return commentThread;
Expand Down
10 changes: 6 additions & 4 deletions src/vs/workbench/contrib/comments/browser/commentReply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
private _commentOptions: languages.CommentOptions | undefined,
private _pendingComment: string | undefined,
private _parentThread: ICommentThreadWidget,
focus: boolean,
private _actionRunDelegate: (() => void) | null,
@ICommentService private commentService: ICommentService,
@IThemeService private themeService: IThemeService,
Expand All @@ -75,10 +76,10 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
this.commentEditorIsEmpty = CommentContextKeys.commentIsEmpty.bindTo(this._contextKeyService);
this.commentEditorIsEmpty.set(!this._pendingComment);

this.initialize();
this.initialize(focus);
}

async initialize() {
async initialize(focus: boolean) {
const hasExistingComments = this._commentThread.comments && this._commentThread.comments.length > 0;
const modeId = generateUuid() + '-' + (hasExistingComments ? this._commentThread.threadId : ++INMEM_MODEL_ID);
const params = JSON.stringify({
Expand Down Expand Up @@ -118,7 +119,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
// Only add the additional step of clicking a reply button to expand the textarea when there are existing comments
if (hasExistingComments) {
this.createReplyButton(this.commentEditor, this.form);
} else if ((this._commentThread.comments && this._commentThread.comments.length === 0) || this._pendingComment) {
} else if (focus && ((this._commentThread.comments && this._commentThread.comments.length === 0) || this._pendingComment)) {
this.expandReplyArea();
}
this._error = dom.append(this.form, dom.$('.validation-error.hidden'));
Expand All @@ -140,12 +141,13 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {

public updateCommentThread(commentThread: languages.CommentThread<IRange | ICellRange>) {
const isReplying = this.commentEditor.hasTextFocus();
const oldAndNewBothEmpty = !this._commentThread.comments?.length && !commentThread.comments?.length;

if (!this._reviewThreadReplyButton) {
this.createReplyButton(this.commentEditor, this.form);
}

if (this._commentThread.comments && this._commentThread.comments.length === 0) {
if (this._commentThread.comments && this._commentThread.comments.length === 0 && !oldAndNewBothEmpty) {
this.expandReplyArea();
}

Expand Down
8 changes: 4 additions & 4 deletions src/vs/workbench/contrib/comments/browser/commentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export interface ICommentController {
options?: CommentOptions;
contextValue?: string;
owner: string;
createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined): Promise<void>;
createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined, editorId?: string): Promise<void>;
updateCommentThreadTemplate(threadHandle: number, range: IRange): Promise<void>;
deleteCommentThreadMain(commentThreadId: string): void;
toggleReaction(uri: URI, thread: CommentThread, comment: Comment, reaction: CommentReaction, token: CancellationToken): Promise<void>;
Expand Down Expand Up @@ -97,7 +97,7 @@ export interface ICommentService {
registerCommentController(uniqueOwner: string, commentControl: ICommentController): void;
unregisterCommentController(uniqueOwner?: string): void;
getCommentController(uniqueOwner: string): ICommentController | undefined;
createCommentThreadTemplate(uniqueOwner: string, resource: URI, range: Range | undefined): Promise<void>;
createCommentThreadTemplate(uniqueOwner: string, resource: URI, range: Range | undefined, editorId?: string): Promise<void>;
updateCommentThreadTemplate(uniqueOwner: string, threadHandle: number, range: Range): Promise<void>;
getCommentMenus(uniqueOwner: string): CommentMenus;
updateComments(ownerId: string, event: CommentThreadChangedEvent<IRange>): void;
Expand Down Expand Up @@ -361,14 +361,14 @@ export class CommentService extends Disposable implements ICommentService {
return this._commentControls.get(uniqueOwner);
}

async createCommentThreadTemplate(uniqueOwner: string, resource: URI, range: Range | undefined): Promise<void> {
async createCommentThreadTemplate(uniqueOwner: string, resource: URI, range: Range | undefined, editorId?: string): Promise<void> {
const commentController = this._commentControls.get(uniqueOwner);

if (!commentController) {
return;
}

return commentController.createCommentThreadTemplate(resource, range);
return commentController.createCommentThreadTemplate(resource, range, editorId);
}

async updateCommentThreadTemplate(uniqueOwner: string, threadHandle: number, range: Range) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,15 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
}
}

async display(lineHeight: number) {
async display(lineHeight: number, focus: boolean) {
const headHeight = Math.max(23, Math.ceil(lineHeight * 1.2)); // 23 is the value of `Math.ceil(lineHeight * 1.2)` with the default editor font size
this._header.updateHeight(headHeight);

await this._body.display();

// create comment thread only when it supports reply
if (this._commentThread.canReply) {
this._createCommentForm();
this._createCommentForm(focus);
}
this._createAdditionalActions();

Expand Down Expand Up @@ -272,7 +272,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
this._commentReply.updateCanReply();
} else {
if (this._commentThread.canReply) {
this._createCommentForm();
this._createCommentForm(false);
}
}
}));
Expand All @@ -286,7 +286,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
}));
}

private _createCommentForm() {
private _createCommentForm(focus: boolean) {
this._commentReply = this._scopedInstantiationService.createInstance(
CommentReply,
this._owner,
Expand All @@ -299,6 +299,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
this._commentOptions,
this._pendingComment,
this,
focus,
this._containerDelegate.actionRunner
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,13 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
this._commentThreadWidget.layout(widthInPixel);
}

async display(range: IRange | undefined) {
async display(range: IRange | undefined, shouldReveal: boolean) {
if (range) {
this._commentGlyph = new CommentGlyphWidget(this.editor, range?.endLineNumber ?? -1);
this._commentGlyph.setThreadState(this._commentThread.state);
}

await this._commentThreadWidget.display(this.editor.getOption(EditorOption.lineHeight));
await this._commentThreadWidget.display(this.editor.getOption(EditorOption.lineHeight), shouldReveal);
this._disposables.add(this._commentThreadWidget.onDidResize(dimension => {
this._refresh(dimension);
}));
Expand All @@ -371,7 +371,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
}

// 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))) {
if (shouldReveal) {
this.reveal();
}

Expand Down Expand Up @@ -463,10 +463,6 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
this._viewZone.afterLineNumber = currentPosition.lineNumber;
}

if (!this._commentThread.comments || !this._commentThread.comments.length) {
this._commentThreadWidget.focusCommentEditor();
}

const capture = StableEditorScrollState.capture(this.editor);
this._relayout(computedLinesNumber);
capture.restore(this.editor);
Expand Down
Loading

0 comments on commit a812bde

Please sign in to comment.