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.
- package/lib/commonjs/a11y/hooks/useA11yLabel.js +4 -3
- package/lib/commonjs/a11y/hooks/useA11yLabel.js.map +1 -1
- package/lib/commonjs/a11y/hooks/useAccessibilityActivateAction.js +25 -0
- package/lib/commonjs/a11y/hooks/useAccessibilityActivateAction.js.map +1 -0
- package/lib/commonjs/a11y/index.js +11 -0
- package/lib/commonjs/a11y/index.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +20 -0
- package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js +1 -0
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js +19 -2
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerContent.js +2 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerContent.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentTypePickerButton.js +9 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentTypePickerButton.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +2 -2
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js +16 -4
- package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js +3 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +5 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/InputButtons/AttachButton.js +12 -3
- package/lib/commonjs/components/MessageInput/components/InputButtons/AttachButton.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/OutputButtons/EditButton.js +1 -0
- package/lib/commonjs/components/MessageInput/components/OutputButtons/EditButton.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/OutputButtons/SendButton.js +1 -0
- package/lib/commonjs/components/MessageInput/components/OutputButtons/SendButton.js.map +1 -1
- package/lib/commonjs/components/MessageList/MessageFlashList.js +19 -2
- package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
- package/lib/commonjs/components/MessageList/MessageList.js +19 -2
- package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
- package/lib/commonjs/components/MessageList/ScrollToBottomButton.js +12 -6
- package/lib/commonjs/components/MessageList/ScrollToBottomButton.js.map +1 -1
- package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js +1 -0
- package/lib/commonjs/components/MessageList/UnreadMessagesNotification.js.map +1 -1
- package/lib/commonjs/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js +47 -0
- package/lib/commonjs/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js.map +1 -0
- package/lib/commonjs/components/MessageMenu/MessageActionListItem.js +12 -4
- package/lib/commonjs/components/MessageMenu/MessageActionListItem.js.map +1 -1
- package/lib/commonjs/components/MessageMenu/MessageReactionPicker.js +1 -0
- package/lib/commonjs/components/MessageMenu/MessageReactionPicker.js.map +1 -1
- package/lib/commonjs/components/MessageMenu/ReactionButton.js +9 -6
- package/lib/commonjs/components/MessageMenu/ReactionButton.js.map +1 -1
- package/lib/commonjs/components/Poll/components/CreatePollHeader.js +2 -0
- package/lib/commonjs/components/Poll/components/CreatePollHeader.js.map +1 -1
- package/lib/commonjs/components/Poll/components/MultipleVotesSettings.js +2 -0
- package/lib/commonjs/components/Poll/components/MultipleVotesSettings.js.map +1 -1
- package/lib/commonjs/components/Poll/components/PollModalHeader.js +1 -0
- package/lib/commonjs/components/Poll/components/PollModalHeader.js.map +1 -1
- package/lib/commonjs/components/Reply/Reply.js +1 -0
- package/lib/commonjs/components/Reply/Reply.js.map +1 -1
- package/lib/commonjs/components/ui/Avatar/Avatar.js +6 -3
- package/lib/commonjs/components/ui/Avatar/Avatar.js.map +1 -1
- package/lib/commonjs/components/ui/Button/Button.js +16 -3
- package/lib/commonjs/components/ui/Button/Button.js.map +1 -1
- package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js +21 -1
- package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
- package/lib/commonjs/i18n/en.json +35 -1
- package/lib/commonjs/i18n/es.json +35 -1
- package/lib/commonjs/i18n/fr.json +35 -1
- package/lib/commonjs/i18n/he.json +35 -1
- package/lib/commonjs/i18n/hi.json +35 -1
- package/lib/commonjs/i18n/it.json +35 -1
- package/lib/commonjs/i18n/ja.json +35 -1
- package/lib/commonjs/i18n/ko.json +35 -1
- package/lib/commonjs/i18n/nl.json +35 -1
- package/lib/commonjs/i18n/pt-br.json +35 -1
- package/lib/commonjs/i18n/ru.json +35 -1
- package/lib/commonjs/i18n/tr.json +35 -1
- package/lib/commonjs/mock-builders/DB/mock.js +3 -1
- package/lib/commonjs/mock-builders/DB/mock.js.map +1 -1
- package/lib/commonjs/test-utils/BetterSqlite.js +3 -2
- package/lib/commonjs/test-utils/BetterSqlite.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/a11y/hooks/useA11yLabel.js +4 -3
- package/lib/module/a11y/hooks/useA11yLabel.js.map +1 -1
- package/lib/module/a11y/hooks/useAccessibilityActivateAction.js +25 -0
- package/lib/module/a11y/hooks/useAccessibilityActivateAction.js.map +1 -0
- package/lib/module/a11y/index.js +11 -0
- package/lib/module/a11y/index.js.map +1 -1
- package/lib/module/components/AttachmentPicker/AttachmentPicker.js +20 -0
- package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js +1 -0
- package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.js.map +1 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js +19 -2
- package/lib/module/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.js.map +1 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentPickerContent.js +2 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentPickerContent.js.map +1 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentTypePickerButton.js +9 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentTypePickerButton.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +2 -2
- package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
- package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js +16 -4
- package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.js.map +1 -1
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js +3 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +5 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -1
- package/lib/module/components/MessageInput/components/InputButtons/AttachButton.js +12 -3
- package/lib/module/components/MessageInput/components/InputButtons/AttachButton.js.map +1 -1
- package/lib/module/components/MessageInput/components/OutputButtons/EditButton.js +1 -0
- package/lib/module/components/MessageInput/components/OutputButtons/EditButton.js.map +1 -1
- package/lib/module/components/MessageInput/components/OutputButtons/SendButton.js +1 -0
- package/lib/module/components/MessageInput/components/OutputButtons/SendButton.js.map +1 -1
- package/lib/module/components/MessageList/MessageFlashList.js +19 -2
- package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
- package/lib/module/components/MessageList/MessageList.js +19 -2
- package/lib/module/components/MessageList/MessageList.js.map +1 -1
- package/lib/module/components/MessageList/ScrollToBottomButton.js +12 -6
- package/lib/module/components/MessageList/ScrollToBottomButton.js.map +1 -1
- package/lib/module/components/MessageList/UnreadMessagesNotification.js +1 -0
- package/lib/module/components/MessageList/UnreadMessagesNotification.js.map +1 -1
- package/lib/module/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js +47 -0
- package/lib/module/components/MessageList/hooks/useScrollToBottomAccessibilityAction.js.map +1 -0
- package/lib/module/components/MessageMenu/MessageActionListItem.js +12 -4
- package/lib/module/components/MessageMenu/MessageActionListItem.js.map +1 -1
- package/lib/module/components/MessageMenu/MessageReactionPicker.js +1 -0
- package/lib/module/components/MessageMenu/MessageReactionPicker.js.map +1 -1
- package/lib/module/components/MessageMenu/ReactionButton.js +9 -6
- package/lib/module/components/MessageMenu/ReactionButton.js.map +1 -1
- package/lib/module/components/Poll/components/CreatePollHeader.js +2 -0
- package/lib/module/components/Poll/components/CreatePollHeader.js.map +1 -1
- package/lib/module/components/Poll/components/MultipleVotesSettings.js +2 -0
- package/lib/module/components/Poll/components/MultipleVotesSettings.js.map +1 -1
- package/lib/module/components/Poll/components/PollModalHeader.js +1 -0
- package/lib/module/components/Poll/components/PollModalHeader.js.map +1 -1
- package/lib/module/components/Reply/Reply.js +1 -0
- package/lib/module/components/Reply/Reply.js.map +1 -1
- package/lib/module/components/ui/Avatar/Avatar.js +6 -3
- package/lib/module/components/ui/Avatar/Avatar.js.map +1 -1
- package/lib/module/components/ui/Button/Button.js +16 -3
- package/lib/module/components/ui/Button/Button.js.map +1 -1
- package/lib/module/contexts/accessibilityContext/AccessibilityContext.js +21 -1
- package/lib/module/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
- package/lib/module/i18n/en.json +35 -1
- package/lib/module/i18n/es.json +35 -1
- package/lib/module/i18n/fr.json +35 -1
- package/lib/module/i18n/he.json +35 -1
- package/lib/module/i18n/hi.json +35 -1
- package/lib/module/i18n/it.json +35 -1
- package/lib/module/i18n/ja.json +35 -1
- package/lib/module/i18n/ko.json +35 -1
- package/lib/module/i18n/nl.json +35 -1
- package/lib/module/i18n/pt-br.json +35 -1
- package/lib/module/i18n/ru.json +35 -1
- package/lib/module/i18n/tr.json +35 -1
- package/lib/module/mock-builders/DB/mock.js +3 -1
- package/lib/module/mock-builders/DB/mock.js.map +1 -1
- package/lib/module/test-utils/BetterSqlite.js +3 -2
- package/lib/module/test-utils/BetterSqlite.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/a11y/a11yUtils.d.ts +3 -3
- package/lib/typescript/a11y/a11yUtils.d.ts.map +1 -1
- package/lib/typescript/a11y/hooks/useA11yLabel.d.ts +2 -1
- package/lib/typescript/a11y/hooks/useA11yLabel.d.ts.map +1 -1
- package/lib/typescript/a11y/hooks/useAccessibilityActivateAction.d.ts +17 -0
- package/lib/typescript/a11y/hooks/useAccessibilityActivateAction.d.ts.map +1 -0
- package/lib/typescript/a11y/index.d.ts +1 -0
- package/lib/typescript/a11y/index.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerContent.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentTypePickerButton.d.ts +2 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentTypePickerButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.d.ts +5 -2
- package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecorder.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/InputButtons/AttachButton.d.ts +1 -0
- package/lib/typescript/components/MessageInput/components/InputButtons/AttachButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/OutputButtons/EditButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/OutputButtons/SendButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/MessageFlashList.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/ScrollToBottomButton.d.ts +2 -0
- package/lib/typescript/components/MessageList/ScrollToBottomButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/UnreadMessagesNotification.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/hooks/useScrollToBottomAccessibilityAction.d.ts +20 -0
- package/lib/typescript/components/MessageList/hooks/useScrollToBottomAccessibilityAction.d.ts.map +1 -0
- package/lib/typescript/components/MessageMenu/MessageActionListItem.d.ts.map +1 -1
- package/lib/typescript/components/MessageMenu/MessageReactionPicker.d.ts.map +1 -1
- package/lib/typescript/components/MessageMenu/ReactionButton.d.ts.map +1 -1
- package/lib/typescript/components/Poll/components/CreatePollHeader.d.ts.map +1 -1
- package/lib/typescript/components/Poll/components/MultipleVotesSettings.d.ts.map +1 -1
- package/lib/typescript/components/Poll/components/PollModalHeader.d.ts.map +1 -1
- package/lib/typescript/components/Reply/Reply.d.ts.map +1 -1
- package/lib/typescript/components/ui/Avatar/Avatar.d.ts.map +1 -1
- package/lib/typescript/components/ui/Button/Button.d.ts +10 -1
- package/lib/typescript/components/ui/Button/Button.d.ts.map +1 -1
- package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts +1 -1
- package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts.map +1 -1
- package/lib/typescript/i18n/en.json +35 -1
- package/lib/typescript/i18n/es.json +35 -1
- package/lib/typescript/i18n/fr.json +35 -1
- package/lib/typescript/i18n/he.json +35 -1
- package/lib/typescript/i18n/hi.json +35 -1
- package/lib/typescript/i18n/it.json +35 -1
- package/lib/typescript/i18n/ja.json +35 -1
- package/lib/typescript/i18n/ko.json +35 -1
- package/lib/typescript/i18n/nl.json +35 -1
- package/lib/typescript/i18n/pt-br.json +35 -1
- package/lib/typescript/i18n/ru.json +35 -1
- package/lib/typescript/i18n/tr.json +35 -1
- package/lib/typescript/test-utils/BetterSqlite.d.ts.map +1 -1
- package/lib/typescript/utils/i18n/Streami18n.d.ts +34 -0
- package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/offline-support/offline-feature.tsx +40 -34
- package/src/a11y/a11yUtils.ts +2 -2
- package/src/a11y/hooks/useA11yLabel.ts +7 -4
- package/src/a11y/hooks/useAccessibilityActivateAction.ts +44 -0
- package/src/a11y/index.ts +1 -0
- package/src/components/AttachmentPicker/AttachmentPicker.tsx +23 -1
- package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentMediaPicker.tsx +1 -0
- package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx +15 -2
- package/src/components/AttachmentPicker/components/AttachmentPickerContent.tsx +1 -0
- package/src/components/AttachmentPicker/components/AttachmentTypePickerButton.tsx +9 -0
- package/src/components/ChannelList/__tests__/ChannelListView.test.tsx +16 -5
- package/src/components/ImageGallery/__tests__/ImageGalleryFooter.test.tsx +9 -3
- package/src/components/ImageGallery/__tests__/ImageGalleryHeader.test.tsx +4 -1
- package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +2 -2
- package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +1 -1
- package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +1 -1
- package/src/components/MessageInput/components/AttachmentPreview/AttachmentRemoveControl.tsx +18 -2
- package/src/components/MessageInput/components/AudioRecorder/AudioRecorder.tsx +3 -0
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingButton.tsx +8 -1
- package/src/components/MessageInput/components/InputButtons/AttachButton.tsx +13 -3
- package/src/components/MessageInput/components/OutputButtons/EditButton.tsx +1 -0
- package/src/components/MessageInput/components/OutputButtons/SendButton.tsx +1 -0
- package/src/components/MessageList/MessageFlashList.tsx +23 -2
- package/src/components/MessageList/MessageList.tsx +23 -2
- package/src/components/MessageList/ScrollToBottomButton.tsx +18 -6
- package/src/components/MessageList/UnreadMessagesNotification.tsx +1 -0
- package/src/components/MessageList/__tests__/MessageList.test.tsx +186 -0
- package/src/components/MessageList/__tests__/ScrollToBottomButton.test.tsx +2 -2
- package/src/components/MessageList/__tests__/__snapshots__/ScrollToBottomButton.test.tsx.snap +2 -0
- package/src/components/MessageList/hooks/useScrollToBottomAccessibilityAction.ts +74 -0
- package/src/components/MessageMenu/MessageActionListItem.tsx +10 -4
- package/src/components/MessageMenu/MessageReactionPicker.tsx +1 -0
- package/src/components/MessageMenu/ReactionButton.tsx +7 -9
- package/src/components/MessageMenu/__tests__/MessageReactionPicker.test.tsx +13 -15
- package/src/components/MessageMenu/__tests__/MessageUserReactions.test.tsx +20 -18
- package/src/components/MessageMenu/__tests__/ReactionButton.test.tsx +18 -5
- package/src/components/Poll/components/CreatePollHeader.tsx +2 -0
- package/src/components/Poll/components/MultipleVotesSettings.tsx +2 -0
- package/src/components/Poll/components/PollModalHeader.tsx +1 -0
- package/src/components/Reply/Reply.tsx +4 -1
- package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +3 -0
- package/src/components/ui/Avatar/Avatar.tsx +2 -1
- package/src/components/ui/Button/Button.tsx +26 -0
- package/src/components/ui/Button/__tests__/Button.test.tsx +44 -0
- package/src/contexts/accessibilityContext/AccessibilityContext.tsx +35 -1
- package/src/i18n/en.json +35 -1
- package/src/i18n/es.json +35 -1
- package/src/i18n/fr.json +35 -1
- package/src/i18n/he.json +35 -1
- package/src/i18n/hi.json +35 -1
- package/src/i18n/it.json +35 -1
- package/src/i18n/ja.json +35 -1
- package/src/i18n/ko.json +35 -1
- package/src/i18n/nl.json +35 -1
- package/src/i18n/pt-br.json +35 -1
- package/src/i18n/ru.json +35 -1
- package/src/i18n/tr.json +35 -1
- package/src/mock-builders/DB/mock.ts +2 -1
- package/src/test-utils/BetterSqlite.ts +3 -1
- 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
|
|
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={
|
|
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
|
|
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={
|
|
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
|
|
27
|
-
unreadCount ?
|
|
28
|
-
|
|
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
|
-
|
|
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
|
|
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}
|
|
@@ -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
|
|
|
@@ -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>
|
|
@@ -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
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
63
|
-
|
|
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 {
|
|
83
|
+
const { getAllByRole, getByLabelText } = renderComponent();
|
|
84
84
|
await waitFor(() => {
|
|
85
85
|
expect(getByLabelText('Reaction Selector on long pressing message')).toBeTruthy();
|
|
86
|
-
expect(
|
|
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 {
|
|
96
|
+
const { getAllByRole } = renderComponent();
|
|
99
97
|
|
|
100
98
|
await waitFor(() => {
|
|
101
|
-
const reactionButtons =
|
|
102
|
-
expect(reactionButtons[0].props.
|
|
103
|
-
expect(reactionButtons[1].props.
|
|
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 {
|
|
106
|
+
const { getAllByRole } = renderComponent();
|
|
109
107
|
|
|
110
108
|
await waitFor(() => {
|
|
111
|
-
const reactionButtons =
|
|
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 {
|
|
118
|
+
const { getAllByRole } = renderComponent({ handleReaction: undefined });
|
|
121
119
|
await waitFor(() => {
|
|
122
|
-
const reactionButtons =
|
|
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 {
|
|
133
|
+
const { getAllByRole } = renderComponent({ supportedReactions: customSupportedReactions });
|
|
136
134
|
|
|
137
135
|
await waitFor(() => {
|
|
138
|
-
const reactionButtons =
|
|
139
|
-
expect(reactionButtons).toHaveLength(customSupportedReactions.length);
|
|
136
|
+
const reactionButtons = getAllByRole('button');
|
|
137
|
+
expect(reactionButtons).toHaveLength(customSupportedReactions.length + 1);
|
|
140
138
|
});
|
|
141
139
|
});
|
|
142
140
|
});
|