stream-chat-react-native-core 9.4.0-beta.10 → 9.4.0-beta.11

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 (308) hide show
  1. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteInput.js +7 -0
  2. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteInput.js.map +1 -1
  3. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionHeader.js +2 -0
  4. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionHeader.js.map +1 -1
  5. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionItem.js +41 -55
  6. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionItem.js.map +1 -1
  7. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionList.js +27 -7
  8. package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionList.js.map +1 -1
  9. package/lib/commonjs/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.js +55 -0
  10. package/lib/commonjs/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.js.map +1 -0
  11. package/lib/commonjs/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.js +47 -0
  12. package/lib/commonjs/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.js.map +1 -0
  13. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.js +39 -0
  14. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.js.map +1 -0
  15. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionItem.js +45 -0
  16. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionItem.js.map +1 -0
  17. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionRoleItem.js +33 -0
  18. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionRoleItem.js.map +1 -0
  19. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.js +26 -0
  20. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.js.map +1 -0
  21. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionUserItem.js +53 -0
  22. package/lib/commonjs/components/AutoCompleteInput/mentionItems/MentionUserItem.js.map +1 -0
  23. package/lib/commonjs/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.js +38 -0
  24. package/lib/commonjs/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.js.map +1 -0
  25. package/lib/commonjs/components/AutoCompleteInput/mentionItems/index.js +60 -0
  26. package/lib/commonjs/components/AutoCompleteInput/mentionItems/index.js.map +1 -0
  27. package/lib/commonjs/components/Message/Message.js.map +1 -1
  28. package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js +14 -0
  29. package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
  30. package/lib/commonjs/components/Message/MessageItemView/utils/renderText.js +69 -11
  31. package/lib/commonjs/components/Message/MessageItemView/utils/renderText.js.map +1 -1
  32. package/lib/commonjs/components/MessageInput/MessageComposer.js +5 -12
  33. package/lib/commonjs/components/MessageInput/MessageComposer.js.map +1 -1
  34. package/lib/commonjs/components/MessageList/MessageFlashList.js +22 -3
  35. package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
  36. package/lib/commonjs/components/MessageList/MessageList.js +23 -4
  37. package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
  38. package/lib/commonjs/components/UIComponents/BottomSheetModal.js +4 -17
  39. package/lib/commonjs/components/UIComponents/BottomSheetModal.js.map +1 -1
  40. package/lib/commonjs/components/UIComponents/ClippingFadeBottom.js +56 -0
  41. package/lib/commonjs/components/UIComponents/ClippingFadeBottom.js.map +1 -0
  42. package/lib/commonjs/components/UIComponents/PortalWhileClosingView.js +0 -3
  43. package/lib/commonjs/components/UIComponents/PortalWhileClosingView.js.map +1 -1
  44. package/lib/commonjs/components/UIComponents/index.js +11 -0
  45. package/lib/commonjs/components/UIComponents/index.js.map +1 -1
  46. package/lib/commonjs/components/index.js +11 -0
  47. package/lib/commonjs/components/index.js.map +1 -1
  48. package/lib/commonjs/contexts/componentsContext/defaultComponents.js +1 -0
  49. package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
  50. package/lib/commonjs/contexts/themeContext/utils/theme.js +6 -1
  51. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  52. package/lib/commonjs/i18n/ar.json +6 -0
  53. package/lib/commonjs/i18n/en.json +7 -1
  54. package/lib/commonjs/i18n/es.json +6 -0
  55. package/lib/commonjs/i18n/fr.json +6 -0
  56. package/lib/commonjs/i18n/he.json +6 -0
  57. package/lib/commonjs/i18n/hi.json +6 -0
  58. package/lib/commonjs/i18n/it.json +6 -0
  59. package/lib/commonjs/i18n/ja.json +6 -0
  60. package/lib/commonjs/i18n/ko.json +6 -0
  61. package/lib/commonjs/i18n/nl.json +6 -0
  62. package/lib/commonjs/i18n/pt-br.json +6 -0
  63. package/lib/commonjs/i18n/ru.json +6 -0
  64. package/lib/commonjs/i18n/tr.json +6 -0
  65. package/lib/commonjs/icons/megaphone.js +36 -0
  66. package/lib/commonjs/icons/megaphone.js.map +1 -0
  67. package/lib/commonjs/icons/shield.js +36 -0
  68. package/lib/commonjs/icons/shield.js.map +1 -0
  69. package/lib/commonjs/store/SqliteClient.js +1 -1
  70. package/lib/commonjs/store/mappers/mapDraftMessageToStorable.js +8 -0
  71. package/lib/commonjs/store/mappers/mapDraftMessageToStorable.js.map +1 -1
  72. package/lib/commonjs/store/mappers/mapStorableToDraftMessage.js +8 -0
  73. package/lib/commonjs/store/mappers/mapStorableToDraftMessage.js.map +1 -1
  74. package/lib/commonjs/store/schema.js +4 -0
  75. package/lib/commonjs/store/schema.js.map +1 -1
  76. package/lib/commonjs/theme/generated/dark/StreamTokens.android.js +10 -1
  77. package/lib/commonjs/theme/generated/dark/StreamTokens.android.js.map +1 -1
  78. package/lib/commonjs/theme/generated/dark/StreamTokens.ios.js +10 -1
  79. package/lib/commonjs/theme/generated/dark/StreamTokens.ios.js.map +1 -1
  80. package/lib/commonjs/theme/generated/dark/StreamTokens.web.js +10 -1
  81. package/lib/commonjs/theme/generated/dark/StreamTokens.web.js.map +1 -1
  82. package/lib/commonjs/theme/generated/light/StreamTokens.android.js +10 -1
  83. package/lib/commonjs/theme/generated/light/StreamTokens.android.js.map +1 -1
  84. package/lib/commonjs/theme/generated/light/StreamTokens.ios.js +10 -1
  85. package/lib/commonjs/theme/generated/light/StreamTokens.ios.js.map +1 -1
  86. package/lib/commonjs/theme/generated/light/StreamTokens.web.js +10 -1
  87. package/lib/commonjs/theme/generated/light/StreamTokens.web.js.map +1 -1
  88. package/lib/commonjs/version.json +1 -1
  89. package/lib/module/components/AutoCompleteInput/AutoCompleteInput.js +7 -0
  90. package/lib/module/components/AutoCompleteInput/AutoCompleteInput.js.map +1 -1
  91. package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionHeader.js +2 -0
  92. package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionHeader.js.map +1 -1
  93. package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionItem.js +41 -55
  94. package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionItem.js.map +1 -1
  95. package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionList.js +27 -7
  96. package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionList.js.map +1 -1
  97. package/lib/module/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.js +55 -0
  98. package/lib/module/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.js.map +1 -0
  99. package/lib/module/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.js +47 -0
  100. package/lib/module/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.js.map +1 -0
  101. package/lib/module/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.js +39 -0
  102. package/lib/module/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.js.map +1 -0
  103. package/lib/module/components/AutoCompleteInput/mentionItems/MentionItem.js +45 -0
  104. package/lib/module/components/AutoCompleteInput/mentionItems/MentionItem.js.map +1 -0
  105. package/lib/module/components/AutoCompleteInput/mentionItems/MentionRoleItem.js +33 -0
  106. package/lib/module/components/AutoCompleteInput/mentionItems/MentionRoleItem.js.map +1 -0
  107. package/lib/module/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.js +26 -0
  108. package/lib/module/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.js.map +1 -0
  109. package/lib/module/components/AutoCompleteInput/mentionItems/MentionUserItem.js +53 -0
  110. package/lib/module/components/AutoCompleteInput/mentionItems/MentionUserItem.js.map +1 -0
  111. package/lib/module/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.js +38 -0
  112. package/lib/module/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.js.map +1 -0
  113. package/lib/module/components/AutoCompleteInput/mentionItems/index.js +60 -0
  114. package/lib/module/components/AutoCompleteInput/mentionItems/index.js.map +1 -0
  115. package/lib/module/components/Message/Message.js.map +1 -1
  116. package/lib/module/components/Message/MessageItemView/MessageTextContainer.js +14 -0
  117. package/lib/module/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
  118. package/lib/module/components/Message/MessageItemView/utils/renderText.js +69 -11
  119. package/lib/module/components/Message/MessageItemView/utils/renderText.js.map +1 -1
  120. package/lib/module/components/MessageInput/MessageComposer.js +5 -12
  121. package/lib/module/components/MessageInput/MessageComposer.js.map +1 -1
  122. package/lib/module/components/MessageList/MessageFlashList.js +22 -3
  123. package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
  124. package/lib/module/components/MessageList/MessageList.js +23 -4
  125. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  126. package/lib/module/components/UIComponents/BottomSheetModal.js +4 -17
  127. package/lib/module/components/UIComponents/BottomSheetModal.js.map +1 -1
  128. package/lib/module/components/UIComponents/ClippingFadeBottom.js +56 -0
  129. package/lib/module/components/UIComponents/ClippingFadeBottom.js.map +1 -0
  130. package/lib/module/components/UIComponents/PortalWhileClosingView.js +0 -3
  131. package/lib/module/components/UIComponents/PortalWhileClosingView.js.map +1 -1
  132. package/lib/module/components/UIComponents/index.js +11 -0
  133. package/lib/module/components/UIComponents/index.js.map +1 -1
  134. package/lib/module/components/index.js +11 -0
  135. package/lib/module/components/index.js.map +1 -1
  136. package/lib/module/contexts/componentsContext/defaultComponents.js +1 -0
  137. package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
  138. package/lib/module/contexts/themeContext/utils/theme.js +6 -1
  139. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  140. package/lib/module/i18n/ar.json +6 -0
  141. package/lib/module/i18n/en.json +7 -1
  142. package/lib/module/i18n/es.json +6 -0
  143. package/lib/module/i18n/fr.json +6 -0
  144. package/lib/module/i18n/he.json +6 -0
  145. package/lib/module/i18n/hi.json +6 -0
  146. package/lib/module/i18n/it.json +6 -0
  147. package/lib/module/i18n/ja.json +6 -0
  148. package/lib/module/i18n/ko.json +6 -0
  149. package/lib/module/i18n/nl.json +6 -0
  150. package/lib/module/i18n/pt-br.json +6 -0
  151. package/lib/module/i18n/ru.json +6 -0
  152. package/lib/module/i18n/tr.json +6 -0
  153. package/lib/module/icons/megaphone.js +36 -0
  154. package/lib/module/icons/megaphone.js.map +1 -0
  155. package/lib/module/icons/shield.js +36 -0
  156. package/lib/module/icons/shield.js.map +1 -0
  157. package/lib/module/store/SqliteClient.js +1 -1
  158. package/lib/module/store/mappers/mapDraftMessageToStorable.js +8 -0
  159. package/lib/module/store/mappers/mapDraftMessageToStorable.js.map +1 -1
  160. package/lib/module/store/mappers/mapStorableToDraftMessage.js +8 -0
  161. package/lib/module/store/mappers/mapStorableToDraftMessage.js.map +1 -1
  162. package/lib/module/store/schema.js +4 -0
  163. package/lib/module/store/schema.js.map +1 -1
  164. package/lib/module/theme/generated/dark/StreamTokens.android.js +10 -1
  165. package/lib/module/theme/generated/dark/StreamTokens.android.js.map +1 -1
  166. package/lib/module/theme/generated/dark/StreamTokens.ios.js +10 -1
  167. package/lib/module/theme/generated/dark/StreamTokens.ios.js.map +1 -1
  168. package/lib/module/theme/generated/dark/StreamTokens.web.js +10 -1
  169. package/lib/module/theme/generated/dark/StreamTokens.web.js.map +1 -1
  170. package/lib/module/theme/generated/light/StreamTokens.android.js +10 -1
  171. package/lib/module/theme/generated/light/StreamTokens.android.js.map +1 -1
  172. package/lib/module/theme/generated/light/StreamTokens.ios.js +10 -1
  173. package/lib/module/theme/generated/light/StreamTokens.ios.js.map +1 -1
  174. package/lib/module/theme/generated/light/StreamTokens.web.js +10 -1
  175. package/lib/module/theme/generated/light/StreamTokens.web.js.map +1 -1
  176. package/lib/module/version.json +1 -1
  177. package/lib/typescript/components/AutoCompleteInput/AutoCompleteInput.d.ts.map +1 -1
  178. package/lib/typescript/components/AutoCompleteInput/AutoCompleteSuggestionHeader.d.ts.map +1 -1
  179. package/lib/typescript/components/AutoCompleteInput/AutoCompleteSuggestionItem.d.ts +8 -2
  180. package/lib/typescript/components/AutoCompleteInput/AutoCompleteSuggestionItem.d.ts.map +1 -1
  181. package/lib/typescript/components/AutoCompleteInput/AutoCompleteSuggestionList.d.ts +1 -1
  182. package/lib/typescript/components/AutoCompleteInput/AutoCompleteSuggestionList.d.ts.map +1 -1
  183. package/lib/typescript/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.d.ts +13 -0
  184. package/lib/typescript/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.d.ts.map +1 -0
  185. package/lib/typescript/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.d.ts +26 -0
  186. package/lib/typescript/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.d.ts.map +1 -0
  187. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.d.ts +7 -0
  188. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.d.ts.map +1 -0
  189. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionItem.d.ts +17 -0
  190. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionItem.d.ts.map +1 -0
  191. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionRoleItem.d.ts +7 -0
  192. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionRoleItem.d.ts.map +1 -0
  193. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.d.ts +7 -0
  194. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.d.ts.map +1 -0
  195. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionUserItem.d.ts +7 -0
  196. package/lib/typescript/components/AutoCompleteInput/mentionItems/MentionUserItem.d.ts.map +1 -0
  197. package/lib/typescript/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.d.ts +21 -0
  198. package/lib/typescript/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.d.ts.map +1 -0
  199. package/lib/typescript/components/AutoCompleteInput/mentionItems/index.d.ts +17 -0
  200. package/lib/typescript/components/AutoCompleteInput/mentionItems/index.d.ts.map +1 -0
  201. package/lib/typescript/components/Message/Message.d.ts +11 -1
  202. package/lib/typescript/components/Message/Message.d.ts.map +1 -1
  203. package/lib/typescript/components/Message/MessageItemView/MessageTextContainer.d.ts.map +1 -1
  204. package/lib/typescript/components/Message/MessageItemView/utils/renderText.d.ts.map +1 -1
  205. package/lib/typescript/components/MessageInput/MessageComposer.d.ts.map +1 -1
  206. package/lib/typescript/components/MessageList/MessageFlashList.d.ts.map +1 -1
  207. package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
  208. package/lib/typescript/components/UIComponents/BottomSheetModal.d.ts.map +1 -1
  209. package/lib/typescript/components/UIComponents/ClippingFadeBottom.d.ts +18 -0
  210. package/lib/typescript/components/UIComponents/ClippingFadeBottom.d.ts.map +1 -0
  211. package/lib/typescript/components/UIComponents/index.d.ts +1 -0
  212. package/lib/typescript/components/UIComponents/index.d.ts.map +1 -1
  213. package/lib/typescript/components/index.d.ts +1 -0
  214. package/lib/typescript/components/index.d.ts.map +1 -1
  215. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +1 -0
  216. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
  217. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts +5 -0
  218. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts.map +1 -1
  219. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +5 -0
  220. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  221. package/lib/typescript/i18n/ar.json +6 -0
  222. package/lib/typescript/i18n/en.json +7 -1
  223. package/lib/typescript/i18n/es.json +6 -0
  224. package/lib/typescript/i18n/fr.json +6 -0
  225. package/lib/typescript/i18n/he.json +6 -0
  226. package/lib/typescript/i18n/hi.json +6 -0
  227. package/lib/typescript/i18n/it.json +6 -0
  228. package/lib/typescript/i18n/ja.json +6 -0
  229. package/lib/typescript/i18n/ko.json +6 -0
  230. package/lib/typescript/i18n/nl.json +6 -0
  231. package/lib/typescript/i18n/pt-br.json +6 -0
  232. package/lib/typescript/i18n/ru.json +6 -0
  233. package/lib/typescript/i18n/tr.json +6 -0
  234. package/lib/typescript/icons/megaphone.d.ts +4 -0
  235. package/lib/typescript/icons/megaphone.d.ts.map +1 -0
  236. package/lib/typescript/icons/shield.d.ts +4 -0
  237. package/lib/typescript/icons/shield.d.ts.map +1 -0
  238. package/lib/typescript/store/mappers/mapDraftMessageToStorable.d.ts.map +1 -1
  239. package/lib/typescript/store/mappers/mapStorableToDraftMessage.d.ts.map +1 -1
  240. package/lib/typescript/store/schema.d.ts +4 -0
  241. package/lib/typescript/store/schema.d.ts.map +1 -1
  242. package/lib/typescript/theme/generated/StreamTokens.types.d.ts +9 -0
  243. package/lib/typescript/theme/generated/StreamTokens.types.d.ts.map +1 -1
  244. package/lib/typescript/theme/generated/dark/StreamTokens.android.d.ts.map +1 -1
  245. package/lib/typescript/theme/generated/dark/StreamTokens.ios.d.ts.map +1 -1
  246. package/lib/typescript/theme/generated/dark/StreamTokens.web.d.ts.map +1 -1
  247. package/lib/typescript/theme/generated/light/StreamTokens.android.d.ts.map +1 -1
  248. package/lib/typescript/theme/generated/light/StreamTokens.ios.d.ts.map +1 -1
  249. package/lib/typescript/theme/generated/light/StreamTokens.web.d.ts.map +1 -1
  250. package/lib/typescript/utils/i18n/Streami18n.d.ts +6 -0
  251. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  252. package/package.json +2 -2
  253. package/src/components/AutoCompleteInput/AutoCompleteInput.tsx +13 -0
  254. package/src/components/AutoCompleteInput/AutoCompleteSuggestionHeader.tsx +2 -1
  255. package/src/components/AutoCompleteInput/AutoCompleteSuggestionItem.tsx +35 -43
  256. package/src/components/AutoCompleteInput/AutoCompleteSuggestionList.tsx +28 -3
  257. package/src/components/AutoCompleteInput/mentionItems/EnhancedMentionContent.tsx +71 -0
  258. package/src/components/AutoCompleteInput/mentionItems/EnhancedMentionIcon.tsx +71 -0
  259. package/src/components/AutoCompleteInput/mentionItems/MentionBroadcastItem.tsx +36 -0
  260. package/src/components/AutoCompleteInput/mentionItems/MentionItem.tsx +59 -0
  261. package/src/components/AutoCompleteInput/mentionItems/MentionRoleItem.tsx +27 -0
  262. package/src/components/AutoCompleteInput/mentionItems/MentionUserGroupItem.tsx +23 -0
  263. package/src/components/AutoCompleteInput/mentionItems/MentionUserItem.tsx +55 -0
  264. package/src/components/AutoCompleteInput/mentionItems/TokenizedSuggestionParts.tsx +56 -0
  265. package/src/components/AutoCompleteInput/mentionItems/__tests__/MentionItems.test.tsx +129 -0
  266. package/src/components/AutoCompleteInput/mentionItems/__tests__/TokenizedSuggestionParts.test.tsx +63 -0
  267. package/src/components/AutoCompleteInput/mentionItems/index.ts +16 -0
  268. package/src/components/Message/Message.tsx +14 -2
  269. package/src/components/Message/MessageItemView/MessageTextContainer.tsx +25 -0
  270. package/src/components/Message/MessageItemView/utils/renderText.tsx +97 -18
  271. package/src/components/MessageInput/MessageComposer.tsx +7 -9
  272. package/src/components/MessageList/MessageFlashList.tsx +28 -0
  273. package/src/components/MessageList/MessageList.tsx +28 -0
  274. package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +24 -15
  275. package/src/components/UIComponents/BottomSheetModal.tsx +2 -17
  276. package/src/components/UIComponents/ClippingFadeBottom.tsx +47 -0
  277. package/src/components/UIComponents/PortalWhileClosingView.tsx +0 -4
  278. package/src/components/UIComponents/index.ts +1 -0
  279. package/src/components/index.ts +1 -0
  280. package/src/contexts/componentsContext/defaultComponents.ts +5 -1
  281. package/src/contexts/themeContext/utils/theme.ts +10 -0
  282. package/src/i18n/ar.json +6 -0
  283. package/src/i18n/en.json +7 -1
  284. package/src/i18n/es.json +6 -0
  285. package/src/i18n/fr.json +6 -0
  286. package/src/i18n/he.json +6 -0
  287. package/src/i18n/hi.json +6 -0
  288. package/src/i18n/it.json +6 -0
  289. package/src/i18n/ja.json +6 -0
  290. package/src/i18n/ko.json +6 -0
  291. package/src/i18n/nl.json +6 -0
  292. package/src/i18n/pt-br.json +6 -0
  293. package/src/i18n/ru.json +6 -0
  294. package/src/i18n/tr.json +6 -0
  295. package/src/icons/megaphone.tsx +21 -0
  296. package/src/icons/shield.tsx +21 -0
  297. package/src/store/SqliteClient.ts +1 -1
  298. package/src/store/mappers/mapDraftMessageToStorable.ts +8 -0
  299. package/src/store/mappers/mapStorableToDraftMessage.ts +8 -0
  300. package/src/store/schema.ts +8 -0
  301. package/src/theme/generated/StreamTokens.types.ts +9 -0
  302. package/src/theme/generated/dark/StreamTokens.android.ts +10 -1
  303. package/src/theme/generated/dark/StreamTokens.ios.ts +10 -1
  304. package/src/theme/generated/dark/StreamTokens.web.ts +10 -1
  305. package/src/theme/generated/light/StreamTokens.android.ts +10 -1
  306. package/src/theme/generated/light/StreamTokens.ios.ts +10 -1
  307. package/src/theme/generated/light/StreamTokens.web.ts +10 -1
  308. package/src/version.json +1 -1
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+
3
+ import type { ChannelMentionSuggestion, HereMentionSuggestion } from 'stream-chat';
4
+
5
+ import { EnhancedMentionContent } from './EnhancedMentionContent';
6
+ import { EnhancedMentionIcon } from './EnhancedMentionIcon';
7
+ import { MentionItem } from './MentionItem';
8
+
9
+ import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
10
+ import { Megaphone } from '../../../icons/megaphone';
11
+
12
+ export type MentionBroadcastItemProps = {
13
+ entity: ChannelMentionSuggestion | HereMentionSuggestion;
14
+ };
15
+
16
+ // @channel and @here are literal SDK command keywords (matching mentioned_channel
17
+ // and mentioned_here on the wire). The title is not localized; only the
18
+ // description below it is.
19
+ const TITLE = { channel: '@channel', here: '@here' } as const;
20
+ const SUBTITLE_KEY = {
21
+ channel: 'mention/Channel Description',
22
+ here: 'mention/Here Description',
23
+ } as const;
24
+
25
+ export const MentionBroadcastItem = ({ entity }: MentionBroadcastItemProps) => {
26
+ const { t } = useTranslationContext();
27
+ return (
28
+ <MentionItem leading={<EnhancedMentionIcon Icon={Megaphone} />}>
29
+ <EnhancedMentionContent
30
+ subtitle={t(SUBTITLE_KEY[entity.mentionType])}
31
+ testID='mentions-item-name'
32
+ title={TITLE[entity.mentionType]}
33
+ />
34
+ </MentionItem>
35
+ );
36
+ };
@@ -0,0 +1,59 @@
1
+ import React, { PropsWithChildren, ReactNode, useMemo } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+
4
+ import { useTheme } from '../../../contexts/themeContext/ThemeContext';
5
+ import { primitives } from '../../../theme';
6
+
7
+ export type MentionItemProps = PropsWithChildren<{
8
+ /**
9
+ * Leading visual rendered to the left of the row. UserAvatar for user
10
+ * mentions, an `EnhancedMentionIcon` for the rest.
11
+ */
12
+ leading?: ReactNode;
13
+ testID?: string;
14
+ }>;
15
+
16
+ /**
17
+ * Layout primitive for every mention-suggestion row: `[leading | content]`.
18
+ * The per-type content (tokenized user name, or `EnhancedMentionContent` for
19
+ * channel/here/role/user_group) is passed as children. Container and column
20
+ * styles come from `theme.messageComposer.suggestions.mention`.
21
+ */
22
+ export const MentionItem = ({ children, leading, testID }: MentionItemProps) => {
23
+ const {
24
+ theme: {
25
+ messageComposer: {
26
+ suggestions: {
27
+ mention: { column, container },
28
+ },
29
+ },
30
+ },
31
+ } = useTheme();
32
+ const styles = useStyles();
33
+
34
+ return (
35
+ <View style={[styles.container, container]} testID={testID}>
36
+ {leading}
37
+ <View style={[styles.column, column]}>{children}</View>
38
+ </View>
39
+ );
40
+ };
41
+
42
+ const useStyles = () =>
43
+ useMemo(
44
+ () =>
45
+ StyleSheet.create({
46
+ column: {
47
+ flex: 1,
48
+ justifyContent: 'space-evenly',
49
+ },
50
+ container: {
51
+ alignItems: 'center',
52
+ flexDirection: 'row',
53
+ paddingHorizontal: primitives.spacingXs,
54
+ paddingVertical: primitives.spacingXs,
55
+ gap: primitives.spacingSm,
56
+ },
57
+ }),
58
+ [],
59
+ );
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+
3
+ import type { RoleMentionSuggestion } from 'stream-chat';
4
+
5
+ import { EnhancedMentionContent } from './EnhancedMentionContent';
6
+ import { EnhancedMentionIcon } from './EnhancedMentionIcon';
7
+ import { MentionItem } from './MentionItem';
8
+
9
+ import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
10
+ import { Shield } from '../../../icons/shield';
11
+
12
+ export type MentionRoleItemProps = {
13
+ entity: RoleMentionSuggestion;
14
+ };
15
+
16
+ export const MentionRoleItem = ({ entity }: MentionRoleItemProps) => {
17
+ const { t } = useTranslationContext();
18
+ return (
19
+ <MentionItem leading={<EnhancedMentionIcon Icon={Shield} />}>
20
+ <EnhancedMentionContent
21
+ subtitle={t('Notify all {{ role }} members', { role: entity.name })}
22
+ testID='mentions-item-name'
23
+ title={`@${entity.name}`}
24
+ />
25
+ </MentionItem>
26
+ );
27
+ };
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+
3
+ import type { UserGroupMentionSuggestion } from 'stream-chat';
4
+
5
+ import { EnhancedMentionContent } from './EnhancedMentionContent';
6
+ import { EnhancedMentionIcon } from './EnhancedMentionIcon';
7
+ import { MentionItem } from './MentionItem';
8
+
9
+ import { PeopleIcon } from '../../../icons/users';
10
+
11
+ export type MentionUserGroupItemProps = {
12
+ entity: UserGroupMentionSuggestion;
13
+ };
14
+
15
+ export const MentionUserGroupItem = ({ entity }: MentionUserGroupItemProps) => (
16
+ <MentionItem leading={<EnhancedMentionIcon Icon={PeopleIcon} />}>
17
+ <EnhancedMentionContent
18
+ subtitle={entity.description}
19
+ testID='mentions-item-name'
20
+ title={`@${entity.name}`}
21
+ />
22
+ </MentionItem>
23
+ );
@@ -0,0 +1,55 @@
1
+ import React, { useMemo } from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import type { UserSuggestion } from 'stream-chat';
5
+
6
+ import { MentionItem } from './MentionItem';
7
+ import { TokenizedSuggestionParts } from './TokenizedSuggestionParts';
8
+
9
+ import { useTheme } from '../../../contexts/themeContext/ThemeContext';
10
+ import { primitives } from '../../../theme';
11
+ import { UserAvatar } from '../../ui/Avatar/UserAvatar';
12
+
13
+ export type MentionUserItemProps = {
14
+ entity: UserSuggestion;
15
+ };
16
+
17
+ export const MentionUserItem = ({ entity }: MentionUserItemProps) => {
18
+ const styles = useStyles();
19
+
20
+ return (
21
+ <MentionItem
22
+ leading={
23
+ <View importantForAccessibility='no-hide-descendants'>
24
+ <UserAvatar showOnlineIndicator={!!entity.online} size='md' user={entity} />
25
+ </View>
26
+ }
27
+ >
28
+ <TokenizedSuggestionParts
29
+ fallback={entity.name || entity.id}
30
+ matchStyle={styles.match}
31
+ style={styles.name}
32
+ testID='mentions-item-name'
33
+ tokenizedDisplayName={entity.tokenizedDisplayName}
34
+ />
35
+ </MentionItem>
36
+ );
37
+ };
38
+
39
+ const useStyles = () => {
40
+ const {
41
+ theme: { semantics },
42
+ } = useTheme();
43
+ return useMemo(
44
+ () => ({
45
+ match: { fontWeight: primitives.typographyFontWeightBold },
46
+ name: {
47
+ color: semantics.textPrimary,
48
+ fontSize: primitives.typographyFontSizeMd,
49
+ lineHeight: primitives.typographyLineHeightNormal,
50
+ paddingBottom: 2,
51
+ },
52
+ }),
53
+ [semantics.textPrimary],
54
+ );
55
+ };
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { StyleProp, Text, TextStyle } from 'react-native';
3
+
4
+ import type { TokenizationPayload } from 'stream-chat';
5
+
6
+ export type TokenizedSuggestionPartsProps = {
7
+ /**
8
+ * Token + parts payload produced by the stream-chat-js text composer search
9
+ * source. When the consumer matches against a display name the source splits
10
+ * the name into substrings around the matched token; we render each part and
11
+ * bold whichever part case-insensitively equals the token.
12
+ */
13
+ tokenizedDisplayName?: TokenizationPayload['tokenizedDisplayName'];
14
+ /**
15
+ * Fallback string rendered when the tokenized payload is absent (or empty).
16
+ */
17
+ fallback?: string;
18
+ style?: StyleProp<TextStyle>;
19
+ matchStyle?: StyleProp<TextStyle>;
20
+ testID?: string;
21
+ };
22
+
23
+ const partMatchesToken = (part: string, token: string) =>
24
+ token.length > 0 && part.toLowerCase() === token.toLowerCase();
25
+
26
+ export const TokenizedSuggestionParts = ({
27
+ fallback,
28
+ matchStyle,
29
+ style,
30
+ tokenizedDisplayName,
31
+ testID,
32
+ }: TokenizedSuggestionPartsProps) => {
33
+ if (!tokenizedDisplayName || tokenizedDisplayName.parts.length === 0) {
34
+ if (!fallback) return null;
35
+ return (
36
+ <Text style={style} testID={testID}>
37
+ {fallback}
38
+ </Text>
39
+ );
40
+ }
41
+
42
+ const { parts, token } = tokenizedDisplayName;
43
+ return (
44
+ <Text style={style} testID={testID}>
45
+ {parts.map((part, index) =>
46
+ partMatchesToken(part, token) ? (
47
+ <Text key={index} style={matchStyle}>
48
+ {part}
49
+ </Text>
50
+ ) : (
51
+ part
52
+ ),
53
+ )}
54
+ </Text>
55
+ );
56
+ };
@@ -0,0 +1,129 @@
1
+ import React from 'react';
2
+
3
+ import { cleanup, render } from '@testing-library/react-native';
4
+
5
+ // UserAvatar pulls in ComponentsContext defaults which transitively load
6
+ // stream-chat-js's CJS dist; that fails to resolve @babel/runtime when the
7
+ // SDK is consumed from a workspace symlink during tests. The avatar itself
8
+ // isn't what we assert on here, so substitute a no-op.
9
+ jest.mock('../../../ui/Avatar/UserAvatar', () => ({
10
+ UserAvatar: () => null,
11
+ }));
12
+
13
+ // Same reason — useMessageComposer (used by AutoCompleteSuggestionItem) pulls
14
+ // stream-chat-js's CJS dist at module load. The dispatcher we're testing
15
+ // doesn't use these hooks itself, so stub them.
16
+ jest.mock('../../../../contexts/messageInputContext/hooks/useMessageComposer', () => ({
17
+ useMessageComposer: () => ({ textComposer: { handleSelect: () => {} } }),
18
+ }));
19
+ jest.mock('../../../../contexts/messageInputContext/hooks/useIsCommandDisabled', () => ({
20
+ useIsCommandDisabled: () => false,
21
+ }));
22
+
23
+ import type {
24
+ ChannelMentionSuggestion,
25
+ HereMentionSuggestion,
26
+ RoleMentionSuggestion,
27
+ UserGroupMentionSuggestion,
28
+ UserSuggestion,
29
+ } from 'stream-chat';
30
+
31
+ import { ThemeProvider } from '../../../../contexts/themeContext/ThemeContext';
32
+ import { defaultTheme } from '../../../../contexts/themeContext/utils/theme';
33
+ import { MentionSuggestionItem } from '../../AutoCompleteSuggestionItem';
34
+
35
+ const wrap = (ui: React.ReactElement) =>
36
+ render(<ThemeProvider theme={defaultTheme}>{ui}</ThemeProvider>);
37
+
38
+ const userEntity: UserSuggestion = {
39
+ id: 'u1',
40
+ mentionType: 'user',
41
+ name: 'Alice',
42
+ tokenizedDisplayName: { parts: ['Alice'], token: '' },
43
+ } as unknown as UserSuggestion;
44
+
45
+ const channelEntity: ChannelMentionSuggestion = {
46
+ id: 'channel',
47
+ mentionType: 'channel',
48
+ name: 'channel',
49
+ tokenizedDisplayName: { parts: ['channel'], token: '' },
50
+ } as unknown as ChannelMentionSuggestion;
51
+
52
+ const hereEntity: HereMentionSuggestion = {
53
+ id: 'here',
54
+ mentionType: 'here',
55
+ name: 'here',
56
+ tokenizedDisplayName: { parts: ['here'], token: '' },
57
+ } as unknown as HereMentionSuggestion;
58
+
59
+ const roleEntity: RoleMentionSuggestion = {
60
+ id: 'admin',
61
+ mentionType: 'role',
62
+ name: 'admin',
63
+ tokenizedDisplayName: { parts: ['admin'], token: '' },
64
+ } as unknown as RoleMentionSuggestion;
65
+
66
+ const groupEntity: UserGroupMentionSuggestion = {
67
+ description: 'Engineering org',
68
+ id: 'eng',
69
+ memberCount: 42,
70
+ mentionType: 'user_group',
71
+ name: 'engineering',
72
+ tokenizedDisplayName: { parts: ['engineering'], token: '' },
73
+ } as unknown as UserGroupMentionSuggestion;
74
+
75
+ describe('MentionSuggestionItem', () => {
76
+ afterEach(() => {
77
+ cleanup();
78
+ });
79
+
80
+ it('renders a user row with the display name', () => {
81
+ const { getByText } = wrap(<MentionSuggestionItem {...userEntity} />);
82
+ expect(getByText('Alice')).toBeTruthy();
83
+ });
84
+
85
+ it('renders a broadcast row for @channel with description subtitle', () => {
86
+ const { getByText } = wrap(<MentionSuggestionItem {...channelEntity} />);
87
+ expect(getByText('@channel')).toBeTruthy();
88
+ expect(getByText('mention/Channel Description')).toBeTruthy();
89
+ });
90
+
91
+ it('renders a broadcast row for @here with description subtitle', () => {
92
+ const { getByText } = wrap(<MentionSuggestionItem {...hereEntity} />);
93
+ expect(getByText('@here')).toBeTruthy();
94
+ expect(getByText('mention/Here Description')).toBeTruthy();
95
+ });
96
+
97
+ it('renders a role row with the role name and the notify subtitle', () => {
98
+ const { getByText } = wrap(<MentionSuggestionItem {...roleEntity} />);
99
+ expect(getByText('@admin')).toBeTruthy();
100
+ // The test translation context echoes the i18n key; the {{ role }}
101
+ // interpolation is left as-is, which is enough to assert the right key
102
+ // was selected with the right argument.
103
+ expect(getByText(/Notify all .* members/)).toBeTruthy();
104
+ });
105
+
106
+ it('renders a user group row with name + description', () => {
107
+ const { getByText } = wrap(<MentionSuggestionItem {...groupEntity} />);
108
+ expect(getByText('@engineering')).toBeTruthy();
109
+ expect(getByText('Engineering org')).toBeTruthy();
110
+ });
111
+
112
+ it('omits the subtitle slot when a user group has no description', () => {
113
+ const { queryByText } = wrap(
114
+ <MentionSuggestionItem
115
+ {...({ ...groupEntity, description: undefined } as UserGroupMentionSuggestion)}
116
+ />,
117
+ );
118
+ expect(queryByText('Engineering org')).toBeNull();
119
+ });
120
+
121
+ it('renders nothing for an unknown mention type', () => {
122
+ const { toJSON } = wrap(
123
+ <MentionSuggestionItem
124
+ {...({ id: 'x', mentionType: 'unknown' } as unknown as ChannelMentionSuggestion)}
125
+ />,
126
+ );
127
+ expect(toJSON()).toBeNull();
128
+ });
129
+ });
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+
3
+ import { cleanup, render } from '@testing-library/react-native';
4
+
5
+ import { TokenizedSuggestionParts } from '../TokenizedSuggestionParts';
6
+
7
+ describe('TokenizedSuggestionParts', () => {
8
+ afterEach(() => {
9
+ cleanup();
10
+ });
11
+
12
+ it('renders the fallback when no tokenized payload is provided', () => {
13
+ const { getByText } = render(<TokenizedSuggestionParts fallback='Jane Doe' />);
14
+ expect(getByText('Jane Doe')).toBeTruthy();
15
+ });
16
+
17
+ it('renders nothing when neither tokenized payload nor fallback is provided', () => {
18
+ const { toJSON } = render(<TokenizedSuggestionParts />);
19
+ expect(toJSON()).toBeNull();
20
+ });
21
+
22
+ it('renders all parts when the tokenized payload is present', () => {
23
+ const { queryByText } = render(
24
+ <TokenizedSuggestionParts tokenizedDisplayName={{ parts: ['Al', 'i', 'ce'], token: 'i' }} />,
25
+ );
26
+ // The full name still reads through because RN concatenates nested Text children.
27
+ expect(queryByText('Alice')).toBeTruthy();
28
+ });
29
+
30
+ it('wraps the matched part in a separate Text node so it can be styled', () => {
31
+ const matchStyle = { fontWeight: 'bold' as const };
32
+ const { UNSAFE_root } = render(
33
+ <TokenizedSuggestionParts
34
+ matchStyle={matchStyle}
35
+ tokenizedDisplayName={{ parts: ['Al', 'ice', 'son'], token: 'ice' }}
36
+ />,
37
+ );
38
+ // The matched substring is rendered inside a nested Text — the only one
39
+ // carrying our matchStyle — so the count of styled descendants equals the
40
+ // number of matching parts (case-insensitive).
41
+ const matchedNodes = UNSAFE_root.findAll(
42
+ (node) =>
43
+ typeof node.type !== 'string' &&
44
+ Array.isArray(node.props?.style) === false &&
45
+ node.props?.style === matchStyle,
46
+ );
47
+ expect(matchedNodes.length).toBe(1);
48
+ });
49
+
50
+ it('matches case-insensitively', () => {
51
+ const matchStyle = { fontWeight: 'bold' as const };
52
+ const { UNSAFE_root } = render(
53
+ <TokenizedSuggestionParts
54
+ matchStyle={matchStyle}
55
+ tokenizedDisplayName={{ parts: ['Channel'], token: 'channel' }}
56
+ />,
57
+ );
58
+ const matchedNodes = UNSAFE_root.findAll(
59
+ (node) => typeof node.type !== 'string' && node.props?.style === matchStyle,
60
+ );
61
+ expect(matchedNodes.length).toBe(1);
62
+ });
63
+ });
@@ -0,0 +1,16 @@
1
+ export { EnhancedMentionContent } from './EnhancedMentionContent';
2
+ export type { EnhancedMentionContentProps } from './EnhancedMentionContent';
3
+ export { EnhancedMentionIcon } from './EnhancedMentionIcon';
4
+ export type { EnhancedMentionIconProps } from './EnhancedMentionIcon';
5
+ export { MentionBroadcastItem } from './MentionBroadcastItem';
6
+ export type { MentionBroadcastItemProps } from './MentionBroadcastItem';
7
+ export { MentionItem } from './MentionItem';
8
+ export type { MentionItemProps } from './MentionItem';
9
+ export { MentionRoleItem } from './MentionRoleItem';
10
+ export type { MentionRoleItemProps } from './MentionRoleItem';
11
+ export { MentionUserGroupItem } from './MentionUserGroupItem';
12
+ export type { MentionUserGroupItemProps } from './MentionUserGroupItem';
13
+ export { MentionUserItem } from './MentionUserItem';
14
+ export type { MentionUserItemProps } from './MentionUserItem';
15
+ export { TokenizedSuggestionParts } from './TokenizedSuggestionParts';
16
+ export type { TokenizedSuggestionPartsProps } from './TokenizedSuggestionParts';
@@ -11,7 +11,7 @@ import {
11
11
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
12
12
  import { Portal } from 'react-native-teleport';
13
13
 
14
- import type { Attachment, LocalMessage, UserResponse } from 'stream-chat';
14
+ import type { Attachment, LocalMessage, MentionEntity, UserResponse } from 'stream-chat';
15
15
 
16
16
  import { useCreateMessageContext } from './hooks/useCreateMessageContext';
17
17
  import { useMessageActionHandlers } from './hooks/useMessageActionHandlers';
@@ -94,7 +94,19 @@ export type TouchableEmitter =
94
94
  | 'messageReplies'
95
95
  | 'reactionList';
96
96
 
97
- export type TextMentionTouchableHandlerAdditionalInfo = { user?: UserResponse };
97
+ export type TextMentionTouchableHandlerAdditionalInfo = {
98
+ /**
99
+ * The typed mention entity for the pressed mention (user / channel / here /
100
+ * role / user_group). Always populated by the default renderText pipeline;
101
+ * undefined only when a custom renderer doesn't resolve a match.
102
+ */
103
+ mentionedEntity?: MentionEntity;
104
+ /**
105
+ * Back-compat: still populated when the mention is a user, so existing
106
+ * integrators reading `additionalInfo.user` keep working.
107
+ */
108
+ user?: UserResponse;
109
+ };
98
110
 
99
111
  export type TextMentionTouchableHandlerPayload = {
100
112
  emitter: 'textMention';
@@ -166,6 +166,31 @@ const areEqual = (
166
166
  return false;
167
167
  }
168
168
 
169
+ // Enhanced mention sources (channel/here/roles/groups) — without these the
170
+ // renderText cache would refresh on a new entity but this comparator would
171
+ // short-circuit it away and the highlight would not appear until something
172
+ // else re-rendered the row.
173
+ const mentionedBroadcastEqual =
174
+ prevMessage.mentioned_channel === nextMessage.mentioned_channel &&
175
+ prevMessage.mentioned_here === nextMessage.mentioned_here;
176
+ if (!mentionedBroadcastEqual) {
177
+ return false;
178
+ }
179
+
180
+ const joinIds = (values?: string[]) => (values ?? []).join('|');
181
+ const mentionedRolesEqual =
182
+ joinIds(prevMessage.mentioned_roles) === joinIds(nextMessage.mentioned_roles);
183
+ if (!mentionedRolesEqual) {
184
+ return false;
185
+ }
186
+
187
+ const groupIds = (m: typeof prevMessage) =>
188
+ joinIds(m.mentioned_groups?.map((g) => g.id) ?? m.mentioned_group_ids);
189
+ const mentionedGroupsEqual = groupIds(prevMessage) === groupIds(nextMessage);
190
+ if (!mentionedGroupsEqual) {
191
+ return false;
192
+ }
193
+
169
194
  // stringify could be an expensive operation, so lets rule out the obvious
170
195
  // possibilities first such as different object reference or empty objects etc.
171
196
  // Also keeping markdown equality check at the last to make sure other less