Skip to content

Commit 74fc2b7

Browse files
Add archiving handlers
1 parent 66ea7c9 commit 74fc2b7

File tree

3 files changed

+114
-48
lines changed

3 files changed

+114
-48
lines changed

src/components/ChannelList/ChannelList.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ const UnMemoizedChannelList = <SCG extends DefaultStreamChatGenerics = DefaultSt
168168
customActiveChannel,
169169
customQueryChannels,
170170
EmptyStateIndicator = DefaultEmptyStateIndicator,
171-
filters,
171+
filters = {},
172172
getLatestMessagePreview,
173173
LoadingErrorIndicator = NullComponent,
174174
LoadingIndicator = LoadingChannels,
@@ -285,11 +285,10 @@ const UnMemoizedChannelList = <SCG extends DefaultStreamChatGenerics = DefaultSt
285285

286286
useMobileNavigation(channelListRef, navOpen, closeMobileNav);
287287

288-
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
289-
290288
const { customFn, defaultFn } = usePrepareShapeHandlers<SCG>({
291289
allowNewMessagesFromUnfilteredChannels,
292-
considerPinnedChannels,
290+
filters,
291+
sort,
293292
lockChannelOrder,
294293
onAddedToChannel,
295294
onChannelDeleted,

src/components/ChannelList/hooks/useChannelListShape.ts

Lines changed: 74 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@ import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useRef } fro
44
import { Channel, Event, ExtendableGenerics } from 'stream-chat';
55
import uniqBy from 'lodash.uniqby';
66

7-
import { isChannelPinned } from '.';
8-
import { findLastPinnedChannelIndex, moveChannelUpwards } from '../utils';
7+
import {
8+
findLastPinnedChannelIndex,
9+
isChannelArchived,
10+
isChannelPinned,
11+
moveChannelUpwards,
12+
shouldConsiderArchivedChannels,
13+
shouldConsiderPinnedChannels,
14+
} from '../utils';
915
import { useChatContext } from '../../../context';
1016
import { getChannel } from '../../../utils';
1117
import { ChannelListProps } from '../ChannelList';
@@ -27,16 +33,14 @@ type RepeatedParameters<SCG extends ExtendableGenerics> = {
2733
type HandleMessageNewParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> &
2834
RepeatedParameters<SCG> & {
2935
allowNewMessagesFromUnfilteredChannels: boolean;
30-
considerPinnedChannels: boolean;
3136
lockChannelOrder: boolean;
32-
};
37+
} & Required<Pick<ChannelListProps<SCG>, 'filters' | 'sort'>>;
3338

3439
type HandleNotificationMessageNewParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> &
3540
RepeatedParameters<SCG> & {
3641
allowNewMessagesFromUnfilteredChannels: boolean;
37-
considerPinnedChannels: boolean;
3842
lockChannelOrder: boolean;
39-
};
43+
} & Required<Pick<ChannelListProps<SCG>, 'filters' | 'sort'>>;
4044

4145
type HandleNotificationRemovedFromChannelParameters<SCG extends ExtendableGenerics> =
4246
BaseParameters<SCG> & RepeatedParameters<SCG>;
@@ -45,14 +49,12 @@ type HandleNotificationAddedToChannelParameters<SCG extends ExtendableGenerics>
4549
BaseParameters<SCG> &
4650
RepeatedParameters<SCG> & {
4751
allowNewMessagesFromUnfilteredChannels: boolean;
48-
considerPinnedChannels: boolean;
4952
lockChannelOrder: boolean;
50-
};
53+
} & Required<Pick<ChannelListProps<SCG>, 'sort'>>;
5154

5255
type HandleMemberUpdatedParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & {
53-
considerPinnedChannels: boolean;
5456
lockChannelOrder: boolean;
55-
};
57+
} & Required<Pick<ChannelListProps<SCG>, 'sort'>>;
5658

