@sendbird/uikit-chat-hooks 2.4.2 → 2.5.0-rc.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 (46) hide show
  1. package/lib/commonjs/channel/{useGroupChannelMessages/reducer.js → useChannelMessagesReducer.js} +39 -30
  2. package/lib/commonjs/channel/useChannelMessagesReducer.js.map +1 -0
  3. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +169 -99
  4. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  5. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +56 -25
  6. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  7. package/lib/commonjs/channel/useOpenChannelList/useOpenChannelListWithQuery.js +0 -4
  8. package/lib/commonjs/channel/useOpenChannelList/useOpenChannelListWithQuery.js.map +1 -1
  9. package/lib/commonjs/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js +128 -28
  10. package/lib/commonjs/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js.map +1 -1
  11. package/lib/commonjs/common/useUserList.js +2 -2
  12. package/lib/commonjs/common/useUserList.js.map +1 -1
  13. package/lib/commonjs/types.js.map +1 -1
  14. package/lib/module/channel/{useGroupChannelMessages/reducer.js → useChannelMessagesReducer.js} +38 -29
  15. package/lib/module/channel/useChannelMessagesReducer.js.map +1 -0
  16. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +170 -100
  17. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  18. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +57 -26
  19. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  20. package/lib/module/channel/useOpenChannelList/useOpenChannelListWithQuery.js +0 -4
  21. package/lib/module/channel/useOpenChannelList/useOpenChannelListWithQuery.js.map +1 -1
  22. package/lib/module/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js +129 -29
  23. package/lib/module/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js.map +1 -1
  24. package/lib/module/common/useUserList.js +2 -2
  25. package/lib/module/common/useUserList.js.map +1 -1
  26. package/lib/module/types.js.map +1 -1
  27. package/lib/typescript/src/channel/useChannelMessagesReducer.d.ts +18 -0
  28. package/lib/typescript/src/types.d.ts +51 -20
  29. package/package.json +4 -5
  30. package/src/channel/useChannelMessagesReducer.ts +143 -0
  31. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.ts +168 -96
  32. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.ts +62 -25
  33. package/src/channel/useOpenChannelList/useOpenChannelListWithQuery.ts +0 -4
  34. package/src/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.ts +142 -25
  35. package/src/common/useUserList.ts +2 -2
  36. package/src/types.ts +58 -20
  37. package/lib/commonjs/channel/useGroupChannelMessages/reducer.js.map +0 -1
  38. package/lib/commonjs/channel/useOpenChannelMessages/reducer.js +0 -144
  39. package/lib/commonjs/channel/useOpenChannelMessages/reducer.js.map +0 -1
  40. package/lib/module/channel/useGroupChannelMessages/reducer.js.map +0 -1
  41. package/lib/module/channel/useOpenChannelMessages/reducer.js +0 -137
  42. package/lib/module/channel/useOpenChannelMessages/reducer.js.map +0 -1
  43. package/lib/typescript/src/channel/useGroupChannelMessages/reducer.d.ts +0 -15
  44. package/lib/typescript/src/channel/useOpenChannelMessages/reducer.d.ts +0 -15
  45. package/src/channel/useGroupChannelMessages/reducer.ts +0 -126
  46. package/src/channel/useOpenChannelMessages/reducer.ts +0 -126
