|
| 1 | +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; |
| 2 | +import type Sendbird from 'sendbird'; |
| 3 | + |
| 4 | +import type { GroupChannelListHook } from '../types'; |
| 5 | +import { arrayToMap } from '../utils'; |
| 6 | + |
| 7 | +type GroupChannelMap = Record<string, Sendbird.GroupChannel>; |
| 8 | +type Options = { |
| 9 | + comparator: (a: Sendbird.GroupChannel, b: Sendbird.GroupChannel) => number; |
| 10 | + query: Sendbird.GroupChannelListQuery; |
| 11 | +}; |
| 12 | + |
| 13 | +const createDefaultGroupChannelListQuery = (sdk: Sendbird.SendBirdInstance) => { |
| 14 | + const query = sdk.GroupChannel.createMyGroupChannelListQuery(); |
| 15 | + query.memberStateFilter = 'all'; |
| 16 | + query.order = 'latest_last_message'; |
| 17 | + query.includeEmpty = true; |
| 18 | + query.limit = 10; |
| 19 | + |
| 20 | + return query; |
| 21 | +}; |
| 22 | + |
| 23 | +const useGroupChannelList = ( |
| 24 | + sdk: Sendbird.SendBirdInstance, |
| 25 | + userId: string, |
| 26 | + options?: Options, |
| 27 | +): GroupChannelListHook => { |
| 28 | + const queryRef = useRef(options?.query); |
| 29 | + const [groupChannelMap, setGroupChannelMap] = useState<GroupChannelMap>({}); |
| 30 | + |
| 31 | + const init = useCallback( |
| 32 | + async (uid: string) => { |
| 33 | + if (uid) { |
| 34 | + let groupQuery = options?.query; |
| 35 | + if (!groupQuery) groupQuery = createDefaultGroupChannelListQuery(sdk); |
| 36 | + queryRef.current = groupQuery; |
| 37 | + |
| 38 | + const channels = await groupQuery.next(); |
| 39 | + setGroupChannelMap((prev) => ({ |
| 40 | + ...prev, |
| 41 | + ...arrayToMap(channels, 'url'), |
| 42 | + })); |
| 43 | + channels.forEach((channel) => sdk.markAsDelivered(channel.url)); |
| 44 | + } else { |
| 45 | + setGroupChannelMap({}); |
| 46 | + } |
| 47 | + }, |
| 48 | + [sdk, options?.query], |
| 49 | + ); |
| 50 | + |
| 51 | + useEffect(() => { |
| 52 | + init(userId); |
| 53 | + }, [init, userId]); |
| 54 | + |
| 55 | + const groupChannels = useMemo( |
| 56 | + () => Object.values(groupChannelMap).sort(options?.comparator), |
| 57 | + [groupChannelMap, options?.comparator], |
| 58 | + ); |
| 59 | + |
| 60 | + const refresh = useCallback(() => init(userId), [init, userId]); |
| 61 | + |
| 62 | + const update = useCallback( |
| 63 | + (channel: Sendbird.GroupChannel) => { |
| 64 | + sdk.markAsDelivered(channel.url); |
| 65 | + setGroupChannelMap((prev) => ({ ...prev, [channel.url]: channel })); |
| 66 | + }, |
| 67 | + [sdk], |
| 68 | + ); |
| 69 | + |
| 70 | + const loadPrev = useCallback(async () => { |
| 71 | + if (queryRef.current?.hasNext) { |
| 72 | + const channels = await queryRef.current.next(); |
| 73 | + setGroupChannelMap((prev) => ({ |
| 74 | + ...prev, |
| 75 | + ...arrayToMap(channels, 'url'), |
| 76 | + })); |
| 77 | + channels.forEach((channel) => sdk.markAsDelivered(channel.url)); |
| 78 | + } |
| 79 | + }, [sdk]); |
| 80 | + return { groupChannels, update, refresh, loadPrev }; |
| 81 | +}; |
| 82 | + |
| 83 | +export default useGroupChannelList; |
0 commit comments