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

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 (331) hide show
  1. package/lib/commonjs/components/ChannelDetails/ChannelDetails.js +8 -3
  2. package/lib/commonjs/components/ChannelDetails/ChannelDetails.js.map +1 -1
  3. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsActionItem.js +2 -1
  4. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsActionItem.js.map +1 -1
  5. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsEditButton.js +57 -0
  6. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsEditButton.js.map +1 -0
  7. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsNavHeader.js +3 -32
  8. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsNavHeader.js.map +1 -1
  9. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsNavigationSection.js +64 -25
  10. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsNavigationSection.js.map +1 -1
  11. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsProfile.js +3 -2
  12. package/lib/commonjs/components/ChannelDetails/components/ChannelDetailsProfile.js.map +1 -1
  13. package/lib/commonjs/components/ChannelDetails/components/ChannelEditImageSheet.js +2 -2
  14. package/lib/commonjs/components/ChannelDetails/components/ChannelEditImageSheet.js.map +1 -1
  15. package/lib/commonjs/components/ChannelDetails/components/index.js +22 -0
  16. package/lib/commonjs/components/ChannelDetails/components/index.js.map +1 -1
  17. package/lib/commonjs/components/ChannelDetails/components/members/ChannelMemberItem.js +2 -1
  18. package/lib/commonjs/components/ChannelDetails/components/members/ChannelMemberItem.js.map +1 -1
  19. package/lib/commonjs/components/ChannelDetails/components/modal/Modal.js +22 -23
  20. package/lib/commonjs/components/ChannelDetails/components/modal/Modal.js.map +1 -1
  21. package/lib/commonjs/components/ChannelDetails/components/modal/ModalHeader.js +6 -4
  22. package/lib/commonjs/components/ChannelDetails/components/modal/ModalHeader.js.map +1 -1
  23. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentItem.js +65 -0
  24. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentItem.js.map +1 -0
  25. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentList.js +174 -0
  26. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentList.js.map +1 -0
  27. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.js +21 -0
  28. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.js.map +1 -0
  29. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.js +45 -0
  30. package/lib/commonjs/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.js.map +1 -0
  31. package/lib/commonjs/components/ChannelDetails/components/navigation-section/MediaItem.js +120 -0
  32. package/lib/commonjs/components/ChannelDetails/components/navigation-section/MediaItem.js.map +1 -0
  33. package/lib/commonjs/components/ChannelDetails/components/navigation-section/MediaList.js +206 -0
  34. package/lib/commonjs/components/ChannelDetails/components/navigation-section/MediaList.js.map +1 -0
  35. package/lib/commonjs/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.js +63 -0
  36. package/lib/commonjs/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.js.map +1 -0
  37. package/lib/commonjs/components/ChannelDetails/components/navigation-section/PinnedMessageItem.js +84 -0
  38. package/lib/commonjs/components/ChannelDetails/components/navigation-section/PinnedMessageItem.js.map +1 -0
  39. package/lib/commonjs/components/ChannelDetails/components/navigation-section/PinnedMessageList.js +177 -0
  40. package/lib/commonjs/components/ChannelDetails/components/navigation-section/PinnedMessageList.js.map +1 -0
  41. package/lib/commonjs/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.js +21 -0
  42. package/lib/commonjs/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.js.map +1 -0
  43. package/lib/commonjs/components/ChannelDetails/components/navigation-section/index.js +114 -0
  44. package/lib/commonjs/components/ChannelDetails/components/navigation-section/index.js.map +1 -0
  45. package/lib/commonjs/components/ChannelDetails/hooks/index.js +33 -0
  46. package/lib/commonjs/components/ChannelDetails/hooks/index.js.map +1 -1
  47. package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.js +55 -0
  48. package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.js.map +1 -0
  49. package/lib/commonjs/components/ChannelDetails/hooks/useFileAttachmentListSections.js +52 -0
  50. package/lib/commonjs/components/ChannelDetails/hooks/useFileAttachmentListSections.js.map +1 -0
  51. package/lib/commonjs/components/ChannelDetails/hooks/useMediaList.js +30 -0
  52. package/lib/commonjs/components/ChannelDetails/hooks/useMediaList.js.map +1 -0
  53. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +23 -15
  54. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  55. package/lib/commonjs/components/UIComponents/EmptyList.js +78 -0
  56. package/lib/commonjs/components/UIComponents/EmptyList.js.map +1 -0
  57. package/lib/commonjs/components/UIComponents/index.js +11 -0
  58. package/lib/commonjs/components/UIComponents/index.js.map +1 -1
  59. package/lib/commonjs/components/ui/Avatar/AvatarGroup.js +3 -3
  60. package/lib/commonjs/components/ui/Avatar/constants.js +2 -2
  61. package/lib/commonjs/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js +64 -0
  62. package/lib/commonjs/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js.map +1 -0
  63. package/lib/commonjs/contexts/channelMediaListContext/ChannelMediaListContext.js +63 -0
  64. package/lib/commonjs/contexts/channelMediaListContext/ChannelMediaListContext.js.map +1 -0
  65. package/lib/commonjs/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js +73 -0
  66. package/lib/commonjs/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js.map +1 -0
  67. package/lib/commonjs/contexts/componentsContext/defaultComponents.js +8 -0
  68. package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
  69. package/lib/commonjs/contexts/index.js +33 -0
  70. package/lib/commonjs/contexts/index.js.map +1 -1
  71. package/lib/commonjs/contexts/themeContext/utils/theme.js +57 -2
  72. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  73. package/lib/commonjs/i18n/ar.json +11 -0
  74. package/lib/commonjs/i18n/en.json +11 -0
  75. package/lib/commonjs/i18n/es.json +11 -0
  76. package/lib/commonjs/i18n/fr.json +11 -0
  77. package/lib/commonjs/i18n/he.json +11 -0
  78. package/lib/commonjs/i18n/hi.json +11 -0
  79. package/lib/commonjs/i18n/it.json +11 -0
  80. package/lib/commonjs/i18n/ja.json +11 -0
  81. package/lib/commonjs/i18n/ko.json +11 -0
  82. package/lib/commonjs/i18n/nl.json +11 -0
  83. package/lib/commonjs/i18n/pt-br.json +11 -0
  84. package/lib/commonjs/i18n/ru.json +11 -0
  85. package/lib/commonjs/i18n/tr.json +11 -0
  86. package/lib/commonjs/icons/folder.js +37 -0
  87. package/lib/commonjs/icons/folder.js.map +1 -0
  88. package/lib/commonjs/icons/index.js +12 -0
  89. package/lib/commonjs/icons/index.js.map +1 -1
  90. package/lib/commonjs/version.json +1 -1
  91. package/lib/module/components/ChannelDetails/ChannelDetails.js +8 -3
  92. package/lib/module/components/ChannelDetails/ChannelDetails.js.map +1 -1
  93. package/lib/module/components/ChannelDetails/components/ChannelDetailsActionItem.js +2 -1
  94. package/lib/module/components/ChannelDetails/components/ChannelDetailsActionItem.js.map +1 -1
  95. package/lib/module/components/ChannelDetails/components/ChannelDetailsEditButton.js +57 -0
  96. package/lib/module/components/ChannelDetails/components/ChannelDetailsEditButton.js.map +1 -0
  97. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavHeader.js +3 -32
  98. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavHeader.js.map +1 -1
  99. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavigationSection.js +64 -25
  100. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavigationSection.js.map +1 -1
  101. package/lib/module/components/ChannelDetails/components/ChannelDetailsProfile.js +3 -2
  102. package/lib/module/components/ChannelDetails/components/ChannelDetailsProfile.js.map +1 -1
  103. package/lib/module/components/ChannelDetails/components/ChannelEditImageSheet.js +2 -2
  104. package/lib/module/components/ChannelDetails/components/ChannelEditImageSheet.js.map +1 -1
  105. package/lib/module/components/ChannelDetails/components/index.js +22 -0
  106. package/lib/module/components/ChannelDetails/components/index.js.map +1 -1
  107. package/lib/module/components/ChannelDetails/components/members/ChannelMemberItem.js +2 -1
  108. package/lib/module/components/ChannelDetails/components/members/ChannelMemberItem.js.map +1 -1
  109. package/lib/module/components/ChannelDetails/components/modal/Modal.js +22 -23
  110. package/lib/module/components/ChannelDetails/components/modal/Modal.js.map +1 -1
  111. package/lib/module/components/ChannelDetails/components/modal/ModalHeader.js +6 -4
  112. package/lib/module/components/ChannelDetails/components/modal/ModalHeader.js.map +1 -1
  113. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentItem.js +65 -0
  114. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentItem.js.map +1 -0
  115. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentList.js +174 -0
  116. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentList.js.map +1 -0
  117. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.js +21 -0
  118. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.js.map +1 -0
  119. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.js +45 -0
  120. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.js.map +1 -0
  121. package/lib/module/components/ChannelDetails/components/navigation-section/MediaItem.js +120 -0
  122. package/lib/module/components/ChannelDetails/components/navigation-section/MediaItem.js.map +1 -0
  123. package/lib/module/components/ChannelDetails/components/navigation-section/MediaList.js +206 -0
  124. package/lib/module/components/ChannelDetails/components/navigation-section/MediaList.js.map +1 -0
  125. package/lib/module/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.js +63 -0
  126. package/lib/module/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.js.map +1 -0
  127. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageItem.js +84 -0
  128. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageItem.js.map +1 -0
  129. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageList.js +177 -0
  130. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageList.js.map +1 -0
  131. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.js +21 -0
  132. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.js.map +1 -0
  133. package/lib/module/components/ChannelDetails/components/navigation-section/index.js +114 -0
  134. package/lib/module/components/ChannelDetails/components/navigation-section/index.js.map +1 -0
  135. package/lib/module/components/ChannelDetails/hooks/index.js +33 -0
  136. package/lib/module/components/ChannelDetails/hooks/index.js.map +1 -1
  137. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.js +55 -0
  138. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.js.map +1 -0
  139. package/lib/module/components/ChannelDetails/hooks/useFileAttachmentListSections.js +52 -0
  140. package/lib/module/components/ChannelDetails/hooks/useFileAttachmentListSections.js.map +1 -0
  141. package/lib/module/components/ChannelDetails/hooks/useMediaList.js +30 -0
  142. package/lib/module/components/ChannelDetails/hooks/useMediaList.js.map +1 -0
  143. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +23 -15
  144. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  145. package/lib/module/components/UIComponents/EmptyList.js +78 -0
  146. package/lib/module/components/UIComponents/EmptyList.js.map +1 -0
  147. package/lib/module/components/UIComponents/index.js +11 -0
  148. package/lib/module/components/UIComponents/index.js.map +1 -1
  149. package/lib/module/components/ui/Avatar/AvatarGroup.js +3 -3
  150. package/lib/module/components/ui/Avatar/constants.js +2 -2
  151. package/lib/module/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js +64 -0
  152. package/lib/module/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js.map +1 -0
  153. package/lib/module/contexts/channelMediaListContext/ChannelMediaListContext.js +63 -0
  154. package/lib/module/contexts/channelMediaListContext/ChannelMediaListContext.js.map +1 -0
  155. package/lib/module/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js +73 -0
  156. package/lib/module/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js.map +1 -0
  157. package/lib/module/contexts/componentsContext/defaultComponents.js +8 -0
  158. package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
  159. package/lib/module/contexts/index.js +33 -0
  160. package/lib/module/contexts/index.js.map +1 -1
  161. package/lib/module/contexts/themeContext/utils/theme.js +57 -2
  162. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  163. package/lib/module/i18n/ar.json +11 -0
  164. package/lib/module/i18n/en.json +11 -0
  165. package/lib/module/i18n/es.json +11 -0
  166. package/lib/module/i18n/fr.json +11 -0
  167. package/lib/module/i18n/he.json +11 -0
  168. package/lib/module/i18n/hi.json +11 -0
  169. package/lib/module/i18n/it.json +11 -0
  170. package/lib/module/i18n/ja.json +11 -0
  171. package/lib/module/i18n/ko.json +11 -0
  172. package/lib/module/i18n/nl.json +11 -0
  173. package/lib/module/i18n/pt-br.json +11 -0
  174. package/lib/module/i18n/ru.json +11 -0
  175. package/lib/module/i18n/tr.json +11 -0
  176. package/lib/module/icons/folder.js +37 -0
  177. package/lib/module/icons/folder.js.map +1 -0
  178. package/lib/module/icons/index.js +12 -0
  179. package/lib/module/icons/index.js.map +1 -1
  180. package/lib/module/version.json +1 -1
  181. package/lib/typescript/components/ChannelDetails/ChannelDetails.d.ts +11 -1
  182. package/lib/typescript/components/ChannelDetails/ChannelDetails.d.ts.map +1 -1
  183. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsActionItem.d.ts.map +1 -1
  184. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsEditButton.d.ts +6 -0
  185. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsEditButton.d.ts.map +1 -0
  186. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsNavHeader.d.ts +3 -1
  187. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsNavHeader.d.ts.map +1 -1
  188. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsNavigationSection.d.ts.map +1 -1
  189. package/lib/typescript/components/ChannelDetails/components/index.d.ts +3 -0
  190. package/lib/typescript/components/ChannelDetails/components/index.d.ts.map +1 -1
  191. package/lib/typescript/components/ChannelDetails/components/members/ChannelMemberItem.d.ts.map +1 -1
  192. package/lib/typescript/components/ChannelDetails/components/modal/Modal.d.ts +2 -1
  193. package/lib/typescript/components/ChannelDetails/components/modal/Modal.d.ts.map +1 -1
  194. package/lib/typescript/components/ChannelDetails/components/modal/ModalHeader.d.ts +3 -1
  195. package/lib/typescript/components/ChannelDetails/components/modal/ModalHeader.d.ts.map +1 -1
  196. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentItem.d.ts +31 -0
  197. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentItem.d.ts.map +1 -0
  198. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentList.d.ts +17 -0
  199. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentList.d.ts.map +1 -0
  200. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.d.ts +9 -0
  201. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.d.ts.map +1 -0
  202. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.d.ts +13 -0
  203. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.d.ts.map +1 -0
  204. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaItem.d.ts +35 -0
  205. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaItem.d.ts.map +1 -0
  206. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaList.d.ts +17 -0
  207. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaList.d.ts.map +1 -0
  208. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.d.ts +11 -0
  209. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.d.ts.map +1 -0
  210. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageItem.d.ts +19 -0
  211. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageItem.d.ts.map +1 -0
  212. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageList.d.ts +19 -0
  213. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageList.d.ts.map +1 -0
  214. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.d.ts +9 -0
  215. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.d.ts.map +1 -0
  216. package/lib/typescript/components/ChannelDetails/components/navigation-section/index.d.ts +11 -0
  217. package/lib/typescript/components/ChannelDetails/components/navigation-section/index.d.ts.map +1 -0
  218. package/lib/typescript/components/ChannelDetails/hooks/index.d.ts +3 -0
  219. package/lib/typescript/components/ChannelDetails/hooks/index.d.ts.map +1 -1
  220. package/lib/typescript/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.d.ts +56 -0
  221. package/lib/typescript/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.d.ts.map +1 -0
  222. package/lib/typescript/components/ChannelDetails/hooks/useFileAttachmentListSections.d.ts +28 -0
  223. package/lib/typescript/components/ChannelDetails/hooks/useFileAttachmentListSections.d.ts.map +1 -0
  224. package/lib/typescript/components/ChannelDetails/hooks/useMediaList.d.ts +20 -0
  225. package/lib/typescript/components/ChannelDetails/hooks/useMediaList.d.ts.map +1 -0
  226. package/lib/typescript/components/ImageGallery/components/ImageGalleryHeader.d.ts.map +1 -1
  227. package/lib/typescript/components/UIComponents/EmptyList.d.ts +24 -0
  228. package/lib/typescript/components/UIComponents/EmptyList.d.ts.map +1 -0
  229. package/lib/typescript/components/UIComponents/index.d.ts +1 -0
  230. package/lib/typescript/components/UIComponents/index.d.ts.map +1 -1
  231. package/lib/typescript/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.d.ts +21 -0
  232. package/lib/typescript/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.d.ts.map +1 -0
  233. package/lib/typescript/contexts/channelMediaListContext/ChannelMediaListContext.d.ts +21 -0
  234. package/lib/typescript/contexts/channelMediaListContext/ChannelMediaListContext.d.ts.map +1 -0
  235. package/lib/typescript/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.d.ts +21 -0
  236. package/lib/typescript/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.d.ts.map +1 -0
  237. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +18 -2
  238. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
  239. package/lib/typescript/contexts/index.d.ts +3 -0
  240. package/lib/typescript/contexts/index.d.ts.map +1 -1
  241. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts +56 -1
  242. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts.map +1 -1
  243. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +56 -1
  244. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  245. package/lib/typescript/i18n/ar.json +11 -0
  246. package/lib/typescript/i18n/en.json +11 -0
  247. package/lib/typescript/i18n/es.json +11 -0
  248. package/lib/typescript/i18n/fr.json +11 -0
  249. package/lib/typescript/i18n/he.json +11 -0
  250. package/lib/typescript/i18n/hi.json +11 -0
  251. package/lib/typescript/i18n/it.json +11 -0
  252. package/lib/typescript/i18n/ja.json +11 -0
  253. package/lib/typescript/i18n/ko.json +11 -0
  254. package/lib/typescript/i18n/nl.json +11 -0
  255. package/lib/typescript/i18n/pt-br.json +11 -0
  256. package/lib/typescript/i18n/ru.json +11 -0
  257. package/lib/typescript/i18n/tr.json +11 -0
  258. package/lib/typescript/icons/folder.d.ts +4 -0
  259. package/lib/typescript/icons/folder.d.ts.map +1 -0
  260. package/lib/typescript/icons/index.d.ts +1 -0
  261. package/lib/typescript/icons/index.d.ts.map +1 -1
  262. package/lib/typescript/utils/i18n/Streami18n.d.ts +11 -0
  263. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  264. package/package.json +1 -1
  265. package/src/components/ChannelDetails/ChannelDetails.tsx +17 -2
  266. package/src/components/ChannelDetails/__tests__/ChannelDetails.test.tsx +29 -0
  267. package/src/components/ChannelDetails/__tests__/ChannelDetailsEditButton.test.tsx +127 -0
  268. package/src/components/ChannelDetails/__tests__/ChannelDetailsNavHeader.test.tsx +21 -56
  269. package/src/components/ChannelDetails/__tests__/ChannelDetailsNavigationSection.test.tsx +225 -6
  270. package/src/components/ChannelDetails/__tests__/useFileAttachmentListSections.test.tsx +159 -0
  271. package/src/components/ChannelDetails/__tests__/useMediaList.test.tsx +53 -0
  272. package/src/components/ChannelDetails/components/ChannelDetailsActionItem.tsx +6 -1
  273. package/src/components/ChannelDetails/components/ChannelDetailsEditButton.tsx +50 -0
  274. package/src/components/ChannelDetails/components/ChannelDetailsNavHeader.tsx +6 -33
  275. package/src/components/ChannelDetails/components/ChannelDetailsNavigationSection.tsx +80 -32
  276. package/src/components/ChannelDetails/components/ChannelDetailsProfile.tsx +2 -1
  277. package/src/components/ChannelDetails/components/ChannelEditImageSheet.tsx +2 -2
  278. package/src/components/ChannelDetails/components/__tests__/navigation-section/FileAttachmentItem.test.tsx +80 -0
  279. package/src/components/ChannelDetails/components/__tests__/navigation-section/FileAttachmentList.test.tsx +334 -0
  280. package/src/components/ChannelDetails/components/__tests__/navigation-section/FileAttachmentListSectionHeader.test.tsx +19 -0
  281. package/src/components/ChannelDetails/components/__tests__/navigation-section/MediaItem.test.tsx +97 -0
  282. package/src/components/ChannelDetails/components/__tests__/navigation-section/MediaList.test.tsx +351 -0
  283. package/src/components/ChannelDetails/components/__tests__/navigation-section/PinnedMessageItem.test.tsx +112 -0
  284. package/src/components/ChannelDetails/components/__tests__/navigation-section/PinnedMessageList.test.tsx +324 -0
  285. package/src/components/ChannelDetails/components/index.ts +3 -0
  286. package/src/components/ChannelDetails/components/members/ChannelMemberItem.tsx +6 -1
  287. package/src/components/ChannelDetails/components/modal/Modal.tsx +37 -24
  288. package/src/components/ChannelDetails/components/modal/ModalHeader.tsx +11 -4
  289. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentItem.tsx +92 -0
  290. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentList.tsx +204 -0
  291. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.tsx +23 -0
  292. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.tsx +56 -0
  293. package/src/components/ChannelDetails/components/navigation-section/MediaItem.tsx +160 -0
  294. package/src/components/ChannelDetails/components/navigation-section/MediaList.tsx +244 -0
  295. package/src/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.tsx +66 -0
  296. package/src/components/ChannelDetails/components/navigation-section/PinnedMessageItem.tsx +94 -0
  297. package/src/components/ChannelDetails/components/navigation-section/PinnedMessageList.tsx +198 -0
  298. package/src/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.tsx +23 -0
  299. package/src/components/ChannelDetails/components/navigation-section/index.ts +10 -0
  300. package/src/components/ChannelDetails/hooks/index.ts +3 -0
  301. package/src/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.ts +108 -0
  302. package/src/components/ChannelDetails/hooks/useFileAttachmentListSections.ts +79 -0
  303. package/src/components/ChannelDetails/hooks/useMediaList.ts +51 -0
  304. package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +21 -18
  305. package/src/components/UIComponents/EmptyList.tsx +80 -0
  306. package/src/components/UIComponents/__tests__/EmptyList.test.tsx +90 -0
  307. package/src/components/UIComponents/index.ts +1 -0
  308. package/src/components/ui/Avatar/AvatarGroup.tsx +3 -3
  309. package/src/components/ui/Avatar/constants.ts +2 -2
  310. package/src/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.tsx +67 -0
  311. package/src/contexts/channelMediaListContext/ChannelMediaListContext.tsx +68 -0
  312. package/src/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.tsx +72 -0
  313. package/src/contexts/componentsContext/defaultComponents.ts +16 -1
  314. package/src/contexts/index.ts +3 -0
  315. package/src/contexts/themeContext/utils/theme.ts +112 -2
  316. package/src/i18n/ar.json +11 -0
  317. package/src/i18n/en.json +11 -0
  318. package/src/i18n/es.json +11 -0
  319. package/src/i18n/fr.json +11 -0
  320. package/src/i18n/he.json +11 -0
  321. package/src/i18n/hi.json +11 -0
  322. package/src/i18n/it.json +11 -0
  323. package/src/i18n/ja.json +11 -0
  324. package/src/i18n/ko.json +11 -0
  325. package/src/i18n/nl.json +11 -0
  326. package/src/i18n/pt-br.json +11 -0
  327. package/src/i18n/ru.json +11 -0
  328. package/src/i18n/tr.json +11 -0
  329. package/src/icons/folder.tsx +28 -0
  330. package/src/icons/index.ts +1 -0
  331. package/src/version.json +1 -1
