stream-chat-react-native-core 6.0.0-rc.9 → 6.0.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 (564) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/components/AITypingIndicatorView/AITypingIndicatorView.js +53 -0
  3. package/lib/commonjs/components/AITypingIndicatorView/AITypingIndicatorView.js.map +1 -0
  4. package/lib/commonjs/components/AITypingIndicatorView/hooks/useAIState.js +59 -0
  5. package/lib/commonjs/components/AITypingIndicatorView/hooks/useAIState.js.map +1 -0
  6. package/lib/commonjs/components/AITypingIndicatorView/index.js +26 -0
  7. package/lib/commonjs/components/AITypingIndicatorView/index.js.map +1 -0
  8. package/lib/commonjs/components/Attachment/AudioAttachment.js +27 -22
  9. package/lib/commonjs/components/Attachment/AudioAttachment.js.map +1 -1
  10. package/lib/commonjs/components/Attachment/Gallery.js +3 -1
  11. package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
  12. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +2 -2
  13. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  14. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerItem.js +37 -133
  15. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerItem.js.map +1 -1
  16. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerSelectionBar.js +6 -4
  17. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerSelectionBar.js.map +1 -1
  18. package/lib/commonjs/components/Channel/Channel.js +478 -1045
  19. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  20. package/lib/commonjs/components/Channel/hooks/useChannelDataState.js +174 -0
  21. package/lib/commonjs/components/Channel/hooks/useChannelDataState.js.map +1 -0
  22. package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js +2 -0
  23. package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
  24. package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +4 -0
  25. package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
  26. package/lib/commonjs/components/Channel/hooks/useCreatePaginatedMessageListContext.js +3 -3
  27. package/lib/commonjs/components/Channel/hooks/useCreatePaginatedMessageListContext.js.map +1 -1
  28. package/lib/commonjs/components/Channel/hooks/useMessageListPagination.js +324 -0
  29. package/lib/commonjs/components/Channel/hooks/useMessageListPagination.js.map +1 -0
  30. package/lib/commonjs/components/ChannelList/Skeleton.js +7 -3
  31. package/lib/commonjs/components/ChannelList/Skeleton.js.map +1 -1
  32. package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js +85 -45
  33. package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
  34. package/lib/commonjs/components/ChannelPreview/ChannelPreview.js +17 -91
  35. package/lib/commonjs/components/ChannelPreview/ChannelPreview.js.map +1 -1
  36. package/lib/commonjs/components/ChannelPreview/ChannelPreviewMessenger.js +3 -24
  37. package/lib/commonjs/components/ChannelPreview/ChannelPreviewMessenger.js.map +1 -1
  38. package/lib/commonjs/components/ChannelPreview/ChannelPreviewMutedStatus.js +2 -2
  39. package/lib/commonjs/components/ChannelPreview/ChannelPreviewMutedStatus.js.map +1 -1
  40. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js +121 -0
  41. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -0
  42. package/lib/commonjs/components/ChannelPreview/hooks/useIsChannelMuted.js +35 -0
  43. package/lib/commonjs/components/ChannelPreview/hooks/useIsChannelMuted.js.map +1 -0
  44. package/lib/commonjs/components/Chat/Chat.js +5 -1
  45. package/lib/commonjs/components/Chat/Chat.js.map +1 -1
  46. package/lib/commonjs/components/Chat/hooks/useAppSettings.js +15 -9
  47. package/lib/commonjs/components/Chat/hooks/useAppSettings.js.map +1 -1
  48. package/lib/commonjs/components/Chat/hooks/useCreateChatContext.js +2 -0
  49. package/lib/commonjs/components/Chat/hooks/useCreateChatContext.js.map +1 -1
  50. package/lib/commonjs/components/Chat/hooks/useIsOnline.js +0 -4
  51. package/lib/commonjs/components/Chat/hooks/useIsOnline.js.map +1 -1
  52. package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
  53. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +46 -46
  54. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  55. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +3 -4
  56. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  57. package/lib/commonjs/components/ImageGallery/hooks/useAnimatedGalleryStyle.js +2 -2
  58. package/lib/commonjs/components/ImageGallery/hooks/useAnimatedGalleryStyle.js.map +1 -1
  59. package/lib/commonjs/components/Message/Message.js +7 -0
  60. package/lib/commonjs/components/Message/Message.js.map +1 -1
  61. package/lib/commonjs/components/Message/MessageSimple/MessageContent.js +17 -4
  62. package/lib/commonjs/components/Message/MessageSimple/MessageContent.js.map +1 -1
  63. package/lib/commonjs/components/Message/MessageSimple/MessageFooter.js +15 -6
  64. package/lib/commonjs/components/Message/MessageSimple/MessageFooter.js.map +1 -1
  65. package/lib/commonjs/components/Message/MessageSimple/StreamingMessageView.js +36 -0
  66. package/lib/commonjs/components/Message/MessageSimple/StreamingMessageView.js.map +1 -0
  67. package/lib/commonjs/components/Message/MessageSimple/utils/generateMarkdownText.js +9 -1
  68. package/lib/commonjs/components/Message/MessageSimple/utils/generateMarkdownText.js.map +1 -1
  69. package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js +209 -23
  70. package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js.map +1 -1
  71. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +2 -0
  72. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  73. package/lib/commonjs/components/Message/hooks/useStreamingMessage.js +43 -0
  74. package/lib/commonjs/components/Message/hooks/useStreamingMessage.js.map +1 -0
  75. package/lib/commonjs/components/MessageInput/MessageInput.js +41 -21
  76. package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
  77. package/lib/commonjs/components/MessageInput/StopMessageStreamingButton.js +39 -0
  78. package/lib/commonjs/components/MessageInput/StopMessageStreamingButton.js.map +1 -0
  79. package/lib/commonjs/components/MessageList/MessageList.js +74 -73
  80. package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
  81. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js +1 -1
  82. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js.map +1 -1
  83. package/lib/commonjs/components/MessageList/hooks/useMessageList.js.map +1 -1
  84. package/lib/commonjs/components/MessageList/utils/getReadStates.js.map +1 -1
  85. package/lib/commonjs/components/MessageMenu/MessageUserReactions.js +1 -1
  86. package/lib/commonjs/components/MessageMenu/MessageUserReactions.js.map +1 -1
  87. package/lib/commonjs/components/MessageMenu/MessageUserReactionsItem.js +4 -2
  88. package/lib/commonjs/components/MessageMenu/MessageUserReactionsItem.js.map +1 -1
  89. package/lib/commonjs/components/MessageMenu/hooks/useFetchReactions.js +3 -2
  90. package/lib/commonjs/components/MessageMenu/hooks/useFetchReactions.js.map +1 -1
  91. package/lib/commonjs/components/Poll/CreatePollContent.js +14 -9
  92. package/lib/commonjs/components/Poll/CreatePollContent.js.map +1 -1
  93. package/lib/commonjs/components/Poll/Poll.js +2 -8
  94. package/lib/commonjs/components/Poll/Poll.js.map +1 -1
  95. package/lib/commonjs/components/Poll/components/Button.js +9 -474
  96. package/lib/commonjs/components/Poll/components/Button.js.map +1 -1
  97. package/lib/commonjs/components/Poll/components/CreatePollIcon.js +2 -2
  98. package/lib/commonjs/components/Poll/components/CreatePollIcon.js.map +1 -1
  99. package/lib/commonjs/components/Poll/components/CreatePollOptions.js +9 -4
  100. package/lib/commonjs/components/Poll/components/CreatePollOptions.js.map +1 -1
  101. package/lib/commonjs/components/Poll/components/PollAnswersList.js +99 -26
  102. package/lib/commonjs/components/Poll/components/PollAnswersList.js.map +1 -1
  103. package/lib/commonjs/components/Poll/components/PollButtons.js +291 -0
  104. package/lib/commonjs/components/Poll/components/PollButtons.js.map +1 -0
  105. package/lib/commonjs/components/Poll/components/PollInputDialog.js +14 -4
  106. package/lib/commonjs/components/Poll/components/PollInputDialog.js.map +1 -1
  107. package/lib/commonjs/components/Poll/components/PollModalHeader.js +7 -1
  108. package/lib/commonjs/components/Poll/components/PollModalHeader.js.map +1 -1
  109. package/lib/commonjs/components/Poll/components/PollOption.js +88 -6
  110. package/lib/commonjs/components/Poll/components/PollOption.js.map +1 -1
  111. package/lib/commonjs/components/Poll/components/PollResults/PollOptionFullResults.js +2 -2
  112. package/lib/commonjs/components/Poll/components/PollResults/PollOptionFullResults.js.map +1 -1
  113. package/lib/commonjs/components/Poll/components/PollResults/PollResultItem.js +62 -67
  114. package/lib/commonjs/components/Poll/components/PollResults/PollResultItem.js.map +1 -1
  115. package/lib/commonjs/components/Poll/components/PollResults/PollVote.js +89 -0
  116. package/lib/commonjs/components/Poll/components/PollResults/PollVote.js.map +1 -0
  117. package/lib/commonjs/components/Poll/components/index.js +11 -0
  118. package/lib/commonjs/components/Poll/components/index.js.map +1 -1
  119. package/lib/commonjs/components/ThreadList/ThreadList.js +0 -3
  120. package/lib/commonjs/components/ThreadList/ThreadList.js.map +1 -1
  121. package/lib/commonjs/components/UIComponents/BottomSheetModal.js +11 -5
  122. package/lib/commonjs/components/UIComponents/BottomSheetModal.js.map +1 -1
  123. package/lib/commonjs/components/index.js +66 -0
  124. package/lib/commonjs/components/index.js.map +1 -1
  125. package/lib/commonjs/contexts/channelContext/ChannelContext.js.map +1 -1
  126. package/lib/commonjs/contexts/channelsStateContext/ChannelsStateContext.js +0 -35
  127. package/lib/commonjs/contexts/channelsStateContext/ChannelsStateContext.js.map +1 -1
  128. package/lib/commonjs/contexts/channelsStateContext/useChannelState.js +7 -84
  129. package/lib/commonjs/contexts/channelsStateContext/useChannelState.js.map +1 -1
  130. package/lib/commonjs/contexts/chatContext/ChatContext.js.map +1 -1
  131. package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
  132. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +4 -2
  133. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  134. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +2 -0
  135. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
  136. package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
  137. package/lib/commonjs/contexts/paginatedMessageListContext/PaginatedMessageListContext.js.map +1 -1
  138. package/lib/commonjs/contexts/themeContext/utils/theme.js +15 -0
  139. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  140. package/lib/commonjs/i18n/en.json +2 -0
  141. package/lib/commonjs/i18n/es.json +2 -0
  142. package/lib/commonjs/i18n/fr.json +2 -0
  143. package/lib/commonjs/i18n/he.json +2 -0
  144. package/lib/commonjs/i18n/hi.json +2 -0
  145. package/lib/commonjs/i18n/it.json +2 -0
  146. package/lib/commonjs/i18n/ja.json +2 -0
  147. package/lib/commonjs/i18n/ko.json +2 -0
  148. package/lib/commonjs/i18n/nl.json +2 -0
  149. package/lib/commonjs/i18n/pt-br.json +2 -0
  150. package/lib/commonjs/i18n/ru.json +2 -0
  151. package/lib/commonjs/i18n/tr.json +2 -0
  152. package/lib/commonjs/mock-builders/event/notificationChannelMutesUpdated.js +14 -0
  153. package/lib/commonjs/mock-builders/event/notificationChannelMutesUpdated.js.map +1 -0
  154. package/lib/commonjs/mock-builders/event/notificationMarkRead.js +14 -0
  155. package/lib/commonjs/mock-builders/event/notificationMarkRead.js.map +1 -0
  156. package/lib/commonjs/mock-builders/event/notificationMarkUnread.js +17 -0
  157. package/lib/commonjs/mock-builders/event/notificationMarkUnread.js.map +1 -0
  158. package/lib/commonjs/mock-builders/generator/channel.js +1 -0
  159. package/lib/commonjs/mock-builders/generator/channel.js.map +1 -1
  160. package/lib/commonjs/store/SqliteClient.js +11 -2
  161. package/lib/commonjs/store/SqliteClient.js.map +1 -1
  162. package/lib/commonjs/utils/getTrimmedAttachmentTitle.js +8 -2
  163. package/lib/commonjs/utils/getTrimmedAttachmentTitle.js.map +1 -1
  164. package/lib/commonjs/utils/utils.js +3 -2
  165. package/lib/commonjs/utils/utils.js.map +1 -1
  166. package/lib/commonjs/version.json +1 -1
  167. package/lib/module/components/AITypingIndicatorView/AITypingIndicatorView.js +53 -0
  168. package/lib/module/components/AITypingIndicatorView/AITypingIndicatorView.js.map +1 -0
  169. package/lib/module/components/AITypingIndicatorView/hooks/useAIState.js +59 -0
  170. package/lib/module/components/AITypingIndicatorView/hooks/useAIState.js.map +1 -0
  171. package/lib/module/components/AITypingIndicatorView/index.js +26 -0
  172. package/lib/module/components/AITypingIndicatorView/index.js.map +1 -0
  173. package/lib/module/components/Attachment/AudioAttachment.js +27 -22
  174. package/lib/module/components/Attachment/AudioAttachment.js.map +1 -1
  175. package/lib/module/components/Attachment/Gallery.js +3 -1
  176. package/lib/module/components/Attachment/Gallery.js.map +1 -1
  177. package/lib/module/components/AttachmentPicker/AttachmentPicker.js +2 -2
  178. package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  179. package/lib/module/components/AttachmentPicker/components/AttachmentPickerItem.js +37 -133
  180. package/lib/module/components/AttachmentPicker/components/AttachmentPickerItem.js.map +1 -1
  181. package/lib/module/components/AttachmentPicker/components/AttachmentPickerSelectionBar.js +6 -4
  182. package/lib/module/components/AttachmentPicker/components/AttachmentPickerSelectionBar.js.map +1 -1
  183. package/lib/module/components/Channel/Channel.js +478 -1045
  184. package/lib/module/components/Channel/Channel.js.map +1 -1
  185. package/lib/module/components/Channel/hooks/useChannelDataState.js +174 -0
  186. package/lib/module/components/Channel/hooks/useChannelDataState.js.map +1 -0
  187. package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js +2 -0
  188. package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
  189. package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +4 -0
  190. package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
  191. package/lib/module/components/Channel/hooks/useCreatePaginatedMessageListContext.js +3 -3
  192. package/lib/module/components/Channel/hooks/useCreatePaginatedMessageListContext.js.map +1 -1
  193. package/lib/module/components/Channel/hooks/useMessageListPagination.js +324 -0
  194. package/lib/module/components/Channel/hooks/useMessageListPagination.js.map +1 -0
  195. package/lib/module/components/ChannelList/Skeleton.js +7 -3
  196. package/lib/module/components/ChannelList/Skeleton.js.map +1 -1
  197. package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js +85 -45
  198. package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
  199. package/lib/module/components/ChannelPreview/ChannelPreview.js +17 -91
  200. package/lib/module/components/ChannelPreview/ChannelPreview.js.map +1 -1
  201. package/lib/module/components/ChannelPreview/ChannelPreviewMessenger.js +3 -24
  202. package/lib/module/components/ChannelPreview/ChannelPreviewMessenger.js.map +1 -1
  203. package/lib/module/components/ChannelPreview/ChannelPreviewMutedStatus.js +2 -2
  204. package/lib/module/components/ChannelPreview/ChannelPreviewMutedStatus.js.map +1 -1
  205. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js +121 -0
  206. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -0
  207. package/lib/module/components/ChannelPreview/hooks/useIsChannelMuted.js +35 -0
  208. package/lib/module/components/ChannelPreview/hooks/useIsChannelMuted.js.map +1 -0
  209. package/lib/module/components/Chat/Chat.js +5 -1
  210. package/lib/module/components/Chat/Chat.js.map +1 -1
  211. package/lib/module/components/Chat/hooks/useAppSettings.js +15 -9
  212. package/lib/module/components/Chat/hooks/useAppSettings.js.map +1 -1
  213. package/lib/module/components/Chat/hooks/useCreateChatContext.js +2 -0
  214. package/lib/module/components/Chat/hooks/useCreateChatContext.js.map +1 -1
  215. package/lib/module/components/Chat/hooks/useIsOnline.js +0 -4
  216. package/lib/module/components/Chat/hooks/useIsOnline.js.map +1 -1
  217. package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
  218. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +46 -46
  219. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  220. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +3 -4
  221. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  222. package/lib/module/components/ImageGallery/hooks/useAnimatedGalleryStyle.js +2 -2
  223. package/lib/module/components/ImageGallery/hooks/useAnimatedGalleryStyle.js.map +1 -1
  224. package/lib/module/components/Message/Message.js +7 -0
  225. package/lib/module/components/Message/Message.js.map +1 -1
  226. package/lib/module/components/Message/MessageSimple/MessageContent.js +17 -4
  227. package/lib/module/components/Message/MessageSimple/MessageContent.js.map +1 -1
  228. package/lib/module/components/Message/MessageSimple/MessageFooter.js +15 -6
  229. package/lib/module/components/Message/MessageSimple/MessageFooter.js.map +1 -1
  230. package/lib/module/components/Message/MessageSimple/StreamingMessageView.js +36 -0
  231. package/lib/module/components/Message/MessageSimple/StreamingMessageView.js.map +1 -0
  232. package/lib/module/components/Message/MessageSimple/utils/generateMarkdownText.js +9 -1
  233. package/lib/module/components/Message/MessageSimple/utils/generateMarkdownText.js.map +1 -1
  234. package/lib/module/components/Message/MessageSimple/utils/renderText.js +209 -23
  235. package/lib/module/components/Message/MessageSimple/utils/renderText.js.map +1 -1
  236. package/lib/module/components/Message/hooks/useCreateMessageContext.js +2 -0
  237. package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  238. package/lib/module/components/Message/hooks/useStreamingMessage.js +43 -0
  239. package/lib/module/components/Message/hooks/useStreamingMessage.js.map +1 -0
  240. package/lib/module/components/MessageInput/MessageInput.js +41 -21
  241. package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
  242. package/lib/module/components/MessageInput/StopMessageStreamingButton.js +39 -0
  243. package/lib/module/components/MessageInput/StopMessageStreamingButton.js.map +1 -0
  244. package/lib/module/components/MessageList/MessageList.js +74 -73
  245. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  246. package/lib/module/components/MessageList/ScrollToBottomButton.js +1 -1
  247. package/lib/module/components/MessageList/ScrollToBottomButton.js.map +1 -1
  248. package/lib/module/components/MessageList/hooks/useMessageList.js.map +1 -1
  249. package/lib/module/components/MessageList/utils/getReadStates.js.map +1 -1
  250. package/lib/module/components/MessageMenu/MessageUserReactions.js +1 -1
  251. package/lib/module/components/MessageMenu/MessageUserReactions.js.map +1 -1
  252. package/lib/module/components/MessageMenu/MessageUserReactionsItem.js +4 -2
  253. package/lib/module/components/MessageMenu/MessageUserReactionsItem.js.map +1 -1
  254. package/lib/module/components/MessageMenu/hooks/useFetchReactions.js +3 -2
  255. package/lib/module/components/MessageMenu/hooks/useFetchReactions.js.map +1 -1
  256. package/lib/module/components/Poll/CreatePollContent.js +14 -9
  257. package/lib/module/components/Poll/CreatePollContent.js.map +1 -1
  258. package/lib/module/components/Poll/Poll.js +2 -8
  259. package/lib/module/components/Poll/Poll.js.map +1 -1
  260. package/lib/module/components/Poll/components/Button.js +9 -474
  261. package/lib/module/components/Poll/components/Button.js.map +1 -1
  262. package/lib/module/components/Poll/components/CreatePollIcon.js +2 -2
  263. package/lib/module/components/Poll/components/CreatePollIcon.js.map +1 -1
  264. package/lib/module/components/Poll/components/CreatePollOptions.js +9 -4
  265. package/lib/module/components/Poll/components/CreatePollOptions.js.map +1 -1
  266. package/lib/module/components/Poll/components/PollAnswersList.js +99 -26
  267. package/lib/module/components/Poll/components/PollAnswersList.js.map +1 -1
  268. package/lib/module/components/Poll/components/PollButtons.js +291 -0
  269. package/lib/module/components/Poll/components/PollButtons.js.map +1 -0
  270. package/lib/module/components/Poll/components/PollInputDialog.js +14 -4
  271. package/lib/module/components/Poll/components/PollInputDialog.js.map +1 -1
  272. package/lib/module/components/Poll/components/PollModalHeader.js +7 -1
  273. package/lib/module/components/Poll/components/PollModalHeader.js.map +1 -1
  274. package/lib/module/components/Poll/components/PollOption.js +88 -6
  275. package/lib/module/components/Poll/components/PollOption.js.map +1 -1
  276. package/lib/module/components/Poll/components/PollResults/PollOptionFullResults.js +2 -2
  277. package/lib/module/components/Poll/components/PollResults/PollOptionFullResults.js.map +1 -1
  278. package/lib/module/components/Poll/components/PollResults/PollResultItem.js +62 -67
  279. package/lib/module/components/Poll/components/PollResults/PollResultItem.js.map +1 -1
  280. package/lib/module/components/Poll/components/PollResults/PollVote.js +89 -0
  281. package/lib/module/components/Poll/components/PollResults/PollVote.js.map +1 -0
  282. package/lib/module/components/Poll/components/index.js +11 -0
  283. package/lib/module/components/Poll/components/index.js.map +1 -1
  284. package/lib/module/components/ThreadList/ThreadList.js +0 -3
  285. package/lib/module/components/ThreadList/ThreadList.js.map +1 -1
  286. package/lib/module/components/UIComponents/BottomSheetModal.js +11 -5
  287. package/lib/module/components/UIComponents/BottomSheetModal.js.map +1 -1
  288. package/lib/module/components/index.js +66 -0
  289. package/lib/module/components/index.js.map +1 -1
  290. package/lib/module/contexts/channelContext/ChannelContext.js.map +1 -1
  291. package/lib/module/contexts/channelsStateContext/ChannelsStateContext.js +0 -35
  292. package/lib/module/contexts/channelsStateContext/ChannelsStateContext.js.map +1 -1
  293. package/lib/module/contexts/channelsStateContext/useChannelState.js +7 -84
  294. package/lib/module/contexts/channelsStateContext/useChannelState.js.map +1 -1
  295. package/lib/module/contexts/chatContext/ChatContext.js.map +1 -1
  296. package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
  297. package/lib/module/contexts/messageInputContext/MessageInputContext.js +4 -2
  298. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  299. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +2 -0
  300. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
  301. package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
  302. package/lib/module/contexts/paginatedMessageListContext/PaginatedMessageListContext.js.map +1 -1
  303. package/lib/module/contexts/themeContext/utils/theme.js +15 -0
  304. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  305. package/lib/module/i18n/en.json +2 -0
  306. package/lib/module/i18n/es.json +2 -0
  307. package/lib/module/i18n/fr.json +2 -0
  308. package/lib/module/i18n/he.json +2 -0
  309. package/lib/module/i18n/hi.json +2 -0
  310. package/lib/module/i18n/it.json +2 -0
  311. package/lib/module/i18n/ja.json +2 -0
  312. package/lib/module/i18n/ko.json +2 -0
  313. package/lib/module/i18n/nl.json +2 -0
  314. package/lib/module/i18n/pt-br.json +2 -0
  315. package/lib/module/i18n/ru.json +2 -0
  316. package/lib/module/i18n/tr.json +2 -0
  317. package/lib/module/mock-builders/event/notificationChannelMutesUpdated.js +14 -0
  318. package/lib/module/mock-builders/event/notificationChannelMutesUpdated.js.map +1 -0
  319. package/lib/module/mock-builders/event/notificationMarkRead.js +14 -0
  320. package/lib/module/mock-builders/event/notificationMarkRead.js.map +1 -0
  321. package/lib/module/mock-builders/event/notificationMarkUnread.js +17 -0
  322. package/lib/module/mock-builders/event/notificationMarkUnread.js.map +1 -0
  323. package/lib/module/mock-builders/generator/channel.js +1 -0
  324. package/lib/module/mock-builders/generator/channel.js.map +1 -1
  325. package/lib/module/store/SqliteClient.js +11 -2
  326. package/lib/module/store/SqliteClient.js.map +1 -1
  327. package/lib/module/utils/getTrimmedAttachmentTitle.js +8 -2
  328. package/lib/module/utils/getTrimmedAttachmentTitle.js.map +1 -1
  329. package/lib/module/utils/utils.js +3 -2
  330. package/lib/module/utils/utils.js.map +1 -1
  331. package/lib/module/version.json +1 -1
  332. package/lib/typescript/components/AITypingIndicatorView/AITypingIndicatorView.d.ts +11 -0
  333. package/lib/typescript/components/AITypingIndicatorView/AITypingIndicatorView.d.ts.map +1 -0
  334. package/lib/typescript/components/AITypingIndicatorView/hooks/useAIState.d.ts +18 -0
  335. package/lib/typescript/components/AITypingIndicatorView/hooks/useAIState.d.ts.map +1 -0
  336. package/lib/typescript/components/AITypingIndicatorView/index.d.ts +3 -0
  337. package/lib/typescript/components/AITypingIndicatorView/index.d.ts.map +1 -0
  338. package/lib/typescript/components/Attachment/AudioAttachment.d.ts.map +1 -1
  339. package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts.map +1 -1
  340. package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerItem.d.ts.map +1 -1
  341. package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerSelectionBar.d.ts.map +1 -1
  342. package/lib/typescript/components/Channel/Channel.d.ts +7 -6
  343. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  344. package/lib/typescript/components/Channel/hooks/useChannelDataState.d.ts +75 -0
  345. package/lib/typescript/components/Channel/hooks/useChannelDataState.d.ts.map +1 -0
  346. package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts +1 -1
  347. package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts.map +1 -1
  348. package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +128 -1
  349. package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts.map +1 -1
  350. package/lib/typescript/components/Channel/hooks/useCreatePaginatedMessageListContext.d.ts +1 -1
  351. package/lib/typescript/components/Channel/hooks/useCreatePaginatedMessageListContext.d.ts.map +1 -1
  352. package/lib/typescript/components/Channel/hooks/useMessageListPagination.d.ts +28 -0
  353. package/lib/typescript/components/Channel/hooks/useMessageListPagination.d.ts.map +1 -0
  354. package/lib/typescript/components/ChannelList/Skeleton.d.ts.map +1 -1
  355. package/lib/typescript/components/ChannelList/hooks/usePaginatedChannels.d.ts.map +1 -1
  356. package/lib/typescript/components/ChannelPreview/ChannelPreview.d.ts +1 -2
  357. package/lib/typescript/components/ChannelPreview/ChannelPreview.d.ts.map +1 -1
  358. package/lib/typescript/components/ChannelPreview/ChannelPreviewMessenger.d.ts +2 -0
  359. package/lib/typescript/components/ChannelPreview/ChannelPreviewMessenger.d.ts.map +1 -1
  360. package/lib/typescript/components/ChannelPreview/ChannelPreviewMutedStatus.d.ts.map +1 -1
  361. package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts +8 -0
  362. package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts.map +1 -0
  363. package/lib/typescript/components/ChannelPreview/hooks/useIsChannelMuted.d.ts +8 -0
  364. package/lib/typescript/components/ChannelPreview/hooks/useIsChannelMuted.d.ts.map +1 -0
  365. package/lib/typescript/components/Chat/Chat.d.ts +7 -1
  366. package/lib/typescript/components/Chat/Chat.d.ts.map +1 -1
  367. package/lib/typescript/components/Chat/hooks/useAppSettings.d.ts.map +1 -1
  368. package/lib/typescript/components/Chat/hooks/useCreateChatContext.d.ts +1 -1
  369. package/lib/typescript/components/Chat/hooks/useCreateChatContext.d.ts.map +1 -1
  370. package/lib/typescript/components/Chat/hooks/useIsOnline.d.ts.map +1 -1
  371. package/lib/typescript/components/ImageGallery/ImageGallery.d.ts.map +1 -1
  372. package/lib/typescript/components/Message/Message.d.ts +1 -1
  373. package/lib/typescript/components/Message/Message.d.ts.map +1 -1
  374. package/lib/typescript/components/Message/MessageSimple/MessageContent.d.ts +1 -1
  375. package/lib/typescript/components/Message/MessageSimple/MessageContent.d.ts.map +1 -1
  376. package/lib/typescript/components/Message/MessageSimple/MessageFooter.d.ts.map +1 -1
  377. package/lib/typescript/components/Message/MessageSimple/StreamingMessageView.d.ts +12 -0
  378. package/lib/typescript/components/Message/MessageSimple/StreamingMessageView.d.ts.map +1 -0
  379. package/lib/typescript/components/Message/MessageSimple/utils/generateMarkdownText.d.ts.map +1 -1
  380. package/lib/typescript/components/Message/MessageSimple/utils/renderText.d.ts +16 -1
  381. package/lib/typescript/components/Message/MessageSimple/utils/renderText.d.ts.map +1 -1
  382. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts +1 -1
  383. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts.map +1 -1
  384. package/lib/typescript/components/Message/hooks/useStreamingMessage.d.ts +17 -0
  385. package/lib/typescript/components/Message/hooks/useStreamingMessage.d.ts.map +1 -0
  386. package/lib/typescript/components/MessageInput/MessageInput.d.ts +1 -1
  387. package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
  388. package/lib/typescript/components/MessageInput/StopMessageStreamingButton.d.ts +10 -0
  389. package/lib/typescript/components/MessageInput/StopMessageStreamingButton.d.ts.map +1 -0
  390. package/lib/typescript/components/MessageList/MessageList.d.ts +1 -1
  391. package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
  392. package/lib/typescript/components/MessageList/hooks/useMessageList.d.ts.map +1 -1
  393. package/lib/typescript/components/MessageList/utils/getReadStates.d.ts +1 -1
  394. package/lib/typescript/components/MessageList/utils/getReadStates.d.ts.map +1 -1
  395. package/lib/typescript/components/MessageMenu/MessageUserReactionsItem.d.ts.map +1 -1
  396. package/lib/typescript/components/MessageMenu/hooks/useFetchReactions.d.ts +3 -2
  397. package/lib/typescript/components/MessageMenu/hooks/useFetchReactions.d.ts.map +1 -1
  398. package/lib/typescript/components/Poll/Poll.d.ts +0 -1
  399. package/lib/typescript/components/Poll/Poll.d.ts.map +1 -1
  400. package/lib/typescript/components/Poll/components/Button.d.ts +0 -17
  401. package/lib/typescript/components/Poll/components/Button.d.ts.map +1 -1
  402. package/lib/typescript/components/Poll/components/CreatePollOptions.d.ts.map +1 -1
  403. package/lib/typescript/components/Poll/components/PollAnswersList.d.ts +2 -0
  404. package/lib/typescript/components/Poll/components/PollAnswersList.d.ts.map +1 -1
  405. package/lib/typescript/components/Poll/components/PollButtons.d.ts +10 -0
  406. package/lib/typescript/components/Poll/components/PollButtons.d.ts.map +1 -0
  407. package/lib/typescript/components/Poll/components/PollInputDialog.d.ts.map +1 -1
  408. package/lib/typescript/components/Poll/components/PollOption.d.ts +2 -0
  409. package/lib/typescript/components/Poll/components/PollOption.d.ts.map +1 -1
  410. package/lib/typescript/components/Poll/components/PollResults/PollResultItem.d.ts +11 -4
  411. package/lib/typescript/components/Poll/components/PollResults/PollResultItem.d.ts.map +1 -1
  412. package/lib/typescript/components/Poll/components/PollResults/PollVote.d.ts +6 -0
  413. package/lib/typescript/components/Poll/components/PollResults/PollVote.d.ts.map +1 -0
  414. package/lib/typescript/components/Poll/components/index.d.ts +1 -0
  415. package/lib/typescript/components/Poll/components/index.d.ts.map +1 -1
  416. package/lib/typescript/components/ThreadList/ThreadList.d.ts.map +1 -1
  417. package/lib/typescript/components/UIComponents/BottomSheetModal.d.ts.map +1 -1
  418. package/lib/typescript/components/index.d.ts +6 -0
  419. package/lib/typescript/components/index.d.ts.map +1 -1
  420. package/lib/typescript/contexts/channelContext/ChannelContext.d.ts +27 -25
  421. package/lib/typescript/contexts/channelContext/ChannelContext.d.ts.map +1 -1
  422. package/lib/typescript/contexts/channelsStateContext/ChannelsStateContext.d.ts +0 -16
  423. package/lib/typescript/contexts/channelsStateContext/ChannelsStateContext.d.ts.map +1 -1
  424. package/lib/typescript/contexts/channelsStateContext/useChannelState.d.ts +7 -13
  425. package/lib/typescript/contexts/channelsStateContext/useChannelState.d.ts.map +1 -1
  426. package/lib/typescript/contexts/chatContext/ChatContext.d.ts +2 -1
  427. package/lib/typescript/contexts/chatContext/ChatContext.d.ts.map +1 -1
  428. package/lib/typescript/contexts/messageContext/MessageContext.d.ts +4 -0
  429. package/lib/typescript/contexts/messageContext/MessageContext.d.ts.map +1 -1
  430. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +2 -1
  431. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts.map +1 -1
  432. package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts +1 -1
  433. package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts.map +1 -1
  434. package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +8 -4
  435. package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts.map +1 -1
  436. package/lib/typescript/contexts/paginatedMessageListContext/PaginatedMessageListContext.d.ts +17 -16
  437. package/lib/typescript/contexts/paginatedMessageListContext/PaginatedMessageListContext.d.ts.map +1 -1
  438. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +16 -1
  439. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  440. package/lib/typescript/i18n/en.json +2 -0
  441. package/lib/typescript/i18n/es.json +2 -0
  442. package/lib/typescript/i18n/fr.json +2 -0
  443. package/lib/typescript/i18n/he.json +2 -0
  444. package/lib/typescript/i18n/hi.json +2 -0
  445. package/lib/typescript/i18n/it.json +2 -0
  446. package/lib/typescript/i18n/ja.json +2 -0
  447. package/lib/typescript/i18n/ko.json +2 -0
  448. package/lib/typescript/i18n/nl.json +2 -0
  449. package/lib/typescript/i18n/pt-br.json +2 -0
  450. package/lib/typescript/i18n/ru.json +2 -0
  451. package/lib/typescript/i18n/tr.json +2 -0
  452. package/lib/typescript/store/SqliteClient.d.ts.map +1 -1
  453. package/lib/typescript/types/types.d.ts +3 -0
  454. package/lib/typescript/types/types.d.ts.map +1 -1
  455. package/lib/typescript/utils/getTrimmedAttachmentTitle.d.ts.map +1 -1
  456. package/lib/typescript/utils/i18n/Streami18n.d.ts +2 -0
  457. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  458. package/lib/typescript/utils/utils.d.ts.map +1 -1
  459. package/package.json +5 -5
  460. package/src/components/AITypingIndicatorView/AITypingIndicatorView.tsx +50 -0
  461. package/src/components/AITypingIndicatorView/hooks/useAIState.ts +68 -0
  462. package/src/components/AITypingIndicatorView/index.ts +2 -0
  463. package/src/components/Attachment/AudioAttachment.tsx +20 -19
  464. package/src/components/Attachment/Gallery.tsx +1 -1
  465. package/src/components/AttachmentPicker/AttachmentPicker.tsx +7 -2
  466. package/src/components/AttachmentPicker/components/AttachmentPickerItem.tsx +16 -32
  467. package/src/components/AttachmentPicker/components/AttachmentPickerSelectionBar.tsx +3 -5
  468. package/src/components/Channel/Channel.tsx +262 -821
  469. package/src/components/Channel/__tests__/Channel.test.js +244 -13
  470. package/src/components/Channel/__tests__/useMessageListPagination.test.js +419 -0
  471. package/src/components/Channel/hooks/useChannelDataState.ts +235 -0
  472. package/src/components/Channel/hooks/useCreateInputMessageInputContext.ts +2 -0
  473. package/src/components/Channel/hooks/useCreateMessagesContext.ts +4 -0
  474. package/src/components/Channel/hooks/useCreatePaginatedMessageListContext.ts +3 -10
  475. package/src/components/Channel/hooks/useMessageListPagination.tsx +246 -0
  476. package/src/components/ChannelList/Skeleton.tsx +9 -1
  477. package/src/components/ChannelList/hooks/usePaginatedChannels.ts +37 -30
  478. package/src/components/ChannelPreview/ChannelPreview.tsx +28 -107
  479. package/src/components/ChannelPreview/ChannelPreviewMessenger.tsx +5 -15
  480. package/src/components/ChannelPreview/ChannelPreviewMutedStatus.tsx +2 -7
  481. package/src/components/ChannelPreview/__tests__/ChannelPreview.test.tsx +226 -10
  482. package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayName.test.tsx +1 -1
  483. package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewMuted.test.tsx +62 -0
  484. package/src/components/ChannelPreview/hooks/useChannelPreviewData.ts +138 -0
  485. package/src/components/ChannelPreview/hooks/useIsChannelMuted.ts +29 -0
  486. package/src/components/Chat/Chat.tsx +11 -2
  487. package/src/components/Chat/hooks/__tests__/useAppSettings.test.tsx +1 -0
  488. package/src/components/Chat/hooks/useAppSettings.ts +2 -0
  489. package/src/components/Chat/hooks/useCreateChatContext.ts +2 -0
  490. package/src/components/Chat/hooks/useIsOnline.ts +0 -5
  491. package/src/components/ImageGallery/ImageGallery.tsx +1 -0
  492. package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +32 -32
  493. package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +5 -6
  494. package/src/components/ImageGallery/hooks/useAnimatedGalleryStyle.tsx +2 -2
  495. package/src/components/Message/Message.tsx +16 -2
  496. package/src/components/Message/MessageSimple/MessageContent.tsx +22 -2
  497. package/src/components/Message/MessageSimple/MessageFooter.tsx +16 -5
  498. package/src/components/Message/MessageSimple/StreamingMessageView.tsx +34 -0
  499. package/src/components/Message/MessageSimple/utils/generateMarkdownText.ts +15 -1
  500. package/src/components/Message/MessageSimple/utils/renderText.tsx +207 -3
  501. package/src/components/Message/hooks/useCreateMessageContext.ts +2 -0
  502. package/src/components/Message/hooks/useStreamingMessage.ts +54 -0
  503. package/src/components/MessageInput/MessageInput.tsx +38 -20
  504. package/src/components/MessageInput/StopMessageStreamingButton.tsx +34 -0
  505. package/src/components/MessageInput/__tests__/MessageInput.test.js +116 -2
  506. package/src/components/MessageList/MessageList.tsx +53 -85
  507. package/src/components/MessageList/ScrollToBottomButton.tsx +1 -1
  508. package/src/components/MessageList/__tests__/MessageList.test.js +174 -2
  509. package/src/components/MessageList/__tests__/ScrollToBottomButton.test.js +3 -3
  510. package/src/components/MessageList/__tests__/__snapshots__/ScrollToBottomButton.test.js.snap +1 -1
  511. package/src/components/MessageList/hooks/useMessageList.ts +2 -5
  512. package/src/components/MessageList/utils/getReadStates.ts +3 -2
  513. package/src/components/MessageMenu/MessageUserReactions.tsx +1 -1
  514. package/src/components/MessageMenu/MessageUserReactionsItem.tsx +4 -2
  515. package/src/components/MessageMenu/hooks/useFetchReactions.ts +6 -3
  516. package/src/components/Poll/CreatePollContent.tsx +4 -4
  517. package/src/components/Poll/Poll.tsx +1 -20
  518. package/src/components/Poll/components/Button.tsx +8 -420
  519. package/src/components/Poll/components/CreatePollIcon.tsx +1 -1
  520. package/src/components/Poll/components/CreatePollOptions.tsx +9 -4
  521. package/src/components/Poll/components/PollAnswersList.tsx +66 -3
  522. package/src/components/Poll/components/PollButtons.tsx +241 -0
  523. package/src/components/Poll/components/PollInputDialog.tsx +9 -6
  524. package/src/components/Poll/components/PollModalHeader.tsx +3 -3
  525. package/src/components/Poll/components/PollOption.tsx +74 -4
  526. package/src/components/Poll/components/PollResults/PollOptionFullResults.tsx +1 -1
  527. package/src/components/Poll/components/PollResults/PollResultItem.tsx +68 -52
  528. package/src/components/Poll/components/PollResults/PollVote.tsx +68 -0
  529. package/src/components/Poll/components/index.ts +1 -0
  530. package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +37 -4
  531. package/src/components/ThreadList/ThreadList.tsx +0 -2
  532. package/src/components/UIComponents/BottomSheetModal.tsx +7 -3
  533. package/src/components/index.ts +7 -0
  534. package/src/contexts/channelContext/ChannelContext.tsx +35 -25
  535. package/src/contexts/channelsStateContext/ChannelsStateContext.tsx +1 -67
  536. package/src/contexts/channelsStateContext/useChannelState.ts +6 -108
  537. package/src/contexts/chatContext/ChatContext.tsx +2 -1
  538. package/src/contexts/messageContext/MessageContext.tsx +4 -0
  539. package/src/contexts/messageInputContext/MessageInputContext.tsx +5 -1
  540. package/src/contexts/messageInputContext/hooks/useCreateMessageInputContext.ts +2 -0
  541. package/src/contexts/messagesContext/MessagesContext.tsx +8 -3
  542. package/src/contexts/paginatedMessageListContext/PaginatedMessageListContext.tsx +17 -16
  543. package/src/contexts/themeContext/utils/theme.ts +30 -1
  544. package/src/i18n/en.json +2 -0
  545. package/src/i18n/es.json +2 -0
  546. package/src/i18n/fr.json +2 -0
  547. package/src/i18n/he.json +2 -0
  548. package/src/i18n/hi.json +2 -0
  549. package/src/i18n/it.json +2 -0
  550. package/src/i18n/ja.json +2 -0
  551. package/src/i18n/ko.json +2 -0
  552. package/src/i18n/nl.json +2 -0
  553. package/src/i18n/pt-br.json +2 -0
  554. package/src/i18n/ru.json +2 -0
  555. package/src/i18n/tr.json +2 -0
  556. package/src/mock-builders/event/notificationChannelMutesUpdated.js +7 -0
  557. package/src/mock-builders/event/notificationMarkRead.js +7 -0
  558. package/src/mock-builders/event/notificationMarkUnread.js +9 -0
  559. package/src/mock-builders/generator/channel.ts +1 -0
  560. package/src/store/SqliteClient.ts +5 -1
  561. package/src/types/types.ts +3 -0
  562. package/src/utils/getTrimmedAttachmentTitle.ts +10 -2
  563. package/src/utils/utils.ts +5 -2
  564. package/src/version.json +1 -1
