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],
);
};