Skip to content

Commit d9cebfa

Browse files
committed
fix: move renderItem in the MessageList outside of the main component
1 parent 25f812a commit d9cebfa

File tree

2 files changed

+189
-126
lines changed

2 files changed

+189
-126
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import React, { useMemo } from 'react';
2+
import { StyleSheet, View } from 'react-native';
3+
4+
import { isMessageWithStylesReadByAndDateSeparator, MessageType } from './hooks/useMessageList';
5+
6+
import { useChannelContext } from '../../contexts/channelContext/ChannelContext';
7+
import { useChatContext } from '../../contexts/chatContext/ChatContext';
8+
9+
import { useMessagesContext } from '../../contexts/messagesContext/MessagesContext';
10+
11+
import { mergeThemes, ThemeProvider, useTheme } from '../../contexts/themeContext/ThemeContext';
12+
import { ChannelUnreadState, DefaultStreamChatGenerics } from '../../types/types';
13+
14+
const shouldShowUnreadSeparator = <
15+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
16+
>(
17+
message: MessageType<StreamChatGenerics>,
18+
index: number,
19+
unreadState?: ChannelUnreadState,
20+
) => {
21+
if (!unreadState) {
22+
return false;
23+
}
24+
const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
25+
const lastReadTimestamp = unreadState?.last_read?.getTime();
26+
const isNewestMessage = index === 0;
27+
const isLastReadMessage =
28+
unreadState?.last_read_message_id === message.id ||
29+
(!unreadState?.unread_messages && createdAtTimestamp === lastReadTimestamp);
30+
31+
const showUnreadSeparator =
32+
isLastReadMessage &&
33+
!isNewestMessage &&
34+
(!!unreadState?.first_unread_message_id || !!unreadState?.unread_messages);
35+
36+
return showUnreadSeparator;
37+
};
38+
39+
export const MessageItem = <
40+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
41+
>({
42+
index,
43+
message,
44+
goToMessage,
45+
highlightedMessageId,
46+
lastReceivedMessageId,
47+
onThreadSelect,
48+
shouldApplyAndroidWorkaround,
49+
}: {
50+
index: number;
51+
message: MessageType<StreamChatGenerics>;
52+
goToMessage: (messageId: string) => Promise<void>;
53+
highlightedMessageId?: string;
54+
lastReceivedMessageId?: string;
55+
onThreadSelect?: (message: MessageType<DefaultStreamChatGenerics>) => void;
56+
shouldApplyAndroidWorkaround: boolean;
57+
}) => {
58+
const { client } = useChatContext();
59+
const clientUserId = client.user?.id;
60+
const { theme } = useTheme();
61+
const {
62+
messageList: { messageContainer },
63+
screenPadding,
64+
} = theme;
65+
66+
const { channelUnreadState, threadList } = useChannelContext();
67+
const {
68+
Message,
69+
MessageSystem,
70+
myMessageTheme,
71+
InlineDateSeparator,
72+
InlineUnreadIndicator,
73+
shouldShowUnreadUnderlay,
74+
} = useMessagesContext();
75+
76+
const myMessageThemeString = useMemo(() => JSON.stringify(myMessageTheme), [myMessageTheme]);
77+
78+
const modifiedTheme = useMemo(
79+
() => mergeThemes({ style: myMessageTheme, theme }),
80+
// eslint-disable-next-line react-hooks/exhaustive-deps
81+
[myMessageThemeString, theme],
82+
);
83+
84+
const showUnreadUnderlay =
85+
!!shouldShowUnreadUnderlay && shouldShowUnreadSeparator(message, index, channelUnreadState);
86+
87+
const wrapMessageInTheme = clientUserId === message.user?.id && !!myMessageTheme;
88+
const renderDateSeperator = isMessageWithStylesReadByAndDateSeparator(message) &&
89+
message.dateSeparator && <InlineDateSeparator date={message.dateSeparator} />;
90+
91+
const renderMessage = (
92+
<Message
93+
goToMessage={goToMessage}
94+
groupStyles={isMessageWithStylesReadByAndDateSeparator(message) ? message.groupStyles : []}
95+
isTargetedMessage={highlightedMessageId === message.id}
96+
lastReceivedId={
97+
lastReceivedMessageId === message.id || message.quoted_message_id
98+
? lastReceivedMessageId
99+
: undefined
100+
}
101+
message={message}
102+
onThreadSelect={onThreadSelect}
103+
showUnreadUnderlay={showUnreadUnderlay}
104+
style={[messageContainer]}
105+
threadList={threadList}
106+
/>
107+
);
108+
109+
return (
110+
<View
111+
style={[shouldApplyAndroidWorkaround ? styles.invertAndroid : undefined]}
112+
testID={`message-list-item-${index}`}
113+
>
114+
{message.type === 'system' ? (
115+
<MessageSystem
116+
message={message}
117+
style={[{ paddingHorizontal: screenPadding }, messageContainer]}
118+
/>
119+
) : wrapMessageInTheme ? (
120+
<ThemeProvider mergedStyle={modifiedTheme}>
121+
<View testID={`message-list-item-${index}`}>
122+
{renderDateSeperator}
123+
{renderMessage}
124+
</View>
125+
</ThemeProvider>
126+
) : (
127+
<View testID={`message-list-item-${index}`}>
128+
{renderDateSeperator}
129+
{renderMessage}
130+
</View>
131+
)}
132+
{showUnreadUnderlay && <InlineUnreadIndicator />}
133+
</View>
134+
);
135+
};
136+
137+
const styles = StyleSheet.create({
138+
invertAndroid: {
139+
transform: [{ scaleX: -1 }, { scaleY: -1 }],
140+
},
141+
});

0 commit comments

Comments
 (0)