mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 09:42:34 -05:00
Merge from vscode 5b9869eb02fa4c96205a74d05cad9164dfd06d60 (#5607)
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -38,9 +38,18 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/commentThreadWidget';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { CommentMenus } from 'vs/workbench/contrib/comments/browser/commentMenus';
|
||||
import { MenuItemAction, IMenu } from 'vs/platform/actions/common/actions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
|
||||
import { CommentFormActions } from 'vs/workbench/contrib/comments/browser/commentFormActions';
|
||||
|
||||
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
|
||||
const COLLAPSE_ACTION_CLASS = 'expand-review-action octicon octicon-x';
|
||||
const COLLAPSE_ACTION_CLASS = 'expand-review-action octicon octicon-chevron-up';
|
||||
const COMMENT_SCHEME = 'comment';
|
||||
|
||||
|
||||
@@ -70,6 +79,11 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
private _styleElement: HTMLStyleElement;
|
||||
private _formActions: HTMLElement | null;
|
||||
private _error: HTMLElement;
|
||||
private _contextKeyService: IContextKeyService;
|
||||
private _threadIsEmpty: IContextKey<boolean>;
|
||||
private _commentThreadContextValue: IContextKey<string>;
|
||||
private _commentEditorIsEmpty: IContextKey<boolean>;
|
||||
private _commentFormActions: CommentFormActions;
|
||||
|
||||
public get owner(): string {
|
||||
return this._owner;
|
||||
@@ -86,6 +100,8 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
return this._draftMode;
|
||||
}
|
||||
|
||||
private _commentMenus: CommentMenus;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
private _owner: string,
|
||||
@@ -98,15 +114,25 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
@IModelService private modelService: IModelService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@ICommentService private commentService: ICommentService,
|
||||
@IOpenerService private openerService: IOpenerService
|
||||
@IOpenerService private openerService: IOpenerService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(editor, { keepEditorSelection: true });
|
||||
this._contextKeyService = contextKeyService.createScoped(this.domNode);
|
||||
this._threadIsEmpty = CommentContextKeys.commentThreadIsEmpty.bindTo(this._contextKeyService);
|
||||
this._threadIsEmpty.set(!_commentThread.comments || !_commentThread.comments.length);
|
||||
this._commentThreadContextValue = contextKeyService.createKey('commentThread', _commentThread.contextValue);
|
||||
|
||||
this._resizeObserver = null;
|
||||
this._isExpanded = _commentThread.collapsibleState ? _commentThread.collapsibleState === modes.CommentThreadCollapsibleState.Expanded : undefined;
|
||||
this._globalToDispose = [];
|
||||
this._commentThreadDisposables = [];
|
||||
this._submitActionsDisposables = [];
|
||||
this._formActions = null;
|
||||
this._commentMenus = this.commentService.getCommentMenus(this._owner);
|
||||
this.create();
|
||||
|
||||
this._styleElement = dom.createStyleSheet(this.domNode);
|
||||
@@ -185,10 +211,6 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
|
||||
this._bodyElement = <HTMLDivElement>dom.$('.body');
|
||||
container.appendChild(this._bodyElement);
|
||||
|
||||
dom.addDisposableListener(this._bodyElement, dom.EventType.FOCUS_IN, e => {
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
});
|
||||
}
|
||||
|
||||
protected _fillHead(container: HTMLElement): void {
|
||||
@@ -198,12 +220,41 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this.createThreadLabel();
|
||||
|
||||
const actionsContainer = dom.append(this._headElement, dom.$('.review-actions'));
|
||||
this._actionbarWidget = new ActionBar(actionsContainer, {});
|
||||
this._actionbarWidget = new ActionBar(actionsContainer, {
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
if (action instanceof MenuItemAction) {
|
||||
let item = new ContextAwareMenuEntryActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
return item;
|
||||
} else {
|
||||
let item = new ActionViewItem({}, action, { label: false, icon: true });
|
||||
return item;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this._disposables.push(this._actionbarWidget);
|
||||
|
||||
this._collapseAction = new Action('review.expand', nls.localize('label.collapse', "Collapse"), COLLAPSE_ACTION_CLASS, true, () => this.collapse());
|
||||
|
||||
this._actionbarWidget.push(this._collapseAction, { label: false, icon: true });
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
const menu = this._commentMenus.getCommentThreadTitleActions(this._commentThread as modes.CommentThread2, this._contextKeyService);
|
||||
this.setActionBarActions(menu);
|
||||
|
||||
this._disposables.push(menu);
|
||||
this._disposables.push(menu.onDidChange(e => {
|
||||
this.setActionBarActions(menu);
|
||||
}));
|
||||
} else {
|
||||
this._actionbarWidget.push([this._collapseAction], { label: false, icon: true });
|
||||
}
|
||||
|
||||
this._actionbarWidget.context = this._commentThread;
|
||||
}
|
||||
|
||||
private setActionBarActions(menu: IMenu): void {
|
||||
const groups = menu.getActions({ shouldForwardArgs: true }).reduce((r, [, actions]) => [...r, ...actions], <MenuItemAction[]>[]);
|
||||
this._actionbarWidget.clear();
|
||||
this._actionbarWidget.push([...groups, this._collapseAction], { label: false, icon: true });
|
||||
}
|
||||
|
||||
public collapse(): Promise<void> {
|
||||
@@ -214,9 +265,9 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
} else {
|
||||
const deleteCommand = (this._commentThread as modes.CommentThread2).deleteCommand;
|
||||
if (deleteCommand) {
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
return this.commandService.executeCommand(deleteCommand.id, ...(deleteCommand.arguments || []));
|
||||
} else if (this._commentEditor.getValue() === '') {
|
||||
this.commentService.disposeCommentThread(this._owner, this._commentThread.threadId!);
|
||||
this.dispose();
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -245,9 +296,10 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
async update(commentThread: modes.CommentThread | modes.CommentThread2, replaceTemplate: boolean = false) {
|
||||
async update(commentThread: modes.CommentThread | modes.CommentThread2) {
|
||||
const oldCommentsLen = this._commentElements.length;
|
||||
const newCommentsLen = commentThread.comments ? commentThread.comments.length : 0;
|
||||
this._threadIsEmpty.set(!newCommentsLen);
|
||||
|
||||
let commentElementsToDel: CommentNode[] = [];
|
||||
let commentElementsToDelIndex: number[] = [];
|
||||
@@ -294,26 +346,12 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
|
||||
this._commentThread = commentThread;
|
||||
this._commentElements = newCommentNodeList;
|
||||
this.createThreadLabel(replaceTemplate);
|
||||
|
||||
if (replaceTemplate) {
|
||||
// since we are replacing the old comment thread, we need to rebind the listeners.
|
||||
this._commentThreadDisposables.forEach(global => global.dispose());
|
||||
this._commentThreadDisposables = [];
|
||||
}
|
||||
|
||||
if (replaceTemplate) {
|
||||
this.createTextModelListener();
|
||||
}
|
||||
this.createThreadLabel();
|
||||
|
||||
if (this._formActions && this._commentEditor.hasModel()) {
|
||||
dom.clearNode(this._formActions);
|
||||
const model = this._commentEditor.getModel();
|
||||
this.createCommentWidgetActions2(this._formActions, model);
|
||||
|
||||
if (replaceTemplate) {
|
||||
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||
}
|
||||
}
|
||||
|
||||
// Move comment glyph widget and show position if the line has changed.
|
||||
@@ -346,6 +384,12 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (this._commentThread.contextValue) {
|
||||
this._commentThreadContextValue.set(this._commentThread.contextValue);
|
||||
} else {
|
||||
this._commentThreadContextValue.reset();
|
||||
}
|
||||
}
|
||||
|
||||
updateDraftMode(draftMode: modes.DraftMode | undefined) {
|
||||
@@ -368,7 +412,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._commentEditor.layout({ height: 5 * 18, width: widthInPixel - 54 /* margin 20px * 10 + scrollbar 14px*/ });
|
||||
}
|
||||
|
||||
display(lineNumber: number, fromTemplate: boolean = false) {
|
||||
display(lineNumber: number) {
|
||||
this._commentGlyph = new CommentGlyphWidget(this.editor, lineNumber);
|
||||
|
||||
this._disposables.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
||||
@@ -394,18 +438,30 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
const hasExistingComments = this._commentThread.comments && this._commentThread.comments.length > 0;
|
||||
this._commentForm = dom.append(this._bodyElement, dom.$('.comment-form'));
|
||||
this._commentEditor = this.instantiationService.createInstance(SimpleCommentEditor, this._commentForm, SimpleCommentEditor.getEditorOptions(), this._parentEditor, this);
|
||||
this._commentEditorIsEmpty = CommentContextKeys.commentIsEmpty.bindTo(this._contextKeyService);
|
||||
this._commentEditorIsEmpty.set(!this._pendingComment);
|
||||
|
||||
const modeId = generateUuid() + '-' + (hasExistingComments ? this._commentThread.threadId : ++INMEM_MODEL_ID);
|
||||
const params = JSON.stringify({
|
||||
extensionId: this.extensionId,
|
||||
commentThreadId: this.commentThread.threadId
|
||||
});
|
||||
const resource = URI.parse(`${COMMENT_SCHEME}:commentinput-${modeId}.md?${params}`);
|
||||
|
||||
let resource = URI.parse(`${COMMENT_SCHEME}://${this.extensionId}/commentinput-${modeId}.md?${params}`); // TODO. Remove params once extensions adopt authority.
|
||||
let commentController = this.commentService.getCommentController(this.owner);
|
||||
if (commentController) {
|
||||
resource = resource.with({ authority: commentController.id });
|
||||
}
|
||||
|
||||
const model = this.modelService.createModel(this._pendingComment || '', this.modeService.createByFilepathOrFirstLine(resource.path), resource, false);
|
||||
this._disposables.push(model);
|
||||
this._commentEditor.setModel(model);
|
||||
this._disposables.push(this._commentEditor);
|
||||
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => this.setCommentEditorDecorations()));
|
||||
this._disposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => {
|
||||
this.setCommentEditorDecorations();
|
||||
this._commentEditorIsEmpty.set(!this._commentEditor.getValue());
|
||||
}));
|
||||
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
this.createTextModelListener();
|
||||
}
|
||||
@@ -426,9 +482,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._formActions = dom.append(this._commentForm, dom.$('.form-actions'));
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
this.createCommentWidgetActions2(this._formActions, model);
|
||||
if (!fromTemplate) {
|
||||
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||
}
|
||||
this.createCommentWidgetActionsListener(this._formActions, model);
|
||||
} else {
|
||||
this.createCommentWidgetActions(this._formActions, model);
|
||||
}
|
||||
@@ -462,7 +516,6 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
uri: this._commentEditor.getModel()!.uri,
|
||||
value: this._commentEditor.getValue()
|
||||
};
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
}));
|
||||
|
||||
this._commentThreadDisposables.push(this._commentEditor.getModel()!.onDidChangeContent(() => {
|
||||
@@ -674,7 +727,6 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
uri: this._commentEditor.getModel()!.uri,
|
||||
value: this._commentEditor.getValue()
|
||||
};
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
await this.commandService.executeCommand(acceptInputCommand.id, ...(acceptInputCommand.arguments || []));
|
||||
}));
|
||||
|
||||
@@ -699,11 +751,29 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
uri: this._commentEditor.getModel()!.uri,
|
||||
value: this._commentEditor.getValue()
|
||||
};
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
await this.commandService.executeCommand(command.id, ...(command.arguments || []));
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
const menu = this._commentMenus.getCommentThreadActions(commentThread, this._contextKeyService);
|
||||
|
||||
this._disposables.push(menu);
|
||||
this._disposables.push(menu.onDidChange(() => {
|
||||
this._commentFormActions.setActions(menu);
|
||||
}));
|
||||
|
||||
this._commentFormActions = new CommentFormActions(container, (action: IAction) => {
|
||||
action.run({
|
||||
thread: this._commentThread,
|
||||
text: this._commentEditor.getValue(),
|
||||
$mid: 8
|
||||
});
|
||||
|
||||
this.hideReplyArea();
|
||||
}, this.themeService);
|
||||
|
||||
this._commentFormActions.setActions(menu);
|
||||
}
|
||||
|
||||
private createNewCommentNode(comment: modes.Comment): CommentNode {
|
||||
@@ -751,7 +821,6 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
uri: this._commentEditor.getModel()!.uri,
|
||||
value: this._commentEditor.getValue()
|
||||
};
|
||||
this.commentService.setActiveCommentThread(this._commentThread);
|
||||
let commandId = commentThread.acceptInputCommand.id;
|
||||
let args = commentThread.acceptInputCommand.arguments || [];
|
||||
|
||||
@@ -827,14 +896,13 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
private createThreadLabel(replaceTemplate: boolean = false) {
|
||||
private createThreadLabel() {
|
||||
let label: string | undefined;
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
label = (this._commentThread as modes.CommentThread2).label;
|
||||
}
|
||||
|
||||
if (label === undefined && !replaceTemplate) {
|
||||
// if it's for replacing the comment thread template, the comment thread widget title can be undefined as extensions may set it later
|
||||
if (label === undefined) {
|
||||
if (this._commentThread.comments && this._commentThread.comments.length) {
|
||||
const participantsList = this._commentThread.comments.filter(arrays.uniqueFilter(comment => comment.userName)).map(comment => `@${comment.userName}`).join(', ');
|
||||
label = nls.localize('commentThreadParticipants', "Participants: {0}", participantsList);
|
||||
@@ -847,7 +915,6 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._headingLabel.innerHTML = strings.escape(label);
|
||||
this._headingLabel.setAttribute('aria-label', label);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private expandReplyArea() {
|
||||
@@ -857,6 +924,17 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
}
|
||||
}
|
||||
|
||||
private hideReplyArea() {
|
||||
this._commentEditor.setValue('');
|
||||
this._pendingComment = '';
|
||||
if (dom.hasClass(this._commentForm, 'expand')) {
|
||||
dom.removeClass(this._commentForm, 'expand');
|
||||
}
|
||||
this._commentEditor.getDomNode()!.style.outline = '';
|
||||
this._error.textContent = '';
|
||||
dom.addClass(this._error, 'hidden');
|
||||
}
|
||||
|
||||
private createReplyButton() {
|
||||
this._reviewThreadReplyButton = <HTMLButtonElement>dom.append(this._commentForm, dom.$('button.review-thread-reply-button'));
|
||||
if ((this._commentThread as modes.CommentThread2).commentThreadHandle !== undefined) {
|
||||
|
||||
Reference in New Issue
Block a user