diff --git a/package/src/components/Channel/Channel.tsx b/package/src/components/Channel/Channel.tsx index 03a2c3a0b9..8341ed10e2 100644 --- a/package/src/components/Channel/Channel.tsx +++ b/package/src/components/Channel/Channel.tsx @@ -158,6 +158,10 @@ import { MessageStatus as MessageStatusDefault } from '../Message/MessageSimple/ import { MessageSwipeContent as MessageSwipeContentDefault } from '../Message/MessageSimple/MessageSwipeContent'; import { MessageTimestamp as MessageTimestampDefault } from '../Message/MessageSimple/MessageTimestamp'; import { ReactionListBottom as ReactionListBottomDefault } from '../Message/MessageSimple/ReactionList/ReactionListBottom'; +import { ReactionListClustered as ReactionListClusteredDefault } from '../Message/MessageSimple/ReactionList/ReactionListClustered'; +import { ReactionListCountItem as ReactionListCountItemDefault } from '../Message/MessageSimple/ReactionList/ReactionListItem'; +import { ReactionListItem as ReactionListItemDefault } from '../Message/MessageSimple/ReactionList/ReactionListItem'; +import { ReactionListItemWrapper as ReactionListItemWrapperDefault } from '../Message/MessageSimple/ReactionList/ReactionListItemWrapper'; import { ReactionListTop as ReactionListTopDefault } from '../Message/MessageSimple/ReactionList/ReactionListTop'; import { StreamingMessageView as DefaultStreamingMessageView } from '../Message/MessageSimple/StreamingMessageView'; import { AttachmentUploadPreviewList as AttachmentUploadPreviewDefault } from '../MessageInput/components/AttachmentPreview/AttachmentUploadPreviewList'; @@ -393,6 +397,10 @@ export type ChannelPropsWithContext = Pick & | 'reactionListPosition' | 'reactionListType' | 'ReactionListTop' + | 'ReactionListClustered' + | 'ReactionListItem' + | 'ReactionListItemWrapper' + | 'ReactionListCountItem' | 'Reply' | 'shouldShowUnreadUnderlay' | 'ScrollToBottomButton' @@ -722,6 +730,10 @@ const ChannelWithContext = (props: PropsWithChildren) = reactionListPosition = 'top', reactionListType = 'clustered', ReactionListTop = ReactionListTopDefault, + ReactionListClustered = ReactionListClusteredDefault, + ReactionListItem = ReactionListItemDefault, + ReactionListItemWrapper = ReactionListItemWrapperDefault, + ReactionListCountItem = ReactionListCountItemDefault, Reply = ReplyDefault, ScrollToBottomButton = ScrollToBottomButtonDefault, selectReaction, @@ -1978,6 +1990,10 @@ const ChannelWithContext = (props: PropsWithChildren) = reactionListPosition, reactionListType, ReactionListTop, + ReactionListClustered, + ReactionListItem, + ReactionListItemWrapper, + ReactionListCountItem, removeMessage, Reply, retrySendMessage, diff --git a/package/src/components/Channel/hooks/useCreateMessagesContext.ts b/package/src/components/Channel/hooks/useCreateMessagesContext.ts index 178ce6a077..31fc4491bd 100644 --- a/package/src/components/Channel/hooks/useCreateMessagesContext.ts +++ b/package/src/components/Channel/hooks/useCreateMessagesContext.ts @@ -91,6 +91,10 @@ export const useCreateMessagesContext = ({ reactionListPosition, reactionListType, ReactionListTop, + ReactionListClustered, + ReactionListItem, + ReactionListItemWrapper, + ReactionListCountItem, removeMessage, Reply, retrySendMessage, @@ -207,6 +211,10 @@ export const useCreateMessagesContext = ({ reactionListPosition, reactionListType, ReactionListTop, + ReactionListClustered, + ReactionListItem, + ReactionListItemWrapper, + ReactionListCountItem, removeMessage, Reply, retrySendMessage, diff --git a/package/src/components/Message/MessageSimple/ReactionList/ReactionListBottom.tsx b/package/src/components/Message/MessageSimple/ReactionList/ReactionListBottom.tsx index b029f74249..641b0a8d44 100644 --- a/package/src/components/Message/MessageSimple/ReactionList/ReactionListBottom.tsx +++ b/package/src/components/Message/MessageSimple/ReactionList/ReactionListBottom.tsx @@ -1,8 +1,7 @@ -import React, { useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { FlatList, StyleSheet, View } from 'react-native'; -import { ReactionListClustered } from './ReactionListClustered'; -import { ReactionListItem, ReactionListItemProps } from './ReactionListItem'; +import { ReactionListItemProps } from './ReactionListItem'; import { MessageContextValue, @@ -16,22 +15,6 @@ import { useTheme } from '../../../../contexts/themeContext/ThemeContext'; import { primitives } from '../../../../theme'; -const renderItem = ({ index, item }: { index: number; item: ReactionListItemProps }) => ( - -); - export type ReactionListBottomProps = Partial< Pick< MessageContextValue, @@ -46,7 +29,9 @@ export type ReactionListBottomProps = Partial< | 'showReactionsOverlay' > > & - Partial> & { + Partial< + Pick + > & { type?: 'clustered' | 'segmented'; showCount?: boolean; }; @@ -70,6 +55,8 @@ export const ReactionListBottom = (props: ReactionListBottomProps) => { supportedReactions: propSupportedReactions, type, showCount = true, + ReactionListClustered: propReactionListClustered, + ReactionListItem: propReactionListItem, } = props; const { @@ -84,7 +71,11 @@ export const ReactionListBottom = (props: ReactionListBottomProps) => { showReactionsOverlay: contextShowReactionsOverlay, } = useMessageContext(); - const { supportedReactions: contextSupportedReactions } = useMessagesContext(); + const { + supportedReactions: contextSupportedReactions, + ReactionListClustered: contextReactionListClustered, + ReactionListItem: contextReactionListItem, + } = useMessagesContext(); const alignment = propAlignment || contextAlignment; const handleReaction = propHandlerReaction || contextHandleReaction; @@ -96,6 +87,27 @@ export const ReactionListBottom = (props: ReactionListBottomProps) => { const reactions = propReactions || contextReactions; const showReactionsOverlay = propShowReactionsOverlay || contextShowReactionsOverlay; const supportedReactions = propSupportedReactions || contextSupportedReactions; + const ReactionListClustered = propReactionListClustered || contextReactionListClustered; + const ReactionListItem = propReactionListItem || contextReactionListItem; + + const renderItem = useCallback( + ({ index, item }: { index: number; item: ReactionListItemProps }) => ( + + ), + [ReactionListItem], + ); const styles = useStyles({ messageAlignment: alignment }); const supportedReactionTypes = supportedReactions?.map( diff --git a/package/src/components/Message/MessageSimple/ReactionList/ReactionListItemWrapper.tsx b/package/src/components/Message/MessageSimple/ReactionList/ReactionListItemWrapper.tsx index 4f33cab3f3..4bb0664c4d 100644 --- a/package/src/components/Message/MessageSimple/ReactionList/ReactionListItemWrapper.tsx +++ b/package/src/components/Message/MessageSimple/ReactionList/ReactionListItemWrapper.tsx @@ -4,7 +4,7 @@ import { Pressable, PressableProps, StyleProp, StyleSheet, View, ViewStyle } fro import { useTheme } from '../../../../contexts/themeContext/ThemeContext'; import { primitives } from '../../../../theme'; -type ReactionListItemWrapperProps = PressableProps & { +export type ReactionListItemWrapperProps = PressableProps & { selected?: boolean; style?: StyleProp; }; diff --git a/package/src/components/Message/MessageSimple/ReactionList/ReactionListTop.tsx b/package/src/components/Message/MessageSimple/ReactionList/ReactionListTop.tsx index c012ac3bf1..7393f392f7 100644 --- a/package/src/components/Message/MessageSimple/ReactionList/ReactionListTop.tsx +++ b/package/src/components/Message/MessageSimple/ReactionList/ReactionListTop.tsx @@ -1,10 +1,6 @@ import React, { useMemo } from 'react'; import { ScrollView, StyleSheet, View } from 'react-native'; -import { ReactionListClustered } from './ReactionListClustered'; - -import { ReactionListCountItem, ReactionListItem } from './ReactionListItem'; - import { useTheme } from '../../../../contexts'; import { MessageContextValue, @@ -29,12 +25,19 @@ export type ReactionListTopProps = Partial< | 'reactions' | 'showReactionsOverlay' | 'handleReaction' - > -> & - Pick & { - type?: 'clustered' | 'segmented'; - showCount?: boolean; - }; + > & + Pick< + MessagesContextValue, + | 'supportedReactions' + | 'reactionListType' + | 'ReactionListClustered' + | 'ReactionListItem' + | 'ReactionListCountItem' + > +> & { + type?: 'clustered' | 'segmented'; + showCount?: boolean; +}; /** * ReactionListTop - A high level component which implements all the logic required for a message reaction list @@ -53,6 +56,9 @@ export const ReactionListTop = (props: ReactionListTopProps) => { handleReaction: propHandleReaction, type, showCount = true, + ReactionListClustered: propReactionListClustered, + ReactionListItem: propReactionListItem, + ReactionListCountItem: propReactionListCountItem, } = props; const { @@ -67,7 +73,12 @@ export const ReactionListTop = (props: ReactionListTopProps) => { handleReaction: contextHandleReaction, } = useMessageContext(); - const { supportedReactions: contextSupportedReactions } = useMessagesContext(); + const { + supportedReactions: contextSupportedReactions, + ReactionListClustered: contextReactionListClustered, + ReactionListItem: contextReactionListItem, + ReactionListCountItem: contextReactionListCountItem, + } = useMessagesContext(); const alignment = propAlignment || contextAlignment; const hasReactions = propHasReactions || contextHasReactions; @@ -79,6 +90,10 @@ export const ReactionListTop = (props: ReactionListTopProps) => { const showReactionsOverlay = propShowReactionsOverlay || contextShowReactionsOverlay; const supportedReactions = propSupportedReactions || contextSupportedReactions; const handleReaction = propHandleReaction || contextHandleReaction; + const ReactionListClustered = propReactionListClustered || contextReactionListClustered; + const ReactionListItem = propReactionListItem || contextReactionListItem; + const ReactionListCountItem = propReactionListCountItem || contextReactionListCountItem; + const styles = useStyles({ alignment }); const supportedReactionTypes = supportedReactions?.map( diff --git a/package/src/components/index.ts b/package/src/components/index.ts index b5402f95a1..c365b49536 100644 --- a/package/src/components/index.ts +++ b/package/src/components/index.ts @@ -106,6 +106,9 @@ export * from './Message/MessageSimple/MessageTextContainer'; export * from './Message/MessageSimple/MessageTimestamp'; export * from './Message/MessageSimple/ReactionList/ReactionListBottom'; export * from './Message/MessageSimple/ReactionList/ReactionListTop'; +export * from './Message/MessageSimple/ReactionList/ReactionListClustered'; +export * from './Message/MessageSimple/ReactionList/ReactionListItem'; +export * from './Message/MessageSimple/ReactionList/ReactionListItemWrapper'; export * from './Message/MessageSimple/utils/renderText'; export * from './Message/utils/messageActions'; export * from '../utils/removeReservedFields'; diff --git a/package/src/contexts/messagesContext/MessagesContext.tsx b/package/src/contexts/messagesContext/MessagesContext.tsx index 53adab5444..6b089eba62 100644 --- a/package/src/contexts/messagesContext/MessagesContext.tsx +++ b/package/src/contexts/messagesContext/MessagesContext.tsx @@ -49,6 +49,12 @@ import type { MessageStatusProps } from '../../components/Message/MessageSimple/ import type { MessageTextProps } from '../../components/Message/MessageSimple/MessageTextContainer'; import { MessageTimestampProps } from '../../components/Message/MessageSimple/MessageTimestamp'; import { ReactionListBottomProps } from '../../components/Message/MessageSimple/ReactionList/ReactionListBottom'; +import { ReactionListClusteredProps } from '../../components/Message/MessageSimple/ReactionList/ReactionListClustered'; +import { + ReactionListItemProps, + ReactionListCountItemProps, +} from '../../components/Message/MessageSimple/ReactionList/ReactionListItem'; +import { ReactionListItemWrapperProps } from '../../components/Message/MessageSimple/ReactionList/ReactionListItemWrapper'; import type { ReactionListTopProps } from '../../components/Message/MessageSimple/ReactionList/ReactionListTop'; import type { MarkdownRules } from '../../components/Message/MessageSimple/utils/renderText'; import type { MessageActionsParams } from '../../components/Message/utils/messageActions'; @@ -608,6 +614,25 @@ export type MessagesContextValue = Pick; + /** + * UI component for ReactionListBottom + * Defaults to: [ReactionList](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Reaction/ReactionList.tsx) + */ + ReactionListClustered: React.ComponentType; + /** + * UI component for ReactionListSegmented + * Defaults to: [ReactionList](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Reaction/ReactionList.tsx) + */ + ReactionListItem: React.ComponentType; + + /** + * UI component for ReactionListItemWrapper + * Defaults to: [ReactionListItemWrapper](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Reaction/ReactionListItemWrapper.tsx) + */ + ReactionListItemWrapper: React.ComponentType; + + ReactionListCountItem: React.ComponentType; + /** * Full override of the reaction function on Message and Message Overlay *