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

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 (388) 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/ImageGallery.js +21 -76
  54. package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
  55. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js +6 -10
  56. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
  57. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js +16 -14
  58. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -1
  59. package/lib/commonjs/components/ImageGallery/components/ImageGalleryA11yProbe.js +67 -0
  60. package/lib/commonjs/components/ImageGallery/components/ImageGalleryA11yProbe.js.map +1 -0
  61. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +23 -15
  62. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  63. package/lib/commonjs/components/ImageGallery/hooks/useAnimatedGalleryStyle.js +4 -3
  64. package/lib/commonjs/components/ImageGallery/hooks/useAnimatedGalleryStyle.js.map +1 -1
  65. package/lib/commonjs/components/ImageGallery/hooks/useCurrentImageHeight.js +53 -0
  66. package/lib/commonjs/components/ImageGallery/hooks/useCurrentImageHeight.js.map +1 -0
  67. package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js +25 -31
  68. package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -1
  69. package/lib/commonjs/components/UIComponents/EmptyList.js +78 -0
  70. package/lib/commonjs/components/UIComponents/EmptyList.js.map +1 -0
  71. package/lib/commonjs/components/UIComponents/index.js +11 -0
  72. package/lib/commonjs/components/UIComponents/index.js.map +1 -1
  73. package/lib/commonjs/components/ui/Avatar/AvatarGroup.js +3 -3
  74. package/lib/commonjs/components/ui/Avatar/constants.js +2 -2
  75. package/lib/commonjs/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js +64 -0
  76. package/lib/commonjs/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js.map +1 -0
  77. package/lib/commonjs/contexts/channelMediaListContext/ChannelMediaListContext.js +63 -0
  78. package/lib/commonjs/contexts/channelMediaListContext/ChannelMediaListContext.js.map +1 -0
  79. package/lib/commonjs/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js +73 -0
  80. package/lib/commonjs/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js.map +1 -0
  81. package/lib/commonjs/contexts/componentsContext/defaultComponents.js +8 -0
  82. package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
  83. package/lib/commonjs/contexts/index.js +33 -0
  84. package/lib/commonjs/contexts/index.js.map +1 -1
  85. package/lib/commonjs/contexts/themeContext/utils/theme.js +57 -2
  86. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  87. package/lib/commonjs/i18n/ar.json +11 -0
  88. package/lib/commonjs/i18n/en.json +11 -0
  89. package/lib/commonjs/i18n/es.json +11 -0
  90. package/lib/commonjs/i18n/fr.json +11 -0
  91. package/lib/commonjs/i18n/he.json +11 -0
  92. package/lib/commonjs/i18n/hi.json +11 -0
  93. package/lib/commonjs/i18n/it.json +11 -0
  94. package/lib/commonjs/i18n/ja.json +11 -0
  95. package/lib/commonjs/i18n/ko.json +11 -0
  96. package/lib/commonjs/i18n/nl.json +11 -0
  97. package/lib/commonjs/i18n/pt-br.json +11 -0
  98. package/lib/commonjs/i18n/ru.json +11 -0
  99. package/lib/commonjs/i18n/tr.json +11 -0
  100. package/lib/commonjs/icons/folder.js +37 -0
  101. package/lib/commonjs/icons/folder.js.map +1 -0
  102. package/lib/commonjs/icons/index.js +12 -0
  103. package/lib/commonjs/icons/index.js.map +1 -1
  104. package/lib/commonjs/state-store/image-gallery-state-store.js +12 -3
  105. package/lib/commonjs/state-store/image-gallery-state-store.js.map +1 -1
  106. package/lib/commonjs/version.json +1 -1
  107. package/lib/module/components/ChannelDetails/ChannelDetails.js +8 -3
  108. package/lib/module/components/ChannelDetails/ChannelDetails.js.map +1 -1
  109. package/lib/module/components/ChannelDetails/components/ChannelDetailsActionItem.js +2 -1
  110. package/lib/module/components/ChannelDetails/components/ChannelDetailsActionItem.js.map +1 -1
  111. package/lib/module/components/ChannelDetails/components/ChannelDetailsEditButton.js +57 -0
  112. package/lib/module/components/ChannelDetails/components/ChannelDetailsEditButton.js.map +1 -0
  113. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavHeader.js +3 -32
  114. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavHeader.js.map +1 -1
  115. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavigationSection.js +64 -25
  116. package/lib/module/components/ChannelDetails/components/ChannelDetailsNavigationSection.js.map +1 -1
  117. package/lib/module/components/ChannelDetails/components/ChannelDetailsProfile.js +3 -2
  118. package/lib/module/components/ChannelDetails/components/ChannelDetailsProfile.js.map +1 -1
  119. package/lib/module/components/ChannelDetails/components/ChannelEditImageSheet.js +2 -2
  120. package/lib/module/components/ChannelDetails/components/ChannelEditImageSheet.js.map +1 -1
  121. package/lib/module/components/ChannelDetails/components/index.js +22 -0
  122. package/lib/module/components/ChannelDetails/components/index.js.map +1 -1
  123. package/lib/module/components/ChannelDetails/components/members/ChannelMemberItem.js +2 -1
  124. package/lib/module/components/ChannelDetails/components/members/ChannelMemberItem.js.map +1 -1
  125. package/lib/module/components/ChannelDetails/components/modal/Modal.js +22 -23
  126. package/lib/module/components/ChannelDetails/components/modal/Modal.js.map +1 -1
  127. package/lib/module/components/ChannelDetails/components/modal/ModalHeader.js +6 -4
  128. package/lib/module/components/ChannelDetails/components/modal/ModalHeader.js.map +1 -1
  129. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentItem.js +65 -0
  130. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentItem.js.map +1 -0
  131. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentList.js +174 -0
  132. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentList.js.map +1 -0
  133. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.js +21 -0
  134. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.js.map +1 -0
  135. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.js +45 -0
  136. package/lib/module/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.js.map +1 -0
  137. package/lib/module/components/ChannelDetails/components/navigation-section/MediaItem.js +120 -0
  138. package/lib/module/components/ChannelDetails/components/navigation-section/MediaItem.js.map +1 -0
  139. package/lib/module/components/ChannelDetails/components/navigation-section/MediaList.js +206 -0
  140. package/lib/module/components/ChannelDetails/components/navigation-section/MediaList.js.map +1 -0
  141. package/lib/module/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.js +63 -0
  142. package/lib/module/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.js.map +1 -0
  143. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageItem.js +84 -0
  144. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageItem.js.map +1 -0
  145. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageList.js +177 -0
  146. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageList.js.map +1 -0
  147. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.js +21 -0
  148. package/lib/module/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.js.map +1 -0
  149. package/lib/module/components/ChannelDetails/components/navigation-section/index.js +114 -0
  150. package/lib/module/components/ChannelDetails/components/navigation-section/index.js.map +1 -0
  151. package/lib/module/components/ChannelDetails/hooks/index.js +33 -0
  152. package/lib/module/components/ChannelDetails/hooks/index.js.map +1 -1
  153. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.js +55 -0
  154. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.js.map +1 -0
  155. package/lib/module/components/ChannelDetails/hooks/useFileAttachmentListSections.js +52 -0
  156. package/lib/module/components/ChannelDetails/hooks/useFileAttachmentListSections.js.map +1 -0
  157. package/lib/module/components/ChannelDetails/hooks/useMediaList.js +30 -0
  158. package/lib/module/components/ChannelDetails/hooks/useMediaList.js.map +1 -0
  159. package/lib/module/components/ImageGallery/ImageGallery.js +21 -76
  160. package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
  161. package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js +6 -10
  162. package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
  163. package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js +16 -14
  164. package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -1
  165. package/lib/module/components/ImageGallery/components/ImageGalleryA11yProbe.js +67 -0
  166. package/lib/module/components/ImageGallery/components/ImageGalleryA11yProbe.js.map +1 -0
  167. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +23 -15
  168. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  169. package/lib/module/components/ImageGallery/hooks/useAnimatedGalleryStyle.js +4 -3
  170. package/lib/module/components/ImageGallery/hooks/useAnimatedGalleryStyle.js.map +1 -1
  171. package/lib/module/components/ImageGallery/hooks/useCurrentImageHeight.js +53 -0
  172. package/lib/module/components/ImageGallery/hooks/useCurrentImageHeight.js.map +1 -0
  173. package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js +25 -31
  174. package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -1
  175. package/lib/module/components/UIComponents/EmptyList.js +78 -0
  176. package/lib/module/components/UIComponents/EmptyList.js.map +1 -0
  177. package/lib/module/components/UIComponents/index.js +11 -0
  178. package/lib/module/components/UIComponents/index.js.map +1 -1
  179. package/lib/module/components/ui/Avatar/AvatarGroup.js +3 -3
  180. package/lib/module/components/ui/Avatar/constants.js +2 -2
  181. package/lib/module/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js +64 -0
  182. package/lib/module/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.js.map +1 -0
  183. package/lib/module/contexts/channelMediaListContext/ChannelMediaListContext.js +63 -0
  184. package/lib/module/contexts/channelMediaListContext/ChannelMediaListContext.js.map +1 -0
  185. package/lib/module/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js +73 -0
  186. package/lib/module/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.js.map +1 -0
  187. package/lib/module/contexts/componentsContext/defaultComponents.js +8 -0
  188. package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
  189. package/lib/module/contexts/index.js +33 -0
  190. package/lib/module/contexts/index.js.map +1 -1
  191. package/lib/module/contexts/themeContext/utils/theme.js +57 -2
  192. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  193. package/lib/module/i18n/ar.json +11 -0
  194. package/lib/module/i18n/en.json +11 -0
  195. package/lib/module/i18n/es.json +11 -0
  196. package/lib/module/i18n/fr.json +11 -0
  197. package/lib/module/i18n/he.json +11 -0
  198. package/lib/module/i18n/hi.json +11 -0
  199. package/lib/module/i18n/it.json +11 -0
  200. package/lib/module/i18n/ja.json +11 -0
  201. package/lib/module/i18n/ko.json +11 -0
  202. package/lib/module/i18n/nl.json +11 -0
  203. package/lib/module/i18n/pt-br.json +11 -0
  204. package/lib/module/i18n/ru.json +11 -0
  205. package/lib/module/i18n/tr.json +11 -0
  206. package/lib/module/icons/folder.js +37 -0
  207. package/lib/module/icons/folder.js.map +1 -0
  208. package/lib/module/icons/index.js +12 -0
  209. package/lib/module/icons/index.js.map +1 -1
  210. package/lib/module/state-store/image-gallery-state-store.js +12 -3
  211. package/lib/module/state-store/image-gallery-state-store.js.map +1 -1
  212. package/lib/module/version.json +1 -1
  213. package/lib/typescript/components/ChannelDetails/ChannelDetails.d.ts +11 -1
  214. package/lib/typescript/components/ChannelDetails/ChannelDetails.d.ts.map +1 -1
  215. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsActionItem.d.ts.map +1 -1
  216. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsEditButton.d.ts +6 -0
  217. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsEditButton.d.ts.map +1 -0
  218. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsNavHeader.d.ts +3 -1
  219. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsNavHeader.d.ts.map +1 -1
  220. package/lib/typescript/components/ChannelDetails/components/ChannelDetailsNavigationSection.d.ts.map +1 -1
  221. package/lib/typescript/components/ChannelDetails/components/index.d.ts +3 -0
  222. package/lib/typescript/components/ChannelDetails/components/index.d.ts.map +1 -1
  223. package/lib/typescript/components/ChannelDetails/components/members/ChannelMemberItem.d.ts.map +1 -1
  224. package/lib/typescript/components/ChannelDetails/components/modal/Modal.d.ts +2 -1
  225. package/lib/typescript/components/ChannelDetails/components/modal/Modal.d.ts.map +1 -1
  226. package/lib/typescript/components/ChannelDetails/components/modal/ModalHeader.d.ts +3 -1
  227. package/lib/typescript/components/ChannelDetails/components/modal/ModalHeader.d.ts.map +1 -1
  228. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentItem.d.ts +31 -0
  229. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentItem.d.ts.map +1 -0
  230. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentList.d.ts +17 -0
  231. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentList.d.ts.map +1 -0
  232. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.d.ts +9 -0
  233. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.d.ts.map +1 -0
  234. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.d.ts +13 -0
  235. package/lib/typescript/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.d.ts.map +1 -0
  236. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaItem.d.ts +35 -0
  237. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaItem.d.ts.map +1 -0
  238. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaList.d.ts +17 -0
  239. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaList.d.ts.map +1 -0
  240. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.d.ts +11 -0
  241. package/lib/typescript/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.d.ts.map +1 -0
  242. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageItem.d.ts +19 -0
  243. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageItem.d.ts.map +1 -0
  244. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageList.d.ts +19 -0
  245. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageList.d.ts.map +1 -0
  246. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.d.ts +9 -0
  247. package/lib/typescript/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.d.ts.map +1 -0
  248. package/lib/typescript/components/ChannelDetails/components/navigation-section/index.d.ts +11 -0
  249. package/lib/typescript/components/ChannelDetails/components/navigation-section/index.d.ts.map +1 -0
  250. package/lib/typescript/components/ChannelDetails/hooks/index.d.ts +3 -0
  251. package/lib/typescript/components/ChannelDetails/hooks/index.d.ts.map +1 -1
  252. package/lib/typescript/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.d.ts +56 -0
  253. package/lib/typescript/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.d.ts.map +1 -0
  254. package/lib/typescript/components/ChannelDetails/hooks/useFileAttachmentListSections.d.ts +28 -0
  255. package/lib/typescript/components/ChannelDetails/hooks/useFileAttachmentListSections.d.ts.map +1 -0
  256. package/lib/typescript/components/ChannelDetails/hooks/useMediaList.d.ts +20 -0
  257. package/lib/typescript/components/ChannelDetails/hooks/useMediaList.d.ts.map +1 -0
  258. package/lib/typescript/components/ImageGallery/ImageGallery.d.ts.map +1 -1
  259. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryImage.d.ts.map +1 -1
  260. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts +1 -4
  261. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts.map +1 -1
  262. package/lib/typescript/components/ImageGallery/components/ImageGalleryA11yProbe.d.ts +20 -0
  263. package/lib/typescript/components/ImageGallery/components/ImageGalleryA11yProbe.d.ts.map +1 -0
  264. package/lib/typescript/components/ImageGallery/components/ImageGalleryHeader.d.ts.map +1 -1
  265. package/lib/typescript/components/ImageGallery/hooks/useAnimatedGalleryStyle.d.ts +2 -3
  266. package/lib/typescript/components/ImageGallery/hooks/useAnimatedGalleryStyle.d.ts.map +1 -1
  267. package/lib/typescript/components/ImageGallery/hooks/useCurrentImageHeight.d.ts +24 -0
  268. package/lib/typescript/components/ImageGallery/hooks/useCurrentImageHeight.d.ts.map +1 -0
  269. package/lib/typescript/components/ImageGallery/hooks/useImageGalleryGestures.d.ts +1 -1
  270. package/lib/typescript/components/ImageGallery/hooks/useImageGalleryGestures.d.ts.map +1 -1
  271. package/lib/typescript/components/UIComponents/EmptyList.d.ts +24 -0
  272. package/lib/typescript/components/UIComponents/EmptyList.d.ts.map +1 -0
  273. package/lib/typescript/components/UIComponents/index.d.ts +1 -0
  274. package/lib/typescript/components/UIComponents/index.d.ts.map +1 -1
  275. package/lib/typescript/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.d.ts +21 -0
  276. package/lib/typescript/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.d.ts.map +1 -0
  277. package/lib/typescript/contexts/channelMediaListContext/ChannelMediaListContext.d.ts +21 -0
  278. package/lib/typescript/contexts/channelMediaListContext/ChannelMediaListContext.d.ts.map +1 -0
  279. package/lib/typescript/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.d.ts +21 -0
  280. package/lib/typescript/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.d.ts.map +1 -0
  281. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +18 -2
  282. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
  283. package/lib/typescript/contexts/index.d.ts +3 -0
  284. package/lib/typescript/contexts/index.d.ts.map +1 -1
  285. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts +56 -1
  286. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts.map +1 -1
  287. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +56 -1
  288. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  289. package/lib/typescript/i18n/ar.json +11 -0
  290. package/lib/typescript/i18n/en.json +11 -0
  291. package/lib/typescript/i18n/es.json +11 -0
  292. package/lib/typescript/i18n/fr.json +11 -0
  293. package/lib/typescript/i18n/he.json +11 -0
  294. package/lib/typescript/i18n/hi.json +11 -0
  295. package/lib/typescript/i18n/it.json +11 -0
  296. package/lib/typescript/i18n/ja.json +11 -0
  297. package/lib/typescript/i18n/ko.json +11 -0
  298. package/lib/typescript/i18n/nl.json +11 -0
  299. package/lib/typescript/i18n/pt-br.json +11 -0
  300. package/lib/typescript/i18n/ru.json +11 -0
  301. package/lib/typescript/i18n/tr.json +11 -0
  302. package/lib/typescript/icons/folder.d.ts +4 -0
  303. package/lib/typescript/icons/folder.d.ts.map +1 -0
  304. package/lib/typescript/icons/index.d.ts +1 -0
  305. package/lib/typescript/icons/index.d.ts.map +1 -1
  306. package/lib/typescript/state-store/image-gallery-state-store.d.ts +8 -0
  307. package/lib/typescript/state-store/image-gallery-state-store.d.ts.map +1 -1
  308. package/lib/typescript/utils/i18n/Streami18n.d.ts +11 -0
  309. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  310. package/package.json +1 -1
  311. package/src/components/ChannelDetails/ChannelDetails.tsx +17 -2
  312. package/src/components/ChannelDetails/__tests__/ChannelDetails.test.tsx +29 -0
  313. package/src/components/ChannelDetails/__tests__/ChannelDetailsEditButton.test.tsx +127 -0
  314. package/src/components/ChannelDetails/__tests__/ChannelDetailsNavHeader.test.tsx +21 -56
  315. package/src/components/ChannelDetails/__tests__/ChannelDetailsNavigationSection.test.tsx +225 -6
  316. package/src/components/ChannelDetails/__tests__/useFileAttachmentListSections.test.tsx +159 -0
  317. package/src/components/ChannelDetails/__tests__/useMediaList.test.tsx +53 -0
  318. package/src/components/ChannelDetails/components/ChannelDetailsActionItem.tsx +6 -1
  319. package/src/components/ChannelDetails/components/ChannelDetailsEditButton.tsx +50 -0
  320. package/src/components/ChannelDetails/components/ChannelDetailsNavHeader.tsx +6 -33
  321. package/src/components/ChannelDetails/components/ChannelDetailsNavigationSection.tsx +80 -32
  322. package/src/components/ChannelDetails/components/ChannelDetailsProfile.tsx +2 -1
  323. package/src/components/ChannelDetails/components/ChannelEditImageSheet.tsx +2 -2
  324. package/src/components/ChannelDetails/components/__tests__/navigation-section/FileAttachmentItem.test.tsx +80 -0
  325. package/src/components/ChannelDetails/components/__tests__/navigation-section/FileAttachmentList.test.tsx +334 -0
  326. package/src/components/ChannelDetails/components/__tests__/navigation-section/FileAttachmentListSectionHeader.test.tsx +19 -0
  327. package/src/components/ChannelDetails/components/__tests__/navigation-section/MediaItem.test.tsx +97 -0
  328. package/src/components/ChannelDetails/components/__tests__/navigation-section/MediaList.test.tsx +351 -0
  329. package/src/components/ChannelDetails/components/__tests__/navigation-section/PinnedMessageItem.test.tsx +112 -0
  330. package/src/components/ChannelDetails/components/__tests__/navigation-section/PinnedMessageList.test.tsx +324 -0
  331. package/src/components/ChannelDetails/components/index.ts +3 -0
  332. package/src/components/ChannelDetails/components/members/ChannelMemberItem.tsx +6 -1
  333. package/src/components/ChannelDetails/components/modal/Modal.tsx +37 -24
  334. package/src/components/ChannelDetails/components/modal/ModalHeader.tsx +11 -4
  335. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentItem.tsx +92 -0
  336. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentList.tsx +204 -0
  337. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentListLoadingSkeleton.tsx +23 -0
  338. package/src/components/ChannelDetails/components/navigation-section/FileAttachmentListSectionHeader.tsx +56 -0
  339. package/src/components/ChannelDetails/components/navigation-section/MediaItem.tsx +160 -0
  340. package/src/components/ChannelDetails/components/navigation-section/MediaList.tsx +244 -0
  341. package/src/components/ChannelDetails/components/navigation-section/MediaListLoadingSkeleton.tsx +66 -0
  342. package/src/components/ChannelDetails/components/navigation-section/PinnedMessageItem.tsx +94 -0
  343. package/src/components/ChannelDetails/components/navigation-section/PinnedMessageList.tsx +198 -0
  344. package/src/components/ChannelDetails/components/navigation-section/PinnedMessageListLoadingSkeleton.tsx +23 -0
  345. package/src/components/ChannelDetails/components/navigation-section/index.ts +10 -0
  346. package/src/components/ChannelDetails/hooks/index.ts +3 -0
  347. package/src/components/ChannelDetails/hooks/useChannelDetailsNavigationItems.ts +108 -0
  348. package/src/components/ChannelDetails/hooks/useFileAttachmentListSections.ts +79 -0
  349. package/src/components/ChannelDetails/hooks/useMediaList.ts +51 -0
  350. package/src/components/ImageGallery/ImageGallery.tsx +41 -120
  351. package/src/components/ImageGallery/__tests__/ImageGallery.test.tsx +4 -1
  352. package/src/components/ImageGallery/__tests__/ImageGalleryAdjustable.test.tsx +5 -4
  353. package/src/components/ImageGallery/components/AnimatedGalleryImage.tsx +9 -11
  354. package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx +28 -15
  355. package/src/components/ImageGallery/components/ImageGalleryA11yProbe.tsx +82 -0
  356. package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +21 -18
  357. package/src/components/ImageGallery/hooks/useAnimatedGalleryStyle.tsx +5 -5
  358. package/src/components/ImageGallery/hooks/useCurrentImageHeight.ts +86 -0
  359. package/src/components/ImageGallery/hooks/useImageGalleryGestures.tsx +42 -51
  360. package/src/components/UIComponents/EmptyList.tsx +80 -0
  361. package/src/components/UIComponents/__tests__/EmptyList.test.tsx +90 -0
  362. package/src/components/UIComponents/index.ts +1 -0
  363. package/src/components/ui/Avatar/AvatarGroup.tsx +3 -3
  364. package/src/components/ui/Avatar/constants.ts +2 -2
  365. package/src/contexts/channelFileAttachmentListContext/ChannelFileAttachmentListContext.tsx +67 -0
  366. package/src/contexts/channelMediaListContext/ChannelMediaListContext.tsx +68 -0
  367. package/src/contexts/channelPinnedMessageListContext/ChannelPinnedMessageListContext.tsx +72 -0
  368. package/src/contexts/componentsContext/defaultComponents.ts +16 -1
  369. package/src/contexts/index.ts +3 -0
  370. package/src/contexts/themeContext/utils/theme.ts +112 -2
  371. package/src/i18n/ar.json +11 -0
  372. package/src/i18n/en.json +11 -0
  373. package/src/i18n/es.json +11 -0
  374. package/src/i18n/fr.json +11 -0
  375. package/src/i18n/he.json +11 -0
  376. package/src/i18n/hi.json +11 -0
  377. package/src/i18n/it.json +11 -0
  378. package/src/i18n/ja.json +11 -0
  379. package/src/i18n/ko.json +11 -0
  380. package/src/i18n/nl.json +11 -0
  381. package/src/i18n/pt-br.json +11 -0
  382. package/src/i18n/ru.json +11 -0
  383. package/src/i18n/tr.json +11 -0
  384. package/src/icons/folder.tsx +28 -0
  385. package/src/icons/index.ts +1 -0
  386. package/src/state-store/__tests__/image-gallery-state-store.test.ts +81 -0
  387. package/src/state-store/image-gallery-state-store.ts +27 -1
  388. package/src/version.json +1 -1
