@@ -39,8 +39,8 @@ import {
3939 DropdownMenuSeparator ,
4040 DropdownMenuTrigger ,
4141} from "@/shared/ui/dropdown-menu" ;
42+ import { isPositiveEmojiParticle } from "@/shared/ui/EmojiBurstProvider" ;
4243import { Popover , PopoverContent , PopoverTrigger } from "@/shared/ui/popover" ;
43- import { Spinner } from "@/shared/ui/spinner" ;
4444import { Tooltip , TooltipContent , TooltipTrigger } from "@/shared/ui/tooltip" ;
4545
4646function copyToClipboard ( text : string , successMessage : string ) {
@@ -263,12 +263,12 @@ export function MessageActionBar({
263263 onEdit,
264264 onFollowThread,
265265 onMarkUnread,
266+ onReactionBadgeBurstRequest,
266267 onReactionSelect,
267268 onReply,
268269 onUnfollowThread,
269270 reactionErrorMessage = null ,
270271 reactions,
271- reactionPending = false ,
272272 isFollowingThread,
273273} : {
274274 /** Channel UUID — required for the "Copy link" action; when omitted the
@@ -279,12 +279,12 @@ export function MessageActionBar({
279279 onEdit ?: ( message : TimelineMessage ) => void ;
280280 onFollowThread ?: ( message : TimelineMessage ) => void ;
281281 onMarkUnread ?: ( message : TimelineMessage ) => void ;
282+ onReactionBadgeBurstRequest ?: ( emoji : string ) => void ;
282283 onReactionSelect ?: ( emoji : string ) => Promise < void > ;
283284 onReply ?: ( message : TimelineMessage ) => void ;
284285 onUnfollowThread ?: ( message : TimelineMessage ) => void ;
285286 reactionErrorMessage ?: string | null ;
286287 reactions : TimelineReaction [ ] ;
287- reactionPending ?: boolean ;
288288 isFollowingThread ?: boolean ;
289289} ) {
290290 const [ isReactionPickerOpen , setIsReactionPickerOpen ] = React . useState ( false ) ;
@@ -307,6 +307,10 @@ export function MessageActionBar({
307307 const selectedReactionCount = reactions . filter (
308308 ( reaction ) => reaction . reactedByCurrentUser ,
309309 ) . length ;
310+ const wouldAddReaction = ( emoji : string ) =>
311+ ! reactions . some (
312+ ( reaction ) => reaction . emoji === emoji && reaction . reactedByCurrentUser ,
313+ ) ;
310314
311315 return (
312316 < div
@@ -334,7 +338,6 @@ export function MessageActionBar({
334338 aria-label = "Open reactions"
335339 className = "h-6 w-6 rounded-full p-0"
336340 data-testid = { `react-message-${ message . id } ` }
337- disabled = { reactionPending }
338341 size = "sm"
339342 type = "button"
340343 variant = {
@@ -343,11 +346,7 @@ export function MessageActionBar({
343346 : "ghost"
344347 }
345348 >
346- { reactionPending ? (
347- < Spinner className = "h-3 w-3" />
348- ) : (
349- < SmilePlus className = "h-3 w-3" />
350- ) }
349+ < SmilePlus className = "h-3 w-3" />
351350 </ Button >
352351 </ PopoverTrigger >
353352 </ TooltipTrigger >
@@ -374,6 +373,12 @@ export function MessageActionBar({
374373 }
375374 // `value` is already a `native` glyph or a `:shortcode:` for
376375 // custom emoji; the toggle mutation resolves the URL.
376+ if (
377+ wouldAddReaction ( value ) &&
378+ isPositiveEmojiParticle ( value )
379+ ) {
380+ onReactionBadgeBurstRequest ?.( value ) ;
381+ }
377382 void onReactionSelect ( value ) . finally ( ( ) => {
378383 setIsReactionPickerOpen ( false ) ;
379384 } ) ;
0 commit comments