import React, { useMemo } from 'react'; import { StyleSheet, View } from 'react-native'; import { LocalMessage } from 'stream-chat'; import { useMessageDateSeparator } from '../../../components/MessageList/hooks/useMessageDateSeparator'; import { useMessageGroupStyles } from '../../../components/MessageList/hooks/useMessageGroupStyles'; import { useChannelContext } from '../../../contexts/channelContext/ChannelContext'; import { useChatContext } from '../../../contexts/chatContext/ChatContext'; import { useComponentsContext } from '../../../contexts/componentsContext/ComponentsContext'; import { useMessageListItemContext } from '../../../contexts/messageListItemContext/MessageListItemContext'; import { useMessagesContext } from '../../../contexts/messagesContext/MessagesContext'; import { ThemeProvider, useTheme } from '../../../contexts/themeContext/ThemeContext'; import { useStateStore } from '../../../hooks/useStateStore'; import { ChannelUnreadStateStoreType } from '../../../state-store/channel-unread-state'; import { primitives } from '../../../theme'; const channelUnreadStateSelector = (state: ChannelUnreadStateStoreType) => ({ first_unread_message_id: state.channelUnreadState?.first_unread_message_id, last_read_message_id: state.channelUnreadState?.last_read_message_id, last_read_timestamp: state.channelUnreadState?.last_read?.getTime(), unread_messages: state.channelUnreadState?.unread_messages, }); export type MessageWrapperProps = { message: LocalMessage; previousMessage?: LocalMessage; nextMessage?: LocalMessage; }; export const MessageWrapper = React.memo((props: MessageWrapperProps) => { const { message, previousMessage, nextMessage } = props; const { client } = useChatContext(); const { channelUnreadStateStore, channel, hideDateSeparators, highlightedMessageId, maxTimeBetweenGroupedMessages, threadList, } = useChannelContext(); const { InlineDateSeparator, InlineUnreadIndicator, Message, MessageSystem } = useComponentsContext(); const { getMessageGroupStyle, myMessageTheme, shouldShowUnreadUnderlay } = useMessagesContext(); const { goToMessage, onThreadSelect, noGroupByUser, modifiedTheme } = useMessageListItemContext(); const dateSeparatorDate = useMessageDateSeparator({ hideDateSeparators, message, previousMessage, }); const isNewestMessage = nextMessage === undefined; const groupStyles = useMessageGroupStyles({ dateSeparatorDate, getMessageGroupStyle, maxTimeBetweenGroupedMessages, message, previousMessage, nextMessage, noGroupByUser, }); const { first_unread_message_id, last_read_timestamp, last_read_message_id, unread_messages } = useStateStore(channelUnreadStateStore.state, channelUnreadStateSelector); const { theme: { messageList: { messageContainer }, }, } = useTheme(); const styles = useStyles(); if (!channel || channel.disconnected) { return null; } const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime(); const isLastReadMessage = last_read_message_id === message.id || (!unread_messages && createdAtTimestamp === last_read_timestamp); const showUnreadSeparator = isLastReadMessage && !isNewestMessage && // The `channelUnreadState?.first_unread_message_id` is here for sent messages unread label (!!first_unread_message_id || !!unread_messages); const showUnreadUnderlay = !!shouldShowUnreadUnderlay && showUnreadSeparator; const wrapMessageInTheme = client.userID === message.user?.id && !!myMessageTheme; const renderDateSeperator = dateSeparatorDate ? ( ) : null; const renderMessage = ( ); return ( {message.type === 'system' ? ( ) : wrapMessageInTheme ? ( {renderDateSeperator} {renderMessage} ) : ( {renderDateSeperator} {renderMessage} )} {showUnreadUnderlay && ( )} ); }); const useStyles = () => { const { theme: { messageList: { unreadUnderlayContainer, inlineDateSeparatorContainer, systemMessageContainer, }, }, } = useTheme(); return useMemo( () => StyleSheet.create({ dateSeparatorContainer: { paddingVertical: primitives.spacingXs, ...inlineDateSeparatorContainer, }, unreadUnderlayContainer: { paddingVertical: primitives.spacingXs, ...unreadUnderlayContainer, }, systemMessageContainer: { alignItems: 'center', ...systemMessageContainer, }, }), [unreadUnderlayContainer, inlineDateSeparatorContainer, systemMessageContainer], ); };