提交 cae0668a 编写于 作者: P Peng Lyu

reactions handler

上级 a03caec7
......@@ -9054,6 +9054,31 @@ declare module 'vscode' {
iconPath?: Uri;
}
/**
* Reactions of a [comment](#Comment)
*/
export interface CommentReaction {
/**
* The human-readable label for the reaction
*/
readonly label: string;
/**
* Icon for the reaction shown in UI.
*/
readonly iconPath: string | Uri;
/**
* The number of users who have reacted to this reaction
*/
readonly count: number;
/**
* Whether the [author](CommentAuthorInformation) of the comment has reacted to this reaction
*/
readonly authorHasReacted: boolean;
}
/**
* A comment is displayed within the editor or the Comments Panel, depending on how it is provided.
*/
......@@ -9093,6 +9118,11 @@ declare module 'vscode' {
*/
contextValue?: string;
/**
* Optional reactions of the [comment](#Comment)
*/
reactions?: CommentReaction[];
/**
* Optional label describing the [Comment](#Comment)
* Label will be rendered next to authorName if exists.
......@@ -9157,6 +9187,11 @@ declare module 'vscode' {
*/
createCommentThread(uri: Uri, range: Range, comments: Comment[]): CommentThread;
/**
* Optional reaction handler for creating and deleting reactions on a [comment](#Comment).
*/
reactionHandler?: (comment: Comment, reaction: CommentReaction) => Promise<void>;
/**
* Dispose this comment controller.
*
......
......@@ -851,9 +851,6 @@ declare module 'vscode' {
* Stay in proposed.
*/
interface CommentReaction {
readonly label?: string;
readonly iconPath?: string | Uri;
count?: number;
readonly hasReacted?: boolean;
}
......
......@@ -284,6 +284,9 @@ export class MainThreadCommentController {
private readonly _threads: Map<number, MainThreadCommentThread> = new Map<number, MainThreadCommentThread>();
public activeCommentThread?: MainThreadCommentThread;
get features(): CommentProviderFeatures {
return this._features;
}
constructor(
private readonly _proxy: ExtHostCommentsShape,
......
......@@ -131,6 +131,7 @@ export interface CommentProviderFeatures {
finishDraftLabel?: string;
reactionGroup?: modes.CommentReaction[];
commentThreadTemplate?: CommentThreadTemplate;
reactionHandler?: boolean;
}
export interface MainThreadCommentsShape extends IDisposable {
......
......@@ -210,7 +210,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
const document = this._documents.getDocument(URI.revive(uri));
const commentController = this._commentControllers.get(commentControllerHandle);
if (!commentController || !commentController.reactionProvider || !commentController.reactionProvider.toggleReaction) {
if (!commentController || !((commentController.reactionProvider && commentController.reactionProvider.toggleReaction) || commentController.reactionHandler)) {
return Promise.resolve(undefined);
}
......@@ -219,9 +219,16 @@ export class ExtHostComments implements ExtHostCommentsShape {
if (commentThread) {
const vscodeComment = commentThread.getComment(comment.commentId);
if (commentController !== undefined && commentController.reactionProvider && commentController.reactionProvider.toggleReaction && vscodeComment) {
return commentController.reactionProvider.toggleReaction(document, vscodeComment, convertFromReaction(reaction));
if (commentController !== undefined && vscodeComment) {
if (commentController.reactionHandler) {
return commentController.reactionHandler(vscodeComment, convertFromReaction(reaction));
}
if (commentController.reactionProvider && commentController.reactionProvider.toggleReaction) {
return commentController.reactionProvider.toggleReaction(document, vscodeComment, convertFromReaction(reaction));
}
}
}
return Promise.resolve(undefined);
......@@ -635,7 +642,7 @@ export class ExtHostCommentThread implements vscode.CommentThread {
}
getComment(commentId: string): vscode.Comment | undefined {
const comments = this._comments.filter(comment => comment.commentId === commentId);
const comments = this._comments.filter(comment => (comment.commentId === commentId || comment.id === commentId));
if (comments && comments.length) {
return comments[0];
......@@ -707,6 +714,9 @@ export class ExtHostCommentInputBox implements vscode.CommentInputBox {
this._value = input;
}
}
type ReactionHandler = (comment: vscode.Comment, reaction: vscode.CommentReaction) => Promise<void>;
class ExtHostCommentController implements vscode.CommentController {
get id(): string {
return this._id;
......@@ -740,6 +750,18 @@ class ExtHostCommentController implements vscode.CommentController {
}
}
private _reactionHandler?: ReactionHandler;
get reactionHandler(): ReactionHandler | undefined {
return this._reactionHandler;
}
set reactionHandler(handler: ReactionHandler | undefined) {
this._reactionHandler = handler;
this._proxy.$updateCommentControllerFeatures(this.handle, { reactionHandler: !!handler });
}
constructor(
_extension: IExtensionDescription,
private _handle: number,
......@@ -861,9 +883,12 @@ function convertFromComment(comment: modes.Comment): vscode.Comment {
isDraft: comment.isDraft,
commentReactions: comment.commentReactions ? comment.commentReactions.map(reaction => {
return {
label: reaction.label,
count: reaction.count,
hasReacted: reaction.hasReacted
label: reaction.label || '',
count: reaction.count || 0,
iconPath: reaction.iconPath ? URI.revive(reaction.iconPath) : '',
hasReacted: reaction.hasReacted,
authorHasReacted: reaction.hasReacted || false
};
}) : undefined,
mode: comment.mode ? comment.mode : modes.CommentMode.Preview
......@@ -878,6 +903,7 @@ function convertToModeComment2(thread: ExtHostCommentThread, commentController:
}
const iconPath = vscodeComment.author && vscodeComment.author.iconPath ? vscodeComment.author.iconPath.toString() : undefined;
const reactions = vscodeComment.reactions || vscodeComment.commentReactions;
return {
commentId: vscodeComment.id || vscodeComment.commentId,
......@@ -892,7 +918,7 @@ function convertToModeComment2(thread: ExtHostCommentThread, commentController:
editCommand: vscodeComment.editCommand ? commandsConverter.toInternal(vscodeComment.editCommand) : undefined,
deleteCommand: vscodeComment.deleteCommand ? commandsConverter.toInternal(vscodeComment.deleteCommand) : undefined,
label: vscodeComment.label,
commentReactions: vscodeComment.commentReactions ? vscodeComment.commentReactions.map(reaction => convertToReaction2(commentController.reactionProvider, reaction)) : undefined
commentReactions: reactions ? reactions.map(reaction => convertToReaction2(commentController.reactionProvider, reaction)) : undefined
};
}
......@@ -939,9 +965,11 @@ function convertToReaction2(provider: vscode.CommentReactionProvider | undefined
function convertFromReaction(reaction: modes.CommentReaction): vscode.CommentReaction {
return {
label: reaction.label,
count: reaction.count,
hasReacted: reaction.hasReacted
label: reaction.label || '',
count: reaction.count || 0,
iconPath: reaction.iconPath ? URI.revive(reaction.iconPath) : '',
hasReacted: reaction.hasReacted,
authorHasReacted: reaction.hasReacted || false
};
}
......
......@@ -649,6 +649,7 @@ export class SimpleCommentService implements ICommentService {
addReaction: any;
deleteReaction: any;
getReactionGroup: any;
hasReactionHandler: any;
toggleReaction: any;
setActiveCommentThread: any;
}
......
......@@ -119,7 +119,7 @@ export class CommentNode extends Disposable {
this._md = this.markdownRenderer.render(comment.body).element;
this._body.appendChild(this._md);
if (this.comment.commentReactions && this.comment.commentReactions.length) {
if (this.comment.commentReactions && this.comment.commentReactions.length && this.comment.commentReactions.filter(reaction => !!reaction.count).length) {
this.createReactionsContainer(this._commentDetailsContainer);
}
......@@ -154,15 +154,23 @@ export class CommentNode extends Disposable {
private createActionsToolbar() {
const actions: IAction[] = [];
let reactionGroup = this.commentService.getReactionGroup(this.owner);
if (reactionGroup && reactionGroup.length) {
let commentThread = this.commentThread as modes.CommentThread2;
if (commentThread.commentThreadHandle !== undefined) {
let toggleReactionAction = this.createReactionPicker2();
actions.push(toggleReactionAction);
} else {
let toggleReactionAction = this.createReactionPicker();
actions.push(toggleReactionAction);
let hasReactionHandler = this.commentService.hasReactionHandler(this.owner);
if (hasReactionHandler) {
let toggleReactionAction = this.createReactionPicker2(this.comment.commentReactions || []);
actions.push(toggleReactionAction);
} else {
let reactionGroup = this.commentService.getReactionGroup(this.owner);
if (reactionGroup && reactionGroup.length) {
let commentThread = this.commentThread as modes.CommentThread2;
if (commentThread.commentThreadHandle !== undefined) {
let reactionGroup = this.commentService.getReactionGroup(this.owner);
let toggleReactionAction = this.createReactionPicker2(reactionGroup || []);
actions.push(toggleReactionAction);
} else {
let toggleReactionAction = this.createReactionPicker();
actions.push(toggleReactionAction);
}
}
}
......@@ -241,7 +249,7 @@ export class CommentNode extends Disposable {
}
}
private createReactionPicker2(): ToggleReactionsAction {
private createReactionPicker2(reactionGroup: modes.CommentReaction[]): ToggleReactionsAction {
let toggleReactionActionViewItem: DropdownMenuActionViewItem;
let toggleReactionAction = this._register(new ToggleReactionsAction(() => {
if (toggleReactionActionViewItem) {
......@@ -250,7 +258,6 @@ export class CommentNode extends Disposable {
}, nls.localize('commentToggleReaction', "Toggle Reaction")));
let reactionMenuActions: Action[] = [];
let reactionGroup = this.commentService.getReactionGroup(this.owner);
if (reactionGroup && reactionGroup.length) {
reactionMenuActions = reactionGroup.map((reaction) => {
return new Action(`reaction.command.${reaction.label}`, `${reaction.label}`, '', true, async () => {
......@@ -356,8 +363,9 @@ export class CommentNode extends Disposable {
});
this._register(this._reactionsActionBar);
this.comment.commentReactions!.map(reaction => {
let action = new ReactionAction(`reaction.${reaction.label}`, `${reaction.label}`, reaction.hasReacted && reaction.canEdit ? 'active' : '', reaction.canEdit, async () => {
let hasReactionHandler = this.commentService.hasReactionHandler(this.owner);
this.comment.commentReactions!.filter(reaction => !!reaction.count).map(reaction => {
let action = new ReactionAction(`reaction.${reaction.label}`, `${reaction.label}`, reaction.hasReacted && (reaction.canEdit || hasReactionHandler) ? 'active' : '', (reaction.canEdit || hasReactionHandler), async () => {
try {
let commentThread = this.commentThread as modes.CommentThread2;
if (commentThread.commentThreadHandle !== undefined) {
......@@ -390,15 +398,20 @@ export class CommentNode extends Disposable {
}
});
let reactionGroup = this.commentService.getReactionGroup(this.owner);
if (reactionGroup && reactionGroup.length) {
let commentThread = this.commentThread as modes.CommentThread2;
if (commentThread.commentThreadHandle !== undefined) {
let toggleReactionAction = this.createReactionPicker2();
this._reactionsActionBar.push(toggleReactionAction, { label: false, icon: true });
} else {
let toggleReactionAction = this.createReactionPicker();
this._reactionsActionBar.push(toggleReactionAction, { label: false, icon: true });
if (hasReactionHandler) {
let toggleReactionAction = this.createReactionPicker2(this.comment.commentReactions || []);
this._reactionsActionBar.push(toggleReactionAction, { label: false, icon: true });
} else {
let reactionGroup = this.commentService.getReactionGroup(this.owner);
if (reactionGroup && reactionGroup.length) {
let commentThread = this.commentThread as modes.CommentThread2;
if (commentThread.commentThreadHandle !== undefined) {
let toggleReactionAction = this.createReactionPicker2(reactionGroup || []);
this._reactionsActionBar.push(toggleReactionAction, { label: false, icon: true });
} else {
let toggleReactionAction = this.createReactionPicker();
this._reactionsActionBar.push(toggleReactionAction, { label: false, icon: true });
}
}
}
}
......
......@@ -69,6 +69,7 @@ export interface ICommentService {
addReaction(owner: string, resource: URI, comment: Comment, reaction: CommentReaction): Promise<void>;
deleteReaction(owner: string, resource: URI, comment: Comment, reaction: CommentReaction): Promise<void>;
getReactionGroup(owner: string): CommentReaction[] | undefined;
hasReactionHandler(owner: string): boolean;
toggleReaction(owner: string, resource: URI, thread: CommentThread2, comment: Comment, reaction: CommentReaction): Promise<void>;
setActiveCommentThread(commentThread: CommentThread | null): void;
}
......@@ -304,6 +305,16 @@ export class CommentService extends Disposable implements ICommentService {
return undefined;
}
hasReactionHandler(owner: string): boolean {
const commentProvider = this._commentControls.get(owner);
if (commentProvider) {
return !!commentProvider.features.reactionHandler;
}
return false;
}
getStartDraftLabel(owner: string): string | undefined {
const commentProvider = this._commentProviders.get(owner);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册