stream-chat-react-native-core 8.11.0 → 8.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/components/Channel/Channel.js +26 -17
  3. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  4. package/lib/commonjs/components/Channel/hooks/useCreateChannelContext.js +3 -2
  5. package/lib/commonjs/components/Channel/hooks/useCreateChannelContext.js.map +1 -1
  6. package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +4 -0
  7. package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
  8. package/lib/commonjs/components/Message/Message.js +6 -8
  9. package/lib/commonjs/components/Message/Message.js.map +1 -1
  10. package/lib/commonjs/components/Message/MessageSimple/MessageBlocked.js +70 -0
  11. package/lib/commonjs/components/Message/MessageSimple/MessageBlocked.js.map +1 -0
  12. package/lib/commonjs/components/Message/MessageSimple/MessageContent.js +0 -2
  13. package/lib/commonjs/components/Message/MessageSimple/MessageContent.js.map +1 -1
  14. package/lib/commonjs/components/Message/MessageSimple/MessageWrapper.js +126 -0
  15. package/lib/commonjs/components/Message/MessageSimple/MessageWrapper.js.map +1 -0
  16. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +1 -3
  17. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  18. package/lib/commonjs/components/MessageList/MessageFlashList.js +74 -105
  19. package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
  20. package/lib/commonjs/components/MessageList/MessageList.js +77 -119
  21. package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
  22. package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js +2 -2
  23. package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js.map +1 -1
  24. package/lib/commonjs/components/MessageList/hooks/useMessageDateSeparator.js +45 -0
  25. package/lib/commonjs/components/MessageList/hooks/useMessageDateSeparator.js.map +1 -0
  26. package/lib/commonjs/components/MessageList/hooks/useMessageGroupStyles.js +46 -0
  27. package/lib/commonjs/components/MessageList/hooks/useMessageGroupStyles.js.map +1 -0
  28. package/lib/commonjs/components/MessageList/hooks/useMessageList.js +49 -29
  29. package/lib/commonjs/components/MessageList/hooks/useMessageList.js.map +1 -1
  30. package/lib/commonjs/components/MessageList/utils/getDateSeparators.js +5 -14
  31. package/lib/commonjs/components/MessageList/utils/getDateSeparators.js.map +1 -1
  32. package/lib/commonjs/components/MessageList/utils/getGroupStyles.js +22 -17
  33. package/lib/commonjs/components/MessageList/utils/getGroupStyles.js.map +1 -1
  34. package/lib/commonjs/components/MessageList/utils/getLastReceivedMessage.js +1 -1
  35. package/lib/commonjs/components/MessageList/utils/getLastReceivedMessage.js.map +1 -1
  36. package/lib/commonjs/components/index.js +33 -0
  37. package/lib/commonjs/components/index.js.map +1 -1
  38. package/lib/commonjs/contexts/channelContext/ChannelContext.js.map +1 -1
  39. package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
  40. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +3 -0
  41. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  42. package/lib/commonjs/contexts/messageListItemContext/MessageListItemContext.js +29 -0
  43. package/lib/commonjs/contexts/messageListItemContext/MessageListItemContext.js.map +1 -0
  44. package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
  45. package/lib/commonjs/contexts/themeContext/utils/theme.js +6 -0
  46. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  47. package/lib/commonjs/state-store/channel-unread-state.js +31 -0
  48. package/lib/commonjs/state-store/channel-unread-state.js.map +1 -0
  49. package/lib/commonjs/state-store/message-list-prev-next-state.js +46 -0
  50. package/lib/commonjs/state-store/message-list-prev-next-state.js.map +1 -0
  51. package/lib/commonjs/store/apis/getChannelMessages.js +7 -10
  52. package/lib/commonjs/store/apis/getChannelMessages.js.map +1 -1
  53. package/lib/commonjs/utils/utils.js +4 -4
  54. package/lib/commonjs/utils/utils.js.map +1 -1
  55. package/lib/commonjs/version.json +1 -1
  56. package/lib/module/components/Channel/Channel.js +26 -17
  57. package/lib/module/components/Channel/Channel.js.map +1 -1
  58. package/lib/module/components/Channel/hooks/useCreateChannelContext.js +3 -2
  59. package/lib/module/components/Channel/hooks/useCreateChannelContext.js.map +1 -1
  60. package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +4 -0
  61. package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
  62. package/lib/module/components/Message/Message.js +6 -8
  63. package/lib/module/components/Message/Message.js.map +1 -1
  64. package/lib/module/components/Message/MessageSimple/MessageBlocked.js +70 -0
  65. package/lib/module/components/Message/MessageSimple/MessageBlocked.js.map +1 -0
  66. package/lib/module/components/Message/MessageSimple/MessageContent.js +0 -2
  67. package/lib/module/components/Message/MessageSimple/MessageContent.js.map +1 -1
  68. package/lib/module/components/Message/MessageSimple/MessageWrapper.js +126 -0
  69. package/lib/module/components/Message/MessageSimple/MessageWrapper.js.map +1 -0
  70. package/lib/module/components/Message/hooks/useCreateMessageContext.js +1 -3
  71. package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  72. package/lib/module/components/MessageList/MessageFlashList.js +74 -105
  73. package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
  74. package/lib/module/components/MessageList/MessageList.js +77 -119
  75. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  76. package/lib/module/components/MessageList/UnreadMessagesNotification.js +2 -2
  77. package/lib/module/components/MessageList/UnreadMessagesNotification.js.map +1 -1
  78. package/lib/module/components/MessageList/hooks/useMessageDateSeparator.js +45 -0
  79. package/lib/module/components/MessageList/hooks/useMessageDateSeparator.js.map +1 -0
  80. package/lib/module/components/MessageList/hooks/useMessageGroupStyles.js +46 -0
  81. package/lib/module/components/MessageList/hooks/useMessageGroupStyles.js.map +1 -0
  82. package/lib/module/components/MessageList/hooks/useMessageList.js +49 -29
  83. package/lib/module/components/MessageList/hooks/useMessageList.js.map +1 -1
  84. package/lib/module/components/MessageList/utils/getDateSeparators.js +5 -14
  85. package/lib/module/components/MessageList/utils/getDateSeparators.js.map +1 -1
  86. package/lib/module/components/MessageList/utils/getGroupStyles.js +22 -17
  87. package/lib/module/components/MessageList/utils/getGroupStyles.js.map +1 -1
  88. package/lib/module/components/MessageList/utils/getLastReceivedMessage.js +1 -1
  89. package/lib/module/components/MessageList/utils/getLastReceivedMessage.js.map +1 -1
  90. package/lib/module/components/index.js +33 -0
  91. package/lib/module/components/index.js.map +1 -1
  92. package/lib/module/contexts/channelContext/ChannelContext.js.map +1 -1
  93. package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
  94. package/lib/module/contexts/messageInputContext/MessageInputContext.js +3 -0
  95. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  96. package/lib/module/contexts/messageListItemContext/MessageListItemContext.js +29 -0
  97. package/lib/module/contexts/messageListItemContext/MessageListItemContext.js.map +1 -0
  98. package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
  99. package/lib/module/contexts/themeContext/utils/theme.js +6 -0
  100. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  101. package/lib/module/state-store/channel-unread-state.js +31 -0
  102. package/lib/module/state-store/channel-unread-state.js.map +1 -0
  103. package/lib/module/state-store/message-list-prev-next-state.js +46 -0
  104. package/lib/module/state-store/message-list-prev-next-state.js.map +1 -0
  105. package/lib/module/store/apis/getChannelMessages.js +7 -10
  106. package/lib/module/store/apis/getChannelMessages.js.map +1 -1
  107. package/lib/module/utils/utils.js +4 -4
  108. package/lib/module/utils/utils.js.map +1 -1
  109. package/lib/module/version.json +1 -1
  110. package/lib/typescript/components/Channel/Channel.d.ts +3 -3
  111. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  112. package/lib/typescript/components/Channel/hooks/useCreateChannelContext.d.ts +1 -1
  113. package/lib/typescript/components/Channel/hooks/useCreateChannelContext.d.ts.map +1 -1
  114. package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +1 -1
  115. package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts.map +1 -1
  116. package/lib/typescript/components/Channel/hooks/useMessageListPagination.d.ts +2 -2
  117. package/lib/typescript/components/Channel/hooks/useMessageListPagination.d.ts.map +1 -1
  118. package/lib/typescript/components/Message/Message.d.ts +1 -1
  119. package/lib/typescript/components/Message/Message.d.ts.map +1 -1
  120. package/lib/typescript/components/Message/MessageSimple/MessageBlocked.d.ts +19 -0
  121. package/lib/typescript/components/Message/MessageSimple/MessageBlocked.d.ts.map +1 -0
  122. package/lib/typescript/components/Message/MessageSimple/MessageContent.d.ts.map +1 -1
  123. package/lib/typescript/components/Message/MessageSimple/MessageWrapper.d.ts +7 -0
  124. package/lib/typescript/components/Message/MessageSimple/MessageWrapper.d.ts.map +1 -0
  125. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts +1 -1
  126. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts.map +1 -1
  127. package/lib/typescript/components/MessageList/MessageFlashList.d.ts +1 -1
  128. package/lib/typescript/components/MessageList/MessageFlashList.d.ts.map +1 -1
  129. package/lib/typescript/components/MessageList/MessageList.d.ts +1 -1
  130. package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
  131. package/lib/typescript/components/MessageList/hooks/useMessageDateSeparator.d.ts +16 -0
  132. package/lib/typescript/components/MessageList/hooks/useMessageDateSeparator.d.ts.map +1 -0
  133. package/lib/typescript/components/MessageList/hooks/useMessageGroupStyles.d.ts +15 -0
  134. package/lib/typescript/components/MessageList/hooks/useMessageGroupStyles.d.ts.map +1 -0
  135. package/lib/typescript/components/MessageList/hooks/useMessageList.d.ts +8 -0
  136. package/lib/typescript/components/MessageList/hooks/useMessageList.d.ts.map +1 -1
  137. package/lib/typescript/components/MessageList/utils/getDateSeparators.d.ts +12 -0
  138. package/lib/typescript/components/MessageList/utils/getDateSeparators.d.ts.map +1 -1
  139. package/lib/typescript/components/MessageList/utils/getGroupStyles.d.ts +25 -0
  140. package/lib/typescript/components/MessageList/utils/getGroupStyles.d.ts.map +1 -1
  141. package/lib/typescript/components/MessageList/utils/getLastReceivedMessage.d.ts.map +1 -1
  142. package/lib/typescript/components/index.d.ts +3 -0
  143. package/lib/typescript/components/index.d.ts.map +1 -1
  144. package/lib/typescript/contexts/channelContext/ChannelContext.d.ts +10 -4
  145. package/lib/typescript/contexts/channelContext/ChannelContext.d.ts.map +1 -1
  146. package/lib/typescript/contexts/messageContext/MessageContext.d.ts +4 -1
  147. package/lib/typescript/contexts/messageContext/MessageContext.d.ts.map +1 -1
  148. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts.map +1 -1
  149. package/lib/typescript/contexts/messageListItemContext/MessageListItemContext.d.ts +37 -0
  150. package/lib/typescript/contexts/messageListItemContext/MessageListItemContext.d.ts.map +1 -0
  151. package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +11 -1
  152. package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts.map +1 -1
  153. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +6 -0
  154. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  155. package/lib/typescript/hooks/useTranslatedMessage.d.ts.map +1 -1
  156. package/lib/typescript/state-store/channel-unread-state.d.ts +12 -0
  157. package/lib/typescript/state-store/channel-unread-state.d.ts.map +1 -0
  158. package/lib/typescript/state-store/message-list-prev-next-state.d.ts +16 -0
  159. package/lib/typescript/state-store/message-list-prev-next-state.d.ts.map +1 -0
  160. package/lib/typescript/store/apis/getChannelMessages.d.ts.map +1 -1
  161. package/lib/typescript/utils/utils.d.ts +1 -2
  162. package/lib/typescript/utils/utils.d.ts.map +1 -1
  163. package/package.json +2 -2
  164. package/src/components/Channel/Channel.tsx +31 -16
  165. package/src/components/Channel/hooks/useCreateChannelContext.ts +2 -2
  166. package/src/components/Channel/hooks/useCreateMessagesContext.ts +4 -0
  167. package/src/components/Message/Message.tsx +6 -15
  168. package/src/components/Message/MessageSimple/MessageBlocked.tsx +67 -0
  169. package/src/components/Message/MessageSimple/MessageContent.tsx +0 -2
  170. package/src/components/Message/MessageSimple/MessageWrapper.tsx +147 -0
  171. package/src/components/Message/MessageSimple/__tests__/MessageStatus.test.js +1 -5
  172. package/src/components/Message/hooks/useCreateMessageContext.ts +0 -3
  173. package/src/components/MessageList/MessageFlashList.tsx +81 -143
  174. package/src/components/MessageList/MessageList.tsx +83 -165
  175. package/src/components/MessageList/UnreadMessagesNotification.tsx +2 -2
  176. package/src/components/MessageList/__tests__/MessageList.test.js +10 -8
  177. package/src/components/MessageList/__tests__/useMessageDateSeparator.test.ts +83 -0
  178. package/src/components/MessageList/hooks/useMessageDateSeparator.ts +66 -0
  179. package/src/components/MessageList/hooks/useMessageGroupStyles.ts +75 -0
  180. package/src/components/MessageList/hooks/useMessageList.ts +68 -36
  181. package/src/components/MessageList/utils/getDateSeparators.ts +16 -20
  182. package/src/components/MessageList/utils/getGroupStyles.ts +44 -33
  183. package/src/components/MessageList/utils/getLastReceivedMessage.ts +1 -4
  184. package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +6 -6
  185. package/src/components/index.ts +3 -0
  186. package/src/contexts/channelContext/ChannelContext.tsx +13 -4
  187. package/src/contexts/messageContext/MessageContext.tsx +4 -1
  188. package/src/contexts/messageInputContext/MessageInputContext.tsx +5 -0
  189. package/src/contexts/messageListItemContext/MessageListItemContext.tsx +63 -0
  190. package/src/contexts/messagesContext/MessagesContext.tsx +16 -1
  191. package/src/contexts/themeContext/utils/theme.ts +12 -0
  192. package/src/state-store/channel-unread-state.ts +28 -0
  193. package/src/state-store/message-list-prev-next-state.ts +58 -0
  194. package/src/store/apis/getChannelMessages.ts +9 -12
  195. package/src/utils/utils.ts +9 -8
  196. package/src/version.json +1 -1
  197. package/src/components/MessageList/utils/__tests__/getDateSeparators.test.ts +0 -71
