@sendbird/uikit-chat-hooks 3.0.4-rc.1 → 3.1.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 (25) hide show
  1. package/lib/commonjs/channel/useChannelMessagesReducer.js +60 -11
  2. package/lib/commonjs/channel/useChannelMessagesReducer.js.map +1 -1
  3. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +94 -83
  4. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  5. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +44 -26
  6. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  7. package/lib/commonjs/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js +46 -28
  8. package/lib/commonjs/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js.map +1 -1
  9. package/lib/commonjs/types.js.map +1 -1
  10. package/lib/module/channel/useChannelMessagesReducer.js +61 -12
  11. package/lib/module/channel/useChannelMessagesReducer.js.map +1 -1
  12. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +96 -85
  13. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  14. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +44 -26
  15. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  16. package/lib/module/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js +46 -28
  17. package/lib/module/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.js.map +1 -1
  18. package/lib/module/types.js.map +1 -1
  19. package/lib/typescript/src/types.d.ts +1 -0
  20. package/package.json +6 -5
  21. package/src/channel/useChannelMessagesReducer.ts +66 -17
  22. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.ts +75 -84
  23. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.ts +26 -22
  24. package/src/channel/useOpenChannelMessages/useOpenChannelMessagesWithQuery.ts +31 -26
  25. package/src/types.ts +1 -0
@@ -1,12 +1,15 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
 
3
- import { MessageCollectionInitPolicy, MessageEventSource, MessageFilter } from '@sendbird/chat/groupChannel';
3
+ import { CollectionEventSource } from '@sendbird/chat';
4
+ import { MessageCollectionInitPolicy, MessageFilter } from '@sendbird/chat/groupChannel';
4
5
  import type { SendbirdFileMessage, SendbirdGroupChannel, SendbirdMessageCollection } from '@sendbird/uikit-utils';
