@sendbird/uikit-chat-hooks 1.0.2 → 1.1.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 (74) hide show
  1. package/lib/commonjs/channel/{useGroupChannelList.js → useGroupChannelList/index.js} +1 -1
  2. package/lib/commonjs/channel/useGroupChannelList/index.js.map +1 -0
  3. package/lib/commonjs/channel/useGroupChannelList/reducer.js +184 -0
  4. package/lib/commonjs/channel/useGroupChannelList/reducer.js.map +1 -0
  5. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithCollection.js +134 -0
  6. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithCollection.js.map +1 -0
  7. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithQuery.js +118 -0
  8. package/lib/commonjs/channel/useGroupChannelList/useGroupChannelListWithQuery.js.map +1 -0
  9. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +4 -5
  10. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  11. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +3 -3
  12. package/lib/commonjs/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  13. package/lib/commonjs/common/useAppFeatures.js +8 -28
  14. package/lib/commonjs/common/useAppFeatures.js.map +1 -1
  15. package/lib/commonjs/common/useMessageOutgoingStatus.js +49 -0
  16. package/lib/commonjs/common/useMessageOutgoingStatus.js.map +1 -0
  17. package/lib/commonjs/handler/useChannelHandler.js +16 -5
  18. package/lib/commonjs/handler/useChannelHandler.js.map +1 -1
  19. package/lib/commonjs/index.js +12 -4
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/commonjs/types.js.map +1 -1
  22. package/lib/module/channel/{useGroupChannelList.js → useGroupChannelList/index.js} +1 -1
  23. package/lib/module/channel/useGroupChannelList/index.js.map +1 -0
  24. package/lib/module/channel/useGroupChannelList/reducer.js +174 -0
  25. package/lib/module/channel/useGroupChannelList/reducer.js.map +1 -0
  26. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithCollection.js +120 -0
  27. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithCollection.js.map +1 -0
  28. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithQuery.js +104 -0
  29. package/lib/module/channel/useGroupChannelList/useGroupChannelListWithQuery.js.map +1 -0
  30. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js +4 -5
  31. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.js.map +1 -1
  32. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js +3 -3
  33. package/lib/module/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.js.map +1 -1
  34. package/lib/module/common/useAppFeatures.js +8 -27
  35. package/lib/module/common/useAppFeatures.js.map +1 -1
  36. package/lib/module/common/useMessageOutgoingStatus.js +36 -0
  37. package/lib/module/common/useMessageOutgoingStatus.js.map +1 -0
  38. package/lib/module/handler/useChannelHandler.js +17 -6
  39. package/lib/module/handler/useChannelHandler.js.map +1 -1
  40. package/lib/module/index.js +4 -3
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/types.js.map +1 -1
  43. package/lib/typescript/src/channel/{useGroupChannelList.d.ts → useGroupChannelList/index.d.ts} +1 -1
  44. package/lib/typescript/src/channel/useGroupChannelList/reducer.d.ts +14 -0
  45. package/lib/typescript/src/channel/{useGroupChannelListWithCollection.d.ts → useGroupChannelList/useGroupChannelListWithCollection.d.ts} +1 -1
  46. package/lib/typescript/src/channel/{useGroupChannelListWithQuery.d.ts → useGroupChannelList/useGroupChannelListWithQuery.d.ts} +1 -1
  47. package/lib/typescript/src/common/useMessageOutgoingStatus.d.ts +3 -0
  48. package/lib/typescript/src/handler/useChannelHandler.d.ts +1 -2
  49. package/lib/typescript/src/index.d.ts +4 -3
  50. package/lib/typescript/src/types.d.ts +0 -7
  51. package/package.json +3 -3
  52. package/src/channel/{useGroupChannelList.ts → useGroupChannelList/index.ts} +1 -1
  53. package/src/channel/useGroupChannelList/reducer.ts +154 -0
  54. package/src/channel/useGroupChannelList/useGroupChannelListWithCollection.ts +116 -0
  55. package/src/channel/useGroupChannelList/useGroupChannelListWithQuery.ts +114 -0
  56. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithCollection.ts +14 -20
  57. package/src/channel/useGroupChannelMessages/useGroupChannelMessagesWithQuery.ts +48 -53
  58. package/src/common/useAppFeatures.ts +5 -22
  59. package/src/common/useMessageOutgoingStatus.ts +56 -0
  60. package/src/handler/useChannelHandler.ts +11 -5
  61. package/src/index.ts +4 -3
  62. package/src/types.ts +0 -8
  63. package/lib/commonjs/channel/useGroupChannelList.js.map +0 -1
  64. package/lib/commonjs/channel/useGroupChannelListWithCollection.js +0 -148
  65. package/lib/commonjs/channel/useGroupChannelListWithCollection.js.map +0 -1
  66. package/lib/commonjs/channel/useGroupChannelListWithQuery.js +0 -130
  67. package/lib/commonjs/channel/useGroupChannelListWithQuery.js.map +0 -1
  68. package/lib/module/channel/useGroupChannelList.js.map +0 -1
  69. package/lib/module/channel/useGroupChannelListWithCollection.js +0 -135
  70. package/lib/module/channel/useGroupChannelListWithCollection.js.map +0 -1
  71. package/lib/module/channel/useGroupChannelListWithQuery.js +0 -117
  72. package/lib/module/channel/useGroupChannelListWithQuery.js.map +0 -1
  73. package/src/channel/useGroupChannelListWithCollection.ts +0 -144
  74. package/src/channel/useGroupChannelListWithQuery.ts +0 -124
