@@ -7,7 +7,12 @@ import { Modal as DefaultModal } from '../Modal';
77import { useFetchReactions } from './hooks/useFetchReactions' ;
88import { LoadingIndicator } from '../Loading' ;
99import { Avatar } from '../Avatar' ;
10- import { useComponentContext , useMessageContext } from '../../context' ;
10+ import {
11+ useChatContext ,
12+ useComponentContext ,
13+ useMessageContext ,
14+ useTranslationContext ,
15+ } from '../../context' ;
1116import type { ReactionSort } from 'stream-chat' ;
1217import type { ModalProps } from '../Modal' ;
1318import type { MessageContextValue } from '../../context' ;
@@ -34,11 +39,11 @@ export function ReactionsListModal({
3439 ...modalProps
3540} : ReactionsListModalProps ) {
3641 const { Modal = DefaultModal } = useComponentContext ( ) ;
37- const selectedReaction = reactions . find (
38- ( { reactionType } ) => reactionType === selectedReactionType ,
39- ) ;
40- const SelectedEmojiComponent = selectedReaction ?. EmojiComponent ?? null ;
42+ const { client } = useChatContext ( ) ;
43+ const { t } = useTranslationContext ( ) ;
44+
4145 const {
46+ message,
4247 reactionDetailsSort : contextReactionDetailsSort ,
4348 sortReactionDetails : contextSortReactionDetails ,
4449 } = useMessageContext ( 'ReactionsListModal' ) ;
@@ -53,6 +58,15 @@ export function ReactionsListModal({
5358 sort : reactionDetailsSort ,
5459 } ) ;
5560
61+ const totalReactionCount = useMemo (
62+ ( ) =>
63+ Object . entries ( message . reaction_counts ?? { } ) . reduce (
64+ ( total , [ , reactionCount ] ) => total + reactionCount ,
65+ 0 ,
66+ ) ,
67+ [ message . reaction_counts ] ,
68+ ) ;
69+
5670 const reactionDetailsWithLegacyFallback = useMemo (
5771 ( ) =>
5872 legacySortReactionDetails
@@ -64,70 +78,86 @@ export function ReactionsListModal({
6478 return (
6579 < Modal
6680 { ...modalProps }
67- className = { clsx ( 'str-chat__message-reactions-details -modal' , modalProps . className ) }
81+ className = { clsx ( 'str-chat__message-reactions-detail -modal' , modalProps . className ) }
6882 >
6983 < div
70- className = 'str-chat__message-reactions-details '
84+ className = 'str-chat__message-reactions-detail '
7185 data-testid = 'reactions-list-modal'
7286 >
73- < div className = 'str-chat__message-reactions-details-reaction-types' >
74- { reactions . map (
75- ( { EmojiComponent, reactionCount, reactionType } ) =>
76- EmojiComponent && (
77- < div
78- className = { clsx ( 'str-chat__message-reactions-details-reaction-type' , {
79- 'str-chat__message-reactions-details-reaction-type--selected' :
80- selectedReactionType === reactionType ,
81- } ) }
82- data-testid = { `reaction-details-selector-${ reactionType } ` }
83- key = { reactionType }
84- onClick = { ( ) =>
85- onSelectedReactionTypeChange ?.( reactionType as ReactionType )
86- }
87- >
88- < span className = 'str-chat__message-reaction-emoji str-chat__message-reaction-emoji--with-fallback' >
89- < EmojiComponent />
90- </ span >
91-
92- < span className = 'str-chat__message-reaction-count' >
93- { reactionCount }
94- </ span >
95- </ div >
96- ) ,
97- ) }
87+ < div className = 'str-chat__message-reactions-detail__total-count' >
88+ { t ( '{{ count }} reactions' , { count : totalReactionCount } ) }
89+ </ div >
90+ < div className = 'str-chat__message-reactions-detail__reaction-type-list-container' >
91+ < ul className = 'str-chat__message-reactions-detail__reaction-type-list' >
92+ { reactions . map (
93+ ( { EmojiComponent, reactionCount, reactionType } ) =>
94+ EmojiComponent && (
95+ < li
96+ className = 'str-chat__message-reactions-detail__reaction-type-list-item'
97+ key = { reactionType }
98+ >
99+ < button
100+ aria-pressed = { reactionType === selectedReactionType }
101+ className = 'str-chat__message-reactions-detail__reaction-type-list-item-button'
102+ onClick = { ( ) => onSelectedReactionTypeChange ?.( reactionType ) }
103+ >
104+ < span className = 'str-chat__message-reactions-detail__reaction-type-list-item-icon' >
105+ < EmojiComponent />
106+ </ span >
107+ { reactionCount > 1 && (
108+ < span
109+ className = 'str-chat__message-reactions-detail__reaction-type-list-item-count'
110+ data-testclass = 'message-reactions-item-count'
111+ >
112+ { reactionCount }
113+ </ span >
114+ ) }
115+ </ button >
116+ </ li >
117+ ) ,
118+ ) }
119+ </ ul >
98120 </ div >
99- { SelectedEmojiComponent && (
100- < div className = 'str-chat__message-reaction-emoji str-chat__message-reaction-emoji--with-fallback str-chat__message-reaction-emoji-big' >
101- < SelectedEmojiComponent />
102- </ div >
103- ) }
104121 < div
105- className = 'str-chat__message-reactions-details-reacting-users '
122+ className = 'str-chat__message-reactions-detail__user-list '
106123 data-testid = 'all-reacting-users'
107124 >
108125 { areReactionsLoading ? (
109126 < LoadingIndicator />
110127 ) : (
111- reactionDetailsWithLegacyFallback . map ( ( { user } ) => (
112- < div
113- className = 'str-chat__message-reactions-details-reacting-user'
114- key = { user ?. id }
115- >
116- < Avatar
117- className = 'stream-chat__avatar--reaction'
118- data-testid = 'avatar'
119- imageUrl = { user ?. image as string | undefined }
120- size = 'md'
121- userName = { user ?. name || user ?. id }
122- />
123- < span
124- className = 'str-chat__user-item--name'
125- data-testid = 'reaction-user-username'
128+ reactionDetailsWithLegacyFallback . map ( ( { user } ) => {
129+ const belongsToCurrentUser = client . user ?. id === user ?. id ;
130+ return (
131+ < div
132+ className = 'str-chat__message-reactions-detail__user-list-item'
133+ key = { user ?. id }
126134 >
127- { user ?. name || user ?. id }
128- </ span >
129- </ div >
130- ) )
135+ < Avatar
136+ className = 'str-chat__avatar--with-border'
137+ data-testid = 'avatar'
138+ imageUrl = { user ?. image as string | undefined }
139+ size = 'sm'
140+ userName = { user ?. name || user ?. id }
141+ />
142+ < div className = 'str-chat__message-reactions-detail__user-list-item-info' >
143+ < span
144+ className = 'str-chat__message-reactions-detail__user-list-item-username'
145+ data-testid = 'reaction-user-username'
146+ >
147+ { belongsToCurrentUser ? t ( 'You' ) : user ?. name || user ?. id }
148+ </ span >
149+ { belongsToCurrentUser && (
150+ < button
151+ className = 'str-chat__message-reactions-detail__user-list-item-button'
152+ data-testid = 'remove-reaction-button'
153+ >
154+ { t ( 'Tap to remove' ) }
155+ </ button >
156+ ) }
157+ </ div >
158+ </ div >
159+ ) ;
160+ } )
131161 ) }
132162 </ div >
133163 </ div >
0 commit comments