@@ -49,9 +49,9 @@ export type UseGroupChannelListOptions = {
49
49
  /**
50
50
  * @interface UseGroupChannelMessages
51
51
  * @description interface for group channel messages hook
52
- * - Receive new messages from other users -> append to state(nextMessages)
52
+ * - Receive new messages from other users & should count new messages -> append to state(newMessages)
53
53
  * - onTopReached -> prev() -> fetch prev messages and append to state(messages)
54
- * - onBottomReached -> next() -> nextMessages append to state(messages)
54
+ * - onBottomReached -> next() -> fetch next messages and append to state(messages)
55
55
  * */
56
56
  export interface UseGroupChannelMessages {
57
57
  (sdk: SendbirdChatSDK, channel: SendbirdGroupChannel, userId?: string, options?: UseGroupChannelMessagesOptions): {
@@ -81,24 +81,35 @@ export interface UseGroupChannelMessages {
81
81
  * */
82
82
  prev: () => Promise<void>;
83
83
  /**
84
- * Get messages, this state is for temporary data before render
85
- * For example, if a user receives a new messages while searching for an old message
86
- * for this case, new messages will be included here.
84
+ * Check if there are more prev messages to fetch
85
+ * @return {boolean}
87
86
  * */
88
- nextMessages: SendbirdMessage[];
87
+ hasPrev: () => boolean;
88
+ /**
89
+ * Fetch next messages to state
90
+ * @return {Promise<void>}
91
+ * */
92
+ next: () => Promise<void>;
93
+ /**
94
+ * Check if there are more next messages to fetch
95
+ * @return {boolean}
96
+ * */
97
+ hasNext: () => boolean;
89
98
  /**
90
- * Get new messages from nextMessages
91
99
  * A new message means a message that meets the below conditions
92
100
  * - Not admin message
93
101
  * - Not updated message
94
102
  * - Not current user's message
95
103
  * */
96
- newMessagesFromMembers: SendbirdMessage[];
104
+ newMessages: SendbirdMessage[];
97
105
  /**
98
- * Fetch next messages to state
99
- * @return {Promise<void>}
106
+ * reset message list with starting point
100
107
  * */
101
- next: () => Promise<void>;
108
+ resetWithStartingPoint: (startingPoint: number, callback?: () => void) => void;
109
+ /**
110
+ * Reset new messages
111
+ * */
112
+ resetNewMessages: () => void;
102
113
  /**
103
114
  * Send file message
104
115
  * @param params file message params
@@ -139,14 +150,21 @@ export interface UseGroupChannelMessages {
139
150
  * @return {Promise<void>}
140
151
  * */
141
152
  deleteMessage: (message: SendbirdFileMessage | SendbirdUserMessage) => Promise<void>;
153
+ /** @deprecated Please use `newMessages` instead **/
154
+ newMessagesFromMembers: SendbirdMessage[];
155
+ /** @deprecated Please use `newMessages` instead **/
156
+ nextMessages: SendbirdMessage[];
142
157
  };
143
158
  }
144
159
  export type UseGroupChannelMessagesOptions = {
145
160
  sortComparator?: (a: SendbirdMessage, b: SendbirdMessage) => number;
146
161
  queryCreator?: () => SendbirdPreviousMessageListQuery;
147
- collectionCreator?: () => SendbirdMessageCollection;
162
+ collectionCreator?: (options?: Pick<UseGroupChannelMessagesOptions, 'startingPoint'>) => SendbirdMessageCollection;
148
163
  enableCollectionWithoutLocalCache?: boolean;
149
164
  onChannelDeleted?: () => void;
165
+ shouldCountNewMessages?: () => boolean;
166
+ startingPoint?: number;
167
+ onMessagesReceived?: (messages: SendbirdMessage[]) => void;
150
168
  };
151
169
  /**
152
170
  * @interface UseOpenChannelList
@@ -188,9 +206,9 @@ export type UseOpenChannelListOptions = {
188
206
  /**
189
207
  * @interface UseOpenChannelMessages
190
208
  * @description interface for open channel messages hook
191
- * - Receive new messages from other users -> append to state(nextMessages)
209
+ * - Receive new messages from other users & should count new messages -> append to state(newMessages)
192
210
  * - onTopReached -> prev() -> fetch prev messages and append to state(messages)
193
- * - onBottomReached -> next() -> nextMessages append to state(messages)
211
+ * - onBottomReached -> noop
194
212
  * */
195
213
  export interface UseOpenChannelMessages {
196
214
  (sdk: SendbirdChatSDK, channel: SendbirdOpenChannel, userId?: string, options?: UseOpenChannelMessagesOptions): {
@@ -220,24 +238,31 @@ export interface UseOpenChannelMessages {
220
238
  * */
221
239
  prev: () => Promise<void>;
222
240
  /**
223
- * Get messages, this state is for temporary data before render
224
- * For example, if a user receives a new messages while searching for an old message
225
- * for this case, new messages will be included here.
241
+ * Check if there are more prev messages to fetch
242
+ * @return {boolean}
226
243
  * */
227
- nextMessages: SendbirdMessage[];
244
+ hasPrev: () => boolean;
228
245
  /**
229
- * Get new messages from nextMessages
230
246
  * A new message means a message that meets the below conditions
231
247
  * - Not admin message
232
248
  * - Not updated message
233
249
  * - Not current user's message
234
250
  * */
235
- newMessagesFromMembers: SendbirdMessage[];
251
+ newMessages: SendbirdMessage[];
252
+ /**
253
+ * Reset new messages
254
+ * */
255
+ resetNewMessages: () => void;
236
256
  /**
237
257
  * Fetch next messages to state
238
258
  * @return {Promise<void>}
239
259
  * */
240
260
  next: () => Promise<void>;
261
+ /**
262
+ * Check if there are more next messages to fetch
263
+ * @return {boolean}
264
+ * */
265
+ hasNext: () => boolean;
241
266
  /**
242
267
  * Send file message
243
268
  * @param params file message params
@@ -278,6 +303,10 @@ export interface UseOpenChannelMessages {
278
303
  * @return {Promise<void>}
279
304
  * */
280
305
  deleteMessage: (message: SendbirdFileMessage | SendbirdUserMessage) => Promise<void>;
306
+ /** @deprecated Please use `newMessages` instead **/
307
+ newMessagesFromMembers: SendbirdMessage[];
308
+ /** @deprecated Please use `newMessages` instead **/
309
+ nextMessages: SendbirdMessage[];
281
310
  };
282
311
  }
283
312
  export type UseOpenChannelMessagesOptions = {
@@ -285,6 +314,8 @@ export type UseOpenChannelMessagesOptions = {
285
314
  queryCreator?: () => SendbirdPreviousMessageListQuery;
286
315
  onChannelDeleted?: () => void;
287
316
  onError?: (error?: unknown) => void;
317
+ shouldCountNewMessages?: () => boolean;
318
+ onMessagesReceived?: (messages: SendbirdMessage[]) => void;
288
319
  };
289
320
  /**
290
321
  * @interface UseUserListReturn
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendbird/uikit-chat-hooks",
3
- "version": "2.4.2",
3
+ "version": "2.5.0-rc.0",
4
4
  "description": "A set of React hooks for integrating Sendbird chat functionality into your React app.",
5
5
  "keywords": [
6
6
  "sendbird",
@@ -43,10 +43,10 @@
43
43
  "access": "public"
44
44
  },
45
45
  "dependencies": {
46
- "@sendbird/uikit-utils": "2.4.2"
46
+ "@sendbird/uikit-utils": "2.5.0-rc.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@sendbird/uikit-testing-tools": "2.4.2",
49
+ "@sendbird/uikit-testing-tools": "2.5.0-rc.0",
50
50
  "@types/react": "*",
51
51
  "react": "17.0.2",
52
52
  "react-native-builder-bob": "^0.18.0",
@@ -74,6 +74,5 @@
74
74
  "entryPoint": "./src/index.ts",
75
75
  "readmeFile": "./README.md",
76
76
  "displayName": "@sendbird/uikit-chat-hooks"
77
- },
78
- "gitHead": "ae9e60edc60cdd4f6e9b0e4019e84584e807bc2c"
77
+ }
79
78
  }
@@ -0,0 +1,143 @@
1
+ import { useReducer } from 'react';
2
+
3
+ import type { SendbirdBaseMessage } from '@sendbird/uikit-utils';
4
+ import {
5
+ SendbirdMessage,
6
+ arrayToMapWithGetter,
7
+ getMessageUniqId,
8
+ isNewMessage,
9
+ isSendableMessage,
10
+ useIIFE,
11
+ } from '@sendbird/uikit-utils';
12
+
13
+ type Options = {
14
+ sortComparator?: (a: SendbirdMessage, b: SendbirdMessage) => number;
15
+ };
16
+
17
+ type Action =
18
+ | {
19
+ type: 'update_loading' | 'update_refreshing';
20
+ value: { status: boolean };
21
+ }
22
+ | {
23
+ type: 'update_messages' | 'update_new_messages';
24
+ value: { messages: SendbirdBaseMessage[]; clearBeforeAction: boolean; currentUserId?: string };
25
+ }
26
+ | {
27
+ type: 'delete_messages' | 'delete_new_messages';
28
+ value: { messageIds: number[]; reqIds: string[] };
29
+ };
30
+
31
+ type State = {
32
+ loading: boolean;
33
+ refreshing: boolean;
34
+ messageMap: Record<string, SendbirdBaseMessage>;
35
+ newMessageMap: Record<string, SendbirdBaseMessage>;
36
+ };
37
+
38
+ const defaultReducer = ({ ...draft }: State, action: Action) => {
39
+ switch (action.type) {
40
+ case 'update_refreshing': {
41
+ draft['refreshing'] = action.value.status;
42
+ return draft;
43
+ }
44
+ case 'update_loading': {
45
+ draft['loading'] = action.value.status;
46
+ return draft;
47
+ }
48
+ case 'update_messages': {
49
+ if (action.value.clearBeforeAction) {
50
+ draft['messageMap'] = arrayToMapWithGetter(action.value.messages, getMessageUniqId);
51
+ } else {
52
+ // Remove existing messages before update for prevent duplicate display
53
+ const messageKeys = action.value.messages
54
+ .map((it) => (isSendableMessage(it) ? [it.messageId, it.reqId] : [it.messageId]))
55
+ .flat();
56
+ messageKeys.forEach((key) => delete draft['messageMap'][key]);
57
+
58
+ draft['messageMap'] = {
59
+ ...draft['messageMap'],
60
+ ...arrayToMapWithGetter(action.value.messages, getMessageUniqId),
61
+ };
62
+ }
63
+
64
+ return draft;
65
+ }
66
+ case 'update_new_messages': {
67
+ const newMessages = action.value.messages.filter((it) => isNewMessage(it, action.value.currentUserId));
68
+
69
+ if (action.value.clearBeforeAction) {
70
+ draft['newMessageMap'] = arrayToMapWithGetter(newMessages, getMessageUniqId);
71
+ } else {
72
+ // Remove existing messages before update for prevent duplicate display
73
+ const messageKeys = newMessages.map((it) => it.messageId);
74
+ messageKeys.forEach((key) => delete draft['newMessageMap'][key]);
75
+
76
+ draft['newMessageMap'] = {
77
+ ...draft['newMessageMap'],
78
+ ...arrayToMapWithGetter(newMessages, getMessageUniqId),
79
+ };
80
+ }
81
+
82
+ return draft;
83
+ }
84
+ case 'delete_messages':
85
+ case 'delete_new_messages': {
86
+ const key = action.type === 'delete_messages' ? 'messageMap' : 'newMessageMap';
87
+ draft[key] = { ...draft[key] };
88
+ action.value.messageIds.forEach((msgId) => delete draft[key][msgId]);
89
+ action.value.reqIds.forEach((reqId) => delete draft[key][reqId]);
90
+
91
+ return draft;
92
+ }
93
+ }
94
+ };
95
+
96
+ export const useChannelMessagesReducer = (sortComparator?: Options['sortComparator']) => {
97
+ const [{ loading, refreshing, messageMap, newMessageMap }, dispatch] = useReducer(defaultReducer, {
98
+ loading: true,
99
+ refreshing: false,
100
+ messageMap: {},
101
+ newMessageMap: {},
102
+ });
103
+
104
+ const updateMessages = (messages: SendbirdBaseMessage[], clearBeforeAction: boolean, currentUserId?: string) => {
105
+ dispatch({ type: 'update_messages', value: { messages, clearBeforeAction, currentUserId } });
106
+ };
107
+ const deleteMessages = (messageIds: number[], reqIds: string[]) => {
108
+ dispatch({ type: 'delete_messages', value: { messageIds, reqIds } });
109
+ };
110
+ const updateNewMessages = (messages: SendbirdBaseMessage[], clearBeforeAction: boolean, currentUserId?: string) => {
111
+ dispatch({ type: 'update_new_messages', value: { messages, clearBeforeAction, currentUserId } });
112
+ };
113
+ const deleteNewMessages = (messageIds: number[], reqIds: string[]) => {
114
+ dispatch({ type: 'delete_new_messages', value: { messageIds, reqIds } });
115
+ };
116
+ const updateLoading = (status: boolean) => {
117
+ dispatch({ type: 'update_loading', value: { status } });
118
+ };
119
+ const updateRefreshing = (status: boolean) => {
120
+ dispatch({ type: 'update_refreshing', value: { status } });
121
+ };
122
+
123
+ const messages = useIIFE(() => {
124
+ if (sortComparator) return Object.values(messageMap).sort(sortComparator);
125
+ return Object.values(messageMap);
126
+ });
127
+ const newMessages = Object.values(newMessageMap);
128
+
129
+ return {
130
+ updateLoading,
131
+ updateRefreshing,
132
+ updateMessages,
133
+ deleteMessages,
134
+
135
+ loading,
136
+ refreshing,
137
+ messages,
138
+
139
+ newMessages,
140
+ updateNewMessages,
141
+ deleteNewMessages,
142
+ };
143
+ };