@@ -0,0 +1,116 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ import type { SendbirdChatSDK, SendbirdGroupChannelCollection } from '@sendbird/uikit-utils';
4
+ import { useAsyncEffect, useFreshCallback, useUniqId } from '@sendbird/uikit-utils';
5
+
6
+ import { useAppFeatures } from '../../common/useAppFeatures';
7
+ import { useChannelHandler } from '../../handler/useChannelHandler';
8
+ import type { UseGroupChannelList, UseGroupChannelListOptions } from '../../types';
9
+ import { useGroupChannelListReducer } from './reducer';
10
+
11
+ const HOOK_NAME = 'useGroupChannelListWithCollection';
12
+
13
+ const createGroupChannelListCollection = (
14
+ sdk: SendbirdChatSDK,
15
+ collectionCreator: UseGroupChannelListOptions['collectionCreator'],
16
+ ) => {
17
+ const passedCollection = collectionCreator?.();
18
+ if (passedCollection) return passedCollection;
19
+
20
+ const defaultOptions = {
21
+ includeEmpty: false,
22
+ limit: 5,
23
+ order: sdk.GroupChannelCollection.GroupChannelOrder.LATEST_LAST_MESSAGE,
24
+ };
25
+ const collectionBuilder = sdk.GroupChannel.createGroupChannelCollection();
26
+ const groupChannelFilter = new sdk.GroupChannelFilter();
27
+ groupChannelFilter.includeEmpty = defaultOptions.includeEmpty;
28
+
29
+ return collectionBuilder
30
+ .setFilter(groupChannelFilter)
31
+ .setLimit(defaultOptions.limit)
32
+ .setOrder(defaultOptions.order)
33
+ .build();
34
+ };
35
+
36
+ export const useGroupChannelListWithCollection: UseGroupChannelList = (sdk, userId, options) => {
37
+ const id = useUniqId(HOOK_NAME);
38
+ const { deliveryReceiptEnabled } = useAppFeatures(sdk);
39
+
40
+ const collectionRef = useRef<SendbirdGroupChannelCollection>();
41
+
42
+ const { loading, groupChannels, refreshing, setChannels, deleteChannels, updateRefreshing, updateLoading } =
43
+ useGroupChannelListReducer();
44
+
45
+ const updateChannelsAndMarkAsDelivered = (markAsDelivered: boolean) => {
46
+ const channels = collectionRef.current?.channelList ?? [];
47
+ setChannels(channels, true);
48
+ if (markAsDelivered && deliveryReceiptEnabled) channels.forEach((channel) => sdk.markAsDelivered(channel.url));
49
+ };
50
+
51
+ const init = useFreshCallback(async (uid?: string) => {
52
+ if (collectionRef.current) collectionRef.current?.dispose();
53
+
54
+ if (uid) {
55
+ collectionRef.current = createGroupChannelListCollection(sdk, options?.collectionCreator);
56
+
57
+ if (collectionRef.current?.hasMore) {
58
+ await collectionRef.current?.loadMore();
59
+ updateChannelsAndMarkAsDelivered(true);
60
+ }
61
+
62
+ collectionRef.current?.setGroupChannelCollectionHandler({
63
+ onChannelsAdded() {
64
+ updateChannelsAndMarkAsDelivered(true);
65
+ },
66
+ onChannelsUpdated() {
67
+ updateChannelsAndMarkAsDelivered(true);
68
+ },
69
+ onChannelsDeleted() {
70
+ updateChannelsAndMarkAsDelivered(false);
71
+ },
72
+ });
73
+ }
74
+ });
75
+
76
+ useEffect(() => {
77
+ return () => {
78
+ if (collectionRef.current) collectionRef.current?.dispose();
79
+ };
80
+ }, []);
81
+
82
+ useAsyncEffect(async () => {
83
+ updateLoading(true);
84
+ await init(userId);
85
+ updateLoading(false);
86
+ }, [init, userId]);
87
+
88
+ useChannelHandler(sdk, `${HOOK_NAME}_${id}`, {
89
+ onUserBanned: (channel, user) => {
90
+ const isMe = user.userId === userId;
91
+ if (isMe) deleteChannels([channel.url]);
92
+ else updateChannelsAndMarkAsDelivered(false);
93
+ },
94
+ });
95
+
96
+ const refresh = useFreshCallback(async () => {
97
+ updateRefreshing(true);
98
+ await init(userId);
99
+ updateRefreshing(false);
100
+ });
101
+
102
+ const next = useFreshCallback(async () => {
103
+ if (collectionRef.current?.hasMore) {
104
+ await collectionRef.current?.loadMore();
105
+ updateChannelsAndMarkAsDelivered(true);
106
+ }
107
+ });
108
+
109
+ return {
110
+ loading,
111
+ groupChannels,
112
+ refresh,
113
+ refreshing,
114
+ next,
115
+ };
116
+ };
@@ -0,0 +1,114 @@
1
+ import { useRef } from 'react';
2
+ import type Sendbird from 'sendbird';
3
+
4
+ import type { SendbirdChannel, SendbirdChatSDK } from '@sendbird/uikit-utils';
5
+ import { useAsyncEffect, useFreshCallback } 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
+ import { useGroupChannelListReducer } from './reducer';
11
+
12
+ const HOOK_NAME = 'useGroupChannelListWithQuery';
13
+
14
+ const createGroupChannelListQuery = (
15
+ sdk: SendbirdChatSDK,
16
+ queryCreator: UseGroupChannelListOptions['queryCreator'],
17
+ ) => {
18
+ const passedQuery = queryCreator?.();
19
+ if (passedQuery) return passedQuery;
20
+
21
+ const defaultOptions = {
22
+ includeEmpty: false,
23
+ limit: 20,
24
+ order: 'latest_last_message',
25
+ } as const;
26
+ const defaultQuery = sdk.GroupChannel.createMyGroupChannelListQuery();
27
+ defaultQuery.limit = defaultOptions.limit;
28
+ defaultQuery.order = defaultOptions.order;
29
+ defaultQuery.includeEmpty = defaultOptions.includeEmpty;
30
+ return defaultQuery;
31
+ };
32
+
33
+ export const useGroupChannelListWithQuery: UseGroupChannelList = (sdk, userId, options) => {
34
+ const { deliveryReceiptEnabled } = useAppFeatures(sdk);
35
+ const queryRef = useRef<Sendbird.GroupChannelListQuery>();
36
+
37
+ const {
38
+ loading,
39
+ groupChannels,
40
+ refreshing,
41
+ updateChannels,
42
+ setChannels,
43
+ deleteChannels,
44
+ updateRefreshing,
45
+ updateLoading,
46
+ updateOrder,
47
+ } = useGroupChannelListReducer();
48
+
49
+ const updateChannelsAndMarkAsDelivered = (channels: SendbirdChannel[]) => {
50
+ updateChannels(channels);
51
+ if (deliveryReceiptEnabled) channels.forEach((channel) => sdk.markAsDelivered(channel.url));
52
+ };
53
+
54
+ const init = useFreshCallback(async (uid?: string) => {
55
+ if (uid) {
56
+ queryRef.current = createGroupChannelListQuery(sdk, options?.queryCreator);
57
+ updateOrder(queryRef.current?.order);
58
+
59
+ if (queryRef.current?.hasNext) {
60
+ const channels = await queryRef.current.next();
61
+
62
+ setChannels(channels, true);
63
+ if (deliveryReceiptEnabled) channels.forEach((channel) => sdk.markAsDelivered(channel.url));
64
+ }
65
+ }
66
+ });
67
+
68
+ useAsyncEffect(async () => {
69
+ updateLoading(true);
70
+ await init(userId);
71
+ updateLoading(false);
72
+ }, [init, userId]);
73
+
74
+ useChannelHandler(sdk, HOOK_NAME, {
75
+ onChannelChanged: (channel) => updateChannelsAndMarkAsDelivered([channel]),
76
+ onChannelFrozen: (channel) => updateChannels([channel]),
77
+ onChannelUnfrozen: (channel) => updateChannels([channel]),
78
+ onChannelMemberCountChanged: (channels) => updateChannels(channels),
79
+ onChannelDeleted: (url) => deleteChannels([url]),
80
+ onUserJoined: (channel) => updateChannelsAndMarkAsDelivered([channel]),
81
+ onUserLeft: (channel, user) => {
82
+ const isMe = user.userId === userId;
83
+ if (isMe) deleteChannels([channel.url]);
84
+ else updateChannelsAndMarkAsDelivered([channel]);
85
+ },
86
+ onUserBanned(channel, user) {
87
+ const isMe = user.userId === userId;
88
+ if (isMe) deleteChannels([channel.url]);
89
+ else updateChannelsAndMarkAsDelivered([channel]);
90
+ },
91
+ });
92
+
93
+ const refresh = useFreshCallback(async () => {
94
+ updateRefreshing(true);
95
+ await init(userId);
96
+ updateRefreshing(false);
97
+ });
98
+
99
+ const next = useFreshCallback(async () => {
100
+ if (queryRef.current?.hasNext) {
101
+ const channels = await queryRef.current.next();
102
+ setChannels(channels, false);
103
+ if (deliveryReceiptEnabled) channels.forEach((channel) => sdk.markAsDelivered(channel.url));
104
+ }
105
+ });
106
+
107
+ return {
108
+ loading,
109
+ groupChannels,
110
+ refresh,
111
+ refreshing,
112
+ next,
113
+ };
114
+ };
@@ -62,18 +62,17 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
62
62
  try {
63
63
  if (deliveryReceiptEnabled) sdk.markAsDelivered(activeChannel.url);
64
64
  } catch (e) {
65
- Logger.error(`[${HOOK_NAME}/channelMarkAs/Delivered]`, e);
65
+ Logger.warn(`[${HOOK_NAME}/channelMarkAs/Delivered]`, e);
66
66
  }