@@ -1,4 +1,4 @@
1
- import React, { PropsWithChildren, useCallback, useEffect, useMemo, useRef, useState } from 'react';
1
+ import React, { PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { KeyboardAvoidingViewProps, StyleSheet, Text, View } from 'react-native';
3
3
 
4
4
  import debounce from 'lodash/debounce';
@@ -11,6 +11,7 @@ import {
11
11
  ChannelState,
12
12
  Channel as ChannelType,
13
13
  EventHandler,
14
+ FormatMessageResponse,
14
15
  logChatPromiseExecution,
15
16
  MessageResponse,
16
17
  Reaction,
@@ -21,6 +22,7 @@ import {
21
22
  Thread,
22
23
  } from 'stream-chat';
23
24
 
25
+ import { useChannelDataState } from './hooks/useChannelDataState';
24
26
  import { useCreateChannelContext } from './hooks/useCreateChannelContext';
25
27
 
26
28
  import { useCreateInputMessageInputContext } from './hooks/useCreateInputMessageInputContext';
@@ -34,8 +36,10 @@ import { useCreateThreadContext } from './hooks/useCreateThreadContext';
34
36
 
35
37
  import { useCreateTypingContext } from './hooks/useCreateTypingContext';
36
38
 
39
+ import { useMessageListPagination } from './hooks/useMessageListPagination';
37
40
  import { useTargetedMessage } from './hooks/useTargetedMessage';
38
41
 
42
+ import { MessageContextValue } from '../../contexts';
39
43
  import { ChannelContextValue, ChannelProvider } from '../../contexts/channelContext/ChannelContext';
40
44
  import type { UseChannelStateValue } from '../../contexts/channelsStateContext/useChannelState';
41
45
  import { useChannelState } from '../../contexts/channelsStateContext/useChannelState';
@@ -142,6 +146,7 @@ import { MessageStatus as MessageStatusDefault } from '../Message/MessageSimple/
142
146
  import { MessageTimestamp as MessageTimestampDefault } from '../Message/MessageSimple/MessageTimestamp';
143
147
  import { ReactionListBottom as ReactionListBottomDefault } from '../Message/MessageSimple/ReactionList/ReactionListBottom';
144
148
  import { ReactionListTop as ReactionListTopDefault } from '../Message/MessageSimple/ReactionList/ReactionListTop';
149
+ import { StreamingMessageView as DefaultStreamingMessageView } from '../Message/MessageSimple/StreamingMessageView';
145
150
  import { AttachButton as AttachButtonDefault } from '../MessageInput/AttachButton';
146
151
  import { CommandsButton as CommandsButtonDefault } from '../MessageInput/CommandsButton';
147
152
  import { AudioRecorder as AudioRecorderDefault } from '../MessageInput/components/AudioRecorder/AudioRecorder';
@@ -161,6 +166,7 @@ import { MoreOptionsButton as MoreOptionsButtonDefault } from '../MessageInput/M
161
166
  import { SendButton as SendButtonDefault } from '../MessageInput/SendButton';
162
167
  import { SendMessageDisallowedIndicator as SendMessageDisallowedIndicatorDefault } from '../MessageInput/SendMessageDisallowedIndicator';
163
168
  import { ShowThreadMessageInChannelButton as ShowThreadMessageInChannelButtonDefault } from '../MessageInput/ShowThreadMessageInChannelButton';
169
+ import { StopMessageStreamingButton as DefaultStopMessageStreamingButton } from '../MessageInput/StopMessageStreamingButton';
164
170
  import { UploadProgressIndicator as UploadProgressIndicatorDefault } from '../MessageInput/UploadProgressIndicator';
165
171
  import { DateHeader as DateHeaderDefault } from '../MessageList/DateHeader';
166
172
  import type { MessageType } from '../MessageList/hooks/useMessageList';
@@ -265,7 +271,7 @@ export type ChannelPropsWithContext<
265
271
  'messages' | 'loadingMore' | 'loadingMoreRecent'
266
272
  >
267
273
  > &
268
- UseChannelStateValue<StreamChatGenerics> &
274
+ Pick<UseChannelStateValue<StreamChatGenerics>, 'threadMessages' | 'setThreadMessages'> &
269
275
  Partial<
270
276
  Pick<
271
277
  MessagesContextValue<StreamChatGenerics>,
@@ -354,8 +360,10 @@ export type ChannelPropsWithContext<
354
360
  | 'VideoThumbnail'
355
361
  | 'PollContent'
356
362
  | 'hasCreatePoll'
363
+ | 'StreamingMessageView'
357
364
  >
358
365
  > &
366
+ Partial<Pick<MessageContextValue<StreamChatGenerics>, 'isMessageAIGenerated'>> &
359
367
  Partial<Pick<ThreadContextValue<StreamChatGenerics>, 'allowThreadMessagesInChannel'>> & {
360
368
  shouldSyncChannel: boolean;
361
369
  thread: ThreadType<StreamChatGenerics>;
@@ -363,10 +371,6 @@ export type ChannelPropsWithContext<
363
371
  * Additional props passed to keyboard avoiding view
364
372
  */
365
373
  additionalKeyboardAvoidingViewProps?: Partial<KeyboardAvoidingViewProps>;
366
- /**
367
- * Disables the channel UI if the channel is frozen
368
- */
369
- disableIfFrozenChannel?: boolean;
370
374
  /**
371
375
  * When true, disables the KeyboardCompatibleView wrapper
372
376
  *
@@ -434,6 +438,10 @@ export type ChannelPropsWithContext<
434
438
  * Load the channel at a specified message instead of the most recent message.
435
439
  */
436
440
  messageId?: string;
441
+ /**
442
+ * @deprecated
443
+ * The time interval for throttling while updating the message state
444
+ */
437
445
  newMessageStateUpdateThrottleInterval?: number;
438
446
  overrideOwnCapabilities?: Partial<OwnCapabilitiesContextValue>;
439
447
  stateUpdateThrottleInterval?: number;
@@ -441,7 +449,12 @@ export type ChannelPropsWithContext<
441
449
  * Tells if channel is rendering a thread list
442
450
  */
443
451
  threadList?: boolean;
444
- } & Partial<Pick<InputMessageInputContextValue, 'openPollCreationDialog' | 'CreatePollContent'>>;
452
+ } & Partial<
453
+ Pick<
454
+ InputMessageInputContextValue,
455
+ 'openPollCreationDialog' | 'CreatePollContent' | 'StopMessageStreamingButton'
456
+ >
457
+ >;
445
458
 
446
459
  const ChannelWithContext = <
447
460
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
@@ -486,7 +499,6 @@ const ChannelWithContext = <
486
499
  CreatePollContent,
487
500
  DateHeader = DateHeaderDefault,
488
501
  deletedMessagesVisibilityType = 'always',
489
- disableIfFrozenChannel = true,
490
502
  disableKeyboardCompatibleView = false,
491
503
  disableTypingIndicator,
492
504
  dismissKeyboardOnMessageTouch = true,
@@ -544,6 +556,7 @@ const ChannelWithContext = <
544
556
  InputGiphySearch = InputGiphyCommandInputDefault,
545
557
  InputReplyStateHeader = InputReplyStateHeaderDefault,
546
558
  isAttachmentEqual,
559
+ isMessageAIGenerated = () => false,
547
560
  keyboardBehavior,
548
561
  KeyboardCompatibleView = KeyboardCompatibleViewDefault,
549
562
  keyboardVerticalOffset,
@@ -556,7 +569,6 @@ const ChannelWithContext = <
556
569
  maxMessageLength: maxMessageLengthProp,
557
570
  maxNumberOfFiles = 10,
558
571
  maxTimeBetweenGroupedMessages,
559
- members,
560
572
  mentionAllAppUsersEnabled = false,
561
573
  mentionAllAppUsersQuery,
562
574
  Message = MessageDefault,
@@ -566,7 +578,15 @@ const ChannelWithContext = <
566
578
  MessageAvatar = MessageAvatarDefault,
567
579
  MessageBounce = MessageBounceDefault,
568
580
  MessageContent = MessageContentDefault,
569
- messageContentOrder = ['quoted_reply', 'gallery', 'files', 'poll', 'text', 'attachments'],
581
+ messageContentOrder = [
582
+ 'quoted_reply',
583
+ 'gallery',
584
+ 'files',
585
+ 'poll',
586
+ 'ai_text',
587
+ 'text',
588
+ 'attachments',
589
+ ],
570
590
  MessageDeleted = MessageDeletedDefault,
571
591
  MessageEditedTimestamp = MessageEditedTimestampDefault,
572
592
  MessageError = MessageErrorDefault,
@@ -579,12 +599,11 @@ const ChannelWithContext = <
579
599
  MessageReactionPicker = MessageReactionPickerDefault,
580
600
  MessageReplies = MessageRepliesDefault,
581
601
  MessageRepliesAvatars = MessageRepliesAvatarsDefault,
582
- messages,
583
602
  MessageSimple = MessageSimpleDefault,
584
603
  MessageStatus = MessageStatusDefault,
585
604
  MessageSystem = MessageSystemDefault,
586
605
  MessageText,
587
- messageTextNumberOfLines = 5,
606
+ messageTextNumberOfLines,
588
607
  MessageTimestamp = MessageTimestampDefault,
589
608
  MessageUserReactions = MessageUserReactionsDefault,
590
609
  MessageUserReactionsAvatar = MessageUserReactionsAvatarDefault,
@@ -592,6 +611,7 @@ const ChannelWithContext = <
592
611
  MoreOptionsButton = MoreOptionsButtonDefault,
593
612
  myMessageTheme,
594
613
  NetworkDownIndicator = NetworkDownIndicatorDefault,
614
+ // TODO: Think about this one
595
615
  newMessageStateUpdateThrottleInterval = defaultThrottleInterval,
596
616
  numberOfLines = 5,
597
617
  onChangeText,
@@ -604,7 +624,6 @@ const ChannelWithContext = <
604
624
  ReactionListBottom = ReactionListBottomDefault,
605
625
  reactionListPosition = 'top',
606
626
  ReactionListTop = ReactionListTopDefault,
607
- read,
608
627
  Reply = ReplyDefault,
609
628
  ScrollToBottomButton = ScrollToBottomButtonDefault,
610
629
  selectReaction,
@@ -612,35 +631,32 @@ const ChannelWithContext = <
612
631
  sendImageAsync = false,
613
632
  SendMessageDisallowedIndicator = SendMessageDisallowedIndicatorDefault,
614
633
  setInputRef,
615
- setMembers,
616
- setMessages,
617
- setRead,
618
634
  setThreadMessages,
619
- setTyping,
620
- setWatcherCount,
621
- setWatchers,
622
635
  shouldShowUnreadUnderlay = true,
623
636
  shouldSyncChannel,
624
637
  ShowThreadMessageInChannelButton = ShowThreadMessageInChannelButtonDefault,
625
638
  StartAudioRecordingButton = AudioRecordingButtonDefault,
626
639
  stateUpdateThrottleInterval = defaultThrottleInterval,
627
640
  StickyHeader = StickyHeaderDefault,
641
+ StopMessageStreamingButton: StopMessageStreamingButtonOverride,
642
+ StreamingMessageView = DefaultStreamingMessageView,
628
643
  supportedReactions = reactionData,
629
644
  t,
630
645
  thread: threadFromProps,
631
646
  threadList,
632
647
  threadMessages,
633
- typing,
634
648
  TypingIndicator = TypingIndicatorDefault,
635
649
  TypingIndicatorContainer = TypingIndicatorContainerDefault,
636
650
  UploadProgressIndicator = UploadProgressIndicatorDefault,
637
651
  UrlPreview = CardDefault,
638
652
  VideoThumbnail = VideoThumbnailDefault,
639
- watcherCount,
640
- watchers,
641
653
  } = props;