@@ -1,12 +1,5 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
- import {
3
- AccessibilityInfo,
4
- Image,
5
- ImageStyle,
6
- Platform,
7
- StyleSheet,
8
- ViewStyle,
9
- } from 'react-native';
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { AccessibilityInfo, ImageStyle, Platform, StyleSheet, ViewStyle } from 'react-native';
10
3
  import { Gesture, GestureDetector } from 'react-native-gesture-handler';
11
4
 
12
5
  import Animated, {
@@ -20,15 +13,16 @@ import Animated, {
20
13
 
21
14
  import { AnimatedGalleryImage } from './components/AnimatedGalleryImage';
22
15
  import { AnimatedGalleryVideo } from './components/AnimatedGalleryVideo';
16
+ import { ImageGalleryA11yProbe } from './components/ImageGalleryA11yProbe';
23
17
  import type {
24
18
  ImageGalleryFooterProps,
25
19
  ImageGalleryGridProps,
26
20
  ImageGalleryHeaderProps,
27
21
  } from './components/types';
28
22
 
23
+ import { useCurrentImageHeight } from './hooks/useCurrentImageHeight';
29
24
  import { useImageGalleryGestures } from './hooks/useImageGalleryGestures';
30
25
 
31
- import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
32
26
  import { useAccessibilityContext } from '../../contexts/accessibilityContext/AccessibilityContext';
33
27
  import { useComponentsContext } from '../../contexts/componentsContext/ComponentsContext';
34
28
  import {
@@ -73,7 +67,6 @@ export enum IsSwiping {
73
67
 
74
68
  const imageGallerySelector = (state: ImageGalleryState) => ({
75
69
  assets: state.assets,
76
- currentIndex: state.currentIndex,
77
70
  });
78
71
 
79
72
  type ImageGalleryWithContextProps = Pick<
@@ -102,12 +95,7 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
102
95
  },
103
96
  } = useTheme();
104
97
  const { imageGalleryStateStore } = useImageGalleryContext();
105
- const { assets, currentIndex } = useStateStore(
106
- imageGalleryStateStore.state,
107
- imageGallerySelector,
108
- );
109
- const { videoPlayerPool } = imageGalleryStateStore;
110
-
98
+ const { assets } = useStateStore(imageGalleryStateStore.state, imageGallerySelector);
111
99
  const { vh, vw } = useViewport();
112
100
 
113
101
  const fullWindowHeight = vh(100);
@@ -139,9 +127,17 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
139
127
  }, [showScreen]);
