Skip to content

Commit f958df3

Browse files
author
Sravan S
authored
feat: add prop activeChannelUrl to ChannelList (#407)
Add prop: activeChannelUrl activeChannelUrl gives customer an option to pragmatically set a channel from a parent component/ router If channel is present in client side, it is used If not present in client side, channel is fetched from backend and added to end of the list and set as selected If not present, no errors will be thrown If user clicks other channel, the item set from outside is removed and clicked channel will be selected If activeChannelUrl is present, ChannelList behaves similar to "disableAutoSelect" is true example ``` const MyChat = () => { const {my_active_channel} = useRouter(); return ( <ChannelList activeChannelUrl={my_active_channel} /> ); ``` fixes: https://sendbird.atlassian.net/browse/UIKIT-3180
1 parent 7fec59f commit f958df3

File tree

5 files changed

+117
-1
lines changed

5 files changed

+117
-1
lines changed

scripts/index_d_ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ declare module "SendbirdUIKitGlobal" {
332332
renderUserProfile?: (props: RenderUserProfileProps) => React.ReactNode | React.ReactElement;
333333
disableUserProfile?: boolean;
334334
disableAutoSelect?: boolean;
335+
activeChannelUrl?: string;
335336
isTypingIndicatorEnabled?: boolean;
336337
isMessageReceiptStatusEnabled?: boolean;
337338
}

src/smart-components/ChannelList/context/ChannelListProvider.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { CustomUseReducerDispatcher } from '../../../lib/SendbirdState';
3333
import channelListReducers from '../dux/reducers';
3434
import channelListInitialState from '../dux/initialState';
3535
import { CHANNEL_TYPE } from '../../CreateChannel/types';
36+
import useActiveChannelUrl from './hooks/useActiveChannelUrl';
3637

3738
interface ApplicationUserListQuery {
3839
limit?: number;
@@ -88,6 +89,7 @@ export interface ChannelListProviderProps {
8889
renderUserProfile?: (props: RenderUserProfileProps) => React.ReactElement;
8990
disableUserProfile?: boolean;
9091
disableAutoSelect?: boolean;
92+
activeChannelUrl?: string;
9193
typingChannels?: Array<GroupChannel>;
9294
isTypingIndicatorEnabled?: boolean;
9395
isMessageReceiptStatusEnabled?: boolean;
@@ -150,10 +152,13 @@ const ChannelListProvider: React.FC<ChannelListProviderProps> = (props: ChannelL
150152
onBeforeCreateChannel,
151153
sortChannelList,
152154
overrideInviteUser,
153-
disableAutoSelect,
155+
activeChannelUrl,
154156
isTypingIndicatorEnabled = null,
155157
isMessageReceiptStatusEnabled = null,
156158
} = props;
159+
// disable autoselect, if activeChannelUrl is provided
160+
// useActiveChannelUrl should be executed when activeChannelUrl is present
161+
const disableAutoSelect = props?.disableAutoSelect || !!activeChannelUrl;
157162
const onChannelSelect = props?.onChannelSelect || noop;
158163
// fetch store from <SendbirdProvider />
159164
const globalStore = useSendbirdStateContext();
@@ -350,6 +355,16 @@ const ChannelListProvider: React.FC<ChannelListProviderProps> = (props: ChannelL
350355
});
351356
}, [currentChannel?.url]);
352357

