diff --git a/comment-sample/resources/reactions/confused.png b/comment-sample/resources/reactions/confused.png new file mode 100644 index 000000000..77734d403 Binary files /dev/null and b/comment-sample/resources/reactions/confused.png differ diff --git a/comment-sample/resources/reactions/eyes.png b/comment-sample/resources/reactions/eyes.png new file mode 100644 index 000000000..b303dee34 Binary files /dev/null and b/comment-sample/resources/reactions/eyes.png differ diff --git a/comment-sample/resources/reactions/heart.png b/comment-sample/resources/reactions/heart.png new file mode 100644 index 000000000..277e3e8d4 Binary files /dev/null and b/comment-sample/resources/reactions/heart.png differ diff --git a/comment-sample/resources/reactions/hooray.png b/comment-sample/resources/reactions/hooray.png new file mode 100644 index 000000000..c3cce94d5 Binary files /dev/null and b/comment-sample/resources/reactions/hooray.png differ diff --git a/comment-sample/resources/reactions/laugh.png b/comment-sample/resources/reactions/laugh.png new file mode 100644 index 000000000..a3abe0090 Binary files /dev/null and b/comment-sample/resources/reactions/laugh.png differ diff --git a/comment-sample/resources/reactions/rocket.png b/comment-sample/resources/reactions/rocket.png new file mode 100644 index 000000000..ea8fbcce7 Binary files /dev/null and b/comment-sample/resources/reactions/rocket.png differ diff --git a/comment-sample/resources/reactions/thumbs_down.png b/comment-sample/resources/reactions/thumbs_down.png new file mode 100644 index 000000000..ee2c24ee8 Binary files /dev/null and b/comment-sample/resources/reactions/thumbs_down.png differ diff --git a/comment-sample/resources/reactions/thumbs_up.png b/comment-sample/resources/reactions/thumbs_up.png new file mode 100644 index 000000000..bcca0f1ba Binary files /dev/null and b/comment-sample/resources/reactions/thumbs_up.png differ diff --git a/comment-sample/src/extension.ts b/comment-sample/src/extension.ts index 7936614b7..4780a9653 100644 --- a/comment-sample/src/extension.ts +++ b/comment-sample/src/extension.ts @@ -1,6 +1,65 @@ 'use strict'; import * as vscode from 'vscode'; +import * as path from 'path'; +class Resource { + static icons: any; + + static initialize(context: vscode.ExtensionContext) { + Resource.icons = { + reactions: { + THUMBS_UP: context.asAbsolutePath(path.join('resources', 'reactions', 'thumbs_up.png')), + THUMBS_DOWN: context.asAbsolutePath(path.join('resources', 'reactions', 'thumbs_down.png')), + CONFUSED: context.asAbsolutePath(path.join('resources', 'reactions', 'confused.png')), + EYES: context.asAbsolutePath(path.join('resources', 'reactions', 'eyes.png')), + HEART: context.asAbsolutePath(path.join('resources', 'reactions', 'heart.png')), + HOORAY: context.asAbsolutePath(path.join('resources', 'reactions', 'hooray.png')), + LAUGH: context.asAbsolutePath(path.join('resources', 'reactions', 'laugh.png')), + ROCKET: context.asAbsolutePath(path.join('resources', 'reactions', 'rocket.png')), + } + }; + } +} + +function getReactionGroup(): { title: string; label: string; icon: vscode.Uri }[] { + const ret = [ + { + title: 'CONFUSED', + label: '😕', + icon: Resource.icons.reactions.CONFUSED + }, { + title: 'EYES', + label: '👀', + icon: Resource.icons.reactions.EYES + }, { + title: 'HEART', + label: '❤️', + icon: Resource.icons.reactions.HEART + }, { + title: 'HOORAY', + label: '🎉', + icon: Resource.icons.reactions.HOORAY + }, { + title: 'LAUGH', + label: '😄', + icon: Resource.icons.reactions.LAUGH + }, { + title: 'ROCKET', + label: '🚀', + icon: Resource.icons.reactions.ROCKET + }, { + title: 'THUMBS_DOWN', + label: '👎', + icon: Resource.icons.reactions.THUMBS_DOWN + }, { + title: 'THUMBS_UP', + label: '👍', + icon: Resource.icons.reactions.THUMBS_UP + } + ]; + + return ret; +} let commentId = 1; @@ -11,7 +70,8 @@ class NoteComment implements vscode.Comment { public body: string | vscode.MarkdownString, public mode: vscode.CommentMode, public author: vscode.CommentAuthorInformation, - public parent?: vscode.CommentThread, + public parent: vscode.CommentThread, + public reactions: vscode.CommentReaction[] = [], public contextValue?: string ) { this.id = ++commentId; @@ -19,10 +79,30 @@ class NoteComment implements vscode.Comment { } export function activate(context: vscode.ExtensionContext) { + Resource.initialize(context); // A `CommentController` is able to provide comments for documents. const commentController = vscode.comments.createCommentController('comment-sample', 'Comment API Sample'); context.subscriptions.push(commentController); + commentController.reactionHandler = async (c: vscode.Comment, reaction: vscode.CommentReaction) => { + const comment = c as NoteComment; + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.map(cmt => { + if ((cmt as NoteComment).id === comment.id) { + const index = cmt.reactions!.findIndex(r => r.label === reaction.label); + cmt.reactions!.splice(index, 1, { + ...reaction, + count: reaction.authorHasReacted ? reaction.count - 1 : reaction.count + 1, + authorHasReacted: !reaction.authorHasReacted, + }); + } + + return cmt; + }); + } // A `CommentingRangeProvider` controls where gutter decorations that allow adding comments are shown commentController.commentingRangeProvider = { provideCommentingRanges: (document: vscode.TextDocument, token: vscode.CancellationToken) => { @@ -130,7 +210,19 @@ export function activate(context: vscode.ExtensionContext) { function replyNote(reply: vscode.CommentReply) { const thread = reply.thread; - const newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'vscode' }, thread, thread.comments.length ? 'canDelete' : undefined); + const newComment = new NoteComment( + reply.text, + vscode.CommentMode.Preview, + { name: 'vscode' }, + thread, + getReactionGroup().map(reaction => ({ + iconPath: reaction.icon, + label: reaction.label, + count: 0, + authorHasReacted: false, + })), + thread.comments.length ? 'canDelete' : undefined + ); if (thread.contextValue === 'draft') { newComment.label = 'pending'; }