import React, { useCallback, useMemo, useState } from 'react'; import { StyleSheet, TextStyle, TouchableOpacity, View, ViewStyle, } from 'react-native'; import { userProfile } from '@livelike/javascript'; import { useStyles, useReactionSpace, useUserReactions, useUserReactionActions, useAnalytics, } from '../../hooks'; import { ComponentStyleProp, LLComponentStyleFn } from '../../types'; import { LLReactionPicker, LLReactionPickerProps } from './LLReactionPicker'; import { LLUserReactionCountDetail, LLUserReactionCountDetailProps, } from './LLUserReactionCountDetail'; import { LLText } from '../LLText'; export type LLUserReactionCountsStyles = { reactionCountsContainer: ViewStyle; moreReactionsView: ViewStyle; moreReactionsText: TextStyle; }; export type LLUserReactionCountsProps = ComponentStyleProp & { targetGroupId: string; targetId: string; showReactionPicker?: boolean; reactionsLimit?: number; onReactionItemPress?: () => void; UserReactionCountDetailComponent?: typeof LLUserReactionCountDetail; UserReactionCountDetailComponentStyles?: LLUserReactionCountDetailProps['styles']; MessageReactionPickerComponent?: typeof LLReactionPicker; MessageReactionPickerComponentStyles?: LLReactionPickerProps['styles']; }; const DEFAULT_REACTIONS_LIMIT = 4; const DUMMY_USER_REACTION_ID = 'DUMMY_USER_REACTION_ID'; export function LLUserReactionCounts({ targetGroupId, targetId, showReactionPicker, onReactionItemPress, styles: stylesProp, MessageReactionPickerComponentStyles, UserReactionCountDetailComponentStyles, reactionsLimit = DEFAULT_REACTIONS_LIMIT, UserReactionCountDetailComponent = LLUserReactionCountDetail, MessageReactionPickerComponent = LLReactionPicker, }: LLUserReactionCountsProps) { const [showAllReactions, setShowAllReactions] = useState(false); const { reactionSpace } = useReactionSpace({ targetGroupId, }); const reactionSpaceId = reactionSpace?.id; const { userReactions } = useUserReactions({ reactionSpaceId, targetId, }); const userReactionCountStyles = useStyles({ componentStylesFn: getRUserReactionCountStyles, stylesProp, }); const { addReaction, removeReaction } = useUserReactionActions({ targetGroupId, targetId, }); const { trackEvent } = useAnalytics(); const onReactionItemPressHandler = useCallback( async (reactionId: string) => { const selfReactionId = userReactions?.[reactionId]?.self_reacted_user_reaction_id; const actionArgs = { reactionSpaceId: reactionSpace?.id, userReaction: { target_id: targetId, reaction_id: reactionId, reacted_by_id: userProfile.id, id: DUMMY_USER_REACTION_ID, }, profileId: userProfile.id, }; if (selfReactionId) { removeReaction(actionArgs, selfReactionId); } else { addReaction(actionArgs); } onReactionItemPress?.(); }, [userReactions, reactionSpaceId, targetId, addReaction, removeReaction] ); const onReactionPanelOpen = useCallback(() => { trackEvent('Reaction Panel Opened', { targetId, targetGroupId, }); }, []); const onReactionPanelClose = useCallback(() => { trackEvent('Reaction Panel Closed', { targetId, targetGroupId, }); }, [targetId, targetGroupId, trackEvent]); const userReactionValues = useMemo( () => Object.values(userReactions), [userReactions] ); const reactionsRenderer = useMemo( () => (limit?: number) => userReactionValues.map( (reaction, index) => (!limit || index < limit) && reaction.count > 0 && ( ) ), [userReactions] ); const onShowAllReactionCounts = useCallback(() => { setShowAllReactions(true); }, [setShowAllReactions]); return ( <> {reactionsRenderer( showAllReactions ? userReactionValues.length : reactionsLimit )} {!showAllReactions && userReactionValues.length > reactionsLimit && ( {`+${userReactionValues.length - reactionsLimit} more`} )} {showReactionPicker && ( )} ); } const getRUserReactionCountStyles: LLComponentStyleFn< LLUserReactionCountsStyles > = ({ theme }) => StyleSheet.create({ reactionCountsContainer: { flexDirection: 'row', flexWrap: 'wrap', marginHorizontal: 3, flex: 1, }, moreReactionsView: { flexDirection: 'row', alignItems: 'center', backgroundColor: theme.popoverBackground, marginHorizontal: 3, marginBottom: 4, paddingHorizontal: 5, paddingVertical: 2, borderRadius: 4, }, moreReactionsText: { color: theme.text, fontSize: 11, lineHeight: 22, fontWeight: 'bold', }, });