stream-chat-react-native-core 9.0.0-beta.32 → 9.0.0-beta.34
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/components/Attachment/Giphy/Giphy.js +5 -3
- package/lib/commonjs/components/Attachment/Giphy/Giphy.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +0 -3
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +0 -2
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/commonjs/components/ChannelList/ChannelListView.js +6 -6
- package/lib/commonjs/components/ChannelList/ChannelListView.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreview.js +3 -3
- package/lib/commonjs/components/ChannelPreview/ChannelPreview.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewMessage.js +9 -9
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewMessage.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js +13 -13
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
- package/lib/commonjs/components/Message/MessageItemView/MessageItemView.js +5 -2
- package/lib/commonjs/components/Message/MessageItemView/MessageItemView.js.map +1 -1
- package/lib/commonjs/components/MessageList/hooks/useMessageList.js +2 -35
- package/lib/commonjs/components/MessageList/hooks/useMessageList.js.map +1 -1
- package/lib/commonjs/contexts/channelsContext/ChannelsContext.js.map +1 -1
- package/lib/commonjs/contexts/componentsContext/PLAN.md +15 -15
- package/lib/commonjs/contexts/componentsContext/defaultComponents.js +14 -13
- package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/commonjs/contexts/overlayContext/MessageOverlayHostLayer.js +30 -22
- package/lib/commonjs/contexts/overlayContext/MessageOverlayHostLayer.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/Giphy/Giphy.js +5 -3
- package/lib/module/components/Attachment/Giphy/Giphy.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +0 -3
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +0 -2
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/module/components/ChannelList/ChannelListView.js +6 -6
- package/lib/module/components/ChannelList/ChannelListView.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreview.js +3 -3
- package/lib/module/components/ChannelPreview/ChannelPreview.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewMessage.js +9 -9
- package/lib/module/components/ChannelPreview/ChannelPreviewMessage.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewView.js +13 -13
- package/lib/module/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
- package/lib/module/components/Message/MessageItemView/MessageItemView.js +5 -2
- package/lib/module/components/Message/MessageItemView/MessageItemView.js.map +1 -1
- package/lib/module/components/MessageList/hooks/useMessageList.js +2 -35
- package/lib/module/components/MessageList/hooks/useMessageList.js.map +1 -1
- package/lib/module/contexts/channelsContext/ChannelsContext.js.map +1 -1
- package/lib/module/contexts/componentsContext/PLAN.md +15 -15
- package/lib/module/contexts/componentsContext/defaultComponents.js +14 -13
- package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
- package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/module/contexts/overlayContext/MessageOverlayHostLayer.js +30 -22
- package/lib/module/contexts/overlayContext/MessageOverlayHostLayer.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/ChannelListView.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewMessage.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageItemView/MessageItemView.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/hooks/useMessageList.d.ts +0 -5
- package/lib/typescript/components/MessageList/hooks/useMessageList.d.ts.map +1 -1
- package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts +2 -1
- package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts.map +1 -1
- package/lib/typescript/contexts/componentsContext/ComponentsContext.d.ts +14 -13
- package/lib/typescript/contexts/componentsContext/ComponentsContext.d.ts.map +1 -1
- package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +15 -13
- package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
- package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +0 -8
- package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts.map +1 -1
- package/lib/typescript/contexts/overlayContext/MessageOverlayHostLayer.d.ts +7 -0
- package/lib/typescript/contexts/overlayContext/MessageOverlayHostLayer.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/offline-support/offline-feature.js +12 -4
- package/src/components/Attachment/Giphy/Giphy.tsx +11 -6
- package/src/components/Attachment/__tests__/Giphy.test.js +25 -0
- package/src/components/Channel/Channel.tsx +0 -3
- package/src/components/Channel/hooks/useCreateMessagesContext.ts +0 -2
- package/src/components/ChannelList/ChannelListView.tsx +6 -5
- package/src/components/ChannelList/__tests__/ChannelList.test.js +35 -35
- package/src/components/ChannelPreview/ChannelPreview.tsx +3 -3
- package/src/components/ChannelPreview/ChannelPreviewMessage.tsx +11 -8
- package/src/components/ChannelPreview/ChannelPreviewView.tsx +17 -13
- package/src/components/ChannelPreview/__tests__/ChannelPreview.test.tsx +2 -2
- package/src/components/Message/MessageItemView/MessageItemView.tsx +2 -0
- package/src/components/MessageList/__tests__/MessageList.test.js +1 -130
- package/src/components/MessageList/hooks/useMessageList.ts +1 -41
- package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +24 -4
- package/src/contexts/channelsContext/ChannelsContext.tsx +2 -1
- package/src/contexts/componentsContext/PLAN.md +15 -15
- package/src/contexts/componentsContext/__tests__/defaultComponents.test.ts +1 -0
- package/src/contexts/componentsContext/defaultComponents.ts +15 -13
- package/src/contexts/messagesContext/MessagesContext.tsx +0 -9
- package/src/contexts/overlayContext/MessageOverlayHostLayer.tsx +36 -16
- package/src/contexts/overlayContext/__tests__/MessageOverlayHostLayer.test.tsx +59 -1
- package/src/version.json +1 -1
|
@@ -92,7 +92,7 @@ describe('MessageList', () => {
|
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
it('should render deleted message in the list
|
|
95
|
+
it('should render deleted message in the list', async () => {
|
|
96
96
|
const user1 = generateUser();
|
|
97
97
|
const mockedChannel = generateChannelResponse({
|
|
98
98
|
members: [generateMember({ user: user1 })],
|
|
@@ -124,135 +124,6 @@ describe('MessageList', () => {
|
|
|
124
124
|
});
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
it('should render deleted message in the list when `deleteMessagesVisibilityType` is set to sender', async () => {
|
|
128
|
-
const user1 = generateUser();
|
|
129
|
-
const user2 = generateUser({ id: 'testID' });
|
|
130
|
-
const mockedChannel = generateChannelResponse({
|
|
131
|
-
members: [generateMember({ user: user1 })],
|
|
132
|
-
messages: [
|
|
133
|
-
generateMessage({ type: 'deleted', user: user2 }),
|
|
134
|
-
generateMessage({ type: 'system', user: undefined }),
|
|
135
|
-
generateMessage({ user: user1 }),
|
|
136
|
-
],
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
const chatClient = await getTestClientWithUser({ id: 'testID' });
|
|
140
|
-
useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
|
|
141
|
-
const channel = chatClient.channel('messaging', mockedChannel.id);
|
|
142
|
-
await channel.watch();
|
|
143
|
-
|
|
144
|
-
const { queryByTestId } = render(
|
|
145
|
-
<OverlayProvider>
|
|
146
|
-
<Chat client={chatClient}>
|
|
147
|
-
<Channel channel={channel} deletedMessagesVisibilityType='sender'>
|
|
148
|
-
<MessageList />
|
|
149
|
-
</Channel>
|
|
150
|
-
</Chat>
|
|
151
|
-
</OverlayProvider>,
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
await waitFor(() => {
|
|
155
|
-
expect(queryByTestId('message-deleted')).toBeTruthy();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('should render deleted message in the list when `deleteMessagesVisibilityType` is set to receiver', async () => {
|
|
160
|
-
const user1 = generateUser();
|
|
161
|
-
const user2 = generateUser({ id: 'testID' });
|
|
162
|
-
const mockedChannel = generateChannelResponse({
|
|
163
|
-
members: [generateMember({ user: user1 })],
|
|
164
|
-
messages: [
|
|
165
|
-
generateMessage({ user: user2 }),
|
|
166
|
-
generateMessage({ type: 'system', user: undefined }),
|
|
167
|
-
generateMessage({ type: 'deleted', user: user1 }),
|
|
168
|
-
],
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const chatClient = await getTestClientWithUser({ id: 'testID' });
|
|
172
|
-
useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
|
|
173
|
-
const channel = chatClient.channel('messaging', mockedChannel.id);
|
|
174
|
-
await channel.watch();
|
|
175
|
-
|
|
176
|
-
const { getByTestId, queryByTestId } = render(
|
|
177
|
-
<OverlayProvider>
|
|
178
|
-
<Chat client={chatClient}>
|
|
179
|
-
<Channel channel={channel} deletedMessagesVisibilityType='receiver'>
|
|
180
|
-
<MessageList />
|
|
181
|
-
</Channel>
|
|
182
|
-
</Chat>
|
|
183
|
-
</OverlayProvider>,
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
await waitFor(() => {
|
|
187
|
-
expect(getByTestId('message-deleted')).toBeTruthy();
|
|
188
|
-
expect(queryByTestId('only-visible-to-you')).toBeNull();
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('should render deleted message in the list when `deleteMessagesVisibilityType` is set to never', async () => {
|
|
193
|
-
const user1 = generateUser();
|
|
194
|
-
const user2 = generateUser({ id: 'testID' });
|
|
195
|
-
const mockedChannel = generateChannelResponse({
|
|
196
|
-
members: [generateMember({ user: user1 })],
|
|
197
|
-
messages: [
|
|
198
|
-
generateMessage({ user: user2 }),
|
|
199
|
-
generateMessage({ type: 'system', user: undefined }),
|
|
200
|
-
generateMessage({ type: 'deleted', user: user1 }),
|
|
201
|
-
],
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
const chatClient = await getTestClientWithUser({ id: 'testID' });
|
|
205
|
-
useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
|
|
206
|
-
const channel = chatClient.channel('messaging', mockedChannel.id);
|
|
207
|
-
await channel.watch();
|
|
208
|
-
|
|
209
|
-
const { queryByTestId } = render(
|
|
210
|
-
<OverlayProvider>
|
|
211
|
-
<Chat client={chatClient}>
|
|
212
|
-
<Channel channel={channel} deletedMessagesVisibilityType='never'>
|
|
213
|
-
<MessageList />
|
|
214
|
-
</Channel>
|
|
215
|
-
</Chat>
|
|
216
|
-
</OverlayProvider>,
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
await waitFor(() => {
|
|
220
|
-
expect(queryByTestId('message-deleted')).toBeNull();
|
|
221
|
-
expect(queryByTestId('only-visible-to-you')).toBeNull();
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('should render deleted message in the list', async () => {
|
|
226
|
-
const user1 = generateUser();
|
|
227
|
-
const mockedChannel = generateChannelResponse({
|
|
228
|
-
members: [generateMember({ user: user1 })],
|
|
229
|
-
messages: [
|
|
230
|
-
generateMessage({ type: 'deleted', user: user1 }),
|
|
231
|
-
generateMessage({ type: 'system', user: undefined }),
|
|
232
|
-
generateMessage({ user: user1 }),
|
|
233
|
-
],
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
const chatClient = await getTestClientWithUser({ id: 'testID' });
|
|
237
|
-
useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
|
|
238
|
-
const channel = chatClient.channel('messaging', mockedChannel.id);
|
|
239
|
-
await channel.watch();
|
|
240
|
-
|
|
241
|
-
const { getByTestId } = render(
|
|
242
|
-
<OverlayProvider>
|
|
243
|
-
<Chat client={chatClient}>
|
|
244
|
-
<Channel channel={channel}>
|
|
245
|
-
<MessageList />
|
|
246
|
-
</Channel>
|
|
247
|
-
</Chat>
|
|
248
|
-
</OverlayProvider>,
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
await waitFor(() => {
|
|
252
|
-
expect(getByTestId('message-deleted')).toBeTruthy();
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
127
|
it('should render the typing indicator when typing object is non empty', async () => {
|
|
257
128
|
const user1 = generateUser();
|
|
258
129
|
const mockedChannel = generateChannelResponse({
|
|
@@ -2,11 +2,6 @@ import { useMemo } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import type { LocalMessage } from 'stream-chat';
|
|
4
4
|
|
|
5
|
-
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
|
|
6
|
-
import {
|
|
7
|
-
DeletedMessagesVisibilityType,
|
|
8
|
-
useMessagesContext,
|
|
9
|
-
} from '../../../contexts/messagesContext/MessagesContext';
|
|
10
5
|
import { usePaginatedMessageListContext } from '../../../contexts/paginatedMessageListContext/PaginatedMessageListContext';
|
|
11
6
|
import { useThreadContext } from '../../../contexts/threadContext/ThreadContext';
|
|
12
7
|
|
|
@@ -27,35 +22,8 @@ export type MessageGroupStyles = {
|
|
|
27
22
|
[key: string]: string[];
|
|
28
23
|
};
|
|
29
24
|
|
|
30
|
-
export const shouldIncludeMessageInList = (
|
|
31
|
-
message: LocalMessage,
|
|
32
|
-
options: { deletedMessagesVisibilityType?: DeletedMessagesVisibilityType; userId?: string },
|
|
33
|
-
) => {
|
|
34
|
-
const { deletedMessagesVisibilityType, userId } = options;
|
|
35
|
-
const isMessageTypeDeleted = message.type === 'deleted';
|
|
36
|
-
const isSender = message.user?.id === userId;
|
|
37
|
-
|
|
38
|
-
if (!isMessageTypeDeleted) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
switch (deletedMessagesVisibilityType) {
|
|
43
|
-
case 'always':
|
|
44
|
-
return true;
|
|
45
|
-
case 'sender':
|
|
46
|
-
return isSender;
|
|
47
|
-
case 'receiver':
|
|
48
|
-
return !isSender;
|
|
49
|
-
case 'never':
|
|
50
|
-
default:
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
25
|
export const useMessageList = (params: UseMessageListParams) => {
|
|
56
26
|
const { threadList, isLiveStreaming, isFlashList = false } = params;
|
|
57
|
-
const { client } = useChatContext();
|
|
58
|
-
const { deletedMessagesVisibilityType } = useMessagesContext();
|
|
59
27
|
const { messages, viewabilityChangedCallback } = usePaginatedMessageListContext();
|
|
60
28
|
const { threadMessages } = useThreadContext();
|
|
61
29
|
const messageList = threadList ? threadMessages : messages;
|
|
@@ -63,14 +31,6 @@ export const useMessageList = (params: UseMessageListParams) => {
|
|
|
63
31
|
const processedMessageList = useMemo<LocalMessage[]>(() => {
|
|
64
32
|
const newMessageList = [];
|
|
65
33
|
for (const message of messageList) {
|
|
66
|
-
if (
|
|
67
|
-
!shouldIncludeMessageInList(message, {
|
|
68
|
-
deletedMessagesVisibilityType,
|
|
69
|
-
userId: client.userID,
|
|
70
|
-
})
|
|
71
|
-
) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
34
|
if (isFlashList) {
|
|
75
35
|
newMessageList.push(message);
|
|
76
36
|
} else {
|
|
@@ -78,7 +38,7 @@ export const useMessageList = (params: UseMessageListParams) => {
|
|
|
78
38
|
}
|
|
79
39
|
}
|
|
80
40
|
return newMessageList;
|
|
81
|
-
}, [messageList,
|
|
41
|
+
}, [messageList, isFlashList]);
|
|
82
42
|
|
|
83
43
|
const data = useRAFCoalescedValue(processedMessageList, isLiveStreaming);
|
|
84
44
|
|
|
@@ -465,7 +465,11 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
465
465
|
testID="message-components"
|
|
466
466
|
>
|
|
467
467
|
<View
|
|
468
|
-
style={
|
|
468
|
+
style={
|
|
469
|
+
{
|
|
470
|
+
"zIndex": 1,
|
|
471
|
+
}
|
|
472
|
+
}
|
|
469
473
|
>
|
|
470
474
|
<View
|
|
471
475
|
style={
|
|
@@ -606,6 +610,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
606
610
|
style={
|
|
607
611
|
{
|
|
608
612
|
"marginTop": -4,
|
|
613
|
+
"zIndex": 0,
|
|
609
614
|
}
|
|
610
615
|
}
|
|
611
616
|
/>
|
|
@@ -799,7 +804,11 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
799
804
|
testID="message-components"
|
|
800
805
|
>
|
|
801
806
|
<View
|
|
802
|
-
style={
|
|
807
|
+
style={
|
|
808
|
+
{
|
|
809
|
+
"zIndex": 1,
|
|
810
|
+
}
|
|
811
|
+
}
|
|
803
812
|
>
|
|
804
813
|
<View
|
|
805
814
|
style={
|
|
@@ -940,6 +949,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
940
949
|
style={
|
|
941
950
|
{
|
|
942
951
|
"marginTop": -4,
|
|
952
|
+
"zIndex": 0,
|
|
943
953
|
}
|
|
944
954
|
}
|
|
945
955
|
/>
|
|
@@ -1166,7 +1176,11 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
1166
1176
|
testID="message-components"
|
|
1167
1177
|
>
|
|
1168
1178
|
<View
|
|
1169
|
-
style={
|
|
1179
|
+
style={
|
|
1180
|
+
{
|
|
1181
|
+
"zIndex": 1,
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1170
1184
|
>
|
|
1171
1185
|
<View
|
|
1172
1186
|
style={
|
|
@@ -1307,6 +1321,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
1307
1321
|
style={
|
|
1308
1322
|
{
|
|
1309
1323
|
"marginTop": -4,
|
|
1324
|
+
"zIndex": 0,
|
|
1310
1325
|
}
|
|
1311
1326
|
}
|
|
1312
1327
|
/>
|
|
@@ -1491,7 +1506,11 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
1491
1506
|
testID="message-components"
|
|
1492
1507
|
>
|
|
1493
1508
|
<View
|
|
1494
|
-
style={
|
|
1509
|
+
style={
|
|
1510
|
+
{
|
|
1511
|
+
"zIndex": 1,
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1495
1514
|
>
|
|
1496
1515
|
<View
|
|
1497
1516
|
style={
|
|
@@ -1632,6 +1651,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
1632
1651
|
style={
|
|
1633
1652
|
{
|
|
1634
1653
|
"marginTop": -4,
|
|
1654
|
+
"zIndex": 0,
|
|
1635
1655
|
}
|
|
1636
1656
|
}
|
|
1637
1657
|
/>
|
|
@@ -51,7 +51,8 @@ export type ChannelsContextValue = {
|
|
|
51
51
|
*/
|
|
52
52
|
loadingChannels: boolean;
|
|
53
53
|
/**
|
|
54
|
-
* Whether or not additional channels are being loaded, triggers the
|
|
54
|
+
* Whether or not additional channels are being loaded, triggers the
|
|
55
|
+
* ChannelListFooterLoadingIndicator
|
|
55
56
|
*/
|
|
56
57
|
loadingNextPage: boolean;
|
|
57
58
|
/**
|
|
@@ -69,26 +69,26 @@ const getDefaults = () => {
|
|
|
69
69
|
|
|
70
70
|
Some component keys differ from their default component names to avoid collisions:
|
|
71
71
|
|
|
72
|
-
| Override Key
|
|
73
|
-
|
|
|
74
|
-
| `FileAttachmentIcon`
|
|
75
|
-
| `ChannelListLoadingIndicator`
|
|
76
|
-
| `MessageListLoadingIndicator`
|
|
77
|
-
| `ChatLoadingIndicator`
|
|
78
|
-
| `ThreadMessageComposer`
|
|
79
|
-
| `ThreadListComponent`
|
|
80
|
-
| `StartAudioRecordingButton`
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
72
|
+
| Override Key | Default Component | Why renamed |
|
|
73
|
+
| --------------------------------------- | --------------------------------------- | ---------------------------------------------------------- |
|
|
74
|
+
| `FileAttachmentIcon` | `FileIcon` | Clarity |
|
|
75
|
+
| `ChannelListLoadingIndicator` | `ChannelListLoadingIndicator` | Split from shared `LoadingIndicator` — renders skeleton UI |
|
|
76
|
+
| `MessageListLoadingIndicator` | `LoadingIndicator` | Split from shared `LoadingIndicator` — renders text |
|
|
77
|
+
| `ChatLoadingIndicator` | `undefined` | Optional, no default |
|
|
78
|
+
| `ThreadMessageComposer` | `MessageComposer` | Avoid collision with `MessageComposer` component name |
|
|
79
|
+
| `ThreadListComponent` | `DefaultThreadListComponent` | Avoid collision with exported `ThreadList` |
|
|
80
|
+
| `StartAudioRecordingButton` | `AudioRecordingButton` | Historical naming |
|
|
81
|
+
| `ChannelPreview` | `ChannelPreviewView` | ChannelList preview item |
|
|
82
|
+
| `ChannelPreviewAvatar` | `ChannelAvatar` | ChannelList preview avatar |
|
|
83
|
+
| `ChannelListFooterLoadingIndicator` | `ChannelListFooterLoadingIndicator` | ChannelList footer |
|
|
84
|
+
| `ChannelListHeaderErrorIndicator` | `ChannelListHeaderErrorIndicator` | ChannelList header |
|
|
85
|
+
| `ChannelListHeaderNetworkDownIndicator` | `ChannelListHeaderNetworkDownIndicator` | ChannelList header |
|
|
86
86
|
|
|
87
87
|
### Optional Components (no default)
|
|
88
88
|
|
|
89
89
|
These exist in `DEFAULT_COMPONENTS` as `undefined` with `React.ComponentType<any> | undefined` type assertions:
|
|
90
90
|
|
|
91
|
-
`AttachmentPickerIOSSelectMorePhotos`, `ChatLoadingIndicator`, `CreatePollContent`, `ImageComponent`, `Input`, `ListHeaderComponent`, `MessageContentBottomView`, `MessageContentLeadingView`, `MessageContentTopView`, `MessageContentTrailingView`, `MessageLocation`, `MessageSpacer`, `MessageText`, `PollContent`
|
|
91
|
+
`AttachmentPickerIOSSelectMorePhotos`, `ChatLoadingIndicator`, `CreatePollContent`, `ImageComponent`, `Input`, `ListHeaderComponent`, `MessageActions`, `MessageContentBottomView`, `MessageContentLeadingView`, `MessageContentTopView`, `MessageContentTrailingView`, `MessageLocation`, `MessageSpacer`, `MessageText`, `PollContent`
|
|
92
92
|
|
|
93
93
|
### Shared Component Keys (audited)
|
|
94
94
|
|
|
@@ -144,6 +144,7 @@ import { ThreadListUnreadBanner } from '../../components/ThreadList/ThreadListUn
|
|
|
144
144
|
import { ThreadMessagePreviewDeliveryStatus } from '../../components/ThreadList/ThreadMessagePreviewDeliveryStatus';
|
|
145
145
|
import { ChannelAvatar } from '../../components/ui/Avatar/ChannelAvatar';
|
|
146
146
|
import { DefaultMessageOverlayBackground } from '../../contexts/overlayContext/MessageOverlayHostLayer';
|
|
147
|
+
import type { MessageActionsProps } from '../../contexts/overlayContext/MessageOverlayHostLayer';
|
|
147
148
|
|
|
148
149
|
/**
|
|
149
150
|
* All default component implementations used across the SDK.
|
|
@@ -177,11 +178,11 @@ export const DEFAULT_COMPONENTS = {
|
|
|
177
178
|
FileUploadNotSupportedIndicator,
|
|
178
179
|
FileUploadRetryIndicator,
|
|
179
180
|
FilePreview,
|
|
180
|
-
|
|
181
|
+
ChannelListFooterLoadingIndicator,
|
|
181
182
|
Gallery,
|
|
182
183
|
Giphy,
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
ChannelListHeaderErrorIndicator,
|
|
185
|
+
ChannelListHeaderNetworkDownIndicator,
|
|
185
186
|
ImageAttachmentUploadPreview,
|
|
186
187
|
ImageLoadingFailedIndicator,
|
|
187
188
|
ImageLoadingIndicator,
|
|
@@ -231,16 +232,16 @@ export const DEFAULT_COMPONENTS = {
|
|
|
231
232
|
MessageUserReactionsAvatar,
|
|
232
233
|
MessageUserReactionsItem,
|
|
233
234
|
NetworkDownIndicator,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
ChannelPreview: ChannelPreviewView,
|
|
236
|
+
ChannelPreviewAvatar: ChannelAvatar,
|
|
237
|
+
ChannelPreviewLastMessage: ChannelLastMessagePreview,
|
|
238
|
+
ChannelPreviewMessage,
|
|
239
|
+
ChannelPreviewMessageDeliveryStatus: ChannelMessagePreviewDeliveryStatus,
|
|
240
|
+
ChannelPreviewMutedStatus,
|
|
241
|
+
ChannelPreviewStatus,
|
|
242
|
+
ChannelPreviewTitle,
|
|
243
|
+
ChannelPreviewTypingIndicator,
|
|
244
|
+
ChannelPreviewUnreadCount,
|
|
244
245
|
ReactionListBottom,
|
|
245
246
|
ReactionListClustered,
|
|
246
247
|
ReactionListCountItem,
|
|
@@ -309,6 +310,7 @@ export const DEFAULT_COMPONENTS = {
|
|
|
309
310
|
ChatLoadingIndicator: undefined as React.ComponentType<any> | null | undefined,
|
|
310
311
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
311
312
|
CreatePollContent: undefined as React.ComponentType<any> | undefined,
|
|
313
|
+
MessageActions: undefined as React.ComponentType<MessageActionsProps> | undefined,
|
|
312
314
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
313
315
|
Input: undefined as React.ComponentType<any> | undefined,
|
|
314
316
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -39,7 +39,6 @@ export type MessageContentType =
|
|
|
39
39
|
| 'ai_text'
|
|
40
40
|
| 'text'
|
|
41
41
|
| 'location';
|
|
42
|
-
export type DeletedMessagesVisibilityType = 'always' | 'never' | 'receiver' | 'sender';
|
|
43
42
|
|
|
44
43
|
export type MessageLocationProps = {
|
|
45
44
|
message: LocalMessage;
|
|
@@ -112,14 +111,6 @@ export type MessagesContextValue = Pick<MessageContextValue, 'isMessageAIGenerat
|
|
|
112
111
|
message: LocalMessage;
|
|
113
112
|
}) => void;
|
|
114
113
|
|
|
115
|
-
/**
|
|
116
|
-
* Full override of the delete message button in the Message Actions
|
|
117
|
-
*
|
|
118
|
-
* Please check [cookbook](https://github.com/GetStream/stream-chat-react-native/wiki/Cookbook-v3.0#override-or-intercept-message-actions-edit-delete-reaction-reply-etc) for details.
|
|
119
|
-
*/
|
|
120
|
-
/** Control if the deleted message is visible to both the send and reciever, either of them or none */
|
|
121
|
-
deletedMessagesVisibilityType?: DeletedMessagesVisibilityType;
|
|
122
|
-
|
|
123
114
|
disableTypingIndicator?: boolean;
|
|
124
115
|
/**
|
|
125
116
|
* Enable swipe to reply on messages.
|
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
Platform,
|
|
5
5
|
Pressable,
|
|
6
6
|
StyleSheet,
|
|
7
|
+
StyleProp,
|
|
7
8
|
useWindowDimensions,
|
|
8
9
|
View,
|
|
10
|
+
ViewStyle,
|
|
9
11
|
} from 'react-native';
|
|
10
12
|
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
11
13
|
import Animated, {
|
|
@@ -53,8 +55,15 @@ export const DefaultMessageOverlayBackground = () => {
|
|
|
53
55
|
);
|
|
54
56
|
};
|
|
55
57
|
|
|
58
|
+
export type MessageActionsProps = {
|
|
59
|
+
bottomItemStyle: StyleProp<ViewStyle>;
|
|
60
|
+
hostStyle: StyleProp<ViewStyle>;
|
|
61
|
+
portalHostStyle: StyleProp<ViewStyle>;
|
|
62
|
+
topItemStyle: StyleProp<ViewStyle>;
|
|
63
|
+
};
|
|
64
|
+
|
|
56
65
|
export const MessageOverlayHostLayer = () => {
|
|
57
|
-
const { MessageOverlayBackground } = useComponentsContext();
|
|
66
|
+
const { MessageActions, MessageOverlayBackground } = useComponentsContext();
|
|
58
67
|
const { id, closing } = useOverlayController();
|
|
59
68
|
const insets = useSafeAreaInsets();
|
|
60
69
|
const { height: screenH } = useWindowDimensions();
|
|
@@ -259,21 +268,32 @@ export const MessageOverlayHostLayer = () => {
|
|
|
259
268
|
/>
|
|
260
269
|
) : null}
|
|
261
270
|
|
|
262
|
-
|
|
263
|
-
<
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
271
|
+
{MessageActions ? (
|
|
272
|
+
<MessageActions
|
|
273
|
+
bottomItemStyle={bottomItemStyle}
|
|
274
|
+
hostStyle={hostStyle}
|
|
275
|
+
portalHostStyle={styles.absoluteFill}
|
|
276
|
+
topItemStyle={topItemStyle}
|
|
277
|
+
/>
|
|
278
|
+
) : (
|
|
279
|
+
<>
|
|
280
|
+
<Animated.View style={topItemStyle} testID='message-overlay-top'>
|
|
281
|
+
<PortalHost name='top-item' style={styles.absoluteFill} />
|
|
282
|
+
</Animated.View>
|
|
283
|
+
|
|
284
|
+
<Animated.View
|
|
285
|
+
pointerEvents='box-none'
|
|
286
|
+
style={hostStyle}
|
|
287
|
+
testID='message-overlay-message'
|
|
288
|
+
>
|
|
289
|
+
<PortalHost name='message-overlay' style={styles.absoluteFill} />
|
|
290
|
+
</Animated.View>
|
|
291
|
+
|
|
292
|
+
<Animated.View style={bottomItemStyle} testID='message-overlay-bottom'>
|
|
293
|
+
<PortalHost name='bottom-item' style={styles.absoluteFill} />
|
|
294
|
+
</Animated.View>
|
|
295
|
+
</>
|
|
296
|
+
)}
|
|
277
297
|
</View>
|
|
278
298
|
|
|
279
299
|
<ClosingPortalHostsLayer closeCoverOpacity={closeCoverOpacity} />
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
setOverlayTopH,
|
|
15
15
|
} from '../../../state-store';
|
|
16
16
|
import { WithComponents } from '../../componentsContext/ComponentsContext';
|
|
17
|
-
import { MessageOverlayHostLayer } from '../MessageOverlayHostLayer';
|
|
17
|
+
import { MessageActionsProps, MessageOverlayHostLayer } from '../MessageOverlayHostLayer';
|
|
18
18
|
|
|
19
19
|
jest.mock('react-native', () => {
|
|
20
20
|
const actual = jest.requireActual('react-native');
|
|
@@ -93,6 +93,18 @@ const TOP_RECT = { h: 20, w: 90, x: 5, y: 0 };
|
|
|
93
93
|
const MESSAGE_RECT = { h: 50, w: 180, x: 10, y: 0 };
|
|
94
94
|
const BOTTOM_RECT = { h: 30, w: 140, x: 20, y: 100 };
|
|
95
95
|
const NoopBackground = () => null;
|
|
96
|
+
const CustomMessageActions = ({
|
|
97
|
+
bottomItemStyle,
|
|
98
|
+
hostStyle,
|
|
99
|
+
topItemStyle,
|
|
100
|
+
}: MessageActionsProps) => (
|
|
101
|
+
<>
|
|
102
|
+
<Text testID='custom-message-actions'>Custom</Text>
|
|
103
|
+
<Text style={topItemStyle} testID='custom-message-actions-top' />
|
|
104
|
+
<Text style={hostStyle} testID='custom-message-actions-message' />
|
|
105
|
+
<Text style={bottomItemStyle} testID='custom-message-actions-bottom' />
|
|
106
|
+
</>
|
|
107
|
+
);
|
|
96
108
|
|
|
97
109
|
const flushAnimationFrameQueue = () => {
|
|
98
110
|
act(() => {
|
|
@@ -260,4 +272,50 @@ describe('MessageOverlayHostLayer', () => {
|
|
|
260
272
|
height: 0,
|
|
261
273
|
});
|
|
262
274
|
});
|
|
275
|
+
|
|
276
|
+
it('renders MessageActions override instead of the default host wrappers when provided', () => {
|
|
277
|
+
const renderTree = () => (
|
|
278
|
+
<WithComponents
|
|
279
|
+
overrides={{
|
|
280
|
+
MessageActions: CustomMessageActions,
|
|
281
|
+
MessageOverlayBackground: NoopBackground,
|
|
282
|
+
}}
|
|
283
|
+
>
|
|
284
|
+
<MessageOverlayHostLayer />
|
|
285
|
+
</WithComponents>
|
|
286
|
+
);
|
|
287
|
+
const { rerender } = render(renderTree());
|
|
288
|
+
|
|
289
|
+
act(() => {
|
|
290
|
+
setOverlayTopH(TOP_RECT);
|
|
291
|
+
setOverlayMessageH(MESSAGE_RECT);
|
|
292
|
+
setOverlayBottomH(BOTTOM_RECT);
|
|
293
|
+
openOverlay('message-1');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
rerender(renderTree());
|
|
297
|
+
|
|
298
|
+
expect(screen.getByTestId('custom-message-actions')).toBeTruthy();
|
|
299
|
+
expect(screen.queryByTestId('message-overlay-top')).toBeNull();
|
|
300
|
+
expect(screen.queryByTestId('message-overlay-message')).toBeNull();
|
|
301
|
+
expect(screen.queryByTestId('message-overlay-bottom')).toBeNull();
|
|
302
|
+
expect(
|
|
303
|
+
StyleSheet.flatten(screen.getByTestId('custom-message-actions-top').props.style),
|
|
304
|
+
).toMatchObject({
|
|
305
|
+
height: TOP_RECT.h,
|
|
306
|
+
width: TOP_RECT.w,
|
|
307
|
+
});
|
|
308
|
+
expect(
|
|
309
|
+
StyleSheet.flatten(screen.getByTestId('custom-message-actions-message').props.style),
|
|
310
|
+
).toMatchObject({
|
|
311
|
+
height: MESSAGE_RECT.h,
|
|
312
|
+
width: MESSAGE_RECT.w,
|
|
313
|
+
});
|
|
314
|
+
expect(
|
|
315
|
+
StyleSheet.flatten(screen.getByTestId('custom-message-actions-bottom').props.style),
|
|
316
|
+
).toMatchObject({
|
|
317
|
+
height: BOTTOM_RECT.h,
|
|
318
|
+
width: BOTTOM_RECT.w,
|
|
319
|
+
});
|
|
320
|
+
});
|
|
263
321
|
});
|
package/src/version.json
CHANGED