From 646bb51ab271f9f2bb5eeba55d64d46c1d65f21b Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 18 Dec 2023 16:57:34 +0100 Subject: [PATCH] Add comment reactors to comment reactions (#201132) Add comment reactors proposal Part of #201131 --- src/vs/editor/common/languages.ts | 1 + .../workbench/api/common/extHostComments.ts | 8 ++- .../contrib/comments/browser/commentNode.ts | 2 +- .../comments/browser/reactionsAction.ts | 49 +++++++++++++------ .../common/extensionsApiProposals.ts | 1 + .../vscode.proposed.commentReactor.d.ts | 13 +++++ 6 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 src/vscode-dts/vscode.proposed.commentReactor.d.ts diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index a836db5afad..7a362c9d9d2 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1778,6 +1778,7 @@ export interface CommentReaction { readonly count?: number; readonly hasReacted?: boolean; readonly canEdit?: boolean; + readonly reactors?: readonly string[]; } /** diff --git a/src/vs/workbench/api/common/extHostComments.ts b/src/vs/workbench/api/common/extHostComments.ts index cf8d72d05bd..04541a1decb 100644 --- a/src/vs/workbench/api/common/extHostComments.ts +++ b/src/vs/workbench/api/common/extHostComments.ts @@ -673,6 +673,10 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo checkProposedApiEnabled(extension, 'commentsDraftState'); } + if (vscodeComment.reactions?.some(reaction => reaction.reactors !== undefined)) { + checkProposedApiEnabled(extension, 'commentReactor'); + } + return { mode: vscodeComment.mode, contextValue: vscodeComment.contextValue, @@ -693,6 +697,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo iconPath: reaction.iconPath ? extHostTypeConverter.pathOrURIToURI(reaction.iconPath) : undefined, count: reaction.count, hasReacted: reaction.authorHasReacted, + reactors: reaction.reactors }; } @@ -701,7 +706,8 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo label: reaction.label || '', count: reaction.count || 0, iconPath: reaction.iconPath ? URI.revive(reaction.iconPath) : '', - authorHasReacted: reaction.hasReacted || false + authorHasReacted: reaction.hasReacted || false, + reactors: reaction.reactors }; } diff --git a/src/vs/workbench/contrib/comments/browser/commentNode.ts b/src/vs/workbench/contrib/comments/browser/commentNode.ts index 496dd604aa9..2b244af9e62 100644 --- a/src/vs/workbench/contrib/comments/browser/commentNode.ts +++ b/src/vs/workbench/contrib/comments/browser/commentNode.ts @@ -459,7 +459,7 @@ export class CommentNode extends Disposable { } this.notificationService.error(error); } - }, reaction.iconPath, reaction.count); + }, reaction.reactors, reaction.iconPath, reaction.count); this._reactionsActionBar?.push(action, { label: true, icon: true }); }); diff --git a/src/vs/workbench/contrib/comments/browser/reactionsAction.ts b/src/vs/workbench/contrib/comments/browser/reactionsAction.ts index 0ce2f442d10..14c771d3134 100644 --- a/src/vs/workbench/contrib/comments/browser/reactionsAction.ts +++ b/src/vs/workbench/contrib/comments/browser/reactionsAction.ts @@ -66,27 +66,46 @@ export class ReactionActionViewItem extends ActionViewItem { 'This is a tooltip for an emoji button so that the current user can toggle their reaction to a comment.', 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second is the name of the reaction.'] }, "{0}{1} reaction", toggleMessage, action.label); - } else if (action.count === 1) { - return nls.localize({ - key: 'comment.reactionLabelOne', comment: [ - 'This is a tooltip for an emoji that is a "reaction" to a comment where the count of the reactions is 1.', - 'The emoji is also a button so that the current user can also toggle their own emoji reaction.', - 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second is the name of the reaction.'] - }, "{0}1 reaction with {1}", toggleMessage, action.label); - } else if (action.count > 1) { - return nls.localize({ - key: 'comment.reactionLabelMany', comment: [ - 'This is a tooltip for an emoji that is a "reaction" to a comment where the count of the reactions is greater than 1.', - 'The emoji is also a button so that the current user can also toggle their own emoji reaction.', - 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second is number of users who have reacted with that reaction, and the third is the name of the reaction.'] - }, "{0}{1} reactions with {2}", toggleMessage, action.count, action.label); + } else if (action.reactors === undefined || action.reactors.length === 0) { + if (action.count === 1) { + return nls.localize({ + key: 'comment.reactionLabelOne', comment: [ + 'This is a tooltip for an emoji that is a "reaction" to a comment where the count of the reactions is 1.', + 'The emoji is also a button so that the current user can also toggle their own emoji reaction.', + 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second is the name of the reaction.'] + }, "{0}1 reaction with {1}", toggleMessage, action.label); + } else if (action.count > 1) { + return nls.localize({ + key: 'comment.reactionLabelMany', comment: [ + 'This is a tooltip for an emoji that is a "reaction" to a comment where the count of the reactions is greater than 1.', + 'The emoji is also a button so that the current user can also toggle their own emoji reaction.', + 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second is number of users who have reacted with that reaction, and the third is the name of the reaction.'] + }, "{0}{1} reactions with {2}", toggleMessage, action.count, action.label); + } + } else { + if (action.reactors.length <= 10 && action.reactors.length === action.count) { + return nls.localize({ + key: 'comment.reactionLessThanTen', comment: [ + 'This is a tooltip for an emoji that is a "reaction" to a comment where the count of the reactions is less than or equal to 10.', + 'The emoji is also a button so that the current user can also toggle their own emoji reaction.', + 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second iis a list of the reactors, and the third is the name of the reaction.'] + }, "{0}{1} reacted with {2}", toggleMessage, action.reactors.join(', '), action.label); + } else if (action.count > 1) { + const displayedReactors = action.reactors.slice(0, 10); + return nls.localize({ + key: 'comment.reactionMoreThanTen', comment: [ + 'This is a tooltip for an emoji that is a "reaction" to a comment where the count of the reactions is less than or equal to 10.', + 'The emoji is also a button so that the current user can also toggle their own emoji reaction.', + 'The first arg is localized message "Toggle reaction" or empty if the user doesn\'t have permission to toggle the reaction, the second iis a list of the reactors, and the third is the name of the reaction.'] + }, "{0}{1} and {2} more reacted with {3}", toggleMessage, displayedReactors.join(', '), action.count - displayedReactors.length, action.label); + } } return undefined; } } export class ReactionAction extends Action { static readonly ID = 'toolbar.toggle.reaction'; - constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: any) => Promise, public icon?: UriComponents, public count?: number) { + constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: any) => Promise, public readonly reactors?: readonly string[], public icon?: UriComponents, public count?: number) { super(ReactionAction.ID, label, cssClass, enabled, actionCallback); } } diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 06142a238d1..3ebb6ae371d 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -19,6 +19,7 @@ export const allApiProposals = Object.freeze({ chatVariables: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.chatVariables.d.ts', codeActionAI: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.codeActionAI.d.ts', codiconDecoration: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.codiconDecoration.d.ts', + commentReactor: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentReactor.d.ts', commentsDraftState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentsDraftState.d.ts', contribCommentEditorActionsMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentEditorActionsMenu.d.ts', contribCommentPeekContext: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentPeekContext.d.ts', diff --git a/src/vscode-dts/vscode.proposed.commentReactor.d.ts b/src/vscode-dts/vscode.proposed.commentReactor.d.ts new file mode 100644 index 00000000000..13cad5f50a2 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.commentReactor.d.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // @alexr00 https://github.com/microsoft/vscode/issues/201131 + + export interface CommentReaction { + readonly reactors?: readonly string[]; + } +}