stream-chat-react-native-core 9.3.1-beta.6 → 9.3.1-beta.8

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 (329) hide show
  1. package/lib/commonjs/a11y/hooks/useAnnounceOnShow.js +27 -0
  2. package/lib/commonjs/a11y/hooks/useAnnounceOnShow.js.map +1 -0
  3. package/lib/commonjs/a11y/index.js +11 -0
  4. package/lib/commonjs/a11y/index.js.map +1 -1
  5. package/lib/commonjs/components/Accessibility/CompositeAccessibilityProbe.js +29 -0
  6. package/lib/commonjs/components/Accessibility/CompositeAccessibilityProbe.js.map +1 -0
  7. package/lib/commonjs/components/Accessibility/HiddenA11yText.js +30 -0
  8. package/lib/commonjs/components/Accessibility/HiddenA11yText.js.map +1 -0
  9. package/lib/commonjs/components/Accessibility/OverlayA11yShield.js +37 -0
  10. package/lib/commonjs/components/Accessibility/OverlayA11yShield.js.map +1 -0
  11. package/lib/commonjs/components/Accessibility/index.js +22 -0
  12. package/lib/commonjs/components/Accessibility/index.js.map +1 -1
  13. package/lib/commonjs/components/Attachment/Gallery.js +10 -0
  14. package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
  15. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +31 -29
  16. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  17. package/lib/commonjs/components/ChannelPreview/ChannelPreviewMutedStatus.js +11 -5
  18. package/lib/commonjs/components/ChannelPreview/ChannelPreviewMutedStatus.js.map +1 -1
  19. package/lib/commonjs/components/ChannelPreview/ChannelPreviewStatus.js +18 -2
  20. package/lib/commonjs/components/ChannelPreview/ChannelPreviewStatus.js.map +1 -1
  21. package/lib/commonjs/components/ChannelPreview/ChannelPreviewUnreadCount.js +8 -2
  22. package/lib/commonjs/components/ChannelPreview/ChannelPreviewUnreadCount.js.map +1 -1
  23. package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js +3 -0
  24. package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
  25. package/lib/commonjs/components/ImageGallery/ImageGallery.js +56 -1
  26. package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
  27. package/lib/commonjs/components/Message/MessageItemView/Headers/MessageReminderHeader.js +2 -0
  28. package/lib/commonjs/components/Message/MessageItemView/Headers/MessageReminderHeader.js.map +1 -1
  29. package/lib/commonjs/components/Message/MessageItemView/Headers/SentToChannelHeader.js +2 -0
  30. package/lib/commonjs/components/Message/MessageItemView/Headers/SentToChannelHeader.js.map +1 -1
  31. package/lib/commonjs/components/Message/MessageItemView/MessageContent.js +26 -4
  32. package/lib/commonjs/components/Message/MessageItemView/MessageContent.js.map +1 -1
  33. package/lib/commonjs/components/Message/MessageItemView/MessageFooter.js +2 -0
  34. package/lib/commonjs/components/Message/MessageItemView/MessageFooter.js.map +1 -1
  35. package/lib/commonjs/components/Message/MessageItemView/MessageReplies.js +7 -3
  36. package/lib/commonjs/components/Message/MessageItemView/MessageReplies.js.map +1 -1
  37. package/lib/commonjs/components/Message/MessageItemView/MessageRepliesAvatars.js +2 -0
  38. package/lib/commonjs/components/Message/MessageItemView/MessageRepliesAvatars.js.map +1 -1
  39. package/lib/commonjs/components/Message/MessageItemView/MessageStatus.js +35 -30
  40. package/lib/commonjs/components/Message/MessageItemView/MessageStatus.js.map +1 -1
  41. package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js +16 -6
  42. package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
  43. package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListClustered.js +19 -6
  44. package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListClustered.js.map +1 -1
  45. package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListItem.js +10 -1
  46. package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListItem.js.map +1 -1
  47. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +6 -1
  48. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  49. package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js +8 -0
  50. package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
  51. package/lib/commonjs/components/MessageList/InlineDateSeparator.js +8 -1
  52. package/lib/commonjs/components/MessageList/InlineDateSeparator.js.map +1 -1
  53. package/lib/commonjs/components/MessageMenu/ReactionButton.js +0 -7
  54. package/lib/commonjs/components/MessageMenu/ReactionButton.js.map +1 -1
  55. package/lib/commonjs/components/Poll/Poll.js +2 -17
  56. package/lib/commonjs/components/Poll/Poll.js.map +1 -1
  57. package/lib/commonjs/components/Poll/components/PollOption.js +6 -1
  58. package/lib/commonjs/components/Poll/components/PollOption.js.map +1 -1
  59. package/lib/commonjs/components/Reply/Reply.js +43 -6
  60. package/lib/commonjs/components/Reply/Reply.js.map +1 -1
  61. package/lib/commonjs/components/ui/Avatar/ChannelAvatar.js +17 -11
  62. package/lib/commonjs/components/ui/Avatar/ChannelAvatar.js.map +1 -1
  63. package/lib/commonjs/components/ui/Badge/BadgeNotification.js +3 -1
  64. package/lib/commonjs/components/ui/Badge/BadgeNotification.js.map +1 -1
  65. package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js +6 -22
  66. package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
  67. package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
  68. package/lib/commonjs/contexts/overlayContext/MessageOverlayHostLayer.js +1 -0
  69. package/lib/commonjs/contexts/overlayContext/MessageOverlayHostLayer.js.map +1 -1
  70. package/lib/commonjs/contexts/overlayContext/OverlayProvider.js +4 -1
  71. package/lib/commonjs/contexts/overlayContext/OverlayProvider.js.map +1 -1
  72. package/lib/commonjs/i18n/ar.json +26 -8
  73. package/lib/commonjs/i18n/en.json +23 -5
  74. package/lib/commonjs/i18n/es.json +23 -5
  75. package/lib/commonjs/i18n/fr.json +23 -5
  76. package/lib/commonjs/i18n/he.json +23 -5
  77. package/lib/commonjs/i18n/hi.json +24 -6
  78. package/lib/commonjs/i18n/it.json +23 -5
  79. package/lib/commonjs/i18n/ja.json +23 -5
  80. package/lib/commonjs/i18n/ko.json +23 -5
  81. package/lib/commonjs/i18n/nl.json +24 -6
  82. package/lib/commonjs/i18n/pt-br.json +25 -7
  83. package/lib/commonjs/i18n/ru.json +23 -5
  84. package/lib/commonjs/i18n/tr.json +24 -6
  85. package/lib/commonjs/state-store/image-gallery-state-store.js +13 -0
  86. package/lib/commonjs/state-store/image-gallery-state-store.js.map +1 -1
  87. package/lib/commonjs/utils/i18n/getDateString.js +26 -1
  88. package/lib/commonjs/utils/i18n/getDateString.js.map +1 -1
  89. package/lib/commonjs/version.json +1 -1
  90. package/lib/module/a11y/hooks/useAnnounceOnShow.js +27 -0
  91. package/lib/module/a11y/hooks/useAnnounceOnShow.js.map +1 -0
  92. package/lib/module/a11y/index.js +11 -0
  93. package/lib/module/a11y/index.js.map +1 -1
  94. package/lib/module/components/Accessibility/CompositeAccessibilityProbe.js +29 -0
  95. package/lib/module/components/Accessibility/CompositeAccessibilityProbe.js.map +1 -0
  96. package/lib/module/components/Accessibility/HiddenA11yText.js +30 -0
  97. package/lib/module/components/Accessibility/HiddenA11yText.js.map +1 -0
  98. package/lib/module/components/Accessibility/OverlayA11yShield.js +37 -0
  99. package/lib/module/components/Accessibility/OverlayA11yShield.js.map +1 -0
  100. package/lib/module/components/Accessibility/index.js +22 -0
  101. package/lib/module/components/Accessibility/index.js.map +1 -1
  102. package/lib/module/components/Attachment/Gallery.js +10 -0
  103. package/lib/module/components/Attachment/Gallery.js.map +1 -1
  104. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +31 -29
  105. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  106. package/lib/module/components/ChannelPreview/ChannelPreviewMutedStatus.js +11 -5
  107. package/lib/module/components/ChannelPreview/ChannelPreviewMutedStatus.js.map +1 -1
  108. package/lib/module/components/ChannelPreview/ChannelPreviewStatus.js +18 -2
  109. package/lib/module/components/ChannelPreview/ChannelPreviewStatus.js.map +1 -1
  110. package/lib/module/components/ChannelPreview/ChannelPreviewUnreadCount.js +8 -2
  111. package/lib/module/components/ChannelPreview/ChannelPreviewUnreadCount.js.map +1 -1
  112. package/lib/module/components/ChannelPreview/ChannelPreviewView.js +3 -0
  113. package/lib/module/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
  114. package/lib/module/components/ImageGallery/ImageGallery.js +56 -1
  115. package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
  116. package/lib/module/components/Message/MessageItemView/Headers/MessageReminderHeader.js +2 -0
  117. package/lib/module/components/Message/MessageItemView/Headers/MessageReminderHeader.js.map +1 -1
  118. package/lib/module/components/Message/MessageItemView/Headers/SentToChannelHeader.js +2 -0
  119. package/lib/module/components/Message/MessageItemView/Headers/SentToChannelHeader.js.map +1 -1
  120. package/lib/module/components/Message/MessageItemView/MessageContent.js +26 -4
  121. package/lib/module/components/Message/MessageItemView/MessageContent.js.map +1 -1
  122. package/lib/module/components/Message/MessageItemView/MessageFooter.js +2 -0
  123. package/lib/module/components/Message/MessageItemView/MessageFooter.js.map +1 -1
  124. package/lib/module/components/Message/MessageItemView/MessageReplies.js +7 -3
  125. package/lib/module/components/Message/MessageItemView/MessageReplies.js.map +1 -1
  126. package/lib/module/components/Message/MessageItemView/MessageRepliesAvatars.js +2 -0
  127. package/lib/module/components/Message/MessageItemView/MessageRepliesAvatars.js.map +1 -1
  128. package/lib/module/components/Message/MessageItemView/MessageStatus.js +35 -30
  129. package/lib/module/components/Message/MessageItemView/MessageStatus.js.map +1 -1
  130. package/lib/module/components/Message/MessageItemView/MessageTextContainer.js +16 -6
  131. package/lib/module/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
  132. package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListClustered.js +19 -6
  133. package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListClustered.js.map +1 -1
  134. package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListItem.js +10 -1
  135. package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListItem.js.map +1 -1
  136. package/lib/module/components/Message/hooks/useCreateMessageContext.js +6 -1
  137. package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  138. package/lib/module/components/Message/hooks/useMessageActionHandlers.js +8 -0
  139. package/lib/module/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
  140. package/lib/module/components/MessageList/InlineDateSeparator.js +8 -1
  141. package/lib/module/components/MessageList/InlineDateSeparator.js.map +1 -1
  142. package/lib/module/components/MessageMenu/ReactionButton.js +0 -7
  143. package/lib/module/components/MessageMenu/ReactionButton.js.map +1 -1
  144. package/lib/module/components/Poll/Poll.js +2 -17
  145. package/lib/module/components/Poll/Poll.js.map +1 -1
  146. package/lib/module/components/Poll/components/PollOption.js +6 -1
  147. package/lib/module/components/Poll/components/PollOption.js.map +1 -1
  148. package/lib/module/components/Reply/Reply.js +43 -6
  149. package/lib/module/components/Reply/Reply.js.map +1 -1
  150. package/lib/module/components/ui/Avatar/ChannelAvatar.js +17 -11
  151. package/lib/module/components/ui/Avatar/ChannelAvatar.js.map +1 -1
  152. package/lib/module/components/ui/Badge/BadgeNotification.js +3 -1
  153. package/lib/module/components/ui/Badge/BadgeNotification.js.map +1 -1
  154. package/lib/module/contexts/accessibilityContext/AccessibilityContext.js +6 -22
  155. package/lib/module/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
  156. package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
  157. package/lib/module/contexts/overlayContext/MessageOverlayHostLayer.js +1 -0
  158. package/lib/module/contexts/overlayContext/MessageOverlayHostLayer.js.map +1 -1
  159. package/lib/module/contexts/overlayContext/OverlayProvider.js +4 -1
  160. package/lib/module/contexts/overlayContext/OverlayProvider.js.map +1 -1
  161. package/lib/module/i18n/ar.json +26 -8
  162. package/lib/module/i18n/en.json +23 -5
  163. package/lib/module/i18n/es.json +23 -5
  164. package/lib/module/i18n/fr.json +23 -5
  165. package/lib/module/i18n/he.json +23 -5
  166. package/lib/module/i18n/hi.json +24 -6
  167. package/lib/module/i18n/it.json +23 -5
  168. package/lib/module/i18n/ja.json +23 -5
  169. package/lib/module/i18n/ko.json +23 -5
  170. package/lib/module/i18n/nl.json +24 -6
  171. package/lib/module/i18n/pt-br.json +25 -7
  172. package/lib/module/i18n/ru.json +23 -5
  173. package/lib/module/i18n/tr.json +24 -6
  174. package/lib/module/state-store/image-gallery-state-store.js +13 -0
  175. package/lib/module/state-store/image-gallery-state-store.js.map +1 -1
  176. package/lib/module/utils/i18n/getDateString.js +26 -1
  177. package/lib/module/utils/i18n/getDateString.js.map +1 -1
  178. package/lib/module/version.json +1 -1
  179. package/lib/typescript/a11y/hooks/useAnnounceOnShow.d.ts +21 -0
  180. package/lib/typescript/a11y/hooks/useAnnounceOnShow.d.ts.map +1 -0
  181. package/lib/typescript/a11y/index.d.ts +1 -0
  182. package/lib/typescript/a11y/index.d.ts.map +1 -1
  183. package/lib/typescript/components/Accessibility/CompositeAccessibilityProbe.d.ts +30 -0
  184. package/lib/typescript/components/Accessibility/CompositeAccessibilityProbe.d.ts.map +1 -0
  185. package/lib/typescript/components/Accessibility/HiddenA11yText.d.ts +25 -0
  186. package/lib/typescript/components/Accessibility/HiddenA11yText.d.ts.map +1 -0
  187. package/lib/typescript/components/Accessibility/OverlayA11yShield.d.ts +20 -0
  188. package/lib/typescript/components/Accessibility/OverlayA11yShield.d.ts.map +1 -0
  189. package/lib/typescript/components/Accessibility/index.d.ts +2 -0
  190. package/lib/typescript/components/Accessibility/index.d.ts.map +1 -1
  191. package/lib/typescript/components/Attachment/Gallery.d.ts.map +1 -1
  192. package/lib/typescript/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.d.ts.map +1 -1
  193. package/lib/typescript/components/ChannelPreview/ChannelPreviewMutedStatus.d.ts.map +1 -1
  194. package/lib/typescript/components/ChannelPreview/ChannelPreviewStatus.d.ts.map +1 -1
  195. package/lib/typescript/components/ChannelPreview/ChannelPreviewUnreadCount.d.ts.map +1 -1
  196. package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts.map +1 -1
  197. package/lib/typescript/components/ImageGallery/ImageGallery.d.ts.map +1 -1
  198. package/lib/typescript/components/Message/MessageItemView/Headers/MessageReminderHeader.d.ts.map +1 -1
  199. package/lib/typescript/components/Message/MessageItemView/Headers/SentToChannelHeader.d.ts.map +1 -1
  200. package/lib/typescript/components/Message/MessageItemView/MessageContent.d.ts +1 -1
  201. package/lib/typescript/components/Message/MessageItemView/MessageContent.d.ts.map +1 -1
  202. package/lib/typescript/components/Message/MessageItemView/MessageFooter.d.ts.map +1 -1
  203. package/lib/typescript/components/Message/MessageItemView/MessageReplies.d.ts.map +1 -1
  204. package/lib/typescript/components/Message/MessageItemView/MessageRepliesAvatars.d.ts.map +1 -1
  205. package/lib/typescript/components/Message/MessageItemView/MessageStatus.d.ts.map +1 -1
  206. package/lib/typescript/components/Message/MessageItemView/MessageTextContainer.d.ts +1 -1
  207. package/lib/typescript/components/Message/MessageItemView/MessageTextContainer.d.ts.map +1 -1
  208. package/lib/typescript/components/Message/MessageItemView/ReactionList/ReactionListClustered.d.ts.map +1 -1
  209. package/lib/typescript/components/Message/MessageItemView/ReactionList/ReactionListItem.d.ts.map +1 -1
  210. package/lib/typescript/components/Message/MessageOverlayWrapper.d.ts +1 -1
  211. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts +1 -1
  212. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts.map +1 -1
  213. package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts.map +1 -1
  214. package/lib/typescript/components/MessageList/InlineDateSeparator.d.ts.map +1 -1
  215. package/lib/typescript/components/MessageMenu/ReactionButton.d.ts.map +1 -1
  216. package/lib/typescript/components/Poll/Poll.d.ts.map +1 -1
  217. package/lib/typescript/components/Poll/components/PollOption.d.ts.map +1 -1
  218. package/lib/typescript/components/Reply/Reply.d.ts.map +1 -1
  219. package/lib/typescript/components/ui/Avatar/ChannelAvatar.d.ts.map +1 -1
  220. package/lib/typescript/components/ui/Badge/BadgeNotification.d.ts +5 -0
  221. package/lib/typescript/components/ui/Badge/BadgeNotification.d.ts.map +1 -1
  222. package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts +32 -2
  223. package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts.map +1 -1
  224. package/lib/typescript/contexts/messageContext/MessageContext.d.ts +8 -0
  225. package/lib/typescript/contexts/messageContext/MessageContext.d.ts.map +1 -1
  226. package/lib/typescript/contexts/overlayContext/MessageOverlayHostLayer.d.ts.map +1 -1
  227. package/lib/typescript/contexts/overlayContext/OverlayProvider.d.ts.map +1 -1
  228. package/lib/typescript/hooks/useTranslatedMessage.d.ts +1 -1
  229. package/lib/typescript/i18n/ar.json +26 -8
  230. package/lib/typescript/i18n/en.json +23 -5
  231. package/lib/typescript/i18n/es.json +23 -5
  232. package/lib/typescript/i18n/fr.json +23 -5
  233. package/lib/typescript/i18n/he.json +23 -5
  234. package/lib/typescript/i18n/hi.json +24 -6
  235. package/lib/typescript/i18n/it.json +23 -5
  236. package/lib/typescript/i18n/ja.json +23 -5
  237. package/lib/typescript/i18n/ko.json +23 -5
  238. package/lib/typescript/i18n/nl.json +24 -6
  239. package/lib/typescript/i18n/pt-br.json +25 -7
  240. package/lib/typescript/i18n/ru.json +23 -5
  241. package/lib/typescript/i18n/tr.json +24 -6
  242. package/lib/typescript/state-store/image-gallery-state-store.d.ts +5 -1
  243. package/lib/typescript/state-store/image-gallery-state-store.d.ts.map +1 -1
  244. package/lib/typescript/utils/i18n/Streami18n.d.ts +22 -4
  245. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  246. package/lib/typescript/utils/i18n/getDateString.d.ts +28 -0
  247. package/lib/typescript/utils/i18n/getDateString.d.ts.map +1 -1
  248. package/package.json +1 -1
  249. package/src/a11y/hooks/useAnnounceOnShow.ts +44 -0
  250. package/src/a11y/index.ts +1 -0
  251. package/src/components/Accessibility/CompositeAccessibilityProbe.tsx +48 -0
  252. package/src/components/Accessibility/HiddenA11yText.tsx +49 -0
  253. package/src/components/Accessibility/OverlayA11yShield.tsx +49 -0
  254. package/src/components/Accessibility/__tests__/OverlayA11yShield.test.tsx +83 -0
  255. package/src/components/Accessibility/index.ts +2 -0
  256. package/src/components/Attachment/Gallery.tsx +14 -2
  257. package/src/components/Channel/__tests__/ownCapabilities.test.tsx +25 -2
  258. package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx +19 -16
  259. package/src/components/ChannelPreview/ChannelPreviewMutedStatus.tsx +8 -1
  260. package/src/components/ChannelPreview/ChannelPreviewStatus.tsx +26 -6
  261. package/src/components/ChannelPreview/ChannelPreviewUnreadCount.tsx +5 -1
  262. package/src/components/ChannelPreview/ChannelPreviewView.tsx +3 -0
  263. package/src/components/ImageGallery/ImageGallery.tsx +82 -4
  264. package/src/components/ImageGallery/__tests__/ImageGallery.test.tsx +13 -3
  265. package/src/components/ImageGallery/__tests__/ImageGalleryAdjustable.test.tsx +141 -0
  266. package/src/components/Message/MessageItemView/Headers/MessageReminderHeader.tsx +7 -1
  267. package/src/components/Message/MessageItemView/Headers/SentToChannelHeader.tsx +7 -1
  268. package/src/components/Message/MessageItemView/MessageContent.tsx +34 -4
  269. package/src/components/Message/MessageItemView/MessageFooter.tsx +6 -1
  270. package/src/components/Message/MessageItemView/MessageReplies.tsx +9 -7
  271. package/src/components/Message/MessageItemView/MessageRepliesAvatars.tsx +5 -1
  272. package/src/components/Message/MessageItemView/MessageStatus.tsx +36 -39
  273. package/src/components/Message/MessageItemView/MessageTextContainer.tsx +27 -4
  274. package/src/components/Message/MessageItemView/ReactionList/ReactionListClustered.tsx +24 -10
  275. package/src/components/Message/MessageItemView/ReactionList/ReactionListItem.tsx +7 -1
  276. package/src/components/Message/MessageItemView/__tests__/Message.test.tsx +10 -3
  277. package/src/components/Message/MessageItemView/__tests__/MessageReplies.test.tsx +10 -2
  278. package/src/components/Message/MessageItemView/__tests__/MessageStatus.test.tsx +10 -7
  279. package/src/components/Message/MessageItemView/__tests__/ReactionListBottom.test.tsx +1 -1
  280. package/src/components/Message/hooks/useCreateMessageContext.ts +12 -1
  281. package/src/components/Message/hooks/useMessageActionHandlers.ts +7 -0
  282. package/src/components/MessageInput/__tests__/__snapshots__/AttachButton.test.tsx.snap +3 -0
  283. package/src/components/MessageInput/__tests__/__snapshots__/SendButton.test.tsx.snap +2 -0
  284. package/src/components/MessageList/InlineDateSeparator.tsx +10 -3
  285. package/src/components/MessageMenu/ReactionButton.tsx +0 -7
  286. package/src/components/MessageMenu/__tests__/ReactionButton.test.tsx +1 -14
  287. package/src/components/Poll/Poll.tsx +2 -26
  288. package/src/components/Poll/components/PollOption.tsx +7 -1
  289. package/src/components/Reply/Reply.tsx +58 -7
  290. package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +9 -0
  291. package/src/components/ui/Avatar/ChannelAvatar.tsx +39 -29
  292. package/src/components/ui/Badge/BadgeNotification.tsx +11 -2
  293. package/src/contexts/accessibilityContext/AccessibilityContext.tsx +60 -36
  294. package/src/contexts/messageContext/MessageContext.tsx +8 -0
  295. package/src/contexts/overlayContext/MessageOverlayHostLayer.tsx +5 -1
  296. package/src/contexts/overlayContext/OverlayProvider.tsx +2 -1
  297. package/src/i18n/ar.json +26 -8
  298. package/src/i18n/en.json +23 -5
  299. package/src/i18n/es.json +23 -5
  300. package/src/i18n/fr.json +23 -5
  301. package/src/i18n/he.json +23 -5
  302. package/src/i18n/hi.json +24 -6
  303. package/src/i18n/it.json +23 -5
  304. package/src/i18n/ja.json +23 -5
  305. package/src/i18n/ko.json +23 -5
  306. package/src/i18n/nl.json +24 -6
  307. package/src/i18n/pt-br.json +25 -7
  308. package/src/i18n/ru.json +23 -5
  309. package/src/i18n/tr.json +24 -6
  310. package/src/state-store/__tests__/image-gallery-state-store.test.ts +1 -0
  311. package/src/state-store/image-gallery-state-store.ts +13 -1
  312. package/src/utils/i18n/getDateString.ts +57 -0
  313. package/src/version.json +1 -1
  314. package/lib/commonjs/components/Poll/hooks/usePollAccessibilityActions.js +0 -150
  315. package/lib/commonjs/components/Poll/hooks/usePollAccessibilityActions.js.map +0 -1
  316. package/lib/commonjs/components/Poll/hooks/usePollAccessibilityLabel.js +0 -59
  317. package/lib/commonjs/components/Poll/hooks/usePollAccessibilityLabel.js.map +0 -1
  318. package/lib/module/components/Poll/hooks/usePollAccessibilityActions.js +0 -150
  319. package/lib/module/components/Poll/hooks/usePollAccessibilityActions.js.map +0 -1
  320. package/lib/module/components/Poll/hooks/usePollAccessibilityLabel.js +0 -59
  321. package/lib/module/components/Poll/hooks/usePollAccessibilityLabel.js.map +0 -1
  322. package/lib/typescript/components/Poll/hooks/usePollAccessibilityActions.d.ts +0 -25
  323. package/lib/typescript/components/Poll/hooks/usePollAccessibilityActions.d.ts.map +0 -1
  324. package/lib/typescript/components/Poll/hooks/usePollAccessibilityLabel.d.ts +0 -8
  325. package/lib/typescript/components/Poll/hooks/usePollAccessibilityLabel.d.ts.map +0 -1
  326. package/src/components/Poll/hooks/__tests__/usePollAccessibilityActions.test.tsx +0 -358
  327. package/src/components/Poll/hooks/__tests__/usePollAccessibilityLabel.test.tsx +0 -142
  328. package/src/components/Poll/hooks/usePollAccessibilityActions.ts +0 -191
  329. package/src/components/Poll/hooks/usePollAccessibilityLabel.ts +0 -75