5759
type HandleChannelDeletedParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> &
5860
RepeatedParameters<SCG>;
@@ -97,7 +99,8 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
9799
const handleMessageNew = useCallback(
98100
({
99101
allowNewMessagesFromUnfilteredChannels,
100-
considerPinnedChannels,
102+
filters,
103+
sort,
101104
customHandler,
102105
event,
103106
lockChannelOrder,
@@ -110,12 +113,17 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
110113
setChannels((channels) => {
111114
const targetChannelIndex = channels.findIndex((channel) => channel.cid === event.cid);
112115
const targetChannelExistsWithinList = targetChannelIndex >= 0;
116+
const targetChannel = channels[targetChannelIndex];
113117

114-
const isTargetChannelPinned = isChannelPinned({
115-
channel: channels[targetChannelIndex],
116-
});
118+
const isTargetChannelPinned = isChannelPinned(targetChannel);
119+
const isTargetChannelArchived = isChannelArchived(targetChannel);
120+
121+
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
122+
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
117123

118124
if (
125+
// target channel is archived
126+
(isTargetChannelArchived && considerArchivedChannels) ||
119127
// target channel is pinned
120128
(isTargetChannelPinned && considerPinnedChannels) ||
121129
// list order is locked
@@ -151,6 +159,8 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
151159
const handleNotificationMessageNew = useCallback(
152160
async ({
153161
allowNewMessagesFromUnfilteredChannels,
162+
sort,
163+
filters,
154164
customHandler,
155165
event,
156166
setChannels,
@@ -159,14 +169,31 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
159169
return customHandler(setChannels, event);
160170
}
161171

162-
if (allowNewMessagesFromUnfilteredChannels && event.channel?.type) {
163-
const channel = await getChannel({
164-
client,
165-
id: event.channel.id,
166-
type: event.channel.type,
167-
});
168-
setChannels((channels) => uniqBy([channel, ...channels], 'cid'));
172+
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
173+
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
174+
175+
if (!event.channel?.type) return;
176+
177+
const channel = await getChannel({
178+
client,
179+
id: event.channel.id,
180+
type: event.channel.type,
181+
});
182+
183+
if (isChannelArchived(channel) && considerArchivedChannels) {
184+
return;
169185
}
186+
187+
if (!allowNewMessagesFromUnfilteredChannels) return;
188+
189+
setChannels((channels) =>
190+
moveChannelUpwards({
191+
channels,
192+
channelToMove: channel,
193+
channelToMoveIndexWithinChannels: -1,
194+
considerPinnedChannels,
195+
}),
196+
);
170197
},
171198
[client],
172199
);
@@ -217,19 +244,16 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
217244
);
218245

219246
const handleMemberUpdated = useCallback(
220-
({
221-
considerPinnedChannels,
222-
event,
223-
lockChannelOrder,
224-
setChannels,
225-
}: HandleMemberUpdatedParameters<SCG>) => {
226-
if (lockChannelOrder || !considerPinnedChannels) return;
247+
({ sort, event, lockChannelOrder, setChannels }: HandleMemberUpdatedParameters<SCG>) => {
248+
if (!event.member?.user || event.member.user.id !== client.userID || !event.channel_type) {
249+
return;
250+
}
227251

228-
if (!event.member || !event.channel_type) return;
229-
// const member = e.member;
230252
const channelType = event.channel_type;
231253
const channelId = event.channel_id;
232254

255+
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
256+
233257
setChannels((currentChannels) => {
234258
const targetChannel = client.channel(channelType, channelId);
235259
// assumes that channel instances are not changing
@@ -242,6 +266,14 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
242266
newChannels.splice(targetChannelIndex, 1);
243267
}
244268

269+
// handle archiving
270+
if (typeof event.member?.archived_at === 'string') {
271+
return newChannels;
272+
}
273+
274+
// handle pinning
275+
if (!considerPinnedChannels || lockChannelOrder) return currentChannels;
276+
245277
const lastPinnedChannelIndex = findLastPinnedChannelIndex({ channels: newChannels });
246278
const newTargetChannelIndex =
247279
typeof lastPinnedChannelIndex === 'number' ? lastPinnedChannelIndex + 1 : 0;
@@ -385,7 +417,10 @@ export const useChannelListShapeDefaults = <SCG extends ExtendableGenerics>() =>
385417
};
386418

387419
type UseDefaultHandleChannelListShapeParameters<SCG extends ExtendableGenerics> = Required<
388-
Pick<ChannelListProps<SCG>, 'allowNewMessagesFromUnfilteredChannels' | 'lockChannelOrder'>
420+
Pick<
421+
ChannelListProps<SCG>,
422+
'allowNewMessagesFromUnfilteredChannels' | 'lockChannelOrder' | 'filters' | 'sort'
423+
>
389424
> &
390425
Pick<
391426
ChannelListProps<SCG>,
@@ -399,7 +434,6 @@ type UseDefaultHandleChannelListShapeParameters<SCG extends ExtendableGenerics>
399434
| 'onMessageNewHandler'
400435
| 'onRemovedFromChannel'
401436
> & {
402-
considerPinnedChannels: boolean;
403437
customHandleChannelListShape?: (data: {
404438
defaults: ReturnType<typeof useChannelListShapeDefaults<SCG>>;
405439
event: Event<SCG>;
@@ -410,7 +444,6 @@ type UseDefaultHandleChannelListShapeParameters<SCG extends ExtendableGenerics>
410444

411445
export const usePrepareShapeHandlers = <SCG extends ExtendableGenerics>({
412446
allowNewMessagesFromUnfilteredChannels,
413-
considerPinnedChannels,
414447
customHandleChannelListShape,
415448
lockChannelOrder,
416449
onAddedToChannel,
@@ -423,6 +456,8 @@ export const usePrepareShapeHandlers = <SCG extends ExtendableGenerics>({
423456
onMessageNewHandler,
424457
onRemovedFromChannel,
425458
setChannels,
459+
filters,
460+
sort,
426461
}: UseDefaultHandleChannelListShapeParameters<SCG>) => {
427462
const defaults = useChannelListShapeDefaults<SCG>();
428463

@@ -439,7 +474,8 @@ export const usePrepareShapeHandlers = <SCG extends ExtendableGenerics>({
439474
case 'message.new':
440475
defaults.handleMessageNew({
441476
allowNewMessagesFromUnfilteredChannels,
442-
considerPinnedChannels,
477+
sort,
478+
filters,
443479
customHandler: onMessageNewHandler,
444480
event,
445481
lockChannelOrder,
@@ -449,7 +485,8 @@ export const usePrepareShapeHandlers = <SCG extends ExtendableGenerics>({
449485
case 'notification.message_new':
450486
defaults.handleNotificationMessageNew({
451487
allowNewMessagesFromUnfilteredChannels,
452-
considerPinnedChannels,
488+
sort,
489+
filters,
453490
customHandler: onMessageNew,
454491
event,
455492
lockChannelOrder,
@@ -459,7 +496,7 @@ export const usePrepareShapeHandlers = <SCG extends ExtendableGenerics>({
459496
case 'notification.added_to_channel':
460497
defaults.handleNotificationAddedToChannel({
461498
allowNewMessagesFromUnfilteredChannels,
462-
considerPinnedChannels,
499+
sort,
463500
customHandler: onAddedToChannel,
464501
event,
465502
lockChannelOrder,
@@ -497,7 +534,7 @@ export const usePrepareShapeHandlers = <SCG extends ExtendableGenerics>({
497534
break;
498535
case 'member.updated':
499536
defaults.handleMemberUpdated({
500-
considerPinnedChannels,
537+
sort,
501538
event,
502539
lockChannelOrder,
503540
setChannels,

src/components/ChannelList/utils.ts

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import uniqBy from 'lodash.uniqby';
22
import type { Channel, ExtendableGenerics } from 'stream-chat';
33

4-
import { isChannelPinned } from './hooks';
54
import type { DefaultStreamChatGenerics } from '../../types/types';
6-
import { ChannelListProps } from './ChannelList';
5+
import type { ChannelListProps } from './ChannelList';
76

87
export const MAX_QUERY_CHANNELS_LIMIT = 30;
98

@@ -45,7 +44,7 @@ export function findLastPinnedChannelIndex<SCG extends ExtendableGenerics>({
4544
let lastPinnedChannelIndex: number | null = null;
4645

4746
for (const channel of channels) {
48-
if (!isChannelPinned({ channel })) break;
47+
if (!isChannelPinned(channel)) break;
4948

5049
if (typeof lastPinnedChannelIndex === 'number') {
5150
lastPinnedChannelIndex++;
@@ -75,7 +74,7 @@ type MoveChannelUpwardsParams<SCG extends DefaultStreamChatGenerics = DefaultStr
7574
};
7675

7776
export const moveChannelUpwards = <
78-
SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
77+
SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
7978
>({
8079
channels,
8180
channelToMove,
@@ -117,14 +116,45 @@ export const moveChannelUpwards = <
117116
};
118117

119118
/**
120-
* Set to true only if `{ pinned_at: -1 }` option is first within the `sort` array.
119+
* Returns true only if `{ pinned_at: -1 }` or `{ pinned_at: 1 }` option is first within the `sort` array.
121120
*/
122-
export const shouldConsiderPinnedChannels = (sort: ChannelListProps['sort']) => {
121+
export const shouldConsiderPinnedChannels = <SCG extends ExtendableGenerics>(
122+
sort: ChannelListProps<SCG>['sort'],
123+
) => {
123124
if (!sort) return false;
124125

125126
if (!Array.isArray(sort)) return false;
126127

127128
const [option] = sort;
128129

129-
return option?.pinned_at === -1;
130+
if (!option?.pinned_at) return false;
131+
132+
return Math.abs(option.pinned_at) === 1;
133+
};
134+
135+
/**
136+
* Returns `true` only if `archived` property is set to `false` within `filters`.
137+
*/
138+
export const shouldConsiderArchivedChannels = <SCG extends ExtendableGenerics>(
139+
filters: ChannelListProps<SCG>['filters'],
140+
) => {
141+
if (!filters) return false;
142+
143+
return !filters.archived;
144+
};
145+
146+
export const isChannelPinned = <SCG extends ExtendableGenerics>(channel: Channel<SCG>) => {
147+
if (!channel) return false;
148+
149+
const member = channel.state.membership;
150+
151+
return !!member?.pinned_at;
152+
};
153+
154+
export const isChannelArchived = <SCG extends ExtendableGenerics>(channel: Channel<SCG>) => {
155+
if (!channel) return false;
156+
157+
const member = channel.state.membership;
158+
159+
return !!member?.archived_at;
130160
};

0 commit comments

Comments
 (0)