@sendbird/uikit-chat-hooks 2.3.0 → 2.4.0

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 (105) hide show
  1. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithCollection.js +2 -4
  2. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithCollection.js.map +1 -1
  3. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithQuery.js +2 -3
  4. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithQuery.js.map +1 -1
  5. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +7 -8
  6. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  7. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +8 -7
  8. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  9. package/lib/commonjs/channel/useOpenChannel.js +33 -0
  10. package/lib/commonjs/channel/useOpenChannel.js.map +1 -0
  11. package/lib/commonjs/channel/useOpenChannelList/index.js +15 -0
  12. package/lib/commonjs/channel/useOpenChannelList/index.js.map +1 -0
  13. package/lib/commonjs/channel/useOpenChannelList/reducer.js +149 -0
  14. package/lib/commonjs/channel/useOpenChannelList/reducer.js.map +1 -0
  15. package/lib/commonjs/channel/useOpenChannelList/useOpenChannelListWithQuery.js +119 -0
  16. package/lib/commonjs/channel/useOpenChannelList/useOpenChannelListWithQuery.js.map +1 -0
  17. package/lib/commonjs/channel/useOpenChannelMessages/index.js +15 -0
  18. package/lib/commonjs/channel/useOpenChannelMessages/index.js.map +1 -0
  19. package/lib/commonjs/channel/useOpenChannelMessages/reducer.js +154 -0
  20. package/lib/commonjs/channel/useOpenChannelMessages/reducer.js.map +1 -0
  21. package/lib/commonjs/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js +240 -0
  22. package/lib/commonjs/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js.map +1 -0
  23. package/lib/commonjs/common/useMessageOutgoingStatus.js +2 -4
  24. package/lib/commonjs/common/useMessageOutgoingStatus.js.map +1 -1
  25. package/lib/commonjs/common/useTotalUnreadChannelCount.js +2 -4
  26. package/lib/commonjs/common/useTotalUnreadChannelCount.js.map +1 -1
  27. package/lib/commonjs/common/useTotalUnreadMessageCount.js +2 -4
  28. package/lib/commonjs/common/useTotalUnreadMessageCount.js.map +1 -1
  29. package/lib/commonjs/common/useUserList.js +2 -0
  30. package/lib/commonjs/common/useUserList.js.map +1 -1
  31. package/lib/commonjs/handler/useChannelHandler.js +34 -4
  32. package/lib/commonjs/handler/useChannelHandler.js.map +1 -1
  33. package/lib/commonjs/index.js +24 -8
  34. package/lib/commonjs/index.js.map +1 -1
  35. package/lib/commonjs/types.js.map +1 -1
  36. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithCollection.js +3 -4
  37. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithCollection.js.map +1 -1
  38. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithQuery.js +3 -3
  39. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithQuery.js.map +1 -1
  40. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +8 -8
  41. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  42. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +9 -7
  43. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  44. package/lib/module/channel/useOpenChannel.js +22 -0
  45. package/lib/module/channel/useOpenChannel.js.map +1 -0
  46. package/lib/module/channel/useOpenChannelList/index.js +5 -0
  47. package/lib/module/channel/useOpenChannelList/index.js.map +1 -0
  48. package/lib/module/channel/useOpenChannelList/reducer.js +139 -0
  49. package/lib/module/channel/useOpenChannelList/reducer.js.map +1 -0
  50. package/lib/module/channel/useOpenChannelList/useOpenChannelListWithQuery.js +107 -0
  51. package/lib/module/channel/useOpenChannelList/useOpenChannelListWithQuery.js.map +1 -0
  52. package/lib/module/channel/useOpenChannelMessages/index.js +5 -0
  53. package/lib/module/channel/useOpenChannelMessages/index.js.map +1 -0
  54. package/lib/module/channel/useOpenChannelMessages/reducer.js +144 -0
  55. package/lib/module/channel/useOpenChannelMessages/reducer.js.map +1 -0
  56. package/lib/module/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js +228 -0
  57. package/lib/module/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js.map +1 -0
  58. package/lib/module/common/useMessageOutgoingStatus.js +3 -4
  59. package/lib/module/common/useMessageOutgoingStatus.js.map +1 -1
  60. package/lib/module/common/useTotalUnreadChannelCount.js +3 -5
  61. package/lib/module/common/useTotalUnreadChannelCount.js.map +1 -1
  62. package/lib/module/common/useTotalUnreadMessageCount.js +3 -4
  63. package/lib/module/common/useTotalUnreadMessageCount.js.map +1 -1
  64. package/lib/module/common/useUserList.js +2 -0
  65. package/lib/module/common/useUserList.js.map +1 -1
  66. package/lib/module/handler/useChannelHandler.js +34 -4
  67. package/lib/module/handler/useChannelHandler.js.map +1 -1
  68. package/lib/module/index.js +3 -1
  69. package/lib/module/index.js.map +1 -1
  70. package/lib/module/types.js.map +1 -1
  71. package/lib/typescript/src/channel/useOpenChannel.d.ts +6 -0
  72. package/lib/typescript/src/channel/useOpenChannelList/index.d.ts +2 -0
  73. package/lib/typescript/src/channel/useOpenChannelList/reducer.d.ts +13 -0
  74. package/lib/typescript/src/channel/useOpenChannelList/useOpenChannelListWithQuery.d.ts +2 -0
  75. package/lib/typescript/src/channel/useOpenChannelMessages/index.d.ts +2 -0
  76. package/lib/typescript/src/channel/useOpenChannelMessages/reducer.d.ts +15 -0
  77. package/lib/typescript/src/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.d.ts +2 -0
  78. package/lib/typescript/src/handler/useChannelHandler.d.ts +4 -1
  79. package/lib/typescript/src/index.d.ts +4 -2
  80. package/lib/typescript/src/types.d.ts +141 -3
  81. package/package.json +4 -4
  82. package/src/channel/useGroupChannelList/useGroupChannelListWithCollection.ts +3 -5
  83. package/src/channel/useGroupChannelList/useGroupChannelListWithQuery.ts +3 -4
  84. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.ts +8 -8
  85. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.ts +9 -6
  86. package/src/channel/useOpenChannel.ts +21 -0
  87. package/src/channel/useOpenChannelList/index.ts +6 -0
  88. package/src/channel/useOpenChannelList/reducer.ts +115 -0
  89. package/src/channel/useOpenChannelList/useOpenChannelListWithQuery.ts +112 -0
  90. package/src/channel/useOpenChannelMessages/index.ts +6 -0
  91. package/src/channel/useOpenChannelMessages/reducer.ts +125 -0
  92. package/src/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.ts +247 -0
  93. package/src/common/useMessageOutgoingStatus.ts +3 -5
  94. package/src/common/useTotalUnreadChannelCount.ts +3 -5
  95. package/src/common/useTotalUnreadMessageCount.ts +3 -4
  96. package/src/common/useUserList.ts +2 -0
  97. package/src/handler/useChannelHandler.ts +31 -5
  98. package/src/index.ts +8 -1
  99. package/src/types.ts +171 -2
  100. package/lib/commonjs/channel/useActiveGroupChannel.js +0 -22
  101. package/lib/commonjs/channel/useActiveGroupChannel.js.map +0 -1
  102. package/lib/module/channel/useActiveGroupChannel.js +0 -12
  103. package/lib/module/channel/useActiveGroupChannel.js.map +0 -1
  104. package/lib/typescript/src/channel/useActiveGroupChannel.d.ts +0 -5
  105. package/src/channel/useActiveGroupChannel.ts +0 -13