@@ -0,0 +1,147 @@
1
+ import React, { useCallback } from 'react';
2
+
3
+ import { View } from 'react-native';
4
+
5
+ import { LocalMessage } from 'stream-chat';
6
+
7
+ import { useMessageDateSeparator } from '../../../components/MessageList/hooks/useMessageDateSeparator';
8
+ import { useMessageGroupStyles } from '../../../components/MessageList/hooks/useMessageGroupStyles';
9
+ import { useChannelContext } from '../../../contexts/channelContext/ChannelContext';
10
+ import { useChatContext } from '../../../contexts/chatContext/ChatContext';
11
+ import { useMessageListItemContext } from '../../../contexts/messageListItemContext/MessageListItemContext';
12
+ import { useMessagesContext } from '../../../contexts/messagesContext/MessagesContext';
13
+ import { ThemeProvider, useTheme } from '../../../contexts/themeContext/ThemeContext';
14
+
15
+ import { useStateStore } from '../../../hooks/useStateStore';
16
+ import { ChannelUnreadStateStoreType } from '../../../state-store/channel-unread-state';
17
+ import { MessagePreviousAndNextMessageStoreType } from '../../../state-store/message-list-prev-next-state';
18
+
19
+ const channelUnreadStateSelector = (state: ChannelUnreadStateStoreType) => ({
20
+ first_unread_message_id: state.channelUnreadState?.first_unread_message_id,
21
+ last_read_message_id: state.channelUnreadState?.last_read_message_id,
22
+ last_read_timestamp: state.channelUnreadState?.last_read?.getTime(),
23
+ unread_messages: state.channelUnreadState?.unread_messages,
24
+ });
25
+
26
+ export type MessageWrapperProps = {
27
+ message: LocalMessage;
28
+ };
29
+
30
+ export const MessageWrapper = React.memo((props: MessageWrapperProps) => {
31
+ const { message } = props;
32
+ const { client } = useChatContext();
33
+ const {
34
+ channelUnreadStateStore,
35
+ channel,
36
+ hideDateSeparators,
37
+ highlightedMessageId,
38
+ maxTimeBetweenGroupedMessages,
39
+ threadList,
40
+ } = useChannelContext();
41
+ const {
42
+ getMessageGroupStyle,
43
+ InlineDateSeparator,
44
+ InlineUnreadIndicator,
45
+ Message,
46
+ MessageSystem,
47
+ myMessageTheme,
48
+ shouldShowUnreadUnderlay,
49
+ } = useMessagesContext();
50
+ const {
51
+ goToMessage,
52
+ onThreadSelect,
53
+ noGroupByUser,
54
+ modifiedTheme,
55
+ messageListPreviousAndNextMessageStore,
56
+ } = useMessageListItemContext();
57
+
58
+ const dateSeparatorDate = useMessageDateSeparator({
59
+ hideDateSeparators,
60
+ message,
61
+ messageListPreviousAndNextMessageStore,
62
+ });
63
+
64
+ const selector = useCallback(
65
+ (state: MessagePreviousAndNextMessageStoreType) => ({
66
+ nextMessage: state.messageList[message.id]?.nextMessage,
67
+ }),
68
+ [message.id],
69
+ );
70
+ const { nextMessage } = useStateStore(messageListPreviousAndNextMessageStore.state, selector);
71
+ const isNewestMessage = nextMessage === undefined;
72
+ const groupStyles = useMessageGroupStyles({
73
+ dateSeparatorDate,
74
+ getMessageGroupStyle,
75
+ maxTimeBetweenGroupedMessages,
76
+ message,
77
+ messageListPreviousAndNextMessageStore,
78
+ noGroupByUser,
79
+ });
80
+
81
+ const { first_unread_message_id, last_read_timestamp, last_read_message_id, unread_messages } =
82
+ useStateStore(channelUnreadStateStore.state, channelUnreadStateSelector);
83
+ const {
84
+ theme: {
85
+ messageList: { messageContainer },
86
+ screenPadding,
87
+ },
88
+ } = useTheme();
89
+ if (!channel || channel.disconnected) {
90
+ return null;
91
+ }
92
+
93
+ const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
94
+ const isLastReadMessage =
95
+ last_read_message_id === message.id ||
96
+ (!unread_messages && createdAtTimestamp === last_read_timestamp);
97
+
98
+ const showUnreadSeparator =
99
+ isLastReadMessage &&
100
+ !isNewestMessage &&
101
+ // The `channelUnreadState?.first_unread_message_id` is here for sent messages unread label
102
+ (!!first_unread_message_id || !!unread_messages);
103
+
104
+ const showUnreadUnderlay = !!shouldShowUnreadUnderlay && showUnreadSeparator;
105
+
106
+ const wrapMessageInTheme = client.userID === message.user?.id && !!myMessageTheme;
107
+ const renderDateSeperator = dateSeparatorDate ? (
108
+ <InlineDateSeparator date={dateSeparatorDate} />
109
+ ) : null;
110
+
111
+ const renderMessage = (
112
+ <Message
113
+ goToMessage={goToMessage}
114
+ groupStyles={groupStyles}
115
+ isTargetedMessage={highlightedMessageId === message.id}
116
+ message={message}
117
+ onThreadSelect={onThreadSelect}
118
+ showUnreadUnderlay={showUnreadUnderlay}
119
+ style={[messageContainer]}
120
+ threadList={threadList}
121
+ />
122
+ );
123
+
124
+ return (
125
+ <View testID={`message-list-item-${message.id}`}>
126
+ {message.type === 'system' ? (
127
+ <MessageSystem
128
+ message={message}
129
+ style={[{ paddingHorizontal: screenPadding }, messageContainer]}
130
+ />
131
+ ) : wrapMessageInTheme ? (
132
+ <ThemeProvider mergedStyle={modifiedTheme}>
133
+ <View testID={`message-list-item-${message.id}`}>
134
+ {renderDateSeperator}
135
+ {renderMessage}
136
+ </View>
137
+ </ThemeProvider>
138
+ ) : (
139
+ <View testID={`message-list-item-${message.id}`}>
140
+ {renderDateSeperator}
141
+ {renderMessage}
142
+ </View>
143
+ )}
144
+ {showUnreadUnderlay && <InlineUnreadIndicator />}
145
+ </View>
146
+ );
147
+ });
@@ -81,11 +81,7 @@ describe('MessageStatus', () => {
81
81
  <ChannelsStateProvider>
82
82
  <Chat client={chatClient} i18nInstance={i18nInstance}>
83
83
  <Channel channel={channel}>
84
- <MessageStatus
85
- lastReceivedId={staticMessage.id}
86
- message={staticMessage}
87
- readBy={readBy}
88
- />
84
+ <MessageStatus message={staticMessage} readBy={readBy} />
89
85
  </Channel>
90
86
  </Chat>
91
87
  </ChannelsStateProvider>,
@@ -22,7 +22,6 @@ export const useCreateMessageContext = ({
22
22
  isMessageAIGenerated,
23
23
  isMyMessage,
24
24
  lastGroupMessage,
25
- lastReceivedId,
26
25
  members,
27
26
  message,
28
27
  messageContentOrder,
@@ -74,7 +73,6 @@ export const useCreateMessageContext = ({
74
73
  isMessageAIGenerated,
75
74
  isMyMessage,
76
75
  lastGroupMessage,
77
- lastReceivedId,
78
76
  members,
79
77
  message,
80
78
  messageContentOrder,
@@ -105,7 +103,6 @@ export const useCreateMessageContext = ({
105
103
  hasReactions,
106
104
  isEditedMessageOpen,
107
105
  lastGroupMessage,
108
- lastReceivedId,
109
106
  membersValue,
110
107
  myMessageThemeString,
111
108
  reactionsValue,
@@ -17,8 +17,6 @@ import { InlineLoadingMoreIndicator } from './InlineLoadingMoreIndicator';
17
17
  import { InlineLoadingMoreRecentIndicator } from './InlineLoadingMoreRecentIndicator';
18
18
  import { InlineLoadingMoreRecentThreadIndicator } from './InlineLoadingMoreRecentThreadIndicator';
19
19
 
20
- import { getLastReceivedMessageFlashList } from './utils/getLastReceivedMessageFlashList';
21
-
22
20
  import {
23
21
  AttachmentPickerContextValue,
24
22
  useAttachmentPickerContext,
@@ -32,6 +30,10 @@ import {
32
30
  ImageGalleryContextValue,
33
31
  useImageGalleryContext,
34
32
  } from '../../contexts/imageGalleryContext/ImageGalleryContext';
33
+ import {
34
+ MessageListItemContextValue,
35
+ MessageListItemProvider,
36
+ } from '../../contexts/messageListItemContext/MessageListItemContext';
35
37
  import {
36
38
  MessagesContextValue,
37
39
  useMessagesContext,
@@ -44,11 +46,12 @@ import {
44
46
  PaginatedMessageListContextValue,
45
47
  usePaginatedMessageListContext,
46
48
  } from '../../contexts/paginatedMessageListContext/PaginatedMessageListContext';
47
- import { mergeThemes, ThemeProvider, useTheme } from '../../contexts/themeContext/ThemeContext';
49
+ import { mergeThemes, useTheme } from '../../contexts/themeContext/ThemeContext';
48
50
  import { ThreadContextValue, useThreadContext } from '../../contexts/threadContext/ThreadContext';
49
51
 
50
52
  import { useStableCallback } from '../../hooks';
51
53
  import { FileTypes } from '../../types/types';
54
+ import { MessageWrapper } from '../Message/MessageSimple/MessageWrapper';
52
55
 
53
56
  let FlashList;
54
57
 
@@ -102,6 +105,7 @@ type MessageFlashListPropsWithContext = Pick<
102
105
  ChannelContextValue,
103
106
  | 'channel'
104
107
  | 'channelUnreadState'
108
+ | 'channelUnreadStateStore'
105
109
  | 'disabled'
106
110
  | 'EmptyStateIndicator'
107
111
  | 'hideStickyDateHeader'
@@ -250,6 +254,10 @@ const getItemTypeInternal = (message: LocalMessage) => {
250
254
  return 'generic-message';
251
255
  };
252
256
 
257
+ const renderItem = ({ item: message }: { item: LocalMessage }) => {
258
+ return <MessageWrapper message={message} />;
259
+ };
260
+
253
261
  const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) => {
254
262
  const LoadingMoreRecentIndicator = props.threadList
255
263
  ? InlineLoadingMoreRecentThreadIndicator
@@ -257,7 +265,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
257
265
  const {
258
266
  additionalFlashListProps,
259
267
  channel,
260
- channelUnreadState,
268
+ channelUnreadStateStore,
261
269
  client,
262
270
  closePicker,
263
271
  DateHeader,
@@ -268,9 +276,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
268
276
  FooterComponent = LoadingMoreRecentIndicator,
269
277
  HeaderComponent = InlineLoadingMoreIndicator,
270
278
  hideStickyDateHeader,
271
- highlightedMessageId,
272
- InlineDateSeparator,
273
- InlineUnreadIndicator,
274
279
  isListActive = false,
275
280
  isLiveStreaming = false,
276
281
  legacyImageViewerSwipeBehaviour,
@@ -283,8 +288,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
283
288
  loadMoreThread,
284
289
  markRead,
285
290
  maximumMessageLimit,
286
- Message,
287
- MessageSystem,
288
291
  myMessageTheme,
289
292
  readEvents,
290
293
  NetworkDownIndicator,
@@ -299,7 +302,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
299
302
  setMessages,
300
303
  setSelectedPicker,
301
304
  setTargetedMessage,
302
- shouldShowUnreadUnderlay,
303
305
  StickyHeader,
304
306
  targetedMessage,
305
307
  thread,
@@ -349,8 +351,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
349
351
  );
350
352
 
351
353
  const {
352
- dateSeparatorsRef,
353
- messageGroupStylesRef,
354
+ messageListPreviousAndNextMessageStore,
354
355
  processedMessageList,
355
356
  rawMessageList,
356
357
  viewabilityChangedCallback,
@@ -378,11 +379,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
378
379
  client.userID,
379
380
  );
380
381
 
381
- const lastReceivedId = useMemo(
382
- () => getLastReceivedMessageFlashList(processedMessageList)?.id,
383
- [processedMessageList],
384
- );
385
-
386
382
  const [autoscrollToRecent, setAutoscrollToRecent] = useState(true);
387
383
 
388
384
  useEffect(() => {
@@ -558,6 +554,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
558
554
  */
559
555
  useEffect(() => {
560
556
  const shouldMarkRead = () => {
557
+ const channelUnreadState = channelUnreadStateStore.channelUnreadState;
561
558
  return (
562
559
  !channelUnreadState?.first_unread_message_id &&
563
560
  !scrollToBottomButtonVisible &&
@@ -569,23 +566,22 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
569
566
  const handleEvent = async (event: Event) => {
570
567
  const mainChannelUpdated = !event.message?.parent_id || event.message?.show_in_channel;
571
568
  const isMyOwnMessage = event.message?.user?.id === client.user?.id;
569
+ const channelUnreadState = channelUnreadStateStore.channelUnreadState;
572
570
  // When the scrollToBottomButtonVisible is true, we need to manually update the channelUnreadState when its a received message.
573
571
  if (
574
572
  (scrollToBottomButtonVisible || channelUnreadState?.first_unread_message_id) &&
575
573
  !isMyOwnMessage
576
574
  ) {
577
- setChannelUnreadState((prev) => {
578
- const previousUnreadCount = prev?.unread_messages ?? 0;
579
- const previousLastMessage = getPreviousLastMessage(channel.state.messages, event.message);
580
- return {
581
- ...(prev || {}),
582
- last_read:
583
- prev?.last_read ??
584
- (previousUnreadCount === 0 && previousLastMessage?.created_at
585
- ? new Date(previousLastMessage.created_at)
586
- : new Date(0)), // not having information about the last read message means the whole channel is unread,
587
- unread_messages: previousUnreadCount + 1,
588
- };
575
+ const previousUnreadCount = channelUnreadState?.unread_messages ?? 0;
576
+ const previousLastMessage = getPreviousLastMessage(channel.state.messages, event.message);
577
+ setChannelUnreadState({
578
+ ...channelUnreadState,
579
+ last_read:
580
+ channelUnreadState?.last_read ??
581
+ (previousUnreadCount === 0 && previousLastMessage?.created_at
582
+ ? new Date(previousLastMessage.created_at)
583
+ : new Date(0)), // not having information about the last read message means the whole channel is unread,
584
+ unread_messages: previousUnreadCount + 1,
589
585
  });
590
586
  } else if (mainChannelUpdated && shouldMarkRead()) {
591
587
  await markRead();
@@ -599,7 +595,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
599
595
  };
600
596
  }, [
601
597
  channel,
602
- channelUnreadState?.first_unread_message_id,
598
+ channelUnreadStateStore,
603
599
  client.user?.id,
604
600
  markRead,
605
601
  scrollToBottomButtonVisible,
@@ -640,12 +636,19 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
640
636
  * This function should show or hide the unread indicator depending on the
641
637
  */
642
638
  const updateStickyUnreadIndicator = useStableCallback((viewableItems: ViewToken[]) => {
643
- if (!viewableItems.length || !readEvents) {
644
- setIsUnreadNotificationOpen(false);
645
- return;
646
- }
639
+ const channelUnreadState = channelUnreadStateStore.channelUnreadState;
640
+ // we need this check to make sure that regular list change do not trigger
641
+ // the unread notification to appear (for example if the old last read messages
642
+ // go out of the viewport).
643
+ const lastReadMessageId = channelUnreadState?.last_read_message_id;
644
+ const lastReadMessageVisible = viewableItems.some((item) => item.item.id === lastReadMessageId);
647
645
 
648
- if (selectedPicker === 'images') {
646
+ if (
647
+ !viewableItems.length ||
648
+ !readEvents ||
649
+ lastReadMessageVisible ||
650
+ selectedPicker === 'images'
651
+ ) {
649
652
  setIsUnreadNotificationOpen(false);
650
653
  return;
651
654
  }
@@ -657,7 +660,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
657
660
  const lastItemMessage = lastItem.item;
658
661
  const lastItemCreatedAt = lastItemMessage.created_at;
659
662
 
660
- const unreadIndicatorDate = channelUnreadState?.last_read.getTime();
663
+ const unreadIndicatorDate = channelUnreadState?.last_read?.getTime();
661
664
  const lastItemDate = lastItemCreatedAt.getTime();
662
665
 
663
666
  if (
@@ -716,89 +719,20 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
716
719
  [],
717
720
  );
718
721
 
719
- const renderItem = useCallback(
720
- ({ index, item: message }: { index: number; item: LocalMessage }) => {
721
- if (!channel || channel.disconnected) {
722
- return null;
723
- }
724
-
725
- const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
726
- const lastReadTimestamp = channelUnreadState?.last_read.getTime();
727
- const isNewestMessage = index === 0;
728
- const isLastReadMessage =
729
- channelUnreadState?.last_read_message_id === message.id ||
730
- (!channelUnreadState?.unread_messages && createdAtTimestamp === lastReadTimestamp);
731
-
732
- const showUnreadSeparator =
733
- isLastReadMessage &&
734
- !isNewestMessage &&
735
- // The `channelUnreadState?.first_unread_message_id` is here for sent messages unread label
736
- (!!channelUnreadState?.first_unread_message_id || !!channelUnreadState?.unread_messages);
737
-
738
- const showUnreadUnderlay = !!shouldShowUnreadUnderlay && showUnreadSeparator;
739
-
740
- const wrapMessageInTheme = client.userID === message.user?.id && !!myMessageTheme;
741
- const renderDateSeperator = dateSeparatorsRef.current[message.id] && (
742
- <InlineDateSeparator date={dateSeparatorsRef.current[message.id]} />
743
- );
744
-
745
- const renderMessage = (
746
- <Message
747
- goToMessage={goToMessage}
748
- groupStyles={messageGroupStylesRef.current[message.id] ?? []}
749
- isTargetedMessage={highlightedMessageId === message.id}
750
- lastReceivedId={
751
- lastReceivedId === message.id || message.quoted_message_id ? lastReceivedId : undefined
752
- }
753
- message={message}
754
- onThreadSelect={onThreadSelect}
755
- showUnreadUnderlay={showUnreadUnderlay}
756
- threadList={threadList}
757
- />
758
- );
759
-
760
- return (
761
- <View testID={`message-list-item-${index}`}>
762
- {message.type === 'system' ? (
763
- <MessageSystem message={message} />
764
- ) : wrapMessageInTheme ? (
765
- <ThemeProvider mergedStyle={modifiedTheme}>
766
- <View testID={`message-list-item-${index}`}>
767
- {renderDateSeperator}
768
- {renderMessage}
769
- </View>
770
- </ThemeProvider>
771
- ) : (
772
- <View testID={`message-list-item-${index}`}>
773
- {renderDateSeperator}
774
- {renderMessage}
775
- </View>
776
- )}
777
- {showUnreadUnderlay && <InlineUnreadIndicator />}
778
- </View>
779
- );
780
- },
722
+ const messageListItemContextValue: MessageListItemContextValue = useMemo(
723
+ () => ({
724
+ goToMessage,
725
+ messageListPreviousAndNextMessageStore,
726
+ modifiedTheme,
727
+ noGroupByUser,
728
+ onThreadSelect,
729
+ }),
781
730
  [
782
- InlineDateSeparator,
783
- InlineUnreadIndicator,
784
- Message,
785
- MessageSystem,
786
- channel,
787
- channelUnreadState?.first_unread_message_id,
788
- channelUnreadState?.last_read,
789
- channelUnreadState?.last_read_message_id,
790
- channelUnreadState?.unread_messages,
791
- client.userID,
792
- dateSeparatorsRef,
793
731
  goToMessage,
794
- highlightedMessageId,
795
- lastReceivedId,
796
- messageGroupStylesRef,
732
+ messageListPreviousAndNextMessageStore,
797
733
  modifiedTheme,
798
- myMessageTheme,
734
+ noGroupByUser,
799
735
  onThreadSelect,
800
- shouldShowUnreadUnderlay,
801
- threadList,
802
736
  ],
803
737
  );
804
738
 
@@ -1129,34 +1063,36 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
1129
1063
  {EmptyStateIndicator ? <EmptyStateIndicator listType='message' /> : null}
1130
1064
  </View>
1131
1065
  ) : (
1132
- <FlashList
1133
- contentContainerStyle={flatListContentContainerStyle}
1134
- data={processedMessageList}
1135
- drawDistance={800}
1136
- getItemType={getItemTypeInternal}
1137
- initialScrollIndex={
1138
- indexToScrollToRef.current === -1 ? undefined : indexToScrollToRef.current
1139
- }
1140
- keyboardShouldPersistTaps='handled'
1141
- keyExtractor={keyExtractor}
1142
- ListFooterComponent={FooterComponent}
1143
- ListHeaderComponent={HeaderComponent}
1144
- maintainVisibleContentPosition={maintainVisibleContentPosition}
1145
- onMomentumScrollEnd={onUserScrollEvent}
1146
- onScroll={handleScroll}
1147
- onScrollBeginDrag={onScrollBeginDrag}
1148
- onScrollEndDrag={onScrollEndDrag}
1149
- onTouchEnd={dismissImagePicker}
1150
- onViewableItemsChanged={stableOnViewableItemsChanged}
1151
- ref={refCallback}
1152
- renderItem={renderItem}
1153
- scrollEventThrottle={isLiveStreaming ? 16 : undefined}
1154
- showsVerticalScrollIndicator={false}
1155
- style={flatListStyle}
1156
- testID='message-flash-list'
1157
- viewabilityConfig={flatListViewabilityConfig}
1158
- {...additionalFlashListPropsExcludingStyle}
1159
- />
1066
+ <MessageListItemProvider value={messageListItemContextValue}>
1067
+ <FlashList
1068
+ contentContainerStyle={flatListContentContainerStyle}
1069
+ data={processedMessageList}
1070
+ drawDistance={800}
1071
+ getItemType={getItemTypeInternal}
1072
+ initialScrollIndex={
1073
+ indexToScrollToRef.current === -1 ? undefined : indexToScrollToRef.current
1074
+ }
1075
+ keyboardShouldPersistTaps='handled'
1076
+ keyExtractor={keyExtractor}
1077
+ ListFooterComponent={FooterComponent}
1078
+ ListHeaderComponent={HeaderComponent}
1079
+ maintainVisibleContentPosition={maintainVisibleContentPosition}
1080
+ onMomentumScrollEnd={onUserScrollEvent}
1081
+ onScroll={handleScroll}
1082
+ onScrollBeginDrag={onScrollBeginDrag}
1083
+ onScrollEndDrag={onScrollEndDrag}
1084
+ onTouchEnd={dismissImagePicker}
1085
+ onViewableItemsChanged={stableOnViewableItemsChanged}
1086
+ ref={refCallback}
1087
+ renderItem={renderItem}
1088
+ scrollEventThrottle={isLiveStreaming ? 16 : undefined}
1089
+ showsVerticalScrollIndicator={false}
1090
+ style={flatListStyle}
1091
+ testID='message-flash-list'
1092
+ viewabilityConfig={flatListViewabilityConfig}
1093
+ {...additionalFlashListPropsExcludingStyle}
1094
+ />
1095
+ </MessageListItemProvider>
1160
1096
  )}
1161
1097
  <View style={styles.stickyHeader}>
1162
1098
  {messageListLengthAfterUpdate && StickyHeader ? (
@@ -1194,6 +1130,7 @@ export const MessageFlashList = (props: MessageFlashListProps) => {
1194
1130
  const {
1195
1131
  channel,
1196
1132
  channelUnreadState,
1133
+ channelUnreadStateStore,
1197
1134
  disabled,
1198
1135
  EmptyStateIndicator,
1199
1136
  enableMessageGroupingByUser,
@@ -1242,6 +1179,7 @@ export const MessageFlashList = (props: MessageFlashListProps) => {
1242
1179
  {...{
1243
1180
  channel,
1244
1181
  channelUnreadState,
1182
+ channelUnreadStateStore,
1245
1183
  client,
1246
1184
  closePicker,
1247
1185
  DateHeader,