stream-chat-react-native-core 9.2.0-beta.1 → 9.2.0-beta.2

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 (279) hide show
  1. package/lib/commonjs/a11y/hooks/useA11yLabel.js +4 -3
  2. package/lib/commonjs/a11y/hooks/useA11yLabel.js.map +1 -1
  3. package/lib/commonjs/a11y/hooks/useAccessibilityActivateAction.js +25 -0
  4. package/lib/commonjs/a11y/hooks/useAccessibilityActivateAction.js.map +1 -0
  5. package/lib/commonjs/a11y/index.js +11 -0
  6. package/lib/commonjs/a11y/index.js.map +1 -1
  7. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +20 -0
  8. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  9. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js +1 -0
  10. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js.map +1 -1
  11. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js +19 -2
  12. package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js.map +1 -1
  13. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerContent.js +2 -1
  14. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerContent.js.map +1 -1
  15. package/lib/commonjs/components/AttachmentPicker/components/AttachmentTypePickerButton.js +9 -1
  16. package/lib/commonjs/components/AttachmentPicker/components/AttachmentTypePickerButton.js.map +1 -1
  17. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +2 -2
  18. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  19. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +1 -1
  20. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  21. package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +1 -1
  22. package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
  23. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js +16 -4
  24. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js.map +1 -1
  25. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js +3 -0
  26. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
  27. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +5 -0
  28. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -1
  29. package/lib/commonjs/components/MessageInput/components/InputButtons/AttachButton.js +12 -3
  30. package/lib/commonjs/components/MessageInput/components/InputButtons/AttachButton.js.map +1 -1
  31. package/lib/commonjs/components/MessageInput/components/OutputButtons/EditButton.js +1 -0
  32. package/lib/commonjs/components/MessageInput/components/OutputButtons/EditButton.js.map +1 -1
  33. package/lib/commonjs/components/MessageInput/components/OutputButtons/SendButton.js +1 -0
  34. package/lib/commonjs/components/MessageInput/components/OutputButtons/SendButton.js.map +1 -1
  35. package/lib/commonjs/components/MessageList/MessageFlashList.js +19 -2
  36. package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
  37. package/lib/commonjs/components/MessageList/MessageList.js +19 -2
  38. package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
  39. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js +12 -6
  40. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js.map +1 -1
  41. package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js +1 -0
  42. package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js.map +1 -1
  43. package/lib/commonjs/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js +47 -0
  44. package/lib/commonjs/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js.map +1 -0
  45. package/lib/commonjs/components/MessageMenu/MessageActionListItem.js +12 -4
  46. package/lib/commonjs/components/MessageMenu/MessageActionListItem.js.map +1 -1
  47. package/lib/commonjs/components/MessageMenu/MessageReactionPicker.js +1 -0
  48. package/lib/commonjs/components/MessageMenu/MessageReactionPicker.js.map +1 -1
  49. package/lib/commonjs/components/MessageMenu/ReactionButton.js +9 -6
  50. package/lib/commonjs/components/MessageMenu/ReactionButton.js.map +1 -1
  51. package/lib/commonjs/components/Poll/components/CreatePollHeader.js +2 -0
  52. package/lib/commonjs/components/Poll/components/CreatePollHeader.js.map +1 -1
  53. package/lib/commonjs/components/Poll/components/MultipleVotesSettings.js +2 -0
  54. package/lib/commonjs/components/Poll/components/MultipleVotesSettings.js.map +1 -1
  55. package/lib/commonjs/components/Poll/components/PollModalHeader.js +1 -0
  56. package/lib/commonjs/components/Poll/components/PollModalHeader.js.map +1 -1
  57. package/lib/commonjs/components/Reply/Reply.js +1 -0
  58. package/lib/commonjs/components/Reply/Reply.js.map +1 -1
  59. package/lib/commonjs/components/ui/Avatar/Avatar.js +6 -3
  60. package/lib/commonjs/components/ui/Avatar/Avatar.js.map +1 -1
  61. package/lib/commonjs/components/ui/Button/Button.js +16 -3
  62. package/lib/commonjs/components/ui/Button/Button.js.map +1 -1
  63. package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js +21 -1
  64. package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
  65. package/lib/commonjs/i18n/en.json +35 -1
  66. package/lib/commonjs/i18n/es.json +35 -1
  67. package/lib/commonjs/i18n/fr.json +35 -1
  68. package/lib/commonjs/i18n/he.json +35 -1
  69. package/lib/commonjs/i18n/hi.json +35 -1
  70. package/lib/commonjs/i18n/it.json +35 -1
  71. package/lib/commonjs/i18n/ja.json +35 -1
  72. package/lib/commonjs/i18n/ko.json +35 -1
  73. package/lib/commonjs/i18n/nl.json +35 -1
  74. package/lib/commonjs/i18n/pt-br.json +35 -1
  75. package/lib/commonjs/i18n/ru.json +35 -1
  76. package/lib/commonjs/i18n/tr.json +35 -1
  77. package/lib/commonjs/mock-builders/DB/mock.js +3 -1
  78. package/lib/commonjs/mock-builders/DB/mock.js.map +1 -1
  79. package/lib/commonjs/test-utils/BetterSqlite.js +3 -2
  80. package/lib/commonjs/test-utils/BetterSqlite.js.map +1 -1
  81. package/lib/commonjs/version.json +1 -1
  82. package/lib/module/a11y/hooks/useA11yLabel.js +4 -3
  83. package/lib/module/a11y/hooks/useA11yLabel.js.map +1 -1
  84. package/lib/module/a11y/hooks/useAccessibilityActivateAction.js +25 -0
  85. package/lib/module/a11y/hooks/useAccessibilityActivateAction.js.map +1 -0
  86. package/lib/module/a11y/index.js +11 -0
  87. package/lib/module/a11y/index.js.map +1 -1
  88. package/lib/module/components/AttachmentPicker/AttachmentPicker.js +20 -0
  89. package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  90. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js +1 -0
  91. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js.map +1 -1
  92. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js +19 -2
  93. package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js.map +1 -1
  94. package/lib/module/components/AttachmentPicker/components/AttachmentPickerContent.js +2 -1
  95. package/lib/module/components/AttachmentPicker/components/AttachmentPickerContent.js.map +1 -1
  96. package/lib/module/components/AttachmentPicker/components/AttachmentTypePickerButton.js +9 -1
  97. package/lib/module/components/AttachmentPicker/components/AttachmentTypePickerButton.js.map +1 -1
  98. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +2 -2
  99. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  100. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +1 -1
  101. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  102. package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +1 -1
  103. package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
  104. package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js +16 -4
  105. package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js.map +1 -1
  106. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js +3 -0
  107. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
  108. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +5 -0
  109. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -1
  110. package/lib/module/components/MessageInput/components/InputButtons/AttachButton.js +12 -3
  111. package/lib/module/components/MessageInput/components/InputButtons/AttachButton.js.map +1 -1
  112. package/lib/module/components/MessageInput/components/OutputButtons/EditButton.js +1 -0
  113. package/lib/module/components/MessageInput/components/OutputButtons/EditButton.js.map +1 -1
  114. package/lib/module/components/MessageInput/components/OutputButtons/SendButton.js +1 -0
  115. package/lib/module/components/MessageInput/components/OutputButtons/SendButton.js.map +1 -1
  116. package/lib/module/components/MessageList/MessageFlashList.js +19 -2
  117. package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
  118. package/lib/module/components/MessageList/MessageList.js +19 -2
  119. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  120. package/lib/module/components/MessageList/ScrollToBottomButton.js +12 -6
  121. package/lib/module/components/MessageList/ScrollToBottomButton.js.map +1 -1
  122. package/lib/module/components/MessageList/UnreadMessagesNotification.js +1 -0
  123. package/lib/module/components/MessageList/UnreadMessagesNotification.js.map +1 -1
  124. package/lib/module/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js +47 -0
  125. package/lib/module/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js.map +1 -0
  126. package/lib/module/components/MessageMenu/MessageActionListItem.js +12 -4
  127. package/lib/module/components/MessageMenu/MessageActionListItem.js.map +1 -1
  128. package/lib/module/components/MessageMenu/MessageReactionPicker.js +1 -0
  129. package/lib/module/components/MessageMenu/MessageReactionPicker.js.map +1 -1
  130. package/lib/module/components/MessageMenu/ReactionButton.js +9 -6
  131. package/lib/module/components/MessageMenu/ReactionButton.js.map +1 -1
  132. package/lib/module/components/Poll/components/CreatePollHeader.js +2 -0
  133. package/lib/module/components/Poll/components/CreatePollHeader.js.map +1 -1
  134. package/lib/module/components/Poll/components/MultipleVotesSettings.js +2 -0
  135. package/lib/module/components/Poll/components/MultipleVotesSettings.js.map +1 -1
  136. package/lib/module/components/Poll/components/PollModalHeader.js +1 -0
  137. package/lib/module/components/Poll/components/PollModalHeader.js.map +1 -1
  138. package/lib/module/components/Reply/Reply.js +1 -0
  139. package/lib/module/components/Reply/Reply.js.map +1 -1
  140. package/lib/module/components/ui/Avatar/Avatar.js +6 -3
  141. package/lib/module/components/ui/Avatar/Avatar.js.map +1 -1
  142. package/lib/module/components/ui/Button/Button.js +16 -3
  143. package/lib/module/components/ui/Button/Button.js.map +1 -1
  144. package/lib/module/contexts/accessibilityContext/AccessibilityContext.js +21 -1
  145. package/lib/module/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
  146. package/lib/module/i18n/en.json +35 -1
  147. package/lib/module/i18n/es.json +35 -1
  148. package/lib/module/i18n/fr.json +35 -1
  149. package/lib/module/i18n/he.json +35 -1
  150. package/lib/module/i18n/hi.json +35 -1
  151. package/lib/module/i18n/it.json +35 -1
  152. package/lib/module/i18n/ja.json +35 -1
  153. package/lib/module/i18n/ko.json +35 -1
  154. package/lib/module/i18n/nl.json +35 -1
  155. package/lib/module/i18n/pt-br.json +35 -1
  156. package/lib/module/i18n/ru.json +35 -1
  157. package/lib/module/i18n/tr.json +35 -1
  158. package/lib/module/mock-builders/DB/mock.js +3 -1
  159. package/lib/module/mock-builders/DB/mock.js.map +1 -1
  160. package/lib/module/test-utils/BetterSqlite.js +3 -2
  161. package/lib/module/test-utils/BetterSqlite.js.map +1 -1
  162. package/lib/module/version.json +1 -1
  163. package/lib/typescript/a11y/a11yUtils.d.ts +3 -3
  164. package/lib/typescript/a11y/a11yUtils.d.ts.map +1 -1
  165. package/lib/typescript/a11y/hooks/useA11yLabel.d.ts +2 -1
  166. package/lib/typescript/a11y/hooks/useA11yLabel.d.ts.map +1 -1
  167. package/lib/typescript/a11y/hooks/useAccessibilityActivateAction.d.ts +17 -0
  168. package/lib/typescript/a11y/hooks/useAccessibilityActivateAction.d.ts.map +1 -0
  169. package/lib/typescript/a11y/index.d.ts +1 -0
  170. package/lib/typescript/a11y/index.d.ts.map +1 -1
  171. package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts.map +1 -1
  172. package/lib/typescript/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.d.ts.map +1 -1
  173. package/lib/typescript/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.d.ts.map +1 -1
  174. package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerContent.d.ts.map +1 -1
  175. package/lib/typescript/components/AttachmentPicker/components/AttachmentTypePickerButton.d.ts +2 -1
  176. package/lib/typescript/components/AttachmentPicker/components/AttachmentTypePickerButton.d.ts.map +1 -1
  177. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.d.ts +5 -2
  178. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.d.ts.map +1 -1
  179. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecorder.d.ts.map +1 -1
  180. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingButton.d.ts.map +1 -1
  181. package/lib/typescript/components/MessageInput/components/InputButtons/AttachButton.d.ts +1 -0
  182. package/lib/typescript/components/MessageInput/components/InputButtons/AttachButton.d.ts.map +1 -1
  183. package/lib/typescript/components/MessageInput/components/OutputButtons/EditButton.d.ts.map +1 -1
  184. package/lib/typescript/components/MessageInput/components/OutputButtons/SendButton.d.ts.map +1 -1
  185. package/lib/typescript/components/MessageList/MessageFlashList.d.ts.map +1 -1
  186. package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
  187. package/lib/typescript/components/MessageList/ScrollToBottomButton.d.ts +2 -0
  188. package/lib/typescript/components/MessageList/ScrollToBottomButton.d.ts.map +1 -1
  189. package/lib/typescript/components/MessageList/UnreadMessagesNotification.d.ts.map +1 -1
  190. package/lib/typescript/components/MessageList/hooks/useScrollToBottomAccessibilityAction.d.ts +20 -0
  191. package/lib/typescript/components/MessageList/hooks/useScrollToBottomAccessibilityAction.d.ts.map +1 -0
  192. package/lib/typescript/components/MessageMenu/MessageActionListItem.d.ts.map +1 -1
  193. package/lib/typescript/components/MessageMenu/MessageReactionPicker.d.ts.map +1 -1
  194. package/lib/typescript/components/MessageMenu/ReactionButton.d.ts.map +1 -1
  195. package/lib/typescript/components/Poll/components/CreatePollHeader.d.ts.map +1 -1
  196. package/lib/typescript/components/Poll/components/MultipleVotesSettings.d.ts.map +1 -1
  197. package/lib/typescript/components/Poll/components/PollModalHeader.d.ts.map +1 -1
  198. package/lib/typescript/components/Reply/Reply.d.ts.map +1 -1
  199. package/lib/typescript/components/ui/Avatar/Avatar.d.ts.map +1 -1
  200. package/lib/typescript/components/ui/Button/Button.d.ts +10 -1
  201. package/lib/typescript/components/ui/Button/Button.d.ts.map +1 -1
  202. package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts +1 -1
  203. package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts.map +1 -1
  204. package/lib/typescript/i18n/en.json +35 -1
  205. package/lib/typescript/i18n/es.json +35 -1
  206. package/lib/typescript/i18n/fr.json +35 -1
  207. package/lib/typescript/i18n/he.json +35 -1
  208. package/lib/typescript/i18n/hi.json +35 -1
  209. package/lib/typescript/i18n/it.json +35 -1
  210. package/lib/typescript/i18n/ja.json +35 -1
  211. package/lib/typescript/i18n/ko.json +35 -1
  212. package/lib/typescript/i18n/nl.json +35 -1
  213. package/lib/typescript/i18n/pt-br.json +35 -1
  214. package/lib/typescript/i18n/ru.json +35 -1
  215. package/lib/typescript/i18n/tr.json +35 -1
  216. package/lib/typescript/test-utils/BetterSqlite.d.ts.map +1 -1
  217. package/lib/typescript/utils/i18n/Streami18n.d.ts +34 -0
  218. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  219. package/package.json +1 -1
  220. package/src/__tests__/offline-support/offline-feature.tsx +40 -34
  221. package/src/a11y/a11yUtils.ts +2 -2
  222. package/src/a11y/hooks/useA11yLabel.ts +7 -4
  223. package/src/a11y/hooks/useAccessibilityActivateAction.ts +44 -0
  224. package/src/a11y/index.ts +1 -0
  225. package/src/components/AttachmentPicker/AttachmentPicker.tsx +23 -1
  226. package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.tsx +1 -0
  227. package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx +15 -2
  228. package/src/components/AttachmentPicker/components/AttachmentPickerContent.tsx +1 -0
  229. package/src/components/AttachmentPicker/components/AttachmentTypePickerButton.tsx +9 -0
  230. package/src/components/ChannelList/__tests__/ChannelListView.test.tsx +16 -5
  231. package/src/components/ImageGallery/__tests__/ImageGalleryFooter.test.tsx +9 -3
  232. package/src/components/ImageGallery/__tests__/ImageGalleryHeader.test.tsx +4 -1
  233. package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +2 -2
  234. package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +1 -1
  235. package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +1 -1
  236. package/src/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.tsx +18 -2
  237. package/src/components/MessageInput/components/AudioRecorder/AudioRecorder.tsx +3 -0
  238. package/src/components/MessageInput/components/AudioRecorder/AudioRecordingButton.tsx +8 -1
  239. package/src/components/MessageInput/components/InputButtons/AttachButton.tsx +13 -3
  240. package/src/components/MessageInput/components/OutputButtons/EditButton.tsx +1 -0
  241. package/src/components/MessageInput/components/OutputButtons/SendButton.tsx +1 -0
  242. package/src/components/MessageList/MessageFlashList.tsx +23 -2
  243. package/src/components/MessageList/MessageList.tsx +23 -2
  244. package/src/components/MessageList/ScrollToBottomButton.tsx +18 -6
  245. package/src/components/MessageList/UnreadMessagesNotification.tsx +1 -0
  246. package/src/components/MessageList/__tests__/MessageList.test.tsx +186 -0
  247. package/src/components/MessageList/__tests__/ScrollToBottomButton.test.tsx +2 -2
  248. package/src/components/MessageList/__tests__/__snapshots__/ScrollToBottomButton.test.tsx.snap +2 -0
  249. package/src/components/MessageList/hooks/useScrollToBottomAccessibilityAction.ts +74 -0
  250. package/src/components/MessageMenu/MessageActionListItem.tsx +10 -4
  251. package/src/components/MessageMenu/MessageReactionPicker.tsx +1 -0
  252. package/src/components/MessageMenu/ReactionButton.tsx +7 -9
  253. package/src/components/MessageMenu/__tests__/MessageReactionPicker.test.tsx +13 -15
  254. package/src/components/MessageMenu/__tests__/MessageUserReactions.test.tsx +20 -18
  255. package/src/components/MessageMenu/__tests__/ReactionButton.test.tsx +18 -5
  256. package/src/components/Poll/components/CreatePollHeader.tsx +2 -0
  257. package/src/components/Poll/components/MultipleVotesSettings.tsx +2 -0
  258. package/src/components/Poll/components/PollModalHeader.tsx +1 -0
  259. package/src/components/Reply/Reply.tsx +4 -1
  260. package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +3 -0
  261. package/src/components/ui/Avatar/Avatar.tsx +2 -1
  262. package/src/components/ui/Button/Button.tsx +26 -0
  263. package/src/components/ui/Button/__tests__/Button.test.tsx +44 -0
  264. package/src/contexts/accessibilityContext/AccessibilityContext.tsx +35 -1
  265. package/src/i18n/en.json +35 -1
  266. package/src/i18n/es.json +35 -1
  267. package/src/i18n/fr.json +35 -1
  268. package/src/i18n/he.json +35 -1
  269. package/src/i18n/hi.json +35 -1
  270. package/src/i18n/it.json +35 -1
  271. package/src/i18n/ja.json +35 -1
  272. package/src/i18n/ko.json +35 -1
  273. package/src/i18n/nl.json +35 -1
  274. package/src/i18n/pt-br.json +35 -1
  275. package/src/i18n/ru.json +35 -1
  276. package/src/i18n/tr.json +35 -1
  277. package/src/mock-builders/DB/mock.ts +2 -1
  278. package/src/test-utils/BetterSqlite.ts +3 -1
  279. package/src/version.json +1 -1
