stream-chat-react-native-core 9.3.1-beta.7 → 9.3.1-beta.9
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/useAccessibilityServiceEnabled.js +43 -0
- package/lib/commonjs/a11y/hooks/useAccessibilityServiceEnabled.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/OverlayA11yShield.js +45 -0
- package/lib/commonjs/components/Accessibility/OverlayA11yShield.js.map +1 -0
- package/lib/commonjs/components/Attachment/Gallery.js +10 -0
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewStatus.js +12 -3
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewStatus.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 -5
- package/lib/commonjs/components/Message/MessageItemView/MessageContent.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/MessageTextContainer.js +16 -6
- package/lib/commonjs/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/ReactionList/ReactionListItem.js +4 -0
- 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/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 -0
- 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/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 +7 -1
- package/lib/commonjs/i18n/en.json +7 -1
- package/lib/commonjs/i18n/es.json +7 -1
- package/lib/commonjs/i18n/fr.json +7 -1
- package/lib/commonjs/i18n/he.json +7 -1
- package/lib/commonjs/i18n/hi.json +7 -1
- package/lib/commonjs/i18n/it.json +7 -1
- package/lib/commonjs/i18n/ja.json +7 -1
- package/lib/commonjs/i18n/ko.json +7 -1
- package/lib/commonjs/i18n/nl.json +7 -1
- package/lib/commonjs/i18n/pt-br.json +7 -1
- package/lib/commonjs/i18n/ru.json +7 -1
- package/lib/commonjs/i18n/tr.json +7 -1
- 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/useAccessibilityServiceEnabled.js +43 -0
- package/lib/module/a11y/hooks/useAccessibilityServiceEnabled.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/OverlayA11yShield.js +45 -0
- package/lib/module/components/Accessibility/OverlayA11yShield.js.map +1 -0
- package/lib/module/components/Attachment/Gallery.js +10 -0
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewStatus.js +12 -3
- package/lib/module/components/ChannelPreview/ChannelPreviewStatus.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 -5
- package/lib/module/components/Message/MessageItemView/MessageContent.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/MessageTextContainer.js +16 -6
- package/lib/module/components/Message/MessageItemView/MessageTextContainer.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/ReactionList/ReactionListItem.js +4 -0
- 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/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 -0
- 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/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 +7 -1
- package/lib/module/i18n/en.json +7 -1
- package/lib/module/i18n/es.json +7 -1
- package/lib/module/i18n/fr.json +7 -1
- package/lib/module/i18n/he.json +7 -1
- package/lib/module/i18n/hi.json +7 -1
- package/lib/module/i18n/it.json +7 -1
- package/lib/module/i18n/ja.json +7 -1
- package/lib/module/i18n/ko.json +7 -1
- package/lib/module/i18n/nl.json +7 -1
- package/lib/module/i18n/pt-br.json +7 -1
- package/lib/module/i18n/ru.json +7 -1
- package/lib/module/i18n/tr.json +7 -1
- 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/useAccessibilityServiceEnabled.d.ts +20 -0
- package/lib/typescript/a11y/hooks/useAccessibilityServiceEnabled.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/OverlayA11yShield.d.ts +20 -0
- package/lib/typescript/components/Accessibility/OverlayA11yShield.d.ts.map +1 -0
- package/lib/typescript/components/Attachment/Gallery.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewStatus.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/MessageReplies.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageRepliesAvatars.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/ReactionListItem.d.ts.map +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/MessageList/InlineDateSeparator.d.ts.map +1 -1
- package/lib/typescript/components/MessageMenu/ReactionButton.d.ts.map +1 -1
- package/lib/typescript/components/Poll/components/PollOption.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/i18n/ar.json +7 -1
- package/lib/typescript/i18n/en.json +7 -1
- package/lib/typescript/i18n/es.json +7 -1
- package/lib/typescript/i18n/fr.json +7 -1
- package/lib/typescript/i18n/he.json +7 -1
- package/lib/typescript/i18n/hi.json +7 -1
- package/lib/typescript/i18n/it.json +7 -1
- package/lib/typescript/i18n/ja.json +7 -1
- package/lib/typescript/i18n/ko.json +7 -1
- package/lib/typescript/i18n/nl.json +7 -1
- package/lib/typescript/i18n/pt-br.json +7 -1
- package/lib/typescript/i18n/ru.json +7 -1
- package/lib/typescript/i18n/tr.json +7 -1
- 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 +6 -0
- 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/useAccessibilityServiceEnabled.ts +66 -0
- package/src/a11y/index.ts +1 -0
- package/src/components/Accessibility/OverlayA11yShield.tsx +57 -0
- package/src/components/Accessibility/__tests__/OverlayA11yShield.test.tsx +118 -0
- package/src/components/Attachment/Gallery.tsx +14 -2
- package/src/components/Channel/__tests__/ownCapabilities.test.tsx +25 -2
- package/src/components/ChannelPreview/ChannelPreviewStatus.tsx +17 -3
- 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 -15
- package/src/components/Message/MessageItemView/MessageReplies.tsx +9 -7
- package/src/components/Message/MessageItemView/MessageRepliesAvatars.tsx +5 -1
- package/src/components/Message/MessageItemView/MessageTextContainer.tsx +27 -4
- package/src/components/Message/MessageItemView/ReactionList/ReactionListItem.tsx +2 -0
- 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/hooks/useCreateMessageContext.ts +12 -1
- 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 +1 -1
- package/src/components/Poll/components/PollOption.tsx +7 -1
- package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +1 -0
- 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 +6 -1
- package/src/i18n/ar.json +7 -1
- package/src/i18n/en.json +7 -1
- package/src/i18n/es.json +7 -1
- package/src/i18n/fr.json +7 -1
- package/src/i18n/he.json +7 -1
- package/src/i18n/hi.json +7 -1
- package/src/i18n/it.json +7 -1
- package/src/i18n/ja.json +7 -1
- package/src/i18n/ko.json +7 -1
- package/src/i18n/nl.json +7 -1
- package/src/i18n/pt-br.json +7 -1
- package/src/i18n/ru.json +7 -1
- package/src/i18n/tr.json +7 -1
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-gallery-state-store.d.ts","sourceRoot":"","sources":["../../../src/state-store/image-gallery-state-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9F,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAOtD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAgBF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"image-gallery-state-store.d.ts","sourceRoot":"","sources":["../../../src/state-store/image-gallery-state-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9F,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAOtD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAgBF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAUF,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;CACvD,CAAC;AAOF,qBAAa,sBAAsB;IACjC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC;IACrC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,eAAe,EAAE,eAAe,CAAC;gBAErB,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM;IAOtD,IAAI,QAAQ,IAuEW,YAAY,EAAE,CArEpC;IAED,IAAI,qBAAqB,IAuEwB,MAAM,GAAG,SAAS,CArElE;IAED,IAAI,aAAa,IA2EgB,MAAM,GAAG,IAAI,CAzE7C;IAED,IAAI,sBAAsB;;;QAsBzB;IAED,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAI9C,IAAI,MAAM;;;;;;;;;;;;;QA4BT;IAGD,IAAI,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,EAEpC;IAED,IAAI,qBAAqB,CAAC,qBAAqB,EAAE,MAAM,GAAG,SAAS,EAElE;IAED,IAAI,YAAY,CAAC,YAAY,EAAE,MAAM,EAEpC;IAED,IAAI,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,EAE7C;IAGD,cAAc,GAAI,UAAU,YAAY,EAAE,UAExC;IAEF,cAAc,GAAI,UAAU,YAAY,EAAE,UAIxC;IAEF,gBAAgB,GAAI,qDAIjB;QACD,QAAQ,EAAE,YAAY,EAAE,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,UAEC;IAEF,mBAAmB,oBAYjB;IAEF,gCAAgC,oBAmB9B;IAEF,qBAAqB,mBASnB;IAEF,KAAK,aAGH;CACH"}
|
|
@@ -396,12 +396,15 @@ export declare class Streami18n {
|
|
|
396
396
|
"a11y/Direct chat with {{name}}": string;
|
|
397
397
|
"a11y/Double tap to open": string;
|
|
398
398
|
"a11y/Double tap to view reactions": string;
|
|
399
|
+
"a11y/Double tap to view thread": string;
|
|
399
400
|
"a11y/Editing message": string;
|
|
400
401
|
"a11y/Editing message: {{text}}": string;
|
|
401
402
|
"a11y/Last message {{date}}": string;
|
|
402
403
|
"a11y/Loading": string;
|
|
403
404
|
"a11y/Loading failed": string;
|
|
404
405
|
"a11y/Message actions": string;
|
|
406
|
+
"a11y/Message from you": string;
|
|
407
|
+
"a11y/Message from {{sender}}": string;
|
|
405
408
|
"a11y/Muted": string;
|
|
406
409
|
"a11y/New message from {{user}}": string;
|
|
407
410
|
"a11y/Offline": string;
|
|
@@ -508,6 +511,9 @@ export declare class Streami18n {
|
|
|
508
511
|
"unknown error": string;
|
|
509
512
|
"unsupported file type": string;
|
|
510
513
|
"a11y/{{count}} unread messages": string;
|
|
514
|
+
"a11y/Gallery Image": string;
|
|
515
|
+
"a11y/Gallery Video": string;
|
|
516
|
+
"a11y/{{position}} of {{count}}": string;
|
|
511
517
|
}>;
|
|
512
518
|
};
|
|
513
519
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Streami18n.d.ts","sourceRoot":"","sources":["../../../../src/utils/i18n/Streami18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAa,EAAE,KAAK,IAAI,IAAI,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAElF,OAAO,KAAK,cAAc,MAAM,iBAAiB,CAAC;AAIlD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAahD,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,oBAAoB,CAAC;AAC5B,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,OAAO,iBAAiB,CAAC;AAmGzB,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAsBF,KAAK,oBAAoB,GAAG,OAAO,KAAK,GAAG,OAAO,cAAc,CAAC;AAajE,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,4BAA4B,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG;QAAE,QAAQ,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,gBAAgB,CAAC;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,OAAO,CAAC,OAAO,cAAc,CAAC,CAAC;CAC1D,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,KAAK,GAAG,WAAW,CAAC;IACjC,aAAa,EAAE;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,YAAY,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,KAAK,GAAG,MAAM,CAAC;IAC5B,sBAAsB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACjD,CAAC;AAkKF,eAAO,MAAM,yBAAyB,EAA6B,SAAS,CAAC;AAE7E,qBAAa,UAAU;IACrB,YAAY,EAAE,YAAY,CAAyB;IACnD,KAAK,OAAQ;IACb,WAAW,UAAS;IAEpB,OAAO,CAAC,mBAAmB,CAA4B;IAEvD,OAAO,CAAC,yBAAyB,CAAkC;IAKnE,OAAO,CAAC,4BAA4B,CAAkC;IAItE,OAAO,CAAC,uBAAuB,CAAwB;IAEvD,CAAC,EAAE,SAAS,CAA6B;IACzC,eAAe,EAAE,eAAe,CAAC;IAEjC,YAAY,EAAE;QACZ,CAAC,GAAG,EAAE,MAAM,GAAG;YACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,cAAc,CAAC,CAAC;SAC/C,CAAC;KACH,CAcC;IAEF;;;;;OAKG;IACH,YAAY,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAM;IAEvD;;OAEG;IACH,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,oBAAoB,CAAC;IACrC,UAAU,EAAE,oBAAoB,GAAG,gBAAgB,CAAwB;IAC3E,sBAAsB,EAAE,OAAO,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;gBACS,OAAO,GAAE,iBAAsB,EAAE,aAAa,GAAE,OAAO,CAAC,aAAa,CAAM;IA0GvF;;OAEG;YACW,IAAI;IA8BlB,YAAY,GAAI,UAAU,MAAM,aAM9B;IAEF,uBAAuB,aAWrB;IAEF,qEAAqE;IACrE,cAAc,QAAO,YAAY,CAAsB;IAEvD,2CAA2C;IAC3C,qBAAqB,iBAAwC;IAE7D,uEAAuE;IACvE,eAAe
|
|
1
|
+
{"version":3,"file":"Streami18n.d.ts","sourceRoot":"","sources":["../../../../src/utils/i18n/Streami18n.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TranslationLanguages } from 'stream-chat';
|
|
1
2
|
import { TimestampFormatterOptions } from './types';
|
|
2
3
|
import { TranslatorFunctions } from '../../contexts/translationContext';
|
|
3
4
|
type DateFormatterOptions = TimestampFormatterOptions & Partial<TranslatorFunctions> & {
|
|
@@ -12,5 +13,32 @@ export declare const noParsingFunctionWarning = "MessageTimestamp was called but
|
|
|
12
13
|
* Utility function to format the date string.
|
|
13
14
|
*/
|
|
14
15
|
export declare function getDateString({ calendar, calendarFormats, date, format, t, tDateTimeParser, timestampTranslationKey, }: DateFormatterOptions): string | number | undefined;
|
|
16
|
+
type DateStringForA11yOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* Optional calendar-format overrides applied on top of the locale defaults
|
|
19
|
+
* and the SDK's `sameElse: 'LL'` substitution. Use this when the visible
|
|
20
|
+
* date format diverges from the locale defaults (e.g. ChannelPreviewStatus
|
|
21
|
+
* uses `sameDay: 'LT'` to show the time instead of "Today").
|
|
22
|
+
*/
|
|
23
|
+
calendarFormatOverrides?: Partial<{
|
|
24
|
+
lastDay: string;
|
|
25
|
+
lastWeek: string;
|
|
26
|
+
nextDay: string;
|
|
27
|
+
nextWeek: string;
|
|
28
|
+
sameDay: string;
|
|
29
|
+
sameElse: string;
|
|
30
|
+
}>;
|
|
31
|
+
date?: string | Date;
|
|
32
|
+
tDateTimeParser?: TranslatorFunctions['tDateTimeParser'];
|
|
33
|
+
userLanguage?: TranslationLanguages;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Produce a TTS-friendly calendar string. iOS VoiceOver reads numeric dates
|
|
37
|
+
* like "04/08/2026" character-by-character; substituting `LL` ("April 8, 2026")
|
|
38
|
+
* for the calendar `sameElse` slot fixes that. The relative slots
|
|
39
|
+
* (sameDay/lastDay/nextDay/lastWeek/nextWeek) are preserved from the locale,
|
|
40
|
+
* so "Today"/"Yesterday"/weekday names still come through.
|
|
41
|
+
*/
|
|
42
|
+
export declare const getDateStringForA11y: ({ calendarFormatOverrides, date, tDateTimeParser, userLanguage, }: DateStringForA11yOptions) => string | undefined;
|
|
15
43
|
export {};
|
|
16
44
|
//# sourceMappingURL=getDateString.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDateString.d.ts","sourceRoot":"","sources":["../../../../src/utils/i18n/getDateString.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAGxE,KAAK,oBAAoB,GAAG,yBAAyB,GACnD,OAAO,CAAC,mBAAmB,CAAC,GAAG;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAIrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEJ,eAAO,MAAM,wBAAwB,oFAC8C,CAAC;AAEpF;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,eAAe,EACf,IAAI,EACJ,MAAM,EACN,CAAC,EACD,eAAe,EACf,uBAAuB,GACxB,EAAE,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CA4CpD"}
|
|
1
|
+
{"version":3,"file":"getDateString.d.ts","sourceRoot":"","sources":["../../../../src/utils/i18n/getDateString.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAGxE,KAAK,oBAAoB,GAAG,yBAAyB,GACnD,OAAO,CAAC,mBAAmB,CAAC,GAAG;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAIrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEJ,eAAO,MAAM,wBAAwB,oFAC8C,CAAC;AAEpF;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,eAAe,EACf,IAAI,EACJ,MAAM,EACN,CAAC,EACD,eAAe,EACf,uBAAuB,GACxB,EAAE,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CA4CpD;AAED,KAAK,wBAAwB,GAAG;IAC9B;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,mEAKlC,wBAAwB,KAAG,MAAM,GAAG,SAoBtC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stream-chat-react-native-core",
|
|
3
3
|
"description": "The official React Native and Expo components for Stream Chat, a service for building chat applications",
|
|
4
|
-
"version": "9.3.1-beta.
|
|
4
|
+
"version": "9.3.1-beta.9",
|
|
5
5
|
"author": {
|
|
6
6
|
"company": "Stream.io Inc",
|
|
7
7
|
"name": "Stream.io Inc"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { AccessibilityInfo, AppState, Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useAccessibilityContext } from '../../contexts/accessibilityContext/AccessibilityContext';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Subscribes to Android accessibility service availability and returns the live state.
|
|
8
|
+
*
|
|
9
|
+
* `AccessibilityInfo.isAccessibilityServiceEnabled` reports whether ANY a11y service is
|
|
10
|
+
* running - TalkBack, Switch Access, Voice Access, Select to Speak, etc. not just
|
|
11
|
+
* screen readers. The signal is Android only; iOS doesn't expose it (and doesn't need to,
|
|
12
|
+
* since the SDK's iOS overlay trap uses `accessibilityViewIsModal`).
|
|
13
|
+
*
|
|
14
|
+
* React Native does not emit a dedicated change event for this signal, so the hook
|
|
15
|
+
* re-polls when the app returns to the foreground - which is the realistic path for a
|
|
16
|
+
* user toggling Accessibility settings and coming back to the app. The most common
|
|
17
|
+
* single service change (TalkBack on/off) is also covered by the `screenReaderChanged`
|
|
18
|
+
* listener.
|
|
19
|
+
*
|
|
20
|
+
* Returns false on non-Android platforms without subscribing.
|
|
21
|
+
* Returns false when the `AccessibilityContext` is disabled so consumers don't pay the
|
|
22
|
+
* listener cost when the SDK's a11y is opted out.
|
|
23
|
+
*/
|
|
24
|
+
export const useAccessibilityServiceEnabled = (): boolean => {
|
|
25
|
+
const { enabled } = useAccessibilityContext();
|
|
26
|
+
const [isEnabled, setIsEnabled] = useState<boolean>(false);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (Platform.OS !== 'android' || !enabled) {
|
|
30
|
+
setIsEnabled(false);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let cancelled = false;
|
|
35
|
+
|
|
36
|
+
const refresh = () => {
|
|
37
|
+
AccessibilityInfo.isAccessibilityServiceEnabled?.()
|
|
38
|
+
.then((value) => {
|
|
39
|
+
if (!cancelled) setIsEnabled(value);
|
|
40
|
+
})
|
|
41
|
+
.catch(() => {
|
|
42
|
+
// Older RN versions / certain environments may not implement this; fall back to false.
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
refresh();
|
|
47
|
+
|
|
48
|
+
const screenReaderSubscription = AccessibilityInfo.addEventListener(
|
|
49
|
+
'screenReaderChanged',
|
|
50
|
+
refresh,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const appStateSubscription = AppState.addEventListener('change', (state) => {
|
|
54
|
+
if (state === 'active') refresh();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return () => {
|
|
58
|
+
cancelled = true;
|
|
59
|
+
screenReaderSubscription?.remove?.();
|
|
60
|
+
appStateSubscription?.remove?.();
|
|
61
|
+
};
|
|
62
|
+
}, [enabled]);
|
|
63
|
+
|
|
64
|
+
if (Platform.OS !== 'android' || !enabled) return false;
|
|
65
|
+
return isEnabled;
|
|
66
|
+
};
|
package/src/a11y/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './a11yUtils';
|
|
2
2
|
export * from './hooks/useScreenReaderEnabled';
|
|
3
|
+
export * from './hooks/useAccessibilityServiceEnabled';
|
|
3
4
|
export * from './hooks/useReducedMotionPreference';
|
|
4
5
|
export * from './hooks/useResolvedModalAccessibilityProps';
|
|
5
6
|
export * from './hooks/useAnnounceOnStateChange';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useAccessibilityServiceEnabled } from '../../a11y';
|
|
5
|
+
import { useAccessibilityContext } from '../../contexts/accessibilityContext/AccessibilityContext';
|
|
6
|
+
import { useOverlayContext } from '../../contexts/overlayContext/OverlayContext';
|
|
7
|
+
import { useStateStore } from '../../hooks';
|
|
8
|
+
import { overlayStore } from '../../state-store/message-overlay-store';
|
|
9
|
+
|
|
10
|
+
const messageOverlayActiveSelector = (state: { id: string | undefined }) => ({
|
|
11
|
+
isMessageOverlayActive: state.id !== undefined,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const useShouldActivateTrap = (): boolean => {
|
|
15
|
+
const { enabled: a11yEnabled } = useAccessibilityContext();
|
|
16
|
+
const { overlay } = useOverlayContext();
|
|
17
|
+
const { isMessageOverlayActive } = useStateStore(overlayStore, messageOverlayActiveSelector);
|
|
18
|
+
const a11yServiceEnabled = useAccessibilityServiceEnabled();
|
|
19
|
+
|
|
20
|
+
return a11yEnabled && (overlay === 'gallery' || isMessageOverlayActive) && a11yServiceEnabled;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Android only accessibility focus trap for the OverlayProvider's children
|
|
25
|
+
* tree. iOS handles modal focus traps natively via `accessibilityViewIsModal`
|
|
26
|
+
* on each overlay's root, but Android has no equivalent prop - the only
|
|
27
|
+
* JS side mechanism is to mark siblings as `'no-hide-descendants'`.
|
|
28
|
+
*
|
|
29
|
+
* The shield wraps `{children}` in a single View whose `importantForAccessibility`
|
|
30
|
+
* flips to `'no-hide-descendants'` whenever any focus trapping overlay is
|
|
31
|
+
* active (the full screen image/video gallery or the message context menu).
|
|
32
|
+
* When closed, the wrapper is a transparent passthrough.
|
|
33
|
+
*
|
|
34
|
+
* In terms of rerendering, only the wrapper View commits new props on overlay state
|
|
35
|
+
* transitions. The `{children}` element reference is stable across renders,
|
|
36
|
+
* so React reconciliation does not rerender any component below the wrapper.
|
|
37
|
+
*
|
|
38
|
+
* On iOS the wrapper is skipped entirely.
|
|
39
|
+
*/
|
|
40
|
+
export function OverlayA11yShield({ children }: PropsWithChildren) {
|
|
41
|
+
const shouldActivateTrap = useShouldActivateTrap();
|
|
42
|
+
|
|
43
|
+
if (Platform.OS !== 'android') {
|
|
44
|
+
return <>{children}</>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<View
|
|
49
|
+
importantForAccessibility={shouldActivateTrap ? 'no-hide-descendants' : undefined}
|
|
50
|
+
style={StyleSheet.absoluteFill}
|
|
51
|
+
pointerEvents='box-none'
|
|
52
|
+
testID='overlay-a11y-shield'
|
|
53
|
+
>
|
|
54
|
+
{children}
|
|
55
|
+
</View>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AccessibilityInfo, Platform, Text } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { act, render, screen, waitFor } from '@testing-library/react-native';
|
|
5
|
+
|
|
6
|
+
import { AccessibilityProvider } from '../../../contexts/accessibilityContext/AccessibilityContext';
|
|
7
|
+
import { OverlayContext } from '../../../contexts/overlayContext/OverlayContext';
|
|
8
|
+
import { overlayStore } from '../../../state-store/message-overlay-store';
|
|
9
|
+
import { OverlayA11yShield } from '../OverlayA11yShield';
|
|
10
|
+
|
|
11
|
+
jest.mock('react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo', () => ({
|
|
12
|
+
__esModule: true,
|
|
13
|
+
default: {
|
|
14
|
+
addEventListener: jest.fn().mockReturnValue({ remove: jest.fn() }),
|
|
15
|
+
announceForAccessibility: jest.fn(),
|
|
16
|
+
isAccessibilityServiceEnabled: jest.fn().mockResolvedValue(true),
|
|
17
|
+
isReduceMotionEnabled: jest.fn().mockResolvedValue(false),
|
|
18
|
+
isScreenReaderEnabled: jest.fn().mockResolvedValue(false),
|
|
19
|
+
},
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const setPlatform = (os: typeof Platform.OS) => {
|
|
23
|
+
Object.defineProperty(Platform, 'OS', { configurable: true, get: () => os });
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const renderShield = (overlay: 'none' | 'gallery' = 'none') =>
|
|
27
|
+
render(
|
|
28
|
+
<AccessibilityProvider value={{ enabled: true }}>
|
|
29
|
+
<OverlayContext.Provider
|
|
30
|
+
value={
|
|
31
|
+
{
|
|
32
|
+
overlay,
|
|
33
|
+
setOverlay: () => undefined,
|
|
34
|
+
style: undefined,
|
|
35
|
+
} as never
|
|
36
|
+
}
|
|
37
|
+
>
|
|
38
|
+
<OverlayA11yShield>
|
|
39
|
+
<Text testID='child'>child</Text>
|
|
40
|
+
</OverlayA11yShield>
|
|
41
|
+
</OverlayContext.Provider>
|
|
42
|
+
</AccessibilityProvider>,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// The wrapper sets `accessibilityElementsHidden` / `importantForAccessibility`
|
|
46
|
+
// when an overlay is active — RTL v13 filters those elements out of a11y queries
|
|
47
|
+
// by default. `includeHiddenElements: true` keeps them queryable for assertion.
|
|
48
|
+
const wrapper = () => screen.queryByTestId('overlay-a11y-shield', { includeHiddenElements: true });
|
|
49
|
+
|
|
50
|
+
describe('OverlayA11yShield', () => {
|
|
51
|
+
const originalOS = Platform.OS;
|
|
52
|
+
afterAll(() => setPlatform(originalOS));
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
(AccessibilityInfo.isAccessibilityServiceEnabled as jest.Mock).mockResolvedValue(true);
|
|
56
|
+
act(() => {
|
|
57
|
+
overlayStore.partialNext({ closing: false, id: undefined, messageId: undefined });
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('on Android', () => {
|
|
62
|
+
beforeAll(() => setPlatform('android'));
|
|
63
|
+
|
|
64
|
+
it('renders children inside the wrapper', async () => {
|
|
65
|
+
renderShield();
|
|
66
|
+
await act(async () => {
|
|
67
|
+
await Promise.resolve();
|
|
68
|
+
});
|
|
69
|
+
expect(screen.getByTestId('child')).toBeTruthy();
|
|
70
|
+
expect(wrapper()).toBeTruthy();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('does not hide descendants when no overlay is active', async () => {
|
|
74
|
+
renderShield('none');
|
|
75
|
+
await act(async () => {
|
|
76
|
+
await Promise.resolve();
|
|
77
|
+
});
|
|
78
|
+
expect(wrapper()?.props.importantForAccessibility).toBeUndefined();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('hides descendants when the gallery overlay is active and an a11y service is on', async () => {
|
|
82
|
+
renderShield('gallery');
|
|
83
|
+
await waitFor(() => {
|
|
84
|
+
expect(wrapper()?.props.importantForAccessibility).toBe('no-hide-descendants');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('hides descendants when the message overlay opens and an a11y service is on', async () => {
|
|
89
|
+
renderShield('none');
|
|
90
|
+
act(() => {
|
|
91
|
+
overlayStore.partialNext({ id: 'msg-1' });
|
|
92
|
+
});
|
|
93
|
+
await waitFor(() => {
|
|
94
|
+
expect(wrapper()?.props.importantForAccessibility).toBe('no-hide-descendants');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('does not flip the prop when no a11y service is running, even with an overlay active', async () => {
|
|
99
|
+
(AccessibilityInfo.isAccessibilityServiceEnabled as jest.Mock).mockResolvedValue(false);
|
|
100
|
+
renderShield('gallery');
|
|
101
|
+
// Allow the async isAccessibilityServiceEnabled() resolution to settle.
|
|
102
|
+
await act(async () => {
|
|
103
|
+
await Promise.resolve();
|
|
104
|
+
});
|
|
105
|
+
expect(wrapper()?.props.importantForAccessibility).toBeUndefined();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('on iOS', () => {
|
|
110
|
+
beforeAll(() => setPlatform('ios'));
|
|
111
|
+
|
|
112
|
+
it('renders children without a wrapper', () => {
|
|
113
|
+
renderShield();
|
|
114
|
+
expect(screen.getByTestId('child')).toBeTruthy();
|
|
115
|
+
expect(wrapper()).toBeNull();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -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(() => {
|
|
@@ -9,7 +9,7 @@ import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
|
9
9
|
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
|
|
10
10
|
|
|
11
11
|
import { primitives } from '../../theme';
|
|
12
|
-
import { getDateString } from '../../utils/i18n/getDateString';
|
|
12
|
+
import { getDateString, getDateStringForA11y } from '../../utils/i18n/getDateString';
|
|
13
13
|
|
|
14
14
|
export type ChannelPreviewStatusProps = Pick<
|
|
15
15
|
ChannelPreviewViewPropsWithContext,
|
|
@@ -19,7 +19,7 @@ export type ChannelPreviewStatusProps = Pick<
|
|
|
19
19
|
|
|
20
20
|
export const ChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
|
|
21
21
|
const { formatLatestMessageDate, lastMessage } = props;
|
|
22
|
-
const { t, tDateTimeParser } = useTranslationContext();
|
|
22
|
+
const { t, tDateTimeParser, userLanguage } = useTranslationContext();
|
|
23
23
|
const styles = useStyles();
|
|
24
24
|
|
|
25
25
|
const created_at = lastMessage?.created_at;
|
|
@@ -36,11 +36,25 @@ export const ChannelPreviewStatus = (props: ChannelPreviewStatusProps) => {
|
|
|
36
36
|
[created_at, t, tDateTimeParser],
|
|
37
37
|
);
|
|
38
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
|
+
|
|
39
50
|
const visibleDate =
|
|
40
51
|
formatLatestMessageDate && latestMessageDate
|
|
41
52
|
? formatLatestMessageDate(latestMessageDate).toString()
|
|
42
53
|
: formattedDate;
|
|
43
|
-
const labelParams = useMemo(
|
|
54
|
+
const labelParams = useMemo(
|
|
55
|
+
() => ({ date: a11yDate ?? visibleDate ?? '' }),
|
|
56
|
+
[a11yDate, visibleDate],
|
|
57
|
+
);
|
|
44
58
|
const accessibilityLabel = useA11yLabel('a11y/Last message {{date}}', labelParams);
|
|
45
59
|
|
|
46
60
|
return (
|
|
@@ -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
|
});
|