stream-chat-react-native-core 6.5.1 → 6.6.0
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/README.md +1 -1
- package/lib/commonjs/components/ChannelList/ChannelList.js +55 -72
- package/lib/commonjs/components/ChannelList/ChannelList.js.map +1 -1
- package/lib/commonjs/components/ChannelList/ChannelListMessenger.js +4 -1
- package/lib/commonjs/components/ChannelList/ChannelListMessenger.js.map +1 -1
- package/lib/commonjs/components/ChannelList/hooks/useCreateChannelsContext.js +3 -1
- package/lib/commonjs/components/ChannelList/hooks/useCreateChannelsContext.js.map +1 -1
- package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js +73 -72
- package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js +4 -1
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/lib/commonjs/contexts/channelsContext/ChannelsContext.js.map +1 -1
- package/lib/commonjs/i18n/en.json +1 -0
- package/lib/commonjs/i18n/es.json +1 -0
- package/lib/commonjs/i18n/fr.json +1 -0
- package/lib/commonjs/i18n/he.json +1 -0
- package/lib/commonjs/i18n/hi.json +1 -0
- package/lib/commonjs/i18n/it.json +1 -0
- package/lib/commonjs/i18n/ja.json +1 -0
- package/lib/commonjs/i18n/ko.json +1 -0
- package/lib/commonjs/i18n/nl.json +1 -0
- package/lib/commonjs/i18n/pt-br.json +1 -0
- package/lib/commonjs/i18n/ru.json +1 -0
- package/lib/commonjs/i18n/tr.json +1 -0
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/ChannelList/ChannelList.js +55 -72
- package/lib/module/components/ChannelList/ChannelList.js.map +1 -1
- package/lib/module/components/ChannelList/ChannelListMessenger.js +4 -1
- package/lib/module/components/ChannelList/ChannelListMessenger.js.map +1 -1
- package/lib/module/components/ChannelList/hooks/useCreateChannelsContext.js +3 -1
- package/lib/module/components/ChannelList/hooks/useCreateChannelsContext.js.map +1 -1
- package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js +73 -72
- package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js +4 -1
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/lib/module/contexts/channelsContext/ChannelsContext.js.map +1 -1
- package/lib/module/i18n/en.json +1 -0
- package/lib/module/i18n/es.json +1 -0
- package/lib/module/i18n/fr.json +1 -0
- package/lib/module/i18n/he.json +1 -0
- package/lib/module/i18n/hi.json +1 -0
- package/lib/module/i18n/it.json +1 -0
- package/lib/module/i18n/ja.json +1 -0
- package/lib/module/i18n/ko.json +1 -0
- package/lib/module/i18n/nl.json +1 -0
- package/lib/module/i18n/pt-br.json +1 -0
- package/lib/module/i18n/ru.json +1 -0
- package/lib/module/i18n/tr.json +1 -0
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/ChannelList/ChannelList.d.ts +11 -11
- package/lib/typescript/components/ChannelList/ChannelList.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/ChannelListMessenger.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/hooks/listeners/useChannelMemberUpdated.d.ts +2 -2
- package/lib/typescript/components/ChannelList/hooks/listeners/useChannelMemberUpdated.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/hooks/listeners/useChannelUpdated.d.ts +2 -2
- package/lib/typescript/components/ChannelList/hooks/listeners/useChannelUpdated.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/hooks/listeners/useUserPresence.d.ts +1 -1
- package/lib/typescript/components/ChannelList/hooks/listeners/useUserPresence.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/hooks/useCreateChannelsContext.d.ts +1 -1
- package/lib/typescript/components/ChannelList/hooks/useCreateChannelsContext.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/hooks/usePaginatedChannels.d.ts +6 -5
- package/lib/typescript/components/ChannelList/hooks/usePaginatedChannels.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecorder.d.ts.map +1 -1
- package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts +4 -0
- package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts.map +1 -1
- package/lib/typescript/i18n/en.json +1 -0
- package/lib/typescript/i18n/es.json +1 -0
- package/lib/typescript/i18n/fr.json +1 -0
- package/lib/typescript/i18n/he.json +1 -0
- package/lib/typescript/i18n/hi.json +1 -0
- package/lib/typescript/i18n/it.json +1 -0
- package/lib/typescript/i18n/ja.json +1 -0
- package/lib/typescript/i18n/ko.json +1 -0
- package/lib/typescript/i18n/nl.json +1 -0
- package/lib/typescript/i18n/pt-br.json +1 -0
- package/lib/typescript/i18n/ru.json +1 -0
- package/lib/typescript/i18n/tr.json +1 -0
- package/lib/typescript/utils/i18n/Streami18n.d.ts +1 -0
- package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/offline-support/offline-feature.js +4 -3
- package/src/components/ChannelList/ChannelList.tsx +83 -81
- package/src/components/ChannelList/ChannelListMessenger.tsx +4 -1
- package/src/components/ChannelList/__tests__/ChannelList.test.js +2 -2
- package/src/components/ChannelList/__tests__/ChannelListMessenger.test.js +3 -1
- package/src/components/ChannelList/hooks/listeners/useChannelMemberUpdated.ts +2 -2
- package/src/components/ChannelList/hooks/listeners/useChannelUpdated.ts +2 -2
- package/src/components/ChannelList/hooks/listeners/useUserPresence.ts +1 -1
- package/src/components/ChannelList/hooks/useCreateChannelsContext.ts +3 -0
- package/src/components/ChannelList/hooks/usePaginatedChannels.ts +51 -41
- package/src/components/MessageInput/components/AudioRecorder/AudioRecorder.tsx +5 -1
- package/src/contexts/channelsContext/ChannelsContext.tsx +4 -0
- package/src/i18n/en.json +1 -0
- package/src/i18n/es.json +1 -0
- package/src/i18n/fr.json +1 -0
- package/src/i18n/he.json +1 -0
- package/src/i18n/hi.json +1 -0
- package/src/i18n/it.json +1 -0
- package/src/i18n/ja.json +1 -0
- package/src/i18n/ko.json +1 -0
- package/src/i18n/nl.json +1 -0
- package/src/i18n/pt-br.json +1 -0
- package/src/i18n/ru.json +1 -0
- package/src/i18n/tr.json +1 -0
- package/src/version.json +1 -1
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import type { FlatList } from 'react-native-gesture-handler';
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { Channel, ChannelFilters, ChannelOptions, ChannelSort, Event } from 'stream-chat';
|
|
6
6
|
|
|
7
7
|
import { ChannelListFooterLoadingIndicator } from './ChannelListFooterLoadingIndicator';
|
|
8
8
|
import { ChannelListHeaderErrorIndicator } from './ChannelListHeaderErrorIndicator';
|
|
9
9
|
import { ChannelListHeaderNetworkDownIndicator } from './ChannelListHeaderNetworkDownIndicator';
|
|
10
10
|
import { ChannelListLoadingIndicator } from './ChannelListLoadingIndicator';
|
|
11
11
|
import { ChannelListMessenger, ChannelListMessengerProps } from './ChannelListMessenger';
|
|
12
|
-
import { useAddedToChannelNotification } from './hooks/listeners/useAddedToChannelNotification';
|
|
13
|
-
import { useChannelDeleted } from './hooks/listeners/useChannelDeleted';
|
|
14
|
-
import { useChannelHidden } from './hooks/listeners/useChannelHidden';
|
|
15
|
-
import { useChannelMemberUpdated } from './hooks/listeners/useChannelMemberUpdated';
|
|
16
|
-
import { useChannelTruncated } from './hooks/listeners/useChannelTruncated';
|
|
17
12
|
import { useChannelUpdated } from './hooks/listeners/useChannelUpdated';
|
|
18
|
-
import { useChannelVisible } from './hooks/listeners/useChannelVisible';
|
|
19
|
-
import { useNewMessage } from './hooks/listeners/useNewMessage';
|
|
20
|
-
import { useNewMessageNotification } from './hooks/listeners/useNewMessageNotification';
|
|
21
|
-
import { useRemovedFromChannelNotification } from './hooks/listeners/useRemovedFromChannelNotification';
|
|
22
13
|
import { useUserPresence } from './hooks/listeners/useUserPresence';
|
|
23
14
|
import { useCreateChannelsContext } from './hooks/useCreateChannelsContext';
|
|
24
15
|
import { usePaginatedChannels } from './hooks/usePaginatedChannels';
|
|
@@ -96,7 +87,7 @@ export type ChannelListProps<
|
|
|
96
87
|
* @overrideType Function
|
|
97
88
|
* */
|
|
98
89
|
onAddedToChannel?: (
|
|
99
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
90
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
100
91
|
event: Event<StreamChatGenerics>,
|
|
101
92
|
options?: ChannelListEventListenerOptions<StreamChatGenerics>,
|
|
102
93
|
) => void;
|
|
@@ -109,7 +100,7 @@ export type ChannelListProps<
|
|
|
109
100
|
* @overrideType Function
|
|
110
101
|
* */
|
|
111
102
|
onChannelDeleted?: (
|
|
112
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
103
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
113
104
|
event: Event<StreamChatGenerics>,
|
|
114
105
|
) => void;
|
|
115
106
|
/**
|
|
@@ -121,7 +112,7 @@ export type ChannelListProps<
|
|
|
121
112
|
* @overrideType Function
|
|
122
113
|
* */
|
|
123
114
|
onChannelHidden?: (
|
|
124
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
115
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
125
116
|
event: Event<StreamChatGenerics>,
|
|
126
117
|
) => void;
|
|
127
118
|
/**
|
|
@@ -135,7 +126,7 @@ export type ChannelListProps<
|
|
|
135
126
|
*/
|
|
136
127
|
onChannelMemberUpdated?: (
|
|
137
128
|
lockChannelOrder: boolean,
|
|
138
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
129
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
139
130
|
event: Event<StreamChatGenerics>,
|
|
140
131
|
options?: ChannelListEventListenerOptions<StreamChatGenerics>,
|
|
141
132
|
) => void;
|
|
@@ -148,7 +139,7 @@ export type ChannelListProps<
|
|
|
148
139
|
* @overrideType Function
|
|
149
140
|
* */
|
|
150
141
|
onChannelTruncated?: (
|
|
151
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
142
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
152
143
|
event: Event<StreamChatGenerics>,
|
|
153
144
|
) => void;
|
|
154
145
|
/**
|
|
@@ -160,7 +151,7 @@ export type ChannelListProps<
|
|
|
160
151
|
* @overrideType Function
|
|
161
152
|
* */
|
|
162
153
|
onChannelUpdated?: (
|
|
163
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
154
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
164
155
|
event: Event<StreamChatGenerics>,
|
|
165
156
|
) => void;
|
|
166
157
|
/**
|
|
@@ -172,7 +163,7 @@ export type ChannelListProps<
|
|
|
172
163
|
* @overrideType Function
|
|
173
164
|
* */
|
|
174
165
|
onChannelVisible?: (
|
|
175
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
166
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
176
167
|
event: Event<StreamChatGenerics>,
|
|
177
168
|
) => void;
|
|
178
169
|
/**
|
|
@@ -189,7 +180,7 @@ export type ChannelListProps<
|
|
|
189
180
|
* */
|
|
190
181
|
onNewMessage?: (
|
|
191
182
|
lockChannelOrder: boolean,
|
|
192
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
183
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
193
184
|
event: Event<StreamChatGenerics>,
|
|
194
185
|
options?: ChannelListEventListenerOptions<StreamChatGenerics>,
|
|
195
186
|
) => void;
|
|
@@ -203,7 +194,7 @@ export type ChannelListProps<
|
|
|
203
194
|
* @overrideType Function
|
|
204
195
|
* */
|
|
205
196
|
onNewMessageNotification?: (
|
|
206
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
197
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
207
198
|
event: Event<StreamChatGenerics>,
|
|
208
199
|
options?: ChannelListEventListenerOptions<StreamChatGenerics>,
|
|
209
200
|
) => void;
|
|
@@ -217,7 +208,7 @@ export type ChannelListProps<
|
|
|
217
208
|
* @overrideType Function
|
|
218
209
|
* */
|
|
219
210
|
onRemovedFromChannel?: (
|
|
220
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
211
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
221
212
|
event: Event<StreamChatGenerics>,
|
|
222
213
|
) => void;
|
|
223
214
|
/**
|
|
@@ -290,8 +281,68 @@ export const ChannelList = <
|
|
|
290
281
|
} = props;
|
|
291
282
|
|
|
292
283
|
const [forceUpdate, setForceUpdate] = useState(0);
|
|
293
|
-
const { enableOfflineSupport } = useChatContext<StreamChatGenerics>();
|
|
284
|
+
const { client, enableOfflineSupport } = useChatContext<StreamChatGenerics>();
|
|
285
|
+
const channelManager = useMemo(() => client.createChannelManager({}), [client]);
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* This hook sets the event handler overrides in the channelManager internally
|
|
289
|
+
* whenever they change. We do this to avoid recreating the channelManager instance
|
|
290
|
+
* every time these change, as we want to keep it as static as possible.
|
|
291
|
+
* This protects us from something like defining the overrides as inline functions
|
|
292
|
+
* causing the manager instance to be recreated over and over again.
|
|
293
|
+
*/
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
channelManager.setEventHandlerOverrides({
|
|
296
|
+
channelDeletedHandler: onChannelDeleted,
|
|
297
|
+
channelHiddenHandler: onChannelHidden,
|
|
298
|
+
channelTruncatedHandler: onChannelTruncated,
|
|
299
|
+
channelVisibleHandler: onChannelVisible,
|
|
300
|
+
memberUpdatedHandler: onChannelMemberUpdated
|
|
301
|
+
? (setChannels, event) =>
|
|
302
|
+
onChannelMemberUpdated(lockChannelOrder, setChannels, event, { filters, sort })
|
|
303
|
+
: undefined,
|
|
304
|
+
newMessageHandler: onNewMessage
|
|
305
|
+
? (setChannels, event) =>
|
|
306
|
+
onNewMessage(lockChannelOrder, setChannels, event, { filters, sort })
|
|
307
|
+
: undefined,
|
|
308
|
+
notificationAddedToChannelHandler: onAddedToChannel
|
|
309
|
+
? (setChannels, event) => onAddedToChannel(setChannels, event, { filters, sort })
|
|
310
|
+
: undefined,
|
|
311
|
+
notificationNewMessageHandler: onNewMessageNotification
|
|
312
|
+
? (setChannels, event) => onNewMessageNotification(setChannels, event, { filters, sort })
|
|
313
|
+
: undefined,
|
|
314
|
+
notificationRemovedFromChannelHandler: onRemovedFromChannel,
|
|
315
|
+
});
|
|
316
|
+
}, [
|
|
317
|
+
channelManager,
|
|
318
|
+
filters,
|
|
319
|
+
lockChannelOrder,
|
|
320
|
+
onAddedToChannel,
|
|
321
|
+
onChannelDeleted,
|
|
322
|
+
onChannelHidden,
|
|
323
|
+
onChannelMemberUpdated,
|
|
324
|
+
onChannelTruncated,
|
|
325
|
+
onChannelVisible,
|
|
326
|
+
onNewMessage,
|
|
327
|
+
onNewMessageNotification,
|
|
328
|
+
onRemovedFromChannel,
|
|
329
|
+
sort,
|
|
330
|
+
]);
|
|
331
|
+
|
|
332
|
+
useEffect(() => {
|
|
333
|
+
channelManager.setOptions({ abortInFlightQuery: true, lockChannelOrder });
|
|
334
|
+
}, [channelManager, lockChannelOrder]);
|
|
335
|
+
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
channelManager.registerSubscriptions();
|
|
338
|
+
|
|
339
|
+
return () => {
|
|
340
|
+
channelManager.unregisterSubscriptions();
|
|
341
|
+
};
|
|
342
|
+
}, [channelManager]);
|
|
343
|
+
|
|
294
344
|
const {
|
|
345
|
+
channelListInitialized,
|
|
295
346
|
channels,
|
|
296
347
|
error,
|
|
297
348
|
hasNextPage,
|
|
@@ -301,9 +352,9 @@ export const ChannelList = <
|
|
|
301
352
|
refreshing,
|
|
302
353
|
refreshList,
|
|
303
354
|
reloadList,
|
|
304
|
-
setChannels,
|
|
305
355
|
staticChannelsActive,
|
|
306
356
|
} = usePaginatedChannels<StreamChatGenerics>({
|
|
357
|
+
channelManager,
|
|
307
358
|
enableOfflineSupport,
|
|
308
359
|
filters,
|
|
309
360
|
options,
|
|
@@ -311,75 +362,25 @@ export const ChannelList = <
|
|
|
311
362
|
sort,
|
|
312
363
|
});
|
|
313
364
|
|
|
314
|
-
// Setup event listeners
|
|
315
|
-
useAddedToChannelNotification({
|
|
316
|
-
onAddedToChannel,
|
|
317
|
-
options: { filters, sort },
|
|
318
|
-
setChannels,
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
useChannelDeleted({
|
|
322
|
-
onChannelDeleted,
|
|
323
|
-
setChannels,
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
useChannelHidden({
|
|
327
|
-
onChannelHidden,
|
|
328
|
-
setChannels,
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
useChannelMemberUpdated({
|
|
332
|
-
lockChannelOrder,
|
|
333
|
-
onChannelMemberUpdated,
|
|
334
|
-
options: { filters, sort },
|
|
335
|
-
setChannels,
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
useChannelTruncated({
|
|
339
|
-
onChannelTruncated,
|
|
340
|
-
refreshList,
|
|
341
|
-
setChannels,
|
|
342
|
-
setForceUpdate,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
365
|
useChannelUpdated({
|
|
346
366
|
onChannelUpdated,
|
|
347
|
-
setChannels,
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
useChannelVisible({
|
|
351
|
-
onChannelVisible,
|
|
352
|
-
options: { sort },
|
|
353
|
-
setChannels,
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
useNewMessage({
|
|
357
|
-
lockChannelOrder,
|
|
358
|
-
onNewMessage,
|
|
359
|
-
options: { filters, sort },
|
|
360
|
-
setChannels,
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
useNewMessageNotification({
|
|
364
|
-
onNewMessageNotification,
|
|
365
|
-
options: { filters, sort },
|
|
366
|
-
setChannels,
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
useRemovedFromChannelNotification({
|
|
370
|
-
onRemovedFromChannel,
|
|
371
|
-
setChannels,
|
|
367
|
+
setChannels: channelManager.setChannels,
|
|
372
368
|
});
|
|
373
369
|
|
|
374
370
|
useUserPresence({
|
|
375
|
-
setChannels,
|
|
371
|
+
setChannels: channelManager.setChannels,
|
|
376
372
|
setForceUpdate,
|
|
377
373
|
});
|
|
378
374
|
|
|
379
375
|
const channelIdsStr = channels?.reduce((acc, channel) => `${acc}${channel.cid}`, '');
|
|
380
376
|
|
|
381
377
|
useEffect(() => {
|
|
382
|
-
if (
|
|
378
|
+
if (
|
|
379
|
+
channels == null ||
|
|
380
|
+
!channelListInitialized ||
|
|
381
|
+
staticChannelsActive ||
|
|
382
|
+
!enableOfflineSupport
|
|
383
|
+
) {
|
|
383
384
|
return;
|
|
384
385
|
}
|
|
385
386
|
|
|
@@ -393,6 +394,7 @@ export const ChannelList = <
|
|
|
393
394
|
|
|
394
395
|
const channelsContext = useCreateChannelsContext({
|
|
395
396
|
additionalFlatListProps,
|
|
397
|
+
channelListInitialized,
|
|
396
398
|
channels: channelRenderFilterFn ? channelRenderFilterFn(channels ?? []) : channels,
|
|
397
399
|
EmptyStateIndicator,
|
|
398
400
|
error,
|
|
@@ -86,6 +86,7 @@ const ChannelListMessengerWithContext = <
|
|
|
86
86
|
const onEndReachedCalledDuringCurrentScrollRef = useRef<boolean>(false);
|
|
87
87
|
const {
|
|
88
88
|
additionalFlatListProps,
|
|
89
|
+
channelListInitialized,
|
|
89
90
|
channels,
|
|
90
91
|
EmptyStateIndicator,
|
|
91
92
|
error,
|
|
@@ -140,7 +141,7 @@ const ChannelListMessengerWithContext = <
|
|
|
140
141
|
});
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
if (error && !refreshing && !loadingChannels && channels === null) {
|
|
144
|
+
if (error && !refreshing && !loadingChannels && (channels === null || !channelListInitialized)) {
|
|
144
145
|
return (
|
|
145
146
|
<LoadingErrorIndicator
|
|
146
147
|
error={error}
|
|
@@ -211,6 +212,7 @@ export const ChannelListMessenger = <
|
|
|
211
212
|
) => {
|
|
212
213
|
const {
|
|
213
214
|
additionalFlatListProps,
|
|
215
|
+
channelListInitialized,
|
|
214
216
|
channels,
|
|
215
217
|
EmptyStateIndicator,
|
|
216
218
|
error,
|
|
@@ -234,6 +236,7 @@ export const ChannelListMessenger = <
|
|
|
234
236
|
<ChannelListMessengerWithContext
|
|
235
237
|
{...{
|
|
236
238
|
additionalFlatListProps,
|
|
239
|
+
channelListInitialized,
|
|
237
240
|
channels,
|
|
238
241
|
EmptyStateIndicator,
|
|
239
242
|
error,
|
|
@@ -287,12 +287,12 @@ describe('ChannelList', () => {
|
|
|
287
287
|
it('should not alter order if `lockChannelOrder` prop is true', async () => {
|
|
288
288
|
render(
|
|
289
289
|
<Chat client={chatClient}>
|
|
290
|
-
<ChannelList {
|
|
290
|
+
<ChannelList lockChannelOrder={true} Preview={props.Preview} />
|
|
291
291
|
</Chat>,
|
|
292
292
|
);
|
|
293
293
|
|
|
294
294
|
await waitFor(() => {
|
|
295
|
-
expect(screen.getByTestId('channel-list')).toBeTruthy();
|
|
295
|
+
expect(screen.getByTestId('channel-list-messenger')).toBeTruthy();
|
|
296
296
|
});
|
|
297
297
|
|
|
298
298
|
const newMessage = sendNewMessageOnChannel3();
|
|
@@ -80,7 +80,9 @@ describe('ChannelListMessenger', () => {
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('renders the `LoadingErrorIndicator` when `error` prop is true', async () => {
|
|
83
|
-
const { getByTestId } = render(
|
|
83
|
+
const { getByTestId } = render(
|
|
84
|
+
<Component channels={mockChannels} error={true} loadingChannels={false} />,
|
|
85
|
+
);
|
|
84
86
|
await waitFor(() => {
|
|
85
87
|
expect(getByTestId('loading-error')).toBeTruthy();
|
|
86
88
|
});
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
type Parameters<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> =
|
|
21
21
|
{
|
|
22
22
|
lockChannelOrder: boolean;
|
|
23
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
23
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>;
|
|
24
24
|
onChannelMemberUpdated?: (
|
|
25
25
|
lockChannelOrder: boolean,
|
|
26
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
26
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
27
27
|
event: Event<StreamChatGenerics>,
|
|
28
28
|
options?: ChannelListEventListenerOptions<StreamChatGenerics>,
|
|
29
29
|
) => void;
|
|
@@ -8,9 +8,9 @@ import type { DefaultStreamChatGenerics } from '../../../../types/types';
|
|
|
8
8
|
|
|
9
9
|
type Parameters<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> =
|
|
10
10
|
{
|
|
11
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
11
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>;
|
|
12
12
|
onChannelUpdated?: (
|
|
13
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
13
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>,
|
|
14
14
|
event: Event<StreamChatGenerics>,
|
|
15
15
|
) => void;
|
|
16
16
|
};
|
|
@@ -8,7 +8,7 @@ import type { DefaultStreamChatGenerics } from '../../../../types/types';
|
|
|
8
8
|
|
|
9
9
|
type Parameters<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> =
|
|
10
10
|
{
|
|
11
|
-
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]
|
|
11
|
+
setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[]>>;
|
|
12
12
|
setForceUpdate: React.Dispatch<React.SetStateAction<number>>;
|
|
13
13
|
};
|
|
14
14
|
|
|
@@ -7,6 +7,7 @@ export const useCreateChannelsContext = <
|
|
|
7
7
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
8
8
|
>({
|
|
9
9
|
additionalFlatListProps,
|
|
10
|
+
channelListInitialized,
|
|
10
11
|
channels,
|
|
11
12
|
EmptyStateIndicator,
|
|
12
13
|
error,
|
|
@@ -51,6 +52,7 @@ export const useCreateChannelsContext = <
|
|
|
51
52
|
const channelsContext: ChannelsContextValue<StreamChatGenerics> = useMemo(
|
|
52
53
|
() => ({
|
|
53
54
|
additionalFlatListProps,
|
|
55
|
+
channelListInitialized,
|
|
54
56
|
channels,
|
|
55
57
|
EmptyStateIndicator,
|
|
56
58
|
error,
|
|
@@ -90,6 +92,7 @@ export const useCreateChannelsContext = <
|
|
|
90
92
|
hasNextPage,
|
|
91
93
|
loadingChannels,
|
|
92
94
|
loadingNextPage,
|
|
95
|
+
channelListInitialized,
|
|
93
96
|
refreshing,
|
|
94
97
|
],
|
|
95
98
|
);
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import {
|
|
4
|
+
ChannelFilters,
|
|
5
|
+
ChannelManager,
|
|
6
|
+
ChannelManagerState,
|
|
7
|
+
ChannelOptions,
|
|
8
|
+
ChannelSort,
|
|
9
|
+
} from 'stream-chat';
|
|
4
10
|
|
|
5
11
|
import { useActiveChannelsRefContext } from '../../../contexts/activeChannelsRefContext/ActiveChannelsRefContext';
|
|
6
12
|
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
|
|
13
|
+
import { useStateStore } from '../../../hooks';
|
|
7
14
|
import { useIsMountedRef } from '../../../hooks/useIsMountedRef';
|
|
8
15
|
|
|
9
16
|
import { getChannelsForFilterSort } from '../../../store/apis/getChannelsForFilterSort';
|
|
@@ -19,6 +26,7 @@ const waitSeconds = (seconds: number) =>
|
|
|
19
26
|
|
|
20
27
|
type Parameters<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> =
|
|
21
28
|
{
|
|
29
|
+
channelManager: ChannelManager<StreamChatGenerics>;
|
|
22
30
|
enableOfflineSupport: boolean;
|
|
23
31
|
filters: ChannelFilters<StreamChatGenerics>;
|
|
24
32
|
options: ChannelOptions;
|
|
@@ -37,23 +45,34 @@ type QueryType = 'queryLocalDB' | 'reload' | 'refresh' | 'loadChannels';
|
|
|
37
45
|
|
|
38
46
|
export type QueryChannels = (queryType?: QueryType, retryCount?: number) => Promise<void>;
|
|
39
47
|
|
|
48
|
+
const selector = <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(
|
|
49
|
+
nextValue: ChannelManagerState<StreamChatGenerics>,
|
|
50
|
+
) =>
|
|
51
|
+
({
|
|
52
|
+
channelListInitialized: nextValue.initialized,
|
|
53
|
+
channels: nextValue.channels,
|
|
54
|
+
pagination: nextValue.pagination,
|
|
55
|
+
} as const);
|
|
56
|
+
|
|
40
57
|
export const usePaginatedChannels = <
|
|
41
58
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
42
59
|
>({
|
|
60
|
+
channelManager,
|
|
43
61
|
enableOfflineSupport,
|
|
44
62
|
filters = {},
|
|
45
63
|
options = DEFAULT_OPTIONS,
|
|
46
64
|
setForceUpdate,
|
|
47
65
|
sort = {},
|
|
48
66
|
}: Parameters<StreamChatGenerics>) => {
|
|
49
|
-
const [channels, setChannels] = useState<Channel<StreamChatGenerics>[] | null>(null);
|
|
50
67
|
const [error, setError] = useState<Error | undefined>(undefined);
|
|
51
68
|
const [staticChannelsActive, setStaticChannelsActive] = useState<boolean>(false);
|
|
52
|
-
const
|
|
53
|
-
const [hasNextPage, setHasNextPage] = useState<boolean>(false);
|
|
69
|
+
const activeQueryType = useRef<QueryType | null>('queryLocalDB');
|
|
54
70
|
const activeChannels = useActiveChannelsRefContext();
|
|
55
71
|
const isMountedRef = useIsMountedRef();
|
|
56
72
|
const { client } = useChatContext<StreamChatGenerics>();
|
|
73
|
+
const { channelListInitialized, channels, pagination } =
|
|
74
|
+
useStateStore(channelManager?.state, selector) ?? {};
|
|
75
|
+
const hasNextPage = pagination?.hasNext;
|
|
57
76
|
|
|
58
77
|
const filtersRef = useRef<typeof filters | null>(null);
|
|
59
78
|
const sortRef = useRef<typeof sort | null>(null);
|
|
@@ -91,43 +110,32 @@ export const usePaginatedChannels = <
|
|
|
91
110
|
setError(undefined);
|
|
92
111
|
activeRequestId.current++;
|
|
93
112
|
const currentRequestId = activeRequestId.current;
|
|
94
|
-
|
|
113
|
+
activeQueryType.current = queryType;
|
|
95
114
|
|
|
96
115
|
const newOptions = {
|
|
97
116
|
limit: options?.limit ?? MAX_QUERY_CHANNELS_LIMIT,
|
|
98
|
-
offset:
|
|
99
|
-
queryType === 'loadChannels' && !staticChannelsActive && channels ? channels.length : 0,
|
|
117
|
+
offset: 0,
|
|
100
118
|
...options,
|
|
101
119
|
};
|
|
102
120
|
|
|
103
121
|
try {
|
|
122
|
+
if (isQueryStale() || !isMountedRef.current) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
104
125
|
/**
|
|
105
126
|
* We skipInitialization here for handling race condition between ChannelList, Channel (and Thread)
|
|
106
127
|
* when they all (may) update the channel state at the same time (when connection state recovers)
|
|
107
128
|
* TODO: if we move the channel state to a single context and share it between ChannelList, Channel and Thread we can remove this
|
|
108
129
|
*/
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
130
|
+
if (queryType === 'loadChannels') {
|
|
131
|
+
await channelManager.loadNext();
|
|
132
|
+
} else {
|
|
133
|
+
await channelManager.queryChannels(filters, sort, newOptions, {
|
|
134
|
+
skipInitialization: enableOfflineSupport ? undefined : activeChannels.current,
|
|
135
|
+
});
|
|
114
136
|
}
|
|
115
137
|
|
|
116
|
-
const newChannels =
|
|
117
|
-
queryType === 'loadChannels' && !staticChannelsActive && channels
|
|
118
|
-
? [...channels, ...channelQueryResponse]
|
|
119
|
-
: channelQueryResponse.map((c) => {
|
|
120
|
-
const existingChannel = client.activeChannels[c.cid];
|
|
121
|
-
if (existingChannel) {
|
|
122
|
-
return existingChannel;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return c;
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
setChannels(newChannels);
|
|
129
138
|
setStaticChannelsActive(false);
|
|
130
|
-
setHasNextPage(channelQueryResponse.length >= newOptions.limit);
|
|
131
139
|
isQueryingRef.current = false;
|
|
132
140
|
} catch (err: unknown) {
|
|
133
141
|
isQueryingRef.current = false;
|
|
@@ -140,7 +148,7 @@ export const usePaginatedChannels = <
|
|
|
140
148
|
// querying.current check is needed in order to make sure the next query call doesnt flick an error
|
|
141
149
|
// state and then succeed (reconnect case)
|
|
142
150
|
if (retryCount === MAX_NUMBER_OF_RETRIES && !isQueryingRef.current) {
|
|
143
|
-
|
|
151
|
+
activeQueryType.current = null;
|
|
144
152
|
console.warn(err);
|
|
145
153
|
|
|
146
154
|
setError(
|
|
@@ -154,7 +162,7 @@ export const usePaginatedChannels = <
|
|
|
154
162
|
return queryChannels(queryType, retryCount + 1);
|
|
155
163
|
}
|
|
156
164
|
|
|
157
|
-
|
|
165
|
+
activeQueryType.current = null;
|
|
158
166
|
};
|
|
159
167
|
|
|
160
168
|
const refreshList = async () => {
|
|
@@ -207,7 +215,7 @@ export const usePaginatedChannels = <
|
|
|
207
215
|
skipInitialization: [], // passing empty array will clear out the existing messages from channel state, this removes the possibility of duplicate messages
|
|
208
216
|
});
|
|
209
217
|
|
|
210
|
-
setChannels(offlineChannels);
|
|
218
|
+
channelManager.setChannels(offlineChannels);
|
|
211
219
|
setStaticChannelsActive(true);
|
|
212
220
|
}
|
|
213
221
|
} catch (e) {
|
|
@@ -215,7 +223,7 @@ export const usePaginatedChannels = <
|
|
|
215
223
|
return false;
|
|
216
224
|
}
|
|
217
225
|
|
|
218
|
-
|
|
226
|
+
activeQueryType.current = null;
|
|
219
227
|
|
|
220
228
|
return true;
|
|
221
229
|
};
|
|
@@ -257,26 +265,28 @@ export const usePaginatedChannels = <
|
|
|
257
265
|
|
|
258
266
|
return () => listener?.unsubscribe?.();
|
|
259
267
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
260
|
-
}, [filterStr, sortStr]);
|
|
268
|
+
}, [filterStr, sortStr, channelManager]);
|
|
261
269
|
|
|
262
270
|
return {
|
|
271
|
+
channelListInitialized,
|
|
263
272
|
channels,
|
|
264
273
|
error,
|
|
265
274
|
hasNextPage,
|
|
266
275
|
loadingChannels:
|
|
267
|
-
activeQueryType === 'queryLocalDB'
|
|
276
|
+
activeQueryType.current === 'queryLocalDB'
|
|
268
277
|
? true
|
|
269
|
-
:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
278
|
+
: // Although channels.length === 0 should come as a given when we have !channelListInitialized,
|
|
279
|
+
// due to the way offline storage works currently we have to do this additional
|
|
280
|
+
// check to make sure channels were not populated before the reactive list becomes
|
|
281
|
+
// ready. I do not like providing a way to set the ready state, as it should be managed
|
|
282
|
+
// in the LLC entirely. Once we move offline support to the LLC, we can remove this check
|
|
283
|
+
// too as it'll be redundant.
|
|
284
|
+
pagination?.isLoading || (!channelListInitialized && channels.length === 0),
|
|
285
|
+
loadingNextPage: pagination?.isLoadingNext,
|
|
286
|
+
loadNextPage: channelManager.loadNext,
|
|
287
|
+
refreshing: activeQueryType.current === 'refresh',
|
|
273
288
|
refreshList,
|
|
274
289
|
reloadList,
|
|
275
|
-
// Although channels can be null, there is no practical case where channels will be null
|
|
276
|
-
// when setChannels is used. setChannels is only recommended to be used for overriding
|
|
277
|
-
// event handler. Thus instead of adding if check for channels === null, its better to
|
|
278
|
-
// simply reassign types here.
|
|
279
|
-
setChannels,
|
|
280
290
|
staticChannelsActive,
|
|
281
291
|
};
|
|
282
292
|
};
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
useMessageInputContext,
|
|
11
11
|
} from '../../../../contexts/messageInputContext/MessageInputContext';
|
|
12
12
|
import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
|
|
13
|
+
import { useTranslationContext } from '../../../../contexts/translationContext/TranslationContext';
|
|
13
14
|
import { ArrowLeft, CircleStop, Delete, Mic, SendCheck } from '../../../../icons';
|
|
14
15
|
|
|
15
16
|
import { AudioRecordingReturnType } from '../../../../native';
|
|
@@ -142,6 +143,7 @@ const AudioRecorderWithContext = <
|
|
|
142
143
|
stopVoiceRecording,
|
|
143
144
|
uploadVoiceRecording,
|
|
144
145
|
} = props;
|
|
146
|
+
const { t } = useTranslationContext();
|
|
145
147
|
|
|
146
148
|
const {
|
|
147
149
|
theme: {
|
|
@@ -189,7 +191,9 @@ const AudioRecorderWithContext = <
|
|
|
189
191
|
<Animated.View
|
|
190
192
|
style={[styles.slideToCancelContainer, slideToCancelStyle, slideToCancelContainer]}
|
|
191
193
|
>
|
|
192
|
-
<Text style={[styles.slideToCancel, { color: grey_dark }]}>
|
|
194
|
+
<Text style={[styles.slideToCancel, { color: grey_dark }]}>
|
|
195
|
+
{t<string>('Slide to Cancel')}
|
|
196
|
+
</Text>
|
|
193
197
|
<ArrowLeft fill={grey_dark} size={24} {...arrowLeftIcon} />
|
|
194
198
|
</Animated.View>
|
|
195
199
|
</>
|
|
@@ -42,6 +42,10 @@ export type ChannelsContextValue<
|
|
|
42
42
|
* **Note:** Don't use `additionalFlatListProps` to access the FlatList ref, use `setFlatListRef`
|
|
43
43
|
*/
|
|
44
44
|
additionalFlatListProps: Partial<FlatListProps<Channel<StreamChatGenerics>>>;
|
|
45
|
+
/**
|
|
46
|
+
* A control prop used to determine whether the first query of the channel list has succeeded.
|
|
47
|
+
*/
|
|
48
|
+
channelListInitialized: boolean;
|
|
45
49
|
/**
|
|
46
50
|
* Channels can be either an array of channels or a promise which resolves to an array of channels
|
|
47
51
|
*/
|
package/src/i18n/en.json
CHANGED
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
"Send a message": "Send a message",
|
|
95
95
|
"Sending links is not allowed in this conversation": "Sending links is not allowed in this conversation",
|
|
96
96
|
"Show All": "Show All",
|
|
97
|
+
"Slide to Cancel": "Slide to Cancel",
|
|
97
98
|
"Slow mode ON": "Slow mode ON",
|
|
98
99
|
"Suggest an option": "Suggest an option",
|
|
99
100
|
"The message has been reported to a moderator.": "The message has been reported to a moderator.",
|
package/src/i18n/es.json
CHANGED
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"Send a message": "Enviar un mensaje",
|
|
97
97
|
"Sending links is not allowed in this conversation": "No está permitido enviar enlaces en esta conversación",
|
|
98
98
|
"Show All": "Mostrar todo",
|
|
99
|
+
"Slide to Cancel": "Desliza para cancelar",
|
|
99
100
|
"Slow mode ON": "Modo lento ACTIVADO",
|
|
100
101
|
"Suggest an option": "Sugerir una opción",
|
|
101
102
|
"The message has been reported to a moderator.": "El mensaje ha sido reportado a un moderador.",
|
package/src/i18n/fr.json
CHANGED
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"Send a message": "Envoyer un message",
|
|
97
97
|
"Sending links is not allowed in this conversation": "Sending links is not allowed in this conversation",
|
|
98
98
|
"Show All": "Afficher tout",
|
|
99
|
+
"Slide to Cancel": "Glisser pour annuler",
|
|
99
100
|
"Slow mode ON": "Mode lent activé",
|
|
100
101
|
"Suggest an option": "Suggérer une option",
|
|
101
102
|
"The message has been reported to a moderator.": "Le message a été signalé à un modérateur.",
|