@@ -14,6 +14,7 @@ import type { FlashListProps, FlashListRef } from '@shopify/flash-list';
14
14
  import type { Channel, Event, LocalMessage, MessageResponse } from 'stream-chat';
15
15
 
16
16
  import { useMessageList } from './hooks/useMessageList';
17
+ import { useScrollToBottomAccessibilityAction } from './hooks/useScrollToBottomAccessibilityAction';
17
18
  import { useShouldScrollToRecentOnNewOwnMessage } from './hooks/useShouldScrollToRecentOnNewOwnMessage';
18
19
  import { useTypingUsers } from './hooks/useTypingUsers';
19
20
  import { InlineLoadingMoreIndicator } from './InlineLoadingMoreIndicator';
@@ -920,6 +921,19 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
920
921
  });
921
922
  });
922
923
 
924
+ const scrollToBottomUnreadCount =
925
+ scrollToBottomButtonVisible && !threadList ? channel?.countUnread() : undefined;
926
+ const {
927
+ accessibilityActions: messageListAccessibilityActions,
928
+ onAccessibilityAction: messageListOnAccessibilityAction,
929
+ } = useScrollToBottomAccessibilityAction({
930
+ accessibilityActions: additionalFlashListProps?.accessibilityActions,
931
+ onAccessibilityAction: additionalFlashListProps?.onAccessibilityAction,
932
+ onScrollToBottom: goToNewMessages,
933
+ unreadCount: scrollToBottomUnreadCount,
934
+ visible: scrollToBottomButtonVisible,
935
+ });
936
+
923
937
  const dismissImagePicker = useStableCallback(() => {
924
938
  if (attachmentPickerStore.state.getLatestValue().selectedPicker) {
925
939
  attachmentPickerStore.setSelectedPicker(undefined);
@@ -1072,10 +1086,17 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
1072
1086
  testID='message-flash-list'
1073
1087
  viewabilityConfig={flatListViewabilityConfig}
1074
1088
  {...additionalFlashListPropsExcludingStyle}
1089
+ accessibilityActions={messageListAccessibilityActions}
1090
+ onAccessibilityAction={messageListOnAccessibilityAction}
1075
1091
  />
1076
1092
  </MessageListItemProvider>
1077
1093
  )}
1078
- <View style={styles.stickyHeaderContainer}>
1094
+ <View
1095
+ accessibilityElementsHidden
1096
+ accessible={false}
1097
+ importantForAccessibility='no-hide-descendants'
1098
+ style={styles.stickyHeaderContainer}
1099
+ >
1079
1100
  {messageListLengthAfterUpdate && StickyHeader ? (
1080
1101
  <StickyHeader date={stickyHeaderDate} />
1081
1102
  ) : null}
@@ -1094,7 +1115,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
1094
1115
  <ScrollToBottomButton
1095
1116
  onPress={goToNewMessages}
1096
1117
  showNotification={scrollToBottomButtonVisible}
1097
- unreadCount={threadList ? 0 : channel?.countUnread()}
1118
+ unreadCount={scrollToBottomUnreadCount}
1098
1119
  />
1099
1120
  </Animated.View>
1100
1121
  <NetworkDownIndicator />
@@ -18,6 +18,7 @@ import debounce from 'lodash/debounce';
18
18
  import type { Channel, Event, LocalMessage, MessageResponse } from 'stream-chat';
19
19
 
20
20
  import { useMessageList } from './hooks/useMessageList';
21
+ import { useScrollToBottomAccessibilityAction } from './hooks/useScrollToBottomAccessibilityAction';
21
22
  import { useShouldScrollToRecentOnNewOwnMessage } from './hooks/useShouldScrollToRecentOnNewOwnMessage';
22
23
 
23
24
  import { InlineLoadingMoreIndicator } from './InlineLoadingMoreIndicator';
@@ -1046,6 +1047,19 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
1046
1047
  });
