From d13c018d7898e1e1c332aa3c9bcf7dd97b7b0155 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 17 May 2019 16:40:30 -0700 Subject: [PATCH 1/7] new api --- comment-sample/package.json | 65 ++++++- comment-sample/resources/close.svg | 1 + comment-sample/resources/close_inverse.svg | 1 + comment-sample/resources/edit.svg | 1 + comment-sample/resources/edit_inverse.svg | 1 + comment-sample/src/extension.ts | 119 ++++--------- .../src/typings/vscode.proposed.d.ts | 162 ++++-------------- 7 files changed, 130 insertions(+), 220 deletions(-) create mode 100644 comment-sample/resources/close.svg create mode 100644 comment-sample/resources/close_inverse.svg create mode 100755 comment-sample/resources/edit.svg create mode 100755 comment-sample/resources/edit_inverse.svg diff --git a/comment-sample/package.json b/comment-sample/package.json index 382d83c1..6d3b1796 100644 --- a/comment-sample/package.json +++ b/comment-sample/package.json @@ -19,15 +19,35 @@ "commands": [ { "command": "mywiki.createNote", - "title": "Comment API: Create a comment thread" + "title": "Create Note" }, { - "command": "mywiki.createComment", - "title": "Comment API: Reply to a comment thread" + "command": "mywiki.replyNote", + "title": "Reply" + }, + { + "command": "mywiki.editNote", + "title": "Edit", + "icon":{ + "dark": "resources/edit_inverse.svg", + "light": "resources/edit.svg" + } }, { "command": "mywiki.deleteNote", - "title": "Comment API: Delete a comment thread" + "title": "Delete", + "icon":{ + "dark": "resources/close_inverse.svg", + "light": "resources/close.svg" + } + }, + { + "command": "mywiki.deleteNoteComment", + "title": "Delete", + "icon":{ + "dark": "resources/close_inverse.svg", + "light": "resources/close.svg" + } } ], "menus": { @@ -37,12 +57,47 @@ "when": "false" }, { - "command": "mywiki.createComment", + "command": "mywiki.replyNote", "when": "false" }, { "command": "mywiki.deleteNote", "when": "false" + }, + { + "command": "mywiki.deleteNoteComment", + "when": "false" + } + ], + "commentThread/title": [ + { + "command": "mywiki.deleteNote", + "group": "navigation", + "when": "!commentThreadIsEmpty" + } + ], + "commentThread/actions": [ + { + "command": "mywiki.createNote", + "precondition": "commentIsEmpty", + "group": "navigation", + "when": "commentThreadIsEmpty" + }, + { + "command": "mywiki.replyNote", + "precondition": "commentIsEmpty", + "group": "navigation", + "when": "!commentThreadIsEmpty" + } + ], + "comment/title": [ + { + "command": "mywiki.editNote", + "group": "group@1" + }, + { + "command": "mywiki.deleteNoteComment", + "group": "group@2" } ] } diff --git a/comment-sample/resources/close.svg b/comment-sample/resources/close.svg new file mode 100644 index 00000000..fde34404 --- /dev/null +++ b/comment-sample/resources/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/comment-sample/resources/close_inverse.svg b/comment-sample/resources/close_inverse.svg new file mode 100644 index 00000000..d88aa121 --- /dev/null +++ b/comment-sample/resources/close_inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/comment-sample/resources/edit.svg b/comment-sample/resources/edit.svg new file mode 100755 index 00000000..ecde9240 --- /dev/null +++ b/comment-sample/resources/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/comment-sample/resources/edit_inverse.svg b/comment-sample/resources/edit_inverse.svg new file mode 100755 index 00000000..da956cb2 --- /dev/null +++ b/comment-sample/resources/edit_inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index e57d6c3f..d7fe2855 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -2,8 +2,19 @@ import * as vscode from 'vscode'; -let threadId = 0; -let commentId = 0; +let commentId = 1; + +class NoteComment implements vscode.Comment { + id: number; + constructor( + public body: string | vscode.MarkdownString, + public mode: vscode.CommentMode, + public author: vscode.CommentAuthorInformation, + public parent?: vscode.CommentThread + ) { + this.id = ++commentId; + } +} export function activate(context: vscode.ExtensionContext) { // A `CommentController` is able to provide comments for documents. @@ -18,92 +29,34 @@ export function activate(context: vscode.ExtensionContext) { } }; - commentController.template = { - label: 'Create New Note:', - acceptInputCommand: { - title: 'Create Note', - command: 'mywiki.createNote', - // Command is responsible for arguments - arguments: [ - commentController - ] - } - }; + let replyNote = (reply: vscode.CommentReply) => { + let thread = reply.thread; + let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); + thread.comments = [...thread.comments, newComment]; + } - // register `mywiki.createNote` command - context.subscriptions.push(vscode.commands.registerCommand('mywiki.createNote', (commentController: vscode.CommentController, thread: vscode.CommentThread | undefined) => { - if (commentController.inputBox) { - if (!thread) { - // the comment thread is created from comment thread template - let thread = commentController.createCommentThread(`${++threadId}`, commentController.inputBox.resource, commentController.inputBox.range, []); - // by default, a comment thread is collapsed, for newly created empty comment thread, we want to expand it and users can start commenting immediately - thread.collapsibleState = vscode.CommentThreadCollapsibleState.Expanded; - - // In this example, we call it `Create New Note` while for GH PR case, we can call it `Start Review` or `Start New Converstation` - let text = commentController.inputBox.value; - let markedString = new vscode.MarkdownString(text); - let newComment = new vscode.Comment(`${++commentId}`, markedString, 'vscode'); - - thread.comments = [newComment]; - thread.label = 'Participants: vscode'; - - // We will render all `acceptInputCommands` as Actions on the bottom of Comment Widget in the editor. - thread.acceptInputCommand = { - title: 'Create Comment', - command: 'mywiki.createComment', - arguments: [ - commentController, - thread - ] - }; - - thread.deleteCommand = { - title: 'Delete Note', - command: 'mywiki.deleteNote', - arguments: [ - thread - ] - }; - - // Lastly, we want to clear the textarea in Comment Widget. - commentController.inputBox.value = ''; - } else { - // Read text from the focused textarea in the Comment Widget. - let text = commentController.inputBox.value; - let markedString = new vscode.MarkdownString(text); - let newComment = new vscode.Comment(`${++commentId}`, markedString, 'vscode'); - - thread.comments = [newComment]; - thread.label = 'Participants: vscode'; - - // After we create the new comment thread, we may want to update the actions on the Comment Widget. - thread.acceptInputCommand = { - title: 'Create Comment', - command: 'mywiki.createComment', - arguments: [ - commentController, - thread - ] - }; - - // Lastly, we want to clear the textarea in Comment Widget. - commentController.inputBox.value = ''; - } - } - })); - - context.subscriptions.push(vscode.commands.registerCommand('mywiki.createComment', (commentController: vscode.CommentController, thread: vscode.CommentThread) => { - if (commentController.inputBox) { - let text = commentController.inputBox.value; - let markedString = new vscode.MarkdownString(text); - let newComment = new vscode.Comment(`${++commentId}`, markedString, 'vscode'); - - thread.comments = [...thread.comments, newComment]; - commentController.inputBox.value = ''; + context.subscriptions.push(vscode.commands.registerCommand('mywiki.createNote', replyNote)); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.replyNote', replyNote)); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNoteComment', (comment: NoteComment) => { + let thread = comment.parent; + thread.comments = thread.comments.filter((cmt: NoteComment) => cmt.id == comment.id); + + if (thread.comments.length === 0) { + thread.dispose(); } })); context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNote', (thread: vscode.CommentThread) => { thread.dispose(); })); + + context.subscriptions.push(vscode.commands.registerCommand('mywiki.editNote', (comment: NoteComment) => { + comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { + if (cmt.id === comment.id) { + cmt.mode = vscode.CommentMode.Editing; + } + + return cmt; + }); + })); } diff --git a/comment-sample/src/typings/vscode.proposed.d.ts b/comment-sample/src/typings/vscode.proposed.d.ts index ef1b2c19..22d0b905 100644 --- a/comment-sample/src/typings/vscode.proposed.d.ts +++ b/comment-sample/src/typings/vscode.proposed.d.ts @@ -35,15 +35,15 @@ declare module 'vscode' { Expanded = 1 } + export enum CommentMode { + Editing = 0, + Preview = 1 + } + /** * A collection of [comments](#Comment) representing a conversation at a particular range in a document. */ export interface CommentThread { - /** - * A unique identifier of the comment thread. - */ - readonly id: string; - /** * The uri of the document the thread has been created on. */ @@ -58,7 +58,7 @@ declare module 'vscode' { /** * The ordered comments of the thread. */ - comments: Comment[]; + comments: ReadonlyArray; /** * Whether the thread should be collapsed or expanded when opening the document. @@ -71,28 +71,6 @@ declare module 'vscode' { */ label?: string; - /** - * Optional accept input command - * - * `acceptInputCommand` is the default action rendered on Comment Widget, which is always placed rightmost. - * This command will be invoked when users the user accepts the value in the comment editor. - * This command will disabled when the comment editor is empty. - */ - acceptInputCommand?: Command; - - /** - * Optional additonal commands. - * - * `additionalCommands` are the secondary actions rendered on Comment Widget. - */ - additionalCommands?: Command[]; - - /** - * The command to be executed when users try to delete the comment thread. Currently, this is only called - * when the user collapses a comment thread that has no comments in it. - */ - deleteCommand?: Command; - /** * Dispose this comment thread. * @@ -102,76 +80,47 @@ declare module 'vscode' { } /** - * A comment is displayed within the editor or the Comments Panel, depending on how it is provided. + * Author information of a [comment](#Comment) */ - export class Comment { + export interface CommentAuthorInformation { /** - * The id of the comment + * The display name of the author of the comment */ - readonly id: string; + name: string; /** - * The human-readable comment body + * The optional icon path for the author */ - readonly body: MarkdownString; - - /** - * The display name of the user who created the comment - */ - readonly userName: string; - - /** - * Optional label describing the [Comment](#Comment) - * Label will be rendered next to userName if exists. - */ - readonly label?: string; - - /** - * The icon path for the user who created the comment - */ - readonly userIconPath?: Uri; - - /** - * The command to be executed if the comment is selected in the Comments Panel - */ - readonly selectCommand?: Command; - - /** - * The command to be executed when users try to save the edits to the comment - */ - readonly editCommand?: Command; - - /** - * The command to be executed when users try to delete the comment - */ - readonly deleteCommand?: Command; - - /** - * @param id The id of the comment - * @param body The human-readable comment body - * @param userName The display name of the user who created the comment - */ - constructor(id: string, body: MarkdownString, userName: string); + iconPath?: Uri; } /** - * The comment input box in Comment Widget. + * A comment is displayed within the editor or the Comments Panel, depending on how it is provided. */ - export interface CommentInputBox { + export interface Comment { /** - * Setter and getter for the contents of the comment input box + * The human-readable comment body */ - value: string; + body: string | MarkdownString; + + mode: CommentMode; /** - * The uri of the document comment input box has been created on + * The author information of the comment */ - resource: Uri; + author: CommentAuthorInformation; /** - * The range the comment input box is located within the document + * Optional label describing the [Comment](#Comment) + * Label will be rendered next to authorName if exists. */ - range: Range; + label?: string; + } + + export interface CommentReply { + thread: CommentThread; + + text: string; } /** @@ -184,38 +133,6 @@ declare module 'vscode' { provideCommentingRanges(document: TextDocument, token: CancellationToken): ProviderResult; } - /** - * Comment thread template for new comment thread creation. - */ - export interface CommentThreadTemplate { - /** - * The human-readable label describing the [Comment Thread](#CommentThread) - */ - readonly label: string; - - /** - * Optional accept input command - * - * `acceptInputCommand` is the default action rendered on Comment Widget, which is always placed rightmost. - * This command will be invoked when users the user accepts the value in the comment editor. - * This command will disabled when the comment editor is empty. - */ - readonly acceptInputCommand?: Command; - - /** - * Optional additonal commands. - * - * `additionalCommands` are the secondary actions rendered on Comment Widget. - */ - readonly additionalCommands?: Command[]; - - /** - * The command to be executed when users try to delete the comment thread. Currently, this is only called - * when the user collapses a comment thread that has no comments in it. - */ - readonly deleteCommand?: Command; - } - /** * A comment controller is able to provide [comments](#CommentThread) support to the editor and * provide users various ways to interact with comments. @@ -231,25 +148,6 @@ declare module 'vscode' { */ readonly label: string; - /** - * The active [comment input box](#CommentInputBox) or `undefined`. The active `inputBox` is the input box of - * the comment thread widget that currently has focus. It's `undefined` when the focus is not in any CommentInputBox. - */ - readonly inputBox: CommentInputBox | undefined; - - /** - * Optional comment thread template information. - * - * The comment controller will use this information to create the comment widget when users attempt to create new comment thread - * from the gutter or command palette. - * - * When users run `CommentThreadTemplate.acceptInputCommand` or `CommentThreadTemplate.additionalCommands`, extensions should create - * the approriate [CommentThread](#CommentThread). - * - * If not provided, users won't be able to create new comment threads in the editor. - */ - template?: CommentThreadTemplate; - /** * Optional commenting range provider. Provide a list [ranges](#Range) which support commenting to any given resource uri. * @@ -266,7 +164,7 @@ declare module 'vscode' { * @param range The range the comment thread is located within the document. * @param comments The ordered comments of the thread. */ - createCommentThread(id: string, resource: Uri, range: Range, comments: Comment[]): CommentThread; + createCommentThread(uri: Uri, range: Range, comments: Comment[]): CommentThread; /** * Dispose this comment controller. From be77259d24007975d40d9270c96a484101fcef3d Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 17 May 2019 18:31:33 -0700 Subject: [PATCH 2/7] Save comment --- comment-sample/package.json | 18 +++++++++++++++++ comment-sample/src/extension.ts | 36 +++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/comment-sample/package.json b/comment-sample/package.json index 6d3b1796..752c358d 100644 --- a/comment-sample/package.json +++ b/comment-sample/package.json @@ -48,6 +48,14 @@ "dark": "resources/close_inverse.svg", "light": "resources/close.svg" } + }, + { + "command": "mywiki.saveNote", + "title": "Save" + }, + { + "command": "mywiki.cancelsaveNote", + "title": "Cancel" } ], "menus": { @@ -99,6 +107,16 @@ "command": "mywiki.deleteNoteComment", "group": "group@2" } + ], + "comment/actions": [ + { + "command": "mywiki.cancelsaveNote", + "group": "group@1" + }, + { + "command": "mywiki.saveNote", + "group": "group@2" + } ] } }, diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index d7fe2855..65c54775 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -29,17 +29,21 @@ export function activate(context: vscode.ExtensionContext) { } }; - let replyNote = (reply: vscode.CommentReply) => { + context.subscriptions.push(vscode.commands.registerCommand('mywiki.createNote', (reply: vscode.CommentReply) => { let thread = reply.thread; let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); thread.comments = [...thread.comments, newComment]; - } - - context.subscriptions.push(vscode.commands.registerCommand('mywiki.createNote', replyNote)); - context.subscriptions.push(vscode.commands.registerCommand('mywiki.replyNote', replyNote)); + })); + + context.subscriptions.push(vscode.commands.registerCommand('mywiki.replyNote', (reply: vscode.CommentReply) => { + let thread = reply.thread; + let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); + thread.comments = [...thread.comments, newComment]; + })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNoteComment', (comment: NoteComment) => { let thread = comment.parent; - thread.comments = thread.comments.filter((cmt: NoteComment) => cmt.id == comment.id); + thread.comments = thread.comments.filter((cmt: NoteComment) => cmt.id !== comment.id); if (thread.comments.length === 0) { thread.dispose(); @@ -50,6 +54,26 @@ export function activate(context: vscode.ExtensionContext) { thread.dispose(); })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.cancelsaveNote', (comment: NoteComment) => { + comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { + if (cmt.id === comment.id) { + cmt.mode = vscode.CommentMode.Preview; + } + + return cmt; + }); + })); + + context.subscriptions.push(vscode.commands.registerCommand('mywiki.saveNote', (comment: NoteComment) => { + comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { + if (cmt.id === comment.id) { + cmt.mode = vscode.CommentMode.Preview; + } + + return cmt; + }); + })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.editNote', (comment: NoteComment) => { comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { if (cmt.id === comment.id) { From 78e140cbb0b56094f3097aa2c3e360488ce6b664 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 17 May 2019 18:36:36 -0700 Subject: [PATCH 3/7] start draft --- comment-sample/package.json | 9 +++++++++ comment-sample/src/extension.ts | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/comment-sample/package.json b/comment-sample/package.json index 752c358d..4bda1b02 100644 --- a/comment-sample/package.json +++ b/comment-sample/package.json @@ -56,6 +56,10 @@ { "command": "mywiki.cancelsaveNote", "title": "Cancel" + }, + { + "command": "mywiki.startDraft", + "title": "Start draft" } ], "menus": { @@ -96,6 +100,11 @@ "precondition": "commentIsEmpty", "group": "navigation", "when": "!commentThreadIsEmpty" + }, + { + "command": "mywiki.startDraft", + "precondition": "commentIsEmpty", + "group": "navigation" } ], "comment/title": [ diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index 65c54775..604cfd0f 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -6,6 +6,7 @@ let commentId = 1; class NoteComment implements vscode.Comment { id: number; + label: string | undefined; constructor( public body: string | vscode.MarkdownString, public mode: vscode.CommentMode, @@ -41,6 +42,13 @@ export function activate(context: vscode.ExtensionContext) { thread.comments = [...thread.comments, newComment]; })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.startDraft', (reply: vscode.CommentReply) => { + let thread = reply.thread; + let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); + newComment.label = 'pending'; + thread.comments = [...thread.comments, newComment]; + })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNoteComment', (comment: NoteComment) => { let thread = comment.parent; thread.comments = thread.comments.filter((cmt: NoteComment) => cmt.id !== comment.id); From cfcdec6f416dede956b494e253602a817fe79099 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 17 May 2019 18:39:54 -0700 Subject: [PATCH 4/7] finish draft --- comment-sample/package.json | 13 ++++++++++++- comment-sample/src/extension.ts | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/comment-sample/package.json b/comment-sample/package.json index 4bda1b02..8222811e 100644 --- a/comment-sample/package.json +++ b/comment-sample/package.json @@ -60,6 +60,10 @@ { "command": "mywiki.startDraft", "title": "Start draft" + }, + { + "command": "mywiki.finishDraft", + "title": "Finish draft" } ], "menus": { @@ -104,7 +108,14 @@ { "command": "mywiki.startDraft", "precondition": "commentIsEmpty", - "group": "navigation" + "group": "navigation", + "when": "!inDraft" + }, + { + "command": "mywiki.finishDraft", + "precondition": "commentIsEmpty", + "group": "navigation", + "when": "inDraft" } ], "comment/title": [ diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index 604cfd0f..0c6c0247 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -21,6 +21,7 @@ export function activate(context: vscode.ExtensionContext) { // A `CommentController` is able to provide comments for documents. const commentController = vscode.comment.createCommentController('comment-sample', 'Comment API Sample'); context.subscriptions.push(commentController); + vscode.commands.executeCommand('setContext', 'inDraft', false); // commenting range provider commentController.commentingRangeProvider = { @@ -43,12 +44,24 @@ export function activate(context: vscode.ExtensionContext) { })); context.subscriptions.push(vscode.commands.registerCommand('mywiki.startDraft', (reply: vscode.CommentReply) => { + vscode.commands.executeCommand('setContext', 'inDraft', true); let thread = reply.thread; let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); newComment.label = 'pending'; thread.comments = [...thread.comments, newComment]; })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.finishDraft', (reply: vscode.CommentReply) => { + vscode.commands.executeCommand('setContext', 'inDraft', false); + + let thread = reply.thread; + let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); + thread.comments = [...thread.comments, newComment].map(comment => { + comment.label = undefined; + return comment; + }); + })); + context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNoteComment', (comment: NoteComment) => { let thread = comment.parent; thread.comments = thread.comments.filter((cmt: NoteComment) => cmt.id !== comment.id); From 21f9ceff1c25c3cb508e7c662874f8866d91b7b8 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 17 May 2019 18:52:59 -0700 Subject: [PATCH 5/7] extract the note --- comment-sample/src/extension.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index 0c6c0247..752f64b9 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -32,15 +32,11 @@ export function activate(context: vscode.ExtensionContext) { }; context.subscriptions.push(vscode.commands.registerCommand('mywiki.createNote', (reply: vscode.CommentReply) => { - let thread = reply.thread; - let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); - thread.comments = [...thread.comments, newComment]; + replyNote(reply); })); context.subscriptions.push(vscode.commands.registerCommand('mywiki.replyNote', (reply: vscode.CommentReply) => { - let thread = reply.thread; - let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); - thread.comments = [...thread.comments, newComment]; + replyNote(reply); })); context.subscriptions.push(vscode.commands.registerCommand('mywiki.startDraft', (reply: vscode.CommentReply) => { @@ -104,4 +100,10 @@ export function activate(context: vscode.ExtensionContext) { return cmt; }); })); + + function replyNote(reply: vscode.CommentReply) { + let thread = reply.thread; + let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); + thread.comments = [...thread.comments, newComment]; + } } From bc3a287d6ac043f4ef4c671dd83a426b1104d7bf Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 21 May 2019 12:03:32 -0700 Subject: [PATCH 6/7] update comments namespace --- comment-sample/package.json | 15 ++++----- comment-sample/src/extension.ts | 32 +++++++++---------- .../src/typings/vscode.proposed.d.ts | 2 +- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/comment-sample/package.json b/comment-sample/package.json index 8222811e..68f699f1 100644 --- a/comment-sample/package.json +++ b/comment-sample/package.json @@ -85,40 +85,39 @@ "when": "false" } ], - "commentThread/title": [ + "comments/commentThread/title": [ { "command": "mywiki.deleteNote", "group": "navigation", "when": "!commentThreadIsEmpty" } ], - "commentThread/actions": [ + "comments/commentThread/actions": [ { "command": "mywiki.createNote", - "precondition": "commentIsEmpty", "group": "navigation", + "precondition": "!commentIsEmpty", "when": "commentThreadIsEmpty" }, { "command": "mywiki.replyNote", - "precondition": "commentIsEmpty", "group": "navigation", + "precondition": "!commentIsEmpty", "when": "!commentThreadIsEmpty" }, { "command": "mywiki.startDraft", - "precondition": "commentIsEmpty", "group": "navigation", + "precondition": "!commentIsEmpty", "when": "!inDraft" }, { "command": "mywiki.finishDraft", - "precondition": "commentIsEmpty", "group": "navigation", "when": "inDraft" } ], - "comment/title": [ + "comments/comment/title": [ { "command": "mywiki.editNote", "group": "group@1" @@ -128,7 +127,7 @@ "group": "group@2" } ], - "comment/actions": [ + "comments/comment/actions": [ { "command": "mywiki.cancelsaveNote", "group": "group@1" diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index 752f64b9..9beb9f47 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -19,7 +19,7 @@ class NoteComment implements vscode.Comment { export function activate(context: vscode.ExtensionContext) { // A `CommentController` is able to provide comments for documents. - const commentController = vscode.comment.createCommentController('comment-sample', 'Comment API Sample'); + const commentController = vscode.comments.createCommentController('comment-sample', 'Comment API Sample'); context.subscriptions.push(commentController); vscode.commands.executeCommand('setContext', 'inDraft', false); @@ -30,15 +30,15 @@ export function activate(context: vscode.ExtensionContext) { return [new vscode.Range(0, 0, lineCount - 1, 0)]; } }; - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.createNote', (reply: vscode.CommentReply) => { replyNote(reply); })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.replyNote', (reply: vscode.CommentReply) => { replyNote(reply); })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.startDraft', (reply: vscode.CommentReply) => { vscode.commands.executeCommand('setContext', 'inDraft', true); let thread = reply.thread; @@ -46,7 +46,7 @@ export function activate(context: vscode.ExtensionContext) { newComment.label = 'pending'; thread.comments = [...thread.comments, newComment]; })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.finishDraft', (reply: vscode.CommentReply) => { vscode.commands.executeCommand('setContext', 'inDraft', false); @@ -57,11 +57,11 @@ export function activate(context: vscode.ExtensionContext) { return comment; }); })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNoteComment', (comment: NoteComment) => { let thread = comment.parent; thread.comments = thread.comments.filter((cmt: NoteComment) => cmt.id !== comment.id); - + if (thread.comments.length === 0) { thread.dispose(); } @@ -70,33 +70,33 @@ export function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand('mywiki.deleteNote', (thread: vscode.CommentThread) => { thread.dispose(); })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.cancelsaveNote', (comment: NoteComment) => { comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { - if (cmt.id === comment.id) { + if (cmt.id === comment.id) { cmt.mode = vscode.CommentMode.Preview; } - + return cmt; }); })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.saveNote', (comment: NoteComment) => { comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { - if (cmt.id === comment.id) { + if (cmt.id === comment.id) { cmt.mode = vscode.CommentMode.Preview; } - + return cmt; }); })); - + context.subscriptions.push(vscode.commands.registerCommand('mywiki.editNote', (comment: NoteComment) => { comment.parent.comments = comment.parent.comments.map((cmt: NoteComment) => { - if (cmt.id === comment.id) { + if (cmt.id === comment.id) { cmt.mode = vscode.CommentMode.Editing; } - + return cmt; }); })); diff --git a/comment-sample/src/typings/vscode.proposed.d.ts b/comment-sample/src/typings/vscode.proposed.d.ts index 22d0b905..308d5479 100644 --- a/comment-sample/src/typings/vscode.proposed.d.ts +++ b/comment-sample/src/typings/vscode.proposed.d.ts @@ -175,7 +175,7 @@ declare module 'vscode' { dispose(): void; } - namespace comment { + namespace comments { /** * Creates a new [comment controller](#CommentController) instance. * From 8d6054d93232f6d3dbf266afa84a15b94ebf0833 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Thu, 23 May 2019 09:21:34 -0700 Subject: [PATCH 7/7] update context key --- comment-sample/package.json | 20 +++++----- comment-sample/src/extension.ts | 3 +- .../src/typings/vscode.proposed.d.ts | 40 +++++++++++++++++++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/comment-sample/package.json b/comment-sample/package.json index 68f699f1..bae17803 100644 --- a/comment-sample/package.json +++ b/comment-sample/package.json @@ -92,29 +92,29 @@ "when": "!commentThreadIsEmpty" } ], - "comments/commentThread/actions": [ + "comments/commentThread/context": [ { "command": "mywiki.createNote", - "group": "navigation", + "group": "inline", "precondition": "!commentIsEmpty", "when": "commentThreadIsEmpty" }, { "command": "mywiki.replyNote", - "group": "navigation", + "group": "inline", "precondition": "!commentIsEmpty", "when": "!commentThreadIsEmpty" }, { "command": "mywiki.startDraft", - "group": "navigation", + "group": "inline", "precondition": "!commentIsEmpty", - "when": "!inDraft" + "when": "commentThread != draft" }, { "command": "mywiki.finishDraft", - "group": "navigation", - "when": "inDraft" + "group": "inline", + "when": "commentThread == draft" } ], "comments/comment/title": [ @@ -127,14 +127,14 @@ "group": "group@2" } ], - "comments/comment/actions": [ + "comments/comment/context": [ { "command": "mywiki.cancelsaveNote", - "group": "group@1" + "group": "inline@1" }, { "command": "mywiki.saveNote", - "group": "group@2" + "group": "inline@2" } ] } diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index 9beb9f47..e946c2d3 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -40,8 +40,8 @@ export function activate(context: vscode.ExtensionContext) { })); context.subscriptions.push(vscode.commands.registerCommand('mywiki.startDraft', (reply: vscode.CommentReply) => { - vscode.commands.executeCommand('setContext', 'inDraft', true); let thread = reply.thread; + thread.contextValue = 'draft'; let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); newComment.label = 'pending'; thread.comments = [...thread.comments, newComment]; @@ -51,6 +51,7 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.executeCommand('setContext', 'inDraft', false); let thread = reply.thread; + thread.collapsibleState = undefined; let newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread); thread.comments = [...thread.comments, newComment].map(comment => { comment.label = undefined; diff --git a/comment-sample/src/typings/vscode.proposed.d.ts b/comment-sample/src/typings/vscode.proposed.d.ts index 308d5479..39b19ece 100644 --- a/comment-sample/src/typings/vscode.proposed.d.ts +++ b/comment-sample/src/typings/vscode.proposed.d.ts @@ -70,6 +70,26 @@ declare module 'vscode' { * The optional human-readable label describing the [Comment Thread](#CommentThread) */ label?: string; + + /** + * Context value of the comment thread. This can be used to contribute thread specific actions. + * For example, a comment thread is given a context value as `editable`. When contributing actions to `comments/commentThread/title` + * using `menus` extension point, you can specify context value for key `commentThread` in `when` expression like `commentThread == editable`. + * ``` + * "contributes": { + * "menus": { + * "comments/commentThread/title": [ + * { + * "command": "extension.deleteCommentThread", + * "when": "commentThread == editable" + * } + * ] + * } + * } + * ``` + * This will show action `extension.deleteCommentThread` only for comment threads with `contextValue` is `editable`. + */ + contextValue?: string; /** * Dispose this comment thread. @@ -115,6 +135,26 @@ declare module 'vscode' { * Label will be rendered next to authorName if exists. */ label?: string; + + /** + * Context value of the comment. This can be used to contribute comment specific actions. + * For example, a comment is given a context value as `editable`. When contributing actions to `comments/comment/title` + * using `menus` extension point, you can specify context value for key `comment` in `when` expression like `comment == editable`. + * ``` + * "contributes": { + * "menus": { + * "comments/comment/title": [ + * { + * "command": "extension.deleteComment", + * "when": "comment == editable" + * } + * ] + * } + * } + * ``` + * This will show action `extension.deleteComment` only for comments with `contextValue` is `editable`. + */ + contextValue?: string; } export interface CommentReply {