@@ -0,0 +1,66 @@
1
+ import React, { useMemo } from 'react';
2
+ import { StyleSheet, useWindowDimensions, View } from 'react-native';
3
+
4
+ import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
5
+ import { primitives } from '../../../../theme';
6
+ import { NativeShimmerView } from '../../../UIComponents/NativeShimmerView';
7
+
8
+ const NUMBER_OF_COLUMNS = 3;
9
+ const NUMBER_OF_ROWS = 6;
10
+ const GRID_GAP = primitives.spacingXxxs;
11
+ const ANIMATION_TIME = 1000;
12
+
13
+ /**
14
+ * Grid of shimmering placeholder tiles shown while the media list is loading.
15
+ *
16
+ * @experimental This component is experimental and is subject to change.
17
+ */
18
+ export const MediaListLoadingSkeleton = () => {
19
+ const {
20
+ theme: { semantics },
21
+ } = useTheme();
22
+ const { width } = useWindowDimensions();
23
+ const styles = useStyles();
24
+
25
+ const tileSize = (width - GRID_GAP * (NUMBER_OF_COLUMNS - 1)) / NUMBER_OF_COLUMNS;
26
+
27
+ return (
28
+ <View style={styles.container} testID='media-list-loading-skeleton'>
29
+ {Array.from({ length: NUMBER_OF_ROWS }).map((_, rowIndex) => (
30
+ <View key={rowIndex} style={styles.row}>
31
+ {Array.from({ length: NUMBER_OF_COLUMNS }).map((__, columnIndex) => (
32
+ <View key={columnIndex} style={[styles.tile, { height: tileSize, width: tileSize }]}>
33
+ <NativeShimmerView
34
+ baseColor={semantics.backgroundCoreSurfaceDefault}
35
+ duration={ANIMATION_TIME}
36
+ gradientColor={semantics.skeletonLoadingHighlight}
37
+ style={StyleSheet.absoluteFill}
38
+ />
39
+ </View>
40
+ ))}
41
+ </View>
42
+ ))}
43
+ </View>
44
+ );
45
+ };
46
+
47
+ MediaListLoadingSkeleton.displayName = 'MediaListLoadingSkeleton';
48
+
49
+ const useStyles = () =>
50
+ useMemo(
51
+ () =>
52
+ StyleSheet.create({
53
+ container: {
54
+ gap: GRID_GAP,
55
+ },
56
+ row: {
57
+ flexDirection: 'row',
58
+ gap: GRID_GAP,
59
+ },
60
+ tile: {
61
+ borderRadius: primitives.radiusXxs,
62
+ overflow: 'hidden',
63
+ },
64
+ }),
65
+ [],
66
+ );
@@ -0,0 +1,94 @@
1
+ import React, { useMemo } from 'react';
2
+ import { I18nManager, StyleSheet, Text, View } from 'react-native';
3
+
4
+ import type { Channel, MessageResponse } from 'stream-chat';
5
+
6
+ import { useComponentsContext } from '../../../../contexts';
7
+ import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
8
+ import { primitives } from '../../../../theme';
9
+ import { ChannelPreviewStatusProps } from '../../../ChannelPreview/ChannelPreviewStatus';
10
+ import { UserAvatar } from '../../../ui/Avatar/UserAvatar';
11
+
12
+ export type PinnedMessageItemProps = {
13
+ /** The channel the pinned message belongs to. */
14
+ channel: Channel;
15
+ /** The pinned message to render. */
16
+ message: MessageResponse;
17
+ } & { formatMessageDate?: ChannelPreviewStatusProps['formatLatestMessageDate'] };
18
+
19
+ /**
20
+ * @experimental This component is experimental and is subject to change.
21
+ */
22
+ export const PinnedMessageItem = (props: PinnedMessageItemProps) => {
23
+ const { channel, message, formatMessageDate } = props;
24
+ const {
25
+ theme: {
26
+ channelDetails: { pinnedMessageItem },
27
+ semantics,
28
+ },
29
+ } = useTheme();
30
+ const { ChannelPreviewLastMessage, ChannelPreviewStatus } = useComponentsContext();
31
+ const styles = useStyles();
32
+
33
+ const senderName = message.user?.name || message.user?.id || '';
34
+
35
+ return (
36
+ <View
37
+ style={[styles.container, pinnedMessageItem.container]}
38
+ testID={`pinned-message-item-${message.id}`}
39
+ >
40
+ {message.user ? <UserAvatar size='lg' user={message.user} /> : null}
41
+ <View style={[styles.content, pinnedMessageItem.content]}>
42
+ <View style={[styles.title, pinnedMessageItem.title]}>
43
+ <Text
44
+ ellipsizeMode='tail'
45
+ numberOfLines={1}
46
+ style={[styles.name, { color: semantics.textPrimary }, pinnedMessageItem.name]}
47
+ >
48
+ {senderName}
49
+ </Text>
50
+ <ChannelPreviewStatus
51
+ channel={channel}
52
+ lastMessage={message}
53
+ formatLatestMessageDate={formatMessageDate}
54
+ />
55
+ </View>
56
+ <ChannelPreviewLastMessage message={message}></ChannelPreviewLastMessage>
57
+ </View>
58
+ </View>
59
+ );
60
+ };
61
+
62
+ PinnedMessageItem.displayName = 'PinnedMessageItem{pinnedMessageItem}';
63
+
64
+ const useStyles = () => {
65
+ return useMemo(
66
+ () =>
67
+ StyleSheet.create({
68
+ container: {
69
+ alignItems: 'center',
70
+ flexDirection: 'row',
71
+ gap: primitives.spacingSm,
72
+ paddingHorizontal: primitives.spacingSm,
73
+ paddingVertical: primitives.spacingMd,
74
+ },
75
+ content: {
76
+ flex: 1,
77
+ gap: primitives.spacingXxxs,
78
+ },
79
+ name: {
80
+ flex: 1,
81
+ fontSize: primitives.typographyFontSizeMd,
82
+ fontWeight: primitives.typographyFontWeightRegular,
83
+ lineHeight: primitives.typographyLineHeightNormal,
84
+ writingDirection: I18nManager.isRTL ? 'rtl' : 'ltr',
85
+ },
86
+ title: {
87
+ alignItems: 'center',
88
+ flexDirection: 'row',
89
+ gap: primitives.spacingXxs,
90
+ },
91
+ }),
92
+ [],
93
+ );
94
+ };
@@ -0,0 +1,198 @@
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { ActivityIndicator, FlatList, type FlatListProps, StyleSheet, View } from 'react-native';
3
+
4
+ import type { MessageResponse, SearchSourceState } from 'stream-chat';
5
+
6
+ import { PinnedMessageListLoadingSkeleton } from './PinnedMessageListLoadingSkeleton';
7
+
8
+ import { useChannelDetailsContext } from '../../../../contexts/channelDetailsContext/channelDetailsContext';
9
+ import {
10
+ ChannelPinnedMessageListProvider,
11
+ useChannelPinnedMessageListContext,
12
+ } from '../../../../contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext';
13
+ import { useComponentsContext } from '../../../../contexts/componentsContext/ComponentsContext';
14
+ import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
15
+ import { useTranslationContext } from '../../../../contexts/translationContext/TranslationContext';
16
+ import { getNotificationErrorOptions } from '../../../../hooks/actions/useChannelActions';
17
+ import { useStateStore } from '../../../../hooks/useStateStore';
18
+ import { Pin } from '../../../../icons/pin';
19
+ import { primitives } from '../../../../theme';
20
+ import { useNotificationApi } from '../../../Notifications/hooks/useNotificationApi';
21
+ import { NotificationList } from '../../../Notifications/NotificationList';
22
+ import { NotificationTargetProvider } from '../../../Notifications/NotificationTargetContext';
23
+ import { EmptyList } from '../../../UIComponents/EmptyList';
24
+ import { EmptySearchResult } from '../../../UIComponents/EmptySearchResult';
25
+ import { SearchInput, SearchInputProps } from '../../../UIComponents/SearchInput';
26
+
27
+ export type PinnedMessageListProps = {
28
+ /**
29
+ * Besides the existing default behavior of the pinned message list, you can attach
30
+ * additional props to the underlying React Native FlatList.
31
+ *
32
+ * See https://reactnative.dev/docs/flatlist#props for the full list.
33
+ */
34
+ additionalFlatListProps?: Partial<FlatListProps<MessageResponse>>;
35
+ searchInputProps?: SearchInputProps;
36
+ };
37
+
38
+ const keyExtractor = (message: MessageResponse) => message.id;
39
+
40
+ const listStateSelector = (state: SearchSourceState<MessageResponse>) => ({
41
+ error: state.lastQueryError,
42
+ hasNext: state.hasNext,
43
+ loading: state.isLoading,
44
+ messages: state.items,
45
+ searchQuery: state.searchQuery,
46
+ });
47
+
48
+ const PinnedMessageListContent = ({
49
+ additionalFlatListProps,
50
+ searchInputProps,
51
+ }: PinnedMessageListProps) => {
52
+ const { t } = useTranslationContext();
53
+ const {
54
+ theme: {
55
+ channelDetails: { pinnedMessageList },
56
+ },
57
+ } = useTheme();
58
+ const styles = useStyles();
59
+ const { PinnedMessageItem } = useComponentsContext();
60
+
61
+ const { addNotification } = useNotificationApi();
62
+
63
+ const { channel, searchSource } = useChannelPinnedMessageListContext();
64
+ const { error, hasNext, loading, messages, searchQuery } = useStateStore(
65
+ searchSource.state,
66
+ listStateSelector,
67
+ );
68
+
69
+ const initialized = useRef(false);
70
+ useEffect(() => {
71
+ if (!initialized.current) {
72
+ initialized.current = true;
73
+ searchSource.search();
74
+ }
75
+ }, [searchSource]);
76
+
77
+ const [isEmpty, setIsEmpty] = useState<boolean | undefined>(undefined);
78
+ useEffect(() => {
79
+ if (!messages || isEmpty !== undefined) return;
80
+ if (!searchSource.state.getLatestValue().searchQuery && messages.length === 0) {
81
+ setIsEmpty(true);
82
+ }
83
+ }, [isEmpty, messages, searchSource]);
84
+
85
+ useEffect(() => {
86
+ if (!error) {
87
+ return;
88
+ }
89
+ addNotification({
90
+ message: t('Failed to load pinned messages'),
91
+ options: {
92
+ ...getNotificationErrorOptions(error),
93
+ severity: 'error',
94
+ type: 'api:channel:query-pinned-messages:failed',
95
+ },
96
+ origin: { context: { channel }, emitter: 'ChannelPinnedMessageList' },
97
+ });
98
+ }, [error, addNotification, channel, t]);
99
+
100
+ const renderItem = useCallback(
101
+ ({ item }: { item: MessageResponse }) => <PinnedMessageItem channel={channel} message={item} />,
102
+ [channel, PinnedMessageItem],
103
+ );
104
+
105
+ const loadMore = useCallback(() => {
106
+ // hasNext is true by default, !!messages prevents calling search on initial load
107
+ if (hasNext && !!messages) {
108
+ searchSource.search();
109
+ }
110
+ }, [hasNext, messages, searchSource]);
111
+
112
+ const emptyState = loading ? (
113
+ <PinnedMessageListLoadingSkeleton />
114
+ ) : isEmpty ? (
115
+ <EmptyList
116
+ icon={Pin}
117
+ subtitle={t('Long-press a message to pin it to the chat')}
118
+ title={t('No pinned messages')}
119
+ />
120
+ ) : (
121
+ <EmptySearchResult label={t('No pinned messages')} />
122
+ );
123
+
124
+ const loadingMoreIndicator = (
125
+ <>{loading && messages && messages.length > 0 && <ActivityIndicator />}</>
126
+ );
127
+
128
+ return (
129
+ <View style={[styles.container, pinnedMessageList.container]}>
130
+ {!isEmpty && (
131
+ <SearchInput
132
+ value={searchQuery}
133
+ accessibilityLabel={t('a11y/Search pinned messages')}
134
+ onChangeText={(text) => {
135
+ searchSource.state.partialNext({ searchQuery: text });
136
+ searchSource.search(text);
137
+ }}
138
+ {...searchInputProps}
139
+ />
140
+ )}
141
+ <FlatList
142
+ contentContainerStyle={[styles.listContent, pinnedMessageList.listContent]}
143
+ data={messages}
144
+ keyboardDismissMode='interactive'
145
+ keyboardShouldPersistTaps='handled'
146
+ keyExtractor={keyExtractor}
147
+ ListEmptyComponent={emptyState}
148
+ ListFooterComponent={loadingMoreIndicator}
149
+ onEndReached={loadMore}
150
+ onEndReachedThreshold={0.2}
151
+ renderItem={renderItem}
152
+ style={[styles.list, pinnedMessageList.list]}
153
+ testID='pinned-message-list'
154
+ {...additionalFlatListProps}
155
+ />
156
+ <NotificationList />
157
+ </View>
158
+ );
159
+ };
160
+
161
+ /**
162
+ * @experimental This component is experimental and is subject to change.
163
+ */
164
+ export const PinnedMessageList = (props: PinnedMessageListProps) => {
165
+ const { channel } = useChannelDetailsContext();
166
+ const notificationHostId = channel?.cid ? `pinned-message-list:${channel.cid}` : undefined;
167
+
168
+ if (!notificationHostId) {
169
+ return null;
170
+ }
171
+
172
+ return (
173
+ <ChannelPinnedMessageListProvider channel={channel}>
174
+ <NotificationTargetProvider hostId={notificationHostId} panel='channel-details'>
175
+ <PinnedMessageListContent {...props} />
176
+ </NotificationTargetProvider>
177
+ </ChannelPinnedMessageListProvider>
178
+ );
179
+ };
180
+
181
+ const useStyles = () => {
182
+ return useMemo(
183
+ () =>
184
+ StyleSheet.create({
185
+ container: {
186
+ flex: 1,
187
+ },
188
+ list: {
189
+ flex: 1,
190
+ },
191
+ listContent: {
192
+ flexGrow: 1,
193
+ paddingBottom: primitives.spacingXl,
194
+ },
195
+ }),
196
+ [],
197
+ );
198
+ };
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+
3
+ import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
4
+ import { GenericListLoadingSkeleton } from '../../../UIComponents/GenericListLoadingSkeleton';
5
+
6
+ /**
7
+ * @experimental This component is experimental and is subject to change.
8
+ */
9
+ export const PinnedMessageListLoadingSkeleton = () => {
10
+ const {
11
+ theme: { pinnedMessageListSkeleton },
12
+ } = useTheme();
13
+
14
+ return (
15
+ <GenericListLoadingSkeleton
16
+ skeleton={pinnedMessageListSkeleton}
17
+ testID='pinned-message-list-loading-skeleton'
18
+ />
19
+ );
20
+ };
21
+
22
+ PinnedMessageListLoadingSkeleton.displayName =
23
+ 'PinnedMessageListLoadingSkeleton{pinnedMessageListSkeleton}';
@@ -0,0 +1,10 @@
1
+ export * from './FileAttachmentItem';
2
+ export * from './FileAttachmentList';
3
+ export * from './FileAttachmentListLoadingSkeleton';
4
+ export * from './FileAttachmentListSectionHeader';
5
+ export * from './MediaItem';
6
+ export * from './MediaList';
7
+ export * from './MediaListLoadingSkeleton';
8
+ export * from './PinnedMessageItem';
9
+ export * from './PinnedMessageList';
10
+ export * from './PinnedMessageListLoadingSkeleton';
@@ -1,6 +1,9 @@
1
1
  export * from './useChannelDetailsActionItems';
