Skip to content

Commit 40cde03

Browse files
authored
1 parent de7bc08 commit 40cde03

File tree

5 files changed

+80
-61
lines changed

5 files changed

+80
-61
lines changed

src/modules/GroupChannel/context/GroupChannelProvider.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,8 @@ const GroupChannelProvider: React.FC<React.PropsWithChildren<GroupChannelProvide
326326
const useGroupChannelStore = () => {
327327
return useStore(GroupChannelContext, state => state, initialState);
328328
};
329-
/**
330-
* Keep this function for backward compatibility.
331-
*/
329+
330+
// Keep this function for backward compatibility.
332331
const useGroupChannelContext = () => {
333332
const { state, actions } = useGroupChannel();
334333
return { ...state, ...actions };

src/modules/GroupChannelList/components/GroupChannelListItem/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export const GroupChannelListItem = ({
2323
const { stringSet } = useLocalization();
2424
const {
2525
state: {
26-
isTypingIndicatorEnabled = false,
27-
isMessageReceiptStatusEnabled = false,
26+
isTypingIndicatorEnabled,
27+
isMessageReceiptStatusEnabled,
2828
},
2929
} = useGroupChannelList();
3030

src/modules/GroupChannelList/context/GroupChannelListProvider.tsx

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React, { useContext, useEffect, useRef } from 'react';
1+
import React, { useEffect, useMemo, useRef } from 'react';
22

33
import type { User } from '@sendbird/chat';
44
import type { GroupChannel, GroupChannelCreateParams, GroupChannelFilterParams } from '@sendbird/chat/groupChannel';
55
import { GroupChannelCollectionParams, GroupChannelFilter } from '@sendbird/chat/groupChannel';
6-
import { useGroupChannelList, useGroupChannelHandler } from '@sendbird/uikit-tools';
6+
import { useGroupChannelList as useGroupChannelListDataSource, useGroupChannelHandler } from '@sendbird/uikit-tools';
77

88
import type { CHANNEL_TYPE } from '../../CreateChannel/types';
99
import { UserProfileProvider } from '../../../lib/UserProfileContext';
@@ -16,9 +16,10 @@ import { createStore } from '../../../utils/storeManager';
1616
import { useStore } from '../../../hooks/useStore';
1717
import { noop } from '../../../utils/utils';
1818
import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
19+
import useGroupChannelList from './useGroupChannelList';
1920

2021
type OnCreateChannelClickParams = { users: Array<string>; onClose: () => void; channelType: CHANNEL_TYPE };
21-
type ChannelListDataSource = ReturnType<typeof useGroupChannelList>;
22+
type ChannelListDataSource = ReturnType<typeof useGroupChannelListDataSource>;
2223
export type ChannelListQueryParamsType = Omit<GroupChannelCollectionParams, 'filter'> & GroupChannelFilterParams;
2324

2425
interface ContextBaseType {
@@ -83,7 +84,7 @@ const initialState: GroupChannelListState = {
8384
/**
8485
* @returns {ReturnType<typeof createStore<GroupChannelListState>>}
8586
*/
86-
const useGroupChannelListStore = () => {
87+
export const useGroupChannelListStore = () => {
8788
return useStore(GroupChannelListContext, state => state, initialState);
8889
};
8990

@@ -92,9 +93,6 @@ export const GroupChannelListManager: React.FC<GroupChannelListProviderProps> =
9293
selectedChannelUrl = '',
9394

9495
disableAutoSelect = false,
95-
allowProfileEdit,
96-
isTypingIndicatorEnabled,
97-
isMessageReceiptStatusEnabled,
9896

9997
channelListQueryParams,
10098
onThemeChange,
@@ -103,17 +101,19 @@ export const GroupChannelListManager: React.FC<GroupChannelListProviderProps> =
103101
onCreateChannelClick,
104102
onBeforeCreateChannel,
105103
onUserProfileUpdated,
104+
...props
106105
}: GroupChannelListProviderProps) => {
107106
const { state: sendbirdState } = useSendbird();
108107
const { config, stores } = sendbirdState;
109-
const { state, updateState } = useGroupChannelListStore();
108+
const { state } = useGroupChannelList();
109+
const { updateState } = useGroupChannelListStore();
110110
const { sdkStore } = stores;
111111

112112
const sdk = sdkStore.sdk;
113113
const isConnected = useOnlineStatus(sdk, config.logger);
114114
const scheduler = useMarkAsDeliveredScheduler({ isConnected }, config);
115115

116-
const channelListDataSource = useGroupChannelList(sdk, {
116+
const channelListDataSource = useGroupChannelListDataSource(sdk, {
117117
collectionCreator: getCollectionCreator(sdk, channelListQueryParams),
118118
markAsDelivered: (channels) => channels.forEach(scheduler.push),
119119
onChannelsDeleted: (channelUrls) => {
@@ -142,6 +142,7 @@ export const GroupChannelListManager: React.FC<GroupChannelListProviderProps> =
142142
]);
143143

144144
const { typingChannelUrls } = state;
145+
145146
useGroupChannelHandler(sdk, {
146147
onTypingStatusUpdated: (channel) => {
147148
const channelList = typingChannelUrls.filter((channelUrl) => channelUrl !== channel.url);
@@ -157,47 +158,62 @@ export const GroupChannelListManager: React.FC<GroupChannelListProviderProps> =
157158
},
158159
});
159160

160-
useEffect(() => {
161-
updateState({
162-
className,
163-
selectedChannelUrl,
164-
disableAutoSelect,
165-
allowProfileEdit,
166-
isTypingIndicatorEnabled,
167-
isMessageReceiptStatusEnabled,
168-
onChannelSelect,
169-
onChannelCreated,
170-
onThemeChange,
171-
onCreateChannelClick,
172-
onBeforeCreateChannel,
173-
onUserProfileUpdated,
174-
typingChannelUrls,
175-
refreshing,
176-
initialized,
177-
groupChannels,
178-
refresh,
179-
loadMore,
180-
});
181-
}, [
182-
className,
183-
selectedChannelUrl,
184-
disableAutoSelect,
185-
allowProfileEdit,
186-
isTypingIndicatorEnabled,
187-
isMessageReceiptStatusEnabled,
161+
const allowProfileEdit = props.allowProfileEdit ?? config.allowProfileEdit ?? true;
162+
const isTypingIndicatorEnabled = props.isTypingIndicatorEnabled ?? config.groupChannelList.enableTypingIndicator ?? false;
163+
const isMessageReceiptStatusEnabled = props.isMessageReceiptStatusEnabled ?? config.groupChannelList.enableMessageReceiptStatus ?? false;
164+
165+
const eventHandlers = useMemo(() => ({
166+
onChannelSelect,
167+
onChannelCreated,
168+
onThemeChange,
169+
onCreateChannelClick,
170+
onBeforeCreateChannel,
171+
onUserProfileUpdated,
172+
}), [
188173
onChannelSelect,
189174
onChannelCreated,
190175
onThemeChange,
191176
onCreateChannelClick,
192177
onBeforeCreateChannel,
193178
onUserProfileUpdated,
179+
]);
180+
const configurations = useMemo(() => ({
181+
className,
182+
selectedChannelUrl,
183+
disableAutoSelect,
184+
allowProfileEdit,
185+
isTypingIndicatorEnabled,
186+
isMessageReceiptStatusEnabled,
187+
typingChannelUrls,
188+
refreshing,
189+
initialized,
190+
refresh,
191+
loadMore,
192+
}), [
193+
className,
194+
selectedChannelUrl,
195+
disableAutoSelect,
196+
allowProfileEdit,
197+
isTypingIndicatorEnabled,
198+
isMessageReceiptStatusEnabled,
194199
typingChannelUrls,
195200
refreshing,
196201
initialized,
197-
groupChannels.map(channel => channel.url).join(),
198202
refresh,
199203
loadMore,
200204
]);
205+
const memoizedGroupChannel = useMemo(() => groupChannels, [groupChannels]);
206+
useEffect(() => {
207+
updateState({
208+
groupChannels: memoizedGroupChannel,
209+
...eventHandlers,
210+
...configurations,
211+
});
212+
}, [
213+
configurations,
214+
eventHandlers,
215+
memoizedGroupChannel,
216+
]);
201217

202218
return null;
203219
};
@@ -225,10 +241,10 @@ export const GroupChannelListProvider = (props: GroupChannelListProviderProps) =
225241
);
226242
};
227243

244+
// Keep this function for backward compatibility.
228245
export const useGroupChannelListContext = () => {
229-
const context = useContext(GroupChannelListContext);
230-
if (!context) throw new Error('GroupChannelListContext not found. Use within the GroupChannelList module.');
231-
return context;
246+
const { state, actions } = useGroupChannelList();
247+
return { ...state, ...actions };
232248
};
233249

234250
function getCollectionCreator(sdk: SdkStore['sdk'], channelListQueryParams?: ChannelListQueryParamsType) {

src/modules/GroupChannelList/context/__tests__/GroupChannelListProvider.spec.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import React from 'react';
2-
import {
3-
GroupChannelListProvider,
4-
useGroupChannelListContext,
5-
} from '../GroupChannelListProvider';
2+
import { GroupChannelListProvider, useGroupChannelListStore } from '../GroupChannelListProvider';
3+
import { useGroupChannelList } from '../useGroupChannelList';
64
import { act, renderHook, waitFor } from '@testing-library/react';
75

86
const mockState = {
@@ -16,7 +14,11 @@ const mockState = {
1614
initialized: true,
1715
},
1816
},
19-
config: { logger: console },
17+
config: {
18+
logger: console,
19+
groupChannelList: {
20+
},
21+
},
2022
};
2123
jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
2224
__esModule: true,
@@ -64,9 +66,9 @@ describe('GroupChannelListProvider', () => {
6466
</GroupChannelListProvider>
6567
);
6668

67-
const { result } = renderHook(() => useGroupChannelListContext(), { wrapper });
69+
const { result } = renderHook(() => useGroupChannelList(), { wrapper });
6870

69-
expect(result.current.getState()).toMatchObject(initialState);
71+
expect(result.current.state).toMatchObject(initialState);
7072
});
7173

7274
it('update state correctly', async () => {
@@ -79,14 +81,14 @@ describe('GroupChannelListProvider', () => {
7981

8082
channelListQueryParams.prev = 42;
8183

82-
const { result } = renderHook(() => useGroupChannelListContext(), { wrapper });
83-
expect(result.current.getState().className).toEqual('old-classname');
84+
const { result } = renderHook(() => useGroupChannelListStore(), { wrapper });
85+
expect(result.current.state.className).toEqual('old-classname');
8486

8587
await act(async () => {
86-
result.current.setState({ className: 'new-classname' });
87-
result.current.setState({ disableAutoSelect: true });
88+
result.current.updateState({ className: 'new-classname' });
89+
result.current.updateState({ disableAutoSelect: true });
8890
await waitFor(() => {
89-
const newState = result.current.getState();
91+
const newState = result.current.state;
9092
expect(newState.className).toEqual('new-classname');
9193
expect(newState.disableAutoSelect).toEqual(true);
9294
});
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { GroupChannelListState, useGroupChannelListContext } from './GroupChannelListProvider';
21
import { useSyncExternalStore } from 'use-sync-external-store/shim';
3-
import { useMemo } from 'react';
2+
import { useMemo, useContext } from 'react';
3+
import { GroupChannelListState, GroupChannelListContext } from './GroupChannelListProvider';
44

55
export const useGroupChannelList = () => {
6-
const store = useGroupChannelListContext();
6+
const store = useContext(GroupChannelListContext);
77
if (!store) throw new Error('useGroupChannelList must be used within a GroupChannelListProvider');
88

99
const state: GroupChannelListState = useSyncExternalStore(store.subscribe, store.getState);
@@ -12,3 +12,5 @@ export const useGroupChannelList = () => {
1212

1313
return { state, actions };
1414
};
15+
16+
export default useGroupChannelList;

0 commit comments

Comments
 (0)