1047
1048
  });
1048
1049
 
1050
+ const scrollToBottomUnreadCount =
1051
+ scrollToBottomButtonVisible && !threadList ? channel?.countUnread() : undefined;
1052
+ const {
1053
+ accessibilityActions: messageListAccessibilityActions,
1054
+ onAccessibilityAction: messageListOnAccessibilityAction,
1055
+ } = useScrollToBottomAccessibilityAction({
1056
+ accessibilityActions: additionalFlatListProps?.accessibilityActions,
1057
+ onAccessibilityAction: additionalFlatListProps?.onAccessibilityAction,
1058
+ onScrollToBottom: goToNewMessages,
1059
+ unreadCount: scrollToBottomUnreadCount,
1060
+ visible: scrollToBottomButtonVisible,
1061
+ });
1062
+
1049
1063
  const scrollToIndexFailedRetryCountRef = useRef<number>(0);
1050
1064
  const failScrollTimeoutId = useRef<ReturnType<typeof setTimeout>>(undefined);
1051
1065
  const onScrollToIndexFailedRef = useRef<
@@ -1298,10 +1312,17 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
1298
1312
  testID='message-flat-list'
1299
1313
  viewabilityConfig={flatListViewabilityConfig}
1300
1314
  {...additionalFlatListPropsExcludingStyle}
