Skip to content

Commit 207a724

Browse files
Allow integrators to shape their ChannelLists however they want with more freedom
1 parent aff7990 commit 207a724

File tree

3 files changed

+578
-62
lines changed

3 files changed

+578
-62
lines changed

src/components/ChannelList/ChannelList.tsx

Lines changed: 32 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,9 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
22
import clsx from 'clsx';
33

44
import { ChannelListMessenger, ChannelListMessengerProps } from './ChannelListMessenger';
5-
import { useChannelDeletedListener } from './hooks/useChannelDeletedListener';
6-
import { useChannelHiddenListener } from './hooks/useChannelHiddenListener';
7-
import { useChannelTruncatedListener } from './hooks/useChannelTruncatedListener';
8-
import { useChannelUpdatedListener } from './hooks/useChannelUpdatedListener';
9-
import { useChannelVisibleListener } from './hooks/useChannelVisibleListener';
105
import { useConnectionRecoveredListener } from './hooks/useConnectionRecoveredListener';
11-
import { useMessageNewListener } from './hooks/useMessageNewListener';
126
import { useMobileNavigation } from './hooks/useMobileNavigation';
13-
import { useNotificationAddedToChannelListener } from './hooks/useNotificationAddedToChannelListener';
14-
import { useNotificationMessageNewListener } from './hooks/useNotificationMessageNewListener';
15-
import { useNotificationRemovedFromChannelListener } from './hooks/useNotificationRemovedFromChannelListener';
167
import { CustomQueryChannelsFn, usePaginatedChannels } from './hooks/usePaginatedChannels';
17-
import { useUserPresenceChangedListener } from './hooks/useUserPresenceChangedListener';
18-
import { useMemberUpdatedListener } from './hooks/useMemberUpdatedListener';
198
import {
209
MAX_QUERY_CHANNELS_LIMIT,
2110
moveChannelUpwards,
@@ -42,13 +31,14 @@ import { useChatContext } from '../../context/ChatContext';
4231
import type { Channel, ChannelFilters, ChannelOptions, ChannelSort, Event } from 'stream-chat';
4332
import type { TranslationContextValue } from '../../context/TranslationContext';
4433
import type { DefaultStreamChatGenerics, PaginatorProps } from '../../types/types';
34+
import { useChannelListShape, usePrepareShapeHandlers } from './hooks/useChannelListShape';
4535

4636
const DEFAULT_FILTERS = {};
4737
const DEFAULT_OPTIONS = {};
4838
const DEFAULT_SORT = {};
4939

5040
export type ChannelListProps<
51-
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
41+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
5242
> = {
5343
/** Additional props for underlying ChannelSearch component and channel search controller, [available props](https://getstream.io/chat/docs/sdk/react/utility-components/channel_search/#props) */
5444
additionalChannelSearchProps?: Omit<ChannelSearchProps<StreamChatGenerics>, 'setChannels'>;
@@ -165,15 +155,13 @@ export type ChannelListProps<
165155
watchers?: { limit?: number; offset?: number };
166156
};
167157

168-
const UnMemoizedChannelList = <
169-
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
170-
>(
171-
props: ChannelListProps<StreamChatGenerics>,
158+
const UnMemoizedChannelList = <SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(
159+
props: ChannelListProps<SCG>,
172160
) => {
173161
const {
174162
additionalChannelSearchProps,
175163
Avatar = DefaultAvatar,
176-
allowNewMessagesFromUnfilteredChannels,
164+
allowNewMessagesFromUnfilteredChannels = true,
177165
channelRenderFilterFn,
178166
ChannelSearch = DefaultChannelSearch,
179167
customActiveChannel,
@@ -184,7 +172,7 @@ const UnMemoizedChannelList = <
184172
LoadingErrorIndicator = NullComponent,
185173
LoadingIndicator = LoadingChannels,
186174
List = ChannelListMessenger,
187-
lockChannelOrder,
175+
lockChannelOrder = false,
188176
onAddedToChannel,
189177
onChannelDeleted,
190178
onChannelHidden,
@@ -216,7 +204,7 @@ const UnMemoizedChannelList = <
216204
setActiveChannel,
217205
theme,
218206
useImageFlagEmojisOnWindows,
219-
} = useChatContext<StreamChatGenerics>('ChannelList');
207+
} = useChatContext<SCG>('ChannelList');
220208

221209
const channelListRef = useRef<HTMLDivElement>(null);
222210
const [channelUpdateCount, setChannelUpdateCount] = useState(0);
@@ -226,8 +214,8 @@ const UnMemoizedChannelList = <
226214
* If customActiveChannel prop is absent, then set the first channel in list as active channel.
227215
*/
228216
const activeChannelHandler = async (
229-
channels: Array<Channel<StreamChatGenerics>>,
230-
setChannels: React.Dispatch<React.SetStateAction<Array<Channel<StreamChatGenerics>>>>,
217+
channels: Array<Channel<SCG>>,
218+
setChannels: React.Dispatch<React.SetStateAction<Array<Channel<SCG>>>>,
231219
) => {
232220
if (!channels.length || channels.length > (options?.limit || MAX_QUERY_CHANNELS_LIMIT)) {
233221
return;
@@ -267,16 +255,11 @@ const UnMemoizedChannelList = <
267255
* For some events, inner properties on the channel will update but the shallow comparison will not
268256
* force a re-render. Incrementing this dummy variable ensures the channel previews update.
269257
*/
270-
const forceUpdate = useCallback(() => setChannelUpdateCount((count) => count + 1), [
271-
setChannelUpdateCount,
272-
]);
258+
const forceUpdate = useCallback(() => setChannelUpdateCount((count) => count + 1), []);
273259

274260
const onSearch = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
275-
if (!event.target.value) {
276-
setSearchActive(false);
277-
} else {
278-
setSearchActive(true);
279-
}
261+
setSearchActive(!!event.target.value);
262+
280263
additionalChannelSearchProps?.onSearch?.(event);
281264
// eslint-disable-next-line react-hooks/exhaustive-deps
282265
}, []);
@@ -299,43 +282,35 @@ const UnMemoizedChannelList = <
299282

300283
const loadedChannels = channelRenderFilterFn ? channelRenderFilterFn(channels) : channels;
301284

302-
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
303-
304285
useMobileNavigation(channelListRef, navOpen, closeMobileNav);
305286

306-
useMessageNewListener(
307-
setChannels,
308-
onMessageNewHandler,
309-
lockChannelOrder,
287+
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
288+
289+
const { customFn, defaultFn } = usePrepareShapeHandlers<SCG>({
310290
allowNewMessagesFromUnfilteredChannels,
311-
// TODO: adjust accordingly (consider sort option)
312291
considerPinnedChannels,
313-
);
314-
useNotificationMessageNewListener(
315-
setChannels,
316-
onMessageNew,
317-
allowNewMessagesFromUnfilteredChannels,
318-
);
319-
useNotificationAddedToChannelListener(
320-
setChannels,
292+
lockChannelOrder,
321293
onAddedToChannel,
322-
allowNewMessagesFromUnfilteredChannels,
323-
);
324-
useMemberUpdatedListener({
325-
considerPinnedChannels,
294+
onChannelDeleted,
295+
onChannelHidden,
296+
onChannelTruncated,
297+
onChannelUpdated,
298+
onChannelVisible,
299+
onMessageNew,
300+
onMessageNewHandler,
301+
onRemovedFromChannel,
326302
setChannels,
303+
// TODO: implement
304+
// customHandleChannelListShape
327305
});
328-
useNotificationRemovedFromChannelListener(setChannels, onRemovedFromChannel);
329-
useChannelDeletedListener(setChannels, onChannelDeleted);
330-
useChannelHiddenListener(setChannels, onChannelHidden);
331-
useChannelVisibleListener(setChannels, onChannelVisible);
332-
useChannelTruncatedListener(setChannels, onChannelTruncated, forceUpdate);
333-
useChannelUpdatedListener(setChannels, onChannelUpdated, forceUpdate);
306+
307+
useChannelListShape<SCG>(customFn ?? defaultFn);
308+
309+
// TODO: maybe move this too
334310
useConnectionRecoveredListener(forceUpdate);
335-
useUserPresenceChangedListener(setChannels);
336311

337312
useEffect(() => {
338-
const handleEvent = (event: Event<StreamChatGenerics>) => {
313+
const handleEvent = (event: Event<SCG>) => {
339314
if (event.cid === channel?.cid) {
340315
setActiveChannel();
341316
}
@@ -351,7 +326,7 @@ const UnMemoizedChannelList = <
351326
// eslint-disable-next-line react-hooks/exhaustive-deps
352327
}, [channel?.cid]);
353328

354-
const renderChannel = (item: Channel<StreamChatGenerics>) => {
329+
const renderChannel = (item: Channel<SCG>) => {
355330
const previewProps = {
356331
activeChannel: channel,
357332
Avatar,

0 commit comments

Comments
 (0)