@@ -0,0 +1,141 @@
1
+ import React, { useEffect } from 'react';
2
+
3
+ import type { SharedValue } from 'react-native-reanimated';
4
+
5
+ import { act, fireEvent, render, screen, waitFor } from '@testing-library/react-native';
6
+
7
+ import { LocalMessage } from 'stream-chat';
8
+
9
+ import {
10
+ ImageGalleryContext,
11
+ ImageGalleryContextValue,
12
+ } from '../../../contexts/imageGalleryContext/ImageGalleryContext';
13
+ import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
14
+ import {
15
+ generateImageAttachment,
16
+ generateVideoAttachment,
17
+ } from '../../../mock-builders/generator/attachment';
18
+ import { generateMessage } from '../../../mock-builders/generator/message';
19
+ import { ImageGalleryStateStore } from '../../../state-store/image-gallery-state-store';
20
+ import { ImageGallery } from '../ImageGallery';
21
+
22
+ jest.mock('../../../native.ts', () => {
23
+ const { View } = require('react-native');
24
+ return {
25
+ isFileSystemAvailable: jest.fn(() => true),
26
+ isImageMediaLibraryAvailable: jest.fn(() => true),
27
+ isShareImageAvailable: jest.fn(() => true),
28
+ isVideoPlayerAvailable: jest.fn(() => true),
29
+ NativeHandlers: { Video: View },
30
+ };
31
+ });
32
+
33
+ type HarnessProps = {
34
+ message: LocalMessage;
35
+ accessibilityEnabled?: boolean;
36
+ store: ImageGalleryStateStore;
37
+ };
38
+
39
+ const Harness = ({ accessibilityEnabled = true, message, store }: HarnessProps) => {
40
+ useEffect(() => {
41
+ const unsubscribe = store.registerSubscriptions();
42
+ return () => unsubscribe();
43
+ }, [store]);
44
+
45
+ const { attachments } = message;
46
+ store.openImageGallery({
47
+ messages: [message],
48
+ selectedAttachmentUrl: attachments?.[0]?.asset_url || attachments?.[0]?.image_url || '',
49
+ });
50
+
51
+ return (
52
+ <OverlayProvider
53
+ accessibility={{ enabled: accessibilityEnabled }}
54
+ value={{ overlayOpacity: { value: 1 } as SharedValue<number> }}
55
+ >
56
+ <ImageGalleryContext.Provider
57
+ value={{ imageGalleryStateStore: store } as unknown as ImageGalleryContextValue}
58
+ >
59
+ <ImageGallery />
60
+ </ImageGalleryContext.Provider>
61
+ </OverlayProvider>
62
+ );
63
+ };
64
+
65
+ const findGalleryRoot = () =>
66
+ screen.getByLabelText('Image Gallery', { includeHiddenElements: true });
67
+
68
+ const fireAccessibilityAction = (actionName: 'increment' | 'decrement') => {
69
+ fireEvent(findGalleryRoot(), 'accessibilityAction', { nativeEvent: { actionName } });
70
+ };
71
+
72
+ const renderWithAssets = (assetsCount: number, accessibilityEnabled = true) => {
73
+ const attachments = [
74
+ ...Array.from({ length: Math.max(assetsCount - 1, 0) }, () => generateImageAttachment()),
75
+ ...(assetsCount > 0 ? [generateVideoAttachment({ type: 'video' })] : []),
76
+ ];
77
+ const message = generateMessage({ attachments });
78
+ const store = new ImageGalleryStateStore();
79
+ render(<Harness accessibilityEnabled={accessibilityEnabled} message={message} store={store} />);
80
+ return { store };
81
+ };
82
+
83
+ describe('ImageGallery adjustable cycling', () => {
84
+ it('marks the root as adjustable with the position value when a11y is enabled and there is more than one asset', async () => {
85
+ renderWithAssets(3);
86
+
87
+ await waitFor(() => {
88
+ const root = findGalleryRoot();
89
+ expect(root.props.accessibilityRole).toBe('adjustable');
90
+ expect(root.props.accessibilityValue).toEqual({ text: '1 of 3' });
91
+ expect(root.props.accessibilityActions).toEqual([
92
+ { name: 'increment' },
93
+ { name: 'decrement' },
94
+ ]);
95
+ });
96
+ });
97
+
98
+ it('does not apply the adjustable role when accessibility is disabled', async () => {
99
+ renderWithAssets(3, false);
100
+
101
+ await waitFor(() => {
102
+ const root = findGalleryRoot();
103
+ expect(root.props.accessibilityRole).toBeUndefined();
104
+ expect(root.props.accessibilityActions).toBeUndefined();
105
+ });
106
+ });
107
+
108
+ it('moves to the next asset on increment and clamps at the last asset', async () => {
109
+ const { store } = renderWithAssets(3);
110
+
111
+ await waitFor(() => expect(findGalleryRoot().props.accessibilityRole).toBe('adjustable'));
112
+
113
+ act(() => fireAccessibilityAction('increment'));
114
+ expect(store.state.getLatestValue().currentIndex).toBe(1);
115
+
116
+ act(() => fireAccessibilityAction('increment'));
117
+ expect(store.state.getLatestValue().currentIndex).toBe(2);
118
+
119
+ act(() => fireAccessibilityAction('increment'));
120
+ expect(store.state.getLatestValue().currentIndex).toBe(2);
121
+ });
122
+
123
+ it('moves to the previous asset on decrement and clamps at the first asset', async () => {
124
+ const { store } = renderWithAssets(3);
125
+
126
+ await waitFor(() => expect(findGalleryRoot().props.accessibilityRole).toBe('adjustable'));
127
+
128
+ act(() => fireAccessibilityAction('increment'));
129
+ act(() => fireAccessibilityAction('increment'));
130
+ expect(store.state.getLatestValue().currentIndex).toBe(2);
131
+
132
+ act(() => fireAccessibilityAction('decrement'));
133
+ expect(store.state.getLatestValue().currentIndex).toBe(1);
134
+
135
+ act(() => fireAccessibilityAction('decrement'));
136
+ expect(store.state.getLatestValue().currentIndex).toBe(0);
137
+
138
+ act(() => fireAccessibilityAction('decrement'));
139
+ expect(store.state.getLatestValue().currentIndex).toBe(0);
140
+ });
141
+ });
@@ -33,7 +33,13 @@ const MessageReminderHeaderWithContext = (props: MessageReminderHeaderPropsWithC
33
33
  <Text style={styles.label}>
34
34
  {isReminderTimeLeft ? t('Reminder set') : t('Reminder overdue')}
35
35
  </Text>
36
- <Text style={styles.dot}>·</Text>
36
+ <Text
37
+ accessibilityElementsHidden
38
+ importantForAccessibility='no-hide-descendants'
39
+ style={styles.dot}
40
+ >
41
+ ·
42
+ </Text>
37
43
  <Text style={styles.time}>
38
44
  {t('duration/Message reminder', {
39
45
  milliseconds: timeLeftMs,
@@ -43,7 +43,13 @@ const SentToChannelHeaderWithContext = (props: SentToChannelHeaderPropsWithConte
43
43
  </Text>
44
44
  {showViewText ? (
45
45
  <>
46
- <Text style={styles.dot}>·</Text>
46
+ <Text
47
+ accessibilityElementsHidden
48
+ importantForAccessibility='no-hide-descendants'
49
+ style={styles.dot}
50
+ >
51
+ ·
52
+ </Text>
47
53
  <Pressable onPress={onPress}>
48
54
  <Text style={styles.link}>{t('View')}</Text>
49
55
  </Pressable>
@@ -1,5 +1,5 @@
1
1
  import React, { useMemo } from 'react';
2
- import { ColorValue, Pressable, StyleSheet, View, ViewStyle } from 'react-native';
2
+ import { ColorValue, Platform, Pressable, StyleSheet, View, ViewStyle } from 'react-native';
3
3
 
4
4
  import { MessageTextContainer } from './MessageTextContainer';
5
5
 
@@ -55,6 +55,7 @@ export type MessageContentPropsWithContext = Pick<
55
55
  | 'alignment'
56
56
  | 'goToMessage'
57
57
  | 'groupStyles'
58
+ | 'hasInteractiveAccessibilityContent'
58
59
  | 'isMyMessage'
59
60
  | 'message'
60
61
  | 'messageContentOrder'
@@ -111,6 +112,7 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
111
112
  enableMessageGroupingByUser,
112
113
  groupStyles,
113
114
  goToMessage,
115
+ hasInteractiveAccessibilityContent,
114
116
  isMessageAIGenerated,
115
117
  isMyMessage,
116
118
  isVeryLastMessage,
@@ -129,6 +131,10 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
129
131
  } = props;
130
132
  const { client } = useChatContext();
131
133
  const accessibilityHint = useA11yLabel('a11y/Double tap and hold to activate contextual menu');
134
+ const a11ySenderLabel = useA11yLabel(
135
+ isMyMessage ? 'a11y/Message from you' : 'a11y/Message from {{sender}}',
136
+ isMyMessage ? undefined : { sender: message.user?.name || message.user?.id || '' },
137
+ );
132
138
  const {
133
139
  Attachment,
134
140
  FileAttachmentGroup,
@@ -317,11 +323,18 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
317
323
  )}
318
324
  </>
319
325
  );
326
+ const a11yPressableLabel = useMemo(() => {
327
+ if (!a11ySenderLabel) return undefined;
328
+ return message.text && !hasInteractiveAccessibilityContent
329
+ ? `${a11ySenderLabel}. ${message.text}`
330
+ : a11ySenderLabel;
331
+ }, [a11ySenderLabel, hasInteractiveAccessibilityContent, message.text]);
320
332
 
321
333
  return (
322
334
  <Pressable
335
+ accessibilityLabel={a11yPressableLabel}
323
336
  accessibilityHint={accessibilityHint}
324
- accessible={message.poll_id ? false : undefined}
337
+ accessible={hasInteractiveAccessibilityContent ? false : undefined}
325
338
  disabled={preventPress}
326
339
  onLongPress={(event) => {
327
340
  if (onLongPress) {
@@ -371,6 +384,15 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
371
384
  ]}
372
385
  testID='message-content-wrapper'
373
386
  >
387
+ {a11ySenderLabel && Platform.OS !== 'android' && hasInteractiveAccessibilityContent ? (
388
+ <View
389
+ accessibilityLabel={a11ySenderLabel}
390
+ accessibilityHint={accessibilityHint}
391
+ accessible
392
+ pointerEvents='none'
393
+ style={StyleSheet.absoluteFill}
394
+ />
395
+ ) : null}
374
396
  {MessageContentTopView ? <MessageContentTopView /> : null}
375
397
  {hasContentSideViews ? (
376
398
  <View
@@ -403,6 +425,7 @@ const areEqual = (
403
425
  preventPress: prevPreventPress,
404
426
  goToMessage: prevGoToMessage,
405
427
  groupStyles: prevGroupStyles,
428
+ hasInteractiveAccessibilityContent: prevHasInteractiveAccessibilityContent,
406
429
  isAttachmentEqual,
407
430
  message: prevMessage,
408
431
  messageContentOrder: prevMessageContentOrder,
@@ -416,6 +439,7 @@ const areEqual = (
416
439
  preventPress: nextPreventPress,
417
440
  goToMessage: nextGoToMessage,
418
441
  groupStyles: nextGroupStyles,
442
+ hasInteractiveAccessibilityContent: nextHasInteractiveAccessibilityContent,
419
443
  message: nextMessage,
420
444
  messageContentOrder: nextMessageContentOrder,
421
445
  myMessageTheme: nextMyMessageTheme,
@@ -423,6 +447,10 @@ const areEqual = (
423
447
  t: nextT,
424
448
  } = nextProps;
425
449
 
450
+ if (prevHasInteractiveAccessibilityContent !== nextHasInteractiveAccessibilityContent) {
451
+ return false;
452
+ }
453
+
426
454
  if (prevBackgroundColor !== nextBackgroundColor) {
427
455
  return false;
428
456
  }
@@ -558,8 +586,11 @@ export type MessageContentProps = Partial<MessageContentPropsWithContext>;
558
586
  export const MessageContent = (props: MessageContentProps) => {
559
587
  const {
560
588
  alignment,
589
+ files,
561
590
  goToMessage,
562
591
  groupStyles,
592
+ hasInteractiveAccessibilityContent,
593
+ images,
563
594
  isMessageAIGenerated,
564
595
  isMyMessage,
565
596
  message,
@@ -570,8 +601,6 @@ export const MessageContent = (props: MessageContentProps) => {
570
601
  otherAttachments,
571
602
  preventPress,
572
603
  threadList,
573
- files,
574
- images,
575
604
  videos,
576
605
  } = useMessageContext();
577
606
  const {
@@ -626,6 +655,7 @@ export const MessageContent = (props: MessageContentProps) => {
626
655
  enableMessageGroupingByUser,
627
656
  goToMessage,
628
657
  groupStyles,
658
+ hasInteractiveAccessibilityContent,
629
659
  isAttachmentEqual,
630
660
  isMessageAIGenerated,
631
661
  isMyMessage,
@@ -69,7 +69,12 @@ const MessageFooterWithContext = (props: MessageFooterPropsWithContext) => {
69
69
  const isEdited = isEditedMessage(message) && !isAIGenerated;
70
70
 
71
71
  return (
72
- <View style={[styles.container, container]} testID='message-status-time'>
72
+ <View
73
+ accessible
74
+ accessibilityRole='text'
75
+ style={[styles.container, container]}
76
+ testID='message-status-time'
77
+ >
73
78
  {Object.keys(members).length > 2 && alignment === 'left' && message.user?.name ? (
74
79
  <Text numberOfLines={1} ellipsizeMode='tail' style={[styles.name, name]}>
75
80
  {message.user.name}
@@ -75,10 +75,18 @@ const MessageRepliesWithContext = (props: MessageRepliesPropsWithContext) => {
75
75
  return null;
76
76
  }
77
77
 
78
+ const replyCountLabel =
79
+ message.reply_count === 1
80
+ ? t('1 Reply')
81
+ : t('{{ replyCount }} Replies', { replyCount: message.reply_count });
82
+
78
83
  return (
79
84
  <View style={[styles.container, container]}>
80
85
  {alignment === 'left' ? connector : null}
81
86
  <Pressable
87
+ accessibilityHint={t('a11y/Double tap to view thread')}
88
+ accessibilityLabel={replyCountLabel}
89
+ accessibilityRole='button'
82
90
  disabled={preventPress}
83
91
  onLongPress={(event) => {
84
92
  if (onLongPress) {
@@ -114,13 +122,7 @@ const MessageRepliesWithContext = (props: MessageRepliesPropsWithContext) => {
114
122
  testID='message-replies'
115
123
  >
116
124
  <MessageRepliesAvatars />
117
- <Text style={[styles.messageRepliesText, messageRepliesText]}>
118
- {message.reply_count === 1
119
- ? t('1 Reply')
120
- : t('{{ replyCount }} Replies', {
121
- replyCount: message.reply_count,
122
- })}
123
- </Text>
125
+ <Text style={[styles.messageRepliesText, messageRepliesText]}>{replyCountLabel}</Text>
124
126
  </Pressable>
125
127
  {alignment === 'right' ? connector : null}
126
128
  </View>
@@ -24,7 +24,11 @@ export const MessageRepliesAvatarsWithContext = (props: MessageRepliesAvatarsPro
24
24
  const avatars = message?.thread_participants || [];
25
25
 
26
26
  return (
27
- <View style={avatarStackContainer}>
27
+ <View
28
+ accessibilityElementsHidden
29
+ importantForAccessibility='no-hide-descendants'
30
+ style={avatarStackContainer}
31
+ >
28
32
  <UserAvatarStack users={avatars} avatarSize='sm' maxVisible={3} overlap={0.4} />
29
33
  </View>
30
34
  );
@@ -1,6 +1,7 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
 
4
+ import { useA11yLabel } from '../../../a11y/hooks/useA11yLabel';
4
5
  import { useChannelContext } from '../../../contexts/channelContext/ChannelContext';
5
6
  import {
6
7
  MessageContextValue,
@@ -12,6 +13,7 @@ import { CheckAll } from '../../../icons/checks';
12
13
  import { Time } from '../../../icons/clock';
13
14
  import { primitives } from '../../../theme';
14
15
  import { MessageStatusTypes } from '../../../utils/utils';
16
+ import { HiddenA11yText } from '../../Accessibility/HiddenA11yText';
15
17
  import { useShouldUseOverlayStyles } from '../hooks/useShouldUseOverlayStyles';
16
18
 
17
19
  export type MessageStatusPropsWithContext = Pick<
@@ -32,10 +34,6 @@ const MessageStatusWithContext = (props: MessageStatusPropsWithContext) => {
32
34
  },
33
35
  } = useTheme();
34
36
 
35
- if (message.status === MessageStatusTypes.FAILED || message.type === 'error') {
36
- return null;
37
- }
38
-
39
37
  const hasReadByGreaterThanOne = typeof readBy === 'number' && readBy > 1;
40
38
 
41
39
  // Variables to determine the status of the message
@@ -48,42 +46,41 @@ const MessageStatusWithContext = (props: MessageStatusPropsWithContext) => {
48
46
  !read &&
49
47
  message.type !== 'ephemeral';
50
48
 
49
+ const accessibilityLabel = useA11yLabel(
50
+ read
51
+ ? 'a11y/Read'
52
+ : delivered
53
+ ? 'a11y/Delivered'
54
+ : sending
55
+ ? 'a11y/Sending'
56
+ : sent
57
+ ? 'a11y/Sent'
58
+ : '',
59
+ );
60
+
61
+ if (message.status === MessageStatusTypes.FAILED || message.type === 'error') {
62
+ return null;
63
+ }
64
+
51
65
  return (
52
- <View style={[styles.container, container]}>
53
- {read ? (
54
- <CheckAll
55
- height={16}
56
- stroke={styles.readCheck.color}
57
- width={16}
58
- accessibilityLabel='Read'
59
- {...checkAllIcon}
60
- />
61
- ) : delivered ? (
62
- <CheckAll
63
- stroke={styles.deliveredCheck.color}
64
- height={16}
65
- width={16}
66
- accessibilityLabel='Delivered'
67
- {...checkAllIcon}
68
- />
69
- ) : sending ? (
70
- <Time
71
- stroke={styles.sendingCheck.color}
72
- height={16}
73
- width={16}
74
- accessibilityLabel='Sending'
75
- {...timeIcon}
76
- />
77
- ) : sent ? (
78
- <Check
79
- stroke={styles.sentCheck.color}
80
- height={16}
81
- width={16}
82
- accessibilityLabel='Sent'
83
- {...checkIcon}
84
- />
85
- ) : null}
86
- </View>
66
+ <>
67
+ <HiddenA11yText label={accessibilityLabel} />
68
+ <View
69
+ accessibilityElementsHidden={!!accessibilityLabel}
70
+ importantForAccessibility={accessibilityLabel ? 'no-hide-descendants' : undefined}
71
+ style={[styles.container, container]}
72
+ >
73
+ {read ? (
74
+ <CheckAll height={16} stroke={styles.readCheck.color} width={16} {...checkAllIcon} />
75
+ ) : delivered ? (
76
+ <CheckAll stroke={styles.deliveredCheck.color} height={16} width={16} {...checkAllIcon} />
77
+ ) : sending ? (
78
+ <Time stroke={styles.sendingCheck.color} height={16} width={16} {...timeIcon} />
79
+ ) : sent ? (
80
+ <Check stroke={styles.sentCheck.color} height={16} width={16} {...checkIcon} />
81
+ ) : null}
82
+ </View>
83
+ </>
87
84
  );
88
85
  };
89
86
 
@@ -31,7 +31,13 @@ export type MessageTextProps = MessageTextContainerProps & {
31
31
 
32
32
  export type MessageTextContainerPropsWithContext = Pick<
33
33
  MessageContextValue,
34
- 'message' | 'onLongPress' | 'onlyEmojis' | 'onPress' | 'preventPress' | 'isMyMessage'
34
+ | 'hasInteractiveAccessibilityContent'
35
+ | 'isMyMessage'
36
+ | 'message'
37
+ | 'onLongPress'
38
+ | 'onlyEmojis'
39
+ | 'onPress'
40
+ | 'preventPress'
35
41
  > &
36
42
  Pick<MessagesContextValue, 'markdownRules' | 'myMessageTheme' | 'messageTextNumberOfLines'> & {
37
43
  markdownStyles?: MarkdownStyle;
@@ -45,6 +51,7 @@ const MessageTextContainerWithContext = (props: MessageTextContainerPropsWithCon
45
51
  const theme = useTheme();
46
52
 
47
53
  const {
54
+ hasInteractiveAccessibilityContent,
48
55
  isMyMessage,
49
56
  markdownRules,
50
57
  markdownStyles: markdownStylesProp = {},
@@ -81,6 +88,8 @@ const MessageTextContainerWithContext = (props: MessageTextContainerPropsWithCon
81
88
 
82
89
  return (
83
90
  <View
91
+ accessible={hasInteractiveAccessibilityContent || undefined}
92
+ accessibilityRole={hasInteractiveAccessibilityContent ? 'text' : undefined}
84
93
  style={[styles.textContainer, textContainer, stylesProp.textContainer]}
85
94
  testID='message-text-container'
86
95
  >
@@ -113,18 +122,24 @@ const areEqual = (
113
122
  nextProps: MessageTextContainerPropsWithContext,
114
123
  ) => {
115
124
  const {
125
+ hasInteractiveAccessibilityContent: prevHasInteractiveAccessibilityContent,
116
126
  markdownStyles: prevMarkdownStyles,
117
127
  message: prevMessage,
118
128
  myMessageTheme: prevMyMessageTheme,
119
129
  onlyEmojis: prevOnlyEmojis,
120
130
  } = prevProps;
121
131
  const {
132
+ hasInteractiveAccessibilityContent: nextHasInteractiveAccessibilityContent,
122
133
  markdownStyles: nextMarkdownStyles,
123
134
  message: nextMessage,
124
135
  myMessageTheme: nextMyMessageTheme,
125
136
  onlyEmojis: nextOnlyEmojis,
126
137
  } = nextProps;
127
138
 
139
+ if (prevHasInteractiveAccessibilityContent !== nextHasInteractiveAccessibilityContent) {
140
+ return false;
141
+ }
142
+
128
143
  const messageStatusEqual = prevMessage.status === nextMessage.status;
129
144
  if (!messageStatusEqual) {
130
145
  return false;
@@ -182,16 +197,24 @@ const MemoizedMessageTextContainer = React.memo(
182
197
  export type MessageTextContainerProps = Partial<MessageTextContainerPropsWithContext>;
183
198
 
184
199
  export const MessageTextContainer = (props: MessageTextContainerProps) => {
185
- const { message, onLongPress, onlyEmojis, onPress, preventPress, isMyMessage } =
186
- useMessageContext();
200
+ const {
201
+ hasInteractiveAccessibilityContent,
202
+ isMyMessage,
203
+ message,
204
+ onLongPress,
205
+ onlyEmojis,
206
+ onPress,
207
+ preventPress,
208
+ } = useMessageContext();
187
209
  const { markdownRules, messageTextNumberOfLines, myMessageTheme } = useMessagesContext();
188
210
 
189
211
  return (
190
212
  <MemoizedMessageTextContainer
191
213
  {...{
214
+ hasInteractiveAccessibilityContent,
215
+ isMyMessage,
192
216
  markdownRules,
193
217
  message,
194
- isMyMessage,
195
218
  messageTextNumberOfLines,
196
219
  myMessageTheme,
197
220
  onLongPress,
@@ -1,8 +1,9 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { Fragment, useMemo } from 'react';
2
2
  import { StyleProp, StyleSheet, Text, ViewStyle } from 'react-native';
3
3
 
4
4
  import { ReactionListItemWrapper } from './ReactionListItemWrapper';
5
5
 
6
+ import { useA11yLabel } from '../../../../a11y/hooks/useA11yLabel';
6
7
  import {
7
8
  MessageContextValue,
8
9
  useMessageContext,
@@ -19,6 +20,7 @@ import type { IconProps } from '../../../../icons/utils/base';
19
20
 
20
21
  import { primitives } from '../../../../theme';
21
22
  import type { ReactionData } from '../../../../utils/utils';
23
+ import { HiddenA11yText } from '../../../Accessibility/HiddenA11yText';
22
24
 
23
25
  type Props = Pick<IconProps, 'pathFill' | 'style'> & {
24
26
  size: number;
@@ -65,6 +67,8 @@ export const ReactionListClusteredWithContext = (props: ReactionListClusteredPro
65
67
  },
66
68
  } = useTheme();
67
69
  const styles = useStyles();
70
+ const accessibilityHint = useA11yLabel('a11y/Double tap to view reactions');
71
+ const youReacted = useA11yLabel('a11y/you reacted');
68
72
  const supportedReactionTypes = supportedReactions?.map(
69
73
  (supportedReaction) => supportedReaction.type,
70
74
  );
@@ -72,6 +76,9 @@ export const ReactionListClusteredWithContext = (props: ReactionListClusteredPro
72
76
  const moreReactionsCount = reactionsCount - 4;
73
77
  const reactionsCountText =
74
78
  moreReactionsCount < 99 ? moreReactionsCount : `+${moreReactionsCount}`;
79
+ const moreReactionsA11yText = useA11yLabel('a11y/and {{count}} more reactions', {
80
+ count: moreReactionsCount,
81
+ });
75
82
 
76
83
  const hasSupportedReactions = reactions?.some((reaction) =>
77
84
  supportedReactionTypes?.includes(reaction.type),
@@ -83,6 +90,8 @@ export const ReactionListClusteredWithContext = (props: ReactionListClusteredPro
83
90
 
84
91
  return (
85
92
  <ReactionListItemWrapper
93
+ accessibilityHint={accessibilityHint}
94
+ accessibilityLabel={accessibilityLabel}
86
95
  disabled={preventPress}
87
96
  onPress={(event) => {
88
97
  if (onPress) {
@@ -111,18 +120,23 @@ export const ReactionListClusteredWithContext = (props: ReactionListClusteredPro
111
120
  }
112
121
  }}
113
122
  style={containerStyle}
114
- accessibilityLabel={accessibilityLabel}
115
123
  >
116
124
  {reactions?.slice(0, 4).map((reaction) => (
117
- <Icon
118
- key={reaction.type}
119
- size={icon.size}
120
- style={[styles.iconStyle, icon.style]}
121
- supportedReactions={supportedReactions}
122
- type={reaction.type}
123
- />
125
+ <Fragment key={reaction.type}>
126
+ <Icon
127
+ size={icon.size}
128
+ style={[styles.iconStyle, icon.style]}
129
+ supportedReactions={supportedReactions}
130
+ type={reaction.type}
131
+ />
132
+ {reaction.own ? <HiddenA11yText label={youReacted} /> : null}
133
+ </Fragment>
124
134
  ))}
125
- {reactionsCount > 4 ? <Text style={styles.reactionCount}>{reactionsCountText}</Text> : null}
135
+ {reactionsCount > 4 ? (
136
+ <Text accessibilityLabel={moreReactionsA11yText} style={styles.reactionCount}>
137
+ {reactionsCountText}
138
+ </Text>
139
+ ) : null}
126
140
  </ReactionListItemWrapper>
127
141
  );
128
142
  };
@@ -3,6 +3,7 @@ import { StyleSheet, Text } from 'react-native';
3
3
 
4
4
  import { ReactionListItemWrapper } from './ReactionListItemWrapper';
5
5
 
6
+ import { useA11yLabel } from '../../../../a11y/hooks/useA11yLabel';
6
7
  import { MessageContextValue } from '../../../../contexts/messageContext/MessageContext';
7
8
  import { MessagesContextValue } from '../../../../contexts/messagesContext/MessagesContext';
8
9
  import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
@@ -13,6 +14,7 @@ import type { IconProps } from '../../../../icons/utils/base';
13
14
 
14
15
  import { primitives } from '../../../../theme';
15
16
  import type { ReactionData } from '../../../../utils/utils';
17
+ import { HiddenA11yText } from '../../../Accessibility/HiddenA11yText';
16
18
  import { ReactionSummary } from '../../hooks/useProcessReactions';
17
19
 
18
20
  type Props = Pick<IconProps, 'pathFill' | 'style'> & {
@@ -66,12 +68,15 @@ export const ReactionListItem = (props: ReactionListItemProps) => {
66
68
  },
67
69
  } = useTheme();
68
70
  const styles = useStyles();
71
+ const youReacted = useA11yLabel('a11y/you reacted');
69
72
 
70
73
  return (
71
74
  <ReactionListItemWrapper
72
- accessibilityLabel='Reaction List Item'
75
+ accessibilityRole='button'
76
+ accessibilityState={{ selected }}
73
77
  disabled={preventPress}
74
78
  key={reaction.type}
79
+ testID='reaction-list-item'
75
80
  onLongPress={(event) => {
76
81
  if (onLongPress) {
77
82
  onLongPress({
@@ -121,6 +126,7 @@ export const ReactionListItem = (props: ReactionListItemProps) => {
121
126
  type={reaction.type}
122
127
  />
123
128
  {showCount ? <Text style={styles.reactionCount}>{reaction.count}</Text> : null}
129
+ {selected ? <HiddenA11yText label={youReacted} /> : null}
124
130
  </ReactionListItemWrapper>
125
131
  );
126
132
  };