@@ -0,0 +1,125 @@
1
+ import { useReducer } from 'react';
2
+
3
+ import type { SendbirdBaseMessage, SendbirdFileMessage, SendbirdUserMessage } from '@sendbird/uikit-utils';
4
+ import { arrayToMapWithGetter, getMessageUniqId, isMyMessage, isNewMessage, useIIFE } from '@sendbird/uikit-utils';
5
+
6
+ import type { UseOpenChannelMessagesOptions } from '../../types';
7
+
8
+ type Action =
9
+ | {
10
+ type: 'update_loading' | 'update_refreshing';
11
+ value: { status: boolean };
12
+ }
13
+ | {
14
+ type: 'update_messages' | 'update_next_messages';
15
+ value: { messages: SendbirdBaseMessage[]; clearPrev: boolean; currentUserId?: string };
16
+ }
17
+ | {
18
+ type: 'delete_messages' | 'delete_next_messages';
19
+ value: { messageIds: number[]; reqIds: string[] };
20
+ };
21
+
22
+ type State = {
23
+ loading: boolean;
24
+ refreshing: boolean;
25
+ messageMap: Record<string, SendbirdBaseMessage>;
26
+ nextMessageMap: Record<string, SendbirdBaseMessage>;
27
+ };
28
+
29
+ const defaultReducer = ({ ...draft }: State, action: Action) => {
30
+ switch (action.type) {
31
+ case 'update_refreshing':
32
+ case 'update_loading': {
33
+ const key = action.type === 'update_loading' ? 'loading' : 'refreshing';
34
+ draft[key] = action.value.status;
35
+
36
+ return draft;
37
+ }
38
+ case 'update_messages':
39
+ case 'update_next_messages': {
40
+ const key = action.type === 'update_messages' ? 'messageMap' : 'nextMessageMap';
41
+ const receivedMessagesAsMap = arrayToMapWithGetter(action.value.messages, getMessageUniqId);
42
+ if (action.value.clearPrev) {
43
+ draft[key] = receivedMessagesAsMap;
44
+ } else {
45
+ draft[key] = { ...draft[key], ...receivedMessagesAsMap };
46
+
47
+ // NOTE: Replace pending message to succeeded message
48
+ action.value.messages
49
+ .filter((m): m is SendbirdUserMessage | SendbirdFileMessage => {
50
+ return (
51
+ (m.isFileMessage() || m.isUserMessage()) &&
52
+ Boolean(draft[key][m.reqId]) &&
53
+ m.sendingStatus === 'succeeded' &&
54
+ isMyMessage(m, action.value.currentUserId)
55
+ );
56
+ })
57
+ .forEach((m) => delete draft[key][m.reqId]);
58
+ }
59
+
60
+ return draft;
61
+ }
62
+ case 'delete_messages':
63
+ case 'delete_next_messages': {
64
+ const key = action.type === 'delete_messages' ? 'messageMap' : 'nextMessageMap';
65
+ draft[key] = { ...draft[key] };
66
+ action.value.messageIds.forEach((msgId) => delete draft[key][msgId]);
67
+ action.value.reqIds.forEach((reqId) => delete draft[key][reqId]);
68
+
69
+ return draft;
70
+ }
71
+ }
72
+ };
73
+
74
+ export const useOpenChannelMessagesReducer = (
75
+ userId?: string,
76
+ sortComparator?: UseOpenChannelMessagesOptions['sortComparator'],
77
+ ) => {
78
+ const [{ loading, refreshing, messageMap, nextMessageMap }, dispatch] = useReducer(defaultReducer, {
79
+ loading: true,
80
+ refreshing: false,
81
+ messageMap: {},
82
+ nextMessageMap: {},
83
+ });
84
+
85
+ const updateMessages = (messages: SendbirdBaseMessage[], clearPrev: boolean, currentUserId?: string) => {
86
+ dispatch({ type: 'update_messages', value: { messages, clearPrev, currentUserId } });
87
+ };
88
+ const deleteMessages = (messageIds: number[], reqIds: string[]) => {
89
+ dispatch({ type: 'delete_messages', value: { messageIds, reqIds } });
90
+ };
91
+ const updateNextMessages = (messages: SendbirdBaseMessage[], clearPrev: boolean, currentUserId?: string) => {
92
+ dispatch({ type: 'update_next_messages', value: { messages, clearPrev, currentUserId } });
93
+ };
94
+ const deleteNextMessages = (messageIds: number[], reqIds: string[]) => {
95
+ dispatch({ type: 'delete_next_messages', value: { messageIds, reqIds } });
96
+ };
97
+ const updateLoading = (status: boolean) => {
98
+ dispatch({ type: 'update_loading', value: { status } });
99
+ };
100
+ const updateRefreshing = (status: boolean) => {
101
+ dispatch({ type: 'update_refreshing', value: { status } });
102
+ };
103
+
104
+ const messages = useIIFE(() => {
105
+ if (sortComparator) return Object.values(messageMap).sort(sortComparator);
106
+ return Object.values(messageMap);
107
+ });
108
+ const nextMessages = Object.values(nextMessageMap);
109
+ const newMessagesFromMembers = nextMessages.filter((msg) => isNewMessage(msg, userId));
110
+
111
+ return {
112
+ updateLoading,
113
+ updateRefreshing,
114
+ updateMessages,
115
+ updateNextMessages,
116
+ deleteMessages,
117
+ deleteNextMessages,
118
+
119
+ loading,
120
+ refreshing,
121
+ messages,
122
+ nextMessages,
123
+ newMessagesFromMembers,
124
+ };
125
+ };
@@ -0,0 +1,247 @@
1
+ import { useRef } from 'react';
2
+
3
+ import type { SendbirdBaseChannel, SendbirdOpenChannel, SendbirdPreviousMessageListQuery } from '@sendbird/uikit-utils';
4
+ import {
5
+ NOOP,
6
+ isDifferentChannel,
7
+ useAsyncEffect,
8
+ useForceUpdate,
9
+ useFreshCallback,
10
+ useUniqHandlerId,
11
+ } from '@sendbird/uikit-utils';
12
+
13
+ import { useChannelHandler } from '../../handler/useChannelHandler';
14
+ import type { UseOpenChannelMessages, UseOpenChannelMessagesOptions } from '../../types';
15
+ import { useOpenChannelMessagesReducer } from './reducer';
16
+
17
+ const createMessageQuery = (channel: SendbirdOpenChannel, creator?: UseOpenChannelMessagesOptions['queryCreator']) => {
18
+ if (creator) return creator();
19
+ return channel.createPreviousMessageListQuery({
20
+ limit: 100,
21
+ reverse: true,
22
+ });
23
+ };
24
+
25
+ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, channel, userId, options) => {
26
+ const queryRef = useRef<SendbirdPreviousMessageListQuery>();
27
+ const forceUpdate = useForceUpdate();
28
+ const handlerId = useUniqHandlerId('useOpenChannelMessagesWithQuery');
29
+
30
+ const {
31
+ loading,
32
+ refreshing,
33
+ messages,
34
+ nextMessages,
35
+ newMessagesFromMembers,
36
+ updateMessages,
37
+ updateNextMessages,
38
+ deleteNextMessages,
39
+ deleteMessages,
40
+ updateLoading,
41
+ updateRefreshing,
42
+ } = useOpenChannelMessagesReducer(userId, options?.sortComparator);
43
+
44
+ const init = useFreshCallback(async (uid?: string) => {
45
+ if (uid) {
46
+ queryRef.current = createMessageQuery(channel, options?.queryCreator);
47
+ if (queryRef.current?.hasNext) {
48
+ const list = await queryRef.current?.load();
49
+
50
+ updateMessages(list, true, sdk.currentUser.userId);
51
+ }
52
+ updateNextMessages([], true, sdk.currentUser.userId);
53
+ }
54
+ });
55
+
56
+ const channelUpdater = (channel: SendbirdBaseChannel) => {
57
+ if (channel.isOpenChannel() && !isDifferentChannel(channel, channel)) {
58
+ forceUpdate();
59
+ }
60
+ };
61
+
62
+ useChannelHandler(
63
+ sdk,
64
+ handlerId,
65
+ {
66
+ // Messages
67
+ onMessageReceived(eventChannel, message) {
68
+ if (isDifferentChannel(channel, eventChannel)) return;
69
+ updateNextMessages([message], false, sdk.currentUser.userId);
70
+ },
71
+ onMessageUpdated(eventChannel, message) {
72
+ if (isDifferentChannel(channel, eventChannel)) return;
73
+ updateMessages([message], false, sdk.currentUser.userId);
74
+ },
75
+ onMessageDeleted(eventChannel, messageId) {
76
+ if (isDifferentChannel(channel, eventChannel)) return;
77
+ deleteMessages([messageId], []);
78
+ deleteNextMessages([messageId], []);
79
+ },
80
+ // Channels
81
+ onChannelChanged: channelUpdater,
82
+ onChannelFrozen: channelUpdater,
83
+ onChannelUnfrozen: channelUpdater,
84
+ onChannelParticipantCountChanged(eventChannel) {
85
+ if (isDifferentChannel(channel, eventChannel)) return;
86
+ channelUpdater(eventChannel);
87
+ },
88
+ onChannelDeleted(channelUrl, type) {
89
+ if (channel.url === channelUrl && type === 'open') {
90
+ options?.onChannelDeleted?.();
91
+ }
92
+ },
93
+ // Users
94
+ onOperatorUpdated: channelUpdater,
95
+ onUserUnbanned: channelUpdater,
96
+ onUserMuted: channelUpdater,
97
+ onUserUnmuted: channelUpdater,
98
+ onUserBanned(eventChannel, bannedUser) {
99
+ if (isDifferentChannel(channel, eventChannel)) return;
100
+
101
+ if (bannedUser.userId === sdk.currentUser.userId) {
102
+ options?.onChannelDeleted?.();
103
+ } else {
104
+ channelUpdater(eventChannel);
105
+ }
106
+ },
107
+ },
108
+ 'open',
109
+ );
110
+
111
+ useAsyncEffect(async () => {
112
+ updateLoading(true);
113
+
114
+ try {
115
+ await channel.enter();
116
+ await init(userId);
117
+ } catch (error) {
118
+ options?.onError?.(error);
119
+ options?.onChannelDeleted?.();
120
+ } finally {
121
+ updateLoading(false);
122
+ }
123
+
124
+ return () => {
125
+ channel.exit().catch(NOOP);
126
+ };
127
+ }, [init, userId]);
128
+
129
+ const refresh: ReturnType<UseOpenChannelMessages>['refresh'] = useFreshCallback(async () => {
130
+ updateRefreshing(true);
131
+ await init(userId);
132
+ updateRefreshing(false);
133
+ });
134
+
135
+ const prev: ReturnType<UseOpenChannelMessages>['prev'] = useFreshCallback(async () => {
136
+ if (queryRef.current && queryRef.current?.hasNext) {
137
+ const list = await queryRef.current?.load();
138
+ updateMessages(list, false, sdk.currentUser.userId);
139
+ }
140
+ });
141
+
142
+ const next: ReturnType<UseOpenChannelMessages>['next'] = useFreshCallback(async () => {
143
+ if (nextMessages.length > 0) {
144
+ updateMessages(nextMessages, false, sdk.currentUser.userId);
145
+ updateNextMessages([], true, sdk.currentUser.userId);
146
+ }
147
+ });
148
+
149
+ const sendUserMessage: ReturnType<UseOpenChannelMessages>['sendUserMessage'] = useFreshCallback(
150
+ (params, onPending) => {
151
+ return new Promise((resolve, reject) => {
152
+ channel
153
+ .sendUserMessage(params)
154
+ .onPending((pendingMessage) => {
155
+ if (pendingMessage.isUserMessage()) {
156
+ updateNextMessages([pendingMessage], false, sdk.currentUser.userId);
157
+ onPending?.(pendingMessage);
158
+ }
159
+ })
160
+ .onSucceeded((sentMessage) => {
161
+ if (sentMessage.isUserMessage()) {
162
+ updateNextMessages([sentMessage], false, sdk.currentUser.userId);
163
+ resolve(sentMessage);
164
+ }
165
+ })
166
+ .onFailed((err, sentMessage) => {
167
+ updateNextMessages([sentMessage], false, sdk.currentUser.userId);
168
+ reject(err);
169
+ });
170
+ });
171
+ },
172
+ );
173
+
174
+ const sendFileMessage: ReturnType<UseOpenChannelMessages>['sendFileMessage'] = useFreshCallback(
175
+ (params, onPending) => {
176
+ return new Promise((resolve, reject) => {
177
+ channel
178
+ .sendFileMessage(params)
179
+ .onPending((pendingMessage) => {
180
+ if (pendingMessage.isFileMessage()) {
181
+ updateNextMessages([pendingMessage], false, sdk.currentUser.userId);
182
+ onPending?.(pendingMessage);
183
+ }
184
+ })
185
+ .onSucceeded((sentMessage) => {
186
+ if (sentMessage.isFileMessage()) {
187
+ updateNextMessages([sentMessage], false, sdk.currentUser.userId);
188
+ resolve(sentMessage);
189
+ }
190
+ })
191
+ .onFailed((err, sentMessage) => {
192
+ updateNextMessages([sentMessage], false, sdk.currentUser.userId);
193
+ reject(err);
194
+ });
195
+ });
196
+ },
197
+ );
198
+
199
+ const updateUserMessage: ReturnType<UseOpenChannelMessages>['updateUserMessage'] = useFreshCallback(
200
+ async (messageId, params) => {
201
+ const updatedMessage = await channel.updateUserMessage(messageId, params);
202
+ updateMessages([updatedMessage], false, sdk.currentUser.userId);
203
+ return updatedMessage;
204
+ },
205
+ );
206
+ const updateFileMessage: ReturnType<UseOpenChannelMessages>['updateFileMessage'] = useFreshCallback(
207
+ async (messageId, params) => {
208
+ const updatedMessage = await channel.updateFileMessage(messageId, params);
209
+ updateMessages([updatedMessage], false, sdk.currentUser.userId);
210
+ return updatedMessage;
211
+ },
212
+ );
213
+ const resendMessage: ReturnType<UseOpenChannelMessages>['resendMessage'] = useFreshCallback(async (failedMessage) => {
214
+ const message = await (() => {
215
+ if (failedMessage.isUserMessage()) return channel.resendUserMessage(failedMessage);
216
+ if (failedMessage.isFileMessage()) return channel.resendFileMessage(failedMessage);
217
+ return null;
218
+ })();
219
+
220
+ if (message) updateNextMessages([message], false, sdk.currentUser.userId);
221
+ });
222
+ const deleteMessage: ReturnType<UseOpenChannelMessages>['deleteMessage'] = useFreshCallback(async (message) => {
223
+ if (message.sendingStatus === 'succeeded') {
224
+ if (message.isUserMessage()) await channel.deleteMessage(message);
225
+ if (message.isFileMessage()) await channel.deleteMessage(message);
226
+ } else {
227
+ deleteMessages([message.messageId], [message.reqId]);
228
+ }
229
+ });
230
+
231
+ return {
232
+ loading,
233
+ refreshing,
234
+ refresh,
235
+ messages,
236
+ nextMessages,
237
+ newMessagesFromMembers,
238
+ next,
239
+ prev,
240
+ sendUserMessage,
241
+ sendFileMessage,
242
+ updateUserMessage,
243
+ updateFileMessage,
244
+ resendMessage,
245
+ deleteMessage,
246
+ };
247
+ };
@@ -1,11 +1,9 @@
1
1
  import type { SendbirdChatSDK, SendbirdGroupChannel, SendbirdMessage } from '@sendbird/uikit-utils';