140
128
 
141
129
  /**
142
- * Image height from URL or default to full screen height
130
+ * Image height for the currently selected asset. SharedValue so worklet
131
+ * consumers (gesture math, header/footer opacity) read it directly on the
132
+ * UI thread so updating it doesn't trigger a parent rerender. The hook
133
+ * owns the value and updates it via a store subscription.
143
134
  */
144
- const [currentImageHeight, setCurrentImageHeight] = useState<number>(fullWindowHeight);
135
+ const currentImageHeight = useCurrentImageHeight({
136
+ assets,
137
+ fullWindowHeight,
138
+ fullWindowWidth,
139
+ imageGalleryStateStore,
140
+ });
145
141
 
146
142
  /**
147
143
  * Header visible value for animating in out
@@ -155,53 +151,20 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
155
151
  const translateY = useSharedValue(0);
156
152
  const offsetScale = useSharedValue(1);
157
153
  const scale = useSharedValue(1);
158
- const translationX = useSharedValue(-(fullWindowWidth + MARGIN) * currentIndex);
154
+ const translationX = useSharedValue(
155
+ -(fullWindowWidth + MARGIN) * imageGalleryStateStore.state.getLatestValue().currentIndex,
156
+ );
157
+
158
+ const currentIndexShared = imageGalleryStateStore.currentIndexShared;
159
159
 
160
160
  useAnimatedReaction(
161
- () => currentIndex,
161
+ () => currentIndexShared.value,
162
162
  (index) => {
163
163
  translationX.value = -(fullWindowWidth + MARGIN) * index;
164
164
  },
165
- [currentIndex, fullWindowWidth],
165
+ [fullWindowWidth],
166
166
  );
167
167
 
168
- /**
169
- * Image heights are not provided and therefore need to be calculated.
170
- * We start by allowing the image to be the full height then reduce it
171
- * to the proper scaled height based on the width being restricted to the
172
- * screen width when the dimensions are received.
173
- */
174
- useEffect(() => {
175
- let currentImageHeight = fullWindowHeight;
176
- const photo = assets[currentIndex];
177
- const height = photo?.original_height;
178
- const width = photo?.original_width;
179
-
180
- if (height && width) {
181
- const imageHeight = Math.floor(height * (fullWindowWidth / width));
182
- currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight;
183
- } else if (photo?.uri) {
184
- if (photo.type === FileTypes.Image) {
185
- Image.getSize(photo.uri, (width, height) => {
186
- const imageHeight = Math.floor(height * (fullWindowWidth / width));
187
- currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight;
188
- });
189
- }
190
- }
191
-
192
- setCurrentImageHeight(currentImageHeight);
193
- // eslint-disable-next-line react-hooks/exhaustive-deps
194
- }, [currentIndex]);
195
-
196
- // If you change the current index, pause the active video player.
197
- useEffect(() => {
198
- const activePlayer = videoPlayerPool.getActivePlayer();
199
-
200
- if (activePlayer) {
201
- activePlayer.pause();
202
- }
203
- }, [currentIndex, videoPlayerPool]);
204
-
205
168
  const { doubleTap, pan, pinch, singleTap } = useImageGalleryGestures({
206
169
  currentImageHeight,
207
170
  halfScreenHeight,
@@ -219,20 +182,21 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
219
182
 
220
183
  /**
221
184
  * If the header is visible we scale down the opacity of it as the
222
- * image is swiped downward
185
+ * image is swiped downward. Reads currentImageHeight from a SharedValue so
186
+ * the worklet doesn't need to be re-registered when the image dimensions
187
+ * change between slides.
223
188
  */
224
- const headerFooterOpacity = useDerivedValue(
225
- () =>
226
- currentImageHeight * scale.value < fullWindowHeight && translateY.value > 0
227
- ? 1 - translateY.value / quarterScreenHeight
228
- : currentImageHeight * scale.value > fullWindowHeight &&
229
- translateY.value > (currentImageHeight / 2) * scale.value - halfScreenHeight
230
- ? 1 -
231
- (translateY.value - ((currentImageHeight / 2) * scale.value - halfScreenHeight)) /
232
- quarterScreenHeight
233
- : 1,
234
- [currentImageHeight],
235
- );
189
+ const headerFooterOpacity = useDerivedValue(() => {
190
+ const imageHeight = currentImageHeight.value;
191
+ return imageHeight * scale.value < fullWindowHeight && translateY.value > 0
192
+ ? 1 - translateY.value / quarterScreenHeight
193
+ : imageHeight * scale.value > fullWindowHeight &&
194
+ translateY.value > (imageHeight / 2) * scale.value - halfScreenHeight
195
+ ? 1 -
196
+ (translateY.value - ((imageHeight / 2) * scale.value - halfScreenHeight)) /
197
+ quarterScreenHeight
198
+ : 1;
199
+ }, []);
236
200
 
237
201
  /**
238
202
  * This transition and scaleX reverse lets use scroll right
@@ -290,45 +254,6 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
290
254
  };
291
255
 
292
256
  const { enabled: isAccessibilityEnabled } = useAccessibilityContext();
293
- const assetsCount = assets.length;
294
- const isAdjustable = isAccessibilityEnabled;
295
- const accessibilityValueParams = useMemo(
296
- () => ({ count: assetsCount, position: currentIndex + 1 }),
297
- [currentIndex, assetsCount],
298
- );
299
- const accessibilityValueText = useA11yLabel(
300
- 'a11y/{{position}} of {{count}}',
301
- accessibilityValueParams,
302
- );
303
- const accessibilityValue = useMemo(
304
- () => (accessibilityValueText ? { text: accessibilityValueText } : undefined),
305
- [accessibilityValueText],
306
- );
307
- const adjustableActions = useMemo(
308
- () =>
309
- isAdjustable ? [{ name: 'increment' as const }, { name: 'decrement' as const }] : undefined,
310
- [isAdjustable],
311
- );
312
-
313
- const onAccessibilityAction = useCallback(
314
- (event: { nativeEvent: { actionName: string } }) => {
315
- if (!isAccessibilityEnabled) return;
316
- const latest = imageGalleryStateStore.state.getLatestValue();
317
- const latestCount = latest.assets.length;
318
- const latestIndex = latest.currentIndex;
319
- if (latestCount <= 1) return;
320
- if (event.nativeEvent.actionName === 'increment') {
321
- if (latestIndex < latestCount - 1) {
322
- imageGalleryStateStore.currentIndex = latestIndex + 1;
323
- }
324
- } else if (event.nativeEvent.actionName === 'decrement') {
325
- if (latestIndex > 0) {
326
- imageGalleryStateStore.currentIndex = latestIndex - 1;
327
- }
328
- }
329
- },
330
- [imageGalleryStateStore, isAccessibilityEnabled],
331
- );
332
257
 
333
258
  useEffect(() => {
334
259
  return () => {
@@ -356,15 +281,11 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
356
281
  pointerEvents={'auto'}
357
282
  style={[StyleSheet.absoluteFill, showScreenStyle]}
358
283
  >
359
- <Animated.View
360
- accessible
361
- accessibilityActions={adjustableActions}
362
- accessibilityLabel='Image Gallery'
363
- accessibilityRole={isAdjustable ? 'adjustable' : undefined}
364
- accessibilityValue={isAdjustable ? accessibilityValue : undefined}
365
- onAccessibilityAction={isAdjustable ? onAccessibilityAction : undefined}
366
- style={[StyleSheet.absoluteFill, containerBackground]}
367
- />
284
+ {isAccessibilityEnabled ? (
285
+ <ImageGalleryA11yProbe containerBackground={containerBackground} />
286
+ ) : (
287
+ <Animated.View style={[StyleSheet.absoluteFill, containerBackground]} />
288
+ )}
368
289
  <GestureDetector gesture={Gesture.Simultaneous(singleTap, doubleTap, pinch, pan)}>
369
290
  <Animated.View style={StyleSheet.absoluteFill}>
370
291
  <Animated.View
@@ -89,10 +89,13 @@ describe('ImageGallery', () => {
89
89
  render(
90
90
  <ImageGalleryComponent
91
91
  message={generateMessage({
92
+ // Video is placed at index 1 so it sits within the video-slide
93
+ // window (`shouldRender < 2`) — at index 2 it would render as a
94
+ // spacer instead of <AnimatedGalleryVideo>.
92
95
  attachments: [
93
96
  generateImageAttachment(),
94
- generateGiphyAttachment(),
95
97
  generateVideoAttachment({ type: 'video' }),
98
+ generateGiphyAttachment(),
96
99
  ],
97
100
  })}
98
101
  />,
@@ -95,13 +95,14 @@ describe('ImageGallery adjustable cycling', () => {
95
95
  });
96
96
  });
97
97
 
98
- it('does not apply the adjustable role when accessibility is disabled', async () => {
98
+ it('does not mount the a11y probe when accessibility is disabled', async () => {
99
99
  renderWithAssets(3, false);
100
100
 
101
+ // The probe is the sole element with this label; the parent ImageGallery
102
+ // renders only the visual background View when a11y is off, with no
103
+ // accessibility attributes to expose.
101
104
  await waitFor(() => {
102
- const root = findGalleryRoot();
103
- expect(root.props.accessibilityRole).toBeUndefined();
104
- expect(root.props.accessibilityActions).toBeUndefined();
105
+ expect(screen.queryByLabelText('Image Gallery', { includeHiddenElements: true })).toBeNull();
105
106
  });
106
107
  });
107
108
 
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
  import type { ImageStyle, StyleProp } from 'react-native';
4
4
  import Animated, { SharedValue } from 'react-native-reanimated';
@@ -30,10 +30,6 @@ type Props = {
30
30
  style?: StyleProp<ImageStyle>;
31
31
  };
32
32
 
33
- const imageGallerySelector = (state: ImageGalleryState) => ({
34
- currentIndex: state.currentIndex,
35
- });
36
-
37
33
  export const AnimatedGalleryImage = React.memo(
38
34
  (props: Props) => {
39
35
  const {
@@ -50,7 +46,13 @@ export const AnimatedGalleryImage = React.memo(
50
46
  } = props;
51
47
  const { imageGalleryStateStore } = useImageGalleryContext();
52
48
  const { resizableCDNHosts } = useChatConfigContext();
53
- const { currentIndex } = useStateStore(imageGalleryStateStore.state, imageGallerySelector);
49
+ const shouldRenderSelector = useCallback(
50
+ (state: ImageGalleryState) => ({
51
+ shouldRender: Math.abs(state.currentIndex - index) < 4,
52
+ }),
53
+ [index],
54
+ );
55
+ const { shouldRender } = useStateStore(imageGalleryStateStore.state, shouldRenderSelector);
54
56
 
55
57
  const uri = useMemo(() => {
56
58
  return getResizedImageUrl({
@@ -62,17 +64,13 @@ export const AnimatedGalleryImage = React.memo(
62
64
  }, [photo.uri, resizableCDNHosts, screenHeight, screenWidth]);
63
65
 
64
66
  const isSvg = useIsSvg(uri);
65
- const selected = currentIndex === index;
66
- const previous = currentIndex > index;
67
- const shouldRender = Math.abs(currentIndex - index) < 4;
68
67
 
69
68
  const animatedStyles = useAnimatedGalleryStyle({
69
+ currentIndexShared: imageGalleryStateStore.currentIndexShared,
70
70
  index,
71
71
  offsetScale,
72
- previous,
73
72
  scale,
74
73
  screenHeight,
75
- selected,
76
74
  translateX,
77
75
  translateY,
78
76
  });
@@ -1,4 +1,4 @@
1
- import React, { RefObject, useEffect, useRef, useState } from 'react';
1
+ import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { StyleSheet, View, ViewStyle } from 'react-native';
3
3
  import type { StyleProp } from 'react-native';
4
4
  import Animated, { SharedValue } from 'react-native-reanimated';
@@ -49,19 +49,14 @@ const styles = StyleSheet.create({
49
49
  },
50
50
  });
51
51
 
52
- const imageGallerySelector = (state: ImageGalleryState) => ({
53
- currentIndex: state.currentIndex,
54
- });
55
-
56
52
  const videoPlayerSelector = (state: VideoPlayerState) => ({
57
53
  currentPlaybackRate: state.currentPlaybackRate,
58
54
  isPlaying: state.isPlaying,
59
55
  });
60
56
 
61
- export const AnimatedGalleryVideo = (props: AnimatedGalleryVideoType) => {
57
+ const AnimatedGalleryVideoComponent = (props: AnimatedGalleryVideoType) => {
62
58
  const [opacity, setOpacity] = useState<number>(1);
63
59
  const { imageGalleryStateStore } = useImageGalleryContext();
64
- const { currentIndex } = useStateStore(imageGalleryStateStore.state, imageGallerySelector);
65
60
 
66
61
  const {
67
62
  attachmentId,
@@ -75,6 +70,14 @@ export const AnimatedGalleryVideo = (props: AnimatedGalleryVideoType) => {
75
70
  translateY,
76
71
  } = props;
77
72
 
73
+ const shouldRenderSelector = useCallback(
74
+ (state: ImageGalleryState) => ({
75
+ shouldRender: Math.abs(state.currentIndex - index) < 2,
76
+ }),
77
+ [index],
78
+ );
79
+ const { shouldRender } = useStateStore(imageGalleryStateStore.state, shouldRenderSelector);
80
+
78
81
  const videoRef = useRef<VideoType>(null);
79
82
 
80
83
  const videoPlayer = useImageGalleryVideoPlayer({
@@ -82,14 +85,15 @@ export const AnimatedGalleryVideo = (props: AnimatedGalleryVideoType) => {
82
85
  });
83
86
 
84
87
  useEffect(() => {
85
- if (videoRef.current) {
88
+ if (videoRef.current && shouldRender) {
86
89
  videoPlayer.initPlayer({ playerRef: videoRef.current });
87
90
  }
88
91
 
89
92
  return () => {
90
93
  videoPlayer.playerRef = null;
94
+ videoPlayer.onRemove();
91
95
  };
92
- }, [videoPlayer]);
96
+ }, [videoPlayer, shouldRender]);
93
97
 
94
98
  const { isPlaying, currentPlaybackRate } = useStateStore(videoPlayer.state, videoPlayerSelector);
95
99
 
@@ -147,17 +151,12 @@ export const AnimatedGalleryVideo = (props: AnimatedGalleryVideoType) => {
147
151
  }
148
152
  };
149
153
 
150
- const selected = currentIndex === index;
151
- const previous = currentIndex > index;
152
- const shouldRender = Math.abs(currentIndex - index) < 4;
153
-
154
154
  const animatedStyles = useAnimatedGalleryStyle({
155
+ currentIndexShared: imageGalleryStateStore.currentIndexShared,
155
156
  index,
156
157
  offsetScale,
157
- previous,
158
158
  scale,
159
159
  screenHeight,
160
- selected,
161
160
  translateX,
162
161
  translateY,
163
162
  });
@@ -216,4 +215,18 @@ export const AnimatedGalleryVideo = (props: AnimatedGalleryVideoType) => {
216
215
  );
217
216
  };
218
217
 
218
+ export const AnimatedGalleryVideo = React.memo(
219
+ AnimatedGalleryVideoComponent,
220
+ (prevProps, nextProps) => {
221
+ if (
222
+ prevProps.photo.uri === nextProps.photo.uri &&
223
+ prevProps.index === nextProps.index &&
224
+ prevProps.screenHeight === nextProps.screenHeight
225
+ ) {
226
+ return true;
227
+ }
228
+ return false;
229
+ },
230
+ );
231
+
219
232
  AnimatedGalleryVideo.displayName = 'AnimatedGalleryVideo';
@@ -0,0 +1,82 @@
1
+ import React, { useCallback, useMemo } from 'react';
2
+ import { StyleSheet, ViewStyle } from 'react-native';
3
+ import Animated, { AnimatedStyle } from 'react-native-reanimated';
4
+
5
+ import { useA11yLabel } from '../../../a11y/hooks/useA11yLabel';
6
+ import { useImageGalleryContext } from '../../../contexts/imageGalleryContext/ImageGalleryContext';
7
+ import { useStateStore } from '../../../hooks';
8
+ import { ImageGalleryState } from '../../../state-store/image-gallery-state-store';
9
+
10
+ const a11ySelector = (state: ImageGalleryState) => ({
11
+ assets: state.assets,
12
+ currentIndex: state.currentIndex,
13
+ });
14
+
15
+ type Props = {
16
+ containerBackground: AnimatedStyle<ViewStyle>;
17
+ };
18
+
19
+ /**
20
+ * Accessibility-enabled variant of the gallery's background fade view. Wires
21
+ * the "X of N" announcement and the VoiceOver/TalkBack increment/decrement
22
+ * actions. Subscribes locally to currentIndex + assets so the parent
23
+ * ImageGallery doesn't need that subscription itself — only this small sibling
24
+ * re-renders to refresh the accessibilityValue text on each swipe.
25
+ *
26
+ * Caller is responsible for gating this on whether accessibility is enabled.
27
+ * When disabled, the parent renders a plain Animated.View with the same
28
+ * background style and no a11y attributes.
29
+ */
30
+ export const ImageGalleryA11yProbe = ({ containerBackground }: Props) => {
31
+ const { imageGalleryStateStore } = useImageGalleryContext();
32
+ const { assets, currentIndex } = useStateStore(imageGalleryStateStore.state, a11ySelector);
33
+ const assetsCount = assets.length;
34
+
35
+ const accessibilityValueParams = useMemo(
36
+ () => ({ count: assetsCount, position: currentIndex + 1 }),
37
+ [currentIndex, assetsCount],
38
+ );
39
+ const accessibilityValueText = useA11yLabel(
40
+ 'a11y/{{position}} of {{count}}',
41
+ accessibilityValueParams,
42
+ );
43
+ const accessibilityValue = useMemo(
44
+ () => (accessibilityValueText ? { text: accessibilityValueText } : undefined),
45
+ [accessibilityValueText],
46
+ );
47
+ const adjustableActions = useMemo(
48
+ () => [{ name: 'increment' as const }, { name: 'decrement' as const }],
49
+ [],
50
+ );
51
+
52
+ const onAccessibilityAction = useCallback(
53
+ (event: { nativeEvent: { actionName: string } }) => {
54
+ const latest = imageGalleryStateStore.state.getLatestValue();
55
+ const latestCount = latest.assets.length;
56
+ const latestIndex = latest.currentIndex;
57
+ if (latestCount <= 1) return;
58
+ if (event.nativeEvent.actionName === 'increment') {
59
+ if (latestIndex < latestCount - 1) {
60
+ imageGalleryStateStore.currentIndex = latestIndex + 1;
61
+ }
62
+ } else if (event.nativeEvent.actionName === 'decrement') {
63
+ if (latestIndex > 0) {
64
+ imageGalleryStateStore.currentIndex = latestIndex - 1;
65
+ }
66
+ }
67
+ },
68
+ [imageGalleryStateStore],
69
+ );
70
+
71
+ return (
72
+ <Animated.View
73
+ accessible
74
+ accessibilityActions={adjustableActions}
75
+ accessibilityLabel='Image Gallery'
76
+ accessibilityRole='adjustable'
77
+ accessibilityValue={accessibilityValue}
78
+ onAccessibilityAction={onAccessibilityAction}
79
+ style={[StyleSheet.absoluteFill, containerBackground]}
80
+ />
81
+ );
82
+ };
@@ -1,8 +1,9 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useContext, useEffect, useMemo, useState } from 'react';
2
2
 
3
3
  import { StyleSheet, Text, View, ViewStyle } from 'react-native';
4
4
 
5
5
  import Animated, { Extrapolation, interpolate, useAnimatedStyle } from 'react-native-reanimated';
6
+ import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
6
7
 
7
8
  import type { ImageGalleryHeaderProps } from './types';
8
9
 
@@ -17,11 +18,6 @@ import { ImageGalleryState } from '../../../state-store/image-gallery-state-stor
17
18
  import { primitives } from '../../../theme';
18
19
  import { getDateString } from '../../../utils/i18n/getDateString';
19
20
  import { Button } from '../../ui/Button/Button';
20
- import { SafeAreaView } from '../../UIComponents/SafeAreaViewWrapper';
21
-
22
- const ReanimatedSafeAreaView = Animated.createAnimatedComponent
23
- ? Animated.createAnimatedComponent(SafeAreaView)
24
- : SafeAreaView;
25
21
 
26
22
  const imageGallerySelector = (state: ImageGalleryState) => ({
27
23
  asset: state.assets[state.currentIndex],
@@ -35,6 +31,7 @@ export const ImageGalleryHeader = (props: ImageGalleryHeaderProps) => {
35
31
  const { imageGalleryStateStore } = useImageGalleryContext();
36
32
  const { asset } = useStateStore(imageGalleryStateStore.state, imageGallerySelector);
37
33
  const { setOverlay } = useOverlayContext();
34
+ const topInset = useContext(SafeAreaInsetsContext)?.top ?? 0;
38
35
 
39
36
  const date = useMemo(
40
37
  () =>
@@ -71,17 +68,19 @@ export const ImageGalleryHeader = (props: ImageGalleryHeaderProps) => {
71
68
  onLayout={(event) => setHeight(event.nativeEvent.layout.height)}
72
69
  pointerEvents={'box-none'}
73
70
  >
74
- <ReanimatedSafeAreaView edges={['top']} style={[styles.container, headerStyle]}>
71
+ <Animated.View style={[styles.container, { paddingTop: topInset }, headerStyle]}>
75
72
  <View style={styles.innerContainer}>
76
- <Button
77
- accessibilityLabelKey='a11y/Hide Overlay'
78
- variant='secondary'
79
- type='ghost'
80
- size='md'
81
- onPress={hideOverlay}
82
- LeadingIcon={ChevronLeft}
83
- iconOnly
84
- />
73
+ <View style={styles.leftContainer}>
74
+ <Button
75
+ accessibilityLabelKey='a11y/Hide Overlay'
76
+ variant='secondary'
77
+ type='ghost'
78
+ size='md'
79
+ onPress={hideOverlay}
80
+ LeadingIcon={ChevronLeft}
81
+ iconOnly
82
+ />
83
+ </View>
85
84
  <View style={styles.centerContainer} accessibilityLabel='Center element'>
86
85
  <Text style={styles.userName}>
87
86
  {asset?.user?.name || asset?.user?.id || t('Unknown User')}
@@ -90,7 +89,7 @@ export const ImageGalleryHeader = (props: ImageGalleryHeaderProps) => {
90
89
  </View>
91
90
  <View style={styles.rightContainer} accessibilityLabel='Right element' />
92
91
  </View>
93
- </ReanimatedSafeAreaView>
92
+ </Animated.View>
94
93
  </View>
95
94
  );
96
95
  };
@@ -114,7 +113,7 @@ const useStyles = () => {
114
113
  },
115
114
  centerContainer: {
116
115
  alignItems: 'center',
117
- flex: 1,
116
+ flex: 2,
118
117
  justifyContent: 'center',
119
118
  gap: primitives.spacingXxs,
120
119
  ...header.centerContainer,
@@ -134,9 +133,13 @@ const useStyles = () => {
134
133
  borderBottomColor: semantics.borderCoreSubtle,
135
134
  ...header.innerContainer,
136
135
  },
136
+ leftContainer: {
137
+ flex: 1,
138
+ },
137
139
  rightContainer: {
138
140
  width: 24,
139
141
  height: 24,
142
+ flex: 1,
140
143
  },
141
144
  userName: {
142
145
  color: semantics.textPrimary,
@@ -4,12 +4,11 @@ import { SharedValue, useAnimatedStyle } from 'react-native-reanimated';
4
4
  import { useViewport } from '../../../hooks/useViewport';
5
5
 
6
6
  type Props = {
7
+ currentIndexShared: SharedValue<number>;
7
8
  index: number;
8
9
  offsetScale: SharedValue<number>;
9
- previous: boolean;
10
10
  scale: SharedValue<number>;
11
11
  screenHeight: number;
12
- selected: boolean;
13
12
  translateX: SharedValue<number>;
14
13
  translateY: SharedValue<number>;
15
14
  };
@@ -17,12 +16,11 @@ type Props = {
17
16
  const oneEighth = 1 / 8;
18
17
 
19
18
  export const useAnimatedGalleryStyle = ({
19
+ currentIndexShared,
20
20
  index,
21
21
  offsetScale,
22
- previous,
23
22
  scale,
24
23
  screenHeight,
25
- selected,
26
24
  translateX,
27
25
  translateY,
28
26
  }: Props) => {
@@ -40,6 +38,8 @@ export const useAnimatedGalleryStyle = ({
40
38
  * place as to not come into the screen when the image shrinks.
41
39
  */
42
40
  const animatedGalleryStyle = useAnimatedStyle<ImageStyle>(() => {
41
+ const selected = currentIndexShared.value === index;
42
+ const previous = currentIndexShared.value > index;
43
43
  const xScaleOffset = -7 * screenWidth * (0.5 + index);
44
44
  const yScaleOffset = -screenHeight * 3.5;
45
45
  return {
@@ -62,7 +62,7 @@ export const useAnimatedGalleryStyle = ({
62
62
  { scaleX: 1 },
63
63
  ],
64
64
  };
65
- }, [previous, selected]);
65
+ }, []);
66
66
 
67
67
  const animatedStyles = useAnimatedStyle(() => {
68
68
  const xScaleOffset = 7 * screenWidth * (0.5 + index);