2
+ export * from './useChannelDetailsNavigationItems';
2
3
  export * from './useChannelDetailsMemberStatusText';
3
4
  export * from './useChannelDetailsMembersPreview';
4
5
  export * from './useEditChannelImage';
6
+ export * from './useFileAttachmentListSections';
7
+ export * from './useMediaList';
5
8
  export * from './useUserActivityStatus';
6
9
  export * from './members';
@@ -0,0 +1,108 @@
1
+ import React, { useMemo } from 'react';
2
+
3
+ import { useChannelDetailsContext } from '../../../contexts/channelDetailsContext/channelDetailsContext';
4
+ import type { TranslationContextValue } from '../../../contexts/translationContext/TranslationContext';
5
+ import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
6
+ import { Picture } from '../../../icons';
7
+ import { Folder } from '../../../icons/folder';
8
+
9
+ import { Pin } from '../../../icons/pin';
10
+ import type { IconProps } from '../../../icons/utils/base';
11
+
12
+ /**
13
+ * Identifies a navigation row. The literals are the built-in sections rendered by default;
14
+ * consumers can also add their own rows with arbitrary section identifiers via `getNavigationItems`,
15
+ * so any string is allowed.
16
+ *
17
+ * @experimental This type is experimental and is subject to change.
18
+ */
19
+ export type ChannelDetailsNavigationSectionType =
20
+ | 'pinned-messages'
21
+ | 'photos-and-videos'
22
+ | 'files'
23
+ | string;
24
+
25
+ /**
26
+ * A single row in the channel details navigation section.
27
+ *
28
+ * @experimental This type is experimental and is subject to change.
29
+ */
30
+ export type ChannelDetailsNavigationItem = {
31
+ /** Icon rendered at the start of the row and reused in the built-in modal header. */
32
+ Icon: React.ComponentType<IconProps>;
33
+ /** Already-translated label rendered for the row and its built-in modal header. */
34
+ label: string;
35
+ /** Identifies which built-in section this row represents. */
36
+ section: ChannelDetailsNavigationSectionType;
37
+ /**
38
+ * Fired when the user taps the row. Leave unset to keep the built-in behavior (opening the
39
+ * built-in modal for the section); set it to route the row somewhere else (e.g. your own screen).
40
+ */
41
+ onPress?: () => void;
42
+ };
43
+
44
+ /**
45
+ * Maps each navigation section to the icon and (translatable) label rendered for its row and,
46
+ * when opened, its modal header. The declaration order also drives the order of the rendered rows.
47
+ */
48
+ const SECTION_CONFIG: Record<
49
+ 'pinned-messages' | 'photos-and-videos' | 'files',
50
+ { Icon: React.ComponentType<IconProps>; label: string }
51
+ > = {
52
+ 'pinned-messages': { Icon: Pin, label: 'Pinned Messages' },
53
+ 'photos-and-videos': { Icon: Picture, label: 'Photos & Videos' },
54
+ files: { Icon: Folder, label: 'Files' },
55
+ };
56
+
57
+ const SECTIONS = Object.keys(SECTION_CONFIG) as Array<keyof typeof SECTION_CONFIG>;
58
+
59
+ export type ChannelDetailsNavigationItemsContext = {
60
+ t: TranslationContextValue['t'];
61
+ };
62
+
63
+ /**
64
+ * Customizes the navigation rows rendered by `ChannelDetailsNavigationSection`. Receives the
65
+ * built-in `defaultItems` (and a `context`) and returns the items to render. Map over
66
+ * `defaultItems` to set a row's `onPress` (e.g. to push your own screen), or add/remove rows. Any
67
+ * row whose `onPress` you leave unset keeps its built-in behavior (opening the built-in modal) —
68
+ * including sections added in future SDK versions.
69
+ *
70
+ * @experimental This type is experimental and is subject to change.
71
+ */
72
+ export type GetChannelDetailsNavigationItems = (params: {
73
+ context: ChannelDetailsNavigationItemsContext;
74
+ defaultItems: ChannelDetailsNavigationItem[];
75
+ }) => ChannelDetailsNavigationItem[];
76
+
77
+ export const getChannelDetailsNavigationItems: GetChannelDetailsNavigationItems = ({
78
+ defaultItems,
79
+ }) => defaultItems;
80
+
81
+ /**
82
+ * Builds the navigation rows rendered by `ChannelDetailsNavigationSection`. Returns the items as a
83
+ * plain array — the section component owns the built-in modal and supplies the default open-modal
84
+ * behavior for any row without a custom `onPress`. Customize the rows by passing `getNavigationItems`
85
+ * to `ChannelDetails` (see {@link GetChannelDetailsNavigationItems}).
86
+ *
87
+ * @experimental This hook is experimental and is subject to change.
88
+ */
89
+ export const useChannelDetailsNavigationItems = (): ChannelDetailsNavigationItem[] => {
90
+ const { t } = useTranslationContext();
91
+ const { getNavigationItems = getChannelDetailsNavigationItems } = useChannelDetailsContext();
92
+
93
+ const context = useMemo<ChannelDetailsNavigationItemsContext>(() => ({ t }), [t]);
94
+
95
+ const defaultItems = useMemo<ChannelDetailsNavigationItem[]>(
96
+ () =>
97
+ SECTIONS.map((section) => {
98
+ const { Icon, label } = SECTION_CONFIG[section];
99
+ return { Icon, label: t(label), section };
100
+ }),
101
+ [t],
102
+ );
103
+
104
+ return useMemo(
105
+ () => getNavigationItems({ context, defaultItems }),
106
+ [context, defaultItems, getNavigationItems],
107
+ );
108
+ };
@@ -0,0 +1,79 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import {
4
+ type Attachment,
5
+ isAudioAttachment,
6
+ isFileAttachment,
7
+ isScrapedContent,
8
+ type MessageResponse,
9
+ } from 'stream-chat';
10
+
11
+ import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
12
+ import { getDateString } from '../../../utils/i18n/getDateString';
13
+
14
+ /**
15
+ * A single file/audio attachment paired with the message it belongs to. The file attachment list
16
+ * renders one row per attachment, so a message with multiple file attachments yields multiple rows.
17
+ *
18
+ * @experimental This type is experimental and is subject to change.
19
+ */
20
+ export type FileAttachmentTile = { attachment: Attachment; message: MessageResponse };
21
+
22
+ export type FileAttachmentSection = { data: FileAttachmentTile[]; title: string };
23
+
24
+ /**
25
+ * Gathers the file/audio attachments from a message, excluding scraped/OG link-preview content.
26
+ */
27
+ const getFileAttachments = (message: MessageResponse): Attachment[] =>
28
+ (message.attachments ?? []).filter(
29
+ (attachment) =>
30
+ // We provide mime_type here to avoid attachments with mime_type being categorized as file
31
+ (isFileAttachment(attachment, attachment?.mime_type ? [attachment.mime_type] : []) ||
32
+ isAudioAttachment(attachment)) &&
33
+ !isScrapedContent(attachment),
34
+ );
35
+
36
+ /**
37
+ * Gathers and filters the file/audio attachments from a list of messages, then groups them into
38
+ * newest-first month sections for the file attachment list. Each section's `data` is a flat list
39
+ * of `{ attachment, message }` tiles; messages without renderable file attachments are skipped.
40
+ *
41
+ * The month label is produced through the shared `getDateString` + translation-key
42
+ * pipeline used by message timestamps (see `useUserActivityStatus`), so the format
43
+ * follows the configured locale and can be customized via the
44
+ * `timestamp/FileAttachmentListSection` translation key.
45
+ * @experimental This hook is experimental and is subject to change.
46
+ */
47
+ export const useFileAttachmentListSections = (
48
+ messages?: MessageResponse[],
49
+ ): FileAttachmentSection[] => {
50
+ const { t, tDateTimeParser } = useTranslationContext();
51
+
52
+ return useMemo<FileAttachmentSection[]>(() => {
53
+ if (!messages || messages.length === 0) {
54
+ return [];
55
+ }
56
+ const result: FileAttachmentSection[] = [];
57
+ for (const message of messages) {
58
+ const fileAttachments = getFileAttachments(message);
59
+ if (fileAttachments.length === 0) {
60
+ continue;
61
+ }
62
+ const formatted = getDateString({
63
+ date: message.created_at as string | Date | undefined,
64
+ t,
65
+ tDateTimeParser,
66
+ timestampTranslationKey: 'timestamp/FileAttachmentListSection',
67
+ });
68
+ const title = typeof formatted === 'string' ? formatted : String(formatted ?? '');
69
+ const tiles = fileAttachments.map((attachment) => ({ attachment, message }));
70
+ const lastSection = result[result.length - 1];
71
+ if (lastSection && lastSection.title === title) {
72
+ lastSection.data.push(...tiles);
73
+ } else {
74
+ result.push({ data: tiles, title });
75
+ }
76
+ }
77
+ return result;
78
+ }, [messages, t, tDateTimeParser]);
79
+ };
@@ -0,0 +1,51 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { type Attachment, isScrapedContent, type MessageResponse } from 'stream-chat';
4
+
5
+ import { FileTypes } from '../../../types/types';
6
+
7
+ /**
8
+ * A single image/video attachment paired with the message it belongs to. The media grid renders
9
+ * one tile per attachment, so a message with multiple media attachments yields multiple tiles.
10
+ *
11
+ * @experimental This type is experimental and is subject to change.
12
+ */
13
+ export type MediaTile = {
14
+ attachment: Attachment;
15
+ message: MessageResponse;
16
+ };
17
+
18
+ /**
19
+ * Flattens search-result messages into one tile per renderable image/video attachment, applying
20
+ * the same attachment rules the message list uses to decide what counts as gallery media.
21
+ */
22
+ const getMediaTiles = (messages: MessageResponse[] | undefined): MediaTile[] => {
23
+ if (!messages) {
24
+ return [];
25
+ }
26
+ const tiles: MediaTile[] = [];
27
+ for (const message of messages) {
28
+ if (!message.attachments) {
29
+ continue;
30
+ }
31
+ for (const attachment of message.attachments) {
32
+ if (
33
+ (attachment.type === FileTypes.Image || attachment.type === FileTypes.Video) &&
34
+ !isScrapedContent(attachment)
35
+ ) {
36
+ tiles.push({ attachment, message });
37
+ }
38
+ }
39
+ }
40
+ return tiles;
41
+ };
42
+
43
+ /**
44
+ * Gathers and filters the image/video attachments from a list of messages into a flat list of
45
+ * media tiles, ready to render in the media grid. Scraped/OG link-preview attachments and
46
+ * non-media attachments are excluded.
47
+ *
48
+ * @experimental This hook is experimental and is subject to change.
49
+ */
50
+ export const useMediaList = (messages?: MessageResponse[]): MediaTile[] =>
51
+ useMemo(() => getMediaTiles(messages), [messages]);