642
654
 
643
655
  const { thread: threadProps, threadInstance } = threadFromProps;
656
+ const StopMessageStreamingButton =
657
+ StopMessageStreamingButtonOverride === undefined
658
+ ? DefaultStopMessageStreamingButton
659
+ : StopMessageStreamingButtonOverride;
644
660
 
645
661
  const {
646
662
  theme: {
@@ -648,15 +664,10 @@ const ChannelWithContext = <
648
664
  colors: { black },
649
665
  },
650
666
  } = useTheme();
651
- const [deleted, setDeleted] = useState(false);
667
+ const [deleted, setDeleted] = useState<boolean>(false);
652
668
  const [editing, setEditing] = useState<MessageType<StreamChatGenerics> | undefined>(undefined);
653
669
  const [error, setError] = useState<Error | boolean>(false);
654
- const [hasMore, setHasMore] = useState(true);
655
670
  const [lastRead, setLastRead] = useState<ChannelContextValue<StreamChatGenerics>['lastRead']>();
656
- const [loading, setLoading] = useState(false);
657
- const [loadingMore, setLoadingMore] = useState(false);
658
-
659
- const [loadingMoreRecent, setLoadingMoreRecent] = useState(false);
660
671
  const [quotedMessage, setQuotedMessage] = useState<MessageType<StreamChatGenerics> | undefined>(
661
672
  undefined,
662
673
  );