358+
// Set active channel (by url)
359+
useActiveChannelUrl({
360+
activeChannelUrl,
361+
channels: sortedChannels,
362+
sdk,
363+
} , {
364+
logger,
365+
channelListDispatcher,
366+
});
367+
353368
return (
354369
<ChannelListContext.Provider value={{
355370
className,
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { useEffect } from 'react';
2+
import * as messageActionTypes from '../../dux/actionTypes';
3+
import { GroupChannel, SendbirdGroupChat } from '@sendbird/chat/groupChannel';
4+
import { Logger } from '../../../../lib/SendbirdState';
5+
6+
export type DynamicProps = {
7+
activeChannelUrl?: string;
8+
channels?: GroupChannel[];
9+
sdk?: SendbirdGroupChat;
10+
};
11+
12+
export type StaticProps = {
13+
logger: Logger;
14+
channelListDispatcher: React.Dispatch<any>;
15+
};
16+
17+
function useActiveChannelUrl({
18+
activeChannelUrl,
19+
channels,
20+
sdk
21+
}: DynamicProps, {
22+
logger,
23+
channelListDispatcher
24+
}: StaticProps): void {
25+
return useEffect(() => {
26+
if (activeChannelUrl) {
27+
logger.info('ChannelListProvider: looking for active channel', { activeChannelUrl });
28+
const activeChannel = channels.find(channel => channel.url === activeChannelUrl);
29+
if (activeChannel) {
30+
channelListDispatcher({
31+
type: messageActionTypes.SET_CURRENT_CHANNEL,
32+
payload: activeChannel,
33+
});
34+
} else {
35+
logger.info('ChannelListProvider: searching backend for active channel', { activeChannelUrl });
36+
sdk?.groupChannel?.getChannel(activeChannelUrl)
37+
.then((channel) => {
38+
channelListDispatcher({
39+
type: messageActionTypes.FETCH_CHANNELS_SUCCESS,
40+
payload: [channel],
41+
});
42+
channelListDispatcher({
43+
type: messageActionTypes.SET_CURRENT_CHANNEL,
44+
payload: channel,
45+
});
46+
})
47+
.catch(() => {
48+
logger.warning('ChannelListProvider: Active channel not found');
49+
});
50+
}
51+
}
52+
}, [activeChannelUrl, channels, sdk]);
53+
}
54+
55+
export default useActiveChannelUrl;

src/smart-components/ChannelList/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const ChannelList: React.FC<ChannelListProps> = (props: ChannelListProps) => {
2222
sortChannelList={props?.sortChannelList}
2323
queries={props?.queries}
2424
disableAutoSelect={props?.disableAutoSelect}
25+
activeChannelUrl={props?.activeChannelUrl}
2526
isTypingIndicatorEnabled={props?.isTypingIndicatorEnabled}
2627
isMessageReceiptStatusEnabled={props?.isMessageReceiptStatusEnabled}
2728
>

src/smart-components/ChannelList/stories/index.stories.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,47 @@ export const QueryParamsForChannelList = () => {
204204
</Sendbird>
205205
);
206206
};
207+
208+
export const preSelectedChannel = () => {
209+
const defaultChannel = 'sendbird_group_channel_199019523_b6febec0ad887b774dbe374e7a907841a9d2a61b';
210+
const defaultQuery = {
211+
channelListQuery: {
212+
limit: 20,
213+
},
214+
};
215+
const [activeChannelUrl, setActiveChannelUrl] = useState(defaultChannel);
216+
const [queries, setQueries] = useState(defaultQuery);
217+
return (
218+
<Sendbird
219+
appId={appId}
220+
userId={userId}
221+
>
222+
<div>
223+
<button
224+
onClick={() => {
225+
setQueries(defaultQuery)
226+
setActiveChannelUrl('random_url');
227+
}}
228+
>Set invalid URL </button>
229+
<button
230+
onClick={() => {
231+
setQueries({
232+
channelListQuery: {
233+
limit: 2,
234+
}
235+
});
236+
setActiveChannelUrl(defaultChannel);
237+
}}
238+
>Set channel outside list </button>
239+
</div>
240+
<div style={{ height: '520px' }}>
241+
<ChannelList
242+
queries={queries}
243+
onChannelSelect={(c) => { console.warn(c); }}
244+
activeChannelUrl={activeChannelUrl}
245+
/>
246+
</div>
247+
248+
</Sendbird>
249+
);
250+
};

0 commit comments

Comments
 (0)