1315
+ accessibilityActions={messageListAccessibilityActions}
1316
+ onAccessibilityAction={messageListOnAccessibilityAction}
1301
1317
  />
1302
1318
  </MessageListItemProvider>
1303
1319
  )}
1304
- <View style={styles.stickyHeaderContainer}>
1320
+ <View
1321
+ accessibilityElementsHidden
1322
+ accessible={false}
1323
+ importantForAccessibility='no-hide-descendants'
1324
+ style={styles.stickyHeaderContainer}
1325
+ >
1305
1326
  {messageListLengthAfterUpdate && StickyHeader ? (
1306
1327
  <StickyHeader date={stickyHeaderDate} />
1307
1328
  ) : null}
@@ -1321,7 +1342,7 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
1321
1342
  <ScrollToBottomButton
1322
1343
  onPress={goToNewMessages}
1323
1344
  showNotification={scrollToBottomButtonVisible}
1324
- unreadCount={threadList ? 0 : channel?.countUnread()}
1345
+ unreadCount={scrollToBottomUnreadCount}
1325
1346
  />
1326
1347
  </Animated.View>
1327
1348
  ) : null}
@@ -3,13 +3,16 @@ import React from 'react';
3
3
  import { StyleSheet, View } from 'react-native';
4
4
  import Animated, { ZoomIn, ZoomOut } from 'react-native-reanimated';