@@ -666,19 +677,7 @@ const ChannelWithContext = <
666
677
 
667
678
  const syncingChannelRef = useRef(false);
668
679
 
669
- /**
670
- * Flag to track if we know for sure that there are no more recent messages to load.
671
- * This is necessary to avoid unnecessary api calls to load recent messages on pagination.
672
- */
673
- const [hasNoMoreRecentMessagesToLoad, setHasNoMoreRecentMessagesToLoad] = useState(true);
674
-
675
- const { prevTargetedMessage, setTargetedMessage, targetedMessage } = useTargetedMessage();
676
-
677
- /**
678
- * If we loaded a channel around message
679
- * We may have moved latest message to a new message set in that case mark this ref to avoid fetching
680
- */
681
- const hasOverlappingRecentMessagesRef = useRef(false);
680
+ const { setTargetedMessage, targetedMessage } = useTargetedMessage();
682
681
 
683
682
  /**
684
683
  * This ref will hold the abort controllers for
@@ -690,50 +689,142 @@ const ChannelWithContext = <
690
689
  const channelId = channel?.id || '';
691
690
  const pollCreationEnabled = !channel.disconnected && !!channel?.id && channel?.getConfig()?.polls;
692
691
 
692
+ const {
693
+ copyStateFromChannel,
694
+ initStateFromChannel,
695
+ setTyping,
696
+ state: channelState,
697
+ } = useChannelDataState<StreamChatGenerics>(channel);
698
+
699
+ const {
700
+ copyMessagesStateFromChannel,
701
+ loadChannelAroundMessage: loadChannelAroundMessageFn,
702
+ loadChannelAtFirstUnreadMessage,
703
+ loadInitialMessagesStateFromChannel,
704
+ loadLatestMessages,
705
+ loadMore,
706
+ loadMoreRecent,
707
+ state: channelMessagesState,
708
+ } = useMessageListPagination<StreamChatGenerics>({
709
+ channel,
710
+ });
711
+
712
+ /**
713
+ * Since we copy the current channel state all together, we need to find the greatest time among the below two and apply it as the throttling time for copying the channel state.
714
+ * This is done until we remove the newMessageStateUpdateThrottleInterval prop.
715
+ */
716
+ const copyChannelStateThrottlingTime =
717
+ newMessageStateUpdateThrottleInterval > stateUpdateThrottleInterval
718
+ ? newMessageStateUpdateThrottleInterval
719
+ : stateUpdateThrottleInterval;
720
+
721
+ const copyChannelState = useRef(
722
+ throttle(
723
+ () => {
724
+ if (channel) {
725
+ copyStateFromChannel(channel);
726
+ copyMessagesStateFromChannel(channel);
727
+ }
728
+ },
729
+ copyChannelStateThrottlingTime,
730
+ throttleOptions,
731
+ ),
732
+ ).current;
733
+
734
+ const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
735
+ if (shouldSyncChannel) {
736
+ // Ignore user.watching.start and user.watching.stop events
737
+ const ignorableEvents = ['user.watching.start', 'user.watching.stop'];
738
+ if (ignorableEvents.includes(event.type)) return;
739
+
740
+ // If the event is typing.start or typing.stop, set the typing state
741
+ const isTypingEvent = event.type === 'typing.start' || event.type === 'typing.stop';
742
+ if (isTypingEvent) {
743
+ setTyping(channel);
744
+ } else {
745
+ if (thread?.id) {
746
+ const updatedThreadMessages =
747
+ (thread.id && channel && channel.state.threads[thread.id]) || threadMessages;
748
+ setThreadMessages(updatedThreadMessages);
749
+
750
+ if (channel && event.message?.id === thread.id && !threadInstance) {
751
+ const updatedThread = channel.state.formatMessage(event.message);
752
+ setThread(updatedThread);
753
+ }
754
+ }
755
+ }
756
+
757
+ // only update channel state if the events are not the previously subscribed useEffect's subscription events
758
+ if (channel && channel.initialized) {
759
+ copyChannelState();
760
+ }
761
+ }
762
+ };
763
+
693
764
  useEffect(() => {
765
+ let listener: ReturnType<typeof channel.on>;
694
766
  const initChannel = async () => {
695
767
  if (!channel || !shouldSyncChannel || channel.offlineMode) return;
696
- /**
697
- * Loading channel at first unread message requires channel to be initialized in the first place,
698
- * since we use read state on channel to decide what offset to load channel at.
699
- * Also there is no use case from UX perspective, why one would need loading uninitialized channel at particular message.
700
- * If the channel is not initiated, then we need to do channel.watch, which is more expensive for backend than channel.query.
701
- */
702
- if (!channel.initialized) {
703
- await loadChannel();
768
+ let errored = false;
769
+
770
+ if (!channel.initialized || !channel.state.isUpToDate) {
771
+ try {
772
+ await channel?.watch();
773
+ } catch (err) {
774
+ console.warn('Channel watch request failed with error:', err);
775
+ setError(true);
776
+ errored = true;
777
+ }
704
778
  }
705
779
 
706
- if (messageId) {
707
- loadChannelAroundMessage({ messageId });
780
+ if (!errored) {
781
+ initStateFromChannel(channel);
782
+ loadInitialMessagesStateFromChannel(channel, channel.state.messagePagination.hasPrev);
708
783
  }
709
- // The condition, where if the count of unread messages is greater than 4, then scroll to the first unread message.
710
- else if (
784
+
785
+ if (messageId) {
786
+ await loadChannelAroundMessage({ messageId, setTargetedMessage });
787
+ } else if (
711
788
  initialScrollToFirstUnreadMessage &&
712
789
  channel.countUnread() > scrollToFirstUnreadThreshold
713
790
  ) {
714
- loadChannelAtFirstUnreadMessage();
715
- }
716
- // If the messageId is undefined and the last message and the current message id do not match we load the channel at the very bottom.
717
- else if (
718
- channel.state.messages?.[channel.state.messages.length - 1]?.id !==
719
- channel.state.latestMessages?.[channel.state.latestMessages.length - 1]?.id &&
720
- !messageId
721
- ) {
722
- await loadChannel();
791
+ await loadChannelAtFirstUnreadMessage({ setTargetedMessage });
723
792
  }
793
+ listener = channel.on(handleEvent);
724
794
  };
725
795
 
726
796
  initChannel();
727
797
 
728
798
  return () => {
729
799
  copyChannelState.cancel();
730
- copyReadState.cancel();
731
- copyTypingState.cancel();
732
- loadMoreFinished.cancel();
733
800
  loadMoreThreadFinished.cancel();
801
+ listener?.unsubscribe();
734
802
  };
735
803
  // eslint-disable-next-line react-hooks/exhaustive-deps
736
- }, [channelId, messageId]);
804
+ }, [channel.cid, messageId, shouldSyncChannel]);
805
+
806
+ // subscribe to channel.deleted event
807
+ useEffect(() => {
808
+ const { unsubscribe } = client.on('channel.deleted', (event) => {
809
+ if (event.cid === channel?.cid) {
810
+ setDeleted(true);
811
+ }
812
+ });
813
+
814
+ return unsubscribe;
815
+ }, [channel?.cid, client]);
816
+
817
+ /**
818
+ * Subscription to the Notification mark_read event.
819
+ */
820
+ useEffect(() => {
821
+ const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
822
+ if (channel.cid === event.cid) copyChannelState();
823
+ };
824
+
825
+ const { unsubscribe } = client.on('notification.mark_read', handleEvent);
826
+ return unsubscribe;
827
+ }, [channel.cid, client, copyChannelState]);
737
828
 
