stream-chat-react-native-core 9.3.1-beta.6 → 9.3.1-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/a11y/hooks/useAnnounceOnShow.js +27 -0
- package/lib/commonjs/a11y/hooks/useAnnounceOnShow.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/Accessibility/CompositeAccessibilityProbe.js +29 -0
- package/lib/commonjs/components/Accessibility/CompositeAccessibilityProbe.js.map +1 -0
- package/lib/commonjs/components/Accessibility/HiddenA11yText.js +30 -0
- package/lib/commonjs/components/Accessibility/HiddenA11yText.js.map +1 -0
- package/lib/commonjs/components/Accessibility/OverlayA11yShield.js +37 -0
- package/lib/commonjs/components/Accessibility/OverlayA11yShield.js.map +1 -0
- package/lib/commonjs/components/Accessibility/index.js +22 -0
- package/lib/commonjs/components/Accessibility/index.js.map +1 -1
- package/lib/commonjs/components/Attachment/Gallery.js +10 -0
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +31 -29
- package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewMutedStatus.js +11 -5
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewMutedStatus.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewStatus.js +18 -2
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewStatus.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewUnreadCount.js +8 -2
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewUnreadCount.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js +3 -0
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/ImageGallery.js +56 -1
- package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/Headers/MessageReminderHeader.js +2 -0
- package/lib/commonjs/components/Message/MessageItemView/Headers/MessageReminderHeader.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/Headers/SentToChannelHeader.js +2 -0
- package/lib/commonjs/components/Message/MessageItemView/Headers/SentToChannelHeader.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageContent.js +26 -4
- package/lib/commonjs/components/Message/MessageItemView/MessageContent.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageFooter.js +2 -0
- package/lib/commonjs/components/Message/MessageItemView/MessageFooter.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageReplies.js +7 -3
- package/lib/commonjs/components/Message/MessageItemView/MessageReplies.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageRepliesAvatars.js +2 -0
- package/lib/commonjs/components/Message/MessageItemView/MessageRepliesAvatars.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageStatus.js +35 -30
- package/lib/commonjs/components/Message/MessageItemView/MessageStatus.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js +16 -6
- package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListClustered.js +19 -6
- package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListClustered.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListItem.js +10 -1
- package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListItem.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +6 -1
- package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js +8 -0
- package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
- package/lib/commonjs/components/MessageList/InlineDateSeparator.js +8 -1
- package/lib/commonjs/components/MessageList/InlineDateSeparator.js.map +1 -1
- package/lib/commonjs/components/MessageMenu/ReactionButton.js +0 -7
- package/lib/commonjs/components/MessageMenu/ReactionButton.js.map +1 -1
- package/lib/commonjs/components/Poll/Poll.js +2 -17
- package/lib/commonjs/components/Poll/Poll.js.map +1 -1
- package/lib/commonjs/components/Poll/components/PollOption.js +6 -1
- package/lib/commonjs/components/Poll/components/PollOption.js.map +1 -1
- package/lib/commonjs/components/Reply/Reply.js +43 -6
- package/lib/commonjs/components/Reply/Reply.js.map +1 -1
- package/lib/commonjs/components/ui/Avatar/ChannelAvatar.js +17 -11
- package/lib/commonjs/components/ui/Avatar/ChannelAvatar.js.map +1 -1
- package/lib/commonjs/components/ui/Badge/BadgeNotification.js +3 -1
- package/lib/commonjs/components/ui/Badge/BadgeNotification.js.map +1 -1
- package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js +6 -22
- package/lib/commonjs/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
- package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
- package/lib/commonjs/contexts/overlayContext/MessageOverlayHostLayer.js +1 -0
- package/lib/commonjs/contexts/overlayContext/MessageOverlayHostLayer.js.map +1 -1
- package/lib/commonjs/contexts/overlayContext/OverlayProvider.js +4 -1
- package/lib/commonjs/contexts/overlayContext/OverlayProvider.js.map +1 -1
- package/lib/commonjs/i18n/ar.json +26 -8
- package/lib/commonjs/i18n/en.json +23 -5
- package/lib/commonjs/i18n/es.json +23 -5
- package/lib/commonjs/i18n/fr.json +23 -5
- package/lib/commonjs/i18n/he.json +23 -5
- package/lib/commonjs/i18n/hi.json +24 -6
- package/lib/commonjs/i18n/it.json +23 -5
- package/lib/commonjs/i18n/ja.json +23 -5
- package/lib/commonjs/i18n/ko.json +23 -5
- package/lib/commonjs/i18n/nl.json +24 -6
- package/lib/commonjs/i18n/pt-br.json +25 -7
- package/lib/commonjs/i18n/ru.json +23 -5
- package/lib/commonjs/i18n/tr.json +24 -6
- package/lib/commonjs/state-store/image-gallery-state-store.js +13 -0
- package/lib/commonjs/state-store/image-gallery-state-store.js.map +1 -1
- package/lib/commonjs/utils/i18n/getDateString.js +26 -1
- package/lib/commonjs/utils/i18n/getDateString.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/a11y/hooks/useAnnounceOnShow.js +27 -0
- package/lib/module/a11y/hooks/useAnnounceOnShow.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/Accessibility/CompositeAccessibilityProbe.js +29 -0
- package/lib/module/components/Accessibility/CompositeAccessibilityProbe.js.map +1 -0
- package/lib/module/components/Accessibility/HiddenA11yText.js +30 -0
- package/lib/module/components/Accessibility/HiddenA11yText.js.map +1 -0
- package/lib/module/components/Accessibility/OverlayA11yShield.js +37 -0
- package/lib/module/components/Accessibility/OverlayA11yShield.js.map +1 -0
- package/lib/module/components/Accessibility/index.js +22 -0
- package/lib/module/components/Accessibility/index.js.map +1 -1
- package/lib/module/components/Attachment/Gallery.js +10 -0
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +31 -29
- package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewMutedStatus.js +11 -5
- package/lib/module/components/ChannelPreview/ChannelPreviewMutedStatus.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewStatus.js +18 -2
- package/lib/module/components/ChannelPreview/ChannelPreviewStatus.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewUnreadCount.js +8 -2
- package/lib/module/components/ChannelPreview/ChannelPreviewUnreadCount.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewView.js +3 -0
- package/lib/module/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
- package/lib/module/components/ImageGallery/ImageGallery.js +56 -1
- package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/Headers/MessageReminderHeader.js +2 -0
- package/lib/module/components/Message/MessageItemView/Headers/MessageReminderHeader.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/Headers/SentToChannelHeader.js +2 -0
- package/lib/module/components/Message/MessageItemView/Headers/SentToChannelHeader.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageContent.js +26 -4
- package/lib/module/components/Message/MessageItemView/MessageContent.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageFooter.js +2 -0
- package/lib/module/components/Message/MessageItemView/MessageFooter.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageReplies.js +7 -3
- package/lib/module/components/Message/MessageItemView/MessageReplies.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageRepliesAvatars.js +2 -0
- package/lib/module/components/Message/MessageItemView/MessageRepliesAvatars.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageStatus.js +35 -30
- package/lib/module/components/Message/MessageItemView/MessageStatus.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageTextContainer.js +16 -6
- package/lib/module/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListClustered.js +19 -6
- package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListClustered.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListItem.js +10 -1
- package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListItem.js.map +1 -1
- package/lib/module/components/Message/hooks/useCreateMessageContext.js +6 -1
- package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
- package/lib/module/components/Message/hooks/useMessageActionHandlers.js +8 -0
- package/lib/module/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
- package/lib/module/components/MessageList/InlineDateSeparator.js +8 -1
- package/lib/module/components/MessageList/InlineDateSeparator.js.map +1 -1
- package/lib/module/components/MessageMenu/ReactionButton.js +0 -7
- package/lib/module/components/MessageMenu/ReactionButton.js.map +1 -1
- package/lib/module/components/Poll/Poll.js +2 -17
- package/lib/module/components/Poll/Poll.js.map +1 -1
- package/lib/module/components/Poll/components/PollOption.js +6 -1
- package/lib/module/components/Poll/components/PollOption.js.map +1 -1
- package/lib/module/components/Reply/Reply.js +43 -6
- package/lib/module/components/Reply/Reply.js.map +1 -1
- package/lib/module/components/ui/Avatar/ChannelAvatar.js +17 -11
- package/lib/module/components/ui/Avatar/ChannelAvatar.js.map +1 -1
- package/lib/module/components/ui/Badge/BadgeNotification.js +3 -1
- package/lib/module/components/ui/Badge/BadgeNotification.js.map +1 -1
- package/lib/module/contexts/accessibilityContext/AccessibilityContext.js +6 -22
- package/lib/module/contexts/accessibilityContext/AccessibilityContext.js.map +1 -1
- package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
- package/lib/module/contexts/overlayContext/MessageOverlayHostLayer.js +1 -0
- package/lib/module/contexts/overlayContext/MessageOverlayHostLayer.js.map +1 -1
- package/lib/module/contexts/overlayContext/OverlayProvider.js +4 -1
- package/lib/module/contexts/overlayContext/OverlayProvider.js.map +1 -1
- package/lib/module/i18n/ar.json +26 -8
- package/lib/module/i18n/en.json +23 -5
- package/lib/module/i18n/es.json +23 -5
- package/lib/module/i18n/fr.json +23 -5
- package/lib/module/i18n/he.json +23 -5
- package/lib/module/i18n/hi.json +24 -6
- package/lib/module/i18n/it.json +23 -5
- package/lib/module/i18n/ja.json +23 -5
- package/lib/module/i18n/ko.json +23 -5
- package/lib/module/i18n/nl.json +24 -6
- package/lib/module/i18n/pt-br.json +25 -7
- package/lib/module/i18n/ru.json +23 -5
- package/lib/module/i18n/tr.json +24 -6
- package/lib/module/state-store/image-gallery-state-store.js +13 -0
- package/lib/module/state-store/image-gallery-state-store.js.map +1 -1
- package/lib/module/utils/i18n/getDateString.js +26 -1
- package/lib/module/utils/i18n/getDateString.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/a11y/hooks/useAnnounceOnShow.d.ts +21 -0
- package/lib/typescript/a11y/hooks/useAnnounceOnShow.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/Accessibility/CompositeAccessibilityProbe.d.ts +30 -0
- package/lib/typescript/components/Accessibility/CompositeAccessibilityProbe.d.ts.map +1 -0
- package/lib/typescript/components/Accessibility/HiddenA11yText.d.ts +25 -0
- package/lib/typescript/components/Accessibility/HiddenA11yText.d.ts.map +1 -0
- package/lib/typescript/components/Accessibility/OverlayA11yShield.d.ts +20 -0
- package/lib/typescript/components/Accessibility/OverlayA11yShield.d.ts.map +1 -0
- package/lib/typescript/components/Accessibility/index.d.ts +2 -0
- package/lib/typescript/components/Accessibility/index.d.ts.map +1 -1
- package/lib/typescript/components/Attachment/Gallery.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewMutedStatus.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewStatus.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewUnreadCount.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts.map +1 -1
- package/lib/typescript/components/ImageGallery/ImageGallery.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/Headers/MessageReminderHeader.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/Headers/SentToChannelHeader.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageContent.d.ts +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageContent.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageFooter.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageReplies.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageRepliesAvatars.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageStatus.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageTextContainer.d.ts +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageTextContainer.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/ReactionList/ReactionListClustered.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/ReactionList/ReactionListItem.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageOverlayWrapper.d.ts +1 -1
- package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts +1 -1
- package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts.map +1 -1
- package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/InlineDateSeparator.d.ts.map +1 -1
- package/lib/typescript/components/MessageMenu/ReactionButton.d.ts.map +1 -1
- package/lib/typescript/components/Poll/Poll.d.ts.map +1 -1
- package/lib/typescript/components/Poll/components/PollOption.d.ts.map +1 -1
- package/lib/typescript/components/Reply/Reply.d.ts.map +1 -1
- package/lib/typescript/components/ui/Avatar/ChannelAvatar.d.ts.map +1 -1
- package/lib/typescript/components/ui/Badge/BadgeNotification.d.ts +5 -0
- package/lib/typescript/components/ui/Badge/BadgeNotification.d.ts.map +1 -1
- package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts +32 -2
- package/lib/typescript/contexts/accessibilityContext/AccessibilityContext.d.ts.map +1 -1
- package/lib/typescript/contexts/messageContext/MessageContext.d.ts +8 -0
- package/lib/typescript/contexts/messageContext/MessageContext.d.ts.map +1 -1
- package/lib/typescript/contexts/overlayContext/MessageOverlayHostLayer.d.ts.map +1 -1
- package/lib/typescript/contexts/overlayContext/OverlayProvider.d.ts.map +1 -1
- package/lib/typescript/hooks/useTranslatedMessage.d.ts +1 -1
- package/lib/typescript/i18n/ar.json +26 -8
- package/lib/typescript/i18n/en.json +23 -5
- package/lib/typescript/i18n/es.json +23 -5
- package/lib/typescript/i18n/fr.json +23 -5
- package/lib/typescript/i18n/he.json +23 -5
- package/lib/typescript/i18n/hi.json +24 -6
- package/lib/typescript/i18n/it.json +23 -5
- package/lib/typescript/i18n/ja.json +23 -5
- package/lib/typescript/i18n/ko.json +23 -5
- package/lib/typescript/i18n/nl.json +24 -6
- package/lib/typescript/i18n/pt-br.json +25 -7
- package/lib/typescript/i18n/ru.json +23 -5
- package/lib/typescript/i18n/tr.json +24 -6
- package/lib/typescript/state-store/image-gallery-state-store.d.ts +5 -1
- package/lib/typescript/state-store/image-gallery-state-store.d.ts.map +1 -1
- package/lib/typescript/utils/i18n/Streami18n.d.ts +22 -4
- package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
- package/lib/typescript/utils/i18n/getDateString.d.ts +28 -0
- package/lib/typescript/utils/i18n/getDateString.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/a11y/hooks/useAnnounceOnShow.ts +44 -0
- package/src/a11y/index.ts +1 -0
- package/src/components/Accessibility/CompositeAccessibilityProbe.tsx +48 -0
- package/src/components/Accessibility/HiddenA11yText.tsx +49 -0
- package/src/components/Accessibility/OverlayA11yShield.tsx +49 -0
- package/src/components/Accessibility/__tests__/OverlayA11yShield.test.tsx +83 -0
- package/src/components/Accessibility/index.ts +2 -0
- package/src/components/Attachment/Gallery.tsx +14 -2
- package/src/components/Channel/__tests__/ownCapabilities.test.tsx +25 -2
- package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx +19 -16
- package/src/components/ChannelPreview/ChannelPreviewMutedStatus.tsx +8 -1
- package/src/components/ChannelPreview/ChannelPreviewStatus.tsx +26 -6
- package/src/components/ChannelPreview/ChannelPreviewUnreadCount.tsx +5 -1
- package/src/components/ChannelPreview/ChannelPreviewView.tsx +3 -0
- package/src/components/ImageGallery/ImageGallery.tsx +82 -4
- package/src/components/ImageGallery/__tests__/ImageGallery.test.tsx +13 -3
- package/src/components/ImageGallery/__tests__/ImageGalleryAdjustable.test.tsx +141 -0
- package/src/components/Message/MessageItemView/Headers/MessageReminderHeader.tsx +7 -1
- package/src/components/Message/MessageItemView/Headers/SentToChannelHeader.tsx +7 -1
- package/src/components/Message/MessageItemView/MessageContent.tsx +34 -4
- package/src/components/Message/MessageItemView/MessageFooter.tsx +6 -1
- package/src/components/Message/MessageItemView/MessageReplies.tsx +9 -7
- package/src/components/Message/MessageItemView/MessageRepliesAvatars.tsx +5 -1
- package/src/components/Message/MessageItemView/MessageStatus.tsx +36 -39
- package/src/components/Message/MessageItemView/MessageTextContainer.tsx +27 -4
- package/src/components/Message/MessageItemView/ReactionList/ReactionListClustered.tsx +24 -10
- package/src/components/Message/MessageItemView/ReactionList/ReactionListItem.tsx +7 -1
- package/src/components/Message/MessageItemView/__tests__/Message.test.tsx +10 -3
- package/src/components/Message/MessageItemView/__tests__/MessageReplies.test.tsx +10 -2
- package/src/components/Message/MessageItemView/__tests__/MessageStatus.test.tsx +10 -7
- package/src/components/Message/MessageItemView/__tests__/ReactionListBottom.test.tsx +1 -1
- package/src/components/Message/hooks/useCreateMessageContext.ts +12 -1
- package/src/components/Message/hooks/useMessageActionHandlers.ts +7 -0
- package/src/components/MessageInput/__tests__/__snapshots__/AttachButton.test.tsx.snap +3 -0
- package/src/components/MessageInput/__tests__/__snapshots__/SendButton.test.tsx.snap +2 -0
- package/src/components/MessageList/InlineDateSeparator.tsx +10 -3
- package/src/components/MessageMenu/ReactionButton.tsx +0 -7
- package/src/components/MessageMenu/__tests__/ReactionButton.test.tsx +1 -14
- package/src/components/Poll/Poll.tsx +2 -26
- package/src/components/Poll/components/PollOption.tsx +7 -1
- package/src/components/Reply/Reply.tsx +58 -7
- package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +9 -0
- package/src/components/ui/Avatar/ChannelAvatar.tsx +39 -29
- package/src/components/ui/Badge/BadgeNotification.tsx +11 -2
- package/src/contexts/accessibilityContext/AccessibilityContext.tsx +60 -36
- package/src/contexts/messageContext/MessageContext.tsx +8 -0
- package/src/contexts/overlayContext/MessageOverlayHostLayer.tsx +5 -1
- package/src/contexts/overlayContext/OverlayProvider.tsx +2 -1
- package/src/i18n/ar.json +26 -8
- package/src/i18n/en.json +23 -5
- package/src/i18n/es.json +23 -5
- package/src/i18n/fr.json +23 -5
- package/src/i18n/he.json +23 -5
- package/src/i18n/hi.json +24 -6
- package/src/i18n/it.json +23 -5
- package/src/i18n/ja.json +23 -5
- package/src/i18n/ko.json +23 -5
- package/src/i18n/nl.json +24 -6
- package/src/i18n/pt-br.json +25 -7
- package/src/i18n/ru.json +23 -5
- package/src/i18n/tr.json +24 -6
- package/src/state-store/__tests__/image-gallery-state-store.test.ts +1 -0
- package/src/state-store/image-gallery-state-store.ts +13 -1
- package/src/utils/i18n/getDateString.ts +57 -0
- package/src/version.json +1 -1
- package/lib/commonjs/components/Poll/hooks/usePollAccessibilityActions.js +0 -150
- package/lib/commonjs/components/Poll/hooks/usePollAccessibilityActions.js.map +0 -1
- package/lib/commonjs/components/Poll/hooks/usePollAccessibilityLabel.js +0 -59
- package/lib/commonjs/components/Poll/hooks/usePollAccessibilityLabel.js.map +0 -1
- package/lib/module/components/Poll/hooks/usePollAccessibilityActions.js +0 -150
- package/lib/module/components/Poll/hooks/usePollAccessibilityActions.js.map +0 -1
- package/lib/module/components/Poll/hooks/usePollAccessibilityLabel.js +0 -59
- package/lib/module/components/Poll/hooks/usePollAccessibilityLabel.js.map +0 -1
- package/lib/typescript/components/Poll/hooks/usePollAccessibilityActions.d.ts +0 -25
- package/lib/typescript/components/Poll/hooks/usePollAccessibilityActions.d.ts.map +0 -1
- package/lib/typescript/components/Poll/hooks/usePollAccessibilityLabel.d.ts +0 -8
- package/lib/typescript/components/Poll/hooks/usePollAccessibilityLabel.d.ts.map +0 -1
- package/src/components/Poll/hooks/__tests__/usePollAccessibilityActions.test.tsx +0 -358
- package/src/components/Poll/hooks/__tests__/usePollAccessibilityLabel.test.tsx +0 -142
- package/src/components/Poll/hooks/usePollAccessibilityActions.ts +0 -191
- package/src/components/Poll/hooks/usePollAccessibilityLabel.ts +0 -75
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useOverlayContext } from '../../contexts/overlayContext/OverlayContext';
|
|
5
|
+
import { useStateStore } from '../../hooks';
|
|
6
|
+
import { overlayStore } from '../../state-store/message-overlay-store';
|
|
7
|
+
|
|
8
|
+
const messageOverlayActiveSelector = (state: { id: string | undefined }) => ({
|
|
9
|
+
isMessageOverlayActive: state.id !== undefined,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Android only accessibility focus trap for the OverlayProvider's children
|
|
14
|
+
* tree. iOS handles modal focus traps natively via `accessibilityViewIsModal`
|
|
15
|
+
* on each overlay's root, but Android has no equivalent prop - the only
|
|
16
|
+
* JS side mechanism is to mark siblings as `'no-hide-descendants'`.
|
|
17
|
+
*
|
|
18
|
+
* The shield wraps `{children}` in a single View whose `importantForAccessibility`
|
|
19
|
+
* flips to `'no-hide-descendants'` whenever any focus trapping overlay is
|
|
20
|
+
* active (the full screen image/video gallery or the message context menu).
|
|
21
|
+
* When closed, the wrapper is a transparent passthrough.
|
|
22
|
+
*
|
|
23
|
+
* In terms of rerendering, only the wrapper View commits new props on overlay state
|
|
24
|
+
* transitions. The `{children}` element reference is stable across renders,
|
|
25
|
+
* so React reconciliation does not rerender any component below the wrapper.
|
|
26
|
+
*
|
|
27
|
+
* On iOS the wrapper is skipped entirely.
|
|
28
|
+
*/
|
|
29
|
+
export function OverlayA11yShield({ children }: PropsWithChildren) {
|
|
30
|
+
const { overlay } = useOverlayContext();
|
|
31
|
+
const { isMessageOverlayActive } = useStateStore(overlayStore, messageOverlayActiveSelector);
|
|
32
|
+
|
|
33
|
+
if (Platform.OS !== 'android') {
|
|
34
|
+
return <>{children}</>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const isAnyOverlayActive = overlay === 'gallery' || isMessageOverlayActive;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<View
|
|
41
|
+
accessibilityElementsHidden={isAnyOverlayActive}
|
|
42
|
+
importantForAccessibility={isAnyOverlayActive ? 'no-hide-descendants' : 'auto'}
|
|
43
|
+
style={StyleSheet.absoluteFill}
|
|
44
|
+
testID='overlay-a11y-shield'
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</View>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Platform, Text } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { act, render, screen } from '@testing-library/react-native';
|
|
5
|
+
|
|
6
|
+
import { OverlayContext } from '../../../contexts/overlayContext/OverlayContext';
|
|
7
|
+
import { overlayStore } from '../../../state-store/message-overlay-store';
|
|
8
|
+
import { OverlayA11yShield } from '../OverlayA11yShield';
|
|
9
|
+
|
|
10
|
+
const setPlatform = (os: typeof Platform.OS) => {
|
|
11
|
+
Object.defineProperty(Platform, 'OS', { configurable: true, get: () => os });
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const renderShield = (overlay: 'none' | 'gallery' = 'none') =>
|
|
15
|
+
render(
|
|
16
|
+
<OverlayContext.Provider
|
|
17
|
+
value={
|
|
18
|
+
{
|
|
19
|
+
overlay,
|
|
20
|
+
setOverlay: () => undefined,
|
|
21
|
+
style: undefined,
|
|
22
|
+
} as never
|
|
23
|
+
}
|
|
24
|
+
>
|
|
25
|
+
<OverlayA11yShield>
|
|
26
|
+
<Text testID='child'>child</Text>
|
|
27
|
+
</OverlayA11yShield>
|
|
28
|
+
</OverlayContext.Provider>,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// The wrapper sets `accessibilityElementsHidden` / `importantForAccessibility`
|
|
32
|
+
// when an overlay is active — RTL v13 filters those elements out of a11y queries
|
|
33
|
+
// by default. `includeHiddenElements: true` keeps them queryable for assertion.
|
|
34
|
+
const wrapper = () => screen.queryByTestId('overlay-a11y-shield', { includeHiddenElements: true });
|
|
35
|
+
|
|
36
|
+
describe('OverlayA11yShield', () => {
|
|
37
|
+
const originalOS = Platform.OS;
|
|
38
|
+
afterAll(() => setPlatform(originalOS));
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
act(() => {
|
|
42
|
+
overlayStore.partialNext({ closing: false, id: undefined, messageId: undefined });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('on Android', () => {
|
|
47
|
+
beforeAll(() => setPlatform('android'));
|
|
48
|
+
|
|
49
|
+
it('renders children inside the wrapper', () => {
|
|
50
|
+
renderShield();
|
|
51
|
+
expect(screen.getByTestId('child')).toBeTruthy();
|
|
52
|
+
expect(wrapper()).toBeTruthy();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('does not hide descendants when no overlay is active', () => {
|
|
56
|
+
renderShield('none');
|
|
57
|
+
expect(wrapper()?.props.importantForAccessibility).toBe('auto');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('hides descendants when the gallery overlay is active', () => {
|
|
61
|
+
renderShield('gallery');
|
|
62
|
+
expect(wrapper()?.props.importantForAccessibility).toBe('no-hide-descendants');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('hides descendants when the message overlay opens', () => {
|
|
66
|
+
renderShield('none');
|
|
67
|
+
act(() => {
|
|
68
|
+
overlayStore.partialNext({ id: 'msg-1' });
|
|
69
|
+
});
|
|
70
|
+
expect(wrapper()?.props.importantForAccessibility).toBe('no-hide-descendants');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('on iOS', () => {
|
|
75
|
+
beforeAll(() => setPlatform('ios'));
|
|
76
|
+
|
|
77
|
+
it('renders children without a wrapper', () => {
|
|
78
|
+
renderShield();
|
|
79
|
+
expect(screen.getByTestId('child')).toBeTruthy();
|
|
80
|
+
expect(wrapper()).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
2
|
-
import { Pressable, StyleSheet, Text, View } from 'react-native';
|
|
1
|
+
import React, { useMemo, useRef } from 'react';
|
|
2
|
+
import { findNodeHandle, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import type { Attachment, LocalMessage } from 'stream-chat';
|
|
5
5
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
import { openUrlSafely } from './utils/openUrlSafely';
|
|
16
16
|
|
|
17
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
17
18
|
import { useTranslationContext } from '../../contexts';
|
|
18
19
|
import { useChatConfigContext } from '../../contexts/chatConfigContext/ChatConfigContext';
|
|
19
20
|
import { useComponentsContext } from '../../contexts/componentsContext/ComponentsContext';
|
|
@@ -236,12 +237,19 @@ const GalleryThumbnail = ({
|
|
|
236
237
|
} = useTheme();
|
|
237
238
|
const { t } = useTranslationContext();
|
|
238
239
|
const styles = useStyles();
|
|
240
|
+
const isVideo = thumbnail.type === FileTypes.Video;
|
|
241
|
+
const thumbnailAccessibilityLabel = useA11yLabel(
|
|
242
|
+
isVideo ? 'a11y/Gallery Video' : 'a11y/Gallery Image',
|
|
243
|
+
);
|
|
244
|
+
const thumbnailAccessibilityHint = useA11yLabel('a11y/Double tap to open');
|
|
245
|
+
const thumbnailRef = useRef<View>(null);
|
|
239
246
|
const openImageViewer = () => {
|
|
240
247
|
if (!message) {
|
|
241
248
|
return;
|
|
242
249
|
}
|
|
243
250
|
imageGalleryStateStore.openImageGallery({
|
|
244
251
|
messages: [message],
|
|
252
|
+
requesterNode: findNodeHandle(thumbnailRef.current),
|
|
245
253
|
selectedAttachmentUrl: thumbnail.url,
|
|
246
254
|
});
|
|
247
255
|
setOverlay('gallery');
|
|
@@ -260,8 +268,12 @@ const GalleryThumbnail = ({
|
|
|
260
268
|
};
|
|
261
269
|
return (
|
|
262
270
|
<Pressable
|
|
271
|
+
accessibilityHint={thumbnailAccessibilityHint}
|
|
272
|
+
accessibilityLabel={thumbnailAccessibilityLabel}
|
|
273
|
+
accessibilityRole='button'
|
|
263
274
|
disabled={preventPress}
|
|
264
275
|
key={`gallery-item-${message.id}/${colIndex}/${rowIndex}/${imagesAndVideos.length}`}
|
|
276
|
+
ref={thumbnailRef}
|
|
265
277
|
onLongPress={(event) => {
|
|
266
278
|
if (onLongPress) {
|
|
267
279
|
onLongPress({
|
|
@@ -3,7 +3,7 @@ import { FlatList } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
5
5
|
|
|
6
|
-
import { act, fireEvent, render, waitFor } from '@testing-library/react-native';
|
|
6
|
+
import { act, cleanup, fireEvent, render, waitFor } from '@testing-library/react-native';
|
|
7
7
|
import type { Channel as ChannelType, LocalMessage, StreamChat } from 'stream-chat';
|
|
8
8
|
|
|
9
9
|
import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
|
|
@@ -16,6 +16,7 @@ import { generateMessage } from '../../../mock-builders/generator/message';
|
|
|
16
16
|
import { generateUser } from '../../../mock-builders/generator/user';
|
|
17
17
|
import { getTestClientWithUser } from '../../../mock-builders/mock';
|
|
18
18
|
import { registerNativeHandlers } from '../../../native';
|
|
19
|
+
import { closeOverlay, finalizeCloseOverlay } from '../../../state-store';
|
|
19
20
|
import { Channel } from '../../Channel/Channel';
|
|
20
21
|
import { Chat } from '../../Chat/Chat';
|
|
21
22
|
import { MessageComposer } from '../../MessageInput/MessageComposer';
|
|
@@ -49,6 +50,15 @@ describe('Own capabilities', () => {
|
|
|
49
50
|
});
|
|
50
51
|
});
|
|
51
52
|
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
cleanup();
|
|
55
|
+
// The overlay state-store is module-level, so an overlay opened by a
|
|
56
|
+
// previous test would still be `active` when the next test mounts.
|
|
57
|
+
// Reset it so each test starts with `isActive=false`.
|
|
58
|
+
closeOverlay();
|
|
59
|
+
finalizeCloseOverlay();
|
|
60
|
+
});
|
|
61
|
+
|
|
52
62
|
const getComponent = (props: Partial<React.ComponentProps<typeof Channel>> = {}) => (
|
|
53
63
|
<SafeAreaProvider>
|
|
54
64
|
<OverlayProvider>
|
|
@@ -76,7 +86,20 @@ describe('Own capabilities', () => {
|
|
|
76
86
|
targetMessage: LocalMessage,
|
|
77
87
|
props: Partial<React.ComponentProps<typeof Channel>> = {},
|
|
78
88
|
) => {
|
|
79
|
-
const {
|
|
89
|
+
const {
|
|
90
|
+
findByTestId,
|
|
91
|
+
queryByLabelText: rawQueryByLabelText,
|
|
92
|
+
queryByText,
|
|
93
|
+
unmount,
|
|
94
|
+
} = render(getComponent(props));
|
|
95
|
+
// After the overlay opens, the host layer's `accessibilityViewIsModal`
|
|
96
|
+
// marks the chat tree as hidden to RNTL. The message action list is
|
|
97
|
+
// Portal-teleported into the overlay but its React parent stays inside
|
|
98
|
+
// the chat, so the visible-elements filter excludes it. The list IS
|
|
99
|
+
// rendered (and visible in production); we pass `includeHiddenElements`
|
|
100
|
+
// to look past the modal-sibling heuristic.
|
|
101
|
+
const queryByLabelText: typeof rawQueryByLabelText = (text, options) =>
|
|
102
|
+
rawQueryByLabelText(text, { includeHiddenElements: true, ...options });
|
|
80
103
|
await waitFor(() => queryByText(targetMessage.text as string));
|
|
81
104
|
|
|
82
105
|
act(() => {
|
|
@@ -13,6 +13,7 @@ import { MessageDeliveryStatus, useMessageDeliveryStatus } from '../../hooks';
|
|
|
13
13
|
import { Check, CheckAll, Time } from '../../icons';
|
|
14
14
|
import { primitives } from '../../theme';
|
|
15
15
|
import { MessageStatusTypes } from '../../utils/utils';
|
|
16
|
+
import { CompositeAccessibilityProbe } from '../Accessibility/CompositeAccessibilityProbe';
|
|
16
17
|
|
|
17
18
|
export type ChannelMessagePreviewDeliveryStatusProps = Pick<ChannelPreviewProps, 'channel'> & {
|
|
18
19
|
message: MessageResponse | LocalMessage;
|
|
@@ -66,11 +67,11 @@ export const ChannelMessagePreviewDeliveryStatus = ({
|
|
|
66
67
|
message.status === MessageStatusTypes.SENDING
|
|
67
68
|
? 'a11y/Sending'
|
|
68
69
|
: message.status === MessageStatusTypes.RECEIVED && status === MessageDeliveryStatus.READ
|
|
69
|
-
? 'a11y/Read'
|
|
70
|
+
? 'a11y/Read, sent by you'
|
|
70
71
|
: status === MessageDeliveryStatus.DELIVERED
|
|
71
|
-
? 'a11y/Delivered'
|
|
72
|
+
? 'a11y/Delivered, sent by you'
|
|
72
73
|
: status === MessageDeliveryStatus.SENT
|
|
73
|
-
? 'a11y/Sent'
|
|
74
|
+
? 'a11y/Sent by you'
|
|
74
75
|
: 'a11y/Sending',
|
|
75
76
|
);
|
|
76
77
|
|
|
@@ -83,19 +84,21 @@ export const ChannelMessagePreviewDeliveryStatus = ({
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
return (
|
|
86
|
-
<
|
|
87
|
-
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
status ===
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
87
|
+
<CompositeAccessibilityProbe label={statusLabel}>
|
|
88
|
+
<View style={styles.container}>
|
|
89
|
+
{message.status === MessageStatusTypes.SENDING ? (
|
|
90
|
+
<Time stroke={semantics.chatTextTimestamp} height={16} width={16} {...timeIcon} />
|
|
91
|
+
) : message.status === MessageStatusTypes.RECEIVED &&
|
|
92
|
+
status === MessageDeliveryStatus.READ ? (
|
|
93
|
+
<CheckAll stroke={semantics.accentPrimary} height={16} width={16} {...checkAllIcon} />
|
|
94
|
+
) : status === MessageDeliveryStatus.DELIVERED ? (
|
|
95
|
+
<CheckAll stroke={semantics.chatTextTimestamp} height={16} width={16} {...checkAllIcon} />
|
|
96
|
+
) : status === MessageDeliveryStatus.SENT ? (
|
|
97
|
+
<Check stroke={semantics.chatTextTimestamp} height={16} width={16} {...checkIcon} />
|
|
98
|
+
) : null}
|
|
99
|
+
<Text style={styles.text}>{t('You')}:</Text>
|
|
100
|
+
</View>
|
|
101
|
+
</CompositeAccessibilityProbe>
|
|
99
102
|
);
|
|
100
103
|
};
|
|
101
104
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
3
4
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
4
5
|
import { Mute } from '../../icons';
|
|
6
|
+
import { CompositeAccessibilityProbe } from '../Accessibility/CompositeAccessibilityProbe';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* This UI component displays an avatar for a particular channel.
|
|
@@ -13,6 +15,11 @@ export const ChannelPreviewMutedStatus = () => {
|
|
|
13
15
|
semantics,
|
|
14
16
|
},
|
|
15
17
|
} = useTheme();
|
|
18
|
+
const accessibilityLabel = useA11yLabel('a11y/Muted');
|
|
16
19
|
|
|
17
|
-
return
|
|
20
|
+
return (
|
|
21
|
+
<CompositeAccessibilityProbe label={accessibilityLabel}>
|
|
22
|
+
<Mute height={20} fill={semantics.textTertiary} width={20} {...mutedStatus} />
|
|
23
|
+
</CompositeAccessibilityProbe>
|
|
24
|
+
);
|
|
18
25
|
};
|
|
@@ -4,11 +4,12 @@ import { StyleSheet, Text } from 'react-native';
|
|
|
4
4
|
import type { ChannelPreviewProps } from './ChannelPreview';
|
|
5
5
|
import type { ChannelPreviewViewPropsWithContext } from './ChannelPreviewView';
|
|
6
6
|
|
|
7
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
7
8
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
8
9
|
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
|
|
9
10
|
|
|
10
11
|
import { primitives } from '../../theme';
|
|
11
|
-
import { getDateString } from '../../utils/i18n/getDateString';
|
|
12
|
+
import { getDateString, getDateStringForA11y } from '../../utils/i18n/getDateString';
|
|
12
13
|
|
|
13
14
|
export type ChannelPreviewStatusProps = Pick<
|
|
14
15
|
ChannelPreviewViewPropsWithContext,
|
|
@@ -18,7 +19,7 @@ export type ChannelPreviewStatusProps = Pick<
|
|
|
18
19
|
|
|
19
20
|
export const ChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
|
|
20
21
|
const { formatLatestMessageDate, lastMessage } = props;
|
|
21
|
-
const { t, tDateTimeParser } = useTranslationContext();
|
|
22
|
+
const { t, tDateTimeParser, userLanguage } = useTranslationContext();
|
|
22
23
|
const styles = useStyles();
|
|
23
24
|
|
|
24
25
|
const created_at = lastMessage?.created_at;
|
|
@@ -35,11 +36,30 @@ export const ChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
|
|
|
35
36
|
[created_at, t, tDateTimeParser],
|
|
36
37
|
);
|
|
37
38
|
|
|
39
|
+
const a11yDate = useMemo(
|
|
40
|
+
() =>
|
|
41
|
+
getDateStringForA11y({
|
|
42
|
+
calendarFormatOverrides: { sameDay: 'LT' },
|
|
43
|
+
date: created_at,
|
|
44
|
+
tDateTimeParser,
|
|
45
|
+
userLanguage,
|
|
46
|
+
}),
|
|
47
|
+
[created_at, tDateTimeParser, userLanguage],
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const visibleDate =
|
|
51
|
+
formatLatestMessageDate && latestMessageDate
|
|
52
|
+
? formatLatestMessageDate(latestMessageDate).toString()
|
|
53
|
+
: formattedDate;
|
|
54
|
+
const labelParams = useMemo(
|
|
55
|
+
() => ({ date: a11yDate ?? visibleDate ?? '' }),
|
|
56
|
+
[a11yDate, visibleDate],
|
|
57
|
+
);
|
|
58
|
+
const accessibilityLabel = useA11yLabel('a11y/Last message {{date}}', labelParams);
|
|
59
|
+
|
|
38
60
|
return (
|
|
39
|
-
<Text style={styles.date}>
|
|
40
|
-
{
|
|
41
|
-
? formatLatestMessageDate(latestMessageDate).toString()
|
|
42
|
-
: formattedDate}
|
|
61
|
+
<Text accessibilityLabel={accessibilityLabel} style={styles.date}>
|
|
62
|
+
{visibleDate}
|
|
43
63
|
</Text>
|
|
44
64
|
);
|
|
45
65
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ChannelPreviewProps } from './ChannelPreview';
|
|
4
4
|
|
|
5
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
5
6
|
import type { ChannelsContextValue } from '../../contexts/channelsContext/ChannelsContext';
|
|
6
7
|
import { BadgeNotification } from '../ui/Badge';
|
|
7
8
|
|
|
@@ -15,12 +16,15 @@ export type ChannelPreviewUnreadCountProps = Pick<ChannelsContextValue, 'maxUnre
|
|
|
15
16
|
|
|
16
17
|
export const ChannelPreviewUnreadCount = (props: ChannelPreviewUnreadCountProps) => {
|
|
17
18
|
const { maxUnreadCount, unread } = props;
|
|
19
|
+
const labelParams = useMemo(() => ({ count: unread ?? 0 }), [unread]);
|
|
20
|
+
const accessibilityLabel = useA11yLabel('a11y/{{count}} unread messages', labelParams);
|
|
18
21
|
if (!unread) {
|
|
19
22
|
return null;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
return (
|
|
23
26
|
<BadgeNotification
|
|
27
|
+
accessibilityLabel={accessibilityLabel}
|
|
24
28
|
count={unread > maxUnreadCount ? maxUnreadCount : unread}
|
|
25
29
|
size='sm'
|
|
26
30
|
type='primary'
|
|
@@ -5,6 +5,7 @@ import type { ChannelPreviewProps } from './ChannelPreview';
|
|
|
5
5
|
|
|
6
6
|
import type { LastMessageType } from './hooks/useChannelPreviewData';
|
|
7
7
|
|
|
8
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
8
9
|
import {
|
|
9
10
|
ChannelsContextValue,
|
|
10
11
|
useChannelsContext,
|
|
@@ -70,6 +71,7 @@ const ChannelPreviewViewWithContext = (props: ChannelPreviewViewPropsWithContext
|
|
|
70
71
|
} = useTheme();
|
|
71
72
|
const styles = useStyles();
|
|
72
73
|
const swipeRegistry = useSwipeRegistryContext();
|
|
74
|
+
const accessibilityHint = useA11yLabel('a11y/Double tap to open');
|
|
73
75
|
|
|
74
76
|
const onPress = useStableCallback(() => {
|
|
75
77
|
if (swipeRegistry?.hasOpen()) {
|
|
@@ -84,6 +86,7 @@ const ChannelPreviewViewWithContext = (props: ChannelPreviewViewPropsWithContext
|
|
|
84
86
|
return (
|
|
85
87
|
<View style={[styles.wrapper, wrapper]}>
|
|
86
88
|
<Pressable
|
|
89
|
+
accessibilityHint={accessibilityHint}
|
|
87
90
|
onPress={onPress}
|
|
88
91
|
style={({ pressed }) => [
|
|
89
92
|
styles.container,
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
AccessibilityInfo,
|
|
4
|
+
Image,
|
|
5
|
+
ImageStyle,
|
|
6
|
+
Platform,
|
|
7
|
+
StyleSheet,
|
|
8
|
+
ViewStyle,
|
|
9
|
+
} from 'react-native';
|
|
3
10
|
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
4
11
|
|
|
5
12
|
import Animated, {
|
|
@@ -21,6 +28,8 @@ import type {
|
|
|
21
28
|
|
|
22
29
|
import { useImageGalleryGestures } from './hooks/useImageGalleryGestures';
|
|
23
30
|
|
|
31
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
32
|
+
import { useAccessibilityContext } from '../../contexts/accessibilityContext/AccessibilityContext';
|
|
24
33
|
import { useComponentsContext } from '../../contexts/componentsContext/ComponentsContext';
|
|
25
34
|
import {
|
|
26
35
|
ImageGalleryProviderProps,
|
|
@@ -280,13 +289,82 @@ export const ImageGalleryWithContext = (props: ImageGalleryWithContextProps) =>
|
|
|
280
289
|
setIsGridViewVisible(true);
|
|
281
290
|
};
|
|
282
291
|
|
|
292
|
+
const { enabled: isAccessibilityEnabled } = useAccessibilityContext();
|
|
293
|
+
const assetsCount = assets.length;
|
|
294
|
+
const isAdjustable = isAccessibilityEnabled;
|
|
295
|
+
const accessibilityValueParams = useMemo(
|
|
296
|
+
() => ({ count: assetsCount, position: currentIndex + 1 }),
|
|
297
|
+
[currentIndex, assetsCount],
|
|
298
|
+
);
|
|
299
|
+
const accessibilityValueText = useA11yLabel(
|
|
300
|
+
'a11y/{{position}} of {{count}}',
|
|
301
|
+
accessibilityValueParams,
|
|
302
|
+
);
|
|
303
|
+
const accessibilityValue = useMemo(
|
|
304
|
+
() => (accessibilityValueText ? { text: accessibilityValueText } : undefined),
|
|
305
|
+
[accessibilityValueText],
|
|
306
|
+
);
|
|
307
|
+
const adjustableActions = useMemo(
|
|
308
|
+
() =>
|
|
309
|
+
isAdjustable ? [{ name: 'increment' as const }, { name: 'decrement' as const }] : undefined,
|
|
310
|
+
[isAdjustable],
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
const onAccessibilityAction = useCallback(
|
|
314
|
+
(event: { nativeEvent: { actionName: string } }) => {
|
|
315
|
+
if (!isAccessibilityEnabled) return;
|
|
316
|
+
const latest = imageGalleryStateStore.state.getLatestValue();
|
|
317
|
+
const latestCount = latest.assets.length;
|
|
318
|
+
const latestIndex = latest.currentIndex;
|
|
319
|
+
if (latestCount <= 1) return;
|
|
320
|
+
if (event.nativeEvent.actionName === 'increment') {
|
|
321
|
+
if (latestIndex < latestCount - 1) {
|
|
322
|
+
imageGalleryStateStore.currentIndex = latestIndex + 1;
|
|
323
|
+
}
|
|
324
|
+
} else if (event.nativeEvent.actionName === 'decrement') {
|
|
325
|
+
if (latestIndex > 0) {
|
|
326
|
+
imageGalleryStateStore.currentIndex = latestIndex - 1;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
[imageGalleryStateStore, isAccessibilityEnabled],
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
useEffect(() => {
|
|
334
|
+
return () => {
|
|
335
|
+
const handle = imageGalleryStateStore.requesterNode;
|
|
336
|
+
if (handle == null) return;
|
|
337
|
+
imageGalleryStateStore.requesterNode = null;
|
|
338
|
+
// Because of the fact that iOS and Android handle supressing
|
|
339
|
+
// the content underneath differently, we have to wait a frame
|
|
340
|
+
// before iOS is allowed to attempt to refocus (it takes a frame
|
|
341
|
+
// for the native a11y tree to become aware that it no longer has
|
|
342
|
+
// an accessibilityViewIsModal sibling).
|
|
343
|
+
if (Platform.OS === 'android') {
|
|
344
|
+
AccessibilityInfo.setAccessibilityFocus(handle);
|
|
345
|
+
} else {
|
|
346
|
+
requestAnimationFrame(() => {
|
|
347
|
+
AccessibilityInfo.setAccessibilityFocus(handle);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}, [imageGalleryStateStore]);
|
|
352
|
+
|
|
283
353
|
return (
|
|
284
354
|
<Animated.View
|
|
285
|
-
|
|
355
|
+
accessibilityViewIsModal
|
|
286
356
|
pointerEvents={'auto'}
|
|
287
357
|
style={[StyleSheet.absoluteFill, showScreenStyle]}
|
|
288
358
|
>
|
|
289
|
-
<Animated.View
|
|
359
|
+
<Animated.View
|
|
360
|
+
accessible
|
|
361
|
+
accessibilityActions={adjustableActions}
|
|
362
|
+
accessibilityLabel='Image Gallery'
|
|
363
|
+
accessibilityRole={isAdjustable ? 'adjustable' : undefined}
|
|
364
|
+
accessibilityValue={isAdjustable ? accessibilityValue : undefined}
|
|
365
|
+
onAccessibilityAction={isAdjustable ? onAccessibilityAction : undefined}
|
|
366
|
+
style={[StyleSheet.absoluteFill, containerBackground]}
|
|
367
|
+
/>
|
|
290
368
|
<GestureDetector gesture={Gesture.Simultaneous(singleTap, doubleTap, pinch, pan)}>
|
|
291
369
|
<Animated.View style={StyleSheet.absoluteFill}>
|
|
292
370
|
<Animated.View
|
|
@@ -99,8 +99,16 @@ describe('ImageGallery', () => {
|
|
|
99
99
|
);
|
|
100
100
|
|
|
101
101
|
await waitFor(() => {
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
// The pager subtree is marked `accessibilityElementsHidden` /
|
|
103
|
+
// `importantForAccessibility='no-hide-descendants'` so screen readers
|
|
104
|
+
// can't land on the silent shadow views inside it; the queries here
|
|
105
|
+
// opt back into hidden elements so tests can still find the assets.
|
|
106
|
+
expect(
|
|
107
|
+
screen.queryAllByLabelText('Image Item', { includeHiddenElements: true }),
|
|
108
|
+
).toHaveLength(2);
|
|
109
|
+
expect(
|
|
110
|
+
screen.queryAllByLabelText('Image Gallery Video', { includeHiddenElements: true }),
|
|
111
|
+
).toHaveLength(1);
|
|
104
112
|
});
|
|
105
113
|
});
|
|
106
114
|
|
|
@@ -116,7 +124,9 @@ describe('ImageGallery', () => {
|
|
|
116
124
|
);
|
|
117
125
|
|
|
118
126
|
await waitFor(() => {
|
|
119
|
-
const pagerStyle = StyleSheet.flatten(
|
|
127
|
+
const pagerStyle = StyleSheet.flatten(
|
|
128
|
+
screen.getByTestId('image-gallery-pager', { includeHiddenElements: true }).props.style,
|
|
129
|
+
);
|
|
120
130
|
expect(pagerStyle.direction).toBe('ltr');
|
|
121
131
|
});
|
|
122
132
|
});
|