UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

68 lines (67 loc) 3.68 kB
import { useCallback, useMemo } from 'react'; import { useComponentContext, useMessageContext } from '../../../context'; import { defaultReactionOptions } from '../reactionOptions'; export const defaultReactionsSort = (a, b) => { if (a.firstReactionAt && b.firstReactionAt) { return +a.firstReactionAt - +b.firstReactionAt; } return a.reactionType.localeCompare(b.reactionType, 'en'); }; export const useProcessReactions = (params) => { const { own_reactions: propOwnReactions, reaction_groups: propReactionGroups, reactionOptions: propReactionOptions, reactions: propReactions, sortReactions: propSortReactions, } = params; const { message, sortReactions: contextSortReactions } = useMessageContext('useProcessReactions'); const { reactionOptions: contextReactionOptions = defaultReactionOptions } = useComponentContext('useProcessReactions'); const reactionOptions = propReactionOptions ?? contextReactionOptions; const sortReactions = propSortReactions ?? contextSortReactions ?? defaultReactionsSort; const latestReactions = propReactions || message.latest_reactions; const ownReactions = propOwnReactions || message?.own_reactions; const reactionGroups = propReactionGroups || message?.reaction_groups; const isOwnReaction = useCallback((reactionType) => ownReactions?.some((reaction) => reaction.type === reactionType) ?? false, [ownReactions]); const getEmojiByReactionType = useCallback((reactionType) => reactionOptions.find(({ type }) => type === reactionType)?.Component ?? null, [reactionOptions]); const isSupportedReaction = useCallback((reactionType) => reactionOptions.some((reactionOption) => reactionOption.type === reactionType), [reactionOptions]); const getLatestReactedUserNames = useCallback((reactionType) => latestReactions?.flatMap((reaction) => { if (reactionType && reactionType === reaction.type) { const username = reaction.user?.name || reaction.user?.id; return username ? [username] : []; } return []; }) ?? [], [latestReactions]); const existingReactions = useMemo(() => { if (!reactionGroups) { return []; } const unsortedReactions = Object.entries(reactionGroups).flatMap(([reactionType, { count, first_reaction_at, last_reaction_at }]) => { if (count === 0 || !isSupportedReaction(reactionType)) { return []; } const latestReactedUserNames = getLatestReactedUserNames(reactionType); return [ { EmojiComponent: getEmojiByReactionType(reactionType), firstReactionAt: first_reaction_at ? new Date(first_reaction_at) : null, isOwnReaction: isOwnReaction(reactionType), lastReactionAt: last_reaction_at ? new Date(last_reaction_at) : null, latestReactedUserNames, reactionCount: count, reactionType, unlistedReactedUserCount: count - latestReactedUserNames.length, }, ]; }); return unsortedReactions.sort(sortReactions); }, [ getEmojiByReactionType, getLatestReactedUserNames, isOwnReaction, isSupportedReaction, reactionGroups, sortReactions, ]); const hasReactions = existingReactions.length > 0; const totalReactionCount = useMemo(() => existingReactions.reduce((total, { reactionCount }) => total + reactionCount, 0), [existingReactions]); return { existingReactions, hasReactions, totalReactionCount, }; };