738
829
  const threadPropsExists = !!threadProps;
739
830
 
@@ -785,441 +876,6 @@ const ChannelWithContext = <
785
876
  ),
786
877
  ).current;
787
878
 
788
- const copyMessagesState = useRef(
789
- throttle(
790
- () => {
791
- if (channel) {
792
- clearInterval(mergeSetsIntervalRef.current);
793
- setMessages(channel.state.messages);
794
- restartSetsMergeFuncRef.current();
795
- }
796
- },
797
- newMessageStateUpdateThrottleInterval,
798
- throttleOptions,
799
- ),
800
- ).current;
801
-
802
- const copyTypingState = useRef(
803
- throttle(
804
- () => {
805
- if (channel) {
806
- setTyping({ ...channel.state.typing });
807
- }
808
- },
809
- stateUpdateThrottleInterval,
810
- throttleOptions,
811
- ),
812
- ).current;
813
-
814
- const copyReadState = useRef(
815
- throttle(
816
- () => {
817
- if (channel) {
818
- setRead({ ...channel.state.read });
819
- }
820
- },
821
- stateUpdateThrottleInterval,
822
- throttleOptions,
823
- ),
824
- ).current;
825
-
826
- const copyChannelState = useRef(
827
- throttle(
828
- () => {
829
- setLoading(false);
830
- if (channel) {
831
- setMembers({ ...channel.state.members });
832
- setMessages([...channel.state.messages]);
833
- setRead({ ...channel.state.read });
834
- setTyping({ ...channel.state.typing });
835
- setWatcherCount(channel.state.watcher_count);
836
- setWatchers({ ...channel.state.watchers });
837
- }
838
- },
839
- stateUpdateThrottleInterval,
840
- throttleOptions,
841
- ),
842
- ).current;
843
-
844
- // subscribe to specific channel events
845
- useEffect(() => {
846
- const channelSubscriptions: Array<ReturnType<ChannelType['on']>> = [];
847
- if (channel && shouldSyncChannel) {
848
- channelSubscriptions.push(channel.on('message.new', copyMessagesState));
849
- channelSubscriptions.push(channel.on('message.read', copyReadState));
850
- channelSubscriptions.push(channel.on('typing.start', copyTypingState));
851
- channelSubscriptions.push(channel.on('typing.stop', copyTypingState));
852
- }
853
- return () => {
854
- channelSubscriptions.forEach((s) => s.unsubscribe());
855
- };
856
- // eslint-disable-next-line react-hooks/exhaustive-deps
857
- }, [channelId, shouldSyncChannel]);
858
-
859
- // subscribe to the generic all channel event
860
- useEffect(() => {
861
- const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
862
- const ignorableEvents = ['user.watching.start', 'user.watching.stop'];
863
- if (ignorableEvents.includes(event.type)) return;
864
- if (shouldSyncChannel) {
865
- const isTypingEvent = event.type === 'typing.start' || event.type === 'typing.stop';
866
- if (!isTypingEvent) {
867
- if (thread?.id) {
868
- const updatedThreadMessages =
869
- (thread.id && channel && channel.state.threads[thread.id]) || threadMessages;
870
- setThreadMessages(updatedThreadMessages);
871
- }
872
-
873
- if (channel && thread?.id && event.message?.id === thread.id && !threadInstance) {
874
- const updatedThread = channel.state.formatMessage(event.message);
875
- setThread(updatedThread);
876
- }
877
- }
878
-
879
- // only update channel state if the events are not the previously subscribed useEffect's subscription events
880
- if (
881
- channel &&
882
- channel.initialized &&
883
- event.type !== 'message.new' &&
884
- event.type !== 'message.read' &&
885
- event.type !== 'typing.start' &&
886
- event.type !== 'typing.stop'
887
- ) {
888
- copyChannelState();
889
- }
890
- }
891
- };
892
- const { unsubscribe } = channel.on(handleEvent);
893
- return unsubscribe;
894
- // eslint-disable-next-line react-hooks/exhaustive-deps
895
- }, [channelId, thread?.id, shouldSyncChannel]);
896
-
897
- // subscribe to channel.deleted event
898
- useEffect(() => {
899
- const { unsubscribe } = client.on('channel.deleted', (event) => {
900
- if (event.cid === channel?.cid) {
901
- setDeleted(true);
902
- }
903
- });
904
-
905
- return unsubscribe;
906
- // eslint-disable-next-line react-hooks/exhaustive-deps
907
- }, [channelId]);
908
-
909
- useEffect(() => {
910
- const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
911
- if (channel.cid === event.cid) copyChannelState();
912
- };
913
-
914
- const { unsubscribe } = client.on('notification.mark_read', handleEvent);
915
- return unsubscribe;
916
- // eslint-disable-next-line react-hooks/exhaustive-deps
917
- }, []);
918
-
919
- const channelQueryCallRef = useRef(
920
- async (
921
- queryCall: () => Promise<void>,
922
- onAfterQueryCall: (() => void) | undefined = undefined,
923
- // if we are scrolling to a message after the query, pass it here
924
- scrollToMessageId: string | (() => string | undefined) | undefined = undefined,
925
- ) => {
926
- setError(false);
927
- try {
928
- clearInterval(mergeSetsIntervalRef.current);
929
- await queryCall();
930
- setLastRead(new Date());
931
- setHasMore(true);
932
- const currentMessages = channel.state.messages;
933
- const hadCurrentLatestMessages =
934
- currentMessages.length > 0 && currentMessages === channel.state.latestMessages;
935
- if (typeof scrollToMessageId === 'function') {
936
- scrollToMessageId = scrollToMessageId();
937
- }
938
-
939
- const scrollToMessageIndex = scrollToMessageId
940
- ? currentMessages.findIndex(({ id }) => id === scrollToMessageId)
941
- : -1;
942
- if (channel && scrollToMessageIndex !== -1) {
943
- copyChannelState.cancel();
944
- // We assume that on average user sees 5 messages on screen
945
- // We dont want new renders to happen while scrolling to the targeted message
946
- // hence we limit the number of messages to be rendered after the targeted message to 5 - 1 = 4
947
- // NOTE: we have one drawback here, if there were already a split latest and current message set
948
- // the previous latest message set will be thrown away as we cannot merge it with the current message set after the target message is set
949
- const limitAfter = 4;
950
- const currentLength = currentMessages.length;
951
- const noOfMessagesAfter = currentLength - scrollToMessageIndex - 1;
952
- // number of messages are over the limit, limit the length of messages
953
- if (noOfMessagesAfter > limitAfter) {
954
- const endIndex = scrollToMessageIndex + limitAfter;
955
- channel.state.clearMessages();
956
- channel.state.messages = currentMessages.slice(0, endIndex + 1);
957
- splitLatestCurrentMessageSetRef.current();
958
- const restOfMessages = currentMessages.slice(endIndex + 1);
959
- if (hadCurrentLatestMessages) {
960
- const latestSet = channel.state.messageSets.find((set) => set.isLatest);
961
- if (latestSet) {
962
- latestSet.messages = restOfMessages;
963
- hasOverlappingRecentMessagesRef.current = true;
964
- }
965
- }
966
- }
967
- }
968
- const hasLatestMessages = channel.state.latestMessages.length > 0;
969
- channel.state.setIsUpToDate(hasLatestMessages);
970
- setHasNoMoreRecentMessagesToLoad(hasLatestMessages);
971
- copyChannelState();
972
- if (scrollToMessageIndex !== -1) {
973
- // since we need to scroll after immediately do this without throttle
974
- copyChannelState.flush();
975
- }
976
- onAfterQueryCall?.();
977
- } catch (err) {
978
- if (err instanceof Error) {
979
- setError(err);
980
- } else {
981
- setError(true);
982
- }
983
- setLoading(false);
984
- setLastRead(new Date());
985
- }
986
- },
987
- );
988
-
989
- /**
990
- * Loads channel at first unread message.
991
- */
992
- const loadChannelAtFirstUnreadMessage = () => {
993
- if (!channel) return;
994
- let unreadMessageIdToScrollTo: string | undefined;
995
- // query for messages around the last read date
996
- return channelQueryCallRef.current(
997
- async () => {
998
- const unreadCount = channel.countUnread();
999
- if (unreadCount === 0) return;
1000
- const isLatestMessageSetShown = !!channel.state.messageSets.find(
1001
- (set) => set.isCurrent && set.isLatest,
1002
- );
1003
- if (isLatestMessageSetShown && unreadCount <= channel.state.messages.length) {
1004
- unreadMessageIdToScrollTo =
1005
- channel.state.messages[channel.state.messages.length - unreadCount].id;
1006
- return;
1007
- }
1008
- const lastReadDate = channel.lastRead();
1009
-
1010
- // if last read date is present we can just fetch messages around that date
1011
- // last read date not being present is an edge case if somewhere the user of SDK deletes the read state (this will usually never happen)
1012
- if (lastReadDate) {
1013
- setLoading(true);
1014
- // get totally 30 messages... max 15 before last read date and max 15 after last read date
1015
- // ref: https://github.com/GetStream/chat/pull/2588
1016
- const res = await channel.query(
1017
- {
1018
- messages: {
1019
- created_at_around: lastReadDate,
1020
- limit: 30,
1021
- },
1022
- watch: true,
1023
- },
1024
- 'new',
1025
- );
1026
- unreadMessageIdToScrollTo = res.messages.find(
1027
- (m) => lastReadDate < (m.created_at ? new Date(m.created_at) : new Date()),
1028
- )?.id;
1029
- if (unreadMessageIdToScrollTo) {
1030
- channel.state.loadMessageIntoState(unreadMessageIdToScrollTo);
1031
- }
1032
- } else {
1033
- await loadLatestMessagesRef.current();
1034
- }
1035
- },
1036
- () => {
1037
- if (unreadMessageIdToScrollTo) {
1038
- restartSetsMergeFuncRef.current();
1039
- }
1040
- },
1041
- () => unreadMessageIdToScrollTo,
1042
- );
1043
- };
1044
-
1045
- /**
1046
- * Loads channel around a specific message
1047
- *
1048
- * @param messageId If undefined, channel will be loaded at most recent message.
1049
- */
1050
- const loadChannelAroundMessage: ChannelContextValue<StreamChatGenerics>['loadChannelAroundMessage'] =
1051
- async ({ messageId: messageIdToLoadAround }) => {
1052
- if (thread) {
1053
- if (messageIdToLoadAround) {
1054
- setThreadLoadingMore(true);
1055
- try {
1056
- await channel.state.loadMessageIntoState(messageIdToLoadAround, thread.id);
1057
- setThreadLoadingMore(false);
1058
- setThreadMessages(channel.state.threads[thread.id]);
1059
- setTargetedMessage(messageIdToLoadAround);
1060
- } catch (err) {
1061
- if (err instanceof Error) {
1062
- setError(err);
1063
- } else {
1064
- setError(true);
1065
- }
1066
- setThreadLoadingMore(false);
1067
- }
1068
- }
1069
- } else {
1070
- await channelQueryCallRef.current(
1071
- async () => {
1072
- setLoading(true);
1073
- if (messageIdToLoadAround) {
1074
- setMessages([]);
1075
- await channel.state.loadMessageIntoState(messageIdToLoadAround);
1076
- const currentMessageSet = channel.state.messageSets.find((set) => set.isCurrent);
1077
- if (currentMessageSet && !currentMessageSet?.isLatest) {
1078
- // if the current message set is not the latest, we will throw away the latest messages
1079
- // in order to attempt to not throw away, will attempt to merge it by loading 25 more messages
1080
- const recentCurrentSetMsgId =
1081
- currentMessageSet.messages[currentMessageSet.messages.length - 1].id;
1082
- await channel.query(
1083
- {
1084
- messages: {
1085
- id_gte: recentCurrentSetMsgId,
1086
- limit: 25,
1087
- },
1088
- },
1089
- 'current',
1090
- );
1091
- // if the gap is more than 25, we will unfortunately have to throw away the latest messages
1092
- }
1093
- }
1094
- },
1095
- () => {
1096
- if (messageIdToLoadAround) {
1097
- clearInterval(mergeSetsIntervalRef.current); // do not merge sets as we will scroll/highlight to the message
1098
- setTargetedMessage(messageIdToLoadAround);
1099
- }
1100
- },
1101
- messageIdToLoadAround,
1102
- );
1103
- }
1104
- };
1105
-
1106
- useEffect(() => {
1107
- if (!targetedMessage && prevTargetedMessage) {
1108
- // we cleared the merge sets interval to wait for the targeted message to be set
1109
- // now restart it since its done
1110
- restartSetsMergeFuncRef.current();
1111
- }
1112
- // eslint-disable-next-line react-hooks/exhaustive-deps
1113
- }, [targetedMessage]);
1114
-
1115
- /**
1116
- * Utility method to mark that current set if latest into two.
1117
- * With an empty latest set
1118
- * This is useful when we know that we dont know the latest messages anymore
1119
- * Or if we are loading a channel around a message
1120
- */
1121
- const splitLatestCurrentMessageSetRef = useRef(() => {
1122
- const currentLatestSet = channel.state.messageSets.find((set) => set.isCurrent && set.isLatest);
1123
- if (!currentLatestSet) return;
1124
- // unmark the current latest set
1125
- currentLatestSet.isLatest = false;
1126
- // create a new set with empty latest messages
1127
- channel.state.messageSets.push({
1128
- isCurrent: false,
1129
- isLatest: true,
1130
- messages: [],
1131
- pagination: {
1132
- hasNext: true,
1133
- hasPrev: true,
1134
- },
1135
- });
1136
- });
1137
-
1138
- /**
1139
- * Utility method to merge current and latest message set.
1140
- * Returns true if merge was successful, false otherwise.
1141
- */
1142
- const mergeOverlappingMessageSetsRef = useRef((limitToMaxRenderPerBatch = false) => {
1143
- if (hasOverlappingRecentMessagesRef.current) {
1144
- const limit = 5; // 5 is the load to recent limit, a larger value seems to cause jumpiness in some devices..
1145
- // merge current and latest sets
1146
- const latestMessageSet = channel.state.messageSets.find((set) => set.isLatest);
1147
- const currentMessageSet = channel.state.messageSets.find((set) => set.isCurrent);
1148
- if (latestMessageSet && currentMessageSet && latestMessageSet !== currentMessageSet) {
1149
- if (limitToMaxRenderPerBatch && latestMessageSet.messages.length > limit) {
1150
- currentMessageSet.messages = currentMessageSet.messages.concat(
1151
- latestMessageSet.messages.slice(0, limit),
1152
- );
1153
- latestMessageSet.messages = latestMessageSet.messages.slice(limit);
1154
- } else {
1155
- channel.state.messageSets = channel.state.messageSets.filter((set) => !set.isLatest);
1156
- currentMessageSet.messages = currentMessageSet.messages.concat(latestMessageSet.messages);
1157
- currentMessageSet.isLatest = true;
1158
- hasOverlappingRecentMessagesRef.current = false;
1159
- clearInterval(mergeSetsIntervalRef.current);
1160
- }
1161
- return true;
1162
- }
1163
- }
1164
- return false;
1165
- });
1166
-
1167
- const mergeSetsIntervalRef = useRef<NodeJS.Timeout>();
1168
-
1169
- // clear the interval on unmount
1170
- useEffect(
1171
- () => () => {
1172
- clearInterval(mergeSetsIntervalRef.current);
1173
- },
1174
- [],
1175
- );
1176
-
1177
- // if we had split the latest and current message set, we try to merge them back
1178
- // temporarily commented out the interval as it was causing issues with jankiness during scrolling
1179
- const restartSetsMergeFuncRef = useRef(() => {
1180
- clearInterval(mergeSetsIntervalRef.current);
1181
- if (!hasOverlappingRecentMessagesRef.current) return;
1182
- // mergeSetsIntervalRef.current = setInterval(() => {
1183
- // const currentLength = channel.state.messages.length || 0;
1184
- // const didMerge = mergeOverlappingMessageSetsRef.current(true);
1185
- // if (didMerge && channel.state.messages.length !== currentLength) {
1186
- // setMessages(channel.state.messages);
1187
- // }
1188
- // }, 1000);
1189
- });
1190
-
1191
- /**
1192
- * Shows the latest messages from the channel state
1193
- * If recent messages are empty, fetches new
1194
- * @param clearLatest If true, clears the latest messages before loading (useful for complete refresh)
1195
- */
1196
- const loadLatestMessagesRef = useRef(async (clearLatest = false) => {
1197
- mergeOverlappingMessageSetsRef.current();
1198
- if (clearLatest) {
1199
- const latestSet = channel.state.messageSets.find((set) => set.isLatest);
1200
- if (latestSet) latestSet.messages = [];
1201
- }
1202
- if (channel.state.latestMessages.length === 0) {
1203
- await channel.query({}, 'latest');
1204
- }
1205
- await channel.state.loadMessageIntoState('latest');
1206
- });
1207
-
1208
- const loadChannel = () =>
1209
- channelQueryCallRef.current(
1210
- async () => {
1211
- if (!channel?.initialized || !channel.state.isUpToDate) {
1212
- await channel?.watch();
1213
- } else {
1214
- await channel.state.loadMessageIntoState('latest');
1215
- }
1216
- },
1217
- () => {
1218
- channel?.state.setIsUpToDate(true);
1219
- setHasNoMoreRecentMessagesToLoad(true);
1220
- },
1221
- );
1222
-
1223
879
  const reloadThread = async () => {
1224
880
  if (!channel || !thread?.id) return;
1225
881
  setThreadLoadingMore(true);
@@ -1255,105 +911,39 @@ const ChannelWithContext = <
1255
911
 
1256
912
  const resyncChannel = async () => {
1257
913
  if (!channel || syncingChannelRef.current) return;
1258
- hasOverlappingRecentMessagesRef.current = false;
1259
- clearInterval(mergeSetsIntervalRef.current);
1260
914
  syncingChannelRef.current = true;
1261
-
1262
915
  setError(false);
1263
- try {
1264
- /**
1265
- * Allow a buffer of 30 new messages, so that MessageList won't move its scroll position,
1266
- * giving smooth user experience.
1267
- */
1268
- const state = await channel.watch({
1269
- messages: {
1270
- limit: messages.length + 30,
1271
- },
1272
- });
1273
-
1274
- const oldListTopMessage = messages[0];
1275
- const oldListTopMessageId = messages[0]?.id;
1276
- const oldListBottomMessage = messages[messages.length - 1];
1277
916
 
1278
- const newListTopMessage = state.messages[0];
1279
- const newListBottomMessage = state.messages[state.messages.length - 1];
1280
-
1281
- if (
1282
- !oldListTopMessage || // previous list was empty
1283
- !oldListBottomMessage || // previous list was empty
1284
- !newListTopMessage || // new list is truncated
1285
- !newListBottomMessage // new list is truncated
1286
- ) {
1287
- /** Channel was truncated */
1288
- channel.state.clearMessages();
1289
- channel.state.setIsUpToDate(true);
1290
- channel.state.addMessagesSorted(state.messages);
1291
- channel.state.addPinnedMessages(state.pinned_messages);
917
+ const parseMessage = (message: FormatMessageResponse<StreamChatGenerics>) =>
918
+ ({
919
+ ...message,
920
+ created_at: message.created_at.toString(),
921
+ pinned_at: message.pinned_at?.toString(),
922
+ updated_at: message.updated_at?.toString(),
923
+ } as unknown as MessageResponse<StreamChatGenerics>);
1292
924
 
925
+ try {
926
+ if (!thread) {
1293
927
  copyChannelState();
1294
- return;
1295
- }
1296
928
 
1297
- const parseMessage = (message: typeof oldListTopMessage) =>
1298
- ({
1299
- ...message,
1300
- created_at: message.created_at.toString(),
1301
- pinned_at: message.pinned_at?.toString(),
1302
- updated_at: message.updated_at?.toString(),
1303
- } as unknown as MessageResponse<StreamChatGenerics>);
1304
-
1305
- const failedMessages = messages
1306
- .filter((message) => message.status === MessageStatusTypes.FAILED)
1307
- .map(parseMessage);
1308
-
1309
- const failedThreadMessages = thread
1310
- ? threadMessages
1311
- .filter((message) => message.status === MessageStatusTypes.FAILED)
1312
- .map(parseMessage)
1313
- : [];
1314
-
1315
- const oldListTopMessageCreatedAt = oldListTopMessage.created_at;
1316
- const oldListBottomMessageCreatedAt = oldListBottomMessage.created_at;
1317
- const newListTopMessageCreatedAt = newListTopMessage.created_at
1318
- ? new Date(newListTopMessage.created_at)
1319
- : new Date();
1320
- const newListBottomMessageCreatedAt = newListBottomMessage?.created_at
1321
- ? new Date(newListBottomMessage.created_at)
1322
- : new Date();
1323
-
1324
- let finalMessages = [];
1325
-
1326
- if (
1327
- oldListTopMessage &&
1328
- oldListTopMessageCreatedAt &&
1329
- oldListBottomMessageCreatedAt &&
1330
- newListTopMessageCreatedAt < oldListTopMessageCreatedAt &&
1331
- newListBottomMessageCreatedAt >= oldListBottomMessageCreatedAt
1332
- ) {
1333
- const index = state.messages.findIndex((message) => message.id === oldListTopMessageId);
1334
- finalMessages = state.messages.slice(index);
929
+ const failedMessages = channelMessagesState.messages
930
+ ?.filter((message) => message.status === MessageStatusTypes.FAILED)
931
+ .map(parseMessage);
932
+ if (failedMessages?.length) {
933
+ channel.state.addMessagesSorted(failedMessages);
934
+ }
1335
935
  } else {
1336
- finalMessages = state.messages;
1337
- }
1338
-
1339
- channel.state.setIsUpToDate(true);
1340
- channel.state.clearMessages();
1341
- channel.state.addMessagesSorted(finalMessages);
1342
- channel.state.addPinnedMessages(state.pinned_messages);
1343
- setHasNoMoreRecentMessagesToLoad(true);
1344
- setHasMore(true);
1345
- copyChannelState();
1346
-
1347
- if (failedMessages.length) {
1348
- channel.state.addMessagesSorted(failedMessages);
1349
- copyChannelState();
1350
- }
1351
-
1352
- await reloadThread();
1353
-
1354
- if (thread && failedThreadMessages.length) {
1355
- channel.state.addMessagesSorted(failedThreadMessages);
1356
- setThreadMessages([...channel.state.threads[thread.id]]);
936
+ await reloadThread();
937
+
938
+ const failedThreadMessages = thread
939
+ ? threadMessages
940
+ .filter((message) => message.status === MessageStatusTypes.FAILED)
941
+ .map(parseMessage)
942
+ : [];
943
+ if (failedThreadMessages.length) {
944
+ channel.state.addMessagesSorted(failedThreadMessages);
945
+ setThreadMessages([...channel.state.threads[thread.id]]);
946
+ }
1357
947
  }
1358
948
  } catch (err) {
1359
949
  if (err instanceof Error) {
@@ -1361,7 +951,6 @@ const ChannelWithContext = <
1361
951
  } else {
1362
952
  setError(true);
1363
953
  }
1364
- setLoading(false);
1365
954
  }
1366
955
 
1367
956
  syncingChannelRef.current = false;
@@ -1382,7 +971,7 @@ const ChannelWithContext = <
1382
971
  if (enableOfflineSupport) {
1383
972
  connectionChangedSubscription = DBSyncManager.onSyncStatusChange((statusChanged) => {
1384
973
  if (statusChanged) {
1385
- connectionChangedHandler();
974
+ copyChannelState();
1386
975
  }
1387
976
  });
1388
977
  } else {
@@ -1398,15 +987,6 @@ const ChannelWithContext = <
1398
987
  // eslint-disable-next-line react-hooks/exhaustive-deps
1399
988
  }, [enableOfflineSupport, shouldSyncChannel]);
1400
989
 
1401
- const reloadChannel = () =>
1402
- channelQueryCallRef.current(async () => {
1403
- setLoading(true);
1404
- await loadLatestMessagesRef.current(true);
1405
- setLoading(false);
1406
- channel?.state.setIsUpToDate(true);
1407
- setHasNoMoreRecentMessagesToLoad(true);
1408
- });
1409
-
1410
990
  // In case the channel is disconnected which may happen when channel is deleted,
1411
991
  // underlying js client throws an error. Following function ensures that Channel component
1412
992
  // won't result in error in such a case.
@@ -1425,22 +1005,61 @@ const ChannelWithContext = <
1425
1005
  */
1426
1006
  const clientChannelConfig = getChannelConfigSafely();
1427
1007
 
1008
+ const reloadChannel = async () => {
1009
+ try {
1010
+ await loadLatestMessages();
1011
+ } catch (err) {
1012
+ console.warn('Reloading channel failed with error:', err);
1013
+ }
1014
+ };
1015
+
1016
+ const loadChannelAroundMessage: ChannelContextValue<StreamChatGenerics>['loadChannelAroundMessage'] =
1017
+ async ({ messageId: messageIdToLoadAround }): Promise<void> => {
1018
+ if (!messageIdToLoadAround) return;
1019
+ try {
1020
+ if (thread) {
1021
+ setThreadLoadingMore(true);
1022
+ try {
1023
+ await channel.state.loadMessageIntoState(messageIdToLoadAround, thread.id);
1024
+ setThreadLoadingMore(false);
1025
+ setThreadMessages(channel.state.threads[thread.id]);
1026
+ if (setTargetedMessage) {
1027
+ setTargetedMessage(messageIdToLoadAround);
1028
+ }
1029
+ } catch (err) {
1030
+ if (err instanceof Error) {
1031
+ setError(err);
1032
+ } else {
1033
+ setError(true);
1034
+ }
1035
+ setThreadLoadingMore(false);
1036
+ }
1037
+ } else {
1038
+ await loadChannelAroundMessageFn({
1039
+ messageId: messageIdToLoadAround,
1040
+ setTargetedMessage,
1041
+ });
1042
+ }
1043
+ } catch (err) {
1044
+ console.warn('Loading channel around message failed with error:', err);
1045
+ }
1046
+ };
1047
+
1428
1048
  /**
1429
1049
  * MESSAGE METHODS
1430
1050
  */
1431
-
1432
1051
  const updateMessage: MessagesContextValue<StreamChatGenerics>['updateMessage'] = (
1433
1052
  updatedMessage,
1434
1053
  extraState = {},
1435
1054
  ) => {
1436
- if (channel) {
1437
- channel.state.addMessageSorted(updatedMessage, true);
1438
- if (thread && updatedMessage.parent_id) {
1439
- extraState.threadMessages = channel.state.threads[updatedMessage.parent_id] || [];
1440
- setThreadMessages(extraState.threadMessages);
1441
- }
1055
+ if (!channel) return;
1056
+
1057
+ channel.state.addMessageSorted(updatedMessage, true);
1058
+ copyMessagesStateFromChannel(channel);
1442
1059
 
1443
- setMessages([...channel.state.messages]);
1060
+ if (thread && updatedMessage.parent_id) {
1061
+ extraState.threadMessages = channel.state.threads[updatedMessage.parent_id] || [];
1062
+ setThreadMessages(extraState.threadMessages);
1444
1063
  }
1445
1064
  };
1446
1065
 
@@ -1451,11 +1070,12 @@ const ChannelWithContext = <
1451
1070
  if (channel) {
1452
1071
  channel.state.removeMessage(oldMessage);
1453
1072
  channel.state.addMessageSorted(newMessage, true);
1073
+ copyMessagesStateFromChannel(channel);
1074
+
1454
1075
  if (thread && newMessage.parent_id) {
1455
1076
  const threadMessages = channel.state.threads[newMessage.parent_id] || [];
1456
1077
  setThreadMessages(threadMessages);
1457
1078
  }
1458
- setMessages(channel.state.messages);
1459
1079
  }
1460
1080
  };
1461
1081
 
@@ -1505,7 +1125,9 @@ const ChannelWithContext = <
1505
1125
  * as quoted_message is a reserved field.
1506
1126
  */
1507
1127
  if (preview.quoted_message_id) {
1508
- const quotedMessage = messages.find((message) => message.id === preview.quoted_message_id);
1128
+ const quotedMessage = channelMessagesState.messages?.find(
1129
+ (message) => message.id === preview.quoted_message_id,
1130
+ );
1509
1131
 
1510
1132
  preview.quoted_message =
1511
1133
  quotedMessage as MessageResponse<StreamChatGenerics>['quoted_message'];
@@ -1674,8 +1296,6 @@ const ChannelWithContext = <
1674
1296
  attachments: message.attachments || [],
1675
1297
  });
1676
1298
 
1677
- mergeOverlappingMessageSetsRef.current();
1678
-
1679
1299
  updateMessage(messagePreview, {
1680
1300
  commands: [],
1681
1301
  messageInput: '',
@@ -1716,159 +1336,6 @@ const ChannelWithContext = <
1716
1336
  );
1717
1337
  };
1718
1338
 
1719
- // hard limit to prevent you from scrolling faster than 1 page per 2 seconds
1720
- const loadMoreFinished = useRef(
1721
- debounce(
1722
- (updatedHasMore: boolean, newMessages: ChannelState<StreamChatGenerics>['messages']) => {
1723
- setLoading(false);
1724
- setLoadingMore(false);
1725
- setError(false);
1726
- setHasMore(updatedHasMore);
1727
- setMessages(newMessages);
1728
- },
1729
- defaultDebounceInterval,
1730
- debounceOptions,
1731
- ),
1732
- ).current;
1733
-
1734
- /**
1735
- * This function loads more messages before the first message in current channel state.
1736
- */
1737
- const loadMore = useCallback<PaginatedMessageListContextValue<StreamChatGenerics>['loadMore']>(
1738
- async (limit = 20) => {
1739
- if (loadingMore || hasMore === false) {
1740
- return;
1741
- }
1742
-
1743
- const currentMessages = channel.state.messages;
1744
-
1745
- if (!currentMessages.length) {
1746
- return setLoadingMore(false);
1747
- }
1748
-
1749
- const oldestMessage = currentMessages && currentMessages[0];
1750
-
1751
- if (oldestMessage && oldestMessage.status !== MessageStatusTypes.RECEIVED) {
1752
- return setLoadingMore(false);
1753
- }
1754
-
1755
- setLoadingMore(true);
1756
-
1757
- const oldestID = oldestMessage && oldestMessage.id;
1758
-
1759
- try {
1760
- if (channel) {
1761
- const queryResponse = await channel.query({
1762
- messages: { id_lt: oldestID, limit },
1763
- });
1764
-
1765
- const updatedHasMore = queryResponse.messages.length === limit;
1766
- loadMoreFinished(updatedHasMore, channel.state.messages);
1767
- }
1768
- } catch (err) {
1769
- if (err instanceof Error) {
1770
- setError(err);
1771
- } else {
1772
- setError(true);
1773
- }
1774
- setLoadingMore(false);
1775
- throw err;
1776
- }
1777
- },
1778
- /*
1779
- * This function is passed to useCreatePaginatedMessageListContext
1780
- * Where the deps are [channelId, hasMore, loadingMoreRecent, loadingMore]
1781
- * and only those deps should be used here because of that
1782
- */
1783
- // eslint-disable-next-line react-hooks/exhaustive-deps
1784
- [channelId, hasMore, loadingMore],
1785
- );
1786
-
1787
- /**
1788
- * This function loads more messages after the most recent message in current channel state.
1789
- */
1790
- const loadMoreRecent = useCallback<
1791
- PaginatedMessageListContextValue<StreamChatGenerics>['loadMoreRecent']
1792
- >(
1793
- async (limit = 5) => {
1794
- const latestMessageSet = channel.state.messageSets.find((set) => set.isLatest);
1795
- const latestLengthBeforeMerge = latestMessageSet?.messages.length || 0;
1796
- const didMerge = mergeOverlappingMessageSetsRef.current(true);
1797
- if (didMerge) {
1798
- if (latestMessageSet && latestLengthBeforeMerge >= limit) {
1799
- setLoadingMoreRecent(true);
1800
- channel.state.setIsUpToDate(true);
1801
- setHasNoMoreRecentMessagesToLoad(true);
1802
- loadMoreRecentFinished(channel.state.messages);
1803
- restartSetsMergeFuncRef.current();
1804
- return;
1805
- }
1806
- }
1807
- if (channel.state.isUpToDate) {
1808
- setLoadingMoreRecent(false);
1809
- return;
1810
- }
1811
- const currentMessages = channel.state.messages;
1812
- const recentMessage = currentMessages[currentMessages.length - 1];
1813
-
1814
- if (recentMessage?.status !== MessageStatusTypes.RECEIVED) {
1815
- setLoadingMoreRecent(false);
1816
- return;
1817
- }
1818
- setLoadingMoreRecent(true);
1819
- try {
1820
- if (channel) {
1821
- const queryResponse = await channel.query({
1822
- messages: {
1823
- id_gte: recentMessage.id,
1824
- limit,
1825
- },
1826
- watch: true,
1827
- });
1828
- const gotAllRecentMessages = queryResponse.messages.length < limit;
1829
- const currentSet = channel.state.messageSets.find((set) => set.isCurrent);
1830
- if (gotAllRecentMessages && currentSet && !currentSet.isLatest) {
1831
- channel.state.messageSets = channel.state.messageSets.filter((set) => !set.isLatest);
1832
- // make current set as the latest
1833
- currentSet.isLatest = true;
1834
- }
1835
- channel.state.setIsUpToDate(gotAllRecentMessages);
1836
- setHasNoMoreRecentMessagesToLoad(gotAllRecentMessages);
1837
- loadMoreRecentFinished(channel.state.messages);
1838
- }
1839
- } catch (err) {
1840
- console.warn('Message pagination request failed with error', err);
1841
- if (err instanceof Error) {
1842
- setError(err);
1843
- } else {
1844
- setError(true);
1845
- }
1846
- setLoadingMoreRecent(false);
1847
- throw err;
1848
- }
1849
- },
1850
- /*
1851
- * This function is passed to useCreatePaginatedMessageListContext
1852
- * Where the deps are [channelId, hasMore, loadingMoreRecent, loadingMore, hasNoMoreRecentMessagesToLoad]
1853
- * and and only those deps should be used here because of that
1854
- */
1855
- // eslint-disable-next-line react-hooks/exhaustive-deps
1856
- [channelId, hasNoMoreRecentMessagesToLoad],
1857
- );
1858
-
1859
- // hard limit to prevent you from scrolling faster than 1 page per 2 seconds
1860
- const loadMoreRecentFinished = useRef(
1861
- debounce(
1862
- (newMessages: ChannelState<StreamChatGenerics>['messages']) => {
1863
- setLoadingMoreRecent(false);
1864
- setMessages(newMessages);
1865
- setError(false);
1866
- },
1867
- defaultDebounceInterval,
1868
- debounceOptions,
1869
- ),
1870
- ).current;
1871
-
1872
1339
  const editMessage: InputMessageInputContextValue<StreamChatGenerics>['editMessage'] = (
1873
1340
  updatedMessage,
1874
1341
  ) =>
@@ -1903,7 +1370,8 @@ const ChannelWithContext = <
1903
1370
  ) => {
1904
1371
  if (channel) {
1905
1372
  channel.state.removeMessage(message);
1906
- setMessages(channel.state.messages);
1373
+ copyMessagesStateFromChannel(channel);
1374
+
1907
1375
  if (thread) {
1908
1376
  setThreadMessages(channel.state.threads[thread.id] || []);
1909
1377
  }
@@ -1942,7 +1410,7 @@ const ChannelWithContext = <
1942
1410
  user: client.user,
1943
1411
  });
1944
1412
 
1945
- setMessages(channel.state.messages);
1413
+ copyMessagesStateFromChannel(channel);
1946
1414
 
1947
1415
  const sendReactionResponse = await DBSyncManager.queueTask<StreamChatGenerics>({
1948
1416
  client,
@@ -2028,7 +1496,7 @@ const ChannelWithContext = <
2028
1496
  user: client.user,
2029
1497
  });
2030
1498
 
2031
- setMessages(channel.state.messages);
1499
+ copyMessagesStateFromChannel(channel);
2032
1500
 
2033
1501
  await DBSyncManager.queueTask<StreamChatGenerics>({
2034
1502
  client,
@@ -2123,11 +1591,6 @@ const ChannelWithContext = <
2123
1591
  }
2124
1592
  };
2125
1593
 
2126
- const disabledValue = useMemo(
2127
- () => !!channel?.data?.frozen && disableIfFrozenChannel,
2128
- [channel.data?.frozen, disableIfFrozenChannel],
2129
- );
2130
-
2131
1594
  const ownCapabilitiesContext = useCreateOwnCapabilitiesContext({
2132
1595
  channel,
2133
1596
  overrideCapabilities: overrideOwnCapabilities,
@@ -2135,7 +1598,7 @@ const ChannelWithContext = <
2135
1598
 
2136
1599
  const channelContext = useCreateChannelContext({
2137
1600
  channel,
2138
- disabled: disabledValue,
1601
+ disabled: !!channel?.data?.frozen,
2139
1602
  EmptyStateIndicator,
2140
1603
  enableMessageGroupingByUser,
2141
1604
  enforceUniqueReaction,
@@ -2148,13 +1611,13 @@ const ChannelWithContext = <
2148
1611
  isChannelActive: shouldSyncChannel,
2149
1612
  lastRead,
2150
1613
  loadChannelAroundMessage,
2151
- loading,
1614
+ loading: channelMessagesState.loading,
2152
1615
  LoadingIndicator,
2153
1616
  markRead,
2154
1617
  maxTimeBetweenGroupedMessages,
2155
- members,
1618
+ members: channelState.members ?? {},
2156
1619
  NetworkDownIndicator,
2157
- read,
1620
+ read: channelState.read ?? {},
2158
1621
  reloadChannel,
2159
1622
  scrollToFirstUnreadThreshold,
2160
1623
  setLastRead,
@@ -2163,8 +1626,8 @@ const ChannelWithContext = <
2163
1626
  targetedMessage,
2164
1627
  threadList,
2165
1628
  uploadAbortControllerRef,
2166
- watcherCount,
2167
- watchers,
1629
+ watcherCount: channelState.watcherCount,
1630
+ watchers: channelState.watchers,
2168
1631
  });
2169
1632
 
2170
1633
  // This is mainly a hack to get around an issue with sendMessage not being passed correctly as a
@@ -2236,21 +1699,22 @@ const ChannelWithContext = <
2236
1699
  setQuotedMessageState,
2237
1700
  ShowThreadMessageInChannelButton,
2238
1701
  StartAudioRecordingButton,
1702
+ StopMessageStreamingButton,
2239
1703
  UploadProgressIndicator,
2240
1704
  });
2241
1705
 
2242
1706
  const messageListContext = useCreatePaginatedMessageListContext({
2243
1707
  channelId,
2244
- hasMore,
2245
- hasNoMoreRecentMessagesToLoad,
2246
- loadingMore: loadingMoreProp !== undefined ? loadingMoreProp : loadingMore,
1708
+ hasMore: channelMessagesState.hasMore,
1709
+ loadingMore: loadingMoreProp !== undefined ? loadingMoreProp : channelMessagesState.loadingMore,
2247
1710
  loadingMoreRecent:
2248
- loadingMoreRecentProp !== undefined ? loadingMoreRecentProp : loadingMoreRecent,
1711
+ loadingMoreRecentProp !== undefined
1712
+ ? loadingMoreRecentProp
1713
+ : channelMessagesState.loadingMoreRecent,
1714
+ loadLatestMessages,
2249
1715
  loadMore,
2250
1716
  loadMoreRecent,
2251
- messages,
2252
- setLoadingMore,
2253
- setLoadingMoreRecent,
1717
+ messages: channelMessagesState.messages ?? [],
2254
1718
  });
2255
1719
 
2256
1720
  const messagesContext = useCreateMessagesContext({
@@ -2298,6 +1762,7 @@ const ChannelWithContext = <
2298
1762
  InlineDateSeparator,
2299
1763
  InlineUnreadIndicator,
2300
1764
  isAttachmentEqual,
1765
+ isMessageAIGenerated,
2301
1766
  legacyImageViewerSwipeBehaviour,
2302
1767
  markdownRules,
2303
1768
  Message,
@@ -2345,6 +1810,7 @@ const ChannelWithContext = <
2345
1810
  setEditingState,
2346
1811
  setQuotedMessageState,
2347
1812
  shouldShowUnreadUnderlay,
1813
+ StreamingMessageView,
2348
1814
  supportedReactions,
2349
1815
  targetedMessage,
2350
1816
  TypingIndicator,
@@ -2375,13 +1841,13 @@ const ChannelWithContext = <
2375
1841
  });
2376
1842
 
2377
1843
  const typingContext = useCreateTypingContext({
2378
- typing,
1844
+ typing: channelState.typing ?? {},
2379
1845
  });
2380
1846
 
2381
1847
  // TODO: replace the null view with appropriate message. Currently this is waiting a design decision.
2382
1848
  if (deleted) return null;
2383
1849
 
2384
- if (!channel || (error && messages.length === 0)) {
1850
+ if (!channel || (error && channelMessagesState.messages?.length === 0)) {
2385
1851
  return <LoadingErrorIndicator error={error} listType='message' retry={reloadChannel} />;
2386
1852
  }
2387
1853
 
@@ -2441,7 +1907,8 @@ export const Channel = <
2441
1907
  >(
2442
1908
  props: PropsWithChildren<ChannelProps<StreamChatGenerics>>,
2443
1909
  ) => {
2444
- const { client, enableOfflineSupport } = useChatContext<StreamChatGenerics>();
1910
+ const { client, enableOfflineSupport, isMessageAIGenerated } =
1911
+ useChatContext<StreamChatGenerics>();
2445
1912
  const { t } = useTranslationContext();
2446
1913
 
2447
1914
  const threadFromProps = props?.thread;
@@ -2457,22 +1924,7 @@ export const Channel = <
2457
1924
 
2458
1925
  const shouldSyncChannel = threadMessage?.id ? !!props.threadList : true;
2459
1926
 
2460
- const {
2461
- members,
2462
- messages,
2463
- read,
2464
- setMembers,
2465
- setMessages,
2466
- setRead,
2467
- setThreadMessages,
2468
- setTyping,
2469
- setWatcherCount,
2470
- setWatchers,
2471
- threadMessages,
2472
- typing,
2473
- watcherCount,
2474
- watchers,
2475
- } = useChannelState<StreamChatGenerics>(
1927
+ const { setThreadMessages, threadMessages } = useChannelState<StreamChatGenerics>(
2476
1928
  props.channel,
2477
1929
  props.threadList ? threadMessage?.id : undefined,
2478
1930
  );
@@ -2487,21 +1939,10 @@ export const Channel = <
2487
1939
  {...props}
2488
1940
  shouldSyncChannel={shouldSyncChannel}
2489
1941
  {...{
2490
- members,
2491
- messages: props.messages || messages,
2492
- read,
2493
- setMembers,
2494
- setMessages,
2495
- setRead,
1942
+ isMessageAIGenerated,
2496
1943
  setThreadMessages,
2497
- setTyping,
2498
- setWatcherCount,
2499
- setWatchers,
2500
1944
  thread,
2501
1945
  threadMessages,
2502
- typing,
2503
- watcherCount,
2504
- watchers,
2505
1946
  }}
2506
1947
  />
2507
1948
  );