Skip to content

Commit bbb5022

Browse files
authored
Missing copilot's :eyes: reaction to comments (#6888)
Fixes #6880
1 parent ae473bc commit bbb5022

4 files changed

Lines changed: 68 additions & 5 deletions

File tree

src/github/queriesShared.gql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ fragment Reactable on Reactable {
190190
... on User {
191191
login
192192
}
193+
... on Actor {
194+
login
195+
}
193196
}
194197
totalCount
195198
}

src/github/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ export function parseGraphQLReaction(reactionGroups: GraphQL.ReactionGroup[]): R
556556
count: group.reactors.totalCount,
557557
icon: reactionContentEmojiMapping[group.content].icon,
558558
viewerHasReacted: group.viewerHasReacted,
559-
reactors: group.reactors.nodes.map(node => node.login)
559+
reactors: group.reactors.nodes.map(node => COPILOT_ACCOUNTS[node.login].name ?? node.login)
560560
};
561561

562562
return reaction;

webviews/components/comment.tsx

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export function CommentView(commentProps: Props) {
8686
onMouseLeave={() => setShowActionBar(false)}
8787
onFocus={() => setShowActionBar(true)}
8888
>
89-
{ariaAnnouncement ? <div role='alert' aria-label={ariaAnnouncement}/> : null}
89+
{ariaAnnouncement ? <div role='alert' aria-label={ariaAnnouncement} /> : null}
9090
<div className="action-bar comment-actions" style={{ display: showActionBar ? 'flex' : 'none' }}>
9191
<button
9292
title="Quote reply"
@@ -290,8 +290,45 @@ export const CommentBody = ({ comment, bodyHTML, body, canApplyPatch, allowEmpty
290290
<div className="comment-body">
291291
{renderedBody}
292292
{applyPatchButton}
293-
{specialDisplayBodyPostfix ? <br/> : null}
293+
{specialDisplayBodyPostfix ? <br /> : null}
294294
{specialDisplayBodyPostfix ? <em>{specialDisplayBodyPostfix}</em> : null}
295+
<CommentReactions reactions={comment?.reactions} />
296+
</div>
297+
);
298+
};
299+
300+
type CommentReactionsProps = {
301+
reactions?: { label: string; count: number; reactors: readonly string[] }[];
302+
};
303+
304+
const CommentReactions = ({ reactions }: CommentReactionsProps) => {
305+
if (!Array.isArray(reactions) || reactions.length === 0) return null;
306+
const filtered = reactions.filter(r => r.count > 0);
307+
if (filtered.length === 0) return null;
308+
return (
309+
<div className="comment-reactions" style={{ marginTop: 6 }}>
310+
{filtered.map((reaction, idx) => {
311+
const maxReactors = 10;
312+
const reactors = reaction.reactors || [];
313+
const displayReactors = reactors.slice(0, maxReactors);
314+
const moreCount = reactors.length > maxReactors ? reactors.length - maxReactors : 0;
315+
let title: string = '';
316+
if (displayReactors.length > 0) {
317+
if (moreCount > 0) {
318+
title = `${joinWithAnd(displayReactors)} and ${moreCount} more reacted with ${reaction.label}`;
319+
} else {
320+
title = `${joinWithAnd(displayReactors)} reacted with ${reaction.label}`;
321+
}
322+
}
323+
return (
324+
<div
325+
key={reaction.label + idx}
326+
title={title}
327+
>
328+
<span className="reaction-label">{reaction.label}</span>{nbsp}{reaction.count > 1 ? <span className="reaction-count">{reaction.count}</span> : null}
329+
</div>
330+
);
331+
})}
295332
</div>
296333
);
297334
};
@@ -302,7 +339,6 @@ export function AddComment({
302339
hasWritePermission,
303340
isIssue,
304341
isAuthor,
305-
isDraft,
306342
continueOnGitHub,
307343
currentUserReviewState,
308344
lastReviewType,
@@ -468,7 +504,7 @@ export const AddCommentSimple = (pr: PullRequest) => {
468504
const { updatePR, requestChanges, approve, submit, openOnGitHub } = useContext(PullRequestContext);
469505
const [isBusy, setBusy] = useState(false);
470506
const textareaRef = useRef<HTMLTextAreaElement>();
471-
let currentSelection: ReviewType = pr.lastReviewType ?? (pr.currentUserReviewState === 'APPROVED' ? ReviewType.Approve : (pr.currentUserReviewState === 'CHANGES_REQUESTED' ? ReviewType.RequestChanges: ReviewType.Comment));
507+
let currentSelection: ReviewType = pr.lastReviewType ?? (pr.currentUserReviewState === 'APPROVED' ? ReviewType.Approve : (pr.currentUserReviewState === 'CHANGES_REQUESTED' ? ReviewType.RequestChanges : ReviewType.Comment));
472508

473509
async function submitAction(action: ReviewType): Promise<void> {
474510
const { value } = textareaRef.current!;
@@ -558,3 +594,10 @@ export const AddCommentSimple = (pr: PullRequest) => {
558594
</span>
559595
);
560596
};
597+
598+
function joinWithAnd(arr: string[]): string {
599+
if (arr.length === 0) return '';
600+
if (arr.length === 1) return arr[0];
601+
if (arr.length === 2) return `${arr[0]} and ${arr[1]}`;
602+
return `${arr.slice(0, -1).join(', ')} and ${arr[arr.length - 1]}`;
603+
}

webviews/editorWebview/index.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ span.lineContent {
8181
overflow-wrap: anywhere;
8282
}
8383

84+
.comment-reactions {
85+
display: flex;
86+
flex-direction: row;
87+
}
88+
89+
.comment-reactions div {
90+
font-size: 1.1em;
91+
cursor: pointer;
92+
user-select: none;
93+
}
94+
95+
.comment-reactions .reaction-label {
96+
border-radius: 5px;
97+
border: 1px solid var(--vscode-panel-border);
98+
width: 14px;
99+
}
100+
84101
#title:empty {
85102
border: none;
86103
}

0 commit comments

Comments
 (0)