Skip to content

Commit af4b464

Browse files
committed
fix: add improvements
1 parent bdf2c2e commit af4b464

File tree

7 files changed

+103
-62
lines changed

7 files changed

+103
-62
lines changed

package/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
"@types/mime-types": "2.1.0",
119119
"@types/react": "18.2.6",
120120
"@types/react-test-renderer": "18.0.7",
121+
"@types/use-sync-external-store": "^0.0.6",
121122
"@types/uuid": "^8.3.4",
122123
"@typescript-eslint/eslint-plugin": "^6.21.0",
123124
"@typescript-eslint/parser": "^6.21.0",
@@ -149,6 +150,7 @@
149150
"react-native-svg": "15.1.0",
150151
"react-test-renderer": "18.2.0",
151152
"typescript": "5.0.4",
153+
"use-sync-external-store": "^1.4.0",
152154
"uuid": "^8.3.2"
153155
},
154156
"resolutions": {

package/src/components/ChannelList/hooks/listeners/useChannelMemberUpdated.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ export const useChannelMemberUpdated = <
7878

7979
// handle archiving (remove channel)
8080
if (
81-
// When archived filter true, and channel is not archived
82-
(!considerArchivedChannels && !isTargetChannelArchived) ||
81+
// When archived filter true, and channel is unarchived
82+
(considerArchivedChannels && !isTargetChannelArchived && filters?.archived) ||
8383
// When archived filter false, and channel is archived
84-
(considerArchivedChannels && isTargetChannelArchived)
84+
(considerArchivedChannels && isTargetChannelArchived && !filters?.archived)
8585
) {
8686
return newChannels;
8787
}

package/src/components/ChannelList/hooks/listeners/useNewMessage.ts

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,45 +46,35 @@ export const useNewMessage = <
4646
} else {
4747
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
4848
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
49+
50+
const channelType = event.channel_type;
51+
const channelId = event.channel_id;
52+
53+
if (!channelType || !channelId) return;
54+
4955
setChannels((channels) => {
5056
if (!channels) return channels;
51-
const targetChannelIndex = channels.findIndex((channel) => channel.cid === event.cid);
52-
const targetChannel = channels[targetChannelIndex];
57+
const targetChannel = client.channel(channelType, channelId);
58+
const targetChannelIndex = channels.indexOf(targetChannel);
5359

5460
const isTargetChannelArchived = isChannelArchived(targetChannel);
5561
const isTargetChannelPinned = isChannelPinned(targetChannel);
5662

5763
if (
58-
// If the channel is archived and we are not considering archived channels
59-
(isTargetChannelArchived && considerArchivedChannels) ||
64+
// When archived filter false, and channel is archived
65+
(considerArchivedChannels && isTargetChannelArchived && !filters?.archived) ||
66+
// When archived filter true, and channel is unarchived
67+
(considerArchivedChannels && !isTargetChannelArchived && filters?.archived) ||
6068
// If the channel is pinned and we are not considering pinned channels
6169
(isTargetChannelPinned && considerPinnedChannels) ||
6270
lockChannelOrder
6371
) {
6472
return [...channels];
6573
}
6674

67-
// If channel doesn't exist in existing list, check in activeChannels as well.
68-
// It may happen that channel was hidden using channel.hide(). In that case
69-
// We remove it from `channels` state, but its still being watched and exists in client.activeChannels.
70-
const channelToMove =
71-
targetChannel ??
72-
(event.channel_type &&
73-
event.channel_id &&
74-
client.channel(event.channel_type, event.channel_id));
75-
76-
// While adding new channels, we need to consider whether they are archived or not.
77-
if (
78-
// When archived filter false, and channel is archived
79-
(considerArchivedChannels && isChannelArchived(channelToMove)) ||
80-
// When archived filter true, and channel is not archived
81-
(!considerArchivedChannels && !isChannelArchived(channelToMove))
82-
) {
83-
return [...channels];
84-
}
8575
return moveChannelUp<StreamChatGenerics>({
8676
channels,
87-
channelToMove,
77+
channelToMove: targetChannel,
8878
channelToMoveIndexWithinChannels: targetChannelIndex,
8979
sort,
9080
});
Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,22 @@
1-
import { useEffect, useState } from 'react';
1+
import { Channel, ChannelMemberResponse, EventTypes } from 'stream-chat';
22

3-
import { Channel, ChannelState } from 'stream-chat';
3+
import { useSelectedChannelState } from './useSelectedChannelState';
44

5-
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
65
import { DefaultStreamChatGenerics } from '../../../types/types';
76

8-
export const useChannelMembershipState = <
9-
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
10-
>(
11-
channel?: Channel<StreamChatGenerics>,
12-
) => {
13-
const [membership, setMembership] = useState<ChannelState<StreamChatGenerics>['membership']>(
14-
() => channel?.state.membership || {},
15-
);
16-
17-
const { client } = useChatContext<StreamChatGenerics>();
18-
19-
useEffect(
20-
() => {
21-
if (!channel) return;
22-
23-
setMembership(channel.state.membership);
24-
25-
const handleMembershipUpdate = () => {
26-
setMembership(channel.state.membership);
27-
};
7+
const selector = <StreamChatGenerics extends DefaultStreamChatGenerics>(
8+
channel: Channel<StreamChatGenerics>,
9+
) => channel.state.membership;
10+
const keys: EventTypes[] = ['member.updated'];
2811

29-
const subscriptions = ['member.updated'].map((event) =>
30-
client.on(event, handleMembershipUpdate),
31-
);
32-
33-
return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
34-
},
35-
// eslint-disable-next-line react-hooks/exhaustive-deps
36-
[channel?.state.membership, client],
37-
);
38-
39-
return membership;
40-
};
12+
export function useChannelMembershipState<StreamChatGenerics extends DefaultStreamChatGenerics>(
13+
channel: Channel<StreamChatGenerics>,
14+
): ChannelMemberResponse<StreamChatGenerics>;
15+
export function useChannelMembershipState<StreamChatGenerics extends DefaultStreamChatGenerics>(
16+
channel?: Channel<StreamChatGenerics>,
17+
): ChannelMemberResponse<StreamChatGenerics> | undefined;
18+
export function useChannelMembershipState<StreamChatGenerics extends DefaultStreamChatGenerics>(
19+
channel?: Channel<StreamChatGenerics>,
20+
) {
21+
return useSelectedChannelState({ channel, selector, stateChangeEventKeys: keys });
22+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { useCallback } from 'react';
2+
3+
import type { Channel, EventTypes } from 'stream-chat';
4+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
5+
6+
import { DefaultStreamChatGenerics } from '../../../types/types';
7+
8+
const noop = () => {};
9+
10+
export function useSelectedChannelState<
11+
StreamChatGenerics extends DefaultStreamChatGenerics,
12+
O,
13+
>(_: {
14+
channel: Channel<StreamChatGenerics>;
15+
selector: (channel: Channel<StreamChatGenerics>) => O;
16+
stateChangeEventKeys?: EventTypes[];
17+
}): O;
18+
export function useSelectedChannelState<
19+
StreamChatGenerics extends DefaultStreamChatGenerics,
20+
O,
21+
>(_: {
22+
selector: (channel: Channel<StreamChatGenerics>) => O;
23+
channel?: Channel<StreamChatGenerics> | undefined;
24+
stateChangeEventKeys?: EventTypes[];
25+
}): O | undefined;
26+
export function useSelectedChannelState<StreamChatGenerics extends DefaultStreamChatGenerics, O>({
27+
channel,
28+
selector,
29+
stateChangeEventKeys = ['all'],
30+
}: {
31+
selector: (channel: Channel<StreamChatGenerics>) => O;
32+
channel?: Channel<StreamChatGenerics>;
33+
stateChangeEventKeys?: EventTypes[];
34+
}): O | undefined {
35+
const subscribe = useCallback(
36+
(onStoreChange: (value: O) => void) => {
37+
if (!channel) return noop;
38+
39+
const subscriptions = stateChangeEventKeys.map((et) =>
40+
channel.on(et, () => {
41+
onStoreChange(selector(channel));
42+
}),
43+
);
44+
45+
return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
46+
},
47+
[channel, selector, stateChangeEventKeys],
48+
);
49+
50+
const getSnapshot = useCallback(() => {
51+
if (!channel) return undefined;
52+
53+
return selector(channel);
54+
}, [channel, selector]);
55+
56+
return useSyncExternalStore(subscribe, getSnapshot);
57+
}

package/src/components/ChannelList/hooks/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const shouldConsiderArchivedChannels = <
3434
) => {
3535
if (!filters) return false;
3636

37-
return !filters.archived;
37+
return typeof filters.archived === 'boolean';
3838
};
3939

4040
export const extractSortValue = <

package/yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,6 +3089,11 @@
30893089
resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz#51b1c00b516a5774ada5d611e65eb123f988ef8d"
30903090
integrity sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==
30913091

3092+
"@types/use-sync-external-store@^0.0.6":
3093+
version "0.0.6"
3094+
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc"
3095+
integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==
3096+
30923097
"@types/uuid@^8.3.4":
30933098
version "8.3.4"
30943099
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
@@ -9943,6 +9948,11 @@ uri-js@^4.2.2:
99439948
dependencies:
99449949
punycode "^2.1.0"
99459950

9951+
use-sync-external-store@^1.4.0:
9952+
version "1.4.0"
9953+
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc"
9954+
integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==
9955+
99469956
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
99479957
version "1.0.2"
99489958
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"

0 commit comments

Comments
 (0)