diff --git a/apps/web/src/components/pr/pr-diff-viewer.tsx b/apps/web/src/components/pr/pr-diff-viewer.tsx
index bda3897c..3910e122 100644
--- a/apps/web/src/components/pr/pr-diff-viewer.tsx
+++ b/apps/web/src/components/pr/pr-diff-viewer.tsx
@@ -56,6 +56,7 @@ import { useGlobalChatOptional } from "@/components/shared/global-chat-provider"
import { MarkdownEditor, type MarkdownEditorRef } from "@/components/shared/markdown-editor";
import type { ReviewThread, CheckStatus } from "@/lib/github";
import { ClientMarkdown } from "@/components/shared/client-markdown";
+import { ReactionDisplay, type Reactions } from "@/components/shared/reaction-display";
import { CheckStatusBadge } from "@/components/pr/check-status-badge";
import { useMutationEvents } from "@/components/shared/mutation-event-provider";
import { UserTooltip } from "@/components/shared/user-tooltip";
@@ -88,6 +89,7 @@ interface ReviewComment {
original_line: number | null;
side: string | null;
created_at: string;
+ reactions?: Reactions;
}
interface ReviewSummary {
@@ -3506,6 +3508,22 @@ function InlineCommentDisplay({
) : (
+ {owner && repo && (
+
+
+
+ )}
)}
>
diff --git a/apps/web/src/components/shared/reaction-display.tsx b/apps/web/src/components/shared/reaction-display.tsx
index 0a2a9b3c..9f047f36 100644
--- a/apps/web/src/components/shared/reaction-display.tsx
+++ b/apps/web/src/components/shared/reaction-display.tsx
@@ -357,7 +357,12 @@ export function ReactionDisplay({
const getUsersForReaction = (key: string): ReactionWithId[] => {
if (!reactionUsers) return [];
- return reactionUsers.filter((u) => u.content === key);
+ const seen = new Set();
+ return reactionUsers.filter((u) => {
+ if (u.content !== key || seen.has(u.login)) return false;
+ seen.add(u.login);
+ return true;
+ });
};
const currentUserReactions = new Set(
@@ -425,15 +430,28 @@ export function ReactionDisplay({
content,
);
if (result.success && result.reactionId) {
- setReactionUsers((prev) => [
- ...(prev ?? []),
- {
- id: result.reactionId!,
- login: currentUser.login,
- avatar_url: currentUser.avatar_url,
- content,
- },
- ]);
+ setReactionUsers((prev) => {
+ const existing = prev ?? [];
+ if (
+ existing.some(
+ (u) =>
+ u.login ===
+ currentUser.login &&
+ u.content ===
+ content,
+ )
+ )
+ return existing;
+ return [
+ ...existing,
+ {
+ id: result.reactionId!,
+ login: currentUser.login,
+ avatar_url: currentUser.avatar_url,
+ content,
+ },
+ ];
+ });
} else {
setOptimisticReactions((prev) => ({
...prev,