@sendbird/uikit-chat-hooks 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -0
  3. package/lib/commonjs/channel/useActiveGroupChannel.js +22 -0
  4. package/lib/commonjs/channel/useActiveGroupChannel.js.map +1 -0
  5. package/lib/commonjs/channel/useGroupChannelList.js +21 -0
  6. package/lib/commonjs/channel/useGroupChannelList.js.map +1 -0
  7. package/lib/commonjs/channel/useGroupChannelListWithCollection.js +148 -0
  8. package/lib/commonjs/channel/useGroupChannelListWithCollection.js.map +1 -0
  9. package/lib/commonjs/channel/useGroupChannelListWithQuery.js +130 -0
  10. package/lib/commonjs/channel/useGroupChannelListWithQuery.js.map +1 -0
  11. package/lib/commonjs/channel/useGroupChannelMessages/index.js +21 -0
  12. package/lib/commonjs/channel/useGroupChannelMessages/index.js.map +1 -0
  13. package/lib/commonjs/channel/useGroupChannelMessages/reducer.js +158 -0
  14. package/lib/commonjs/channel/useGroupChannelMessages/reducer.js.map +1 -0
  15. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +305 -0
  16. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -0
  17. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +249 -0
  18. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -0
  19. package/lib/commonjs/common/useAppFeatures.js +44 -0
  20. package/lib/commonjs/common/useAppFeatures.js.map +1 -0
  21. package/lib/commonjs/common/usePushTrigger.js +33 -0
  22. package/lib/commonjs/common/usePushTrigger.js.map +1 -0
  23. package/lib/commonjs/common/useTotalUnreadChannelCount.js +29 -0
  24. package/lib/commonjs/common/useTotalUnreadChannelCount.js.map +1 -0
  25. package/lib/commonjs/common/useTotalUnreadMessageCount.js +40 -0
  26. package/lib/commonjs/common/useTotalUnreadMessageCount.js.map +1 -0
  27. package/lib/commonjs/common/useUserList.js +110 -0
  28. package/lib/commonjs/common/useUserList.js.map +1 -0
  29. package/lib/commonjs/handler/useChannelHandler.js +29 -0
  30. package/lib/commonjs/handler/useChannelHandler.js.map +1 -0
  31. package/lib/commonjs/handler/useConnectionHandler.js +29 -0
  32. package/lib/commonjs/handler/useConnectionHandler.js.map +1 -0
  33. package/lib/commonjs/handler/useUserEventHandler.js +29 -0
  34. package/lib/commonjs/handler/useUserEventHandler.js.map +1 -0
  35. package/lib/commonjs/index.js +102 -0
  36. package/lib/commonjs/index.js.map +1 -0
  37. package/lib/commonjs/model/CustomQuery.js +28 -0
  38. package/lib/commonjs/model/CustomQuery.js.map +1 -0
  39. package/lib/commonjs/types.js +6 -0
  40. package/lib/commonjs/types.js.map +1 -0
  41. package/lib/module/channel/useActiveGroupChannel.js +12 -0
  42. package/lib/module/channel/useActiveGroupChannel.js.map +1 -0
  43. package/lib/module/channel/useGroupChannelList.js +10 -0
  44. package/lib/module/channel/useGroupChannelList.js.map +1 -0
  45. package/lib/module/channel/useGroupChannelListWithCollection.js +135 -0
  46. package/lib/module/channel/useGroupChannelListWithCollection.js.map +1 -0
  47. package/lib/module/channel/useGroupChannelListWithQuery.js +117 -0
  48. package/lib/module/channel/useGroupChannelListWithQuery.js.map +1 -0
  49. package/lib/module/channel/useGroupChannelMessages/index.js +10 -0
  50. package/lib/module/channel/useGroupChannelMessages/index.js.map +1 -0
  51. package/lib/module/channel/useGroupChannelMessages/reducer.js +148 -0
  52. package/lib/module/channel/useGroupChannelMessages/reducer.js.map +1 -0
  53. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +289 -0
  54. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -0
  55. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +234 -0
  56. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -0
  57. package/lib/module/common/useAppFeatures.js +33 -0
  58. package/lib/module/common/useAppFeatures.js.map +1 -0
  59. package/lib/module/common/usePushTrigger.js +22 -0
  60. package/lib/module/common/usePushTrigger.js.map +1 -0
  61. package/lib/module/common/useTotalUnreadChannelCount.js +17 -0
  62. package/lib/module/common/useTotalUnreadChannelCount.js.map +1 -0
  63. package/lib/module/common/useTotalUnreadMessageCount.js +28 -0
  64. package/lib/module/common/useTotalUnreadMessageCount.js.map +1 -0
  65. package/lib/module/common/useUserList.js +100 -0
  66. package/lib/module/common/useUserList.js.map +1 -0
  67. package/lib/module/handler/useChannelHandler.js +17 -0
  68. package/lib/module/handler/useChannelHandler.js.map +1 -0
  69. package/lib/module/handler/useConnectionHandler.js +17 -0
  70. package/lib/module/handler/useConnectionHandler.js.map +1 -0
  71. package/lib/module/handler/useUserEventHandler.js +17 -0
  72. package/lib/module/handler/useUserEventHandler.js.map +1 -0
  73. package/lib/module/index.js +13 -0
  74. package/lib/module/index.js.map +1 -0
  75. package/lib/module/model/CustomQuery.js +19 -0
  76. package/lib/module/model/CustomQuery.js.map +1 -0
  77. package/lib/module/types.js +2 -0
  78. package/lib/module/types.js.map +1 -0
  79. package/lib/typescript/src/channel/useActiveGroupChannel.d.ts +5 -0
  80. package/lib/typescript/src/channel/useGroupChannelList.d.ts +2 -0
  81. package/lib/typescript/src/channel/useGroupChannelListWithCollection.d.ts +2 -0
  82. package/lib/typescript/src/channel/useGroupChannelListWithQuery.d.ts +2 -0
  83. package/lib/typescript/src/channel/useGroupChannelMessages/index.d.ts +2 -0
  84. package/lib/typescript/src/channel/useGroupChannelMessages/reducer.d.ts +15 -0
  85. package/lib/typescript/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.d.ts +2 -0
  86. package/lib/typescript/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.d.ts +2 -0
  87. package/lib/typescript/src/common/useAppFeatures.d.ts +7 -0
  88. package/lib/typescript/src/common/usePushTrigger.d.ts +7 -0
  89. package/lib/typescript/src/common/useTotalUnreadChannelCount.d.ts +6 -0
  90. package/lib/typescript/src/common/useTotalUnreadMessageCount.d.ts +8 -0
  91. package/lib/typescript/src/common/useUserList.d.ts +24 -0
  92. package/lib/typescript/src/handler/useChannelHandler.d.ts +4 -0
  93. package/lib/typescript/src/handler/useConnectionHandler.d.ts +4 -0
  94. package/lib/typescript/src/handler/useUserEventHandler.d.ts +4 -0
  95. package/lib/typescript/src/index.d.ts +13 -0
  96. package/lib/typescript/src/model/CustomQuery.d.ts +14 -0
  97. package/lib/typescript/src/types.d.ts +198 -0
  98. package/package.json +73 -0
  99. package/src/channel/useActiveGroupChannel.ts +13 -0
  100. package/src/channel/useGroupChannelList.ts +11 -0
  101. package/src/channel/useGroupChannelListWithCollection.ts +144 -0
  102. package/src/channel/useGroupChannelListWithQuery.ts +124 -0
  103. package/src/channel/useGroupChannelMessages/index.ts +11 -0
  104. package/src/channel/useGroupChannelMessages/reducer.ts +134 -0
  105. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.ts +315 -0
  106. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.ts +251 -0
  107. package/src/common/useAppFeatures.ts +28 -0
  108. package/src/common/usePushTrigger.ts +31 -0
  109. package/src/common/useTotalUnreadChannelCount.ts +26 -0
  110. package/src/common/useTotalUnreadMessageCount.ts +43 -0
  111. package/src/common/useUserList.ts +103 -0
  112. package/src/handler/useChannelHandler.ts +25 -0
  113. package/src/handler/useConnectionHandler.ts +25 -0
  114. package/src/handler/useUserEventHandler.ts +26 -0
  115. package/src/index.ts +26 -0
  116. package/src/model/CustomQuery.ts +20 -0
  117. package/src/types.ts +246 -0
