mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-12 22:08:04 -05:00
Pending edits for vscode.CommentMode.Editing lost when switching file tabs (#174678)
Fixes #166693
This commit is contained in:
@@ -88,6 +88,7 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
|
||||
constructor(
|
||||
private commentThread: languages.CommentThread<T>,
|
||||
public comment: languages.Comment,
|
||||
private pendingEdit: string | undefined,
|
||||
private owner: string,
|
||||
private resource: URI,
|
||||
private parentThread: ICommentThreadWidget,
|
||||
@@ -139,6 +140,10 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
|
||||
this._register(dom.addDisposableListener(this._domNode, dom.EventType.CONTEXT_MENU, e => {
|
||||
return this.onContextMenu(e);
|
||||
}));
|
||||
|
||||
if (pendingEdit) {
|
||||
this.switchToEditMode();
|
||||
}
|
||||
}
|
||||
|
||||
private createScroll(container: HTMLElement, body: HTMLElement) {
|
||||
@@ -431,12 +436,13 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
|
||||
|
||||
private createCommentEditor(editContainer: HTMLElement): void {
|
||||
const container = dom.append(editContainer, dom.$('.edit-textarea'));
|
||||
this._commentEditor = this.instantiationService.createInstance(SimpleCommentEditor, container, SimpleCommentEditor.getEditorOptions(this.configurationService), this.parentThread);
|
||||
this._commentEditor = this.instantiationService.createInstance(SimpleCommentEditor, container, SimpleCommentEditor.getEditorOptions(this.configurationService), this._contextKeyService, this.parentThread);
|
||||
const resource = URI.parse(`comment:commentinput-${this.comment.uniqueIdInThread}-${Date.now()}.md`);
|
||||
this._commentEditorModel = this.modelService.createModel('', this.languageService.createByFilepathOrFirstLine(resource), resource, false);
|
||||
|
||||
this._commentEditor.setModel(this._commentEditorModel);
|
||||
this._commentEditor.setValue(this.commentBodyValue);
|
||||
this._commentEditor.setValue(this.pendingEdit ?? this.commentBodyValue);
|
||||
this.pendingEdit = undefined;
|
||||
this._commentEditor.layout({ width: container.clientWidth - 14, height: 90 });
|
||||
this._commentEditor.focus();
|
||||
|
||||
@@ -480,6 +486,14 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
|
||||
this._register(this._commentEditorModel);
|
||||
}
|
||||
|
||||
getPendingEdit(): string | undefined {
|
||||
const model = this._commentEditor?.getModel();
|
||||
if (model && model.getValueLength() > 0) {
|
||||
return model.getValue();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private removeCommentEditor() {
|
||||
this.isEditing = false;
|
||||
if (this._editAction) {
|
||||
|
||||
@@ -54,7 +54,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
|
||||
private _contextKeyService: IContextKeyService,
|
||||
private _commentMenus: CommentMenus,
|
||||
private _commentOptions: languages.CommentOptions | undefined,
|
||||
private _pendingComment: string | null,
|
||||
private _pendingComment: string | undefined,
|
||||
private _parentThread: ICommentThreadWidget,
|
||||
private _actionRunDelegate: (() => void) | null,
|
||||
@ICommentService private commentService: ICommentService,
|
||||
@@ -66,7 +66,7 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
|
||||
super();
|
||||
|
||||
this.form = dom.append(container, dom.$('.comment-form'));
|
||||
this.commentEditor = this._register(this._scopedInstatiationService.createInstance(SimpleCommentEditor, this.form, SimpleCommentEditor.getEditorOptions(configurationService), this._parentThread));
|
||||
this.commentEditor = this._register(this._scopedInstatiationService.createInstance(SimpleCommentEditor, this.form, SimpleCommentEditor.getEditorOptions(configurationService), _contextKeyService, this._parentThread));
|
||||
this.commentEditorIsEmpty = CommentContextKeys.commentIsEmpty.bindTo(this._contextKeyService);
|
||||
this.commentEditorIsEmpty.set(!this._pendingComment);
|
||||
|
||||
@@ -126,14 +126,14 @@ export class CommentReply<T extends IRange | ICellRange> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public getPendingComment(): string | null {
|
||||
public getPendingComment(): string | undefined {
|
||||
const model = this.commentEditor.getModel();
|
||||
|
||||
if (model && model.getValueLength() > 0) { // checking length is cheap
|
||||
return model.getValue();
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public layout(widthInPixel: number) {
|
||||
|
||||
@@ -47,6 +47,7 @@ export class CommentThreadBody<T extends IRange | ICellRange = IRange> extends D
|
||||
readonly container: HTMLElement,
|
||||
private _options: IMarkdownRendererOptions,
|
||||
private _commentThread: languages.CommentThread<T>,
|
||||
private _pendingEdits: { [key: number]: string } | undefined,
|
||||
private _scopedInstatiationService: IInstantiationService,
|
||||
private _parentCommentThreadWidget: ICommentThreadWidget,
|
||||
@ICommentService private commentService: ICommentService,
|
||||
@@ -125,6 +126,20 @@ export class CommentThreadBody<T extends IRange | ICellRange = IRange> extends D
|
||||
});
|
||||
}
|
||||
|
||||
getPendingEdits(): { [key: number]: string } {
|
||||
const pendingEdits: { [key: number]: string } = {};
|
||||
this._commentElements.forEach(element => {
|
||||
if (element.isEditing) {
|
||||
const pendingEdit = element.getPendingEdit();
|
||||
if (pendingEdit) {
|
||||
pendingEdits[element.comment.uniqueIdInThread] = pendingEdit;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return pendingEdits;
|
||||
}
|
||||
|
||||
getCommentCoords(commentUniqueId: number): { thread: dom.IDomNodePagePosition; comment: dom.IDomNodePagePosition } | undefined {
|
||||
const matchedNode = this._commentElements.filter(commentNode => commentNode.comment.uniqueIdInThread === commentUniqueId);
|
||||
if (matchedNode && matchedNode.length) {
|
||||
@@ -236,6 +251,7 @@ export class CommentThreadBody<T extends IRange | ICellRange = IRange> extends D
|
||||
const newCommentNode = this._scopedInstatiationService.createInstance(CommentNode,
|
||||
this._commentThread,
|
||||
comment,
|
||||
this._pendingEdits ? this._pendingEdits[comment.uniqueIdInThread!] : undefined,
|
||||
this.owner,
|
||||
this.parentResourceUri,
|
||||
this._parentCommentThreadWidget,
|
||||
|
||||
@@ -56,7 +56,8 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
|
||||
private _contextKeyService: IContextKeyService,
|
||||
private _scopedInstatiationService: IInstantiationService,
|
||||
private _commentThread: languages.CommentThread<T>,
|
||||
private _pendingComment: string | null,
|
||||
private _pendingComment: string | undefined,
|
||||
private _pendingEdits: { [key: number]: string } | undefined,
|
||||
private _markdownOptions: IMarkdownRendererOptions,
|
||||
private _commentOptions: languages.CommentOptions | undefined,
|
||||
private _containerDelegate: {
|
||||
@@ -97,6 +98,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
|
||||
bodyElement,
|
||||
this._markdownOptions,
|
||||
this._commentThread,
|
||||
this._pendingEdits,
|
||||
this._scopedInstatiationService,
|
||||
this
|
||||
) as unknown as CommentThreadBody<T>;
|
||||
@@ -259,12 +261,16 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
|
||||
return this._body.getCommentCoords(commentUniqueId);
|
||||
}
|
||||
|
||||
getPendingComment(): string | null {
|
||||
getPendingEdits(): { [key: number]: string } {
|
||||
return this._body.getPendingEdits();
|
||||
}
|
||||
|
||||
getPendingComment(): string | undefined {
|
||||
if (this._commentReply) {
|
||||
return this._commentReply.getPendingComment();
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getDimensions() {
|
||||
|
||||
@@ -117,7 +117,8 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
editor: ICodeEditor,
|
||||
private _owner: string,
|
||||
private _commentThread: languages.CommentThread,
|
||||
private _pendingComment: string | null,
|
||||
private _pendingComment: string | undefined,
|
||||
private _pendingEdits: { [key: number]: string } | undefined,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@ICommentService private commentService: ICommentService,
|
||||
@@ -196,8 +197,11 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
public getPendingComment(): string | null {
|
||||
return this._commentThreadWidget.getPendingComment();
|
||||
public getPendingComments(): { newComment: string | undefined; edits: { [key: number]: string } } {
|
||||
return {
|
||||
newComment: this._commentThreadWidget.getPendingComment(),
|
||||
edits: this._commentThreadWidget.getPendingEdits()
|
||||
};
|
||||
}
|
||||
|
||||
protected _fillContainer(container: HTMLElement): void {
|
||||
@@ -211,6 +215,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._scopedInstantiationService,
|
||||
this._commentThread as unknown as languages.CommentThread<IRange | ICellRange>,
|
||||
this._pendingComment,
|
||||
this._pendingEdits,
|
||||
{ editor: this.editor, codeBlockFontSize: '' },
|
||||
this._commentOptions,
|
||||
{
|
||||
|
||||
@@ -296,7 +296,8 @@ export class CommentController implements IEditorContribution {
|
||||
private _emptyThreadsToAddQueue: [Range, IEditorMouseEvent | undefined][] = [];
|
||||
private _computeCommentingRangePromise!: CancelablePromise<ICommentInfo[]> | null;
|
||||
private _computeCommentingRangeScheduler!: Delayer<Array<ICommentInfo | null>> | null;
|
||||
private _pendingCommentCache: { [key: string]: { [key: string]: string } };
|
||||
private _pendingNewCommentCache: { [key: string]: { [key: string]: string } };
|
||||
private _pendingEditsCache: { [key: string]: { [key: string]: { [key: number]: string } } }; // owner -> threadId -> uniqueIdInThread -> pending comment
|
||||
private _editorDisposables: IDisposable[] = [];
|
||||
private _activeCursorHasCommentingRange: IContextKey<boolean>;
|
||||
|
||||
@@ -314,7 +315,8 @@ export class CommentController implements IEditorContribution {
|
||||
) {
|
||||
this._commentInfos = [];
|
||||
this._commentWidgets = [];
|
||||
this._pendingCommentCache = {};
|
||||
this._pendingNewCommentCache = {};
|
||||
this._pendingEditsCache = {};
|
||||
this._computePromise = null;
|
||||
this._activeCursorHasCommentingRange = ActiveCursorHasCommentingRange.bindTo(contextKeyService);
|
||||
|
||||
@@ -336,7 +338,8 @@ export class CommentController implements IEditorContribution {
|
||||
this.globalToDispose.add(this._commentThreadRangeDecorator = new CommentThreadRangeDecorator(this.commentService));
|
||||
|
||||
this.globalToDispose.add(this.commentService.onDidDeleteDataProvider(ownerId => {
|
||||
delete this._pendingCommentCache[ownerId];
|
||||
delete this._pendingNewCommentCache[ownerId];
|
||||
delete this._pendingEditsCache[ownerId];
|
||||
this.beginCompute();
|
||||
}));
|
||||
this.globalToDispose.add(this.commentService.onDidSetDataProvider(_ => this.beginCompute()));
|
||||
@@ -676,8 +679,9 @@ export class CommentController implements IEditorContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingCommentText = this._pendingCommentCache[e.owner] && this._pendingCommentCache[e.owner][thread.threadId!];
|
||||
this.displayCommentThread(e.owner, thread, pendingCommentText);
|
||||
const pendingCommentText = this._pendingNewCommentCache[e.owner] && this._pendingNewCommentCache[e.owner][thread.threadId!];
|
||||
const pendingEdits = this._pendingEditsCache[e.owner] && this._pendingEditsCache[e.owner][thread.threadId!];
|
||||
this.displayCommentThread(e.owner, thread, pendingCommentText, pendingEdits);
|
||||
this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread);
|
||||
this.tryUpdateReservedSpace();
|
||||
});
|
||||
@@ -701,14 +705,14 @@ export class CommentController implements IEditorContribution {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private displayCommentThread(owner: string, thread: languages.CommentThread, pendingComment: string | null): void {
|
||||
private displayCommentThread(owner: string, thread: languages.CommentThread, pendingComment: string | undefined, pendingEdits: { [key: number]: string } | undefined): void {
|
||||
if (!this.editor) {
|
||||
return;
|
||||
}
|
||||
if (this.isEditorInlineOriginal(this.editor)) {
|
||||
return;
|
||||
}
|
||||
const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, owner, thread, pendingComment);
|
||||
const zoneWidget = this.instantiationService.createInstance(ReviewZoneWidget, this.editor, owner, thread, pendingComment, pendingEdits);
|
||||
zoneWidget.display(thread.range);
|
||||
this._commentWidgets.push(zoneWidget);
|
||||
this.openCommentsView(thread);
|
||||
@@ -943,19 +947,25 @@ export class CommentController implements IEditorContribution {
|
||||
this.removeCommentWidgetsAndStoreCache();
|
||||
|
||||
this._commentInfos.forEach(info => {
|
||||
const providerCacheStore = this._pendingCommentCache[info.owner];
|
||||
const providerCacheStore = this._pendingNewCommentCache[info.owner];
|
||||
const providerEditsCacheStore = this._pendingEditsCache[info.owner];
|
||||
info.threads = info.threads.filter(thread => !thread.isDisposed);
|
||||
info.threads.forEach(thread => {
|
||||
let pendingComment: string | null = null;
|
||||
let pendingComment: string | undefined = undefined;
|
||||
if (providerCacheStore) {
|
||||
pendingComment = providerCacheStore[thread.threadId!];
|
||||
}
|
||||
|
||||
if (pendingComment) {
|
||||
let pendingEdits: { [key: number]: string } | undefined = undefined;
|
||||
if (providerEditsCacheStore) {
|
||||
pendingEdits = providerEditsCacheStore[thread.threadId!];
|
||||
}
|
||||
|
||||
if (pendingComment || pendingEdits) {
|
||||
thread.collapsibleState = languages.CommentThreadCollapsibleState.Expanded;
|
||||
}
|
||||
|
||||
this.displayCommentThread(info.owner, thread, pendingComment);
|
||||
this.displayCommentThread(info.owner, thread, pendingComment, pendingEdits);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -974,8 +984,9 @@ export class CommentController implements IEditorContribution {
|
||||
private removeCommentWidgetsAndStoreCache() {
|
||||
if (this._commentWidgets) {
|
||||
this._commentWidgets.forEach(zone => {
|
||||
const pendingComment = zone.getPendingComment();
|
||||
const providerCacheStore = this._pendingCommentCache[zone.owner];
|
||||
const pendingComments = zone.getPendingComments();
|
||||
const pendingNewComment = pendingComments.newComment;
|
||||
const providerNewCommentCacheStore = this._pendingNewCommentCache[zone.owner];
|
||||
|
||||
let lastCommentBody;
|
||||
if (zone.commentThread.comments && zone.commentThread.comments.length) {
|
||||
@@ -986,18 +997,29 @@ export class CommentController implements IEditorContribution {
|
||||
lastCommentBody = lastComment.body.value;
|
||||
}
|
||||
}
|
||||
if (pendingComment && (pendingComment !== lastCommentBody)) {
|
||||
if (!providerCacheStore) {
|
||||
this._pendingCommentCache[zone.owner] = {};
|
||||
if (pendingNewComment && (pendingNewComment !== lastCommentBody)) {
|
||||
if (!providerNewCommentCacheStore) {
|
||||
this._pendingNewCommentCache[zone.owner] = {};
|
||||
}
|
||||
|
||||
this._pendingCommentCache[zone.owner][zone.commentThread.threadId!] = pendingComment;
|
||||
this._pendingNewCommentCache[zone.owner][zone.commentThread.threadId!] = pendingNewComment;
|
||||
} else {
|
||||
if (providerCacheStore) {
|
||||
delete providerCacheStore[zone.commentThread.threadId!];
|
||||
if (providerNewCommentCacheStore) {
|
||||
delete providerNewCommentCacheStore[zone.commentThread.threadId!];
|
||||
}
|
||||
}
|
||||
|
||||
const pendingEdits = pendingComments.edits;
|
||||
const providerEditsCacheStore = this._pendingEditsCache[zone.owner];
|
||||
if (Object.keys(pendingEdits).length > 0) {
|
||||
if (!providerEditsCacheStore) {
|
||||
this._pendingEditsCache[zone.owner] = {};
|
||||
}
|
||||
this._pendingEditsCache[zone.owner][zone.commentThread.threadId!] = pendingEdits;
|
||||
} else if (providerEditsCacheStore) {
|
||||
delete providerEditsCacheStore[zone.commentThread.threadId!];
|
||||
}
|
||||
|
||||
zone.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,11 +37,11 @@ export class SimpleCommentEditor extends CodeEditorWidget {
|
||||
constructor(
|
||||
domElement: HTMLElement,
|
||||
options: IEditorOptions,
|
||||
scopedContextKeyService: IContextKeyService,
|
||||
parentThread: ICommentThreadWidget,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IAccessibilityService accessibilityService: IAccessibilityService,
|
||||
@@ -58,10 +58,10 @@ export class SimpleCommentEditor extends CodeEditorWidget {
|
||||
]
|
||||
};
|
||||
|
||||
super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService);
|
||||
super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, scopedContextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService);
|
||||
|
||||
this._commentEditorFocused = ctxCommentEditorFocused.bindTo(contextKeyService);
|
||||
this._commentEditorEmpty = CommentContextKeys.commentIsEmpty.bindTo(contextKeyService);
|
||||
this._commentEditorFocused = ctxCommentEditorFocused.bindTo(scopedContextKeyService);
|
||||
this._commentEditorEmpty = CommentContextKeys.commentIsEmpty.bindTo(scopedContextKeyService);
|
||||
this._commentEditorEmpty.set(!this.getValue());
|
||||
this._parentThread = parentThread;
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ export class CellComments extends CellContentPart {
|
||||
this.contextKeyService,
|
||||
this.instantiationService,
|
||||
commentThread,
|
||||
null,
|
||||
undefined,
|
||||
undefined,
|
||||
{
|
||||
codeBlockFontFamily: this.configurationService.getValue<IEditorOptions>('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user