5
6
  import {
6
7
  Logger,
8
+ SendbirdBaseMessage,
7
9
  confirmAndMarkAsRead,
8
10
  isDifferentChannel,
9
11
  isMyMessage,
12
+ isSendableMessage,
10
13
  useForceUpdate,
11
14
  useFreshCallback,
12
15
  useUniqHandlerId,
@@ -39,9 +42,13 @@ function isNotEmpty(arr?: unknown[]): arr is unknown[] {
39
42
  return arr.length !== 0;
40
43
  }
41
44
 
45
+ function shouldUseSearchLimit(startingPoint: number) {
46
+ return startingPoint < Date.now();
47
+ }
48
+
42
49
  export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (sdk, channel, userId, options) => {
43
50
  const initialStartingPoint = options?.startingPoint ?? Number.MAX_SAFE_INTEGER;
44
- const initialLimit = typeof options?.startingPoint === 'number' ? MESSAGE_LIMIT.SEARCH : MESSAGE_LIMIT.DEFAULT;
51
+ const initialLimit = shouldUseSearchLimit(initialStartingPoint) ? MESSAGE_LIMIT.SEARCH : MESSAGE_LIMIT.DEFAULT;
45
52
 
46
53
  const forceUpdate = useForceUpdate();
47
54
  const collectionRef = useRef<SendbirdMessageCollection>();
@@ -61,12 +68,12 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
61
68
  updateRefreshing,
62
69
  } = useChannelMessagesReducer(options?.sortComparator);
63
70
 
64
- const channelMarkAsRead = async (source?: MessageEventSource) => {
71
+ const channelMarkAsRead = async (source?: CollectionEventSource) => {
65
72
  try {
66
73
  switch (source) {
67
- case MessageEventSource.EVENT_MESSAGE_RECEIVED:
68
- case MessageEventSource.EVENT_MESSAGE_SENT_SUCCESS:
69
- case MessageEventSource.SYNC_MESSAGE_FILL:
74
+ case CollectionEventSource.EVENT_MESSAGE_RECEIVED:
75
+ case CollectionEventSource.EVENT_MESSAGE_SENT_SUCCESS:
76
+ case CollectionEventSource.SYNC_MESSAGE_FILL:
70
77
  case undefined:
71
78
  await confirmAndMarkAsRead([channel]);
72
79
  break;
@@ -75,18 +82,31 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
75
82
  Logger.warn('[useGroupChannelMessagesWithCollection/channelMarkAsRead]', e);
76
83
  }
77
84
  };
85
+ const updateNewMessagesReceived = (source: CollectionEventSource, messages: SendbirdBaseMessage[]) => {
86
+ const incomingMessages = messages.filter((it) => !isMyMessage(it, sdk.currentUser?.userId));
87
+ if (incomingMessages.length > 0) {
88
+ switch (source) {
89
+ case CollectionEventSource.EVENT_MESSAGE_RECEIVED:
90
+ case CollectionEventSource.SYNC_MESSAGE_FILL: {
91
+ if (options?.shouldCountNewMessages?.()) updateNewMessages(incomingMessages, false, sdk.currentUser?.userId);
92
+ options?.onMessagesReceived?.(incomingMessages);
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ };
78
98
 
79
- const updateUnsendMessages = () => {
99
+ const updateUnsentMessages = () => {
80
100
  const { pendingMessages, failedMessages } = collectionRef.current ?? {};
81
- if (isNotEmpty(pendingMessages)) updateMessages(pendingMessages, false, sdk.currentUser.userId);
82
- if (isNotEmpty(failedMessages)) updateMessages(failedMessages, false, sdk.currentUser.userId);
101
+ if (isNotEmpty(pendingMessages)) updateMessages(pendingMessages, false, sdk.currentUser?.userId);
102
+ if (isNotEmpty(failedMessages)) updateMessages(failedMessages, false, sdk.currentUser?.userId);
83
103
  };
84
104
 
85
105
  const init = useFreshCallback(async (startingPoint: number, limit: number, callback?: () => void) => {
86
106
  if (collectionRef.current) collectionRef.current?.dispose();
87
107
 
88
108
  channelMarkAsRead();
89
- updateNewMessages([], true, sdk.currentUser.userId);
109
+ updateNewMessages([], true, sdk.currentUser?.userId);
90
110
 
91
111
  collectionInitializedRef.current = false;
92
112
  collectionRef.current = createMessageCollection(channel, limit, {
@@ -95,61 +115,27 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
95
115
  });
96
116
 
97
117
  collectionRef.current?.setMessageCollectionHandler({
98
- onMessagesAdded: (_, __, messages) => {
99
- channelMarkAsRead(_.source);
100
-
101
- const incomingMessages = messages.filter((it) => {
102
- switch (_.source) {
103
- case MessageEventSource.EVENT_MESSAGE_SENT_PENDING:
104
- case MessageEventSource.EVENT_MESSAGE_SENT_SUCCESS:
105
- case MessageEventSource.EVENT_MESSAGE_SENT_FAILED:
106
- return !isMyMessage(it, sdk.currentUser.userId);
107
- default:
108
- return true;
109
- }
110
- });
111
-
112
- if (incomingMessages.length > 0) {
113
- updateMessages(incomingMessages, false, sdk.currentUser.userId);
114
-
115
- if (options?.shouldCountNewMessages?.()) {
116
- updateNewMessages(incomingMessages, false, sdk.currentUser.userId);
117
- }
118
-
119
- switch (_.source) {
120
- case MessageEventSource.EVENT_MESSAGE_RECEIVED:
121
- case MessageEventSource.SYNC_MESSAGE_FILL: {
122
- options?.onMessagesReceived?.(incomingMessages);
123
- }
124
- }
125
- }
118
+ onMessagesAdded: (ctx, __, messages) => {
119
+ channelMarkAsRead(ctx.source);
120
+ updateNewMessagesReceived(ctx.source, messages);
121
+
122
+ updateMessages(messages, false, sdk.currentUser?.userId);
126
123
  },
127
- onMessagesUpdated: (_, __, messages) => {
128
- channelMarkAsRead(_.source);
129
-
130
- const incomingMessages = messages.filter((it) => {
131
- switch (_.source) {
132
- case MessageEventSource.EVENT_MESSAGE_UPDATED:
133
- return !isMyMessage(it, sdk.currentUser.userId);
134
- default:
135
- return true;
136
- }
137
- });
138
-
139
- if (incomingMessages.length > 0) {
140
- // NOTE: admin message is not added via onMessagesAdded handler, not checked yet is this a bug.
141
- updateMessages(messages, false, sdk.currentUser.userId);
142
-
143
- if (options?.shouldCountNewMessages?.()) {
144
- if (_.source === MessageEventSource.EVENT_MESSAGE_RECEIVED) {
145
- updateNewMessages(messages, false, sdk.currentUser.userId);
146
- }
147
- }
124
+ onMessagesUpdated: (ctx, __, messages) => {
125
+ channelMarkAsRead(ctx.source);
126
+ updateNewMessagesReceived(ctx.source, messages); // NOTE: admin message is not added via onMessagesAdded handler, not checked yet is this a bug.
127
+
128
+ updateMessages(messages, false, sdk.currentUser?.userId);
129
+
130
+ if (ctx.source === CollectionEventSource.EVENT_MESSAGE_UPDATED) {
131
+ options?.onMessagesUpdated?.(messages);
148
132
  }
149
133
  },
150
- onMessagesDeleted: (_, __, messageIds) => {
151
- deleteMessages(messageIds, []);
152
- deleteNewMessages(messageIds, []);
134
+ onMessagesDeleted: (_, __, ___, messages) => {
135
+ const msgIds = messages.map((it) => it.messageId);
136
+ const reqIds = messages.filter(isSendableMessage).map((it) => it.reqId);
137
+ deleteMessages(msgIds, reqIds);
138
+ deleteNewMessages(msgIds, reqIds);
153
139
  },
154
140
  onChannelDeleted: () => {
155
141
  options?.onChannelDeleted?.();
@@ -168,23 +154,23 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
168
154
  .initialize(MessageCollectionInitPolicy.CACHE_AND_REPLACE_BY_API)
169
155
  .onCacheResult((err, messages) => {
170
156
  if (err) sdk.isCacheEnabled && Logger.error('[useGroupChannelMessagesWithCollection/onCacheResult]', err);
171
- else {
157
+ else if (messages) {
172
158
  Logger.debug('[useGroupChannelMessagesWithCollection/onCacheResult]', 'message length:', messages.length);
173
159
 
174
- updateMessages(messages, true, sdk.currentUser.userId);
175
- updateUnsendMessages();
160
+ updateMessages(messages, true, sdk.currentUser?.userId);
161
+ updateUnsentMessages();
176
162
  }
177
163
 
178
164
  callback?.();
179
165
  })
180
166
  .onApiResult((err, messages) => {
181
167
  if (err) Logger.warn('[useGroupChannelMessagesWithCollection/onApiResult]', err);
182
- else {
168
+ else if (messages) {
183
169
  Logger.debug('[useGroupChannelMessagesWithCollection/onApiResult]', 'message length:', messages.length);
184
170
 
185
- updateMessages(messages, true, sdk.currentUser.userId);
171
+ updateMessages(messages, true, sdk.currentUser?.userId);
186
172
  if (!options?.startingPoint) options?.onMessagesReceived?.(messages);
187
- if (sdk.isCacheEnabled) updateUnsendMessages();
173
+ if (sdk.isCacheEnabled) updateUnsentMessages();
188
174
  }
189
175
 
190
176
  collectionInitializedRef.current = true;
@@ -195,7 +181,7 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
195
181
  useChannelHandler(sdk, handlerId, {
196
182
  onUserBanned(channel, bannedUser) {
197
183
  if (channel.isGroupChannel() && !isDifferentChannel(channel, channel)) {
198
- if (bannedUser.userId === sdk.currentUser.userId) {
184
+ if (bannedUser.userId === sdk.currentUser?.userId) {
199
185
  options?.onChannelDeleted?.();
200
186
  } else {
201
187
  forceUpdate();
@@ -210,7 +196,7 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
210
196
  updateLoading(true);
211
197
  init(initialStartingPoint, initialLimit, () => updateLoading(false));
212
198
  }, 0);
213
- }, [channel.url, userId]);
199
+ }, [channel.url, userId, options?.replyType]);
214
200
 
215
201
  useEffect(() => {
216
202
  return () => {
@@ -227,7 +213,7 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
227
213
  if (collectionRef.current && collectionRef.current?.hasPrevious) {
228
214
  try {
229
215
  const list = await collectionRef.current?.loadPrevious();
230
- updateMessages(list, false, sdk.currentUser.userId);
216
+ updateMessages(list, false, sdk.currentUser?.userId);
231
217
  } catch {}
232
218
  }
233
219
  });
@@ -244,7 +230,7 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
244
230
  if (collectionRef.current && collectionRef.current?.hasNext) {
245
231
  try {
246
232
  const fetchedList = await collectionRef.current?.loadNext();
247
- updateMessages(fetchedList, false, sdk.currentUser.userId);
233
+ updateMessages(fetchedList, false, sdk.currentUser?.userId);
248
234
  } catch {}
249
235
  }
250
236
  });
@@ -265,17 +251,19 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
265
251
  .onPending((pendingMessage) => {
266
252
  if (pendingMessage.isUserMessage()) {
267
253
  onPending?.(pendingMessage);
268
- updateMessages([pendingMessage], false, sdk.currentUser.userId);
254
+ updateMessages([pendingMessage], false, sdk.currentUser?.userId);
269
255
  }
270
256
  })
271
257
  .onSucceeded((sentMessage) => {
272
258
  if (sentMessage.isUserMessage()) {
273
- updateMessages([sentMessage], false, sdk.currentUser.userId);
259
+ updateMessages([sentMessage], false, sdk.currentUser?.userId);
274
260
  resolve(sentMessage);
275
261
  }
276
262
  })
277
263
  .onFailed((err, failedMessage) => {
278
- updateMessages([failedMessage], false, sdk.currentUser.userId);
264
+ if (failedMessage) {
265
+ updateMessages([failedMessage], false, sdk.currentUser?.userId);
266
+ }
279
267
  reject(err);
280
268
  });
281
269
  });
@@ -288,18 +276,20 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
288
276
  .sendFileMessage(params)
289
277
  .onPending((pendingMessage) => {
290
278
  if (pendingMessage.isFileMessage()) {
291
- updateMessages([pendingMessage], false, sdk.currentUser.userId);
279
+ updateMessages([pendingMessage], false, sdk.currentUser?.userId);
292
280
  onPending?.(pendingMessage);
293
281
  }
294
282
  })
295
283
  .onSucceeded((sentMessage) => {
296
284
  if (sentMessage.isFileMessage()) {
297
- updateMessages([sentMessage], false, sdk.currentUser.userId);
285
+ updateMessages([sentMessage], false, sdk.currentUser?.userId);
298
286
  resolve(sentMessage as SendbirdFileMessage);
299
287
  }
300
288
  })
301
289
  .onFailed((err, failedMessage) => {
302
- updateMessages([failedMessage], false, sdk.currentUser.userId);
290
+ if (failedMessage) {
291
+ updateMessages([failedMessage], false, sdk.currentUser?.userId);
292
+ }
303
293
  reject(err);
304
294
  });
305
295
  });
@@ -308,14 +298,14 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
308
298
  const updateUserMessage: ReturnType<UseGroupChannelMessages>['updateUserMessage'] = useFreshCallback(
309
299
  async (messageId, params) => {
310
300
  const updatedMessage = await channel.updateUserMessage(messageId, params);
311
- updateMessages([updatedMessage], false, sdk.currentUser.userId);
301
+ updateMessages([updatedMessage], false, sdk.currentUser?.userId);
312
302
  return updatedMessage;
313
303
  },
314
304
  );
315
305
  const updateFileMessage: ReturnType<UseGroupChannelMessages>['updateFileMessage'] = useFreshCallback(
316
306
  async (messageId, params) => {
317
307
  const updatedMessage = await channel.updateFileMessage(messageId, params);
318
- updateMessages([updatedMessage], false, sdk.currentUser.userId);
308
+ updateMessages([updatedMessage], false, sdk.currentUser?.userId);
319
309
  return updatedMessage;
320
310
  },
321
311
  );
@@ -327,7 +317,7 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
327
317
  return null;
328
318
  })();
329
319
 
330
- if (resentMessage) updateMessages([resentMessage], false, sdk.currentUser.userId);
320
+ if (resentMessage) updateMessages([resentMessage], false, sdk.currentUser?.userId);
331
321
  },
332
322
  );
333
323
  const deleteMessage: ReturnType<UseGroupChannelMessages>['deleteMessage'] = useFreshCallback(async (message) => {
@@ -343,13 +333,14 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
343
333
  }
344
334
  });
345
335
  const resetNewMessages: ReturnType<UseGroupChannelMessages>['resetNewMessages'] = useFreshCallback(() => {
346
- updateNewMessages([], true, sdk.currentUser.userId);
336
+ updateNewMessages([], true, sdk.currentUser?.userId);
347
337
  });
348
338
  const resetWithStartingPoint: ReturnType<UseGroupChannelMessages>['resetWithStartingPoint'] = useFreshCallback(
349
339
  (startingPoint, callback) => {
340
+ const limit = shouldUseSearchLimit(startingPoint) ? MESSAGE_LIMIT.SEARCH : MESSAGE_LIMIT.DEFAULT;
350
341
  updateLoading(true);
351
- updateMessages([], true, sdk.currentUser.userId);
352
- init(startingPoint, MESSAGE_LIMIT.DEFAULT, () => {
342
+ updateMessages([], true, sdk.currentUser?.userId);
343
+ init(startingPoint, limit, () => {
353
344
  updateLoading(false);
354
345
  callback?.();
355
346
  });
@@ -61,12 +61,12 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
61
61
  const init = useFreshCallback(async (uid?: string) => {
62
62
  if (uid) {
63
63
  channelMarkAsRead();
64
- updateNewMessages([], true, sdk.currentUser.userId);
64
+ updateNewMessages([], true, sdk.currentUser?.userId);
65
65
 
66
66
  queryRef.current = createMessageQuery(channel, options);
67
67
  if (queryRef.current?.hasNext) {
68
68
  const list = await queryRef.current?.load();
69
- updateMessages(list, true, sdk.currentUser.userId);
69
+ updateMessages(list, true, sdk.currentUser?.userId);
70
70
  }
71
71
  }
72
72
  });
@@ -81,13 +81,13 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
81
81
  // Messages
82
82
  onMessageReceived(eventChannel, message) {
83
83
  if (isDifferentChannel(channel, eventChannel)) return;
84
- if (isMyMessage(message, sdk.currentUser.userId)) return;
84
+ if (isMyMessage(message, sdk.currentUser?.userId)) return;
85
85
 
86
86
  channelMarkAsRead();
87
87
 
88
- updateMessages([message], false, sdk.currentUser.userId);
88
+ updateMessages([message], false, sdk.currentUser?.userId);
89
89
  if (options?.shouldCountNewMessages?.()) {
90
- updateNewMessages([message], false, sdk.currentUser.userId);
90
+ updateNewMessages([message], false, sdk.currentUser?.userId);
91
91
  }
92
92
  if (options?.onMessagesReceived) {
93
93
  options.onMessagesReceived([message]);
@@ -95,9 +95,9 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
95
95
  },
96
96
  onMessageUpdated(eventChannel, message) {
97
97
  if (isDifferentChannel(channel, eventChannel)) return;
98
- if (isMyMessage(message, sdk.currentUser.userId)) return;
98
+ if (isMyMessage(message, sdk.currentUser?.userId)) return;
99
99
 
100
- updateMessages([message], false, sdk.currentUser.userId);
100
+ updateMessages([message], false, sdk.currentUser?.userId);
101
101
  },
102
102
  onMessageDeleted(eventChannel, messageId) {
103
103
  if (isDifferentChannel(channel, eventChannel)) return;
@@ -116,7 +116,7 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
116
116
  channelUrl: channel.url,
117
117
  channelType: channel.channelType,
118
118
  });
119
- updateMessages([message], false, sdk.currentUser.userId);
119
+ if (message) updateMessages([message], false, sdk.currentUser?.userId);
120
120
  },
121
121
  // Channels
122
122
  onChannelChanged: channelUpdater,
@@ -142,7 +142,7 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
142
142
  onUserBanned(eventChannel, bannedUser) {
143
143
  if (isDifferentChannel(channel, eventChannel)) return;
144
144
 
145
- if (bannedUser.userId === sdk.currentUser.userId) {
145
+ if (bannedUser.userId === sdk.currentUser?.userId) {
146
146
  options?.onChannelDeleted?.();
147
147
  } else {
148
148
  channelUpdater(eventChannel);
@@ -165,7 +165,7 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
165
165
  const prev: ReturnType<UseGroupChannelMessages>['prev'] = useFreshCallback(async () => {
166
166
  if (queryRef.current && queryRef.current?.hasNext) {
167
167
  const list = await queryRef.current?.load();
168
- updateMessages(list, false, sdk.currentUser.userId);
168
+ updateMessages(list, false, sdk.currentUser?.userId);
169
169
  }
170
170
  });
171
171
  const hasPrev: ReturnType<UseGroupChannelMessages>['hasPrev'] = useFreshCallback(
@@ -182,18 +182,20 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
182
182
  .sendUserMessage(params)
183
183
  .onPending((pendingMessage) => {
184
184
  if (pendingMessage.isUserMessage()) {
185
- updateMessages([pendingMessage], false, sdk.currentUser.userId);
185
+ updateMessages([pendingMessage], false, sdk.currentUser?.userId);
186
186
  onPending?.(pendingMessage);
187
187
  }
188
188
  })
189
189
  .onSucceeded((sentMessage) => {
190
190
  if (sentMessage.isUserMessage()) {
191
- updateMessages([sentMessage], false, sdk.currentUser.userId);
191
+ updateMessages([sentMessage], false, sdk.currentUser?.userId);
192
192
  resolve(sentMessage);
193
193
  }
194
194
  })
195
- .onFailed((err, sentMessage) => {
196
- updateMessages([sentMessage], false, sdk.currentUser.userId);
195
+ .onFailed((err, failedMessage) => {
196
+ if (failedMessage) {
197
+ updateMessages([failedMessage], false, sdk.currentUser?.userId);
198
+ }
197
199
  reject(err);
198
200
  });
199
201
  });
@@ -206,18 +208,20 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
206
208
  .sendFileMessage(params)
207
209
  .onPending((pendingMessage) => {
208
210
  if (pendingMessage.isFileMessage()) {
209
- updateMessages([pendingMessage], false, sdk.currentUser.userId);
211
+ updateMessages([pendingMessage], false, sdk.currentUser?.userId);
210
212
  onPending?.(pendingMessage);
211
213
  }
212
214
  })
213
215
  .onSucceeded((sentMessage) => {
214
216
  if (sentMessage.isFileMessage()) {
215
- updateMessages([sentMessage], false, sdk.currentUser.userId);
217
+ updateMessages([sentMessage], false, sdk.currentUser?.userId);
216
218
  resolve(sentMessage);
217
219
  }
218
220
  })
219
- .onFailed((err, sentMessage) => {
220
- updateMessages([sentMessage], false, sdk.currentUser.userId);
221
+ .onFailed((err, failedMessage) => {
222
+ if (failedMessage) {
223
+ updateMessages([failedMessage], false, sdk.currentUser?.userId);
224
+ }
221
225
  reject(err);
222
226
  });
223
227
  });
@@ -226,14 +230,14 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
226
230
  const updateUserMessage: ReturnType<UseGroupChannelMessages>['updateUserMessage'] = useFreshCallback(
227
231
  async (messageId, params) => {
228
232
  const updatedMessage = await channel.updateUserMessage(messageId, params);
229
- updateMessages([updatedMessage], false, sdk.currentUser.userId);
233
+ updateMessages([updatedMessage], false, sdk.currentUser?.userId);
230
234
  return updatedMessage;
231
235
  },
232
236
  );
233
237
  const updateFileMessage: ReturnType<UseGroupChannelMessages>['updateFileMessage'] = useFreshCallback(
234
238
  async (messageId, params) => {
235
239
  const updatedMessage = await channel.updateFileMessage(messageId, params);
236
- updateMessages([updatedMessage], false, sdk.currentUser.userId);
240
+ updateMessages([updatedMessage], false, sdk.currentUser?.userId);
237
241
  return updatedMessage;
238
242
  },
239
243
  );
@@ -245,7 +249,7 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
245
249
  return null;
246
250
  })();
247
251
 
248
- if (message) updateMessages([message], false, sdk.currentUser.userId);
252
+ if (message) updateMessages([message], false, sdk.currentUser?.userId);
249
253
  },
250
254
  );
251
255
  const deleteMessage: ReturnType<UseGroupChannelMessages>['deleteMessage'] = useFreshCallback(async (message) => {
@@ -257,7 +261,7 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
257
261
  }
258
262
  });
259
263
  const resetNewMessages: ReturnType<UseGroupChannelMessages>['resetNewMessages'] = useFreshCallback(() => {
260
- updateNewMessages([], true, sdk.currentUser.userId);
264
+ updateNewMessages([], true, sdk.currentUser?.userId);
261
265
  });
262
266
 
263
267
  return {
@@ -1,5 +1,6 @@
1
1
  import { useRef } from 'react';
2
2
 
3
+ import { MessageListParams } from '@sendbird/chat/message';
3
4
  import type {
4
5
  SendbirdBaseChannel,
5
6
  SendbirdBaseMessage,
@@ -54,9 +55,9 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
54
55
  if (queryRef.current?.hasNext) {
55
56
  const list = await queryRef.current?.load();
56
57
 
57
- updateMessages(list, true, sdk.currentUser.userId);
58
+ updateMessages(list, true, sdk.currentUser?.userId);
58
59
  }
59
- updateNewMessages([], true, sdk.currentUser.userId);
60
+ updateNewMessages([], true, sdk.currentUser?.userId);
60
61
  }
61
62
  });
62
63
 
@@ -109,7 +110,7 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
109
110
  }
110
111
 
111
112
  // Added messages
112
- const messageQueryParams = {
113
+ const messageQueryParams: MessageListParams = {
113
114
  prevResultSize: 0,
114
115
  nextResultSize: queryRef.current?.limit ?? 100,
115
116
  reverse: queryRef.current?.reverse,
@@ -118,9 +119,9 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
118
119
  includeReactions: queryRef.current?.includeReactions,
119
120
  includeMetaArray: queryRef.current?.includeMetaArray,
120
121
  replyType: queryRef.current?.replyType,
121
- customTypesFilter: queryRef.current?.customTypesFilter,
122
+ customTypesFilter: queryRef.current?.customTypesFilter as never,
122
123
  messageTypeFilter: queryRef.current?.messageTypeFilter,
123
- senderUserIdsFilter: queryRef.current?.senderUserIdsFilter,
124
+ senderUserIdsFilter: queryRef.current?.senderUserIdsFilter as never,
124
125
  showSubchannelMessagesOnly: queryRef.current?.showSubchannelMessagesOnly,
125
126
  };
126
127
 
@@ -144,13 +145,13 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
144
145
  updateMessages(
145
146
  [...messageContext.addedMessages, ...messageContext.updatedMessages],
146
147
  false,
147
- sdk.currentUser.userId,
148
+ sdk.currentUser?.userId,
148
149
  );
149
150
  deleteMessages(messageContext.deletedMessageIds, []);
150
151
 
151
152
  if (messageContext.addedMessages.length > 0) {
152
153
  if (options?.shouldCountNewMessages?.()) {
153
- updateNewMessages(messageContext.addedMessages, false, sdk.currentUser.userId);
154
+ updateNewMessages(messageContext.addedMessages, false, sdk.currentUser?.userId);
154
155
  }
155
156
  if (options?.onMessagesReceived) {
156
157
  options.onMessagesReceived(messageContext.addedMessages);
@@ -166,11 +167,11 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
166
167
  // Messages
167
168
  onMessageReceived(eventChannel, message) {
168
169
  if (isDifferentChannel(channel, eventChannel)) return;
169
- if (isMyMessage(message, sdk.currentUser.userId)) return;
170
+ if (isMyMessage(message, sdk.currentUser?.userId)) return;
170
171
 
171
- updateMessages([message], false, sdk.currentUser.userId);
172
+ updateMessages([message], false, sdk.currentUser?.userId);
172
173
  if (options?.shouldCountNewMessages?.()) {
173
- updateNewMessages([message], false, sdk.currentUser.userId);
174
+ updateNewMessages([message], false, sdk.currentUser?.userId);
174
175
  }
175
176
  if (options?.onMessagesReceived) {
176
177
  options.onMessagesReceived([message]);
@@ -178,9 +179,9 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
178
179
  },
179
180
  onMessageUpdated(eventChannel, message) {
180
181
  if (isDifferentChannel(channel, eventChannel)) return;
181
- if (isMyMessage(message, sdk.currentUser.userId)) return;
182
+ if (isMyMessage(message, sdk.currentUser?.userId)) return;
182
183
 
183
- updateMessages([message], false, sdk.currentUser.userId);
184
+ updateMessages([message], false, sdk.currentUser?.userId);
184
185
  },
185
186
  onMessageDeleted(eventChannel, messageId) {
186
187
  if (isDifferentChannel(channel, eventChannel)) return;
@@ -208,7 +209,7 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
208
209
  onUserBanned(eventChannel, bannedUser) {
209
210
  if (isDifferentChannel(channel, eventChannel)) return;
210
211
 
211
- if (bannedUser.userId === sdk.currentUser.userId) {
212
+ if (bannedUser.userId === sdk.currentUser?.userId) {
212
213
  options?.onChannelDeleted?.();
213
214
  } else {
214
215
  channelUpdater(eventChannel);
@@ -245,7 +246,7 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
245
246
  const prev: ReturnType<UseOpenChannelMessages>['prev'] = useFreshCallback(async () => {
246
247
  if (queryRef.current && queryRef.current?.hasNext) {
247
248
  const list = await queryRef.current?.load();
248
- updateMessages(list, false, sdk.currentUser.userId);
249
+ updateMessages(list, false, sdk.currentUser?.userId);
249
250
  }
250
251
  });
251
252
  const hasPrev: ReturnType<UseOpenChannelMessages>['hasPrev'] = useFreshCallback(
@@ -262,18 +263,20 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
262
263
  .sendUserMessage(params)
263
264
  .onPending((pendingMessage) => {
264
265
  if (pendingMessage.isUserMessage()) {
265
- updateMessages([pendingMessage], false, sdk.currentUser.userId);
266
+ updateMessages([pendingMessage], false, sdk.currentUser?.userId);
266
267
  onPending?.(pendingMessage);
267
268
  }
268
269
  })
269
270
  .onSucceeded((sentMessage) => {
270
271
  if (sentMessage.isUserMessage()) {
271
- updateMessages([sentMessage], false, sdk.currentUser.userId);
272
+ updateMessages([sentMessage], false, sdk.currentUser?.userId);
272
273
  resolve(sentMessage);
273
274
  }
274
275
  })
275
- .onFailed((err, sentMessage) => {
276
- updateMessages([sentMessage], false, sdk.currentUser.userId);
276
+ .onFailed((err, failedMessage) => {
277
+ if (failedMessage) {
278
+ updateMessages([failedMessage], false, sdk.currentUser?.userId);
279
+ }
277
280
  reject(err);
278
281
  });
279
282
  });
@@ -287,18 +290,20 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
287
290
  .sendFileMessage(params)
288
291
  .onPending((pendingMessage) => {
289
292
  if (pendingMessage.isFileMessage()) {
290
- updateMessages([pendingMessage], false, sdk.currentUser.userId);
293
+ updateMessages([pendingMessage], false, sdk.currentUser?.userId);
291
294
  onPending?.(pendingMessage);
292
295
  }
293
296
  })
294
297
  .onSucceeded((sentMessage) => {
295
298
  if (sentMessage.isFileMessage()) {
296
- updateMessages([sentMessage], false, sdk.currentUser.userId);
299
+ updateMessages([sentMessage], false, sdk.currentUser?.userId);
297
300
  resolve(sentMessage);
298
301
  }
299
302
  })
300
- .onFailed((err, sentMessage) => {
301
- updateMessages([sentMessage], false, sdk.currentUser.userId);
303
+ .onFailed((err, failedMessage) => {
304
+ if (failedMessage) {
305
+ updateMessages([failedMessage], false, sdk.currentUser?.userId);
306
+ }
302
307
  reject(err);
303
308
  });
304
309
  });
@@ -308,14 +313,14 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
308
313
  const updateUserMessage: ReturnType<UseOpenChannelMessages>['updateUserMessage'] = useFreshCallback(
309
314
  async (messageId, params) => {
310
315
  const updatedMessage = await channel.updateUserMessage(messageId, params);
311
- updateMessages([updatedMessage], false, sdk.currentUser.userId);
316
+ updateMessages([updatedMessage], false, sdk.currentUser?.userId);
312
317
  return updatedMessage;
313
318
  },
314
319
  );
315
320
  const updateFileMessage: ReturnType<UseOpenChannelMessages>['updateFileMessage'] = useFreshCallback(
316
321
  async (messageId, params) => {
317
322
  const updatedMessage = await channel.updateFileMessage(messageId, params);
318
- updateMessages([updatedMessage], false, sdk.currentUser.userId);
323
+ updateMessages([updatedMessage], false, sdk.currentUser?.userId);
319
324
  return updatedMessage;
320
325
  },
321
326
  );
@@ -326,7 +331,7 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
326
331
  return null;
327
332
  })();
328
333
 
329
- if (message) updateMessages([message], false, sdk.currentUser.userId);
334
+ if (message) updateMessages([message], false, sdk.currentUser?.userId);
330
335
  });
331
336
  const deleteMessage: ReturnType<UseOpenChannelMessages>['deleteMessage'] = useFreshCallback(async (message) => {
332
337
  if (message.sendingStatus === 'succeeded') {
@@ -337,7 +342,7 @@ export const useOpenChannelMessagesWithQuery: UseOpenChannelMessages = (sdk, cha
337
342
  }
338
343
  });
339
344
  const resetNewMessages: ReturnType<UseOpenChannelMessages>['resetNewMessages'] = useFreshCallback(() => {
340
- updateNewMessages([], true, sdk.currentUser.userId);
345
+ updateNewMessages([], true, sdk.currentUser?.userId);
341
346
  });
342
347
 
343
348
  return {
package/src/types.ts CHANGED
@@ -211,6 +211,7 @@ export type UseGroupChannelMessagesOptions = {
211
211
  shouldCountNewMessages?: () => boolean;
212
212
  startingPoint?: number;
213
213
  onMessagesReceived?: (messages: SendbirdMessage[]) => void;
214
+ onMessagesUpdated?: (messages: SendbirdMessage[]) => void;
214
215
  };
215
216
 
216
217
  /**