@@ -0,0 +1,198 @@
1
+ import type Sendbird from 'sendbird';
2
+ import type { SendbirdChatSDK, SendbirdError, SendbirdFileMessage, SendbirdFileMessageParams, SendbirdGroupChannel, SendbirdGroupChannelCollection, SendbirdMessage, SendbirdMessageCollection, SendbirdUserMessage, SendbirdUserMessageParams } from '@sendbird/uikit-utils';
3
+ export interface CustomQueryInterface<Data> {
4
+ isLoading: boolean;
5
+ next: () => Promise<Data[]>;
6
+ hasNext: boolean;
7
+ }
8
+ export interface CustomBidirectionalQueryInterface<Data> {
9
+ isLoading: boolean;
10
+ next: () => Promise<Data[]>;
11
+ hasNext: () => boolean;
12
+ prev: () => Promise<Data[]>;
13
+ hasPrev: () => boolean;
14
+ }
15
+ /**
16
+ * @interface UseGroupChannelList
17
+ * @description interface for group channel list hook
18
+ * */
19
+ export interface UseGroupChannelList {
20
+ (sdk: SendbirdChatSDK, userId?: string, options?: UseGroupChannelListOptions): {
21
+ /**
22
+ * Loading state, only available on first render
23
+ * */
24
+ loading: boolean;
25
+ /**
26
+ * Refreshing state, status is changes when the refresh is called.
27
+ * */
28
+ refreshing: boolean;
29
+ /**
30
+ * Refresh, clear and reload messages from latest
31
+ * @return {Promise<void>}
32
+ * */
33
+ refresh: () => Promise<void>;
34
+ /**
35
+ * Update channel, update or insert channel to state
36
+ * @param {SendbirdGroupChannel} channel
37
+ * @return {void}
38
+ * */
39
+ update: (channel: SendbirdGroupChannel) => void;
40
+ /**
41
+ * Get group channels state
42
+ * */
43
+ groupChannels: SendbirdGroupChannel[];
44
+ /**
45
+ * Fetch next channels to state
46
+ * @return {Promise<void>}
47
+ * */
48
+ next: () => Promise<void>;
49
+ };
50
+ }
51
+ export declare type UseGroupChannelListOptions = {
52
+ sortComparator?: (a: SendbirdGroupChannel, b: SendbirdGroupChannel) => number;
53
+ queryCreator?: () => Sendbird.GroupChannelListQuery;
54
+ collectionCreator?: () => SendbirdGroupChannelCollection;
55
+ enableCollectionWithoutLocalCache?: boolean;
56
+ };
57
+ /**
58
+ * @interface UseGroupChannelMessages
59
+ * @description interface for group channel messages hook
60
+ * - Receive new messages from other users -> append to state(nextMessages)
61
+ * - onTopReached -> prev() -> fetch prev messages and append to state(messages)
62
+ * - onBottomReached -> next() -> nextMessages append to state(messages)
63
+ * */
64
+ export interface UseGroupChannelMessages {
65
+ (sdk: SendbirdChatSDK, channel: SendbirdGroupChannel, userId?: string, options?: UseGroupChannelMessagesOptions): {
66
+ /**
67
+ * Loading state, only available on first render
68
+ * */
69
+ loading: boolean;
70
+ /**
71
+ * Refreshing state, status is changes when the refresh is called.
72
+ * */
73
+ refreshing: boolean;
74
+ /**
75
+ * Refresh, clear and reload messages from latest
76
+ * @return {Promise<void>}
77
+ * */
78
+ refresh: () => Promise<void>;
79
+ /**
80
+ * Get messages, this state is for render
81
+ * For example, if a user receives a new messages while searching for an old message
82
+ * for this case, new messages will be included here.
83
+ * @return {SendbirdMessage[]}
84
+ * */
85
+ messages: SendbirdMessage[];
86
+ /**
87
+ * Fetch prev messages to state
88
+ * @return {Promise<void>}
89
+ * */
90
+ prev: () => Promise<void>;
91
+ /**
92
+ * Get messages, this state is for temporary data before render
93
+ * For example, if a user receives a new messages while searching for an old message
94
+ * for this case, new messages will be included here.
95
+ * */
96
+ nextMessages: SendbirdMessage[];
97
+ /**
98
+ * Get new messages from nextMessages
99
+ * A new message means a message that meets the below conditions
100
+ * - Not admin message
101
+ * - Not updated message
102
+ * - Not current user's message
103
+ * */
104
+ newMessagesFromMembers: SendbirdMessage[];
105
+ /**
106
+ * Fetch next messages to state
107
+ * @return {Promise<void>}
108
+ * */
109
+ next: () => Promise<void>;
110
+ /**
111
+ * Send file message
112
+ * @param params file message params
113
+ * @param callback sent message callback
114
+ * @return pending message
115
+ * */
116
+ sendFileMessage: (params: SendbirdFileMessageParams, onPending?: (message: SendbirdFileMessage, error?: SendbirdError) => void) => Promise<SendbirdFileMessage>;
117
+ /**
118
+ * Send user message
119
+ * @param params user message params
120
+ * @param callback sent message callback
121
+ * @return pending message
122
+ * */
123
+ sendUserMessage: (params: SendbirdUserMessageParams, onPending?: (message: SendbirdUserMessage, error?: SendbirdError) => void) => Promise<SendbirdUserMessage>;
124
+ /**
125
+ * Update file message
126
+ * @param messageId
127
+ * @param params file message params
128
+ * @return updated message
129
+ * */
130
+ updateFileMessage: (messageId: number, params: SendbirdFileMessageParams) => Promise<SendbirdFileMessage>;
131
+ /**
132
+ * Update user message
133
+ * @param messageId
134
+ * @param params user message params
135
+ * @return updated message
136
+ * */
137
+ updateUserMessage: (messageId: number, params: SendbirdUserMessageParams) => Promise<SendbirdUserMessage>;
138
+ /**
139
+ * Resend failed message
140
+ * @param failedMessage failed message to resend
141
+ * @return {Promise<void>}
142
+ * */
143
+ resendMessage: (failedMessage: SendbirdFileMessage | SendbirdUserMessage) => Promise<void>;
144
+ /**
145
+ * Delete message
146
+ * @param message sent or failed message
147
+ * @return {Promise<void>}
148
+ * */
149
+ deleteMessage: (message: SendbirdFileMessage | SendbirdUserMessage) => Promise<void>;
150
+ /**
151
+ * Activated channel
152
+ * */
153
+ activeChannel: SendbirdGroupChannel;
154
+ };
155
+ }
156
+ export declare type UseGroupChannelMessagesOptions = {
157
+ sortComparator?: (a: SendbirdMessage, b: SendbirdMessage) => number;
158
+ queryCreator?: () => Sendbird.PreviousMessageListQuery;
159
+ collectionCreator?: () => SendbirdMessageCollection;
160
+ enableCollectionWithoutLocalCache?: boolean;
161
+ onChannelDeleted?: () => void;
162
+ };
163
+ /**
164
+ * @interface UseUserListReturn
165
+ * @description interface for user list hook return value
166
+ * */
167
+ export interface UseUserListReturn<User> {
168
+ /**
169
+ * Loading state, only available on first render
170
+ * */
171
+ loading: boolean;
172
+ /**
173
+ * Refreshing state, status is changes when the refresh is called.
174
+ * */
175
+ refreshing: boolean;
176
+ /**
177
+ * Error state
178
+ * */
179
+ error: unknown | null;
180
+ /**
181
+ * Refresh, clear and reload messages from latest
182
+ * @return {Promise<void>}
183
+ * */
184
+ refresh: () => Promise<void>;
185
+ /**
186
+ * Get users state
187
+ * */
188
+ users: User[];
189
+ /**
190
+ * Fetch next users to state
191
+ * @return {Promise<void>}
192
+ * */
193
+ next: () => Promise<void>;
194
+ }
195
+ export declare type UseUserListOptions<User> = {
196
+ sortComparator?: (a: User, b: User) => number;
197
+ queryCreator?: () => CustomQueryInterface<User>;
198
+ };
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@sendbird/uikit-chat-hooks",
3
+ "version": "1.0.0-rc.1",
4
+ "description": "React hooks that built with SendbirdChat SDK",
5
+ "main": "lib/commonjs/index",
6
+ "module": "lib/module/index",
7
+ "types": "lib/typescript/src/index.d.ts",
8
+ "react-native": "src/index",
9
+ "source": "src/index",
10
+ "files": [
11
+ "src",
12
+ "lib",
13
+ "!**/__tests__"
14
+ ],
15
+ "sideEffects": false,
16
+ "scripts": {
17
+ "test": "jest",
18
+ "build": "bob build",
19
+ "clean": "del lib"
20
+ },
21
+ "keywords": [
22
+ "react",
23
+ "sendbird"
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/sendbird/sendbird-uikit-react-native.git",
28
+ "directory": "packages/uikit-chat-hooks"
29
+ },
30
+ "author": "Sendbird <support@sendbird.com>",
31
+ "license": "SEE LICENSE IN LICENSE.md",
32
+ "bugs": {
33
+ "url": "https://github.com/sendbird/sendbird-uikit-react-native.git/issues"
34
+ },
35
+ "homepage": "https://github.com/sendbird/sendbird-uikit-react-native.git#readme",
36
+ "publishConfig": {
37
+ "registry": "https://registry.npmjs.org/",
38
+ "access": "public"
39
+ },
40
+ "dependencies": {
41
+ "@sendbird/uikit-utils": "1.0.0-rc.1"
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "17.0.2",
45
+ "react": "^16.13.1",
46
+ "react-native-builder-bob": "^0.18.0",
47
+ "typescript": "^4.1.3"
48
+ },
49
+ "peerDependencies": {
50
+ "react": ">=16.13.1",
51
+ "sendbird": "^3.1.22"
52
+ },
53
+ "react-native-builder-bob": {
54
+ "source": "src",
55
+ "output": "lib",
56
+ "targets": [
57
+ "commonjs",
58
+ "module",
59
+ [
60
+ "typescript",
61
+ {
62
+ "project": "tsconfig.build.json"
63
+ }
64
+ ]
65
+ ]
66
+ },
67
+ "typedoc": {
68
+ "entryPoint": "./src/index.ts",
69
+ "readmeFile": "./README.md",
70
+ "displayName": "@sendbird/uikit-chat-hooks"
71
+ },
72
+ "gitHead": "870c05138843249a23a3978106a17e7a4e466d4d"
73
+ }
@@ -0,0 +1,13 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import type { SendbirdChatSDK, SendbirdGroupChannel } from '@sendbird/uikit-utils';
4
+
5
+ export const useActiveGroupChannel = (sdk: SendbirdChatSDK, staleChannel: SendbirdGroupChannel) => {
6
+ const [activeChannel, setActiveChannel] = useState(() => staleChannel);
7
+
8
+ useEffect(() => {
9
+ sdk.GroupChannel.getChannel(staleChannel.url).then(setActiveChannel);
10
+ }, [staleChannel.url]);
11
+
12
+ return { activeChannel, setActiveChannel };
13
+ };
@@ -0,0 +1,11 @@
1
+ import type { UseGroupChannelList } from '../types';
2
+ import { useGroupChannelListWithCollection } from './useGroupChannelListWithCollection';
3
+ import { useGroupChannelListWithQuery } from './useGroupChannelListWithQuery';
4
+
5
+ export const useGroupChannelList: UseGroupChannelList = (sdk, userId, options) => {
6
+ if (sdk.isCacheEnabled || options?.enableCollectionWithoutLocalCache) {
7
+ return useGroupChannelListWithCollection(sdk, userId, options);
8
+ } else {
9
+ return useGroupChannelListWithQuery(sdk, userId, options);
10
+ }
11
+ };
@@ -0,0 +1,144 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+
3
+ import type {
4
+ SendbirdChannel,
5
+ SendbirdChatSDK,
6
+ SendbirdGroupChannel,
7
+ SendbirdGroupChannelCollection,
8
+ } from '@sendbird/uikit-utils';
9
+ import { arrayToMap, useAsyncEffect, useUniqId } from '@sendbird/uikit-utils';
10
+
11
+ import { useAppFeatures } from '../common/useAppFeatures';
12
+ import { useChannelHandler } from '../handler/useChannelHandler';
13
+ import type { UseGroupChannelList, UseGroupChannelListOptions } from '../types';
14
+
15
+ type GroupChannelMap = Record<string, SendbirdGroupChannel>;
16
+
17
+ const HOOK_NAME = 'useGroupChannelListWithCollection';
18
+ const createGroupChannelListCollection = (
19
+ sdk: SendbirdChatSDK,
20
+ collectionCreator: UseGroupChannelListOptions['collectionCreator'],
21
+ ) => {
22
+ const passedCollection = collectionCreator?.();
23
+ if (passedCollection) return passedCollection;
24
+
25
+ const defaultCollection = sdk.GroupChannel.createGroupChannelCollection();
26
+ const filter = new sdk.GroupChannelFilter();
27
+ return defaultCollection.setLimit(20).setFilter(filter).build();
28
+ };
29
+
30
+ export const useGroupChannelListWithCollection: UseGroupChannelList = (sdk, userId, options) => {
31
+ const id = useUniqId(HOOK_NAME);
32
+ const { deliveryReceiptEnabled } = useAppFeatures(sdk);
33
+
34
+ const collectionRef = useRef<SendbirdGroupChannelCollection>();
35
+ const [loading, setLoading] = useState(false);
36
+ const [refreshing, setRefreshing] = useState(false);
37
+
38
+ const [groupChannelMap, setGroupChannelMap] = useState<GroupChannelMap>({});
39
+ const groupChannels = useMemo(() => {
40
+ const channels = Object.values(groupChannelMap);
41
+ if (options?.sortComparator) return channels.sort(options?.sortComparator);
42
+ return channels;
43
+ }, [groupChannelMap, options?.sortComparator]);
44
+
45
+ // ---------- internal methods ---------- //
46
+ const updateChannels = (channels: SendbirdChannel[], clearPrev: boolean) => {
47
+ const groupChannels = channels.filter((c): c is SendbirdGroupChannel => c.isGroupChannel());
48
+ if (clearPrev) setGroupChannelMap(arrayToMap(groupChannels, 'url'));
49
+ else setGroupChannelMap((prev) => ({ ...prev, ...arrayToMap(groupChannels, 'url') }));
50
+ if (deliveryReceiptEnabled) groupChannels.forEach((channel) => sdk.markAsDelivered(channel.url));
51
+ };
52
+ const deleteChannels = (channelUrls: string[]) => {
53
+ setGroupChannelMap(({ ...draft }) => {
54
+ channelUrls.forEach((url) => delete draft[url]);
55
+ return draft;
56
+ });
57
+ };
58
+ const init = useCallback(
59
+ async (uid?: string) => {
60
+ if (collectionRef.current) collectionRef.current?.dispose();
61
+
62
+ if (uid) {
63
+ collectionRef.current = createGroupChannelListCollection(sdk, options?.collectionCreator);
64
+ if (collectionRef.current?.hasMore) {
65
+ updateChannels(await collectionRef.current?.loadMore(), true);
66
+ }
67
+
68
+ collectionRef.current?.setGroupChannelCollectionHandler({
69
+ onChannelsAdded(_, channels) {
70
+ updateChannels(channels, false);
71
+ },
72
+ onChannelsUpdated(_, channels) {
73
+ updateChannels(channels, false);
74
+ },
75
+ onChannelsDeleted(_, channelUrls) {
76
+ deleteChannels(channelUrls);
77
+ },
78
+ });
79
+ }
80
+ },
81
+ [sdk, options?.collectionCreator],
82
+ );
83
+ // ---------- internal methods ends ---------- //
84
+
85
+ // ---------- internal hooks ---------- //
86
+ useEffect(() => {
87
+ return () => {
88
+ if (collectionRef.current) collectionRef.current?.dispose();
89
+ };
90
+ }, []);
91
+
92
+ useAsyncEffect(async () => {
93
+ setLoading(true);
94
+ await init(userId);
95
+ setLoading(false);
96
+ }, [init, userId]);
97
+
98
+ useChannelHandler(
99
+ sdk,
100
+ `${HOOK_NAME}_${id}`,
101
+ {
102
+ onUserBanned: (channel, user) => {
103
+ const isMe = user.userId === userId;
104
+ if (isMe) deleteChannels([channel.url]);
105
+ else updateChannels([channel], false);
106
+ },
107
+ },
108
+ [sdk, userId],
109
+ );
110
+ // ---------- internal hooks ends ---------- //
111
+
112
+ // ---------- returns methods ---------- //
113
+ const refresh = useCallback(async () => {
114
+ setRefreshing(true);
115
+ await init(userId);
116
+ setRefreshing(false);
117
+ }, [init, userId]);
118
+
119
+ const update = useCallback(
120
+ (channel: SendbirdGroupChannel) => {
121
+ if (deliveryReceiptEnabled) sdk.markAsDelivered(channel.url);
122
+ setGroupChannelMap((prev) => ({ ...prev, [channel.url]: channel }));
123
+ },
124
+ [sdk],
125
+ );
126
+
127
+ const next = useCallback(async () => {
128
+ if (collectionRef.current?.hasMore) {
129
+ const channels = await collectionRef.current?.loadMore();
130
+ setGroupChannelMap((prev) => ({ ...prev, ...arrayToMap(channels, 'url') }));
131
+ if (deliveryReceiptEnabled) channels.forEach((channel) => sdk.markAsDelivered(channel.url));
132
+ }
133
+ }, [sdk]);
134
+ // ---------- returns methods ends ---------- //
135
+
136
+ return {
137
+ loading,
138
+ groupChannels,
139
+ refresh,
140
+ refreshing,
141
+ next,
142
+ update,
143
+ };
144
+ };
@@ -0,0 +1,124 @@
1
+ import { useCallback, useMemo, useRef, useState } from 'react';
2
+ import type Sendbird from 'sendbird';
3
+
4
+ import type { SendbirdChannel, SendbirdChatSDK, SendbirdGroupChannel } from '@sendbird/uikit-utils';
5
+ import { arrayToMap, useAsyncEffect } from '@sendbird/uikit-utils';
6
+
7
+ import { useAppFeatures } from '../common/useAppFeatures';
8
+ import { useChannelHandler } from '../handler/useChannelHandler';
9
+ import type { UseGroupChannelList, UseGroupChannelListOptions } from '../types';
10
+
11
+ type GroupChannelMap = Record<string, SendbirdGroupChannel>;
12
+
13
+ const HOOK_NAME = 'useGroupChannelListWithQuery';
14
+ const createGroupChannelListQuery = (
15
+ sdk: SendbirdChatSDK,
16
+ queryCreator: UseGroupChannelListOptions['queryCreator'],
17
+ ) => {
18
+ const passedQuery = queryCreator?.();
19
+ if (passedQuery) return passedQuery;
20
+
21
+ const defaultQuery = sdk.GroupChannel.createMyGroupChannelListQuery();
22
+ defaultQuery.limit = 20;
23
+ return defaultQuery;
24
+ };
25
+
26
+ export const useGroupChannelListWithQuery: UseGroupChannelList = (sdk, userId, options) => {
27
+ const { deliveryReceiptEnabled } = useAppFeatures(sdk);
28
+ const queryRef = useRef<Sendbird.GroupChannelListQuery>();
29
+ const [loading, setLoading] = useState(false);
30
+ const [refreshing, setRefreshing] = useState(false);
31
+
32
+ const [groupChannelMap, setGroupChannelMap] = useState<GroupChannelMap>({});
33
+ const groupChannels = useMemo(() => {
34
+ const channels = Object.values(groupChannelMap);
35
+ if (options?.sortComparator) return channels.sort(options?.sortComparator);
36
+ return channels;
37
+ }, [groupChannelMap, options?.sortComparator]);
38
+
39
+ // ---------- internal methods ---------- //
40
+ const updateChannels = (channels: SendbirdChannel[], clearPrev: boolean) => {
41
+ const groupChannels = channels.filter((c): c is SendbirdGroupChannel => c.isGroupChannel());
42
+ if (clearPrev) setGroupChannelMap(arrayToMap(groupChannels, 'url'));
43
+ else setGroupChannelMap((prev) => ({ ...prev, ...arrayToMap(groupChannels, 'url') }));
44
+
45
+ if (deliveryReceiptEnabled) groupChannels.forEach((channel) => sdk.markAsDelivered(channel.url));
46
+ };
47
+ const deleteChannels = (channelUrls: string[]) => {
48
+ setGroupChannelMap(({ ...draft }) => {
49
+ channelUrls.forEach((url) => delete draft[url]);
50
+ return draft;
51
+ });
52
+ };
53
+ const init = useCallback(
54
+ async (uid?: string) => {
55
+ if (uid) {
56
+ queryRef.current = createGroupChannelListQuery(sdk, options?.queryCreator);
57
+ if (queryRef.current?.hasNext) {
58
+ const channels = await queryRef.current.next();
59
+ updateChannels(channels, true);
60
+ }
61
+ }
62
+ },
63
+ [sdk, options?.queryCreator],
64
+ );
65
+ // ---------- internal methods ends ---------- //
66
+
67
+ // ---------- internal hooks ---------- //
68
+ useAsyncEffect(async () => {
69
+ setLoading(true);
70
+ await init(userId);
71
+ setLoading(false);
72
+ }, [init, userId]);
73
+
74
+ useChannelHandler(
75
+ sdk,
76
+ HOOK_NAME,
77
+ {
78
+ onChannelChanged: (channel) => updateChannels([channel], false),
79
+ onChannelFrozen: (channel) => updateChannels([channel], false),
80
+ onChannelUnfrozen: (channel) => updateChannels([channel], false),
81
+ onChannelMemberCountChanged: (channels) => updateChannels(channels, false),
82
+ onChannelDeleted: (url) => deleteChannels([url]),
83
+ onUserJoined: (channel) => updateChannels([channel], false),
84
+ onUserLeft: (channel, user) => {
85
+ const isMe = user.userId === userId;
86
+ if (isMe) deleteChannels([channel.url]);
87
+ else updateChannels([channel], false);
88
+ },
89
+ onUserBanned(channel, user) {
90
+ const isMe = user.userId === userId;
91
+ if (isMe) deleteChannels([channel.url]);
92
+ else updateChannels([channel], false);
93
+ },
94
+ },
95
+ [sdk, userId],
96
+ );
97
+ // ---------- internal hooks ends ---------- //
98
+
99
+ // ---------- returns methods ---------- //
100
+ const refresh = useCallback(async () => {
101
+ setRefreshing(true);
102
+ await init(userId);
103
+ setRefreshing(false);
104
+ }, [init, userId]);
105
+
106
+ const update = useCallback(
107
+ (channel: SendbirdGroupChannel) => {
108
+ if (deliveryReceiptEnabled) sdk.markAsDelivered(channel.url);
109
+ setGroupChannelMap((prev) => ({ ...prev, [channel.url]: channel }));
110
+ },
111
+ [sdk],
112
+ );
113
+
114
+ const next = useCallback(async () => {
115
+ if (queryRef.current?.hasNext) {
116
+ const channels = await queryRef.current.next();
117
+ setGroupChannelMap((prev) => ({ ...prev, ...arrayToMap(channels, 'url') }));
118
+ if (deliveryReceiptEnabled) channels.forEach((channel) => sdk.markAsDelivered(channel.url));
119
+ }
120
+ }, [sdk]);
121
+ // ---------- returns methods ends ---------- //
122
+
123
+ return { loading, groupChannels, update, refresh, refreshing, next };
124
+ };
@@ -0,0 +1,11 @@
1
+ import type { UseGroupChannelMessages } from '../../types';
2
+ import { useGroupChannelMessagesWithCollection } from './useGroupChannelMessagesWithCollection';
3
+ import { useGroupChannelMessagesWithQuery } from './useGroupChannelMessagesWithQuery';
4
+
5
+ export const useGroupChannelMessages: UseGroupChannelMessages = (sdk, channel, userId, options) => {
6
+ if (sdk.isCacheEnabled || options?.enableCollectionWithoutLocalCache) {
7
+ return useGroupChannelMessagesWithCollection(sdk, channel, userId, options);
8
+ } else {
9
+ return useGroupChannelMessagesWithQuery(sdk, channel, userId, options);
10
+ }
11
+ };