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
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
4
|
+
|
|
5
|
+
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react-native';
|
|
6
|
+
|
|
7
|
+
import { LocalMessage } from 'stream-chat';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
ImageGalleryContext,
|
|
11
|
+
ImageGalleryContextValue,
|
|
12
|
+
} from '../../../contexts/imageGalleryContext/ImageGalleryContext';
|
|
13
|
+
import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
|
|
14
|
+
import {
|
|
15
|
+
generateImageAttachment,
|
|
16
|
+
generateVideoAttachment,
|
|
17
|
+
} from '../../../mock-builders/generator/attachment';
|
|
18
|
+
import { generateMessage } from '../../../mock-builders/generator/message';
|
|
19
|
+
import { ImageGalleryStateStore } from '../../../state-store/image-gallery-state-store';
|
|
20
|
+
import { ImageGallery } from '../ImageGallery';
|
|
21
|
+
|
|
22
|
+
jest.mock('../../../native.ts', () => {
|
|
23
|
+
const { View } = require('react-native');
|
|
24
|
+
return {
|
|
25
|
+
isFileSystemAvailable: jest.fn(() => true),
|
|
26
|
+
isImageMediaLibraryAvailable: jest.fn(() => true),
|
|
27
|
+
isShareImageAvailable: jest.fn(() => true),
|
|
28
|
+
isVideoPlayerAvailable: jest.fn(() => true),
|
|
29
|
+
NativeHandlers: { Video: View },
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
type HarnessProps = {
|
|
34
|
+
message: LocalMessage;
|
|
35
|
+
accessibilityEnabled?: boolean;
|
|
36
|
+
store: ImageGalleryStateStore;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const Harness = ({ accessibilityEnabled = true, message, store }: HarnessProps) => {
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const unsubscribe = store.registerSubscriptions();
|
|
42
|
+
return () => unsubscribe();
|
|
43
|
+
}, [store]);
|
|
44
|
+
|
|
45
|
+
const { attachments } = message;
|
|
46
|
+
store.openImageGallery({
|
|
47
|
+
messages: [message],
|
|
48
|
+
selectedAttachmentUrl: attachments?.[0]?.asset_url || attachments?.[0]?.image_url || '',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<OverlayProvider
|
|
53
|
+
accessibility={{ enabled: accessibilityEnabled }}
|
|
54
|
+
value={{ overlayOpacity: { value: 1 } as SharedValue<number> }}
|
|
55
|
+
>
|
|
56
|
+
<ImageGalleryContext.Provider
|
|
57
|
+
value={{ imageGalleryStateStore: store } as unknown as ImageGalleryContextValue}
|
|
58
|
+
>
|
|
59
|
+
<ImageGallery />
|
|
60
|
+
</ImageGalleryContext.Provider>
|
|
61
|
+
</OverlayProvider>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const findGalleryRoot = () =>
|
|
66
|
+
screen.getByLabelText('Image Gallery', { includeHiddenElements: true });
|
|
67
|
+
|
|
68
|
+
const fireAccessibilityAction = (actionName: 'increment' | 'decrement') => {
|
|
69
|
+
fireEvent(findGalleryRoot(), 'accessibilityAction', { nativeEvent: { actionName } });
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const renderWithAssets = (assetsCount: number, accessibilityEnabled = true) => {
|
|
73
|
+
const attachments = [
|
|
74
|
+
...Array.from({ length: Math.max(assetsCount - 1, 0) }, () => generateImageAttachment()),
|
|
75
|
+
...(assetsCount > 0 ? [generateVideoAttachment({ type: 'video' })] : []),
|
|
76
|
+
];
|
|
77
|
+
const message = generateMessage({ attachments });
|
|
78
|
+
const store = new ImageGalleryStateStore();
|
|
79
|
+
render(<Harness accessibilityEnabled={accessibilityEnabled} message={message} store={store} />);
|
|
80
|
+
return { store };
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
describe('ImageGallery adjustable cycling', () => {
|
|
84
|
+
it('marks the root as adjustable with the position value when a11y is enabled and there is more than one asset', async () => {
|
|
85
|
+
renderWithAssets(3);
|
|
86
|
+
|
|
87
|
+
await waitFor(() => {
|
|
88
|
+
const root = findGalleryRoot();
|
|
89
|
+
expect(root.props.accessibilityRole).toBe('adjustable');
|
|
90
|
+
expect(root.props.accessibilityValue).toEqual({ text: '1 of 3' });
|
|
91
|
+
expect(root.props.accessibilityActions).toEqual([
|
|
92
|
+
{ name: 'increment' },
|
|
93
|
+
{ name: 'decrement' },
|
|
94
|
+
]);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('does not apply the adjustable role when accessibility is disabled', async () => {
|
|
99
|
+
renderWithAssets(3, false);
|
|
100
|
+
|
|
101
|
+
await waitFor(() => {
|
|
102
|
+
const root = findGalleryRoot();
|
|
103
|
+
expect(root.props.accessibilityRole).toBeUndefined();
|
|
104
|
+
expect(root.props.accessibilityActions).toBeUndefined();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('moves to the next asset on increment and clamps at the last asset', async () => {
|
|
109
|
+
const { store } = renderWithAssets(3);
|
|
110
|
+
|
|
111
|
+
await waitFor(() => expect(findGalleryRoot().props.accessibilityRole).toBe('adjustable'));
|
|
112
|
+
|
|
113
|
+
act(() => fireAccessibilityAction('increment'));
|
|
114
|
+
expect(store.state.getLatestValue().currentIndex).toBe(1);
|
|
115
|
+
|
|
116
|
+
act(() => fireAccessibilityAction('increment'));
|
|
117
|
+
expect(store.state.getLatestValue().currentIndex).toBe(2);
|
|
118
|
+
|
|
119
|
+
act(() => fireAccessibilityAction('increment'));
|
|
120
|
+
expect(store.state.getLatestValue().currentIndex).toBe(2);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('moves to the previous asset on decrement and clamps at the first asset', async () => {
|
|
124
|
+
const { store } = renderWithAssets(3);
|
|
125
|
+
|
|
126
|
+
await waitFor(() => expect(findGalleryRoot().props.accessibilityRole).toBe('adjustable'));
|
|
127
|
+
|
|
128
|
+
act(() => fireAccessibilityAction('increment'));
|
|
129
|
+
act(() => fireAccessibilityAction('increment'));
|
|
130
|
+
expect(store.state.getLatestValue().currentIndex).toBe(2);
|
|
131
|
+
|
|
132
|
+
act(() => fireAccessibilityAction('decrement'));
|
|
133
|
+
expect(store.state.getLatestValue().currentIndex).toBe(1);
|
|
134
|
+
|
|
135
|
+
act(() => fireAccessibilityAction('decrement'));
|
|
136
|
+
expect(store.state.getLatestValue().currentIndex).toBe(0);
|
|
137
|
+
|
|
138
|
+
act(() => fireAccessibilityAction('decrement'));
|
|
139
|
+
expect(store.state.getLatestValue().currentIndex).toBe(0);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -33,7 +33,13 @@ const MessageReminderHeaderWithContext = (props: MessageReminderHeaderPropsWithC
|
|
|
33
33
|
<Text style={styles.label}>
|
|
34
34
|
{isReminderTimeLeft ? t('Reminder set') : t('Reminder overdue')}
|
|
35
35
|
</Text>
|
|
36
|
-
<Text
|
|
36
|
+
<Text
|
|
37
|
+
accessibilityElementsHidden
|
|
38
|
+
importantForAccessibility='no-hide-descendants'
|
|
39
|
+
style={styles.dot}
|
|
40
|
+
>
|
|
41
|
+
·
|
|
42
|
+
</Text>
|
|
37
43
|
<Text style={styles.time}>
|
|
38
44
|
{t('duration/Message reminder', {
|
|
39
45
|
milliseconds: timeLeftMs,
|
|
@@ -43,7 +43,13 @@ const SentToChannelHeaderWithContext = (props: SentToChannelHeaderPropsWithConte
|
|
|
43
43
|
</Text>
|
|
44
44
|
{showViewText ? (
|
|
45
45
|
<>
|
|
46
|
-
<Text
|
|
46
|
+
<Text
|
|
47
|
+
accessibilityElementsHidden
|
|
48
|
+
importantForAccessibility='no-hide-descendants'
|
|
49
|
+
style={styles.dot}
|
|
50
|
+
>
|
|
51
|
+
·
|
|
52
|
+
</Text>
|
|
47
53
|
<Pressable onPress={onPress}>
|
|
48
54
|
<Text style={styles.link}>{t('View')}</Text>
|
|
49
55
|
</Pressable>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import { ColorValue, Pressable, StyleSheet, View, ViewStyle } from 'react-native';
|
|
2
|
+
import { ColorValue, Platform, Pressable, StyleSheet, View, ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { MessageTextContainer } from './MessageTextContainer';
|
|
5
5
|
|
|
@@ -55,6 +55,7 @@ export type MessageContentPropsWithContext = Pick<
|
|
|
55
55
|
| 'alignment'
|
|
56
56
|
| 'goToMessage'
|
|
57
57
|
| 'groupStyles'
|
|
58
|
+
| 'hasInteractiveAccessibilityContent'
|
|
58
59
|
| 'isMyMessage'
|
|
59
60
|
| 'message'
|
|
60
61
|
| 'messageContentOrder'
|
|
@@ -111,6 +112,7 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
|
|
|
111
112
|
enableMessageGroupingByUser,
|
|
112
113
|
groupStyles,
|
|
113
114
|
goToMessage,
|
|
115
|
+
hasInteractiveAccessibilityContent,
|
|
114
116
|
isMessageAIGenerated,
|
|
115
117
|
isMyMessage,
|
|
116
118
|
isVeryLastMessage,
|
|
@@ -129,6 +131,10 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
|
|
|
129
131
|
} = props;
|
|
130
132
|
const { client } = useChatContext();
|
|
131
133
|
const accessibilityHint = useA11yLabel('a11y/Double tap and hold to activate contextual menu');
|
|
134
|
+
const a11ySenderLabel = useA11yLabel(
|
|
135
|
+
isMyMessage ? 'a11y/Message from you' : 'a11y/Message from {{sender}}',
|
|
136
|
+
isMyMessage ? undefined : { sender: message.user?.name || message.user?.id || '' },
|
|
137
|
+
);
|
|
132
138
|
const {
|
|
133
139
|
Attachment,
|
|
134
140
|
FileAttachmentGroup,
|
|
@@ -317,22 +323,18 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
|
|
|
317
323
|
)}
|
|
318
324
|
</>
|
|
319
325
|
);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
message.poll_id ||
|
|
327
|
-
message.quoted_message ||
|
|
328
|
-
message.attachments?.length ||
|
|
329
|
-
message.shared_location
|
|
330
|
-
);
|
|
326
|
+
const a11yPressableLabel = useMemo(() => {
|
|
327
|
+
if (!a11ySenderLabel) return undefined;
|
|
328
|
+
return message.text && !hasInteractiveAccessibilityContent
|
|
329
|
+
? `${a11ySenderLabel}. ${message.text}`
|
|
330
|
+
: a11ySenderLabel;
|
|
331
|
+
}, [a11ySenderLabel, hasInteractiveAccessibilityContent, message.text]);
|
|
331
332
|
|
|
332
333
|
return (
|
|
333
334
|
<Pressable
|
|
335
|
+
accessibilityLabel={a11yPressableLabel}
|
|
334
336
|
accessibilityHint={accessibilityHint}
|
|
335
|
-
accessible={
|
|
337
|
+
accessible={hasInteractiveAccessibilityContent ? false : undefined}
|
|
336
338
|
disabled={preventPress}
|
|
337
339
|
onLongPress={(event) => {
|
|
338
340
|
if (onLongPress) {
|
|
@@ -382,6 +384,15 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
|
|
|
382
384
|
]}
|
|
383
385
|
testID='message-content-wrapper'
|
|
384
386
|
>
|
|
387
|
+
{a11ySenderLabel && Platform.OS !== 'android' && hasInteractiveAccessibilityContent ? (
|
|
388
|
+
<View
|
|
389
|
+
accessibilityLabel={a11ySenderLabel}
|
|
390
|
+
accessibilityHint={accessibilityHint}
|
|
391
|
+
accessible
|
|
392
|
+
pointerEvents='none'
|
|
393
|
+
style={StyleSheet.absoluteFill}
|
|
394
|
+
/>
|
|
395
|
+
) : null}
|
|
385
396
|
{MessageContentTopView ? <MessageContentTopView /> : null}
|
|
386
397
|
{hasContentSideViews ? (
|
|
387
398
|
<View
|
|
@@ -414,6 +425,7 @@ const areEqual = (
|
|
|
414
425
|
preventPress: prevPreventPress,
|
|
415
426
|
goToMessage: prevGoToMessage,
|
|
416
427
|
groupStyles: prevGroupStyles,
|
|
428
|
+
hasInteractiveAccessibilityContent: prevHasInteractiveAccessibilityContent,
|
|
417
429
|
isAttachmentEqual,
|
|
418
430
|
message: prevMessage,
|
|
419
431
|
messageContentOrder: prevMessageContentOrder,
|
|
@@ -427,6 +439,7 @@ const areEqual = (
|
|
|
427
439
|
preventPress: nextPreventPress,
|
|
428
440
|
goToMessage: nextGoToMessage,
|
|
429
441
|
groupStyles: nextGroupStyles,
|
|
442
|
+
hasInteractiveAccessibilityContent: nextHasInteractiveAccessibilityContent,
|
|
430
443
|
message: nextMessage,
|
|
431
444
|
messageContentOrder: nextMessageContentOrder,
|
|
432
445
|
myMessageTheme: nextMyMessageTheme,
|
|
@@ -434,6 +447,10 @@ const areEqual = (
|
|
|
434
447
|
t: nextT,
|
|
435
448
|
} = nextProps;
|
|
436
449
|
|
|
450
|
+
if (prevHasInteractiveAccessibilityContent !== nextHasInteractiveAccessibilityContent) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
|
|
437
454
|
if (prevBackgroundColor !== nextBackgroundColor) {
|
|
438
455
|
return false;
|
|
439
456
|
}
|
|
@@ -569,8 +586,11 @@ export type MessageContentProps = Partial<MessageContentPropsWithContext>;
|
|
|
569
586
|
export const MessageContent = (props: MessageContentProps) => {
|
|
570
587
|
const {
|
|
571
588
|
alignment,
|
|
589
|
+
files,
|
|
572
590
|
goToMessage,
|
|
573
591
|
groupStyles,
|
|
592
|
+
hasInteractiveAccessibilityContent,
|
|
593
|
+
images,
|
|
574
594
|
isMessageAIGenerated,
|
|
575
595
|
isMyMessage,
|
|
576
596
|
message,
|
|
@@ -581,8 +601,6 @@ export const MessageContent = (props: MessageContentProps) => {
|
|
|
581
601
|
otherAttachments,
|
|
582
602
|
preventPress,
|
|
583
603
|
threadList,
|
|
584
|
-
files,
|
|
585
|
-
images,
|
|
586
604
|
videos,
|
|
587
605
|
} = useMessageContext();
|
|
588
606
|
const {
|
|
@@ -637,6 +655,7 @@ export const MessageContent = (props: MessageContentProps) => {
|
|
|
637
655
|
enableMessageGroupingByUser,
|
|
638
656
|
goToMessage,
|
|
639
657
|
groupStyles,
|
|
658
|
+
hasInteractiveAccessibilityContent,
|
|
640
659
|
isAttachmentEqual,
|
|
641
660
|
isMessageAIGenerated,
|
|
642
661
|
isMyMessage,
|
|
@@ -75,10 +75,18 @@ const MessageRepliesWithContext = (props: MessageRepliesPropsWithContext) => {
|
|
|
75
75
|
return null;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const replyCountLabel =
|
|
79
|
+
message.reply_count === 1
|
|
80
|
+
? t('1 Reply')
|
|
81
|
+
: t('{{ replyCount }} Replies', { replyCount: message.reply_count });
|
|
82
|
+
|
|
78
83
|
return (
|
|
79
84
|
<View style={[styles.container, container]}>
|
|
80
85
|
{alignment === 'left' ? connector : null}
|
|
81
86
|
<Pressable
|
|
87
|
+
accessibilityHint={t('a11y/Double tap to view thread')}
|
|
88
|
+
accessibilityLabel={replyCountLabel}
|
|
89
|
+
accessibilityRole='button'
|
|
82
90
|
disabled={preventPress}
|
|
83
91
|
onLongPress={(event) => {
|
|
84
92
|
if (onLongPress) {
|
|
@@ -114,13 +122,7 @@ const MessageRepliesWithContext = (props: MessageRepliesPropsWithContext) => {
|
|
|
114
122
|
testID='message-replies'
|
|
115
123
|
>
|
|
116
124
|
<MessageRepliesAvatars />
|
|
117
|
-
<Text style={[styles.messageRepliesText, messageRepliesText]}>
|
|
118
|
-
{message.reply_count === 1
|
|
119
|
-
? t('1 Reply')
|
|
120
|
-
: t('{{ replyCount }} Replies', {
|
|
121
|
-
replyCount: message.reply_count,
|
|
122
|
-
})}
|
|
123
|
-
</Text>
|
|
125
|
+
<Text style={[styles.messageRepliesText, messageRepliesText]}>{replyCountLabel}</Text>
|
|
124
126
|
</Pressable>
|
|
125
127
|
{alignment === 'right' ? connector : null}
|
|
126
128
|
</View>
|
|
@@ -24,7 +24,11 @@ export const MessageRepliesAvatarsWithContext = (props: MessageRepliesAvatarsPro
|
|
|
24
24
|
const avatars = message?.thread_participants || [];
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
|
-
<View
|
|
27
|
+
<View
|
|
28
|
+
accessibilityElementsHidden
|
|
29
|
+
importantForAccessibility='no-hide-descendants'
|
|
30
|
+
style={avatarStackContainer}
|
|
31
|
+
>
|
|
28
32
|
<UserAvatarStack users={avatars} avatarSize='sm' maxVisible={3} overlap={0.4} />
|
|
29
33
|
</View>
|
|
30
34
|
);
|
|
@@ -31,7 +31,13 @@ export type MessageTextProps = MessageTextContainerProps & {
|
|
|
31
31
|
|
|
32
32
|
export type MessageTextContainerPropsWithContext = Pick<
|
|
33
33
|
MessageContextValue,
|
|
34
|
-
|
|
34
|
+
| 'hasInteractiveAccessibilityContent'
|
|
35
|
+
| 'isMyMessage'
|
|
36
|
+
| 'message'
|
|
37
|
+
| 'onLongPress'
|
|
38
|
+
| 'onlyEmojis'
|
|
39
|
+
| 'onPress'
|
|
40
|
+
| 'preventPress'
|
|
35
41
|
> &
|
|
36
42
|
Pick<MessagesContextValue, 'markdownRules' | 'myMessageTheme' | 'messageTextNumberOfLines'> & {
|
|
37
43
|
markdownStyles?: MarkdownStyle;
|
|
@@ -45,6 +51,7 @@ const MessageTextContainerWithContext = (props: MessageTextContainerPropsWithCon
|
|
|
45
51
|
const theme = useTheme();
|
|
46
52
|
|
|
47
53
|
const {
|
|
54
|
+
hasInteractiveAccessibilityContent,
|
|
48
55
|
isMyMessage,
|
|
49
56
|
markdownRules,
|
|
50
57
|
markdownStyles: markdownStylesProp = {},
|
|
@@ -81,6 +88,8 @@ const MessageTextContainerWithContext = (props: MessageTextContainerPropsWithCon
|
|
|
81
88
|
|
|
82
89
|
return (
|
|
83
90
|
<View
|
|
91
|
+
accessible={hasInteractiveAccessibilityContent || undefined}
|
|
92
|
+
accessibilityRole={hasInteractiveAccessibilityContent ? 'text' : undefined}
|
|
84
93
|
style={[styles.textContainer, textContainer, stylesProp.textContainer]}
|
|
85
94
|
testID='message-text-container'
|
|
86
95
|
>
|
|
@@ -113,18 +122,24 @@ const areEqual = (
|
|
|
113
122
|
nextProps: MessageTextContainerPropsWithContext,
|
|
114
123
|
) => {
|
|
115
124
|
const {
|
|
125
|
+
hasInteractiveAccessibilityContent: prevHasInteractiveAccessibilityContent,
|
|
116
126
|
markdownStyles: prevMarkdownStyles,
|
|
117
127
|
message: prevMessage,
|
|
118
128
|
myMessageTheme: prevMyMessageTheme,
|
|
119
129
|
onlyEmojis: prevOnlyEmojis,
|
|
120
130
|
} = prevProps;
|
|
121
131
|
const {
|
|
132
|
+
hasInteractiveAccessibilityContent: nextHasInteractiveAccessibilityContent,
|
|
122
133
|
markdownStyles: nextMarkdownStyles,
|
|
123
134
|
message: nextMessage,
|
|
124
135
|
myMessageTheme: nextMyMessageTheme,
|
|
125
136
|
onlyEmojis: nextOnlyEmojis,
|
|
126
137
|
} = nextProps;
|
|
127
138
|
|
|
139
|
+
if (prevHasInteractiveAccessibilityContent !== nextHasInteractiveAccessibilityContent) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
|
|
128
143
|
const messageStatusEqual = prevMessage.status === nextMessage.status;
|
|
129
144
|
if (!messageStatusEqual) {
|
|
130
145
|
return false;
|
|
@@ -182,16 +197,24 @@ const MemoizedMessageTextContainer = React.memo(
|
|
|
182
197
|
export type MessageTextContainerProps = Partial<MessageTextContainerPropsWithContext>;
|
|
183
198
|
|
|
184
199
|
export const MessageTextContainer = (props: MessageTextContainerProps) => {
|
|
185
|
-
const {
|
|
186
|
-
|
|
200
|
+
const {
|
|
201
|
+
hasInteractiveAccessibilityContent,
|
|
202
|
+
isMyMessage,
|
|
203
|
+
message,
|
|
204
|
+
onLongPress,
|
|
205
|
+
onlyEmojis,
|
|
206
|
+
onPress,
|
|
207
|
+
preventPress,
|
|
208
|
+
} = useMessageContext();
|
|
187
209
|
const { markdownRules, messageTextNumberOfLines, myMessageTheme } = useMessagesContext();
|
|
188
210
|
|
|
189
211
|
return (
|
|
190
212
|
<MemoizedMessageTextContainer
|
|
191
213
|
{...{
|
|
214
|
+
hasInteractiveAccessibilityContent,
|
|
215
|
+
isMyMessage,
|
|
192
216
|
markdownRules,
|
|
193
217
|
message,
|
|
194
|
-
isMyMessage,
|
|
195
218
|
messageTextNumberOfLines,
|
|
196
219
|
myMessageTheme,
|
|
197
220
|
onLongPress,
|
|
@@ -171,10 +171,17 @@ describe('Message', () => {
|
|
|
171
171
|
|
|
172
172
|
fireEvent(getByTestId('custom-overlay-trigger'), 'longPress');
|
|
173
173
|
|
|
174
|
+
// Once the overlay opens, the host layer's `accessibilityViewIsModal`
|
|
175
|
+
// marks the chat-side subtree as hidden to RNTL. The overlay target's
|
|
176
|
+
// children are Portal-teleported but their React parent stays in the
|
|
177
|
+
// chat, so default visibility filtering excludes them. Pass
|
|
178
|
+
// `includeHiddenElements` to look past the modal-sibling heuristic.
|
|
174
179
|
await waitFor(() => {
|
|
175
|
-
expect(getByText('outside:normal')).toBeTruthy();
|
|
176
|
-
expect(getByText('inside:overlay')).toBeTruthy();
|
|
177
|
-
expect(
|
|
180
|
+
expect(getByText('outside:normal', { includeHiddenElements: true })).toBeTruthy();
|
|
181
|
+
expect(getByText('inside:overlay', { includeHiddenElements: true })).toBeTruthy();
|
|
182
|
+
expect(
|
|
183
|
+
getByTestId('custom-overlay-target-placeholder', { includeHiddenElements: true }),
|
|
184
|
+
).toBeTruthy();
|
|
178
185
|
});
|
|
179
186
|
});
|
|
180
187
|
});
|
|
@@ -33,7 +33,11 @@ describe('MessageReplies', () => {
|
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
await waitFor(() => {
|
|
36
|
-
|
|
36
|
+
const pluralPressable = screen.getByTestId('message-replies');
|
|
37
|
+
expect(pluralPressable).toBeTruthy();
|
|
38
|
+
expect(pluralPressable.props.accessibilityRole).toBe('button');
|
|
39
|
+
expect(pluralPressable.props.accessibilityLabel).toBe('{{ replyCount }} Replies');
|
|
40
|
+
expect(pluralPressable.props.accessibilityHint).toBe('a11y/Double tap to view thread');
|
|
37
41
|
expect(t).toHaveBeenCalledWith('{{ replyCount }} Replies', {
|
|
38
42
|
replyCount: message.reply_count,
|
|
39
43
|
});
|
|
@@ -57,7 +61,11 @@ describe('MessageReplies', () => {
|
|
|
57
61
|
|
|
58
62
|
await waitFor(() => {
|
|
59
63
|
expect(onPressMock).toHaveBeenCalled();
|
|
60
|
-
|
|
64
|
+
const singularPressable = screen.getByTestId('message-replies');
|
|
65
|
+
expect(singularPressable).toBeTruthy();
|
|
66
|
+
expect(singularPressable.props.accessibilityRole).toBe('button');
|
|
67
|
+
expect(singularPressable.props.accessibilityLabel).toBe('1 Reply');
|
|
68
|
+
expect(singularPressable.props.accessibilityHint).toBe('a11y/Double tap to view thread');
|
|
61
69
|
expect(t).toHaveBeenCalledWith('1 Reply');
|
|
62
70
|
expect(screen.getByText('1 Reply')).toBeTruthy();
|
|
63
71
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useMemo, useRef } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useAccessibilityContext } from '../../../contexts/accessibilityContext/AccessibilityContext';
|
|
3
4
|
import type { MessageContextValue } from '../../../contexts/messageContext/MessageContext';
|
|
4
5
|
|
|
5
6
|
import { stringifyMessage } from '../../../utils/utils';
|
|
@@ -58,7 +59,7 @@ export const useCreateMessageContext = ({
|
|
|
58
59
|
threadList,
|
|
59
60
|
videos,
|
|
60
61
|
setQuotedMessage,
|
|
61
|
-
}: MessageContextValue) => {
|
|
62
|
+
}: Omit<MessageContextValue, 'hasInteractiveAccessibilityContent'>) => {
|
|
62
63
|
const stableGroupStyles = useStableRefValue(groupStyles);
|
|
63
64
|
const reactionsValue = reactions.map(({ count, own, type }) => `${own}${type}${count}`).join();
|
|
64
65
|
const stringifiedMessage = stringifyMessage({ message });
|
|
@@ -70,6 +71,14 @@ export const useCreateMessageContext = ({
|
|
|
70
71
|
? stringifyMessage({ includeReactions: false, message: message.quoted_message })
|
|
71
72
|
: '';
|
|
72
73
|
|
|
74
|
+
// Resolved here (not at each consumer) so the boolean lives on MessageContext
|
|
75
|
+
// and downstream components (MessageContent, MessageTextContainer) read it
|
|
76
|
+
// directly. The predicate's identity is stable in the default case; an
|
|
77
|
+
// integrator override is expected to be stable too (documented on the config).
|
|
78
|
+
const { hasInteractiveAccessibilityContent: hasInteractiveAccessibilityContentPredicate } =
|
|
79
|
+
useAccessibilityContext();
|
|
80
|
+
const hasInteractiveAccessibilityContent = hasInteractiveAccessibilityContentPredicate(message);
|
|
81
|
+
|
|
73
82
|
const messageContext: MessageContextValue = useMemo(
|
|
74
83
|
() => ({
|
|
75
84
|
actionsEnabled,
|
|
@@ -85,6 +94,7 @@ export const useCreateMessageContext = ({
|
|
|
85
94
|
hasAttachmentActions,
|
|
86
95
|
handleReaction,
|
|
87
96
|
handleToggleReaction,
|
|
97
|
+
hasInteractiveAccessibilityContent,
|
|
88
98
|
hasReactions,
|
|
89
99
|
messageHasOnlySingleAttachment,
|
|
90
100
|
images,
|
|
@@ -123,6 +133,7 @@ export const useCreateMessageContext = ({
|
|
|
123
133
|
goToMessage,
|
|
124
134
|
stableGroupStyles,
|
|
125
135
|
hasAttachmentActions,
|
|
136
|
+
hasInteractiveAccessibilityContent,
|
|
126
137
|
hasReactions,
|
|
127
138
|
messageHasOnlySingleAttachment,
|
|
128
139
|
lastGroupMessage,
|
|
@@ -818,6 +818,7 @@ exports[`AttachButton should call handleAttachButtonPress when the button is cli
|
|
|
818
818
|
</View>
|
|
819
819
|
</View>
|
|
820
820
|
<View
|
|
821
|
+
accessibilityViewIsModal={false}
|
|
821
822
|
collapsable={false}
|
|
822
823
|
pointerEvents="box-none"
|
|
823
824
|
style={
|
|
@@ -1733,6 +1734,7 @@ exports[`AttachButton should render a enabled AttachButton 1`] = `
|
|
|
1733
1734
|
</View>
|
|
1734
1735
|
</View>
|
|
1735
1736
|
<View
|
|
1737
|
+
accessibilityViewIsModal={false}
|
|
1736
1738
|
collapsable={false}
|
|
1737
1739
|
pointerEvents="box-none"
|
|
1738
1740
|
style={
|
|
@@ -2648,6 +2650,7 @@ exports[`AttachButton should render an disabled AttachButton 1`] = `
|
|
|
2648
2650
|
</View>
|
|
2649
2651
|
</View>
|
|
2650
2652
|
<View
|
|
2653
|
+
accessibilityViewIsModal={false}
|
|
2651
2654
|
collapsable={false}
|
|
2652
2655
|
pointerEvents="box-none"
|
|
2653
2656
|
style={
|
|
@@ -816,6 +816,7 @@ exports[`SendButton should render a SendButton 1`] = `
|
|
|
816
816
|
</View>
|
|
817
817
|
</View>
|
|
818
818
|
<View
|
|
819
|
+
accessibilityViewIsModal={false}
|
|
819
820
|
collapsable={false}
|
|
820
821
|
pointerEvents="box-none"
|
|
821
822
|
style={
|
|
@@ -1729,6 +1730,7 @@ exports[`SendButton should render a disabled SendButton 1`] = `
|
|
|
1729
1730
|
</View>
|
|
1730
1731
|
</View>
|
|
1731
1732
|
<View
|
|
1733
|
+
accessibilityViewIsModal={false}
|
|
1732
1734
|
collapsable={false}
|
|
1733
1735
|
pointerEvents="box-none"
|
|
1734
1736
|
style={
|
|
@@ -4,7 +4,7 @@ import { StyleSheet, Text, View } from 'react-native';
|
|
|
4
4
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
5
5
|
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
|
|
6
6
|
import { primitives } from '../../theme';
|
|
7
|
-
import { getDateString } from '../../utils/i18n/getDateString';
|
|
7
|
+
import { getDateString, getDateStringForA11y } from '../../utils/i18n/getDateString';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Props for the `InlineDateSeparator` component.
|
|
@@ -17,7 +17,7 @@ export type InlineDateSeparatorProps = {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
export const InlineDateSeparator = ({ date }: InlineDateSeparatorProps) => {
|
|
20
|
-
const { t, tDateTimeParser } = useTranslationContext();
|
|
20
|
+
const { t, tDateTimeParser, userLanguage } = useTranslationContext();
|
|
21
21
|
const styles = useStyles();
|
|
22
22
|
|
|
23
23
|
const dateString = useMemo(
|
|
@@ -31,9 +31,16 @@ export const InlineDateSeparator = ({ date }: InlineDateSeparatorProps) => {
|
|
|
31
31
|
[date, t, tDateTimeParser],
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
+
const a11yDateString = useMemo(
|
|
35
|
+
() => getDateStringForA11y({ date, tDateTimeParser, userLanguage }),
|
|
36
|
+
[date, tDateTimeParser, userLanguage],
|
|
37
|
+
);
|
|
38
|
+
|
|
34
39
|
return (
|
|
35
40
|
<View style={styles.container} testID='date-separator'>
|
|
36
|
-
<Text style={styles.text}>
|
|
41
|
+
<Text accessibilityLabel={a11yDateString} style={styles.text}>
|
|
42
|
+
{dateString}
|
|
43
|
+
</Text>
|
|
37
44
|
</View>
|
|
38
45
|
);
|
|
39
46
|
};
|
|
@@ -49,17 +49,10 @@ export const ReactionButton = (props: ReactionButtonProps) => {
|
|
|
49
49
|
() => <Icon size={reactionIconSize ?? 24} />,
|
|
50
50
|
[Icon, reactionIconSize],
|
|
51
51
|
);
|
|
52
|
-
const selectedLabelState = selected ? 'selected' : 'unselected';
|
|
53
|
-
const accessibilityLabelParams = useMemo(
|
|
54
|
-
() => ({ selected: selectedLabelState, type }),
|
|
55
|
-
[selectedLabelState, type],
|
|
56
|
-
);
|
|
57
52
|
|
|
58
53
|
return (
|
|
59
54
|
<View style={styles.reactionButton}>
|
|
60
55
|
<Button
|
|
61
|
-
accessibilityLabelKey='a11y/reaction-button-{{type}}-{{selected}}'
|
|
62
|
-
accessibilityLabelParams={accessibilityLabelParams}
|
|
63
56
|
variant={'secondary'}
|
|
64
57
|
type={'outline'}
|
|
65
58
|
iconOnly={!count}
|
|
@@ -2,9 +2,8 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { Text } from 'react-native';
|
|
4
4
|
|
|
5
|
-
import { cleanup, fireEvent, render
|
|
5
|
+
import { cleanup, fireEvent, render } from '@testing-library/react-native';
|
|
6
6
|
|
|
7
|
-
import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
|
|
8
7
|
import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
|
|
9
8
|
import { defaultTheme } from '../../../contexts/themeContext/utils/theme';
|
|
10
9
|
import { IconProps } from '../../../icons';
|
|
@@ -38,18 +37,6 @@ describe('ReactionButton', () => {
|
|
|
38
37
|
expect(getByText('24')).toBeTruthy();
|
|
39
38
|
});
|
|
40
39
|
|
|
41
|
-
it('uses the released reaction button label when accessibility labels are translated', async () => {
|
|
42
|
-
render(
|
|
43
|
-
<OverlayProvider accessibility={{ enabled: true }}>
|
|
44
|
-
<ReactionButton {...defaultProps} />
|
|
45
|
-
</OverlayProvider>,
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
await waitFor(() => {
|
|
49
|
-
expect(screen.getByLabelText('reaction-button-like-unselected')).toBeTruthy();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
40
|
it('should call onPress function with the correct reaction type when pressed', () => {
|
|
54
41
|
const { getByRole } = render(
|
|
55
42
|
<ThemeProvider theme={defaultTheme}>
|