5
5
 
6
- import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
7
6
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
8
7
  import { Down } from '../../icons/arrow-up';
9
8
  import { primitives } from '../../theme';
10
9
  import { BadgeNotification } from '../ui';
11
10
  import { Button } from '../ui/Button';
12
11
 
12
+ export const SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY = 'a11y/Scroll to bottom';
13
+ export const SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY =
14
+ 'a11y/Scroll to bottom, {{count}} new messages';
15
+
13
16
  export type ScrollToBottomButtonProps = {
14
17
  /** onPress handler */
15
18
  onPress: () => void;
@@ -23,9 +26,9 @@ export const ScrollToBottomButton = (props: ScrollToBottomButtonProps) => {
23
26
  const {
24
27
  theme: { semantics },
25
28
  } = useTheme();
26
- const a11yLabel = useA11yLabel(
27
- unreadCount ? 'a11y/Scroll to latest, {{count}} unread' : 'a11y/Scroll to latest',
28
- { count: unreadCount ?? 0 },
29
+ const accessibilityLabelParams = React.useMemo(
30
+ () => (unreadCount ? { count: unreadCount } : undefined),
31
+ [unreadCount],
29
32
  );
30
33
 
31
34
  if (!showNotification) {
@@ -47,7 +50,12 @@ export const ScrollToBottomButton = (props: ScrollToBottomButtonProps) => {
47
50
  ]}
48
51
  >
49
52
  <Button
50
- accessibilityLabel={a11yLabel}
53
+ accessibilityLabelKey={
54
+ unreadCount
55
+ ? SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY
56
+ : SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY
57
+ }
58
+ accessibilityLabelParams={accessibilityLabelParams}
51
59
  variant='secondary'
52
60
  type='outline'
53
61
  LeadingIcon={Down}
@@ -58,7 +66,11 @@ export const ScrollToBottomButton = (props: ScrollToBottomButtonProps) => {
58
66
  />
59
67
  </View>
60
68
 
61
- <View style={styles.unreadCountNotificationContainer}>
69
+ <View
70
+ accessibilityElementsHidden
71
+ importantForAccessibility='no-hide-descendants'
72
+ style={styles.unreadCountNotificationContainer}
73
+ >
62
74
  {unreadCount ? (
63
75
  <BadgeNotification count={unreadCount} size='xs' type='primary' testID='unread-count' />
64
76
  ) : null}
@@ -84,6 +84,7 @@ export const UnreadMessagesNotification = (props: UnreadMessagesNotificationProp
84
84
  </View>
85
85
  <View style={styles.rightButtonContainer}>
86
86
  <Button
87
+ accessibilityLabelKey='a11y/Dismiss unread messages'
87
88
  variant='secondary'
88
89
  type='ghost'
89
90
  iconOnly
@@ -20,6 +20,7 @@ import { channelInitialState } from '../../Channel/hooks/useChannelDataState';
20
20
  import * as MessageListPaginationHook from '../../Channel/hooks/useMessageListPagination';
21
21
  import { Chat } from '../../Chat/Chat';
22
22
 
23
+ import { SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME } from '../hooks/useScrollToBottomAccessibilityAction';
23
24
  import { MessageList } from '../MessageList';
24
25
 
25
26
  describe('MessageList', () => {
@@ -487,6 +488,49 @@ describe('MessageList pagination', () => {
487
488
  }));
488
489
  };
489
490
 
491
+ const renderMessageListForScrollToBottom = async ({
492
+ additionalFlatListProps,
493
+ accessibility = { enabled: true },
494
+ staleChannelState = false,
495
+ }: {
496
+ additionalFlatListProps?: React.ComponentProps<typeof MessageList>['additionalFlatListProps'];
497
+ accessibility?: React.ComponentProps<typeof OverlayProvider>['accessibility'];
498
+ staleChannelState?: boolean;
499
+ } = {}) => {
500
+ const user1 = generateUser();
501
+ const mockedChannel = generateChannelResponse({
502
+ members: [generateMember({ user: user1 })],
503
+ messages: Array.from({ length: 10 }, (_, i) => generateMessage({ text: `message-${i}` })),
504
+ });
505
+
506
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
507
+ useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
508
+ const channel = chatClient.channel('messaging', mockedChannel.channel.id);
509
+ await channel.watch();
510
+
511
+ if (staleChannelState) {
512
+ channel.state = {
513
+ ...channelInitialState,
514
+ latestMessages: [],
515
+ members: Object.fromEntries(
516
+ Array.from({ length: 10 }, (_, i) => [i, generateMember({ user_id: String(i) })]),
517
+ ),
518
+ messages: Array.from({ length: 10 }, (_, i) => generateMessage({ id: String(i) })),
519
+ messageSets: [{ isCurrent: true, isLatest: true }],
520
+ } as unknown as typeof channel.state;
521
+ }
522
+
523
+ return render(
524
+ <OverlayProvider accessibility={accessibility}>
525
+ <Chat client={chatClient}>
526
+ <Channel channel={channel}>
527
+ <MessageList additionalFlatListProps={additionalFlatListProps} />
528
+ </Channel>
529
+ </Chat>
530
+ </OverlayProvider>,
531
+ );
532
+ };
533
+
490
534
  it('should load more recent messages when the user scrolls to the start of the list', async () => {
491
535
  const user1 = generateUser();
492
536
  const mockedChannel = generateChannelResponse({
@@ -630,4 +674,146 @@ describe('MessageList pagination', () => {
630
674
  expect(loadLatestMessages).toHaveBeenCalledTimes(1);
631
675
  });
632
676
  });
677
+
678
+ it('should not expose the scroll to bottom accessibility action when hidden', async () => {
679
+ const { getByTestId, queryByTestId } = await renderMessageListForScrollToBottom();
680
+
681
+ await waitFor(() => {
682
+ expect(queryByTestId('scroll-to-bottom-button')).toBeFalsy();
683
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toBeUndefined();
684
+ });
685
+ });
686
+
687
+ it('should not expose the SDK scroll to bottom action when SDK accessibility is disabled', async () => {
688
+ const { getByTestId, queryByTestId } = await renderMessageListForScrollToBottom({
689
+ accessibility: { enabled: false },
690
+ staleChannelState: true,
691
+ });
692
+
693
+ act(() => {
694
+ fireEvent(getByTestId('message-flat-list'), 'scroll', {
695
+ nativeEvent: {
696
+ contentOffset: { y: 1900 },
697
+ contentSize: { height: 2000, width: 200 },
698
+ layoutMeasurement: { height: 400, width: 200 },
699
+ },
700
+ });
701
+ });
702
+
703
+ await waitFor(() => {
704
+ expect(queryByTestId('scroll-to-bottom-button')).toBeTruthy();
705
+ expect(getByTestId('message-flat-list').props.accessibilityActions ?? []).not.toEqual(
706
+ expect.arrayContaining([
707
+ expect.objectContaining({
708
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
709
+ }),
710
+ ]),
711
+ );
712
+ });
713
+ });
714
+
715
+ it('should preserve additional message list accessibility actions when scroll to bottom is hidden', async () => {
716
+ const { getByTestId, queryByTestId } = await renderMessageListForScrollToBottom({
717
+ additionalFlatListProps: {
718
+ accessibilityActions: [{ label: 'Custom action', name: 'customAction' }],
719
+ },
720
+ });
721
+
722
+ await waitFor(() => {
723
+ expect(queryByTestId('scroll-to-bottom-button')).toBeFalsy();
724
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toEqual([
725
+ { label: 'Custom action', name: 'customAction' },
726
+ ]);
727
+ });
728
+ });
729
+
730
+ it('should expose scroll to bottom as a message list accessibility action when visible', async () => {
731
+ const loadLatestMessages = jest.fn(() => Promise.resolve());
732
+ mockedHook({ loadLatestMessages });
733
+
734
+ const { getByTestId } = await renderMessageListForScrollToBottom({
735
+ staleChannelState: true,
736
+ });
737
+
738
+ act(() => {
739
+ fireEvent(getByTestId('message-flat-list'), 'scroll', {
740
+ nativeEvent: {
741
+ contentOffset: { y: 1900 },
742
+ contentSize: { height: 2000, width: 200 },
743
+ layoutMeasurement: { height: 400, width: 200 },
744
+ },
745
+ });
746
+ });
747
+
748
+ await waitFor(() => {
749
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toEqual(
750
+ expect.arrayContaining([
751
+ expect.objectContaining({
752
+ label: expect.stringContaining('Scroll to bottom'),
753
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
754
+ }),
755
+ ]),
756
+ );
757
+ });
758
+
759
+ await act(async () => {
760
+ await getByTestId('message-flat-list').props.onAccessibilityAction({
761
+ nativeEvent: { actionName: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME },
762
+ });
763
+ });
764
+
765
+ expect(loadLatestMessages).toHaveBeenCalledTimes(1);
766
+ });
767
+
768
+ it('should preserve additional message list accessibility actions', async () => {
769
+ const loadLatestMessages = jest.fn(() => Promise.resolve());
770
+ const onAccessibilityAction = jest.fn();
771
+ mockedHook({ loadLatestMessages });
772
+
773
+ const { getByTestId } = await renderMessageListForScrollToBottom({
774
+ additionalFlatListProps: {
775
+ accessibilityActions: [{ label: 'Custom action', name: 'customAction' }],
776
+ onAccessibilityAction,
777
+ },
778
+ staleChannelState: true,
779
+ });
780
+
781
+ act(() => {
782
+ fireEvent(getByTestId('message-flat-list'), 'scroll', {
783
+ nativeEvent: {
784
+ contentOffset: { y: 1900 },
785
+ contentSize: { height: 2000, width: 200 },
786
+ layoutMeasurement: { height: 400, width: 200 },
787
+ },
788
+ });
789
+ });
790
+
791
+ await waitFor(() => {
792
+ expect(getByTestId('message-flat-list').props.accessibilityActions).toEqual(
793
+ expect.arrayContaining([
794
+ { label: 'Custom action', name: 'customAction' },
795
+ expect.objectContaining({
796
+ label: expect.stringContaining('Scroll to bottom'),
797
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
798
+ }),
799
+ ]),
800
+ );
801
+ });
802
+
803
+ act(() => {
804
+ getByTestId('message-flat-list').props.onAccessibilityAction({
805
+ nativeEvent: { actionName: 'customAction' },
806
+ });
807
+ });
808
+ expect(onAccessibilityAction).toHaveBeenCalledTimes(1);
809
+
810
+ await act(async () => {
811
+ await getByTestId('message-flat-list').props.onAccessibilityAction({
812
+ nativeEvent: { actionName: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME },
813
+ });
814
+ });
815
+
816
+ expect(loadLatestMessages).toHaveBeenCalledTimes(1);
817
+ expect(onAccessibilityAction).toHaveBeenCalledTimes(1);
818
+ });
633
819
  });
@@ -75,8 +75,8 @@ describe('ScrollToBottomButton', () => {
75
75
  </ThemeProvider>,
76
76
  );
77
77
  await waitFor(() => {
78
- expect(getByTestId('unread-count')).toBeTruthy();
79
- expect(getByText('3')).toBeTruthy();
78
+ expect(getByTestId('unread-count', { includeHiddenElements: true })).toBeTruthy();
79
+ expect(getByText('3', { includeHiddenElements: true })).toBeTruthy();
80
80
  });
81
81
  });
82
82
 
@@ -186,6 +186,8 @@ exports[`ScrollToBottomButton should render the message notification and match s
186
186
  </View>
187
187
  </View>
188
188
  <View
189
+ accessibilityElementsHidden={true}
190
+ importantForAccessibility="no-hide-descendants"
189
191
  style={
190
192
  {
191
193
  "position": "absolute",
@@ -0,0 +1,74 @@
1
+ import { useContext, useMemo } from 'react';
2
+
3
+ import type { AccessibilityActionEvent, AccessibilityProps } from 'react-native';
4
+
5
+ import { mergeAccessibilityActions } from '../../../a11y/a11yUtils';
6
+ import { useAccessibilityContext } from '../../../contexts/accessibilityContext/AccessibilityContext';
7
+ import { TranslationContext } from '../../../contexts/translationContext/TranslationContext';
8
+ import { useStableCallback } from '../../../hooks';
9
+ import {
10
+ SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY,
11
+ SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY,
12
+ } from '../ScrollToBottomButton';
13
+
14
+ export const SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME = 'streamScrollToBottom';
15
+
16
+ type AccessibilityActions = AccessibilityProps['accessibilityActions'];
17
+ type OnAccessibilityAction = AccessibilityProps['onAccessibilityAction'];
18
+
19
+ type UseScrollToBottomAccessibilityActionParams = {
20
+ accessibilityActions?: AccessibilityActions;
21
+ onAccessibilityAction?: OnAccessibilityAction;
22
+ onScrollToBottom: () => Promise<void> | void;
23
+ unreadCount?: number;
24
+ visible: boolean;
25
+ };
26
+
27
+ export const useScrollToBottomAccessibilityAction = ({
28
+ accessibilityActions,
29
+ onAccessibilityAction,
30
+ onScrollToBottom,
31
+ unreadCount,
32
+ visible,
33
+ }: UseScrollToBottomAccessibilityActionParams) => {
34
+ const { enabled } = useAccessibilityContext();
35
+ const { t } = useContext(TranslationContext);
36
+
37
+ const scrollToBottomAccessibilityAction = useMemo(() => {
38
+ if (!enabled || !visible) {
39
+ return undefined;
40
+ }
41
+
42
+ return [
43
+ {
44
+ name: SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME,
45
+ label: unreadCount
46
+ ? t(SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY, { count: unreadCount })
47
+ : t(SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY),
48
+ },
49
+ ];
50
+ }, [enabled, t, unreadCount, visible]);
51
+
52
+ const mergedAccessibilityActions = useMemo(
53
+ () => mergeAccessibilityActions(accessibilityActions, scrollToBottomAccessibilityAction),
54
+ [accessibilityActions, scrollToBottomAccessibilityAction],
55
+ );
56
+
57
+ const handleAccessibilityAction = useStableCallback((event: AccessibilityActionEvent) => {
58
+ if (event.nativeEvent.actionName === SCROLL_TO_BOTTOM_ACCESSIBILITY_ACTION_NAME) {
59
+ return onScrollToBottom();
60
+ }
61
+
62
+ return onAccessibilityAction?.(event);
63
+ });
64
+
65
+ return {
66
+ accessibilityActions: mergedAccessibilityActions.length
67
+ ? mergedAccessibilityActions
68
+ : undefined,
69
+ onAccessibilityAction:
70
+ (enabled && visible) || onAccessibilityAction
71
+ ? handleAccessibilityAction
72
+ : onAccessibilityAction,
73
+ };
74
+ };
@@ -3,6 +3,7 @@ import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native';
3
3
 
4
4
  import { Pressable } from 'react-native-gesture-handler';
5
5
 
6
+ import { useAccessibilityActivateAction } from '../../a11y/hooks/useAccessibilityActivateAction';
6
7
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
7
8
  import { useStableCallback } from '../../hooks';
8
9
  import { closeOverlay, scheduleActionOnClose } from '../../state-store';
@@ -74,20 +75,25 @@ export const MessageActionListItem = (props: MessageActionListItemProps) => {
74
75
  closeOverlay();
75
76
  scheduleActionOnClose(() => action());
76
77
  });
78
+ const accessibilityLabel = `${actionType} action list item`;
79
+ const accessibilityActivateActionProps = useAccessibilityActivateAction({
80
+ onPress: onActionPress,
81
+ shouldHandleActivate: true,
82
+ });
77
83
 
78
84
  return (
79
85
  <Pressable
86
+ accessible
87
+ accessibilityLabel={accessibilityLabel}
80
88
  accessibilityRole='menuitem'
89
+ {...accessibilityActivateActionProps}
81
90
  onPress={onActionPress}
82
91
  style={({ pressed }) => [
83
92
  styles.buttonContainer,
84
93
  { backgroundColor: pressed ? semantics.backgroundUtilityPressed : 'transparent' },
85
94
  ]}
86
95
  >
87
- <View
88
- accessibilityLabel={`${actionType} action list item`}
89
- style={[styles.container, container]}
90
- >
96
+ <View style={[styles.container, container]}>
91
97
  <View style={iconTheme}>{icon}</View>
92
98
  <Text style={[styles.titleStyle, titleStyle, titleTheme]}>{title}</Text>
93
99
  </View>
@@ -115,6 +115,7 @@ export const EmojiViewerButton = ({
115
115
  <>
116
116
  <View style={[styles.emojiViewerButton, emojiViewerButton]}>
117
117
  <Button
118
+ accessibilityLabelKey='a11y/Open more reactions'
118
119
  variant='secondary'
119
120
  type='outline'
120
121
  size='sm'
@@ -1,7 +1,6 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
 
4
- import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
5
4
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
6
5
  import { IconProps } from '../../icons';
7
6
  import { Button, ButtonProps } from '../ui';
@@ -50,18 +49,17 @@ export const ReactionButton = (props: ReactionButtonProps) => {
50
49
  () => <Icon size={reactionIconSize ?? 24} />,
51
50
  [Icon, reactionIconSize],
52
51
  );
53
-
54
- const a11yLabel = useA11yLabel('a11y/Reaction {{emoji}} by {{count}} users', {
55
- count: count ?? '0',
56
- emoji: type,
57
- });
52
+ const selectedLabelState = selected ? 'selected' : 'unselected';
53
+ const accessibilityLabelParams = useMemo(
54
+ () => ({ selected: selectedLabelState, type }),
55
+ [selectedLabelState, type],
56
+ );
58
57
 
59
58
  return (
60
59
  <View style={styles.reactionButton}>
61
60
  <Button
62
- accessibilityLabel={
63
- a11yLabel ?? `reaction-button-${type}-${selected ? 'selected' : 'unselected'}`
64
- }
61
+ accessibilityLabelKey='a11y/reaction-button-{{type}}-{{selected}}'
62
+ accessibilityLabelParams={accessibilityLabelParams}
65
63
  variant={'secondary'}
66
64
  type={'outline'}
67
65
  iconOnly={!count}
@@ -80,12 +80,10 @@ describe('MessageReactionPicker', () => {
80
80
  });
81
81
 
82
82
  it('renders correctly with supported reactions', async () => {
83
- const { getAllByLabelText, getByLabelText } = renderComponent();
83
+ const { getAllByRole, getByLabelText } = renderComponent();
84
84
  await waitFor(() => {
85
85
  expect(getByLabelText('Reaction Selector on long pressing message')).toBeTruthy();
86
- expect(getAllByLabelText(/\breaction-button[^\s]+/)).toHaveLength(
87
- mockSupportedReactions.length,
88
- );
86
+ expect(getAllByRole('button')).toHaveLength(mockSupportedReactions.length + 1);
89
87
  });
90
88
  });
91
89
 
@@ -95,20 +93,20 @@ describe('MessageReactionPicker', () => {
95
93
  });
96
94
 
97
95
  it('marks own reactions as selected', async () => {
98
- const { getAllByLabelText } = renderComponent();
96
+ const { getAllByRole } = renderComponent();
99
97
 
100
98
  await waitFor(() => {
101
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
102
- expect(reactionButtons[0].props.accessibilityLabel).toBe('reaction-button-like-selected');
103
- expect(reactionButtons[1].props.accessibilityLabel).toBe('reaction-button-love-unselected');
99
+ const reactionButtons = getAllByRole('button');
100
+ expect(reactionButtons[0].props.accessibilityState.selected).toBe(true);
101
+ expect(reactionButtons[1].props.accessibilityState.selected).toBe(false);
104
102
  });
105
103
  });
106
104
 
107
105
  it('calls handleReaction and dismissOverlay when a reaction is pressed', async () => {
108
- const { getAllByLabelText } = renderComponent();
106
+ const { getAllByRole } = renderComponent();
109
107
 
110
108
  await waitFor(() => {
111
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
109
+ const reactionButtons = getAllByRole('button');
112
110
  fireEvent.press(reactionButtons[1]);
113
111
  expect(defaultProps.handleReaction).toHaveBeenCalledWith('love');
114
112
  expect(defaultProps.dismissOverlay).toHaveBeenCalled();
@@ -117,9 +115,9 @@ describe('MessageReactionPicker', () => {
117
115
  });
118
116
 
119
117
  it("doesn't call handleReaction when it's not provided", async () => {
120
- const { getAllByLabelText } = renderComponent({ handleReaction: undefined });
118
+ const { getAllByRole } = renderComponent({ handleReaction: undefined });
121
119
  await waitFor(() => {
122
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
120
+ const reactionButtons = getAllByRole('button');
123
121
 
124
122
  fireEvent.press(reactionButtons[1]);
125
123
 
@@ -132,11 +130,11 @@ describe('MessageReactionPicker', () => {
132
130
  { Icon: () => null, isMain: true, type: 'wow' },
133
131
  { Icon: () => null, isMain: true, type: 'haha' },
134
132
  ];
135
- const { getAllByLabelText } = renderComponent({ supportedReactions: customSupportedReactions });
133
+ const { getAllByRole } = renderComponent({ supportedReactions: customSupportedReactions });
136
134
 
137
135
  await waitFor(() => {
138
- const reactionButtons = getAllByLabelText(/\breaction-button[^\s]+/);
139
- expect(reactionButtons).toHaveLength(customSupportedReactions.length);
136
+ const reactionButtons = getAllByRole('button');
137
+ expect(reactionButtons).toHaveLength(customSupportedReactions.length + 1);
140
138
  });
141
139
  });
142
140
  });