2
- import { isDifferentChannel, isMyMessage, useForceUpdate, useUniqId } from '@sendbird/uikit-utils';
2
+ import { isDifferentChannel, isMyMessage, useForceUpdate, useUniqHandlerId } from '@sendbird/uikit-utils';
3
3
 
4
4
  import { useChannelHandler } from '../handler/useChannelHandler';
5
5
  import { useAppFeatures } from './useAppFeatures';
6
6
 
7
- const HOOK_NAME = 'useMessageOutgoingStatus';
8
-
9
7
  export type SBUOutgoingStatus = 'NONE' | 'PENDING' | 'FAILED' | 'UNDELIVERED' | 'DELIVERED' | 'UNREAD' | 'READ';
10
8
 
11
9
  export const useMessageOutgoingStatus = (
@@ -16,9 +14,9 @@ export const useMessageOutgoingStatus = (
16
14
  const features = useAppFeatures(sdk);
17
15
  const forceUpdate = useForceUpdate();
18
16
  const currentUser = sdk.currentUser;
17
+ const handlerId = useUniqHandlerId('useMessageOutgoingStatus');
19
18
 
20
- const uniqId = useUniqId(HOOK_NAME);
21
- useChannelHandler(sdk, `${HOOK_NAME}_${uniqId}`, {
19
+ useChannelHandler(sdk, handlerId, {
22
20
  onUndeliveredMemberStatusUpdated(eventChannel) {
23
21
  if (isDifferentChannel(channel, eventChannel)) return;
24
22
  if (!isMyMessage(message, currentUser?.userId)) return;
@@ -1,24 +1,22 @@
1
1
  import { useState } from 'react';
2
2
 
3
3
  import type { SendbirdChatSDK } from '@sendbird/uikit-utils';
4
- import { truncatedCount, useAsyncEffect } from '@sendbird/uikit-utils';
5
- import { useUniqId } from '@sendbird/uikit-utils';
4
+ import { truncatedCount, useAsyncEffect, useUniqHandlerId } from '@sendbird/uikit-utils';
6
5
 
7
6
  import { useUserEventHandler } from '../handler/useUserEventHandler';
8
7
 
9
8
  type Params = {
10
9
  maxCount?: number;
11
10
  };
12
- const HOOK_NAME = 'useTotalUnreadChannelCount';
13
11
  export const useTotalUnreadChannelCount = (sdk: SendbirdChatSDK, params?: Params) => {
14
- const id = useUniqId(HOOK_NAME);
12
+ const handlerId = useUniqHandlerId('useTotalUnreadChannelCount');
15
13
  const [unreadChannelCount, setUnreadChannelCount] = useState(0);
16
14
 
17
15
  useAsyncEffect(async () => {
18
16
  setUnreadChannelCount(await sdk.groupChannel.getTotalUnreadChannelCount());
19
17
  }, [sdk]);
20
18
 
21
- useUserEventHandler(sdk, HOOK_NAME + id, {
19
+ useUserEventHandler(sdk, handlerId, {
22
20
  onTotalUnreadMessageCountUpdated: async () => {
23
21
  setUnreadChannelCount(await sdk.groupChannel.getTotalUnreadChannelCount());
24
22
  },
@@ -2,7 +2,7 @@ import { useState } from 'react';
2
2
 
3
3
  import { SuperChannelFilter, TotalUnreadMessageCountParams } from '@sendbird/chat/groupChannel';
4
4
  import type { SendbirdChatSDK } from '@sendbird/uikit-utils';
5
- import { truncatedCount, useAsyncEffect, useUniqId } from '@sendbird/uikit-utils';
5
+ import { truncatedCount, useAsyncEffect, useUniqHandlerId } from '@sendbird/uikit-utils';
6
6
 
7
7
  import { useUserEventHandler } from '../handler/useUserEventHandler';
8
8
 
@@ -11,9 +11,8 @@ type Options = {
11
11
  maxCount?: number;
12
12
  };
13
13
 
14
- const HOOK_NAME = 'useTotalUnreadMessageCount';
15
14
  export const useTotalUnreadMessageCount = (sdk: SendbirdChatSDK, options?: Options) => {
16
- const id = useUniqId(HOOK_NAME);
15
+ const handlerId = useUniqHandlerId('useTotalUnreadMessageCount');
17
16
  const [unreadMessageCount, setUnreadMessageCount] = useState(0);
18
17
 
19
18
  useAsyncEffect(async () => {
@@ -24,7 +23,7 @@ export const useTotalUnreadMessageCount = (sdk: SendbirdChatSDK, options?: Optio
24
23
  setUnreadMessageCount(unreadCount);
25
24
  }, [sdk, options?.params?.superChannelFilter, options?.params?.channelCustomTypesFilter]);
26
25
 
27
- useUserEventHandler(sdk, `${HOOK_NAME}_${id}`, {
26
+ useUserEventHandler(sdk, handlerId, {
28
27
  onTotalUnreadMessageCountUpdated: (totalCount: number) => setUnreadMessageCount(totalCount),
29
28
  });
30
29
 
@@ -99,6 +99,7 @@ export const useUserList = <
99
99
  await init();
100
100
  } catch (e) {
101
101
  setError(e);
102
+ setUsers([]);
102
103
  } finally {
103
104
  setLoading(false);
104
105
  }
@@ -111,6 +112,7 @@ export const useUserList = <
111
112
  await init();
112
113
  } catch (e) {
113
114
  setError(e);
115
+ setUsers([]);
114
116
  } finally {
115
117
  setRefreshing(false);
116
118
  }
@@ -1,12 +1,27 @@
1
1
  import { useEffect, useLayoutEffect, useRef } from 'react';
2
2
 
3
3
  import { GroupChannelHandler } from '@sendbird/chat/groupChannel';
4
+ import { OpenChannelHandler } from '@sendbird/chat/openChannel';
4
5
  import { Logger, SendbirdChatSDK } from '@sendbird/uikit-utils';
5
6
 
6
- export const useChannelHandler = (
7
+ type ChannelType = 'open' | 'group';
8
+
9
+ function getChannelHandler(type: ChannelType) {
10
+ switch (type) {
11
+ case 'open': {
12
+ return new OpenChannelHandler();
13
+ }
14
+ case 'group':
15
+ default: {
16
+ return new GroupChannelHandler();
17
+ }
18
+ }
19
+ }
20
+ export const useChannelHandler = <T extends ChannelType = 'group'>(
7
21
  sdk: SendbirdChatSDK,
8
22
  handlerId: string,
9
- hookHandler: Partial<GroupChannelHandler>,
23
+ hookHandler: Partial<T extends 'group' ? GroupChannelHandler : OpenChannelHandler>,
24
+ type = 'group' as T,
10
25
  ) => {
11
26
  const handlerRef = useRef(hookHandler);
12
27
  useLayoutEffect(() => {
@@ -16,7 +31,7 @@ export const useChannelHandler = (
16
31
  useEffect(() => {
17
32
  Logger.debug('[useChannelHandler] hook called by', handlerId);
18
33
 
19
- const handler = new GroupChannelHandler();
34
+ const handler = getChannelHandler(type);
20
35
  const handlerKeys = Object.keys(handler) as (keyof typeof handler)[];
21
36
  handlerKeys.forEach((key) => {
22
37
  handler[key] = (...args: unknown[]) => {
@@ -25,7 +40,18 @@ export const useChannelHandler = (
25
40
  };
26
41
  });
27
42
 
28
- sdk.groupChannel.addGroupChannelHandler(handlerId, handler);
29
- return () => sdk.groupChannel.removeGroupChannelHandler(handlerId);
43
+ if (type === 'group') {
44
+ sdk.groupChannel.addGroupChannelHandler(handlerId, handler);
45
+ } else if (type === 'open') {
46
+ sdk.openChannel.addOpenChannelHandler(handlerId, handler);
47
+ }
48
+
49
+ return () => {
50
+ if (type === 'group') {
51
+ sdk.groupChannel.removeGroupChannelHandler(handlerId);
52
+ } else if (type === 'open') {
53
+ sdk.openChannel.removeOpenChannelHandler(handlerId);
54
+ }
55
+ };
30
56
  }, [sdk, handlerId]);
31
57
  };
package/src/index.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  export { useGroupChannelList } from './channel/useGroupChannelList';
2
2
  export { useGroupChannelMessages } from './channel/useGroupChannelMessages';
3
- export { useActiveGroupChannel } from './channel/useActiveGroupChannel';
4
3
  export { useGroupChannel } from './channel/useGroupChannel';
5
4
 
5
+ export { useOpenChannelList } from './channel/useOpenChannelList';
6
+ export { useOpenChannelMessages } from './channel/useOpenChannelMessages';
7
+ export { useOpenChannel } from './channel/useOpenChannel';
8
+
6
9
  export { useAppFeatures } from './common/useAppFeatures';
7
10
  export { useMessageOutgoingStatus } from './common/useMessageOutgoingStatus';
8
11
  export { usePushTrigger } from './common/usePushTrigger';
@@ -25,4 +28,8 @@ export type {
25
28
  UseUserListReturn,
26
29
  CustomQueryInterface,
27
30
  CustomBidirectionalQueryInterface,
31
+ UseOpenChannelMessagesOptions,
32
+ UseOpenChannelListOptions,
33
+ UseOpenChannelList,
34
+ UseOpenChannelMessages,
28
35
  } from './types';