1- import React , { useCallback , useEffect , useRef , useState } from "react" ;
2- import { CometChatReactionList } from "../CometChatReactionList/CometChatReactionList" ;
1+ import React , { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
2+ import { CometChatReactionList } from "../CometChatReactionList/CometChatReactionList" ;
33import { CometChatPopover } from "../../BaseComponents/CometChatPopover/CometChatPopover" ;
4- import { CometChatReactionInfo } from "../CometChatReactionInfo/CometChatReactionInfo" ;
4+ import { CometChatReactionInfo } from "../CometChatReactionInfo/CometChatReactionInfo" ;
55import { MessageBubbleAlignment , Placement } from "../../../Enums/Enums" ;
66import { useCometChatErrorHandler } from "../../../CometChatCustomHooks" ;
77
@@ -23,7 +23,7 @@ export const CometChatReactions: React.FC<ReactionsProps> = ({
2323 onReactionListItemClick,
2424 reactionsRequestBuilder,
2525 hoverDebounceTime = 500 ,
26- onReactionClick, onError
26+ onReactionClick, onError
2727} ) => {
2828 const errorHandler = useCometChatErrorHandler ( onError ) ;
2929
@@ -59,40 +59,39 @@ export const CometChatReactions: React.FC<ReactionsProps> = ({
5959 /* This function is used to check and update the width and maximum visible emojis. */
6060 const attachObserver = useCallback (
6161 ( ) => {
62- try {
63- const parentNode = parentRef . current ?. parentNode ?. parentNode ;
64- let child = null ;
65- if ( parentNode ) {
66- const childNode = parentNode . querySelector ( '.cometchat-message-bubble__body-content-view' ) || parentNode . firstChild ;
67- if ( childNode ) {
68- child = childNode
69- }
70- } if ( child && ! resizeObserver . current ) {
71- resizeObserver . current = new ResizeObserver ( ( entries ) => {
72- for ( const entry of entries ) {
73- const newWidth = entry . contentRect . width ;
74- if ( previousWidth !== newWidth ) {
75- setPreviousWidth ( newWidth ) ;
76- updateMaxVisibleEmojis ( newWidth ) ;
77- }
62+ try {
63+ const parentNode = parentRef . current ?. parentNode ?. parentNode ;
64+ let child = null ;
65+ if ( parentNode ) {
66+ const childNode = parentNode . querySelector ( '.cometchat-message-bubble__body-content-view' ) || parentNode . firstElementChild ;
67+ if ( childNode ) {
68+ child = childNode
7869 }
79- } ) ;
80- resizeObserver . current . observe ( child ) ;
81- }
82- } catch ( error ) {
83- errorHandler ( error , "attachObserver" ) ;
70+ } if ( child && ! resizeObserver . current ) {
71+ resizeObserver . current = new ResizeObserver ( ( entries ) => {
72+ for ( const entry of entries ) {
73+ const newWidth = entry . contentRect . width ;
74+ if ( previousWidth !== newWidth ) {
75+ setPreviousWidth ( newWidth ) ;
76+ updateMaxVisibleEmojis ( newWidth ) ;
77+ }
78+ }
79+ } ) ;
80+ resizeObserver . current . observe ( child ) ;
81+ }
82+ } catch ( error ) {
83+ errorHandler ( error , "attachObserver" ) ;
8484
85- }
85+ }
8686 } , [ ]
8787 )
8888
8989 /* This function calculates and returns the number of maximum possible emojis. */
9090 const getMaxVisibleEmojis = ( availableWidth : number ) => {
9191 try {
92- const emojiWidth = 36 ;
93- const effectiveWidth = availableWidth <= 50 ? availableWidth : availableWidth - emojiWidth ;
94- const maxFitEmojis = Math . floor ( effectiveWidth / emojiWidth ) ;
95- const adjustedMaxEmojis = Math . max ( 0 , maxFitEmojis - 2 ) ;
92+ const emojiWidth = 46 ;
93+ const maxFitEmojis = Math . floor ( availableWidth / emojiWidth ) ;
94+ const adjustedMaxEmojis = Math . max ( 0 , maxFitEmojis ) ;
9695 const num = Math . min ( 100 , adjustedMaxEmojis ) ;
9796 return num === 0 ? 1 : num ;
9897 } catch ( error ) {
@@ -102,16 +101,20 @@ export const CometChatReactions: React.FC<ReactionsProps> = ({
102101 } ;
103102
104103 /* This function returns the count of extra reaction items. */
105- const moreCount = useCallback (
104+ const moreCount = useMemo (
106105 ( ) => {
107106 try {
108- return messageReactions . length > maxVisibleEmojis
109- ? messageReactions . length - maxVisibleEmojis
107+ const totalReactions = messageReactions . length ;
108+ const showMore = totalReactions > maxVisibleEmojis && maxVisibleEmojis > 2 ;
109+ const visibleCount = showMore ? maxVisibleEmojis - 1 : maxVisibleEmojis ;
110+ return totalReactions > visibleCount
111+ ? totalReactions - visibleCount
110112 : 0 ;
111113 } catch ( error ) {
112114 errorHandler ( error , "moreCount" ) ;
113115 return 0 ;
114- } } , [ messageReactions , maxVisibleEmojis ]
116+ }
117+ } , [ messageReactions , maxVisibleEmojis ]
115118 ) ;
116119
117120 /* This function returns the position of the message bubble. */
@@ -165,31 +168,68 @@ export const CometChatReactions: React.FC<ReactionsProps> = ({
165168 }
166169 } , [ messageObject , alignment ] ) ;
167170
168-
171+ /* This function returns the Reaction detailed list on click of more reactions. */
172+ const showMoreUi = useCallback (
173+ ( ) => {
174+ return (
175+ < CometChatPopover
176+ disableBackgroundInteraction = { true }
177+ useParentContainer = { true }
178+ placement = { moreListAlignment }
179+ content = {
180+ < div >
181+ < CometChatReactionList
182+ messageObject = { messageObject }
183+ reactionsRequestBuilder = { reactionsRequestBuilder }
184+ reactionItemClicked = { onReactionListItemClick }
185+ />
186+ </ div >
187+ }
188+ childClickHandler = { ( openContent : Function , e : Event ) => {
189+ getPlacementAlignment ( ( ) => {
190+ openContent ( e ) ;
191+ } ) ;
192+ } }
193+ >
194+ < div className = "cometchat-reactions__more-reaction" >
195+ < div className = "cometchat-reactions__more-reaction-count" >
196+ +{ moreCount }
197+ </ div >
198+ </ div >
199+ </ CometChatPopover >
200+ ) ;
201+ } , [ moreListAlignment , messageObject , reactionsRequestBuilder , onReactionListItemClick , getPlacementAlignment , moreCount ]
202+ ) ;
169203
170204 /* This function returns view component for reaction info as tooltip. */
171205 const showReactions = useCallback (
172- ( ) => {
173- return messageReactions . slice ( 0 , maxVisibleEmojis ) . map ( ( reaction , index ) => {
174- return (
175- < div className = "cometchat-reactions-info-wrapper" key = { `${ reaction . getReaction ( ) } -${ index } ` }
176- >
177- < CometChatPopover
178- useParentContainer = { true }
179- showOnHover = { true }
180- debounceOnHover = { hoverDebounceTime }
181- placement = { Placement . top }
182- key = { reaction . getReaction ( ) }
183- content = { reactionPopupUi ( reaction ) }
184- showTooltip = { true }
185- >
186- { reactionChildUi ( reaction ) }
187- </ CometChatPopover >
188- </ div >
189- ) ;
190- } ) ;
206+ ( ) => { const totalReactions = messageReactions . length ;
207+ const showMore = totalReactions > maxVisibleEmojis && maxVisibleEmojis > 2 ;
208+ const visibleCount = showMore ? maxVisibleEmojis - 1 : maxVisibleEmojis ;
209+ const visibleReactions = messageReactions . slice ( 0 , visibleCount ) ;
210+
211+ return (
212+ < >
213+ { visibleReactions . map ( ( reaction , index ) => (
214+ < div className = "cometchat-reactions-info-wrapper" key = { `${ reaction . getReaction ( ) } -${ index } ` } >
215+ < CometChatPopover
216+ useParentContainer = { true }
217+ showOnHover = { true }
218+ debounceOnHover = { hoverDebounceTime }
219+ placement = { Placement . top }
220+ key = { reaction . getReaction ( ) }
221+ content = { reactionPopupUi ( reaction ) }
222+ showTooltip = { true }
223+ >
224+ { reactionChildUi ( reaction ) }
225+ </ CometChatPopover >
226+ </ div >
227+ ) ) }
228+ { moreCount > 0 && showMoreUi ( ) }
229+ </ >
230+ ) ;
191231 } ,
192- [ messageReactions , maxVisibleEmojis , setPopoverVisibility , popoverVisibility ]
232+ [ messageReactions , maxVisibleEmojis , moreCount , showMoreUi ]
193233 ) ;
194234
195235 /* This function returns Reaction Info component. */
@@ -229,41 +269,7 @@ export const CometChatReactions: React.FC<ReactionsProps> = ({
229269 ) ;
230270 } ;
231271
232- /* This function returns the Reaction detailed list on click of more reactions. */
233- const showMoreUi = useCallback (
234- ( number : number ) => {
235- const newReactionList = messageReactions . slice ( - number ) ;
236- const myReaction = newReactionList . find ( ( reaction ) => reaction . getReactedByMe ( ) ) ;
237- const showActive = ! ! myReaction ;
238- return (
239- < CometChatPopover
240- disableBackgroundInteraction = { true }
241- useParentContainer = { true }
242- placement = { moreListAlignment }
243- content = {
244- < div >
245- < CometChatReactionList
246- messageObject = { messageObject }
247- reactionsRequestBuilder = { reactionsRequestBuilder }
248- reactionItemClicked = { onReactionListItemClick }
249- />
250- </ div >
251- }
252- childClickHandler = { ( openContent : Function , e : Event ) => {
253- getPlacementAlignment ( ( ) => {
254- openContent ( e ) ;
255- } ) ;
256- } }
257- >
258- < div className = "cometchat-reactions__more-reaction" >
259- < div className = "cometchat-reactions__more-reaction-count" >
260- +{ number }
261- </ div >
262- </ div >
263- </ CometChatPopover >
264- ) ;
265- } , [ messageReactions , moreListAlignment ]
266- ) ;
272+
267273
268274 return (
269275 < div
@@ -273,7 +279,6 @@ export const CometChatReactions: React.FC<ReactionsProps> = ({
273279 onMouseLeave = { ( ) => setPopoverVisibility ( { } ) }
274280 >
275281 { showReactions ( ) }
276- { moreCount ( ) > 0 && showMoreUi ( moreCount ( ) ) }
277282 </ div >
278283 ) ;
279284} ;
0 commit comments