提交 8d78eddd 编写于 作者: R rebornix

render pending comment

上级 1b8f3883
......@@ -1202,6 +1202,7 @@ export interface Comment {
readonly canEdit?: boolean;
readonly canDelete?: boolean;
readonly command?: Command;
readonly isDraft?: boolean;
}
/**
......
......@@ -927,6 +927,11 @@ declare module 'vscode' {
* Changed comment threads.
*/
readonly changed: CommentThread[];
/**
* Changed draft mode
*/
readonly inDraftMode: boolean;
}
interface DocumentCommentProvider {
......
......@@ -52,6 +52,16 @@ export class MainThreadDocumentCommentProvider implements modes.DocumentCommentP
return this._proxy.$deleteComment(this._handle, uri, comment);
}
async startDraft(token): Promise<void> {
return this._proxy.$startDraft(this._handle);
}
async deleteDraft(token): Promise<void> {
return this._proxy.$deleteDraft(this._handle);
}
async finishDraft(token): Promise<void> {
return this._proxy.$finishDraft(this._handle);
}
onDidChangeCommentThreads = null;
}
......
......@@ -1037,6 +1037,9 @@ export interface ExtHostCommentsShape {
$replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Thenable<modes.CommentThread>;
$editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Thenable<void>;
$deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Thenable<void>;
$startDraft(handle: number): Thenable<void>;
$deleteDraft(handle: number): Thenable<void>;
$finishDraft(handle: number): Thenable<void>;
$getStartDraftLabel(handle: number): Thenable<string>;
$provideWorkspaceComments(handle: number): Thenable<modes.CommentThread[]>;
}
......
......@@ -121,6 +121,27 @@ export class ExtHostComments implements ExtHostCommentsShape {
});
}
$startDraft(handle: number): Thenable<void> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.startDraft(CancellationToken.None);
});
}
$deleteDraft(handle: number): Thenable<void> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.deleteDraft(CancellationToken.None);
});
}
$finishDraft(handle: number): Thenable<void> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.finishDraft(CancellationToken.None);
});
}
$getStartDraftLabel(handle: number): Thenable<string> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
......@@ -209,7 +230,8 @@ function convertFromComment(comment: modes.Comment): vscode.Comment {
userName: comment.userName,
userIconPath: userIconPath,
canEdit: comment.canEdit,
canDelete: comment.canDelete
canDelete: comment.canDelete,
isDraft: comment.isDraft
};
}
......@@ -224,6 +246,7 @@ function convertToComment(provider: vscode.DocumentCommentProvider | vscode.Work
userIconPath: iconPath,
canEdit: canEdit,
canDelete: canDelete,
command: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : null
command: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : null,
isDraft: vscodeComment.isDraft
};
}
......@@ -99,6 +99,11 @@ export class CommentNode extends Disposable {
const author = dom.append(header, dom.$('strong.author'));
author.innerText = this.comment.userName;
if (this.comment.isDraft) {
const isPendingLabel = dom.append(header, dom.$('span.isPending'));
isPendingLabel.innerText = 'Pending';
}
const actions: Action[] = [];
if (this.comment.canEdit) {
this._editAction = this.createEditAction(commentDetailsContainer);
......
......@@ -49,6 +49,9 @@ export interface ICommentService {
editComment(owner: string, resource: URI, comment: Comment, text: string): Promise<void>;
deleteComment(owner: string, resource: URI, comment: Comment): Promise<boolean>;
getComments(resource: URI): Promise<ICommentInfo[]>;
startDraft(owner: string): void;
deleteDraft(owner: string): void;
finishDraft(owner: string): void;
getStartDraftLabel(owner: string): string;
getDeleteDraftLabel(owner: string): string;
getFinishDraftLabel(owner: string): string;
......@@ -145,6 +148,36 @@ export class CommentService extends Disposable implements ICommentService {
return Promise.resolve(false);
}
async startDraft(owner: string): Promise<void> {
const commentProvider = this._commentProviders.get(owner);
if (commentProvider && commentProvider.startDraft) {
return commentProvider.startDraft(CancellationToken.None);
} else {
throw new Error('Not supported');
}
}
async deleteDraft(owner: string): Promise<void> {
const commentProvider = this._commentProviders.get(owner);
if (commentProvider && commentProvider.deleteDraft) {
return commentProvider.deleteDraft(CancellationToken.None);
} else {
throw new Error('Not supported');
}
}
async finishDraft(owner: string): Promise<void> {
const commentProvider = this._commentProviders.get(owner);
if (commentProvider && commentProvider.finishDraft) {
return commentProvider.finishDraft(CancellationToken.None);
} else {
throw new Error('Not supported');
}
}
getStartDraftLabel(owner: string): string | null {
const commentProvider = this._commentProviders.get(owner);
......
......@@ -39,6 +39,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { CommentNode } from 'vs/workbench/parts/comments/electron-browser/commentNode';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ITextModel } from 'vs/editor/common/model';
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
const COLLAPSE_ACTION_CLASS = 'expand-review-action octicon octicon-x';
......@@ -332,8 +333,34 @@ export class ReviewZoneWidget extends ZoneWidget {
this._error = dom.append(this._commentForm, dom.$('.validation-error.hidden'));
const formActions = dom.append(this._commentForm, dom.$('.form-actions'));
this.createCommentWidgetActions(formActions, model);
const button = new Button(formActions);
this._resizeObserver = new MutationObserver(this._refresh.bind(this));
this._resizeObserver.observe(this._bodyElement, {
attributes: true,
childList: true,
characterData: true,
subtree: true
});
if (this._commentThread.collapsibleState === modes.CommentThreadCollapsibleState.Expanded) {
this.show({ lineNumber: lineNumber, column: 1 }, 2);
}
// 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.reply && !this._commentThread.comments.length) {
this._commentEditor.focus();
} else if (this._commentEditor.getModel().getValueLength() > 0) {
if (!dom.hasClass(this._commentForm, 'expand')) {
dom.addClass(this._commentForm, 'expand');
}
this._commentEditor.focus();
}
}
private createCommentWidgetActions(container: HTMLElement, model: ITextModel) {
const button = new Button(container);
attachButtonStyler(button, this.themeService);
button.label = 'Add comment';
......@@ -351,48 +378,55 @@ export class ReviewZoneWidget extends ZoneWidget {
this.createComment(lineNumber);
});
if (this._draftMode !== modes.DraftMode.NotSupported) {
// render draft button
const draftButton = new Button(formActions);
attachButtonStyler(draftButton, this.themeService);
draftButton.label = this.commentService.getStartDraftLabel(this._owner);
if (this._draftMode === modes.DraftMode.NotSupported) {
return;
}
switch (this._draftMode) {
case modes.DraftMode.InDraft:
const deletedraftButton = new Button(container);
attachButtonStyler(deletedraftButton, this.themeService);
deletedraftButton.label = this.commentService.getDeleteDraftLabel(this._owner);
draftButton.enabled = model.getValueLength() > 0;
this._localToDispose.push(this._commentEditor.onDidChangeModelContent(_ => {
if (this._commentEditor.getValue()) {
draftButton.enabled = true;
} else {
draftButton.enabled = false;
}
}));
deletedraftButton.enabled = true;
// draftButton.onDidClick(async () => {
// let lineNumber = this._commentGlyph.getPosition().position.lineNumber;
// this.createComment(lineNumber);
// });
}
deletedraftButton.onDidClick(async () => {
await this.commentService.deleteDraft(this._owner);
});
this._resizeObserver = new MutationObserver(this._refresh.bind(this));
const submitdraftButton = new Button(container);
attachButtonStyler(submitdraftButton, this.themeService);
submitdraftButton.label = this.commentService.getFinishDraftLabel(this._owner);
this._resizeObserver.observe(this._bodyElement, {
attributes: true,
childList: true,
characterData: true,
subtree: true
});
submitdraftButton.enabled = true;
if (this._commentThread.collapsibleState === modes.CommentThreadCollapsibleState.Expanded) {
this.show({ lineNumber: lineNumber, column: 1 }, 2);
}
submitdraftButton.onDidClick(async () => {
await this.commentService.finishDraft(this._owner);
});
// 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.reply && !this._commentThread.comments.length) {
this._commentEditor.focus();
} else if (this._commentEditor.getModel().getValueLength() > 0) {
if (!dom.hasClass(this._commentForm, 'expand')) {
dom.addClass(this._commentForm, 'expand');
}
this._commentEditor.focus();
break;
case modes.DraftMode.NotInDraft:
// render draft button
const draftButton = new Button(container);
attachButtonStyler(draftButton, this.themeService);
draftButton.label = this.commentService.getStartDraftLabel(this._owner);
draftButton.enabled = model.getValueLength() > 0;
this._localToDispose.push(this._commentEditor.onDidChangeModelContent(_ => {
if (this._commentEditor.getValue()) {
draftButton.enabled = true;
} else {
draftButton.enabled = false;
}
}));
draftButton.onDidClick(async () => {
await this.commentService.startDraft(this._owner);
let lineNumber = this._commentGlyph.getPosition().position.lineNumber;
await this.createComment(lineNumber);
});
break;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册