67
67
  try {
68
68
  await sdk.markAsReadWithChannelUrls([activeChannel.url]);
69
69
  } catch (e) {
70
- Logger.error(`[${HOOK_NAME}/channelMarkAs/Read]`, e);
70
+ Logger.warn(`[${HOOK_NAME}/channelMarkAs/Read]`, e);
71
71
  }
72
72
  };
73
73
 
74
74
  const updateChannel = (channel: SendbirdChannel) => {
75
75
  if (channel.isGroupChannel() && !isDifferentChannel(channel, activeChannel)) {
76
- setActiveChannel(channel);
77
76
  forceUpdate();
78
77
  }
79
78
  };
@@ -100,7 +99,7 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
100
99
  }
101
100
  })
102
101
  .onApiResult((err, messages) => {
103
- if (err) Logger.error(`[${HOOK_NAME}/onApiResult]`, err);
102
+ if (err) Logger.warn(`[${HOOK_NAME}/onApiResult]`, err);
104
103
  else {
105
104
  Logger.debug(`[${HOOK_NAME}/onApiResult]`, 'message length:', messages.length);
106
105
  updateMessages(messages, true, sdk.currentUser.userId);
@@ -153,24 +152,19 @@ export const useGroupChannelMessagesWithCollection: UseGroupChannelMessages = (s
153
152
  [sdk, activeChannel.url, options?.collectionCreator],
154
153
  );
155
154
 
156
- useChannelHandler(
157
- sdk,
158
- HOOK_NAME,
159
- {
160
- onUserBanned(channel, bannedUser) {
161
- disposeManuallyAfterUnmounted();
162
- if (channel.isGroupChannel() && !isDifferentChannel(channel, activeChannel)) {
163
- if (bannedUser.userId === sdk.currentUser.userId) {
164
- options?.onChannelDeleted?.();
165
- } else {
166
- setActiveChannel(channel);
167
- forceUpdate();
168
- }
155
+ useChannelHandler(sdk, HOOK_NAME, {
156
+ onUserBanned(channel, bannedUser) {
157
+ disposeManuallyAfterUnmounted();
158
+ if (channel.isGroupChannel() && !isDifferentChannel(channel, activeChannel)) {
159
+ if (bannedUser.userId === sdk.currentUser.userId) {
160
+ options?.onChannelDeleted?.();
161
+ } else {
162
+ setActiveChannel(channel);
163
+ forceUpdate();
169
164
  }
170
- },
165
+ }
171
166
  },
172
- [sdk],
173
- );
167
+ });
174
168
 
175
169
  useEffect(() => {
176
170
  // NOTE: Cache read is heavy synchronous task, and it prevents smooth ui transition
@@ -49,12 +49,12 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
49
49
  try {
50
50
  if (deliveryReceiptEnabled) sdk.markAsDelivered(activeChannel.url);
51
51
  } catch (e) {
52
- Logger.error(`[${HOOK_NAME}/channelMarkAs/Delivered]`, e);
52
+ Logger.warn(`[${HOOK_NAME}/channelMarkAs/Delivered]`, e);
53
53
  }
54
54
  try {
55
55
  await sdk.markAsReadWithChannelUrls([activeChannel.url]);
56
56
  } catch (e) {
57
- Logger.error(`[${HOOK_NAME}/channelMarkAs/Read]`, e);
57
+ Logger.warn(`[${HOOK_NAME}/channelMarkAs/Read]`, e);
58
58
  }
59
59
  };
60
60
 
@@ -80,58 +80,53 @@ export const useGroupChannelMessagesWithQuery: UseGroupChannelMessages = (sdk, c
80
80
  }
81
81
  };
82
82
 
83
- useChannelHandler(
84
- sdk,
85
- HOOK_NAME,
86
- {
87
- // Messages
88
- onMessageReceived(eventChannel, message) {
89
- if (isDifferentChannel(activeChannel, eventChannel)) return;
90
- channelMarkAs();
91
- updateNextMessages([message], false, sdk.currentUser.userId);
92
- },
93
- onMessageUpdated(eventChannel, message) {
94
- if (isDifferentChannel(activeChannel, eventChannel)) return;
95
- updateMessages([message], false, sdk.currentUser.userId);
96
- },
97
- onMessageDeleted(eventChannel, messageId) {
98
- if (isDifferentChannel(activeChannel, eventChannel)) return;
99
- deleteMessages([messageId], []);
100
- deleteNextMessages([messageId], []);
101
- },
102
- // Channels
103
- onChannelChanged: channelUpdater,
104
- onChannelFrozen: channelUpdater,
105
- onChannelUnfrozen: channelUpdater,
106
- onChannelHidden: channelUpdater,
107
- onChannelMemberCountChanged(channels) {
108
- const channel = channels.find((c) => !isDifferentChannel(c, activeChannel));
109
- if (channel) channelUpdater(channel);
110
- },
111
- onChannelDeleted(channelUrl: string) {
112
- if (activeChannel.url === channelUrl) options?.onChannelDeleted?.();
113
- },
114
- // Users
115
- onOperatorUpdated: channelUpdater,
116
- onUserLeft: channelUpdater,
117
- onUserEntered: channelUpdater,
118
- onUserExited: channelUpdater,
119
- onUserJoined: channelUpdater,
120
- onUserUnbanned: channelUpdater,
121
- onUserMuted: channelUpdater,
122
- onUserUnmuted: channelUpdater,
123
- onUserBanned(eventChannel, bannedUser) {
124
- if (isDifferentChannel(activeChannel, eventChannel)) return;
125
-
126
- if (bannedUser.userId === sdk.currentUser.userId) {
127
- options?.onChannelDeleted?.();
128
- } else {
129
- channelUpdater(eventChannel);
130
- }
131
- },
83
+ useChannelHandler(sdk, HOOK_NAME, {
84
+ // Messages
85
+ onMessageReceived(eventChannel, message) {
86
+ if (isDifferentChannel(activeChannel, eventChannel)) return;
87
+ channelMarkAs();
88
+ updateNextMessages([message], false, sdk.currentUser.userId);
132
89
  },
133
- [sdk],
134
- );
90
+ onMessageUpdated(eventChannel, message) {
91
+ if (isDifferentChannel(activeChannel, eventChannel)) return;
92
+ updateMessages([message], false, sdk.currentUser.userId);
93
+ },
94
+ onMessageDeleted(eventChannel, messageId) {
95
+ if (isDifferentChannel(activeChannel, eventChannel)) return;
96
+ deleteMessages([messageId], []);
97
+ deleteNextMessages([messageId], []);
98
+ },
99
+ // Channels
100
+ onChannelChanged: channelUpdater,
101
+ onChannelFrozen: channelUpdater,
102
+ onChannelUnfrozen: channelUpdater,
103
+ onChannelHidden: channelUpdater,
104
+ onChannelMemberCountChanged(channels) {
105
+ const channel = channels.find((c) => !isDifferentChannel(c, activeChannel));
106
+ if (channel) channelUpdater(channel);
107
+ },
108
+ onChannelDeleted(channelUrl: string) {
109
+ if (activeChannel.url === channelUrl) options?.onChannelDeleted?.();
110
+ },
111
+ // Users
112
+ onOperatorUpdated: channelUpdater,
113
+ onUserLeft: channelUpdater,
114
+ onUserEntered: channelUpdater,
115
+ onUserExited: channelUpdater,
116
+ onUserJoined: channelUpdater,
117
+ onUserUnbanned: channelUpdater,
118
+ onUserMuted: channelUpdater,
119
+ onUserUnmuted: channelUpdater,
120
+ onUserBanned(eventChannel, bannedUser) {
121
+ if (isDifferentChannel(activeChannel, eventChannel)) return;
122
+
123
+ if (bannedUser.userId === sdk.currentUser.userId) {
124
+ options?.onChannelDeleted?.();
125
+ } else {
126
+ channelUpdater(eventChannel);
127
+ }
128
+ },
129
+ });
135
130
 
136
131
  useAsyncEffect(async () => {
137
132
  updateLoading(true);
@@ -1,28 +1,11 @@
1
- import { useMemo } from 'react';
2
-
3
1
  import { ApplicationAttributes, PremiumFeatures, SendbirdChatSDK } from '@sendbird/uikit-utils';
4
2
 
5
3
  export const useAppFeatures = (sdk: SendbirdChatSDK) => {
6
- const deliveryReceiptEnabled = useMemo(() => {
7
- return Boolean(sdk.appInfo?.premiumFeatureList?.includes?.(PremiumFeatures.delivery_receipt));
8
- }, [sdk.appInfo?.premiumFeatureList]);
9
-
10
- const broadcastChannelEnabled = useMemo(() => {
11
- return Boolean(sdk.appInfo?.applicationAttributes?.includes?.(ApplicationAttributes.allow_broadcast_channel));
12
- }, [sdk.appInfo?.applicationAttributes]);
13
-
14
- const superGroupChannelEnabled = useMemo(() => {
15
- return Boolean(sdk.appInfo?.applicationAttributes?.includes?.(ApplicationAttributes.allow_super_group_channel));
16
- }, [sdk.appInfo?.applicationAttributes]);
17
-
18
- const reactionEnabled = useMemo(() => {
19
- return Boolean(sdk.appInfo?.applicationAttributes?.includes?.(ApplicationAttributes.reactions));
20
- }, [sdk.appInfo?.applicationAttributes]);
21
-
4
+ const { premiumFeatureList = [], applicationAttributes = [] } = sdk.appInfo ?? {};
22
5
  return {
23
- deliveryReceiptEnabled,
24
- broadcastChannelEnabled,
25
- superGroupChannelEnabled,
26
- reactionEnabled,
6
+ deliveryReceiptEnabled: Boolean(premiumFeatureList.includes(PremiumFeatures.delivery_receipt)),
7
+ broadcastChannelEnabled: Boolean(applicationAttributes.includes(ApplicationAttributes.allow_broadcast_channel)),
8
+ superGroupChannelEnabled: Boolean(applicationAttributes.includes(ApplicationAttributes.allow_super_group_channel)),
9
+ reactionEnabled: Boolean(applicationAttributes.includes(ApplicationAttributes.reactions)),
27
10
  };
28
11
  };
@@ -0,0 +1,56 @@
1
+ import type {
2
+ SendbirdAdminMessage,
3
+ SendbirdChatSDK,
4
+ SendbirdFileMessage,
5
+ SendbirdGroupChannel,
6
+ SendbirdUserMessage,
7
+ } from '@sendbird/uikit-utils';
8
+ import { isDifferentChannel, isMyMessage, useForceUpdate, useUniqId } from '@sendbird/uikit-utils';
9
+
10
+ import { useChannelHandler } from '../handler/useChannelHandler';
11
+ import { useAppFeatures } from './useAppFeatures';
12
+
13
+ const HOOK_NAME = 'useMessageOutgoingStatus';
14
+
15
+ export type SBUOutgoingStatus = 'NONE' | 'PENDING' | 'FAILED' | 'UNDELIVERED' | 'DELIVERED' | 'UNREAD' | 'READ';
16
+
17
+ export const useMessageOutgoingStatus = (
18
+ sdk: SendbirdChatSDK,
19
+ channel: SendbirdGroupChannel,
20
+ message?: SendbirdFileMessage | SendbirdUserMessage | SendbirdAdminMessage | null,
21
+ ): SBUOutgoingStatus => {
22
+ const features = useAppFeatures(sdk);
23
+ const forceUpdate = useForceUpdate();
24
+ const currentUser = sdk.currentUser;
25
+
26
+ const uniqId = useUniqId(HOOK_NAME);
27
+ useChannelHandler(sdk, `${HOOK_NAME}_${uniqId}`, {
28
+ onDeliveryReceiptUpdated(eventChannel) {
29
+ if (isDifferentChannel(channel, eventChannel)) return;
30
+ if (!isMyMessage(message, currentUser?.userId)) return;
31
+
32
+ forceUpdate();
33
+ },
34
+ onReadReceiptUpdated(eventChannel) {
35
+ if (isDifferentChannel(channel, eventChannel)) return;
36
+ if (!isMyMessage(message, currentUser?.userId)) return;
37
+
38
+ forceUpdate();
39
+ },
40
+ });
41
+
42
+ if (!message) return 'NONE';
43
+
44
+ if (message.sendingStatus === 'pending') return 'PENDING';
45
+
46
+ if (message.sendingStatus === 'failed') return 'FAILED';
47
+
48
+ if (channel.getUnreadMemberCount(message) === 0) return 'READ';
49
+
50
+ if (features.deliveryReceiptEnabled) {
51
+ if (channel.getUndeliveredMemberCount(message) === 0) return 'DELIVERED';
52
+ return 'UNDELIVERED';
53
+ }
54
+
55
+ return 'UNREAD';
56
+ };
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from 'react';
1
+ import { useEffect, useLayoutEffect, useRef } from 'react';
2
2
  import type Sendbird from 'sendbird';
3
3
 
4
4
  import { Logger, SendbirdChatSDK } from '@sendbird/uikit-utils';
@@ -7,19 +7,25 @@ export const useChannelHandler = (
7
7
  sdk: SendbirdChatSDK,
8
8
  handlerId: string,
9
9
  hookHandler: Partial<Sendbird.ChannelHandler>,
10
- deps: React.DependencyList = [],
11
10
  ) => {
11
+ const handlerRef = useRef(hookHandler);
12
+ useLayoutEffect(() => {
13
+ handlerRef.current = hookHandler;
14
+ });
15
+
12
16
  useEffect(() => {
13
17
  Logger.debug('[useChannelHandler] hook called by', handlerId);
14
18
 
15
19
  const handler = new sdk.ChannelHandler();
16
20
  const handlerKeys = Object.keys(handler) as (keyof typeof handler)[];
17
21
  handlerKeys.forEach((key) => {
18
- const hookHandlerFn = hookHandler[key];
19
- if (hookHandlerFn) handler[key] = hookHandlerFn as () => unknown;
22
+ handler[key] = (...args: unknown[]) => {
23
+ // @ts-ignore
24
+ handlerRef.current[key]?.(...args);
25
+ };
20
26
  });
21
27
 
22
28
  sdk.addChannelHandler(handlerId, handler);
23
29
  return () => sdk.removeChannelHandler(handlerId);
24
- }, [sdk, handlerId, ...deps]);
30
+ }, [sdk, handlerId]);
25
31
  };
package/src/index.ts CHANGED
@@ -2,11 +2,12 @@ export { useGroupChannelList } from './channel/useGroupChannelList';
2
2
  export { useGroupChannelMessages } from './channel/useGroupChannelMessages';
3
3
  export { useActiveGroupChannel } from './channel/useActiveGroupChannel';
4
4
 
5
- export { useUserList } from './common/useUserList';
5
+ export { useAppFeatures } from './common/useAppFeatures';
6
+ export { useMessageOutgoingStatus } from './common/useMessageOutgoingStatus';
6
7
  export { usePushTrigger } from './common/usePushTrigger';
7
- export { useTotalUnreadMessageCount } from './common/useTotalUnreadMessageCount';
8
8
  export { useTotalUnreadChannelCount } from './common/useTotalUnreadChannelCount';
9
- export { useAppFeatures } from './common/useAppFeatures';
9
+ export { useTotalUnreadMessageCount } from './common/useTotalUnreadMessageCount';
10
+ export { useUserList } from './common/useUserList';
10
11
 
11
12
  export { useChannelHandler } from './handler/useChannelHandler';
12
13
  export { useConnectionHandler } from './handler/useConnectionHandler';
package/src/types.ts CHANGED
@@ -48,13 +48,6 @@ export interface UseGroupChannelList {
48
48
  * */
49
49
  refresh: () => Promise<void>;
50
50
 
51
- /**
52
- * Update channel, update or insert channel to state
53
- * @param {SendbirdGroupChannel} channel
54
- * @return {void}
55
- * */
56
- update: (channel: SendbirdGroupChannel) => void;
57
-
58
51
  /**
59
52
  * Get group channels state
60
53
  * */
@@ -68,7 +61,6 @@ export interface UseGroupChannelList {
68
61
  };
69
62
  }
70
63
  export type UseGroupChannelListOptions = {
71
- sortComparator?: (a: SendbirdGroupChannel, b: SendbirdGroupChannel) => number;
72
64
  queryCreator?: () => Sendbird.GroupChannelListQuery;
73
65
  collectionCreator?: () => SendbirdGroupChannelCollection;
74
66
  enableCollectionWithoutLocalCache?: boolean;
@@ -1 +0,0 @@
1
- {"version":3,"names":["useGroupChannelList","sdk","userId","options","isCacheEnabled","enableCollectionWithoutLocalCache","useGroupChannelListWithCollection","useGroupChannelListWithQuery"],"sources":["useGroupChannelList.ts"],"sourcesContent":["import type { UseGroupChannelList } from '../types';\nimport { useGroupChannelListWithCollection } from './useGroupChannelListWithCollection';\nimport { useGroupChannelListWithQuery } from './useGroupChannelListWithQuery';\n\nexport const useGroupChannelList: UseGroupChannelList = (sdk, userId, options) => {\n if (sdk.isCacheEnabled || options?.enableCollectionWithoutLocalCache) {\n return useGroupChannelListWithCollection(sdk, userId, options);\n } else {\n return useGroupChannelListWithQuery(sdk, userId, options);\n }\n};\n"],"mappings":";;;;;;;AACA;;AACA;;AAEO,MAAMA,mBAAwC,GAAG,CAACC,GAAD,EAAMC,MAAN,EAAcC,OAAd,KAA0B;EAChF,IAAIF,GAAG,CAACG,cAAJ,IAAsBD,OAAtB,aAAsBA,OAAtB,eAAsBA,OAAO,CAAEE,iCAAnC,EAAsE;IACpE,OAAO,IAAAC,oEAAA,EAAkCL,GAAlC,EAAuCC,MAAvC,EAA+CC,OAA/C,CAAP;EACD,CAFD,MAEO;IACL,OAAO,IAAAI,0DAAA,EAA6BN,GAA7B,EAAkCC,MAAlC,EAA0CC,OAA1C,CAAP;EACD;AACF,CANM"}