@amityco/ts-sdk-react-native 7.22.1-c05e1197.0 → 7.23.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 (240) hide show
  1. package/dist/@types/core/errors.d.ts +3 -1
  2. package/dist/@types/core/errors.d.ts.map +1 -1
  3. package/dist/@types/core/events.d.ts +7 -1
  4. package/dist/@types/core/events.d.ts.map +1 -1
  5. package/dist/@types/core/model.d.ts +4 -0
  6. package/dist/@types/core/model.d.ts.map +1 -1
  7. package/dist/@types/core/payload.d.ts +15 -0
  8. package/dist/@types/core/payload.d.ts.map +1 -1
  9. package/dist/@types/core/transport.d.ts +1 -0
  10. package/dist/@types/core/transport.d.ts.map +1 -1
  11. package/dist/@types/domains/analytics.d.ts +3 -2
  12. package/dist/@types/domains/analytics.d.ts.map +1 -1
  13. package/dist/@types/domains/block.d.ts +5 -0
  14. package/dist/@types/domains/block.d.ts.map +1 -1
  15. package/dist/@types/domains/channel.d.ts +31 -0
  16. package/dist/@types/domains/channel.d.ts.map +1 -1
  17. package/dist/@types/domains/client.d.ts +31 -2
  18. package/dist/@types/domains/client.d.ts.map +1 -1
  19. package/dist/@types/domains/comment.d.ts +1 -0
  20. package/dist/@types/domains/comment.d.ts.map +1 -1
  21. package/dist/@types/domains/feed.d.ts +14 -0
  22. package/dist/@types/domains/feed.d.ts.map +1 -1
  23. package/dist/@types/domains/message.d.ts +16 -0
  24. package/dist/@types/domains/message.d.ts.map +1 -1
  25. package/dist/@types/domains/notificationSettings.d.ts +101 -0
  26. package/dist/@types/domains/notificationSettings.d.ts.map +1 -0
  27. package/dist/@types/domains/post.d.ts +2 -0
  28. package/dist/@types/domains/post.d.ts.map +1 -1
  29. package/dist/@types/domains/sharableContentType.d.ts +9 -0
  30. package/dist/@types/domains/sharableContentType.d.ts.map +1 -0
  31. package/dist/@types/index.d.ts +3 -1
  32. package/dist/@types/index.d.ts.map +1 -1
  33. package/dist/analytic/service/analytic/AnalyticsEngine.d.ts +1 -0
  34. package/dist/analytic/service/analytic/AnalyticsEngine.d.ts.map +1 -1
  35. package/dist/analytic/service/analytic/AnalyticsEventCapturer.d.ts +2 -1
  36. package/dist/analytic/service/analytic/AnalyticsEventCapturer.d.ts.map +1 -1
  37. package/dist/analytic/service/analytic/AnalyticsService.d.ts +1 -0
  38. package/dist/analytic/service/analytic/AnalyticsService.d.ts.map +1 -1
  39. package/dist/channelRepository/api/archiveChannel.d.ts +16 -0
  40. package/dist/channelRepository/api/archiveChannel.d.ts.map +1 -0
  41. package/dist/channelRepository/api/getArchivedChannelIds.d.ts +13 -0
  42. package/dist/channelRepository/api/getArchivedChannelIds.d.ts.map +1 -0
  43. package/dist/channelRepository/api/index.d.ts +3 -0
  44. package/dist/channelRepository/api/index.d.ts.map +1 -1
  45. package/dist/channelRepository/api/unarchiveChannel.d.ts +16 -0
  46. package/dist/channelRepository/api/unarchiveChannel.d.ts.map +1 -0
  47. package/dist/channelRepository/api/updateChannel.d.ts +1 -1
  48. package/dist/channelRepository/api/updateChannel.d.ts.map +1 -1
  49. package/dist/channelRepository/channelMembership/observers/getMembers/ChannelMemberQueryStreamController.d.ts.map +1 -1
  50. package/dist/channelRepository/channelModeration/api/banMembers.d.ts.map +1 -1
  51. package/dist/channelRepository/channelModeration/api/muteMembers.d.ts.map +1 -1
  52. package/dist/channelRepository/channelModeration/api/unbanMembers.d.ts.map +1 -1
  53. package/dist/channelRepository/channelModeration/api/unmuteMembers.d.ts.map +1 -1
  54. package/dist/channelRepository/events/index.d.ts +2 -0
  55. package/dist/channelRepository/events/index.d.ts.map +1 -1
  56. package/dist/channelRepository/events/onChannelArchived.d.ts +10 -0
  57. package/dist/channelRepository/events/onChannelArchived.d.ts.map +1 -0
  58. package/dist/channelRepository/events/onChannelMemberRoleRemoved.d.ts.map +1 -1
  59. package/dist/channelRepository/events/onChannelUnarchived.d.ts +11 -0
  60. package/dist/channelRepository/events/onChannelUnarchived.d.ts.map +1 -0
  61. package/dist/channelRepository/observers/getArchivedChannels/ArchivedChannelLiveCollectionController.d.ts +12 -0
  62. package/dist/channelRepository/observers/getArchivedChannels/ArchivedChannelLiveCollectionController.d.ts.map +1 -0
  63. package/dist/channelRepository/observers/getArchivedChannels/ArchivedChannelPaginationController.d.ts +11 -0
  64. package/dist/channelRepository/observers/getArchivedChannels/ArchivedChannelPaginationController.d.ts.map +1 -0
  65. package/dist/channelRepository/observers/getArchivedChannels/ArchivedChannelQueryStreamController.d.ts +13 -0
  66. package/dist/channelRepository/observers/getArchivedChannels/ArchivedChannelQueryStreamController.d.ts.map +1 -0
  67. package/dist/channelRepository/observers/getArchivedChannels/getArchivedChannels.d.ts +20 -0
  68. package/dist/channelRepository/observers/getArchivedChannels/getArchivedChannels.d.ts.map +1 -0
  69. package/dist/channelRepository/observers/getArchivedChannels/index.d.ts +2 -0
  70. package/dist/channelRepository/observers/getArchivedChannels/index.d.ts.map +1 -0
  71. package/dist/channelRepository/observers/getChannels/ChannelLiveCollectionController.d.ts.map +1 -1
  72. package/dist/channelRepository/observers/getChannels/ChannelQueryStreamController.d.ts.map +1 -1
  73. package/dist/channelRepository/observers/index.d.ts +2 -0
  74. package/dist/channelRepository/observers/index.d.ts.map +1 -1
  75. package/dist/channelRepository/observers/searchChannels/SearchChannelLiveCollectionController.d.ts +14 -0
  76. package/dist/channelRepository/observers/searchChannels/SearchChannelLiveCollectionController.d.ts.map +1 -0
  77. package/dist/channelRepository/observers/searchChannels/SearchChannelPaginationController.d.ts +10 -0
  78. package/dist/channelRepository/observers/searchChannels/SearchChannelPaginationController.d.ts.map +1 -0
  79. package/dist/channelRepository/observers/searchChannels/SearchChannelQueryStreamController.d.ts +13 -0
  80. package/dist/channelRepository/observers/searchChannels/SearchChannelQueryStreamController.d.ts.map +1 -0
  81. package/dist/channelRepository/observers/searchChannels.d.ts +21 -0
  82. package/dist/channelRepository/observers/searchChannels.d.ts.map +1 -0
  83. package/dist/channelRepository/observers/tests/integrations/searchChannels.integration.test.d.ts +2 -0
  84. package/dist/channelRepository/observers/tests/integrations/searchChannels.integration.test.d.ts.map +1 -0
  85. package/dist/channelRepository/utils/prepareChannelPayload.d.ts.map +1 -1
  86. package/dist/client/api/autoSubscription.d.ts +47 -0
  87. package/dist/client/api/autoSubscription.d.ts.map +1 -0
  88. package/dist/client/api/createClient.d.ts.map +1 -1
  89. package/dist/client/api/getCoreUserSettings.d.ts +16 -0
  90. package/dist/client/api/getCoreUserSettings.d.ts.map +1 -0
  91. package/dist/client/api/getForYouFeedSetting.d.ts +17 -0
  92. package/dist/client/api/getForYouFeedSetting.d.ts.map +1 -0
  93. package/dist/client/api/getShareableLinkConfiguration.d.ts.map +1 -1
  94. package/dist/client/api/index.d.ts +5 -0
  95. package/dist/client/api/index.d.ts.map +1 -1
  96. package/dist/client/api/notifications.d.ts +27 -0
  97. package/dist/client/api/notifications.d.ts.map +1 -0
  98. package/dist/client/api/setupLoginSubscriptions.d.ts.map +1 -1
  99. package/dist/client/api/tests/ShareableLinkConfiguration.test.d.ts +2 -0
  100. package/dist/client/api/tests/ShareableLinkConfiguration.test.d.ts.map +1 -0
  101. package/dist/client/api/tests/notifications.integration.test.d.ts +2 -0
  102. package/dist/client/api/tests/notifications.integration.test.d.ts.map +1 -0
  103. package/dist/client/services/ReadReceiptSync/readReceiptSyncEngine.d.ts.map +1 -1
  104. package/dist/client/utils/autoSubscriptionManager.d.ts +21 -0
  105. package/dist/client/utils/autoSubscriptionManager.d.ts.map +1 -0
  106. package/dist/client/utils/subscribeGlobalTopic.d.ts +6 -1
  107. package/dist/client/utils/subscribeGlobalTopic.d.ts.map +1 -1
  108. package/dist/client/utils/tests/autoSubscriptionManager.test.d.ts +2 -0
  109. package/dist/client/utils/tests/autoSubscriptionManager.test.d.ts.map +1 -0
  110. package/dist/commentRepository/observers/getComments/CommentLiveCollectionController.d.ts.map +1 -1
  111. package/dist/commentRepository/observers/tests/integrations/getCommentsExcludeBlockUser.integration.test.d.ts +2 -0
  112. package/dist/commentRepository/observers/tests/integrations/getCommentsExcludeBlockUser.integration.test.d.ts.map +1 -0
  113. package/dist/core/events.d.ts +3 -3
  114. package/dist/core/events.d.ts.map +1 -1
  115. package/dist/core/model/idResolvers.d.ts.map +1 -1
  116. package/dist/core/model/index.d.ts.map +1 -1
  117. package/dist/core/query/filtering.d.ts +32 -0
  118. package/dist/core/query/filtering.d.ts.map +1 -1
  119. package/dist/core/query/paging.d.ts +1 -0
  120. package/dist/core/query/paging.d.ts.map +1 -1
  121. package/dist/core/subscription.d.ts +3 -0
  122. package/dist/core/subscription.d.ts.map +1 -1
  123. package/dist/feedRepository/errors/AmityForYouFeedDisabledError.d.ts +13 -0
  124. package/dist/feedRepository/errors/AmityForYouFeedDisabledError.d.ts.map +1 -0
  125. package/dist/feedRepository/index.d.ts +2 -1
  126. package/dist/feedRepository/index.d.ts.map +1 -1
  127. package/dist/feedRepository/observers/getForYouFeed/CursorController.d.ts +19 -0
  128. package/dist/feedRepository/observers/getForYouFeed/CursorController.d.ts.map +1 -0
  129. package/dist/feedRepository/observers/getForYouFeed/LiveCollectionController.d.ts +13 -0
  130. package/dist/feedRepository/observers/getForYouFeed/LiveCollectionController.d.ts.map +1 -0
  131. package/dist/feedRepository/observers/getForYouFeed/PaginationController.d.ts +13 -0
  132. package/dist/feedRepository/observers/getForYouFeed/PaginationController.d.ts.map +1 -0
  133. package/dist/feedRepository/observers/getForYouFeed/QueryStreamController.d.ts +15 -0
  134. package/dist/feedRepository/observers/getForYouFeed/QueryStreamController.d.ts.map +1 -0
  135. package/dist/feedRepository/observers/getForYouFeed.d.ts +19 -0
  136. package/dist/feedRepository/observers/getForYouFeed.d.ts.map +1 -0
  137. package/dist/feedRepository/observers/index.d.ts +1 -0
  138. package/dist/feedRepository/observers/index.d.ts.map +1 -1
  139. package/dist/feedRepository/observers/tests/integration/getForYouFeed.integration.test.d.ts +2 -0
  140. package/dist/feedRepository/observers/tests/integration/getForYouFeed.integration.test.d.ts.map +1 -0
  141. package/dist/feedRepository/observers/tests/unit/CursorController.test.d.ts +2 -0
  142. package/dist/feedRepository/observers/tests/unit/CursorController.test.d.ts.map +1 -0
  143. package/dist/fileRepository/api/uploadAudio.d.ts +1 -1
  144. package/dist/fileRepository/api/uploadAudio.d.ts.map +1 -1
  145. package/dist/fileRepository/api/uploadClip.d.ts +1 -1
  146. package/dist/fileRepository/api/uploadClip.d.ts.map +1 -1
  147. package/dist/fileRepository/api/uploadFile.d.ts +1 -1
  148. package/dist/fileRepository/api/uploadFile.d.ts.map +1 -1
  149. package/dist/fileRepository/api/uploadImage.d.ts +1 -1
  150. package/dist/fileRepository/api/uploadImage.d.ts.map +1 -1
  151. package/dist/fileRepository/api/uploadVideo.d.ts +1 -1
  152. package/dist/fileRepository/api/uploadVideo.d.ts.map +1 -1
  153. package/dist/index.cjs.js +2755 -592
  154. package/dist/index.esm.js +2752 -592
  155. package/dist/index.umd.js +3 -3
  156. package/dist/messagePreview/utils/getChannelMessagePreviewWithUser.d.ts +1 -0
  157. package/dist/messagePreview/utils/getChannelMessagePreviewWithUser.d.ts.map +1 -1
  158. package/dist/messagePreview/utils/updateChannelMessagePreviewCache.d.ts.map +1 -1
  159. package/dist/messageRepository/events/onMessageCreated.d.ts.map +1 -1
  160. package/dist/messageRepository/observers/index.d.ts +1 -0
  161. package/dist/messageRepository/observers/index.d.ts.map +1 -1
  162. package/dist/messageRepository/observers/searchMessage/SearchMessageLiveCollectionController.d.ts +12 -0
  163. package/dist/messageRepository/observers/searchMessage/SearchMessageLiveCollectionController.d.ts.map +1 -0
  164. package/dist/messageRepository/observers/searchMessage/SearchMessagePaginationController.d.ts +10 -0
  165. package/dist/messageRepository/observers/searchMessage/SearchMessagePaginationController.d.ts.map +1 -0
  166. package/dist/messageRepository/observers/searchMessage/SearchMessageQueryStreamController.d.ts +8 -0
  167. package/dist/messageRepository/observers/searchMessage/SearchMessageQueryStreamController.d.ts.map +1 -0
  168. package/dist/messageRepository/observers/searchMessage/index.d.ts +2 -0
  169. package/dist/messageRepository/observers/searchMessage/index.d.ts.map +1 -0
  170. package/dist/messageRepository/observers/searchMessage/searchMessage.d.ts +24 -0
  171. package/dist/messageRepository/observers/searchMessage/searchMessage.d.ts.map +1 -0
  172. package/dist/postRepository/observers/getPosts/PostLiveCollectionController.d.ts.map +1 -1
  173. package/dist/postRepository/observers/tests/getPostsExcludeBlockUser.test.d.ts +2 -0
  174. package/dist/postRepository/observers/tests/getPostsExcludeBlockUser.test.d.ts.map +1 -0
  175. package/dist/postRepository/tests/integration/postAnalytics.integration.test.d.ts +2 -0
  176. package/dist/postRepository/tests/integration/postAnalytics.integration.test.d.ts.map +1 -0
  177. package/dist/postRepository/tests/integration/setup.d.ts +6 -0
  178. package/dist/postRepository/tests/integration/setup.d.ts.map +1 -0
  179. package/dist/reactionRepository/internalApi/addReaction.d.ts.map +1 -1
  180. package/dist/reactionRepository/internalApi/removeReaction.d.ts.map +1 -1
  181. package/dist/streamRepository/observers/getStreams/GetStreamsPageController.d.ts +1 -0
  182. package/dist/streamRepository/observers/getStreams/GetStreamsPageController.d.ts.map +1 -1
  183. package/dist/userRepository/api/getAllBlockedUsers.d.ts.map +1 -1
  184. package/dist/userRepository/api/getAllBlockingUsers.d.ts +20 -0
  185. package/dist/userRepository/api/getAllBlockingUsers.d.ts.map +1 -0
  186. package/dist/userRepository/api/index.d.ts +1 -0
  187. package/dist/userRepository/api/index.d.ts.map +1 -1
  188. package/dist/userRepository/api/tests/integration/getAllBlockingUsers.integration.test.d.ts +2 -0
  189. package/dist/userRepository/api/tests/integration/getAllBlockingUsers.integration.test.d.ts.map +1 -0
  190. package/dist/userRepository/observers/getBlockedUsers/BlockedUserLiveCollectionController.d.ts.map +1 -1
  191. package/dist/userRepository/observers/getBlockedUsers/BlockedUserQueryStreamController.d.ts +4 -3
  192. package/dist/userRepository/observers/getBlockedUsers/BlockedUserQueryStreamController.d.ts.map +1 -1
  193. package/dist/userRepository/observers/getBlockingUsers/LiveCollectionController.d.ts +13 -0
  194. package/dist/userRepository/observers/getBlockingUsers/LiveCollectionController.d.ts.map +1 -0
  195. package/dist/userRepository/observers/getBlockingUsers/PaginationController.d.ts +5 -0
  196. package/dist/userRepository/observers/getBlockingUsers/PaginationController.d.ts.map +1 -0
  197. package/dist/userRepository/observers/getBlockingUsers/QueryStreamController.d.ts +16 -0
  198. package/dist/userRepository/observers/getBlockingUsers/QueryStreamController.d.ts.map +1 -0
  199. package/dist/userRepository/observers/getBlockingUsers.d.ts +17 -0
  200. package/dist/userRepository/observers/getBlockingUsers.d.ts.map +1 -0
  201. package/dist/userRepository/observers/index.d.ts +1 -0
  202. package/dist/userRepository/observers/index.d.ts.map +1 -1
  203. package/dist/userRepository/observers/tests/integrations/getBlockingUsers.integration.test.d.ts +2 -0
  204. package/dist/userRepository/observers/tests/integrations/getBlockingUsers.integration.test.d.ts.map +1 -0
  205. package/dist/userRepository/relationship/block/enum/index.d.ts +5 -0
  206. package/dist/userRepository/relationship/block/enum/index.d.ts.map +1 -0
  207. package/dist/userRepository/relationship/block/events/index.d.ts +3 -0
  208. package/dist/userRepository/relationship/block/events/index.d.ts.map +1 -0
  209. package/dist/userRepository/relationship/block/events/onUserDidBlock.d.ts +20 -0
  210. package/dist/userRepository/relationship/block/events/onUserDidBlock.d.ts.map +1 -0
  211. package/dist/userRepository/relationship/block/events/onUserDidUnblock.d.ts +20 -0
  212. package/dist/userRepository/relationship/block/events/onUserDidUnblock.d.ts.map +1 -0
  213. package/dist/userRepository/relationship/block/index.d.ts +1 -0
  214. package/dist/userRepository/relationship/block/index.d.ts.map +1 -1
  215. package/dist/userRepository/relationship/block/utils/blockRealtimeOnLoginHandler.d.ts +12 -0
  216. package/dist/userRepository/relationship/block/utils/blockRealtimeOnLoginHandler.d.ts.map +1 -0
  217. package/dist/userRepository/relationship/block/utils/createBlockEventSubscriber.d.ts +11 -0
  218. package/dist/userRepository/relationship/block/utils/createBlockEventSubscriber.d.ts.map +1 -0
  219. package/dist/userRepository/services/BlockedUserSyncEngine/blockedUserSyncEngine.d.ts +13 -13
  220. package/dist/userRepository/services/BlockedUserSyncEngine/blockedUserSyncEngine.d.ts.map +1 -1
  221. package/dist/userRepository/services/BlockingUserSyncEngine/blockingUserSyncEngine.d.ts +56 -0
  222. package/dist/userRepository/services/BlockingUserSyncEngine/blockingUserSyncEngine.d.ts.map +1 -0
  223. package/dist/userRepository/services/BlockingUserSyncEngine/blockingUserSyncEngineOnLoginHandler.d.ts +3 -0
  224. package/dist/userRepository/services/BlockingUserSyncEngine/blockingUserSyncEngineOnLoginHandler.d.ts.map +1 -0
  225. package/dist/userRepository/utils/prepareBlockingUserPayload.d.ts +2 -0
  226. package/dist/userRepository/utils/prepareBlockingUserPayload.d.ts.map +1 -0
  227. package/dist/utils/constants.d.ts +4 -0
  228. package/dist/utils/constants.d.ts.map +1 -1
  229. package/dist/utils/linkedObject/channelLinkedObject.d.ts.map +1 -1
  230. package/dist/utils/linkedObject/postLinkedObject.d.ts.map +1 -1
  231. package/dist/utils/tests/dummy/block.d.ts +16 -0
  232. package/dist/utils/tests/dummy/block.d.ts.map +1 -1
  233. package/dist/utils/tests/dummy/community.d.ts +2 -0
  234. package/dist/utils/tests/dummy/community.d.ts.map +1 -1
  235. package/dist/utils/tests/dummy/post.d.ts.map +1 -1
  236. package/package.json +1 -1
  237. package/dist/fileRepository/utils/getUploadRequestConfig.d.ts +0 -33
  238. package/dist/fileRepository/utils/getUploadRequestConfig.d.ts.map +0 -1
  239. package/dist/fileRepository/utils/recreateUploadFormData.d.ts +0 -37
  240. package/dist/fileRepository/utils/recreateUploadFormData.d.ts.map +0 -1
package/dist/index.esm.js CHANGED
@@ -8,7 +8,6 @@ import uuid$1 from 'react-native-uuid';
8
8
  import jwtDecode from 'jwt-decode';
9
9
  import { Platform } from 'react-native';
10
10
  import hash from 'object-hash';
11
- import mime from 'mime';
12
11
  import Hls from 'hls.js';
13
12
 
14
13
  var MembershipAcceptanceTypeEnum;
@@ -16,6 +15,13 @@ var MembershipAcceptanceTypeEnum;
16
15
  MembershipAcceptanceTypeEnum["AUTOMATIC"] = "automatic";
17
16
  MembershipAcceptanceTypeEnum["INVITATION"] = "invitation";
18
17
  })(MembershipAcceptanceTypeEnum || (MembershipAcceptanceTypeEnum = {}));
18
+ var AmityAutoSubscription;
19
+ (function (AmityAutoSubscription) {
20
+ AmityAutoSubscription["CHAT"] = "chat";
21
+ AmityAutoSubscription["NETWORK"] = "network";
22
+ AmityAutoSubscription["LIVESTREAM"] = "livestream";
23
+ AmityAutoSubscription["BLOCK"] = "block";
24
+ })(AmityAutoSubscription || (AmityAutoSubscription = {}));
19
25
 
20
26
  var UserTypeEnum;
21
27
  (function (UserTypeEnum) {
@@ -62,6 +68,13 @@ var FileAccessTypeEnum;
62
68
  FileAccessTypeEnum["NETWORK"] = "network";
63
69
  })(FileAccessTypeEnum || (FileAccessTypeEnum = {}));
64
70
 
71
+ var AmityChannelNotificationModeEnum;
72
+ (function (AmityChannelNotificationModeEnum) {
73
+ AmityChannelNotificationModeEnum["Default"] = "default";
74
+ AmityChannelNotificationModeEnum["Silent"] = "silent";
75
+ AmityChannelNotificationModeEnum["Subscribe"] = "subscribe";
76
+ })(AmityChannelNotificationModeEnum || (AmityChannelNotificationModeEnum = {}));
77
+
65
78
  const CommunityPostSettings = Object.freeze({
66
79
  ONLY_ADMIN_CAN_POST: 'ONLY_ADMIN_CAN_POST',
67
80
  ADMIN_REVIEW_POST_REQUIRED: 'ADMIN_REVIEW_POST_REQUIRED',
@@ -237,16 +250,58 @@ var AmityEventOrderOption;
237
250
  AmityEventOrderOption["Descending"] = "desc";
238
251
  })(AmityEventOrderOption || (AmityEventOrderOption = {}));
239
252
 
253
+ var AmitySharableContentType;
254
+ (function (AmitySharableContentType) {
255
+ AmitySharableContentType["POST"] = "post";
256
+ AmitySharableContentType["COMMUNITY"] = "community";
257
+ AmitySharableContentType["USER"] = "user";
258
+ AmitySharableContentType["LIVESTREAM"] = "livestream";
259
+ AmitySharableContentType["EVENT"] = "event";
260
+ })(AmitySharableContentType || (AmitySharableContentType = {}));
261
+
240
262
  var AnalyticsSourceTypeEnum;
241
263
  (function (AnalyticsSourceTypeEnum) {
242
264
  AnalyticsSourceTypeEnum["POST"] = "post";
243
265
  AnalyticsSourceTypeEnum["ROOM"] = "room";
244
266
  })(AnalyticsSourceTypeEnum || (AnalyticsSourceTypeEnum = {}));
245
267
 
268
+ var UserNotificationModuleNameEnum;
269
+ (function (UserNotificationModuleNameEnum) {
270
+ UserNotificationModuleNameEnum["CHAT"] = "chat";
271
+ UserNotificationModuleNameEnum["SOCIAL"] = "social";
272
+ UserNotificationModuleNameEnum["VIDEO_STREAMING"] = "video-streaming";
273
+ })(UserNotificationModuleNameEnum || (UserNotificationModuleNameEnum = {}));
274
+ var CommunityNotificationEventNameEnum;
275
+ (function (CommunityNotificationEventNameEnum) {
276
+ CommunityNotificationEventNameEnum["POST_CREATED"] = "post.created";
277
+ CommunityNotificationEventNameEnum["POST_REACTED"] = "post.reacted";
278
+ CommunityNotificationEventNameEnum["COMMENT_CREATED"] = "comment.created";
279
+ CommunityNotificationEventNameEnum["COMMENT_REPLIED"] = "comment.replied";
280
+ CommunityNotificationEventNameEnum["COMMENT_REACTED"] = "comment.reacted";
281
+ CommunityNotificationEventNameEnum["STORY_CREATED"] = "story.created";
282
+ CommunityNotificationEventNameEnum["STORY_REACTED"] = "story.reacted";
283
+ CommunityNotificationEventNameEnum["STORY_COMMENT_CREATED"] = "story-comment.created";
284
+ CommunityNotificationEventNameEnum["LIVESTREAM_START"] = "video-streaming.didStart";
285
+ })(CommunityNotificationEventNameEnum || (CommunityNotificationEventNameEnum = {}));
286
+ var NotificationSettingsLevelEnum;
287
+ (function (NotificationSettingsLevelEnum) {
288
+ NotificationSettingsLevelEnum["USER"] = "user";
289
+ NotificationSettingsLevelEnum["COMMUNITY"] = "community";
290
+ NotificationSettingsLevelEnum["CHANNEL"] = "channel";
291
+ })(NotificationSettingsLevelEnum || (NotificationSettingsLevelEnum = {}));
292
+ /**
293
+ * `NOT` variant is intentionally excluded from public API (internal server-side use only).
294
+ */
295
+ var NotificationRolesFilterTypeEnum;
296
+ (function (NotificationRolesFilterTypeEnum) {
297
+ NotificationRolesFilterTypeEnum["ALL"] = "all";
298
+ NotificationRolesFilterTypeEnum["ONLY"] = "only";
299
+ })(NotificationRolesFilterTypeEnum || (NotificationRolesFilterTypeEnum = {}));
300
+
246
301
  function getVersion() {
247
302
  try {
248
- // the string ''v7.22.0-esm'' should be replaced by actual value by @rollup/plugin-replace
249
- return 'v7.22.0-esm';
303
+ // the string ''v7.23.0-esm'' should be replaced by actual value by @rollup/plugin-replace
304
+ return 'v7.23.0-esm';
250
305
  }
251
306
  catch (error) {
252
307
  return '__dev__';
@@ -255,6 +310,7 @@ function getVersion() {
255
310
  const VERSION = getVersion();
256
311
 
257
312
  const COLLECTION_DEFAULT_PAGINATION_LIMIT = 5;
313
+ const COLLECTION_DEFAULT_PAGINATION_SIZE = 20;
258
314
  const COLLECTION_DEFAULT_CACHING_POLICY = 'cache_then_server';
259
315
  const ENABLE_CACHE_MESSAGE = 'For using Live Collection feature you need to enable Cache!';
260
316
  const LIVE_OBJECT_ENABLE_CACHE_MESSAGE = 'For using Live Object feature you need to enable Cache!';
@@ -267,6 +323,9 @@ const DAY = 24 * HOUR;
267
323
  const WEEK = 7 * DAY;
268
324
  const YEAR = 365 * DAY;
269
325
  const ACCESS_TOKEN_WATCHER_INTERVAL = 10 * MINUTE;
326
+ const API_ENDPOINTS = {
327
+ forYouFeed: '/api/v1/feeds/for-you',
328
+ };
270
329
 
271
330
  // cache constants
272
331
  const CACHE_KEY_GET = 'get';
@@ -647,6 +706,107 @@ function createSnapshot(data, options) {
647
706
  return Object.assign(Object.assign({}, options), { data });
648
707
  }
649
708
 
709
+ /* eslint-disable max-classes-per-file */
710
+ /**
711
+ * Generic ASC error
712
+ * @category Errors
713
+ */
714
+ class ASCError extends Error {
715
+ /**
716
+ * @param message A custom error message
717
+ * @param code A normalized error code
718
+ * @param level A normalized failure level descriptor
719
+ */
720
+ constructor(message, code, level) {
721
+ super(`Amity SDK (${code}): ${message}`);
722
+ this.code = code;
723
+ this.level = level;
724
+ this.type = 'ASC';
725
+ this.timestamp = Date.now();
726
+ if (Error.captureStackTrace)
727
+ Error.captureStackTrace(this, ASCError);
728
+ }
729
+ }
730
+ /**
731
+ * API level error
732
+ * @category Errors
733
+ */
734
+ class ASCApiError extends ASCError {
735
+ /**
736
+ * @param code A normalized error code
737
+ * @param level A normalized failure level descriptor
738
+ */
739
+ // eslint-disable-next-line no-useless-constructor
740
+ constructor(message, code, level) {
741
+ super(message, code, level);
742
+ }
743
+ }
744
+ /**
745
+ * Unexpected error
746
+ * @category Errors
747
+ */
748
+ class ASCUnknownError extends ASCError {
749
+ /**
750
+ * @param code A normalized error code
751
+ * @param level A normalized failure level descriptor
752
+ */
753
+ constructor(code = 800000 /* Amity.ClientError.UNKNOWN_ERROR */, level = "fatal" /* Amity.ErrorLevel.FATAL */) {
754
+ super('Unexpected error', code, level);
755
+ }
756
+ }
757
+ /**
758
+ * Network related error
759
+ * @category Errors
760
+ */
761
+ class ASCConnectionError extends ASCError {
762
+ /**
763
+ * @param message A custom error message
764
+ */
765
+ constructor(event, message = 'SDK client is having connection issues') {
766
+ super(`${message} (${event})`, event === 'disconnected'
767
+ ? 800211 /* Amity.ClientError.DISCONNECTED */
768
+ : 800210 /* Amity.ClientError.CONNECTION_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
769
+ this.event = event;
770
+ }
771
+ }
772
+ /**
773
+ * Input sanitization related error
774
+ * @category Errors
775
+ */
776
+ class ASCInvalidParameterError extends ASCError {
777
+ /**
778
+ * @param message A custom error message
779
+ */
780
+ constructor(message) {
781
+ super(message, 800110 /* Amity.ClientError.INVALID_PARAMETERS */, "error" /* Amity.ErrorLevel.ERROR */);
782
+ }
783
+ }
784
+
785
+ let activeClient = null;
786
+ /**
787
+ * Get the active client
788
+ *
789
+ * @returns the active client instance
790
+ *
791
+ * @hidden
792
+ */
793
+ const getActiveClient = () => {
794
+ if (!activeClient) {
795
+ throw new ASCError('There is no active client', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
796
+ }
797
+ return activeClient;
798
+ };
799
+ /**
800
+ * Sets the active client
801
+ *
802
+ * @param client the client to assume as currently active client
803
+ *
804
+ * @hidden
805
+ */
806
+ const setActiveClient = (client) => {
807
+ activeClient = client;
808
+ };
809
+
650
810
  /** @hidden */
651
811
  const idResolvers = {
652
812
  user: ({ userId }) => userId,
@@ -655,6 +815,7 @@ const idResolvers = {
655
815
  channel: ({ channelInternalId }) => channelInternalId,
656
816
  subChannel: ({ subChannelId }) => subChannelId,
657
817
  channelUsers: ({ channelId, userId }) => `${channelId}#${userId}`,
818
+ archivedChannel: ({ channelId }) => channelId,
658
819
  message: ({ messageId, referenceId }) => referenceId !== null && referenceId !== void 0 ? referenceId : messageId,
659
820
  messagePreviewChannel: ({ channelId }) => `${channelId}`,
660
821
  messagePreviewSubChannel: ({ subChannelId }) => `${subChannelId}`,
@@ -696,6 +857,7 @@ const idResolvers = {
696
857
  event: ({ eventId }) => eventId,
697
858
  eventResponse: ({ userId }) => userId,
698
859
  product: ({ productId }) => productId,
860
+ feedMetadata: ({ postId }) => postId,
699
861
  };
700
862
  /**
701
863
  * Retrieve the id resolver matching a domain name
@@ -718,6 +880,7 @@ const PAYLOAD2MODEL = {
718
880
  channels: 'channel',
719
881
  messageFeeds: 'subChannel',
720
882
  channelUsers: 'channelUsers',
883
+ archives: 'archivedChannel',
721
884
  messages: 'message',
722
885
  messagePreviewChannel: 'messagePreviewChannel',
723
886
  messagePreviewSubChannel: 'messagePreviewSubChannel',
@@ -756,6 +919,7 @@ const PAYLOAD2MODEL = {
756
919
  viewers: 'viewer',
757
920
  eventResponses: 'eventResponse',
758
921
  products: 'product',
922
+ feedMetadata: 'feedMetadata',
759
923
  };
760
924
  /** hidden */
761
925
  const isOutdated = (prevData, nextData) => {
@@ -770,107 +934,6 @@ function getFutureDate(date = new Date().toISOString()) {
770
934
  return new Date(new Date(date).getTime() + 1).toISOString();
771
935
  }
772
936
 
773
- /* eslint-disable max-classes-per-file */
774
- /**
775
- * Generic ASC error
776
- * @category Errors
777
- */
778
- class ASCError extends Error {
779
- /**
780
- * @param message A custom error message
781
- * @param code A normalized error code
782
- * @param level A normalized failure level descriptor
783
- */
784
- constructor(message, code, level) {
785
- super(`Amity SDK (${code}): ${message}`);
786
- this.code = code;
787
- this.level = level;
788
- this.type = 'ASC';
789
- this.timestamp = Date.now();
790
- if (Error.captureStackTrace)
791
- Error.captureStackTrace(this, ASCError);
792
- }
793
- }
794
- /**
795
- * API level error
796
- * @category Errors
797
- */
798
- class ASCApiError extends ASCError {
799
- /**
800
- * @param code A normalized error code
801
- * @param level A normalized failure level descriptor
802
- */
803
- // eslint-disable-next-line no-useless-constructor
804
- constructor(message, code, level) {
805
- super(message, code, level);
806
- }
807
- }
808
- /**
809
- * Unexpected error
810
- * @category Errors
811
- */
812
- class ASCUnknownError extends ASCError {
813
- /**
814
- * @param code A normalized error code
815
- * @param level A normalized failure level descriptor
816
- */
817
- constructor(code = 800000 /* Amity.ClientError.UNKNOWN_ERROR */, level = "fatal" /* Amity.ErrorLevel.FATAL */) {
818
- super('Unexpected error', code, level);
819
- }
820
- }
821
- /**
822
- * Network related error
823
- * @category Errors
824
- */
825
- class ASCConnectionError extends ASCError {
826
- /**
827
- * @param message A custom error message
828
- */
829
- constructor(event, message = 'SDK client is having connection issues') {
830
- super(`${message} (${event})`, event === 'disconnected'
831
- ? 800211 /* Amity.ClientError.DISCONNECTED */
832
- : 800210 /* Amity.ClientError.CONNECTION_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
833
- this.event = event;
834
- }
835
- }
836
- /**
837
- * Input sanitization related error
838
- * @category Errors
839
- */
840
- class ASCInvalidParameterError extends ASCError {
841
- /**
842
- * @param message A custom error message
843
- */
844
- constructor(message) {
845
- super(message, 800110 /* Amity.ClientError.INVALID_PARAMETERS */, "error" /* Amity.ErrorLevel.ERROR */);
846
- }
847
- }
848
-
849
- let activeClient = null;
850
- /**
851
- * Get the active client
852
- *
853
- * @returns the active client instance
854
- *
855
- * @hidden
856
- */
857
- const getActiveClient = () => {
858
- if (!activeClient) {
859
- throw new ASCError('There is no active client', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "fatal" /* Amity.ErrorLevel.FATAL */);
860
- }
861
- return activeClient;
862
- };
863
- /**
864
- * Sets the active client
865
- *
866
- * @param client the client to assume as currently active client
867
- *
868
- * @hidden
869
- */
870
- const setActiveClient = (client) => {
871
- activeClient = client;
872
- };
873
-
874
937
  /**
875
938
  * ```js
876
939
  * import { enableCache } from '@amityco/ts-sdk-react-native'
@@ -1378,6 +1441,65 @@ const filterBySearchTerm = (collection, searchTerm) => {
1378
1441
  return m.user && ((_a = m.user.displayName) === null || _a === void 0 ? void 0 : _a.match(containsMatcher));
1379
1442
  });
1380
1443
  };
1444
+ /**
1445
+ * The ids of users in a block relationship with the current user — in BOTH
1446
+ * directions — derived synchronously from the local follow cache. For every
1447
+ * `status === 'blocked'` row that involves the current user, the OTHER party
1448
+ * is collected: `from === me` (users I blocked, outgoing) contributes `to`;
1449
+ * `to === me` (users who blocked me, incoming) contributes `from`.
1450
+ *
1451
+ * @returns a set of block-related user ids (both directions)
1452
+ *
1453
+ * @hidden
1454
+ */
1455
+ const getBlockUsersId = () => {
1456
+ var _a;
1457
+ const { userId } = getActiveClient();
1458
+ const ids = new Set();
1459
+ ((_a = queryCache(['follow', 'get'])) !== null && _a !== void 0 ? _a : [])
1460
+ .map(entry => entry.data)
1461
+ .filter(follow => (follow === null || follow === void 0 ? void 0 : follow.status) === 'blocked' && (follow.from === userId || follow.to === userId))
1462
+ .forEach(follow => {
1463
+ ids.add(follow.from === userId ? follow.to : follow.from);
1464
+ });
1465
+ return ids;
1466
+ };
1467
+ /**
1468
+ * Filter out posts whose author or any mentionee is in a block relationship
1469
+ * with the current user, in either direction (see {@link getBlockUsersId}).
1470
+ *
1471
+ * @param collection the post collection to filter
1472
+ * @returns a filtered collection excluding posts involving block-related users
1473
+ *
1474
+ * @hidden
1475
+ */
1476
+ const filterPostsByBlockUsers = (collection) => {
1477
+ const blockUsersId = getBlockUsersId();
1478
+ if (blockUsersId.size === 0)
1479
+ return collection;
1480
+ return collection.filter(post => {
1481
+ var _a, _b;
1482
+ if (blockUsersId.has(post.postedUserId))
1483
+ return false;
1484
+ const mentionedUserIds = (_b = (_a = post.mentionees) === null || _a === void 0 ? void 0 : _a.flatMap(mention => (mention.type === 'user' ? mention.userIds : []))) !== null && _b !== void 0 ? _b : [];
1485
+ return !mentionedUserIds.some(id => blockUsersId.has(id));
1486
+ });
1487
+ };
1488
+ /**
1489
+ * Filter out comments whose creator is in a block relationship with the
1490
+ * current user, in either direction (see {@link getBlockUsersId}).
1491
+ *
1492
+ * @param collection the comment collection to filter
1493
+ * @returns a filtered collection excluding comments from block-related users
1494
+ *
1495
+ * @hidden
1496
+ */
1497
+ const filterCommentsByBlockUsers = (collection) => {
1498
+ const blockUsersId = getBlockUsersId();
1499
+ if (blockUsersId.size === 0)
1500
+ return collection;
1501
+ return collection.filter(comment => !blockUsersId.has(comment.userId));
1502
+ };
1381
1503
 
1382
1504
  // Note:
1383
1505
  // this file should contain a suite of sorting utilities to help the
@@ -1848,13 +1970,13 @@ class NetworkActivitiesWatcher {
1848
1970
  this._listener.clear();
1849
1971
  }
1850
1972
  }
1851
- let instance$9;
1973
+ let instance$b;
1852
1974
  var NetworkActivitiesWatcher$1 = {
1853
1975
  getInstance: () => {
1854
- if (!instance$9) {
1855
- instance$9 = new NetworkActivitiesWatcher();
1976
+ if (!instance$b) {
1977
+ instance$b = new NetworkActivitiesWatcher();
1856
1978
  }
1857
- return instance$9;
1979
+ return instance$b;
1858
1980
  },
1859
1981
  };
1860
1982
 
@@ -20693,18 +20815,149 @@ var mqtt$1 = {exports: {}};
20693
20815
 
20694
20816
  var mqtt = /*@__PURE__*/getDefaultExportFromCjs(mqtt$1.exports);
20695
20817
 
20818
+ class SessionWatcher {
20819
+ constructor() {
20820
+ this._sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
20821
+ this._listener = new Map();
20822
+ }
20823
+ onSessionStateChange(callback) {
20824
+ this._listener.set(callback, callback);
20825
+ return () => {
20826
+ this._listener.delete(callback);
20827
+ };
20828
+ }
20829
+ setSessionState(state, reason) {
20830
+ if (this._sessionState === state)
20831
+ return;
20832
+ this._sessionState = state;
20833
+ this._listener.forEach(cb => cb(state, reason));
20834
+ }
20835
+ destroy() {
20836
+ this._listener.clear();
20837
+ }
20838
+ }
20839
+ let instance$a;
20840
+ var SessionWatcher$1 = {
20841
+ getInstance: () => {
20842
+ if (!instance$a) {
20843
+ instance$a = new SessionWatcher();
20844
+ }
20845
+ return instance$a;
20846
+ },
20847
+ };
20848
+
20849
+ /**
20850
+ * ```js
20851
+ * import { onSessionStateChange } from '@amityco/ts-sdk-react-native'
20852
+ * const dispose = onSessionStateChange((state: Amity.SessionStates) => {
20853
+ * // ...
20854
+ * })
20855
+ * ```
20856
+ *
20857
+ * Fired when any {@link Amity.Client} has a session state change
20858
+ *
20859
+ * @param callback The function to call when the event was fired
20860
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
20861
+ *
20862
+ * @category Client Events
20863
+ */
20864
+ const onSessionStateChange = (callback) => SessionWatcher$1.getInstance().onSessionStateChange(callback);
20865
+
20866
+ const TOPICS = {
20867
+ [AmityAutoSubscription.NETWORK]: [getNetworkTopic],
20868
+ [AmityAutoSubscription.CHAT]: [
20869
+ getSmartFeedChannelTopic,
20870
+ getSmartFeedSubChannelTopic,
20871
+ getSmartFeedMessageTopic,
20872
+ ],
20873
+ [AmityAutoSubscription.LIVESTREAM]: [getLiveStreamTopic],
20874
+ [AmityAutoSubscription.BLOCK]: [getMyFollowersTopic, getMyFollowingsTopic],
20875
+ };
20876
+ const DEFAULT_TOPICS = [
20877
+ AmityAutoSubscription.CHAT,
20878
+ AmityAutoSubscription.NETWORK,
20879
+ AmityAutoSubscription.LIVESTREAM,
20880
+ AmityAutoSubscription.BLOCK,
20881
+ ];
20882
+ const ALL_FEATURES = Object.values(AmityAutoSubscription);
20883
+ /** Ref-counted, reconnect-resilient registry of the managed auto-subscriptions. */
20884
+ class AutoSubscriptionManager {
20885
+ constructor() {
20886
+ this.refCountByFeature = new Map();
20887
+ this.disposers = new Map();
20888
+ this.seed();
20889
+ }
20890
+ seed() {
20891
+ this.refCountByFeature.clear();
20892
+ DEFAULT_TOPICS.forEach(feature => this.refCountByFeature.set(feature, 1));
20893
+ }
20894
+ isActive(feature) {
20895
+ var _a;
20896
+ return ((_a = this.refCountByFeature.get(feature)) !== null && _a !== void 0 ? _a : 0) > 0;
20897
+ }
20898
+ subscribeTopics(feature) {
20899
+ this.unsubscribeTopics(feature);
20900
+ this.disposers.set(feature, TOPICS[feature].map(buildTopic => subscribeTopic(buildTopic())));
20901
+ }
20902
+ unsubscribeTopics(feature) {
20903
+ var _a;
20904
+ ((_a = this.disposers.get(feature)) !== null && _a !== void 0 ? _a : []).forEach(dispose => dispose());
20905
+ this.disposers.delete(feature);
20906
+ }
20907
+ /** Subscribe every enabled handle's topics, converging the broker to the registry. Called on each (re)connect. */
20908
+ initialize() {
20909
+ ALL_FEATURES.forEach(feature => {
20910
+ if (this.isActive(feature))
20911
+ this.subscribeTopics(feature);
20912
+ });
20913
+ }
20914
+ subscribe(feature) {
20915
+ var _a;
20916
+ const next = ((_a = this.refCountByFeature.get(feature)) !== null && _a !== void 0 ? _a : 0) + 1;
20917
+ this.refCountByFeature.set(feature, next);
20918
+ if (next === 1)
20919
+ this.subscribeTopics(feature);
20920
+ }
20921
+ unsubscribe(feature) {
20922
+ var _a;
20923
+ const next = Math.max(0, ((_a = this.refCountByFeature.get(feature)) !== null && _a !== void 0 ? _a : 0) - 1);
20924
+ this.refCountByFeature.set(feature, next);
20925
+ if (next === 0)
20926
+ this.unsubscribeTopics(feature);
20927
+ }
20928
+ subscriptions() {
20929
+ return ALL_FEATURES.map(feature => ({
20930
+ feature,
20931
+ isActive: this.isActive(feature),
20932
+ isSystem: true,
20933
+ topicCount: TOPICS[feature].length,
20934
+ }));
20935
+ }
20936
+ reset() {
20937
+ ALL_FEATURES.forEach(feature => this.unsubscribeTopics(feature));
20938
+ this.disposers.clear();
20939
+ this.seed();
20940
+ }
20941
+ }
20942
+ let instance$9 = null;
20943
+ const getAutoSubscriptionManager = () => {
20944
+ if (!instance$9)
20945
+ instance$9 = new AutoSubscriptionManager();
20946
+ return instance$9;
20947
+ };
20948
+ /** Resets the registry to its default baseline when the session ends. */
20949
+ const resetAutoSubscriptionsOnLogout = () => onSessionStateChange(state => {
20950
+ if (state !== "established" /* Amity.SessionStates.ESTABLISHED */)
20951
+ getAutoSubscriptionManager().reset();
20952
+ });
20953
+
20954
+ /**
20955
+ * (Re)subscribes the managed auto-subscription registry on every (re)connect.
20956
+ * The hardcoded topic list was promoted to the toggleable, ref-counted registry
20957
+ * in {@link getAutoSubscriptionManager} — see `client.manageAutoSubscriptions`.
20958
+ */
20696
20959
  const subscribeGlobalTopic = () => {
20697
- const disposers = [
20698
- subscribeTopic(getNetworkTopic()),
20699
- subscribeTopic(getSmartFeedChannelTopic()),
20700
- subscribeTopic(getSmartFeedSubChannelTopic()),
20701
- subscribeTopic(getSmartFeedMessageTopic()),
20702
- // subscribing to user topic is necessary to handle ban event
20703
- subscribeTopic(getUserTopic(getActiveUser())),
20704
- subscribeTopic(getMarkerUserFeedTopic()),
20705
- subscribeTopic(getLiveStreamTopic()),
20706
- ];
20707
- return () => disposers.forEach(fn => fn());
20960
+ getAutoSubscriptionManager().initialize();
20708
20961
  };
20709
20962
 
20710
20963
  class OnMemoryStorage {
@@ -21277,8 +21530,12 @@ const getChannelMessagePreviewWithUser = (channel) => {
21277
21530
  return Object.assign(Object.assign({}, channel), { messagePreview: messagePreviewWithUser });
21278
21531
  };
21279
21532
 
21533
+ const convertDateStringToTimestamp = (dateString) => {
21534
+ return new Date(dateString).getTime();
21535
+ };
21536
+
21280
21537
  const updateChannelMessagePreviewCache = (rawPayload) => {
21281
- var _a, _b;
21538
+ var _a;
21282
21539
  const withMessageFeedInfo = (messagePreview) => {
21283
21540
  var _a;
21284
21541
  const messageFeedInfo = (_a = rawPayload.messageFeedsInfo) === null || _a === void 0 ? void 0 : _a.find(messageFeed => {
@@ -21300,10 +21557,26 @@ const updateChannelMessagePreviewCache = (rawPayload) => {
21300
21557
  subChannelUpdatedAt: messageFeedInfo === null || messageFeedInfo === void 0 ? void 0 : messageFeedInfo.updatedAt,
21301
21558
  };
21302
21559
  };
21303
- const newData = {
21304
- messagePreviewChannel: (_b = (_a = rawPayload.messagePreviews) === null || _a === void 0 ? void 0 : _a.map(messagePreview => withMessageFeedInfo(messagePreview))) !== null && _b !== void 0 ? _b : [],
21305
- };
21306
- ingestInCache(newData);
21560
+ // Skip server previews older than what's cached — the cache may carry a newer
21561
+ // preview written by handleMessageCreated from an MQTT message that the server
21562
+ // payload hasn't surfaced yet. Mirrors isLastestMessageOnChannel.
21563
+ const newPreviews = ((_a = rawPayload.messagePreviews) !== null && _a !== void 0 ? _a : [])
21564
+ .map(withMessageFeedInfo)
21565
+ .filter(preview => {
21566
+ var _a;
21567
+ const cached = (_a = pullFromCache([
21568
+ 'messagePreviewChannel',
21569
+ 'get',
21570
+ preview.channelId,
21571
+ ])) === null || _a === void 0 ? void 0 : _a.data;
21572
+ if (!cached)
21573
+ return true;
21574
+ return (convertDateStringToTimestamp(cached.createdAt) <=
21575
+ convertDateStringToTimestamp(preview.createdAt));
21576
+ });
21577
+ if (newPreviews.length === 0)
21578
+ return;
21579
+ ingestInCache({ messagePreviewChannel: newPreviews });
21307
21580
  };
21308
21581
 
21309
21582
  const getSubChannelMessagePreview = (subChannelId) => {
@@ -21931,11 +22204,7 @@ getSubChannel$1.locally = (subChannelId) => {
21931
22204
  };
21932
22205
  };
21933
22206
 
21934
- const convertDateStringToTimestamp = (dateString) => {
21935
- return new Date(dateString).getTime();
21936
- };
21937
-
21938
- const getMessagePreviewSetting$1 = async () => {
22207
+ const getMessagePreviewSetting$2 = async () => {
21939
22208
  const client = getActiveClient();
21940
22209
  return client.getMessagePreviewSetting(false);
21941
22210
  };
@@ -21970,7 +22239,7 @@ const isLastestMessageOnChannel = (message) => {
21970
22239
  convertDateStringToTimestamp(cache.createdAt) <= convertDateStringToTimestamp(message.createdAt));
21971
22240
  };
21972
22241
  const handleMessageCreatedOnSubChannel = async (message) => {
21973
- const messagePreviewSetting = await getMessagePreviewSetting$1();
22242
+ const messagePreviewSetting = await getMessagePreviewSetting$2();
21974
22243
  const { channelId, messageId: messagePreviewId, creatorId, createdAt, updatedAt, data, dataType, subChannelId, channelSegment: segment, isDeleted, } = message;
21975
22244
  // 1. get subChannel from cache, if not exist fetch from server
21976
22245
  const subChannelCache = await getSubChannelCache(subChannelId);
@@ -22142,24 +22411,41 @@ const preUpdateChannelCache = (rawPayload, options = { isMessagePreviewUpdated:
22142
22411
  });
22143
22412
  };
22144
22413
  const updateChannelUnread = ({ currentUserId, channels, channelUsers, }) => {
22414
+ var _a, _b;
22145
22415
  const channelsUnread = [];
22146
22416
  for (let i = 0; i < channels.length; i += 1) {
22147
22417
  if (isUnreadCountSupport(channels[i])) {
22148
22418
  const cacheKey = ['channelUnread', 'get', channels[i].channelId];
22149
22419
  const channelUser = channelUsers.find(channelUser => channelUser.channelId === channels[i].channelId && channelUser.userId === currentUserId);
22150
- let unreadCount = 0;
22420
+ // readToSegment, lastMentionedSegment and lastSegment are monotonically non-decreasing;
22421
+ // prefer cached values when ahead of the server so a refetch returning stale data cannot
22422
+ const cached = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
22423
+ const lastSegment = Math.max((_b = cached === null || cached === void 0 ? void 0 : cached.lastSegment) !== null && _b !== void 0 ? _b : 0, channels[i].messageCount);
22151
22424
  let readToSegment = null;
22152
22425
  let lastMentionedSegment = null;
22426
+ let unreadCount = 0;
22153
22427
  let isMentioned = false;
22154
22428
  if (channelUser) {
22155
- readToSegment = channelUser.readToSegment;
22156
- lastMentionedSegment = channelUser.lastMentionedSegment;
22157
- unreadCount = Math.max(channels[i].messageCount - readToSegment, 0);
22158
- isMentioned = lastMentionedSegment > readToSegment;
22429
+ const serverRead = channelUser.readToSegment;
22430
+ const serverMention = channelUser.lastMentionedSegment;
22431
+ readToSegment =
22432
+ typeof (cached === null || cached === void 0 ? void 0 : cached.readToSegment) === 'number' &&
22433
+ (typeof serverRead !== 'number' || cached.readToSegment > serverRead)
22434
+ ? cached.readToSegment
22435
+ : serverRead !== null && serverRead !== void 0 ? serverRead : null;
22436
+ lastMentionedSegment =
22437
+ typeof (cached === null || cached === void 0 ? void 0 : cached.lastMentionedSegment) === 'number' &&
22438
+ (typeof serverMention !== 'number' || cached.lastMentionedSegment > serverMention)
22439
+ ? cached.lastMentionedSegment
22440
+ : serverMention !== null && serverMention !== void 0 ? serverMention : null;
22441
+ const readForCalc = readToSegment !== null && readToSegment !== void 0 ? readToSegment : 0;
22442
+ unreadCount = Math.max(lastSegment - readForCalc, 0);
22443
+ isMentioned =
22444
+ typeof lastMentionedSegment === 'number' && readForCalc < lastMentionedSegment;
22159
22445
  }
22160
22446
  const cacheChannelUnread = {
22161
22447
  channelId: channels[i].channelId,
22162
- lastSegment: channels[i].messageCount,
22448
+ lastSegment,
22163
22449
  readToSegment,
22164
22450
  lastMentionedSegment,
22165
22451
  unreadCount,
@@ -22169,6 +22455,8 @@ const updateChannelUnread = ({ currentUserId, channels, channelUsers, }) => {
22169
22455
  pushToCache(cacheKey, cacheChannelUnread);
22170
22456
  channelsUnread.push(cacheChannelUnread);
22171
22457
  }
22458
+ }
22459
+ if (channelsUnread.length > 0) {
22172
22460
  fireEvent('local.channelUnread.updated', channelsUnread);
22173
22461
  }
22174
22462
  };
@@ -22868,7 +23156,7 @@ const onChannelMemberRoleRemoved = (callback) => {
22868
23156
  const client = getActiveClient();
22869
23157
  const filter = async (payload) => {
22870
23158
  const { channels, channelUsers } = payload;
22871
- callback(channels[0], channelUsers.find(channelUser => channelUser.membership === 'member'));
23159
+ callbacks$1.forEach(cb => cb(channels[0], channelUsers.find(channelUser => channelUser.membership === 'member')));
22872
23160
  };
22873
23161
  mainDisposer$1 = createEventSubscriber(client, 'onChannelMemberRoleRemoved', 'local.channel-moderator.role-removed', filter);
22874
23162
  }
@@ -22876,6 +23164,39 @@ const onChannelMemberRoleRemoved = (callback) => {
22876
23164
  return () => dispose$1(callback);
22877
23165
  };
22878
23166
 
23167
+ /**
23168
+ * Fired when a {@link Amity.Channel} has been archived by the active user.
23169
+ *
23170
+ * @param callback The function to call when the event was fired
23171
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
23172
+ *
23173
+ * @category Channel Events
23174
+ */
23175
+ const onChannelArchived = (callback) => {
23176
+ const client = getActiveClient();
23177
+ const filter = async (payload) => {
23178
+ callback(payload);
23179
+ };
23180
+ return createEventSubscriber(client, 'onChannelArchived', 'local.channel.archived', filter);
23181
+ };
23182
+
23183
+ /**
23184
+ * Fired when a previously archived {@link Amity.Channel} has been unarchived
23185
+ * by the active user.
23186
+ *
23187
+ * @param callback The function to call when the event was fired
23188
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
23189
+ *
23190
+ * @category Channel Events
23191
+ */
23192
+ const onChannelUnarchived = (callback) => {
23193
+ const client = getActiveClient();
23194
+ const filter = async (payload) => {
23195
+ callback(payload);
23196
+ };
23197
+ return createEventSubscriber(client, 'onChannelUnarchived', 'local.channel.unarchived', filter);
23198
+ };
23199
+
22879
23200
  const callbacks = [];
22880
23201
  let mainDisposer = null;
22881
23202
  const dispose = (cb) => {
@@ -22989,6 +23310,17 @@ const channelLinkedObject = (channel) => {
22989
23310
  markAsRead: () => markAsRead(channel.channelInternalId),
22990
23311
  previewMembers,
22991
23312
  myMembership: (callback) => getMyMembership(channel.channelId, callback),
23313
+ get avatar() {
23314
+ var _a;
23315
+ if (!channel.avatarFileId)
23316
+ return undefined;
23317
+ const avatar = (_a = pullFromCache([
23318
+ 'file',
23319
+ 'get',
23320
+ `${channel.avatarFileId}`,
23321
+ ])) === null || _a === void 0 ? void 0 : _a.data;
23322
+ return avatar;
23323
+ },
22992
23324
  });
22993
23325
  };
22994
23326
 
@@ -23087,54 +23419,6 @@ getChannelByIds$1.locally = (channelIds) => {
23087
23419
  };
23088
23420
  };
23089
23421
 
23090
- class SessionWatcher {
23091
- constructor() {
23092
- this._sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
23093
- this._listener = new Map();
23094
- }
23095
- onSessionStateChange(callback) {
23096
- this._listener.set(callback, callback);
23097
- return () => {
23098
- this._listener.delete(callback);
23099
- };
23100
- }
23101
- setSessionState(state, reason) {
23102
- if (this._sessionState === state)
23103
- return;
23104
- this._sessionState = state;
23105
- this._listener.forEach(cb => cb(state, reason));
23106
- }
23107
- destroy() {
23108
- this._listener.clear();
23109
- }
23110
- }
23111
- let instance$8;
23112
- var SessionWatcher$1 = {
23113
- getInstance: () => {
23114
- if (!instance$8) {
23115
- instance$8 = new SessionWatcher();
23116
- }
23117
- return instance$8;
23118
- },
23119
- };
23120
-
23121
- /**
23122
- * ```js
23123
- * import { onSessionStateChange } from '@amityco/ts-sdk-react-native'
23124
- * const dispose = onSessionStateChange((state: Amity.SessionStates) => {
23125
- * // ...
23126
- * })
23127
- * ```
23128
- *
23129
- * Fired when any {@link Amity.Client} has a session state change
23130
- *
23131
- * @param callback The function to call when the event was fired
23132
- * @returns an {@link Amity.Unsubscriber} function to stop listening
23133
- *
23134
- * @category Client Events
23135
- */
23136
- const onSessionStateChange = (callback) => SessionWatcher$1.getInstance().onSessionStateChange(callback);
23137
-
23138
23422
  const setIntervalTask = (handler, timeout) => {
23139
23423
  const timer = setInterval(handler, timeout);
23140
23424
  return () => clearInterval(timer);
@@ -23306,7 +23590,7 @@ const convertMessagePreviewSetting = (chatSetting) => {
23306
23590
  * @category private
23307
23591
  * @async
23308
23592
  */
23309
- const getMessagePreviewSetting = async (refresh = true) => {
23593
+ const getMessagePreviewSetting$1 = async (refresh = true) => {
23310
23594
  var _a;
23311
23595
  const messagePreviewSetting = (_a = pullFromCache([
23312
23596
  'MessagePreviewSetting',
@@ -23327,7 +23611,7 @@ const getMessagePreviewSetting = async (refresh = true) => {
23327
23611
  */
23328
23612
  const initializeMessagePreviewSetting = async () => {
23329
23613
  var _a;
23330
- const newMessagePreviewSetting = await getMessagePreviewSetting();
23614
+ const newMessagePreviewSetting = await getMessagePreviewSetting$1();
23331
23615
  const messagePreviewSetting = (_a = pullFromCache([
23332
23616
  'MessagePreviewSetting',
23333
23617
  ])) === null || _a === void 0 ? void 0 : _a.data;
@@ -23398,6 +23682,26 @@ const getSocialSettings = async () => {
23398
23682
  return data.socialNetworkSetting;
23399
23683
  };
23400
23684
 
23685
+ /**
23686
+ * ```js
23687
+ * import { createClient } from '@amityco/ts-sdk'
23688
+ * const client = createClient(apiKey, apiRegion)
23689
+ * const userSettings = await client.getCoreUserSettings()
23690
+ * ```
23691
+ *
23692
+ * Fetches a {@link Amity.CoreUserSettings} object
23693
+ *
23694
+ * @returns A Promise of {@link Amity.CoreUserSettings} object
23695
+ *
23696
+ * @category Client API
23697
+ * @async
23698
+ */
23699
+ const getCoreUserSettings = async () => {
23700
+ const client = getActiveClient();
23701
+ const { data } = await client.http.get(`/api/v3/network-settings/users`);
23702
+ return data;
23703
+ };
23704
+
23401
23705
  /* begin_public_function
23402
23706
  id: client.getProductCatalogueSetting
23403
23707
  */
@@ -23421,6 +23725,33 @@ const getProductCatalogueSetting = async () => {
23421
23725
  };
23422
23726
  /* end_public_function */
23423
23727
 
23728
+ /* begin_public_function
23729
+ id: client.getForYouFeedSetting
23730
+ */
23731
+ /**
23732
+ * ```js
23733
+ * import { Client } from '@amityco/ts-sdk'
23734
+ * const forYouFeedSetting = await Client.getForYouFeedSetting()
23735
+ * ```
23736
+ *
23737
+ * Fetches the network-level {@link Amity.ForYouFeedSetting} — whether the For You
23738
+ * feed feature is enabled for the current network. Use `forYouFeed.enabled` as a
23739
+ * feature gate before querying {@link getForYouFeed}.
23740
+ *
23741
+ * @returns A Promise of {@link Amity.ForYouFeedSetting} object
23742
+ *
23743
+ * @category Client API
23744
+ * @async
23745
+ */
23746
+ const getForYouFeedSetting = async () => {
23747
+ var _a, _b;
23748
+ const client = getActiveClient();
23749
+ const { data } = await client.http.get(`/api/v3/network-settings/for-you-feed`);
23750
+ // Surface only `enabled`; ignore server-side ranking config (scoringConfig, etc.)
23751
+ return { forYouFeed: { enabled: (_b = (_a = data.forYouFeed) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : false } };
23752
+ };
23753
+ /* end_public_function */
23754
+
23424
23755
  const checkUserPermission = (userId, permission) => {
23425
23756
  var _a;
23426
23757
  const user = (_a = pullFromCache(['user', 'get', userId])) === null || _a === void 0 ? void 0 : _a.data;
@@ -23928,7 +24259,7 @@ class AnalyticsEventSyncer {
23928
24259
 
23929
24260
  class AnalyticsEventCapturer {
23930
24261
  constructor() {
23931
- this._expireTime = 5 * MINUTE;
24262
+ this._expireTime = 5 * SECOND$1;
23932
24263
  this._poolLimit = 1000;
23933
24264
  this._recentViewed = {};
23934
24265
  this._recentHighPriorityViewed = {};
@@ -23982,12 +24313,36 @@ class AnalyticsEventCapturer {
23982
24313
  }
23983
24314
  markPostAsViewed(postId) {
23984
24315
  this.markAs({
23985
- uniqueId: postId,
24316
+ uniqueId: `post.${postId}`,
23986
24317
  contentId: postId,
23987
24318
  contentType: "post" /* Amity.AnalyticEventContentType.Post */,
23988
24319
  activityType: "view" /* Amity.AnalyticEventActivityType.View */,
23989
24320
  });
23990
24321
  }
24322
+ markPostAsMeaningfullyViewed(postId, feedRenderPosition) {
24323
+ var _a;
24324
+ const cached = (_a = pullFromCache(['feedMetadata', 'get', postId])) === null || _a === void 0 ? void 0 : _a.data;
24325
+ const metadata = {};
24326
+ if (feedRenderPosition !== undefined)
24327
+ metadata.feedRenderPosition = feedRenderPosition;
24328
+ if (cached) {
24329
+ metadata.feedSnapshotPosition = cached.feedSnapshotPosition;
24330
+ metadata.feedInjectionType = cached.feedInjectionType;
24331
+ metadata.feedRelevanceScore = cached.feedRelevanceScore;
24332
+ metadata.feedPopularityScore = cached.feedPopularityScore;
24333
+ metadata.feedFreshnessScore = cached.feedFreshnessScore;
24334
+ metadata.feedAffinityScore = cached.feedAffinityScore;
24335
+ metadata.feedFinalScore = cached.feedFinalScore;
24336
+ metadata.feedMmrPenalty = cached.feedMmrPenalty;
24337
+ }
24338
+ this.markAs({
24339
+ uniqueId: `post.${postId}.meaningfulView`,
24340
+ contentId: postId,
24341
+ contentType: "post" /* Amity.AnalyticEventContentType.Post */,
24342
+ activityType: "meaningfulView" /* Amity.AnalyticEventActivityType.MeaningfulView */,
24343
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
24344
+ });
24345
+ }
23991
24346
  markStory(story, activityType) {
23992
24347
  if (!story.expiresAt)
23993
24348
  return;
@@ -24127,6 +24482,12 @@ class AnalyticsEngine {
24127
24482
  this._eventCapturer.markPostAsViewed(postId);
24128
24483
  }
24129
24484
  }
24485
+ markPostAsMeaningfullyViewed(postId, feedRenderPosition) {
24486
+ if (this._client.sessionState === "established" /* Amity.SessionStates.ESTABLISHED */ ||
24487
+ this._client.sessionState === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */) {
24488
+ this._eventCapturer.markPostAsMeaningfullyViewed(postId, feedRenderPosition);
24489
+ }
24490
+ }
24130
24491
  markStoryAsViewed(story) {
24131
24492
  if (this._client.sessionState === "established" /* Amity.SessionStates.ESTABLISHED */ ||
24132
24493
  this._client.sessionState === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */ // For case token_expired, we assume token is expired and gonna re-connect soon
@@ -24178,13 +24539,13 @@ class AnalyticsEngine {
24178
24539
  this._eventCapturer.resetAllBuckets();
24179
24540
  }
24180
24541
  }
24181
- let instance$7;
24542
+ let instance$8;
24182
24543
  var AnalyticsEngine$1 = {
24183
24544
  getInstance: () => {
24184
- if (!instance$7) {
24185
- instance$7 = new AnalyticsEngine();
24545
+ if (!instance$8) {
24546
+ instance$8 = new AnalyticsEngine();
24186
24547
  }
24187
- return instance$7;
24548
+ return instance$8;
24188
24549
  },
24189
24550
  };
24190
24551
 
@@ -24351,9 +24712,8 @@ class MessageReadReceiptSyncEngine {
24351
24712
  // Step 1: Optimistic update of channelUnread.readToSegment to message.segment and update unreadCount value
24352
24713
  const cacheKey = ['channelUnread', 'get', channelId];
24353
24714
  const channelUnread = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
24354
- if (typeof (channelUnread === null || channelUnread === void 0 ? void 0 : channelUnread.readToSegment) === 'number' &&
24355
- channelUnread &&
24356
- segment > channelUnread.readToSegment) {
24715
+ if (channelUnread &&
24716
+ (typeof channelUnread.readToSegment !== 'number' || segment > channelUnread.readToSegment)) {
24357
24717
  channelUnread.readToSegment = segment;
24358
24718
  channelUnread.unreadCount = Math.max(channelUnread.lastSegment - segment, 0);
24359
24719
  pushToCache(cacheKey, channelUnread);
@@ -24412,12 +24772,12 @@ class MessageReadReceiptSyncEngine {
24412
24772
  }
24413
24773
  }
24414
24774
  }
24415
- let instance$6 = null;
24775
+ let instance$7 = null;
24416
24776
  var ReadReceiptSyncEngine = {
24417
24777
  getInstance: () => {
24418
- if (!instance$6)
24419
- instance$6 = new MessageReadReceiptSyncEngine();
24420
- return instance$6;
24778
+ if (!instance$7)
24779
+ instance$7 = new MessageReadReceiptSyncEngine();
24780
+ return instance$7;
24421
24781
  },
24422
24782
  };
24423
24783
 
@@ -24671,12 +25031,12 @@ class LegacyMessageReadReceiptSyncEngine {
24671
25031
  }
24672
25032
  }
24673
25033
  }
24674
- let instance$5 = null;
25034
+ let instance$6 = null;
24675
25035
  var LegacyReadReceiptSyncEngine = {
24676
25036
  getInstance: () => {
24677
- if (!instance$5)
24678
- instance$5 = new LegacyMessageReadReceiptSyncEngine();
24679
- return instance$5;
25037
+ if (!instance$6)
25038
+ instance$6 = new LegacyMessageReadReceiptSyncEngine();
25039
+ return instance$6;
24680
25040
  },
24681
25041
  };
24682
25042
 
@@ -24952,12 +25312,12 @@ class ObjectResolverEngine {
24952
25312
  this.stopResolver();
24953
25313
  }
24954
25314
  }
24955
- let instance$4 = null;
25315
+ let instance$5 = null;
24956
25316
  var ObjectResolverEngine$1 = {
24957
25317
  getInstance: () => {
24958
- if (!instance$4)
24959
- instance$4 = new ObjectResolverEngine();
24960
- return instance$4;
25318
+ if (!instance$5)
25319
+ instance$5 = new ObjectResolverEngine();
25320
+ return instance$5;
24961
25321
  },
24962
25322
  };
24963
25323
 
@@ -25107,13 +25467,13 @@ class LiveReactionSyncEngine {
25107
25467
  this.stopReactionsSync();
25108
25468
  }
25109
25469
  }
25110
- let instance$3;
25470
+ let instance$4;
25111
25471
  var ReactionSyncEngine = {
25112
25472
  getInstance: () => {
25113
- if (!instance$3) {
25114
- instance$3 = new LiveReactionSyncEngine();
25473
+ if (!instance$4) {
25474
+ instance$4 = new LiveReactionSyncEngine();
25115
25475
  }
25116
- return instance$3;
25476
+ return instance$4;
25117
25477
  },
25118
25478
  };
25119
25479
 
@@ -25143,19 +25503,20 @@ function prepareBlockedUserPayload(response) {
25143
25503
  }), users: users.map(convertRawUserToInternalUser) });
25144
25504
  }
25145
25505
 
25146
- const BLOCK_LIST_LIMIT = 100;
25147
- const TTL_MS = 5 * 60 * 1000; // 5 minutes
25506
+ const BLOCK_LIST_LIMIT$1 = 100;
25507
+ const TTL_MS$1 = 5 * 60 * 1000; // 5 minutes
25148
25508
  /**
25149
25509
  * Session-scoped singleton engine that manages TTL-based fetching and caching
25150
25510
  * of blocked users. Provides a lazy `ensureFetched()` gate for the
25151
25511
  * `getAllBlockedUsers()` API.
25152
25512
  *
25153
25513
  * Key behaviours:
25154
- * - `establish()` is a no-op — fetch is lazy, triggered only by consumer call
25155
- * - `destroy()` resets `lastFetchedAt` to null (ensures fresh fetch on next session)
25514
+ * - `onSessionEstablished()` is a no-op — fetch is lazy, triggered only by consumer call
25515
+ * - `onSessionDestroyed()` resets `lastFetchedAt` to null (ensures fresh fetch on next session)
25156
25516
  * - `ensureFetched()` fetches from server only when cache is expired or never fetched
25157
25517
  * - `lastFetchedAt` is only updated on successful fetch
25158
- * - `blockedUserIds` is kept in sync with each successful fetch
25518
+ * - reads query the follow cache live, so block/unblock changes are reflected
25519
+ * even within the TTL window
25159
25520
  *
25160
25521
  * @internal
25161
25522
  */
@@ -25163,12 +25524,7 @@ class BlockedUserSyncEngine {
25163
25524
  constructor() {
25164
25525
  /** Epoch ms of last successful fetch. null = never fetched in this session. */
25165
25526
  this.lastFetchedAt = null;
25166
- /** Ordered list of userId strings from the most recent successful fetch. */
25167
- this.blockedUserIds = [];
25168
25527
  }
25169
- // ---------------------------------------------------------------------------
25170
- // SessionComponent lifecycle
25171
- // ---------------------------------------------------------------------------
25172
25528
  /** No-op — fetch is lazy, triggered by consumer calling getAllBlockedUsers(). */
25173
25529
  // eslint-disable-next-line class-methods-use-this
25174
25530
  onSessionEstablished() {
@@ -25177,24 +25533,17 @@ class BlockedUserSyncEngine {
25177
25533
  /** Resets state so the next session starts with a cold cache. */
25178
25534
  onSessionDestroyed() {
25179
25535
  this.lastFetchedAt = null;
25180
- this.blockedUserIds = [];
25181
25536
  }
25182
25537
  /** No-op for this engine. */
25183
25538
  // eslint-disable-next-line class-methods-use-this
25184
25539
  onTokenExpired() {
25185
25540
  // intentionally empty
25186
25541
  }
25187
- // ---------------------------------------------------------------------------
25188
- // Cache helpers
25189
- // ---------------------------------------------------------------------------
25190
25542
  isCacheExpired() {
25191
25543
  if (this.lastFetchedAt === null)
25192
25544
  return true;
25193
- return Date.now() - this.lastFetchedAt > TTL_MS;
25545
+ return Date.now() - this.lastFetchedAt > TTL_MS$1;
25194
25546
  }
25195
- // ---------------------------------------------------------------------------
25196
- // Core fetch gate
25197
- // ---------------------------------------------------------------------------
25198
25547
  /**
25199
25548
  * Ensures the local store is populated with fresh blocked-user data.
25200
25549
  *
@@ -25210,52 +25559,50 @@ class BlockedUserSyncEngine {
25210
25559
  if (!this.isCacheExpired())
25211
25560
  return;
25212
25561
  const client = getActiveClient();
25213
- const { data } = await client.http.get('/api/v4/me/user-blocks', { params: { options: { limit: BLOCK_LIST_LIMIT }, isDeleted: false } });
25562
+ const { data } = await client.http.get('/api/v4/me/user-blocks', { params: { options: { limit: BLOCK_LIST_LIMIT$1 }, isDeleted: false } });
25214
25563
  const cachedAt = client.cache && Date.now();
25215
25564
  const payload = prepareBlockedUserPayload(data);
25216
25565
  if (client.cache) {
25217
25566
  ingestInCache(payload, { cachedAt });
25218
25567
  }
25219
- // Keep the ordered list of blocked user IDs for getCachedUsers()
25220
- this.blockedUserIds = payload.users.map(u => u.userId);
25221
25568
  // Only update timestamp on success — failure leaves it unchanged so the
25222
25569
  // next call retries.
25223
25570
  this.lastFetchedAt = Date.now();
25224
25571
  }
25225
- // ---------------------------------------------------------------------------
25226
- // Local store read
25227
- // ---------------------------------------------------------------------------
25228
25572
  /**
25229
- * Returns blocked {@link Amity.InternalUser} objects from the in-memory cache.
25230
- *
25231
- * Applies the spec-mandated filter:
25232
- * - Only users whose `isDeleted` is false or null
25233
- * - Hard limit of 100 results
25573
+ * Returns the blocked users by querying the follow cache live — the outgoing
25574
+ * direction (`from === me`, `status === 'blocked'`). Reading the cache (not a
25575
+ * fetched snapshot) means `blockUser()` / `unblockUser()` changes are reflected
25576
+ * even within the TTL window.
25234
25577
  *
25235
- * This always reads the latest local state, so changes made by `blockUser()`
25236
- * and `unblockUser()` are reflected even within the TTL window.
25578
+ * Applies the spec-mandated query:
25579
+ * - filter `from === currentUserId`, `status === 'blocked'`, blocked user not deleted
25580
+ * - sort by `updatedAt` DESC
25581
+ * - hard limit of 100 results
25237
25582
  */
25583
+ // eslint-disable-next-line class-methods-use-this
25238
25584
  getCachedUsers() {
25585
+ var _a;
25239
25586
  const client = getActiveClient();
25240
- if (!client.cache) {
25241
- // No cache available — fall back to the in-memory list from the last fetch
25587
+ if (!client.cache)
25242
25588
  return [];
25243
- }
25244
- return this.blockedUserIds
25245
- .map(id => { var _a; return (_a = pullFromCache(['user', 'get', id])) === null || _a === void 0 ? void 0 : _a.data; })
25589
+ const { userId } = client;
25590
+ return ((_a = queryCache(['follow', 'get'])) !== null && _a !== void 0 ? _a : [])
25591
+ .map(entry => entry.data)
25592
+ .filter(follow => (follow === null || follow === void 0 ? void 0 : follow.status) === 'blocked' && follow.from === userId)
25593
+ .sort((a, b) => { var _a, _b; return (((_a = a.updatedAt) !== null && _a !== void 0 ? _a : '') < ((_b = b.updatedAt) !== null && _b !== void 0 ? _b : '') ? 1 : -1); })
25594
+ .map(follow => { var _a; return (_a = pullFromCache(['user', 'get', follow.to])) === null || _a === void 0 ? void 0 : _a.data; })
25246
25595
  .filter((user) => user != null && user.isDeleted !== true)
25247
- .slice(0, BLOCK_LIST_LIMIT);
25596
+ .slice(0, BLOCK_LIST_LIMIT$1)
25597
+ .map(userLinkedObject);
25248
25598
  }
25249
25599
  }
25250
- // ---------------------------------------------------------------------------
25251
- // Module-level singleton
25252
- // ---------------------------------------------------------------------------
25253
- let instance$2 = null;
25600
+ let instance$3 = null;
25254
25601
  var BlockedUserSyncEngine$1 = {
25255
25602
  getInstance: () => {
25256
- if (!instance$2)
25257
- instance$2 = new BlockedUserSyncEngine();
25258
- return instance$2;
25603
+ if (!instance$3)
25604
+ instance$3 = new BlockedUserSyncEngine();
25605
+ return instance$3;
25259
25606
  },
25260
25607
  };
25261
25608
 
@@ -25277,6 +25624,290 @@ var blockedUserSyncEngineOnLoginHandler = () => {
25277
25624
  };
25278
25625
  };
25279
25626
 
25627
+ function prepareBlockingUserPayload(response) {
25628
+ const { users, follows } = response, rest = __rest(response, ["users", "follows"]);
25629
+ return Object.assign(Object.assign({}, rest), { follows: follows.map(follow => {
25630
+ const followUser = users.find(user => user.userId === follow.from);
25631
+ return Object.assign(Object.assign({}, follow), { user: convertRawUserToInternalUser(followUser) });
25632
+ }), users: users.map(convertRawUserToInternalUser) });
25633
+ }
25634
+
25635
+ const BLOCK_LIST_LIMIT = 100;
25636
+ const TTL_MS = 5 * 60 * 1000; // 5 minutes
25637
+ /**
25638
+ * Session-scoped singleton engine that manages TTL-based fetching and caching
25639
+ * of blocking users (the "blocked-by" list — users who blocked the current
25640
+ * user). Provides a lazy `ensureFetched()` gate for the `getAllBlockingUsers()`
25641
+ * API. Directional inverse of {@link BlockedUserSyncEngine}.
25642
+ *
25643
+ * Key behaviours:
25644
+ * - `onSessionEstablished()` is a no-op — fetch is lazy, triggered only by consumer call
25645
+ * - `onSessionDestroyed()` resets `lastFetchedAt` to null (ensures fresh fetch on next session)
25646
+ * - `ensureFetched()` fetches from server only when cache is expired or never fetched
25647
+ * - `lastFetchedAt` is only updated on successful fetch
25648
+ * - reads query the follow cache live, so block/unblock changes are reflected
25649
+ * even within the TTL window
25650
+ *
25651
+ * @internal
25652
+ */
25653
+ class BlockingUserSyncEngine {
25654
+ constructor() {
25655
+ /** Epoch ms of last successful fetch. null = never fetched in this session. */
25656
+ this.lastFetchedAt = null;
25657
+ }
25658
+ /** No-op — fetch is lazy, triggered by consumer calling getAllBlockingUsers(). */
25659
+ // eslint-disable-next-line class-methods-use-this
25660
+ onSessionEstablished() {
25661
+ // intentionally empty
25662
+ }
25663
+ /** Resets state so the next session starts with a cold cache. */
25664
+ onSessionDestroyed() {
25665
+ this.lastFetchedAt = null;
25666
+ }
25667
+ /** No-op for this engine. */
25668
+ // eslint-disable-next-line class-methods-use-this
25669
+ onTokenExpired() {
25670
+ // intentionally empty
25671
+ }
25672
+ isCacheExpired() {
25673
+ if (this.lastFetchedAt === null)
25674
+ return true;
25675
+ return Date.now() - this.lastFetchedAt > TTL_MS;
25676
+ }
25677
+ /**
25678
+ * Ensures the local store is populated with fresh blocking-user data.
25679
+ *
25680
+ * - If the cache is still within the 5-minute TTL window: resolves immediately
25681
+ * (no server call).
25682
+ * - If the cache is expired (or never fetched): fetches from the server,
25683
+ * persists the payload to the cache, and updates `lastFetchedAt`.
25684
+ *
25685
+ * On failure the error propagates to the caller and `lastFetchedAt` is NOT
25686
+ * updated, so the next call will retry.
25687
+ */
25688
+ async ensureFetched() {
25689
+ if (!this.isCacheExpired())
25690
+ return;
25691
+ const client = getActiveClient();
25692
+ const { data } = await client.http.get('/api/v4/me/blockers', { params: { options: { limit: BLOCK_LIST_LIMIT }, isDeleted: false } });
25693
+ const cachedAt = client.cache && Date.now();
25694
+ const payload = prepareBlockingUserPayload(data);
25695
+ if (client.cache) {
25696
+ ingestInCache(payload, { cachedAt });
25697
+ }
25698
+ // Only update timestamp on success — failure leaves it unchanged so the
25699
+ // next call retries.
25700
+ this.lastFetchedAt = Date.now();
25701
+ }
25702
+ /**
25703
+ * Returns the "blocked-by" users by querying the follow cache live — the
25704
+ * incoming direction (`to === me`, `status === 'blocked'`). Reading the cache
25705
+ * (not a fetched snapshot) means RTE `user.didBlock` / `user.didUnblock`
25706
+ * changes are reflected even within the TTL window.
25707
+ *
25708
+ * Applies the spec-mandated query (REQ-012/013/014):
25709
+ * - filter `to === currentUserId`, `status === 'blocked'`, blocker not deleted
25710
+ * - sort by `updatedAt` DESC
25711
+ * - hard limit of 100 results
25712
+ */
25713
+ // eslint-disable-next-line class-methods-use-this
25714
+ getCachedUsers() {
25715
+ var _a;
25716
+ const client = getActiveClient();
25717
+ if (!client.cache)
25718
+ return [];
25719
+ const { userId } = client;
25720
+ return ((_a = queryCache(['follow', 'get'])) !== null && _a !== void 0 ? _a : [])
25721
+ .map(entry => entry.data)
25722
+ .filter(follow => (follow === null || follow === void 0 ? void 0 : follow.status) === 'blocked' && follow.to === userId)
25723
+ .sort((a, b) => { var _a, _b; return (((_a = a.updatedAt) !== null && _a !== void 0 ? _a : '') < ((_b = b.updatedAt) !== null && _b !== void 0 ? _b : '') ? 1 : -1); })
25724
+ .map(follow => { var _a; return (_a = pullFromCache(['user', 'get', follow.from])) === null || _a === void 0 ? void 0 : _a.data; })
25725
+ .filter((user) => user != null && user.isDeleted !== true)
25726
+ .slice(0, BLOCK_LIST_LIMIT)
25727
+ .map(userLinkedObject);
25728
+ }
25729
+ }
25730
+ let instance$2 = null;
25731
+ var BlockingUserSyncEngine$1 = {
25732
+ getInstance: () => {
25733
+ if (!instance$2)
25734
+ instance$2 = new BlockingUserSyncEngine();
25735
+ return instance$2;
25736
+ },
25737
+ };
25738
+
25739
+ var blockingUserSyncEngineOnLoginHandler = () => {
25740
+ const blockingUserSyncEngine = BlockingUserSyncEngine$1.getInstance();
25741
+ onSessionStateChange(state => {
25742
+ if (state === "established" /* Amity.SessionStates.ESTABLISHED */) {
25743
+ blockingUserSyncEngine.onSessionEstablished();
25744
+ }
25745
+ else if (state === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */) {
25746
+ blockingUserSyncEngine.onTokenExpired();
25747
+ }
25748
+ else {
25749
+ blockingUserSyncEngine.onSessionDestroyed();
25750
+ }
25751
+ });
25752
+ return () => {
25753
+ blockingUserSyncEngine.onSessionDestroyed();
25754
+ };
25755
+ };
25756
+
25757
+ function prepareFollowersPayload(response) {
25758
+ const { users, follows } = response, rest = __rest(response, ["users", "follows"]);
25759
+ return Object.assign(Object.assign({}, rest), { follows, users: users.map(convertRawUserToInternalUser) });
25760
+ }
25761
+ function prepareFollowingsPayload(response) {
25762
+ const { users, follows } = response, rest = __rest(response, ["users", "follows"]);
25763
+ return Object.assign(Object.assign({}, rest), { follows, users: users.map(convertRawUserToInternalUser) });
25764
+ }
25765
+ function prepareFollowStatusPayload(response) {
25766
+ const { follows } = response, rest = __rest(response, ["follows"]);
25767
+ return Object.assign(Object.assign({}, rest), { follows });
25768
+ }
25769
+
25770
+ /**
25771
+ * Subscribes to a block MQTT event (`user.didBlock` / `user.didUnblock`),
25772
+ * ingests the carried `FollowersPayload` (follows + users) into the cache so
25773
+ * the block-relationship rows (`['follow', 'get', from#to]`) and user rows are
25774
+ * kept current, then forwards the affected {@link Amity.FollowStatus} to the
25775
+ * caller.
25776
+ *
25777
+ * @hidden
25778
+ */
25779
+ const createBlockEventSubscriber = (event, callback) => {
25780
+ const client = getActiveClient();
25781
+ const filter = (data) => {
25782
+ const payload = prepareFollowersPayload(data);
25783
+ if (client.cache) {
25784
+ ingestInCache(payload);
25785
+ }
25786
+ callback(payload.follows[0]);
25787
+ };
25788
+ return createEventSubscriber(client, event, event, filter);
25789
+ };
25790
+
25791
+ /**
25792
+ * ```js
25793
+ * import { onUserDidBlock } from '@amityco/ts-sdk'
25794
+ * const dispose = onUserDidBlock(status => {
25795
+ * // ...
25796
+ * })
25797
+ * ```
25798
+ *
25799
+ * Fired when a block relationship is created in real time — either a user
25800
+ * blocks the current user (incoming) or the current user blocks someone on
25801
+ * another device (outgoing). The local block-relationship store is updated
25802
+ * before the callback runs.
25803
+ *
25804
+ * @param callback The function to call when the event was fired
25805
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25806
+ *
25807
+ * @category Block Events
25808
+ */
25809
+ const onUserDidBlock = (callback) => createBlockEventSubscriber('user.didBlock', callback);
25810
+
25811
+ /**
25812
+ * ```js
25813
+ * import { onUserDidUnblock } from '@amityco/ts-sdk'
25814
+ * const dispose = onUserDidUnblock(status => {
25815
+ * // ...
25816
+ * })
25817
+ * ```
25818
+ *
25819
+ * Fired when a block relationship is removed in real time — either a user
25820
+ * unblocks the current user (incoming) or the current user unblocks someone on
25821
+ * another device (outgoing). The local block-relationship store is updated
25822
+ * before the callback runs.
25823
+ *
25824
+ * @param callback The function to call when the event was fired
25825
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
25826
+ *
25827
+ * @category Block Events
25828
+ */
25829
+ const onUserDidUnblock = (callback) => createBlockEventSubscriber('user.didUnblock', callback);
25830
+
25831
+ /**
25832
+ * Keeps the follow cache current for incoming/outgoing block changes for the
25833
+ * whole session — the ingest happens as a side effect inside
25834
+ * createBlockEventSubscriber, so the one-shot `getAllBlockedUsers()` /
25835
+ * `getAllBlockingUsers()` reflect RTE block/unblock within the TTL window.
25836
+ *
25837
+ * Registered via `setupLoginSubscriptions`; the returned unsubscriber is torn
25838
+ * down on logout.
25839
+ */
25840
+ var blockRealtimeOnLoginHandler = () => {
25841
+ const disposers = [onUserDidBlock(() => { }), onUserDidUnblock(() => { })];
25842
+ return () => disposers.forEach(dispose => dispose());
25843
+ };
25844
+
25845
+ class CursorController {
25846
+ constructor(networkId, userId) {
25847
+ this.networkId = networkId;
25848
+ this.userId = userId;
25849
+ }
25850
+ static current() {
25851
+ try {
25852
+ const user = getCurrentUser();
25853
+ if (!user)
25854
+ return null;
25855
+ const networkId = getNetworkId(user);
25856
+ const { userId } = user;
25857
+ return networkId && userId ? new CursorController(networkId, userId) : null;
25858
+ }
25859
+ catch (_a) {
25860
+ return null;
25861
+ }
25862
+ }
25863
+ static isExpired(expiredAt) {
25864
+ return Date.now() >= expiredAt;
25865
+ }
25866
+ static clearOnLogout() {
25867
+ return onSessionStateChange(state => {
25868
+ var _a;
25869
+ if (state === "terminated" /* Amity.SessionStates.TERMINATED */)
25870
+ (_a = CursorController.current()) === null || _a === void 0 ? void 0 : _a.clear();
25871
+ });
25872
+ }
25873
+ get key() {
25874
+ return `amity:forYouFeed:cursor:${this.networkId}:${this.userId}`;
25875
+ }
25876
+ async get() {
25877
+ const raw = await getItem(this.key);
25878
+ if (!raw)
25879
+ return null;
25880
+ try {
25881
+ const parsed = JSON.parse(raw);
25882
+ if (typeof (parsed === null || parsed === void 0 ? void 0 : parsed.cursor) !== 'string' || typeof (parsed === null || parsed === void 0 ? void 0 : parsed.expiredAt) !== 'number')
25883
+ return null;
25884
+ return {
25885
+ cursor: parsed.cursor,
25886
+ expiredAt: parsed.expiredAt,
25887
+ reachedEndOfFeed: parsed.reachedEndOfFeed === true,
25888
+ };
25889
+ }
25890
+ catch (_a) {
25891
+ return null;
25892
+ }
25893
+ }
25894
+ async set(value) {
25895
+ await setItem(this.key, JSON.stringify(value));
25896
+ }
25897
+ async markReachedEndOfFeed(expiredAt) {
25898
+ var _a;
25899
+ const stored = await this.get();
25900
+ await this.set({
25901
+ cursor: (_a = stored === null || stored === void 0 ? void 0 : stored.cursor) !== null && _a !== void 0 ? _a : '',
25902
+ expiredAt,
25903
+ reachedEndOfFeed: true,
25904
+ });
25905
+ }
25906
+ async clear() {
25907
+ await setItem(this.key, '');
25908
+ }
25909
+ }
25910
+
25280
25911
  const EVENTS = [
25281
25912
  'disconnected',
25282
25913
  'error',
@@ -25466,7 +26097,7 @@ const setupLoginSubscriptions = (unsubWatcher) => {
25466
26097
  // NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
25467
26098
  // the channel because currently backend can't handle this, so every time a user is banned from
25468
26099
  // a channel or the channel is deleted the channel's unread count will not be reset to zero
25469
- onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler(), blockedUserSyncEngineOnLoginHandler());
26100
+ onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler(), blockedUserSyncEngineOnLoginHandler(), blockingUserSyncEngineOnLoginHandler(), blockRealtimeOnLoginHandler(), resetAutoSubscriptionsOnLogout(), CursorController.clearOnLogout());
25470
26101
  if (client.useLegacyUnreadCount) {
25471
26102
  subscriptions.push(readReceiptSyncEngineOnLoginHandler());
25472
26103
  }
@@ -26165,16 +26796,13 @@ const onMessageCreatedMqtt = (callback) => {
26165
26796
  }
26166
26797
  if (client.useLegacyUnreadCount) {
26167
26798
  rawPayload.messages.forEach(message => {
26168
- var _a, _b;
26799
+ var _a, _b, _c;
26169
26800
  const channelUnread = (_a = pullFromCache([
26170
26801
  'channelUnread',
26171
26802
  'get',
26172
26803
  message.channelId,
26173
26804
  ])) === null || _a === void 0 ? void 0 : _a.data;
26174
- if (!channelUnread ||
26175
- channelUnread.lastSegment >= message.segment ||
26176
- typeof channelUnread.readToSegment !== 'number' ||
26177
- typeof channelUnread.lastMentionedSegment !== 'number')
26805
+ if (!channelUnread || channelUnread.lastSegment >= message.segment)
26178
26806
  return;
26179
26807
  const lastSegment = message.segment;
26180
26808
  const isMentionedInMessage = (_b = message.mentionedUsers) === null || _b === void 0 ? void 0 : _b.some(mention => {
@@ -26186,7 +26814,8 @@ const onMessageCreatedMqtt = (callback) => {
26186
26814
  const lastMentionedSegment = isMentionedInMessage
26187
26815
  ? message.segment
26188
26816
  : channelUnread.lastMentionedSegment;
26189
- const updatedChannelUnread = Object.assign(Object.assign({}, channelUnread), { lastSegment, unreadCount: Math.max(lastSegment - channelUnread.readToSegment, 0), lastMentionedSegment, isMentioned: !(channelUnread.readToSegment >= lastMentionedSegment) });
26817
+ const readToSegment = (_c = channelUnread.readToSegment) !== null && _c !== void 0 ? _c : 0;
26818
+ const updatedChannelUnread = Object.assign(Object.assign({}, channelUnread), { lastSegment, unreadCount: Math.max(lastSegment - readToSegment, 0), lastMentionedSegment, isMentioned: typeof lastMentionedSegment === 'number' && readToSegment < lastMentionedSegment });
26190
26819
  pushToCache(['channelUnread', 'get', message.channelId], updatedChannelUnread);
26191
26820
  fireEvent('local.channelUnread.updated', [updatedChannelUnread]);
26192
26821
  });
@@ -26569,15 +27198,18 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
26569
27198
  validateUrls,
26570
27199
  validateTexts,
26571
27200
  getFeedSettings,
27201
+ getCoreUserSettings,
26572
27202
  getSocialSettings,
27203
+ getChatSettings,
26573
27204
  getVisitorDeviceId: getDeviceId,
26574
- getMessagePreviewSetting,
27205
+ getMessagePreviewSetting: getMessagePreviewSetting$1,
26575
27206
  onRTEConnectionStateChange,
26576
27207
  use: () => setActiveClient(client),
26577
27208
  isUnreadCountEnabled,
26578
27209
  useLegacyUnreadCount,
26579
27210
  getMarkerSyncConsistentMode,
26580
27211
  getProductCatalogueSetting,
27212
+ getForYouFeedSetting,
26581
27213
  /**
26582
27214
  * Prefix for the deviceId key in the local storage or async storage.
26583
27215
  * This is allow user to have multiple SDK client and Mqtt client within the same app.
@@ -26889,6 +27521,13 @@ const getLinkPreviewMetadata = async (url) => {
26889
27521
  return data;
26890
27522
  };
26891
27523
 
27524
+ const CONTENT_TYPE_CONFIG = {
27525
+ [AmitySharableContentType.POST]: { key: 'posts', placeholder: 'postId' },
27526
+ [AmitySharableContentType.COMMUNITY]: { key: 'communities', placeholder: 'communityId' },
27527
+ [AmitySharableContentType.USER]: { key: 'users', placeholder: 'userId' },
27528
+ [AmitySharableContentType.LIVESTREAM]: { key: 'livestream', placeholder: 'livestream' },
27529
+ [AmitySharableContentType.EVENT]: { key: 'events', placeholder: 'eventId' },
27530
+ };
26892
27531
  /**
26893
27532
  * ```js
26894
27533
  * import Client from '@amityco/ts-sdk-react-native'
@@ -26904,9 +27543,29 @@ const getLinkPreviewMetadata = async (url) => {
26904
27543
  * @async
26905
27544
  */
26906
27545
  const getShareableLinkConfiguration = async () => {
27546
+ var _a, _b;
26907
27547
  const client = getActiveClient();
26908
27548
  const { data } = await client.http.get(`/api/v3/network-settings/shareable-deep-links`);
26909
- return data;
27549
+ const domain = (_a = data.domain) !== null && _a !== void 0 ? _a : '';
27550
+ const patterns = (_b = data.patterns) !== null && _b !== void 0 ? _b : {};
27551
+ return {
27552
+ domain,
27553
+ patterns,
27554
+ isEnabled(contentType) {
27555
+ const { key } = CONTENT_TYPE_CONFIG[contentType];
27556
+ return !!domain && !!patterns[key];
27557
+ },
27558
+ getPattern(contentType) {
27559
+ const { key } = CONTENT_TYPE_CONFIG[contentType];
27560
+ return patterns[key] || null;
27561
+ },
27562
+ generateLink(contentType, referenceId) {
27563
+ const { key, placeholder } = CONTENT_TYPE_CONFIG[contentType];
27564
+ if (!domain || !patterns[key])
27565
+ return null;
27566
+ return domain + patterns[key].replace(`{${placeholder}}`, referenceId);
27567
+ },
27568
+ };
26910
27569
  };
26911
27570
 
26912
27571
  /**
@@ -27097,6 +27756,205 @@ const setAccessTokenHandler = (accessTokenHandler) => {
27097
27756
  client.accessTokenHandler = accessTokenHandler;
27098
27757
  };
27099
27758
 
27759
+ function parseRolesFilter(listenFromRoleIds, ignoreFromRoleIds) {
27760
+ if (ignoreFromRoleIds && ignoreFromRoleIds.length > 0) {
27761
+ return { type: 'not', roleIds: ignoreFromRoleIds };
27762
+ }
27763
+ if (listenFromRoleIds && listenFromRoleIds.length > 0) {
27764
+ return { type: NotificationRolesFilterTypeEnum.ONLY, roleIds: listenFromRoleIds };
27765
+ }
27766
+ return { type: NotificationRolesFilterTypeEnum.ALL };
27767
+ }
27768
+ function serializeRolesFilter(rolesFilter) {
27769
+ if ((rolesFilter === null || rolesFilter === void 0 ? void 0 : rolesFilter.type) === NotificationRolesFilterTypeEnum.ONLY) {
27770
+ return { listenFromRoleIds: rolesFilter.roleIds };
27771
+ }
27772
+ return { listenFromRoleIds: [] };
27773
+ }
27774
+ class ChannelNotifications {
27775
+ constructor(channelId) {
27776
+ this.channelId = channelId;
27777
+ }
27778
+ async enable() {
27779
+ const client = getActiveClient();
27780
+ const body = {
27781
+ level: NotificationSettingsLevelEnum.CHANNEL,
27782
+ channelId: this.channelId,
27783
+ isPushNotifiable: true,
27784
+ };
27785
+ await client.http.post('/api/v3/notification/setting', body);
27786
+ }
27787
+ async disable() {
27788
+ const client = getActiveClient();
27789
+ const body = {
27790
+ level: NotificationSettingsLevelEnum.CHANNEL,
27791
+ channelId: this.channelId,
27792
+ isPushNotifiable: false,
27793
+ };
27794
+ await client.http.post('/api/v3/notification/setting', body);
27795
+ }
27796
+ async getSettings() {
27797
+ const client = getActiveClient();
27798
+ const { data } = await client.http.get(`/api/v3/notification/setting?level=${NotificationSettingsLevelEnum.CHANNEL}&channelId=${encodeURIComponent(this.channelId)}`);
27799
+ return { isEnabled: data.isPushNotifiable };
27800
+ }
27801
+ }
27802
+ class UserNotifications {
27803
+ async enable(modules) {
27804
+ var _a;
27805
+ const client = getActiveClient();
27806
+ const notifiableEvents = (_a = modules === null || modules === void 0 ? void 0 : modules.map(module => (Object.assign({ moduleName: module.moduleName, isPushNotifiable: module.isEnabled }, serializeRolesFilter(module.rolesFilter))))) !== null && _a !== void 0 ? _a : [];
27807
+ const body = {
27808
+ level: NotificationSettingsLevelEnum.USER,
27809
+ isPushNotifiable: true,
27810
+ notifiableEvents,
27811
+ };
27812
+ await client.http.post('/api/v3/notification/setting', body);
27813
+ }
27814
+ async disableAllNotifications() {
27815
+ const client = getActiveClient();
27816
+ const body = {
27817
+ level: NotificationSettingsLevelEnum.USER,
27818
+ isPushNotifiable: false,
27819
+ notifiableEvents: [],
27820
+ };
27821
+ await client.http.post('/api/v3/notification/setting', body);
27822
+ }
27823
+ async getSettings() {
27824
+ var _a;
27825
+ const client = getActiveClient();
27826
+ const { data } = await client.http.get(`/api/v3/notification/setting?level=${NotificationSettingsLevelEnum.USER}`);
27827
+ const validModuleNames = Object.values(UserNotificationModuleNameEnum);
27828
+ const modules = ((_a = data.notifiableEvents) !== null && _a !== void 0 ? _a : [])
27829
+ .filter(e => e.moduleName != null && validModuleNames.includes(e.moduleName))
27830
+ .map(e => ({
27831
+ moduleName: e.moduleName,
27832
+ isEnabled: e.isPushNotifiable,
27833
+ rolesFilter: parseRolesFilter(e.listenFromRoleIds, e.ignoreFromRoleIds),
27834
+ }));
27835
+ return { isEnabled: data.isPushNotifiable, modules };
27836
+ }
27837
+ }
27838
+ class CommunityNotifications {
27839
+ constructor(communityId) {
27840
+ this.communityId = communityId;
27841
+ }
27842
+ async enable(events) {
27843
+ var _a;
27844
+ const client = getActiveClient();
27845
+ const notifiableEvents = (_a = events === null || events === void 0 ? void 0 : events.map(event => (Object.assign({ moduleName: UserNotificationModuleNameEnum.SOCIAL, name: event.eventName, isPushNotifiable: event.isEnabled }, serializeRolesFilter(event.rolesFilter))))) !== null && _a !== void 0 ? _a : [];
27846
+ const body = {
27847
+ level: NotificationSettingsLevelEnum.COMMUNITY,
27848
+ communityId: this.communityId,
27849
+ isPushNotifiable: true,
27850
+ notifiableEvents,
27851
+ };
27852
+ await client.http.post('/api/v3/notification/setting', body);
27853
+ }
27854
+ async disable() {
27855
+ const client = getActiveClient();
27856
+ const body = {
27857
+ level: NotificationSettingsLevelEnum.COMMUNITY,
27858
+ communityId: this.communityId,
27859
+ isPushNotifiable: false,
27860
+ notifiableEvents: [],
27861
+ };
27862
+ await client.http.post('/api/v3/notification/setting', body);
27863
+ }
27864
+ async getSettings() {
27865
+ var _a;
27866
+ const client = getActiveClient();
27867
+ const { data } = await client.http.get(`/api/v3/notification/setting?level=${NotificationSettingsLevelEnum.COMMUNITY}&communityId=${encodeURIComponent(this.communityId)}`);
27868
+ const validEventNames = Object.values(CommunityNotificationEventNameEnum);
27869
+ const events = ((_a = data.notifiableEvents) !== null && _a !== void 0 ? _a : [])
27870
+ .filter(e => e.name != null && validEventNames.includes(e.name))
27871
+ .map(e => ({
27872
+ eventName: e.name,
27873
+ isEnabled: e.isPushNotifiable,
27874
+ isNetworkEnabled: e.isNetworkEnabled,
27875
+ rolesFilter: parseRolesFilter(e.listenFromRoleIds, e.ignoreFromRoleIds),
27876
+ }));
27877
+ return { isEnabled: data.isPushNotifiable, events };
27878
+ }
27879
+ }
27880
+ class Notifications {
27881
+ user() {
27882
+ return new UserNotifications();
27883
+ }
27884
+ community(communityId) {
27885
+ return new CommunityNotifications(communityId);
27886
+ }
27887
+ channel(channelId) {
27888
+ return new ChannelNotifications(channelId);
27889
+ }
27890
+ }
27891
+ const notifications = () => new Notifications();
27892
+
27893
+ /* begin_public_function
27894
+ id: client.enable_auto_subscriptions
27895
+ */
27896
+ /**
27897
+ * ```js
27898
+ * import { Client, AmityAutoSubscription } from '@amityco/ts-sdk'
27899
+ * Client.enableAutoSubscriptions([AmityAutoSubscription.BLOCK])
27900
+ * ```
27901
+ *
27902
+ * Enables one or more managed auto-subscription handles. Managed handles are
27903
+ * re-applied on every (re)connect and ref-counted. All handles are on by
27904
+ * default; use this to re-enable handles previously turned off via
27905
+ * {@link disableAutoSubscriptions}. Synchronous fire-and-forget — the registry
27906
+ * updates immediately and the broker subscribe is retried on reconnect.
27907
+ *
27908
+ * @param features the {@link AmityAutoSubscription} handles to enable
27909
+ *
27910
+ * @category Client API
27911
+ */
27912
+ const enableAutoSubscriptions = (features) => {
27913
+ const manager = getAutoSubscriptionManager();
27914
+ features.forEach(feature => manager.subscribe(feature));
27915
+ };
27916
+ /* end_public_function */
27917
+ /* begin_public_function
27918
+ id: client.disable_auto_subscriptions
27919
+ */
27920
+ /**
27921
+ * ```js
27922
+ * import { Client, AmityAutoSubscription } from '@amityco/ts-sdk'
27923
+ * Client.disableAutoSubscriptions([AmityAutoSubscription.LIVESTREAM])
27924
+ * ```
27925
+ *
27926
+ * Disables one or more managed auto-subscription handles. The change persists
27927
+ * across reconnect (it is not silently re-enabled) until
27928
+ * {@link enableAutoSubscriptions} is called again. Synchronous fire-and-forget.
27929
+ *
27930
+ * @param features the {@link AmityAutoSubscription} handles to disable
27931
+ *
27932
+ * @category Client API
27933
+ */
27934
+ const disableAutoSubscriptions = (features) => {
27935
+ const manager = getAutoSubscriptionManager();
27936
+ features.forEach(feature => manager.unsubscribe(feature));
27937
+ };
27938
+ /* end_public_function */
27939
+ /* begin_public_function
27940
+ id: client.auto_subscriptions
27941
+ */
27942
+ /**
27943
+ * ```js
27944
+ * import { Client } from '@amityco/ts-sdk'
27945
+ * Client.autoSubscriptions().forEach(s => console.log(s.feature, s.isActive, s.topicCount))
27946
+ * ```
27947
+ *
27948
+ * Inspects the managed auto-subscription registry — each handle's `isActive`,
27949
+ * `isSystem`, and `topicCount`.
27950
+ *
27951
+ * @returns a snapshot of the managed subscription registry
27952
+ *
27953
+ * @category Client API
27954
+ */
27955
+ const autoSubscriptions = () => getAutoSubscriptionManager().subscriptions();
27956
+ /* end_public_function */
27957
+
27100
27958
  /**
27101
27959
  * ```js
27102
27960
  * import { onChannelMarkerFetched } from '@amityco/ts-sdk-react-native'
@@ -27474,12 +28332,19 @@ var index$s = /*#__PURE__*/Object.freeze({
27474
28332
  getSocialSettings: getSocialSettings,
27475
28333
  getShareableLinkConfiguration: getShareableLinkConfiguration,
27476
28334
  getProductCatalogueSetting: getProductCatalogueSetting,
28335
+ getForYouFeedSetting: getForYouFeedSetting,
27477
28336
  loginAsVisitor: loginAsVisitor,
27478
28337
  loginAsBot: loginAsBot,
27479
28338
  getCurrentUser: getCurrentUser,
27480
28339
  getCurrentUserType: getCurrentUserType,
27481
28340
  setCurrentUserType: setCurrentUserType,
27482
28341
  setAccessTokenHandler: setAccessTokenHandler,
28342
+ getChatSettings: getChatSettings,
28343
+ getCoreUserSettings: getCoreUserSettings,
28344
+ notifications: notifications,
28345
+ enableAutoSubscriptions: enableAutoSubscriptions,
28346
+ disableAutoSubscriptions: disableAutoSubscriptions,
28347
+ autoSubscriptions: autoSubscriptions,
27483
28348
  onConnectionError: onConnectionError,
27484
28349
  onClientDisconnected: onClientDisconnected,
27485
28350
  onClientBanned: onClientBanned,
@@ -27497,19 +28362,6 @@ var index$s = /*#__PURE__*/Object.freeze({
27497
28362
  getMarkerSyncConsistentMode: getMarkerSyncConsistentMode
27498
28363
  });
27499
28364
 
27500
- function prepareFollowersPayload(response) {
27501
- const { users, follows } = response, rest = __rest(response, ["users", "follows"]);
27502
- return Object.assign(Object.assign({}, rest), { follows, users: users.map(convertRawUserToInternalUser) });
27503
- }
27504
- function prepareFollowingsPayload(response) {
27505
- const { users, follows } = response, rest = __rest(response, ["users", "follows"]);
27506
- return Object.assign(Object.assign({}, rest), { follows, users: users.map(convertRawUserToInternalUser) });
27507
- }
27508
- function prepareFollowStatusPayload(response) {
27509
- const { follows } = response, rest = __rest(response, ["follows"]);
27510
- return Object.assign(Object.assign({}, rest), { follows });
27511
- }
27512
-
27513
28365
  /* begin_public_function
27514
28366
  id: user.relationship.block
27515
28367
  */
@@ -28687,6 +29539,8 @@ var index$r = /*#__PURE__*/Object.freeze({
28687
29539
  __proto__: null,
28688
29540
  blockUser: blockUser,
28689
29541
  unBlockUser: unBlockUser,
29542
+ onUserDidBlock: onUserDidBlock,
29543
+ onUserDidUnblock: onUserDidUnblock,
28690
29544
  follow: follow,
28691
29545
  unfollow: unfollow,
28692
29546
  acceptMyFollower: acceptMyFollower,
@@ -29516,7 +30370,7 @@ const getWatchSessionStorage = () => {
29516
30370
  return storageInstance;
29517
30371
  };
29518
30372
 
29519
- const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAARz+hmBgi8pJ\nQb8LeY41gtHhk+ACMwRfhsn7GqpqRQNG2qU0755mzZuVDUqjQMGSo8THJB7O+OJs\nflbZRkFXlFoFOVNw1UpNOgwEQZ6wB9oRwzepTJAfF1sVhm/o/ixvXh1zDFNDy6yZ\npXyiiJHUVxqyjllZhxnwdvjoVtDs6hW6awG09bB9nh/TTejlUKXoAgzqVwu/1QMu\nUVViET495elEe19aUarEy+oL2iKeXCEvqda/pWNBdbieFyJvvZ08HN8dPuT88wq2\njZLEAth1vrwQ2IAa4ktaLcBQdLJgIkrbDvAiVZ8lQAjS/bq5vXQikTGvoPlC5bbn\nvuOM/3eLAgMBAAECggEAVZ+peHAghq2QVj71nX5lxsNCKaCyYwixSJBpfouTt7Rz\nE6PpzMOXFi1W1o+I22jDakuSM2SOQKqI/u0QefB0r0O/KVk5NrZHXk0mkrdYtxOp\nUgaGyf8UvmjB+8VqHrNKyZdk9qtmbnNj01kTTcAtmE4H39zPR7eR/8Rul94vaZbs\nwCnKJS3mLT3JxyGug6lxanveKkjG+CKC1nJQYWaxCJxaFSzbwXQPvDhB+TvrIbee\npd5v4EAyEJohpr+T9oDGGJkb/KARBZCtwLyB976PKJwwBA8MRVL1i5QwawuMiMq5\nUtnOnbGKtCeFzaLbNU0Qi8bqyims84EQxC6DOu1fkQKBgQDdvsoBsEhsOXV7hlIJ\naEd0eSJZVkdqimxH8uGoMM2FeNaOrcB6yBXqTSP0R3OIyf8eaY6yjRvP30ZNXcll\n/gD3O1Mu6YmWQdt1W2WA6pKOsUuPXasf0pdOF7IiFZKlSabz5YHXFqwVuqm8loaj\nsXel3YWqPVdHiankE7tz+3ssnQKBgQDdqi4TNdD1MdEpihx19jr0QjUiXW3939FK\nqp30HESPEGDGQzXdmJgif9HhZb+cJSuWaHEbjgBrYahvgCF+y6LbEpOD+D/dmT+s\nDEAQaR84sah6dokwPjV8fjBSrcVFjCS+doxv0d3p/9OUEeyUhFrY03nxtIEYkLIE\n/Zvn37b4RwKBgQCLENVFe9XfsaVhQ5r9dV2iyTlmh7qgMZG5CbTFs12hQGhm8McO\n+Z7s41YSJCFr/yq1WwP4LJDtrBw99vyQr1zRsG35tNLp3gGRNzGQSQyC2uQFVHw2\np+7mNewsfhUK/gbrXNsyFnDz6635rPlhfbII3sWuP2wWXFqkxE9CbMwR7QKBgQC6\nawDMzxmo2/iYArrkyevSuEuPVxvFwpF1RgAI6C0QVCnPE38dmdN4UB7mfHekje4W\nVEercMURidPp0cxZolCYBQtilUjAyL0vqC3In1/Ogjq6oy3FEMxSop1pKxMY5j+Q\nnoqFD+6deLUrddeNH7J3X4LSr4dSbX4JjG+tlgt+yQKBgQCuwTL4hA6KqeInQ0Ta\n9VQX5Qr8hFlqJz1gpymi/k63tW/Ob8yedbg3WWNWyShwRMFYyY9S81ITFWM95uL6\nvF3x9rmRjwElJw9PMwVu6dmf/CO0Z1wzXSp2VVD12gbrUD/0/d7MUoJ9LgC8X8f/\nn0txLHYGHbx+nf95+JUg6lV3hg==\n-----END PRIVATE KEY-----";
30373
+ const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHo80SecH7FuF2\nhFYnb+l26/VN8UMLXAQFLnxciNTEwkGVFMpdezlH8rU2HtUJL4RETogbAOLVY0XM\njs6sPn8G1nALmh9qeDpUtVqFOVtBHxEZ910TLOtQiunjqJKO5nWdqZ71EC3OFluR\niGQkO84BiIFbv37ub7xl3S8XarbtKoLcyVpkDHi+1wx1pgCAn6gtBUgckPL5NR8j\nLseabl3HAXQfhTCKo4tmOFM2Dxwl1IUMmIJrJg/aIU/U0tj/1Eoo7mG0JcNWX19l\nW3EecCbi0ncCJOrkUdwlBrcjaMayaX/ubEwyUeTGiLdyc4L3GRLHjyK8xgVNXRMH\nbZWJ2a5NAgMBAAECggEASxuE+35zTFO/XydKgmvIGcWL9FbgMlXb7Vcf0nBoG945\nbiz0NVc2paraIhJXc608xbYF3qLmtAE1MVBI0ORyRdBHNxY024l/6H6SH60Ed+uI\nM4ysp5ourY6Vj+DLwpdRiI9YDjqYAQDIUmhNxJP7XPhOMoZI6st+xZQBM34ic/bv\nAMSJm9OZphSp3+qXVkFZztr2mxD2EZSJJLYxi8BCdgM2qhazalbcJ6zDKHCZWVWm\n8RRxDGldyMb/237JxETzP40tAlzOZDmBAbUgEnurDJ93RVDIE3rbZUshwgeQd18a\nem096mWgvB1AIKYgsTAR3pw+V19YWAjq/glP6fz8wQKBgQD/oQq+ukKF0PRgBeM5\ngeTjSwsdGppQLmf5ndujvoiz/TpdjDEPu6R8kigQr1rG2t4K/yfdZoI8RdmJD1al\n3Q7N9hofooSy4rj6E3txzWZCHJjHad2cnCp/O26HiReGAl7wTcfTmNdiFHhZQzm5\nJBkvWAiwuvQMNfEbnXxw6/vIDwKBgQDH7fX8gsc77JLvAWgp1MaQN/sbqVb6JeT1\nFQfR8E/WFCSmzQBtNzd5KgYuCeelwr/8DyYytvN2BzCYZXp73gI1jF3YlW5jVn74\nOY6TwQ095digwo6Z0yuxopdIOApKgAkL9PRKgNrqAf3NAyMua6lOGifzjDojC3KU\nfylQmxMn4wKBgHp2B9O/H0dEBw5JQ8W0+JX6yWQz7mEjGiR2/1W+XXb8hQ1zr709\nw1r6Gb+EghRpnZ3fBpYGGbYOMFx8wKHM+N6qW3F0ReX8v2juFGE8aRSa5oYBrWzt\nU16Idjbv8hj84cZ1PJmdyvDtpYn9rpWHOZl4rxEbPvbqkIsOMyNVqdT5AoGAOSge\nmwIIU2le2FVeohbibXiToWTYKMuMmURZ5/r72AgKMmWJKbAPe+Q3wBG01/7FRBpQ\noU8Ma0HC8s6QJbliiEyIx9JwrJWd1vkdecBHONrtA4ibm/5zD2WcOllLF+FitLhi\n3qnX6+6F0IaFGFBPJrTzlv0P4dTz/OAdv52V7GECgYEA2TttOKBAqWllgOaZOkql\nLVMJVmgR7s6tLi1+cEP8ZcapV9aRbRzTAKXm4f8AEhtlG9F9kCOvHYCYGi6JaiWJ\nZkHjeex3T+eE6Di6y5Bm/Ift5jtVhJ4jCVwHOKTMej79NPUFTJfv8hCo29haBDv6\nRXFrv+T21KCcw8k3sJeJWWQ=\n-----END PRIVATE KEY-----";
29520
30374
  /*
29521
30375
  * The crypto algorithm used for importing key and signing string
29522
30376
  */
@@ -30838,6 +31692,10 @@ const postLinkedObject = (post) => {
30838
31692
  const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
30839
31693
  analyticsEngineInstance.markPostAsViewed(post.postId);
30840
31694
  },
31695
+ markAsMeaningfullyViewed: (feedRenderPosition) => {
31696
+ const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
31697
+ analyticsEngineInstance.markPostAsMeaningfullyViewed(post.postId, feedRenderPosition);
31698
+ },
30841
31699
  },
30842
31700
  get productTags() {
30843
31701
  var _a, _b;
@@ -31027,6 +31885,11 @@ const addReaction$1 = async (referenceType, referenceId, reactionName, reference
31027
31885
  });
31028
31886
  return true;
31029
31887
  }
31888
+ if (referenceType === 'message') {
31889
+ upsertInCache(['message', 'get', referenceId], updatedModel);
31890
+ fireEvent('local.message.updated', { messages: [updatedModel] });
31891
+ return true;
31892
+ }
31030
31893
  }
31031
31894
  return true;
31032
31895
  };
@@ -31105,7 +31968,7 @@ const removeReaction$1 = async (referenceType, referenceId, reactionName, refere
31105
31968
  return true;
31106
31969
  }
31107
31970
  if (referenceType === 'story') {
31108
- fireEvent('local.story.reactionAdded', {
31971
+ fireEvent('local.story.reactionRemoved', {
31109
31972
  story: updatedModel,
31110
31973
  reactor: {
31111
31974
  userId: client.userId,
@@ -31115,6 +31978,11 @@ const removeReaction$1 = async (referenceType, referenceId, reactionName, refere
31115
31978
  });
31116
31979
  return true;
31117
31980
  }
31981
+ if (referenceType === 'message') {
31982
+ upsertInCache(['message', 'get', referenceId], updatedModel);
31983
+ fireEvent('local.message.updated', { messages: [updatedModel] });
31984
+ return true;
31985
+ }
31118
31986
  }
31119
31987
  return true;
31120
31988
  };
@@ -31387,7 +32255,7 @@ const createEventResponseSubscriber = (event, callback) => {
31387
32255
  const eventResponse = pullFromCache([
31388
32256
  'eventResponse',
31389
32257
  'get',
31390
- payload.eventResponses[0].eventId,
32258
+ unpackedPayload.eventResponses[0].userId,
31391
32259
  ]);
31392
32260
  callback(eventResponse.data);
31393
32261
  }
@@ -32051,7 +32919,38 @@ const getAllBlockedUsers = async () => {
32051
32919
  const engine = BlockedUserSyncEngine$1.getInstance();
32052
32920
  // Ensure data is fetched (no-op if cache is fresh)
32053
32921
  await engine.ensureFetched();
32054
- // Read from the engine's bounded ID list — O(blocked users) not O(cache size)
32922
+ return engine.getCachedUsers();
32923
+ };
32924
+ /* end_public_function */
32925
+
32926
+ /* begin_public_function
32927
+ id: user.get_all_blocking_users
32928
+ */
32929
+ /**
32930
+ * ```js
32931
+ * import { UserRepository } from '@amityco/ts-sdk'
32932
+ * const blockingUsers = await UserRepository.getAllBlockingUsers()
32933
+ * ```
32934
+ *
32935
+ * Returns all users who have blocked the current user
32936
+ * non-paginated list (limit 100) with TTL-based caching (5-minute window). Within the
32937
+ * TTL window, subsequent calls resolve instantly from the local store without any
32938
+ * server call. After the TTL expires, the next call triggers a fresh server fetch.
32939
+ *
32940
+ * The directional inverse of {@link getAllBlockedUsers}.
32941
+ *
32942
+ * @returns A promise that resolves to an array of blocking {@link Amity.User} objects
32943
+ *
32944
+ * @category Block API
32945
+ * @async
32946
+ */
32947
+ const getAllBlockingUsers = async () => {
32948
+ const client = getActiveClient();
32949
+ client.log('user/getAllBlockingUsers');
32950
+ const engine = BlockingUserSyncEngine$1.getInstance();
32951
+ // Ensure data is fetched (no-op if cache is fresh)
32952
+ await engine.ensureFetched();
32953
+ // Read from the engine's bounded ID list — O(blocking users) not O(cache size)
32055
32954
  return engine.getCachedUsers();
32056
32955
  };
32057
32956
  /* end_public_function */
@@ -32434,6 +33333,12 @@ class BlockedUserPaginationController extends PaginationController {
32434
33333
  }
32435
33334
  }
32436
33335
 
33336
+ var EnumBlockActions;
33337
+ (function (EnumBlockActions) {
33338
+ EnumBlockActions["OnBlocked"] = "onBlocked";
33339
+ EnumBlockActions["OnUnblocked"] = "onUnblocked";
33340
+ })(EnumBlockActions || (EnumBlockActions = {}));
33341
+
32437
33342
  class BlockedUserQueryStreamController extends QueryStreamController {
32438
33343
  constructor(query, cacheKey, notifyChange, preparePayload) {
32439
33344
  super(query, cacheKey);
@@ -32463,11 +33368,16 @@ class BlockedUserQueryStreamController extends QueryStreamController {
32463
33368
  }
32464
33369
  reactor(action) {
32465
33370
  return (targetUser) => {
32466
- var _a;
32467
- if (action === EnumFollowActions.OnFollowed) {
33371
+ var _a, _b;
33372
+ const isRemoval = action === EnumFollowActions.OnFollowed || action === EnumBlockActions.OnUnblocked;
33373
+ const isAddition = action === EnumBlockActions.OnBlocked;
33374
+ if (isRemoval || isAddition) {
32468
33375
  const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
32469
- const updatedCollection = collection === null || collection === void 0 ? void 0 : collection.data.filter(id => id !== targetUser.userId);
32470
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: updatedCollection }));
33376
+ const ids = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
33377
+ const data = isAddition
33378
+ ? [...new Set([...ids, targetUser.userId])]
33379
+ : ids.filter(id => id !== targetUser.userId);
33380
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data }));
32471
33381
  }
32472
33382
  this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
32473
33383
  };
@@ -32522,7 +33432,6 @@ class BlockedUserLiveCollectionController extends LiveCollectionController {
32522
33432
  fn: onUserDeleted$2,
32523
33433
  action: EnumUserActions.OnUserDeleted,
32524
33434
  },
32525
- // In the case of unblocking a user, we need to subscribe to the follow events
32526
33435
  {
32527
33436
  fn: convertEventPayload(onLocalUserFollowed, 'to', 'user'),
32528
33437
  action: EnumFollowActions.OnFollowed,
@@ -32531,6 +33440,28 @@ class BlockedUserLiveCollectionController extends LiveCollectionController {
32531
33440
  fn: convertEventPayload(onUserFollowed, 'to', 'user'),
32532
33441
  action: EnumFollowActions.OnFollowed,
32533
33442
  },
33443
+ {
33444
+ fn: (reactor) => onUserDidBlock(status => {
33445
+ var _a;
33446
+ if (status.from !== getActiveClient().userId)
33447
+ return;
33448
+ const blocked = (_a = pullFromCache(['user', 'get', status.to])) === null || _a === void 0 ? void 0 : _a.data;
33449
+ if (blocked)
33450
+ reactor(blocked);
33451
+ }),
33452
+ action: EnumBlockActions.OnBlocked,
33453
+ },
33454
+ {
33455
+ fn: (reactor) => onUserDidUnblock(status => {
33456
+ var _a;
33457
+ if (status.from !== getActiveClient().userId)
33458
+ return;
33459
+ const blocked = (_a = pullFromCache(['user', 'get', status.to])) === null || _a === void 0 ? void 0 : _a.data;
33460
+ if (blocked)
33461
+ reactor(blocked);
33462
+ }),
33463
+ action: EnumBlockActions.OnUnblocked,
33464
+ },
32534
33465
  ]);
32535
33466
  }
32536
33467
  notifyChange({ origin, loading, error }) {
@@ -32598,6 +33529,184 @@ const getBlockedUsers = (params, callback, config) => {
32598
33529
  };
32599
33530
  /* end_public_function */
32600
33531
 
33532
+ class BlockingUserQueryStreamController extends QueryStreamController {
33533
+ constructor(query, cacheKey, notifyChange, preparePayload) {
33534
+ super(query, cacheKey);
33535
+ this.notifyChange = notifyChange;
33536
+ this.preparePayload = preparePayload;
33537
+ }
33538
+ async saveToMainDB(response) {
33539
+ const processedPayload = await this.preparePayload(response);
33540
+ const client = getActiveClient();
33541
+ const cachedAt = client.cache && Date.now();
33542
+ if (client.cache) {
33543
+ ingestInCache(processedPayload, { cachedAt });
33544
+ }
33545
+ }
33546
+ appendToQueryStream(response, direction, refresh = false) {
33547
+ var _a, _b;
33548
+ if (refresh) {
33549
+ pushToCache(this.cacheKey, {
33550
+ data: response.users.map(getResolver('user')),
33551
+ });
33552
+ }
33553
+ else {
33554
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
33555
+ const users = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
33556
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [...new Set([...users, ...response.users.map(getResolver('user'))])] }));
33557
+ }
33558
+ }
33559
+ reactor(action) {
33560
+ return (user) => {
33561
+ var _a, _b;
33562
+ if (user &&
33563
+ (action === EnumBlockActions.OnBlocked || action === EnumBlockActions.OnUnblocked)) {
33564
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
33565
+ const ids = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
33566
+ const data = action === EnumBlockActions.OnBlocked
33567
+ ? [...new Set([...ids, user.userId])]
33568
+ : ids.filter(id => id !== user.userId);
33569
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data }));
33570
+ }
33571
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
33572
+ };
33573
+ }
33574
+ subscribeRTE(createSubscriber) {
33575
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
33576
+ }
33577
+ }
33578
+
33579
+ class BlockingUserPaginationController extends PaginationController {
33580
+ async getRequest(queryParams, token) {
33581
+ const { limit = COLLECTION_DEFAULT_PAGINATION_SIZE } = queryParams, params = __rest(queryParams, ["limit"]);
33582
+ const options = token ? { token } : { limit };
33583
+ const { data: queryResponse } = await this.http.get('/api/v4/me/blockers', {
33584
+ params: Object.assign(Object.assign({}, params), { options, isDeleted: false }),
33585
+ });
33586
+ return queryResponse;
33587
+ }
33588
+ }
33589
+
33590
+ class BlockingUserLiveCollectionController extends LiveCollectionController {
33591
+ constructor(callback) {
33592
+ const queryStreamId = `blocking-users-${getActiveClient().userId}`;
33593
+ const query = {};
33594
+ const cacheKey = ['blockingUsers', 'collection', queryStreamId];
33595
+ const paginationController = new BlockingUserPaginationController(query);
33596
+ super(paginationController, queryStreamId, cacheKey, callback);
33597
+ this.queryStreamController = new BlockingUserQueryStreamController(query, this.cacheKey, this.notifyChange.bind(this), prepareBlockingUserPayload);
33598
+ this.callback = callback.bind(this);
33599
+ this.loadPage({ initial: true });
33600
+ }
33601
+ setup() {
33602
+ var _a;
33603
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
33604
+ if (!collection) {
33605
+ pushToCache(this.cacheKey, {
33606
+ data: [],
33607
+ params: {},
33608
+ });
33609
+ }
33610
+ }
33611
+ async persistModel(queryPayload) {
33612
+ await this.queryStreamController.saveToMainDB(queryPayload);
33613
+ }
33614
+ persistQueryStream({ response, direction, refresh, }) {
33615
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
33616
+ }
33617
+ startSubscription() {
33618
+ return this.queryStreamController.subscribeRTE([
33619
+ {
33620
+ fn: onUserDeleted$2,
33621
+ action: EnumUserActions.OnUserDeleted,
33622
+ },
33623
+ {
33624
+ fn: (reactor) => onUserDidBlock(status => {
33625
+ var _a;
33626
+ if (status.to !== getActiveClient().userId)
33627
+ return;
33628
+ const blocker = (_a = pullFromCache(['user', 'get', status.from])) === null || _a === void 0 ? void 0 : _a.data;
33629
+ if (blocker)
33630
+ reactor(blocker);
33631
+ }),
33632
+ action: EnumBlockActions.OnBlocked,
33633
+ },
33634
+ {
33635
+ fn: (reactor) => onUserDidUnblock(status => {
33636
+ var _a;
33637
+ if (status.to !== getActiveClient().userId)
33638
+ return;
33639
+ const blocker = (_a = pullFromCache(['user', 'get', status.from])) === null || _a === void 0 ? void 0 : _a.data;
33640
+ if (blocker)
33641
+ reactor(blocker);
33642
+ }),
33643
+ action: EnumBlockActions.OnUnblocked,
33644
+ },
33645
+ ]);
33646
+ }
33647
+ notifyChange({ origin, loading, error }) {
33648
+ var _a, _b;
33649
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
33650
+ if (!collection)
33651
+ return;
33652
+ const data = this.applyFilter((_b = collection.data
33653
+ .map(id => pullFromCache(['user', 'get', id]))
33654
+ .filter(isNonNullable)
33655
+ .map(({ data }) => data)
33656
+ .map(LinkedObject.user)) !== null && _b !== void 0 ? _b : []);
33657
+ if (!this.shouldNotify(data) && origin === 'event')
33658
+ return;
33659
+ this.callback({
33660
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
33661
+ data,
33662
+ hasNextPage: !!this.paginationController.getNextToken(),
33663
+ loading,
33664
+ error,
33665
+ });
33666
+ }
33667
+ applyFilter(data) {
33668
+ let users = data;
33669
+ users = users.filter(user => user.isDeleted == null || user.isDeleted === false);
33670
+ return users;
33671
+ }
33672
+ }
33673
+
33674
+ /* begin_public_function
33675
+ id: user.get_blocking_users
33676
+ */
33677
+ /**
33678
+ * ```js
33679
+ * import { UserRepository } from '@amityco/ts-sdk'
33680
+ * const unsubscribe = UserRepository.getBlockingUsers(({ data: users }) => {
33681
+ * console.log(users)
33682
+ * })
33683
+ * ```
33684
+ *
33685
+ * Observe the {@link Amity.User}s who have blocked the current user
33686
+ *
33687
+ * @param callback to receive updates on the blocking {@link Amity.User}s
33688
+ * @returns {@link Amity.Unsubscriber} to unsubscribe from collection
33689
+ *
33690
+ * @category User API
33691
+ */
33692
+ const getBlockingUsers = (callback) => {
33693
+ const { log, cache } = getActiveClient();
33694
+ if (!cache)
33695
+ console.log(ENABLE_CACHE_MESSAGE);
33696
+ const timestamp = Date.now();
33697
+ log(`getBlockingUsers(tmpid: ${timestamp}) > listen`);
33698
+ const blockingUserLiveCollection = new BlockingUserLiveCollectionController(callback);
33699
+ const disposers = blockingUserLiveCollection.startSubscription();
33700
+ const cacheKey = blockingUserLiveCollection.getCacheKey();
33701
+ disposers.push(() => dropFromCache(cacheKey));
33702
+ return () => {
33703
+ log(`getBlockingUsers(tmpid: ${timestamp}) > dispose`);
33704
+ disposers.forEach(fn => fn());
33705
+ dropFromCache(cacheKey);
33706
+ };
33707
+ };
33708
+ /* end_public_function */
33709
+
32601
33710
  class SearchUserPaginationController extends PaginationController {
32602
33711
  async getRequest(queryParams, token) {
32603
33712
  const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT, displayName } = queryParams, params = __rest(queryParams, ["limit", "displayName"]);
@@ -32864,6 +33973,7 @@ var index$q = /*#__PURE__*/Object.freeze({
32864
33973
  unflagUser: unflagUser,
32865
33974
  isUserFlaggedByMe: isUserFlaggedByMe,
32866
33975
  getAllBlockedUsers: getAllBlockedUsers,
33976
+ getAllBlockingUsers: getAllBlockingUsers,
32867
33977
  onUserUpdated: onUserUpdated,
32868
33978
  onUserDeleted: onUserDeleted$2,
32869
33979
  onUserFlagged: onUserFlagged,
@@ -32872,6 +33982,7 @@ var index$q = /*#__PURE__*/Object.freeze({
32872
33982
  getUser: getUser,
32873
33983
  getUsers: getUsers,
32874
33984
  getBlockedUsers: getBlockedUsers,
33985
+ getBlockingUsers: getBlockingUsers,
32875
33986
  searchUserByDisplayName: searchUserByDisplayName,
32876
33987
  getReachedUsers: getReachedUsers,
32877
33988
  get AmityUserSearchMatchType () { return AmityUserSearchMatchType; }
@@ -32936,129 +34047,6 @@ getFile.locally = (fileId) => {
32936
34047
  };
32937
34048
  };
32938
34049
 
32939
- /**
32940
- * Builds the axios request config for multipart file uploads.
32941
- *
32942
- * ## Why this exists (React Native 0.83 New Architecture)
32943
- *
32944
- * Previously every upload hardcoded `{ 'content-type': 'multipart/form-data' }`.
32945
- * That header has **no `boundary`**, which breaks multipart uploads on React
32946
- * Native's New Architecture (Bridgeless): the request body is sent without the
32947
- * file bytes (it surfaces as `[object Object]` / `Stream Closed` /
32948
- * `AxiosError: Network Error`, or the server replies `400 "No files uploaded."`).
32949
- *
32950
- * The correct behaviour for the React Native / browser environment is to let
32951
- * the platform networking layer (XMLHttpRequest) serialize the `FormData` and
32952
- * generate the `multipart/form-data; boundary=…` header itself. So we must NOT
32953
- * set the content-type at all in that environment.
32954
- *
32955
- * We also pin `adapter: 'xhr'` so axios always routes the request through React
32956
- * Native's `XMLHttpRequest` (which understands RN file parts), rather than
32957
- * auto-selecting the `fetch` adapter that the New Architecture now also exposes.
32958
- *
32959
- * On Node (the `form-data` package exposes `getHeaders()`), we keep using its
32960
- * generated headers — which already include the correct boundary — and leave
32961
- * the adapter selection to axios (its http adapter, via the configured agents).
32962
- *
32963
- * @param formData The multipart payload about to be uploaded.
32964
- * @returns A partial axios config to spread into the upload request.
32965
- *
32966
- * @category File Util
32967
- * @hidden
32968
- */
32969
- const getUploadRequestConfig = (formData) => {
32970
- // Node `form-data` instances expose getHeaders() (with a valid boundary).
32971
- if ('getHeaders' in formData) {
32972
- return { headers: formData.getHeaders() };
32973
- }
32974
- // React Native / browser.
32975
- //
32976
- // Set `multipart/form-data` explicitly. We must NOT omit it: when omitted,
32977
- // axios applies its default POST content-type (`application/x-www-form-urlencoded`)
32978
- // and the server rejects the upload (`multipart != application/x-www-form-urlencoded`).
32979
- // React Native's native networking layer appends the real `boundary=…` to this
32980
- // header when it serializes a (recognized) FormData body.
32981
- //
32982
- // `adapter: 'xhr'` pins axios to React Native's XMLHttpRequest (which
32983
- // understands RN file parts) instead of the `fetch` adapter the New
32984
- // Architecture also exposes.
32985
- //
32986
- // NOTE: this only works if the FormData instance is recognized as multipart.
32987
- // See `recreateUploadFormData` — the upload APIs rebuild the FormData in the
32988
- // SDK's own module realm first, otherwise axios/XHR treat it as a plain object
32989
- // and send `[object Object]`.
32990
- return {
32991
- headers: { 'content-type': 'multipart/form-data' },
32992
- adapter: 'xhr',
32993
- };
32994
- };
32995
-
32996
- /**
32997
- * Rebuilds a multipart `FormData` inside the SDK's own module realm.
32998
- *
32999
- * ## Why this is required (React Native 0.83 New Architecture)
33000
- *
33001
- * When the app/UIKit constructs `new FormData()` from a *different* module realm
33002
- * than the SDK (which happens with `.tgz`/duplicate-`react-native` setups, and
33003
- * is common under the New Architecture), the resulting instance is NOT an
33004
- * `instanceof` the `FormData` that the SDK's axios — and React Native's native
33005
- * `XMLHttpRequest` — reference.
33006
- *
33007
- * As a result `axios.isFormData()` returns `false`, so axios:
33008
- * - serializes the body as a plain object → it goes out as `"[object Object]"`, and
33009
- * - applies its default POST content-type (`application/x-www-form-urlencoded`),
33010
- * which the upload server rejects with
33011
- * `"multipart != application/x-www-form-urlencoded"`.
33012
- *
33013
- * Re-creating the FormData here, with the SDK's own `new FormData()`, produces an
33014
- * instance both axios and RN's XHR recognize, so the file is sent as a real
33015
- * multipart body.
33016
- *
33017
- * We also backfill the file part's MIME `type` (via the file name/URI) because
33018
- * React Native on Android does not set it by default, and the backend rejects
33019
- * file parts without a content type.
33020
- *
33021
- * Only React Native's `FormData` exposes `getParts()`. For Node's `form-data`
33022
- * package or a spec-compliant `FormData`, there is nothing to normalize and the
33023
- * original instance is returned unchanged.
33024
- *
33025
- * @param formData The FormData passed in by the caller.
33026
- * @returns A FormData safe to hand to the upload transport.
33027
- *
33028
- * @category File Util
33029
- * @hidden
33030
- */
33031
- const recreateUploadFormData = (formData) => {
33032
- const source = formData;
33033
- if (typeof source.getParts !== 'function') {
33034
- return formData;
33035
- }
33036
- const rebuilt = new FormData();
33037
- source.getParts().forEach(part => {
33038
- var _a;
33039
- const { fieldName } = part;
33040
- // String fields (accessType, preferredFilename, feedType, altText, …).
33041
- if (typeof part.string === 'string') {
33042
- rebuilt.append(fieldName, part.string);
33043
- return;
33044
- }
33045
- // File parts are represented as `{ uri, name?, type? }` in React Native.
33046
- if (part.uri) {
33047
- const type = part.type ||
33048
- ((_a = part.headers) === null || _a === void 0 ? void 0 : _a['content-type']) ||
33049
- (part.name && mime.getType(part.name)) ||
33050
- mime.getType(part.uri) ||
33051
- undefined;
33052
- rebuilt.append(fieldName, {
33053
- uri: part.uri,
33054
- name: part.name,
33055
- type,
33056
- });
33057
- }
33058
- });
33059
- return rebuilt;
33060
- };
33061
-
33062
34050
  /* begin_public_function
33063
34051
  id: file.upload.file
33064
34052
  */
@@ -33077,10 +34065,8 @@ const recreateUploadFormData = (formData) => {
33077
34065
  * @category File API
33078
34066
  * @async
33079
34067
  */
33080
- const uploadFile = async (inputFormData, onProgress) => {
34068
+ const uploadFile = async (formData, onProgress) => {
33081
34069
  const client = getActiveClient();
33082
- // Rebuild in the SDK's realm so axios/XHR serialize it as real multipart.
33083
- const formData = recreateUploadFormData(inputFormData);
33084
34070
  client.log('file/uploadFile', formData);
33085
34071
  const files = formData.getAll('files');
33086
34072
  if (!files.length)
@@ -33088,9 +34074,15 @@ const uploadFile = async (inputFormData, onProgress) => {
33088
34074
  const accessType = GlobalFileAccessType$1.getInstance().getFileAccessType();
33089
34075
  formData.append('accessType', accessType);
33090
34076
  formData.append('preferredFilename', files[0].name);
33091
- const { data } = await client.upload.post('/api/v4/files', formData, Object.assign(Object.assign({}, getUploadRequestConfig(formData)), { onUploadProgress({ loaded, total = 100 }) {
34077
+ const headers = 'getHeaders' in formData
34078
+ ? formData.getHeaders()
34079
+ : { 'content-type': 'multipart/form-data' };
34080
+ const { data } = await client.upload.post('/api/v4/files', formData, {
34081
+ headers,
34082
+ onUploadProgress({ loaded, total = 100 }) {
33092
34083
  onProgress && onProgress(Math.round((loaded * 100) / total));
33093
- } }));
34084
+ },
34085
+ });
33094
34086
  // API-FIX: payload should be serialized properly
33095
34087
  // const { files } = data
33096
34088
  const cachedAt = client.cache && Date.now();
@@ -33160,10 +34152,8 @@ const fileUrlWithSize = (fileUrl, size) => {
33160
34152
  * @category File API
33161
34153
  * @async
33162
34154
  */
33163
- const uploadVideo = async (inputFormData, feedType, onProgress) => {
34155
+ const uploadVideo = async (formData, feedType, onProgress) => {
33164
34156
  const client = getActiveClient();
33165
- // Rebuild in the SDK's realm so axios/XHR serialize it as real multipart.
33166
- const formData = recreateUploadFormData(inputFormData);
33167
34157
  client.log('file/uploadVideo', formData);
33168
34158
  const files = formData.getAll('files');
33169
34159
  if (!files.length)
@@ -33174,9 +34164,15 @@ const uploadVideo = async (inputFormData, feedType, onProgress) => {
33174
34164
  if (feedType) {
33175
34165
  formData.append('feedType', feedType);
33176
34166
  }
33177
- const { data } = await client.upload.post('/api/v4/videos', formData, Object.assign(Object.assign({}, getUploadRequestConfig(formData)), { onUploadProgress({ loaded, total = 100 }) {
34167
+ const headers = 'getHeaders' in formData
34168
+ ? formData.getHeaders()
34169
+ : { 'content-type': 'multipart/form-data' };
34170
+ const { data } = await client.upload.post('/api/v4/videos', formData, {
34171
+ headers,
34172
+ onUploadProgress({ loaded, total = 100 }) {
33178
34173
  onProgress && onProgress(Math.round((loaded * 100) / total));
33179
- } }));
34174
+ },
34175
+ });
33180
34176
  // API-FIX: payload should be serialized properly
33181
34177
  // const { files } = data
33182
34178
  const cachedAt = client.cache && Date.now();
@@ -33208,11 +34204,8 @@ const uploadVideo = async (inputFormData, feedType, onProgress) => {
33208
34204
  * @category File API
33209
34205
  * @async
33210
34206
  */
33211
- const uploadImage = async (inputFormData, onProgress, altText) => {
34207
+ const uploadImage = async (formData, onProgress, altText) => {
33212
34208
  const client = getActiveClient();
33213
- // Rebuild the FormData in the SDK's realm so axios/XHR serialize it as real
33214
- // multipart (otherwise it is sent as "[object Object]"). See helper for details.
33215
- const formData = recreateUploadFormData(inputFormData);
33216
34209
  client.log('file/uploadImage', formData);
33217
34210
  const files = formData.getAll('files');
33218
34211
  if (files === null || files === void 0 ? void 0 : files.length) {
@@ -33232,9 +34225,15 @@ const uploadImage = async (inputFormData, onProgress, altText) => {
33232
34225
  }
33233
34226
  const accessType = GlobalFileAccessType$1.getInstance().getFileAccessType();
33234
34227
  formData.append('accessType', accessType);
33235
- const { data } = await client.upload.post('/api/v4/images', formData, Object.assign(Object.assign({}, getUploadRequestConfig(formData)), { onUploadProgress({ loaded, total = 100 }) {
34228
+ const headers = 'getHeaders' in formData
34229
+ ? formData.getHeaders()
34230
+ : { 'content-type': 'multipart/form-data' };
34231
+ const { data } = await client.upload.post('/api/v4/images', formData, {
34232
+ headers,
34233
+ onUploadProgress({ loaded, total = 100 }) {
33236
34234
  onProgress && onProgress(Math.round((loaded * 100) / total));
33237
- } }));
34235
+ },
34236
+ });
33238
34237
  // API-FIX: payload should be serialized properly
33239
34238
  // const { files } = data
33240
34239
  const cachedAt = client.cache && Date.now();
@@ -33296,10 +34295,8 @@ const updateAltText = async (fileId, altText) => {
33296
34295
  * @category File API
33297
34296
  * @async
33298
34297
  */
33299
- const uploadClip = async (inputFormData, feedType, onProgress) => {
34298
+ const uploadClip = async (formData, feedType, onProgress) => {
33300
34299
  const client = getActiveClient();
33301
- // Rebuild in the SDK's realm so axios/XHR serialize it as real multipart.
33302
- const formData = recreateUploadFormData(inputFormData);
33303
34300
  client.log('file/uploadClip', formData);
33304
34301
  const file = formData.get('files');
33305
34302
  if (!file)
@@ -33310,9 +34307,15 @@ const uploadClip = async (inputFormData, feedType, onProgress) => {
33310
34307
  if (feedType) {
33311
34308
  formData.append('feedType', feedType);
33312
34309
  }
33313
- const { data } = await client.upload.post('/api/v4/clips', formData, Object.assign(Object.assign({}, getUploadRequestConfig(formData)), { onUploadProgress({ loaded, total = 100 }) {
34310
+ const headers = 'getHeaders' in formData
34311
+ ? formData.getHeaders()
34312
+ : { 'content-type': 'multipart/form-data' };
34313
+ const { data } = await client.upload.post('/api/v4/clips', formData, {
34314
+ headers,
34315
+ onUploadProgress({ loaded, total = 100 }) {
33314
34316
  onProgress && onProgress(Math.round((loaded * 100) / total));
33315
- } }));
34317
+ },
34318
+ });
33316
34319
  // API-FIX: payload should be serialized properly
33317
34320
  // const { files } = data
33318
34321
  const cachedAt = client.cache && Date.now();
@@ -33343,10 +34346,8 @@ const uploadClip = async (inputFormData, feedType, onProgress) => {
33343
34346
  * @category File API
33344
34347
  * @async
33345
34348
  */
33346
- const uploadAudio = async (inputFormData, onProgress) => {
34349
+ const uploadAudio = async (formData, onProgress) => {
33347
34350
  const client = getActiveClient();
33348
- // Rebuild in the SDK's realm so axios/XHR serialize it as real multipart.
33349
- const formData = recreateUploadFormData(inputFormData);
33350
34351
  client.log('file/uploadAudio', formData);
33351
34352
  const files = formData.getAll('file');
33352
34353
  if (files.length === 0)
@@ -33355,9 +34356,13 @@ const uploadAudio = async (inputFormData, onProgress) => {
33355
34356
  const accessType = GlobalFileAccessType$1.getInstance().getFileAccessType();
33356
34357
  formData.append('accessType', accessType);
33357
34358
  formData.append('preferredFilename', file.name);
33358
- const { data } = await client.upload.post('/api/v4/audios', formData, Object.assign(Object.assign({}, getUploadRequestConfig(formData)), { onUploadProgress({ loaded, total = 100 }) {
34359
+ const headers = { 'content-type': 'multipart/form-data' };
34360
+ const { data } = await client.upload.post('/api/v4/audios', formData, {
34361
+ headers,
34362
+ onUploadProgress({ loaded, total = 100 }) {
33359
34363
  onProgress === null || onProgress === void 0 ? void 0 : onProgress(Math.round((loaded * 100) / total));
33360
- } }));
34364
+ },
34365
+ });
33361
34366
  const cachedAt = client.cache && Date.now();
33362
34367
  if (client.cache)
33363
34368
  ingestInCache({ files: data }, { cachedAt });
@@ -34144,7 +35149,7 @@ const removeReaction = async (referenceType, referenceId, reactionName) => {
34144
35149
  return true;
34145
35150
  }
34146
35151
  if (referenceType === 'story') {
34147
- fireEvent('local.story.reactionAdded', {
35152
+ fireEvent('local.story.reactionRemoved', {
34148
35153
  story: updatedModel,
34149
35154
  reactor: {
34150
35155
  userId: client.userId,
@@ -35728,6 +36733,104 @@ const unmuteChannel = async (channelId) => {
35728
36733
  };
35729
36734
  /* end_public_function */
35730
36735
 
36736
+ /* begin_public_function
36737
+ id: channel.archive
36738
+ */
36739
+ /**
36740
+ * ```js
36741
+ * import { ChannelRepository } from '@amityco/ts-sdk'
36742
+ * const success = await ChannelRepository.archiveChannel('foobar')
36743
+ * ```
36744
+ *
36745
+ * Archive a {@link Amity.Channel}.
36746
+ *
36747
+ * @param channelId The id of the {@link Amity.Channel} to archive
36748
+ * @returns A success boolean
36749
+ *
36750
+ * @category Channel API
36751
+ * @async
36752
+ */
36753
+ const archiveChannel = async (channelId) => {
36754
+ const client = getActiveClient();
36755
+ client.log('channel/archiveChannel', channelId);
36756
+ await client.http.post(`/api/v1/archives/channels/${encodeURIComponent(channelId)}`);
36757
+ const archive = {
36758
+ channelId,
36759
+ archivedAt: new Date().toISOString(),
36760
+ };
36761
+ if (client.cache) {
36762
+ pushToCache(['archivedChannel', 'get', getResolver('archivedChannel')(archive)], archive);
36763
+ }
36764
+ fireEvent('local.channel.archived', { archives: [archive] });
36765
+ };
36766
+ /* end_public_function */
36767
+
36768
+ /* begin_public_function
36769
+ id: channel.unarchive
36770
+ */
36771
+ /**
36772
+ * ```js
36773
+ * import { ChannelRepository } from '@amityco/ts-sdk'
36774
+ * const success = await ChannelRepository.unarchiveChannel('foobar')
36775
+ * ```
36776
+ *
36777
+ * Unarchive a previously archived {@link Amity.Channel}.
36778
+ *
36779
+ * @param channelId The id of the {@link Amity.Channel} to unarchive
36780
+ * @returns A success boolean
36781
+ *
36782
+ * @category Channel API
36783
+ * @async
36784
+ */
36785
+ const unarchiveChannel = async (channelId) => {
36786
+ var _a;
36787
+ const client = getActiveClient();
36788
+ client.log('channel/unarchiveChannel', channelId);
36789
+ await client.http.delete(`/api/v1/archives/channels/${encodeURIComponent(channelId)}`);
36790
+ const cached = (_a = pullFromCache(['archivedChannel', 'get', channelId])) === null || _a === void 0 ? void 0 : _a.data;
36791
+ const archive = cached !== null && cached !== void 0 ? cached : {
36792
+ channelId,
36793
+ archivedAt: new Date().toISOString(),
36794
+ };
36795
+ if (client.cache) {
36796
+ dropFromCache(['archivedChannel', 'get', channelId], true);
36797
+ }
36798
+ fireEvent('local.channel.unarchived', { archives: [archive] });
36799
+ };
36800
+ /* end_public_function */
36801
+
36802
+ /* begin_public_function
36803
+ id: channel.archive.ids
36804
+ */
36805
+ /**
36806
+ * ```js
36807
+ * import { ChannelRepository } from '@amityco/ts-sdk'
36808
+ * const ids = await ChannelRepository.getArchivedChannelIds()
36809
+ * ```
36810
+ *
36811
+ * @returns A list of archived channel ids sorted by `archivedAt` descending.
36812
+ *
36813
+ * @category Channel API
36814
+ * @async
36815
+ */
36816
+ const getArchivedChannelIds = async () => {
36817
+ var _a;
36818
+ const client = getActiveClient();
36819
+ client.log('channel/getArchivedChannelIds');
36820
+ const { data: payload } = await client.http.get(`/api/v1/archives/channels`);
36821
+ const archives = (_a = payload.archives) !== null && _a !== void 0 ? _a : [];
36822
+ if (client.cache) {
36823
+ dropFromCache(['archivedChannel', 'get']);
36824
+ archives.forEach(archive => {
36825
+ if (!archive.channelId)
36826
+ return;
36827
+ pushToCache(['archivedChannel', 'get', archive.channelId], archive);
36828
+ });
36829
+ }
36830
+ return archives.map(entry => entry.channelId).filter(channelId => !!channelId);
36831
+ };
36832
+ /* end_public_function */
36833
+
35731
36834
  /**
35732
36835
  * ```js
35733
36836
  * import { onMessageUpdated } from '@amityco/ts-sdk-react-native'
@@ -37106,6 +38209,160 @@ const getMessages = (params, callback, config) => {
37106
38209
  };
37107
38210
  /* end_public_function */
37108
38211
 
38212
+ class SearchMessagePaginationController extends PaginationController {
38213
+ async getRequest(queryParams, token) {
38214
+ const { query, exactMatch, channelId, messageFeedId, userIds, tags, types, sortBy, orderBy, limit = COLLECTION_DEFAULT_PAGINATION_LIMIT, } = queryParams;
38215
+ const options = token ? { token } : { limit, sortBy, orderBy };
38216
+ const { data: queryResponse } = await this.http.get(`/api/v2/search/messages`, {
38217
+ params: {
38218
+ query,
38219
+ exactMatch,
38220
+ channelId,
38221
+ messageFeedId,
38222
+ userIds,
38223
+ tags,
38224
+ types,
38225
+ options,
38226
+ },
38227
+ });
38228
+ return queryResponse;
38229
+ }
38230
+ }
38231
+
38232
+ class SearchMessageQueryStreamController extends QueryStreamController {
38233
+ constructor(query, cacheKey, notifyChange) {
38234
+ super(query, cacheKey);
38235
+ this.notifyChange = notifyChange;
38236
+ }
38237
+ async saveToMainDB(response) {
38238
+ var _a;
38239
+ const processedPayload = await prepareMessagePayload(response);
38240
+ const client = getActiveClient();
38241
+ const cachedAt = client.cache && Date.now();
38242
+ if (client.cache) {
38243
+ ingestInCache(processedPayload, { cachedAt });
38244
+ if ((_a = response.channels) === null || _a === void 0 ? void 0 : _a.length) {
38245
+ response.channels.forEach(channel => {
38246
+ pushToCache(['channel', 'get', channel.channelId], channel, { cachedAt });
38247
+ });
38248
+ }
38249
+ }
38250
+ }
38251
+ appendToQueryStream(response, direction, refresh = false) {
38252
+ var _a, _b;
38253
+ if (refresh) {
38254
+ pushToCache(this.cacheKey, {
38255
+ data: response.messages.map(getResolver('message')),
38256
+ });
38257
+ return;
38258
+ }
38259
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
38260
+ const existing = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
38261
+ const incoming = response.messages.map(getResolver('message'));
38262
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: direction === "prev" /* Amity.LiveCollectionPageDirection.PREV */
38263
+ ? [...new Set([...incoming, ...existing])]
38264
+ : [...new Set([...existing, ...incoming])] }));
38265
+ }
38266
+ }
38267
+
38268
+ class SearchMessageLiveCollectionController extends LiveCollectionController {
38269
+ constructor(query, callback) {
38270
+ const queryStreamId = hash(query);
38271
+ const cacheKey = ['message', 'search', queryStreamId];
38272
+ const paginationController = new SearchMessagePaginationController(query);
38273
+ super(paginationController, queryStreamId, cacheKey, callback);
38274
+ this.queryStreamController = new SearchMessageQueryStreamController(query, this.cacheKey, this.notifyChange.bind(this));
38275
+ this.callback = callback.bind(this);
38276
+ this.loadPage({ initial: true });
38277
+ }
38278
+ startSubscription() {
38279
+ return [];
38280
+ }
38281
+ notifyChange({ origin, loading, error }) {
38282
+ var _a, _b;
38283
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
38284
+ if (!collection)
38285
+ return;
38286
+ const data = (_b = collection.data
38287
+ .map(messageId => getMessageFromMainDB(messageId))
38288
+ .filter(isNonNullable)
38289
+ .map(message => LinkedObject.message(message))) !== null && _b !== void 0 ? _b : [];
38290
+ if (!this.shouldNotify(data) && origin === 'event')
38291
+ return;
38292
+ this.callback({
38293
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
38294
+ data,
38295
+ hasNextPage: !!this.paginationController.getNextToken(),
38296
+ loading,
38297
+ error,
38298
+ });
38299
+ }
38300
+ setup() {
38301
+ var _a;
38302
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
38303
+ if (!collection) {
38304
+ pushToCache(this.cacheKey, {
38305
+ data: [],
38306
+ params: {},
38307
+ });
38308
+ }
38309
+ }
38310
+ async persistModel(response) {
38311
+ await this.queryStreamController.saveToMainDB(response);
38312
+ }
38313
+ persistQueryStream({ response, direction, refresh, }) {
38314
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
38315
+ }
38316
+ }
38317
+
38318
+ /* begin_public_function
38319
+ id: message.search
38320
+ */
38321
+ /**
38322
+ * ```js
38323
+ * import { MessageRepository } from '@amityco/ts-sdk';
38324
+ *
38325
+ * let messages = [];
38326
+ *
38327
+ * const unsubscribe = MessageRepository.searchMessage(
38328
+ * { query: 'hello' },
38329
+ * response => merge(messages, response.data),
38330
+ * );
38331
+ * ```
38332
+ *
38333
+ * Live collection of {@link Amity.Message}s matching the search query. Backed
38334
+ * by `GET /api/v2/search/messages`. The first emission delivers the first
38335
+ * page; pagination is driven by `response.onNextPage()`.
38336
+ *
38337
+ * @param params Search parameters. `query` is required.
38338
+ * @param callback Called whenever new data are available.
38339
+ * @returns An {@link Amity.Unsubscriber} function to stop observing.
38340
+ *
38341
+ * @category Message Live Collection
38342
+ */
38343
+ const searchMessage = (params, callback) => {
38344
+ if (!params.query || params.query.trim().length === 0) {
38345
+ throw new Error('Query is required for message search');
38346
+ }
38347
+ const { log, cache } = getActiveClient();
38348
+ if (!cache) {
38349
+ console.log(ENABLE_CACHE_MESSAGE);
38350
+ }
38351
+ const timestamp = Date.now();
38352
+ log(`searchMessage(tmpid: ${timestamp}) > listen`);
38353
+ const controller = new SearchMessageLiveCollectionController(params, callback);
38354
+ const disposers = controller.startSubscription();
38355
+ const cacheKey = controller.getCacheKey();
38356
+ disposers.push(() => {
38357
+ dropFromCache(cacheKey);
38358
+ });
38359
+ return () => {
38360
+ log(`searchMessage(tmpid: ${timestamp}) > dispose`);
38361
+ disposers.forEach(fn => fn());
38362
+ };
38363
+ };
38364
+ /* end_public_function */
38365
+
37109
38366
  var index$n = /*#__PURE__*/Object.freeze({
37110
38367
  __proto__: null,
37111
38368
  createMessage: createMessage,
@@ -37131,6 +38388,7 @@ var index$n = /*#__PURE__*/Object.freeze({
37131
38388
  onMessageFetched: onMessageFetched,
37132
38389
  getMessage: getMessage,
37133
38390
  getMessages: getMessages,
38391
+ searchMessage: searchMessage,
37134
38392
  convertFromRaw: convertFromRaw$1,
37135
38393
  prepareMessagePayload: prepareMessagePayload,
37136
38394
  convertParams: convertParams,
@@ -37978,6 +39236,7 @@ class ChannelQueryStreamController extends QueryStreamController {
37978
39236
  "onCreate" /* Amity.ChannelActionType.OnCreate */,
37979
39237
  "onJoin" /* Amity.ChannelActionType.OnJoin */,
37980
39238
  "onResolveChannel" /* Amity.ChannelActionType.OnResolveChannel */,
39239
+ "onUnarchived" /* Amity.ChannelActionType.OnUnarchived */,
37981
39240
  ].includes(action)) {
37982
39241
  if (Array.isArray(payload)) {
37983
39242
  collection.data = [
@@ -37987,6 +39246,12 @@ class ChannelQueryStreamController extends QueryStreamController {
37987
39246
  else
37988
39247
  collection.data = [...new Set([payload.channelInternalId, ...collection.data])];
37989
39248
  }
39249
+ if (action === "onArchived" /* Amity.ChannelActionType.OnArchived */) {
39250
+ const ids = Array.isArray(payload)
39251
+ ? payload.map(getResolver('channel'))
39252
+ : [getResolver('channel')(payload)];
39253
+ collection.data = collection.data.filter(channelInternalId => !ids.includes(channelInternalId));
39254
+ }
37990
39255
  pushToCache(this.cacheKey, collection);
37991
39256
  this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
37992
39257
  };
@@ -38253,6 +39518,32 @@ class ChannelLiveCollectionController extends LiveCollectionController {
38253
39518
  },
38254
39519
  { fn: onChannelMemberAdded, action: "onMemberAdded" /* Amity.ChannelActionType.OnMemberAdded */ },
38255
39520
  { fn: onChannelMemberRemoved, action: "onMemberRemoved" /* Amity.ChannelActionType.OnMemberRemoved */ },
39521
+ {
39522
+ fn: (reactor) => onChannelArchived(payload => {
39523
+ const channels = payload.archives
39524
+ .map(archive => {
39525
+ var _a;
39526
+ return (_a = pullFromCache(['channel', 'get', archive.channelId])) === null || _a === void 0 ? void 0 : _a.data;
39527
+ })
39528
+ .filter((c) => Boolean(c));
39529
+ if (channels.length > 0)
39530
+ reactor(channels);
39531
+ }),
39532
+ action: "onArchived" /* Amity.ChannelActionType.OnArchived */,
39533
+ },
39534
+ {
39535
+ fn: (reactor) => onChannelUnarchived(payload => {
39536
+ const channels = payload.archives
39537
+ .map(archive => {
39538
+ var _a;
39539
+ return (_a = pullFromCache(['channel', 'get', archive.channelId])) === null || _a === void 0 ? void 0 : _a.data;
39540
+ })
39541
+ .filter((c) => Boolean(c));
39542
+ if (channels.length > 0)
39543
+ reactor(channels);
39544
+ }),
39545
+ action: "onUnarchived" /* Amity.ChannelActionType.OnUnarchived */,
39546
+ },
38256
39547
  {
38257
39548
  fn: convertEventPayload(onChannelMarkerFetched, 'entityId', 'channel'),
38258
39549
  action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
@@ -38431,181 +39722,766 @@ class ChannelLiveCollectionController extends LiveCollectionController {
38431
39722
  action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
38432
39723
  },
38433
39724
  ];
38434
- if (this.paginationController instanceof PaginationController) {
38435
- return [
38436
- ...subscriptions,
38437
- {
38438
- fn: (callback) => {
38439
- return onChannelCreated(channel => {
38440
- resolveUnreadInfoOnChannelEvent(channel);
38441
- callback(channel);
38442
- });
38443
- },
38444
- action: "onCreate" /* Amity.ChannelActionType.OnCreate */,
38445
- },
38446
- ];
38447
- }
38448
- return subscriptions;
39725
+ if (this.paginationController instanceof PaginationController) {
39726
+ return [
39727
+ ...subscriptions,
39728
+ {
39729
+ fn: (callback) => {
39730
+ return onChannelCreated(channel => {
39731
+ resolveUnreadInfoOnChannelEvent(channel);
39732
+ callback(channel);
39733
+ });
39734
+ },
39735
+ action: "onCreate" /* Amity.ChannelActionType.OnCreate */,
39736
+ },
39737
+ ];
39738
+ }
39739
+ return subscriptions;
39740
+ }
39741
+ }
39742
+
39743
+ /* eslint-disable no-use-before-define */
39744
+ /* begin_public_function
39745
+ id: channel.query
39746
+ */
39747
+ /**
39748
+ * ```js
39749
+ * import { getChannels } from '@amityco/ts-sdk-react-native'
39750
+ *
39751
+ * let channels = []
39752
+ * const unsub = getChannels({
39753
+ * displayName: Amity.Channel['displayName'],
39754
+ * }, response => merge(channels, response.data))
39755
+ * ```
39756
+ *
39757
+ * Observe all mutations on a list of {@link Amity.Channel}s
39758
+ *
39759
+ * @param params for querying channels
39760
+ * @param callback the function to call when new data are available
39761
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the channels
39762
+ *
39763
+ * @category Channel Live Collection
39764
+ */
39765
+ const getChannels = (params, callback, config) => {
39766
+ const { log, cache, userId } = getActiveClient();
39767
+ if (!cache) {
39768
+ console.log(ENABLE_CACHE_MESSAGE);
39769
+ }
39770
+ const timestamp = Date.now();
39771
+ log(`getChannels(tmpid: ${timestamp}) > listen`);
39772
+ const channelLiveCollection = new ChannelLiveCollectionController(params, callback);
39773
+ const disposers = channelLiveCollection.startSubscription();
39774
+ const cacheKey = channelLiveCollection.getCacheKey();
39775
+ disposers.push(() => {
39776
+ dropFromCache(cacheKey);
39777
+ });
39778
+ return () => {
39779
+ log(`getChannels(tmpid: ${timestamp}) > dispose`);
39780
+ disposers.forEach(fn => fn());
39781
+ };
39782
+ };
39783
+ /* end_public_function */
39784
+
39785
+ /**
39786
+ *
39787
+ * Calculate user unread from {@link Amity.ChannelUnread} objects
39788
+ *
39789
+ * @returns the {@link Amity.UserUnread} objects
39790
+ *
39791
+ * @category Channel API
39792
+ * @async
39793
+ */
39794
+ const getTotalChannelsUnread$1 = () => {
39795
+ var _a;
39796
+ const client = getActiveClient();
39797
+ client.log('channel/getTotalChannelsUnread.locally');
39798
+ const cachedChannelsUnread = ((_a = queryCache(['channelUnread', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
39799
+ return !data.isDeleted;
39800
+ })) || [];
39801
+ const totalChannelsUnread = (cachedChannelsUnread === null || cachedChannelsUnread === void 0 ? void 0 : cachedChannelsUnread.reduce((acc, { data }) => {
39802
+ acc.unreadCount += data.unreadCount;
39803
+ acc.isMentioned = acc.isMentioned || data.isMentioned;
39804
+ return acc;
39805
+ }, { unreadCount: 0, isMentioned: false })) || { unreadCount: 0, isMentioned: false };
39806
+ const cachedAt = client.cache && Date.now();
39807
+ return {
39808
+ data: totalChannelsUnread,
39809
+ cachedAt,
39810
+ };
39811
+ };
39812
+
39813
+ /* begin_public_function
39814
+ id: totalChannelsUnread.get
39815
+ */
39816
+ /**
39817
+ * ```js
39818
+ * import { ChannelRepository } from '@amityco/ts-sdk-react-native';
39819
+ *
39820
+ * let totalChannelsUnread;
39821
+ *
39822
+ * const unsubscribe = ChannelRepository.getTotalChannelsUnread(response => {
39823
+ * unread = response.data;
39824
+ * });
39825
+ * ```
39826
+ *
39827
+ * Observe all mutation on a given {@link Amity.UserUnread}
39828
+ *
39829
+ * @returns An {@link Amity.UserUnread} function to run when willing to stop observing the message
39830
+ *
39831
+ * @category User Unread Live Object
39832
+ *
39833
+ */
39834
+ const getTotalChannelsUnread = (callback) => {
39835
+ const { _id: userId } = getActiveUser();
39836
+ if (!userId)
39837
+ throw new ASCError('The _id has not been defined in ActiveUser', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
39838
+ const { log, cache } = getActiveClient();
39839
+ if (!cache) {
39840
+ console.log('For using Live Object feature you need to enable Cache!');
39841
+ }
39842
+ const timestamp = Date.now();
39843
+ log(`liveTotalChannelsUnread(tmpid: ${timestamp}) > listen`);
39844
+ const disposers = [];
39845
+ let isUnsyncedModel = false; // for messages
39846
+ let model;
39847
+ const dispatcher = (data) => {
39848
+ const { data: userUnread } = data;
39849
+ const callbackModel = userUnread
39850
+ ? {
39851
+ unreadCount: userUnread.unreadCount,
39852
+ isMentioned: userUnread.isMentioned,
39853
+ }
39854
+ : undefined;
39855
+ model = callbackModel ? convertGetterPropsToStatic(callbackModel) : callbackModel;
39856
+ callback({
39857
+ data: callbackModel
39858
+ ? Object.assign(Object.assign({}, callbackModel), { isMentioned: callbackModel.isMentioned }) : callbackModel,
39859
+ loading: data.loading,
39860
+ error: data.error,
39861
+ });
39862
+ };
39863
+ const realtimeRouter = (_) => {
39864
+ const { data: userUnread } = getTotalChannelsUnread$1();
39865
+ if (isEqual(model, userUnread))
39866
+ return;
39867
+ dispatcher({
39868
+ loading: false,
39869
+ data: userUnread,
39870
+ });
39871
+ };
39872
+ const onFetch = () => {
39873
+ const query = createQuery(async () => getTotalChannelsUnread$1());
39874
+ runQuery(query, ({ error, data, loading, origin, cachedAt }) => {
39875
+ if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
39876
+ dispatcher({
39877
+ data,
39878
+ origin,
39879
+ loading: false,
39880
+ error: new ASCApiError(UNSYNCED_OBJECT_CACHED_AT_MESSAGE, 800800 /* Amity.ClientError.DISALOOW_UNSYNCED_OBJECT */, "error" /* Amity.ErrorLevel.ERROR */),
39881
+ });
39882
+ isUnsyncedModel = true;
39883
+ disposers.forEach(fn => fn());
39884
+ }
39885
+ else if (!isUnsyncedModel) {
39886
+ dispatcher({ loading, data, origin, error });
39887
+ }
39888
+ if (error) {
39889
+ disposers.forEach(fn => fn());
39890
+ }
39891
+ });
39892
+ };
39893
+ disposers.push(onChannelUnreadUpdatedLocal(realtimeRouter));
39894
+ onFetch();
39895
+ return () => {
39896
+ disposers.forEach(fn => fn());
39897
+ };
39898
+ };
39899
+
39900
+ class ArchivedChannelPaginationController extends PaginationController {
39901
+ async getRequest(queryParams, token) {
39902
+ var _a, _b;
39903
+ const limit = (_a = queryParams.limit) !== null && _a !== void 0 ? _a : COLLECTION_DEFAULT_PAGINATION_LIMIT;
39904
+ const pageIndex = token ? Number.parseInt(token, 10) : 0;
39905
+ if (pageIndex === 0) {
39906
+ await getArchivedChannelIds();
39907
+ }
39908
+ const cached = (_b = queryCache(['archivedChannel', 'get'])) !== null && _b !== void 0 ? _b : [];
39909
+ const archives = cached
39910
+ .map(entry => entry.data)
39911
+ .slice()
39912
+ .sort((a, b) => Number(new Date(b.archivedAt)) - Number(new Date(a.archivedAt)));
39913
+ const start = pageIndex * limit;
39914
+ const end = start + limit;
39915
+ const slice = archives.slice(start, end);
39916
+ const hasMore = end < archives.length;
39917
+ if (slice.length > 0) {
39918
+ await getChannelByIds$1(slice.map(archive => archive.channelId));
39919
+ }
39920
+ return {
39921
+ archives: slice,
39922
+ paging: {
39923
+ next: hasMore ? String(pageIndex + 1) : undefined,
39924
+ previous: undefined,
39925
+ },
39926
+ };
39927
+ }
39928
+ }
39929
+
39930
+ class ArchivedChannelQueryStreamController extends QueryStreamController {
39931
+ constructor(query, cacheKey, notifyChange) {
39932
+ super(query, cacheKey);
39933
+ this.notifyChange = notifyChange;
39934
+ }
39935
+ async saveToMainDB(_response) {
39936
+ //
39937
+ }
39938
+ appendToQueryStream(response, direction, refresh = false) {
39939
+ var _a, _b;
39940
+ const channelIds = response.archives.map(archive => archive.channelId);
39941
+ if (refresh) {
39942
+ pushToCache(this.cacheKey, {
39943
+ data: channelIds,
39944
+ params: {},
39945
+ });
39946
+ return;
39947
+ }
39948
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
39949
+ const existing = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
39950
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: direction === "prev" /* Amity.LiveCollectionPageDirection.PREV */
39951
+ ? [...new Set([...channelIds, ...existing])]
39952
+ : [...new Set([...existing, ...channelIds])] }));
39953
+ }
39954
+ reactor(action) {
39955
+ return (channelIds) => {
39956
+ var _a;
39957
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
39958
+ if (!collection)
39959
+ return;
39960
+ if (action === "onArchived" /* Amity.ChannelActionType.OnArchived */) {
39961
+ const filtered = collection.data.filter(id => !channelIds.includes(id));
39962
+ collection.data = [...channelIds, ...filtered];
39963
+ }
39964
+ if (action === "onUnarchived" /* Amity.ChannelActionType.OnUnarchived */ ||
39965
+ action === "onDelete" /* Amity.ChannelActionType.OnDelete */) {
39966
+ collection.data = collection.data.filter(id => !channelIds.includes(id));
39967
+ }
39968
+ pushToCache(this.cacheKey, collection);
39969
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
39970
+ };
39971
+ }
39972
+ subscribeRTE(createSubscriber) {
39973
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
39974
+ }
39975
+ }
39976
+
39977
+ class ArchivedChannelLiveCollectionController extends LiveCollectionController {
39978
+ constructor(query, callback) {
39979
+ const queryStreamId = hash(query);
39980
+ const cacheKey = ['archivedChannel', 'collection', queryStreamId];
39981
+ const paginationController = new ArchivedChannelPaginationController(query);
39982
+ super(paginationController, queryStreamId, cacheKey, callback);
39983
+ this.queryStreamController = new ArchivedChannelQueryStreamController(query, this.cacheKey, this.notifyChange.bind(this));
39984
+ this.callback = callback.bind(this);
39985
+ this.loadPage({ initial: true });
39986
+ }
39987
+ setup() {
39988
+ var _a;
39989
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
39990
+ if (!collection) {
39991
+ pushToCache(this.cacheKey, {
39992
+ data: [],
39993
+ params: {},
39994
+ });
39995
+ }
39996
+ }
39997
+ async persistModel(response) {
39998
+ await this.queryStreamController.saveToMainDB(response);
39999
+ }
40000
+ persistQueryStream({ response, direction, refresh, }) {
40001
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
40002
+ }
40003
+ startSubscription() {
40004
+ return this.queryStreamController.subscribeRTE([
40005
+ {
40006
+ fn: reactor => onChannelArchived(payload => reactor(payload.archives.map(archive => archive.channelId))),
40007
+ action: "onArchived" /* Amity.ChannelActionType.OnArchived */,
40008
+ },
40009
+ {
40010
+ fn: reactor => onChannelUnarchived(payload => reactor(payload.archives.map(archive => archive.channelId))),
40011
+ action: "onUnarchived" /* Amity.ChannelActionType.OnUnarchived */,
40012
+ },
40013
+ {
40014
+ fn: reactor => onChannelUpdated(channel => reactor([channel.channelId])),
40015
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40016
+ },
40017
+ {
40018
+ fn: reactor => onChannelDeleted(channel => reactor([channel.channelId])),
40019
+ action: "onDelete" /* Amity.ChannelActionType.OnDelete */,
40020
+ },
40021
+ ]);
40022
+ }
40023
+ notifyChange({ origin, loading, error }) {
40024
+ var _a, _b;
40025
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40026
+ if (!collection)
40027
+ return;
40028
+ const data = (_b = collection.data
40029
+ .map(channelId => pullFromCache(['channel', 'get', channelId]))
40030
+ .filter((entry) => Boolean(entry))
40031
+ .map(({ data: channel }) => channel)
40032
+ .map(constructChannelObject)) !== null && _b !== void 0 ? _b : [];
40033
+ if (!this.shouldNotify(data) && origin === 'event')
40034
+ return;
40035
+ this.callback({
40036
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
40037
+ data,
40038
+ hasNextPage: !!this.paginationController.getNextToken(),
40039
+ loading,
40040
+ error,
40041
+ });
40042
+ }
40043
+ }
40044
+
40045
+ /* begin_public_function
40046
+ id: channel.archive.collection
40047
+ */
40048
+ /**
40049
+ * ```js
40050
+ * import { ChannelRepository } from '@amityco/ts-sdk'
40051
+ *
40052
+ * let channels = []
40053
+ * const unsub = ChannelRepository.getArchivedChannels(params, response => merge(channels, response.data))
40054
+ * ```
40055
+ *
40056
+ * Live collection of {@link Amity.Channel}s archived by the active user.
40057
+ *
40058
+ * @param params Live collection parameters (only `limit` is honored; the
40059
+ * archive list takes no other filters).
40060
+ * @param callback the function to call when new data are available
40061
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to
40062
+ * stop observing.
40063
+ *
40064
+ * @category Channel Live Collection
40065
+ */
40066
+ const getArchivedChannels = (params, callback) => {
40067
+ const { log, cache } = getActiveClient();
40068
+ if (!cache) {
40069
+ console.log(ENABLE_CACHE_MESSAGE);
40070
+ }
40071
+ const timestamp = Date.now();
40072
+ log(`getArchivedChannels(tmpid: ${timestamp}) > listen`);
40073
+ const controller = new ArchivedChannelLiveCollectionController(params, callback);
40074
+ const disposers = controller.startSubscription();
40075
+ const cacheKey = controller.getCacheKey();
40076
+ disposers.push(() => {
40077
+ dropFromCache(cacheKey);
40078
+ });
40079
+ return () => {
40080
+ log(`getArchivedChannels(tmpid: ${timestamp}) > dispose`);
40081
+ disposers.forEach(fn => fn());
40082
+ };
40083
+ };
40084
+ /* end_public_function */
40085
+
40086
+ class SearchChannelPaginationController extends PaginationController {
40087
+ async getRequest(queryParams, token) {
40088
+ const { query, exactMatch, isMemberOnly, types, tags, sortBy, orderBy, limit = COLLECTION_DEFAULT_PAGINATION_SIZE, } = queryParams;
40089
+ const options = token ? { token } : { limit: Math.min(100, Math.max(1, limit)) };
40090
+ const { data: queryResponse } = await this.http.get(`/api/v2/search/channels`, {
40091
+ params: {
40092
+ query,
40093
+ exactMatch,
40094
+ isMemberOnly,
40095
+ types,
40096
+ tags,
40097
+ sortBy,
40098
+ orderBy,
40099
+ options,
40100
+ },
40101
+ });
40102
+ return queryResponse;
40103
+ }
40104
+ }
40105
+
40106
+ class SearchChannelQueryStreamController extends QueryStreamController {
40107
+ constructor(query, cacheKey, notifyChange) {
40108
+ super(query, cacheKey);
40109
+ this.notifyChange = notifyChange;
40110
+ }
40111
+ async saveToMainDB(response) {
40112
+ const processedPayload = await prepareChannelPayload(response);
40113
+ const client = getActiveClient();
40114
+ const cachedAt = client.cache && Date.now();
40115
+ if (client.cache) {
40116
+ ingestInCache(processedPayload, { cachedAt });
40117
+ }
40118
+ }
40119
+ appendToQueryStream(response, direction, refresh = false) {
40120
+ var _a, _b;
40121
+ if (refresh) {
40122
+ pushToCache(this.cacheKey, {
40123
+ data: response.channels.map(getResolver('channel')),
40124
+ });
40125
+ return;
40126
+ }
40127
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40128
+ const existing = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
40129
+ const incoming = response.channels.map(getResolver('channel'));
40130
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: direction === "prev" /* Amity.LiveCollectionPageDirection.PREV */
40131
+ ? [...new Set([...incoming, ...existing])]
40132
+ : [...new Set([...existing, ...incoming])] }));
40133
+ }
40134
+ reactor() {
40135
+ return () => this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
40136
+ }
40137
+ subscribeRTE(createSubscriber) {
40138
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor()));
40139
+ }
40140
+ }
40141
+
40142
+ /* eslint-disable no-use-before-define */
40143
+ const getMessagePreviewSetting = () => {
40144
+ const client = getActiveClient();
40145
+ return client.getMessagePreviewSetting(false);
40146
+ };
40147
+ class SearchChannelLiveCollectionController extends LiveCollectionController {
40148
+ constructor(query, callback) {
40149
+ const queryStreamId = hash(query);
40150
+ const cacheKey = ['channel', 'search', queryStreamId];
40151
+ const paginationController = new SearchChannelPaginationController(query);
40152
+ super(paginationController, queryStreamId, cacheKey, callback);
40153
+ this.queryStreamController = new SearchChannelQueryStreamController(query, this.cacheKey, this.notifyChange.bind(this));
40154
+ this.callback = callback.bind(this);
40155
+ this.loadPage({ initial: true });
40156
+ }
40157
+ startSubscription() {
40158
+ return this.queryStreamController.subscribeRTE(this.getSubscriptions());
40159
+ }
40160
+ notifyChange({ origin, loading, error }) {
40161
+ var _a, _b;
40162
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40163
+ if (!collection)
40164
+ return;
40165
+ const data = (_b = collection.data
40166
+ .map(channelId => pullFromCache(['channel', 'get', channelId]))
40167
+ .filter(Boolean)
40168
+ .map(cached => constructChannelObject(cached.data))) !== null && _b !== void 0 ? _b : [];
40169
+ if (!this.shouldNotify(data) && origin === 'event')
40170
+ return;
40171
+ this.callback({
40172
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
40173
+ data,
40174
+ hasNextPage: !!this.paginationController.getNextToken(),
40175
+ loading,
40176
+ error,
40177
+ });
40178
+ }
40179
+ setup() {
40180
+ var _a;
40181
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40182
+ if (!collection) {
40183
+ pushToCache(this.cacheKey, {
40184
+ data: [],
40185
+ params: {},
40186
+ });
40187
+ }
40188
+ }
40189
+ async persistModel(response) {
40190
+ await this.queryStreamController.saveToMainDB(response);
40191
+ }
40192
+ persistQueryStream({ response, direction, refresh, }) {
40193
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
40194
+ }
40195
+ shouldAbort(targetChannelId) {
40196
+ var _a;
40197
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40198
+ if (!collection)
40199
+ return true;
40200
+ return !collection.data.find(channelId => channelId === targetChannelId);
40201
+ }
40202
+ getSubscriptions() {
40203
+ return [
40204
+ {
40205
+ fn: convertEventPayload((callback) => {
40206
+ return onMessageCreatedMqtt(message => {
40207
+ var _a;
40208
+ const cacheData = (_a = pullFromCache([
40209
+ 'channel',
40210
+ 'get',
40211
+ message.channelId,
40212
+ ])) === null || _a === void 0 ? void 0 : _a.data;
40213
+ if (!cacheData)
40214
+ return;
40215
+ updateChannelCache(cacheData, {
40216
+ lastActivity: message.createdAt,
40217
+ });
40218
+ callback(message);
40219
+ });
40220
+ }, 'channelId', 'channel'),
40221
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40222
+ },
40223
+ {
40224
+ fn: convertEventPayload((callback) => {
40225
+ return onMessageCreatedLocal(message => {
40226
+ var _a;
40227
+ const cacheData = (_a = pullFromCache([
40228
+ 'channel',
40229
+ 'get',
40230
+ message.channelId,
40231
+ ])) === null || _a === void 0 ? void 0 : _a.data;
40232
+ if (!cacheData)
40233
+ return;
40234
+ updateChannelCache(cacheData, {
40235
+ lastActivity: message.createdAt,
40236
+ });
40237
+ callback(message);
40238
+ });
40239
+ }, 'channelId', 'channel'),
40240
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40241
+ },
40242
+ { fn: onChannelDeleted, action: "onDelete" /* Amity.ChannelActionType.OnDelete */ },
40243
+ { fn: onChannelUpdated, action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */ },
40244
+ { fn: onChannelSetMuted, action: "onMute" /* Amity.ChannelActionType.OnMute */ },
40245
+ {
40246
+ fn: (reactor) => onChannelArchived(payload => {
40247
+ const channels = payload.archives
40248
+ .map(archive => {
40249
+ var _a;
40250
+ return (_a = pullFromCache(['channel', 'get', archive.channelId])) === null || _a === void 0 ? void 0 : _a.data;
40251
+ })
40252
+ .filter((c) => Boolean(c));
40253
+ if (channels.length > 0)
40254
+ reactor(channels);
40255
+ }),
40256
+ action: "onArchived" /* Amity.ChannelActionType.OnArchived */,
40257
+ },
40258
+ {
40259
+ fn: (reactor) => onChannelUnarchived(payload => {
40260
+ const channels = payload.archives
40261
+ .map(archive => {
40262
+ var _a;
40263
+ return (_a = pullFromCache(['channel', 'get', archive.channelId])) === null || _a === void 0 ? void 0 : _a.data;
40264
+ })
40265
+ .filter((c) => Boolean(c));
40266
+ if (channels.length > 0)
40267
+ reactor(channels);
40268
+ }),
40269
+ action: "onUnarchived" /* Amity.ChannelActionType.OnUnarchived */,
40270
+ },
40271
+ {
40272
+ fn: convertEventPayload(onChannelMarkerFetched, 'entityId', 'channel'),
40273
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40274
+ },
40275
+ {
40276
+ fn: convertEventPayload(onChannelMarkerUpdated, 'entityId', 'channel'),
40277
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40278
+ },
40279
+ {
40280
+ fn: convertEventPayload((callback) => {
40281
+ const updateMessagePreview = async (message) => {
40282
+ var _a;
40283
+ const messagePreviewSetting = await getMessagePreviewSetting();
40284
+ if (messagePreviewSetting === "no-message-preview" /* Amity.MessagePreviewSetting.NO_MESSAGE_PREVIEW */)
40285
+ return;
40286
+ handleMessageCreated(message);
40287
+ if (this.shouldAbort(message.channelId))
40288
+ return;
40289
+ const channel = (_a = pullFromCache([
40290
+ 'channel',
40291
+ 'get',
40292
+ message.channelId,
40293
+ ])) === null || _a === void 0 ? void 0 : _a.data;
40294
+ if (!channel)
40295
+ return;
40296
+ updateChannelCache(channel, {
40297
+ messagePreviewId: message.messageId,
40298
+ });
40299
+ callback(message);
40300
+ };
40301
+ return onMessageCreatedMqtt(updateMessagePreview);
40302
+ }, 'channelId', 'channel'),
40303
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40304
+ },
40305
+ {
40306
+ fn: convertEventPayload((callback) => {
40307
+ const updateMessagePreview = async (message) => {
40308
+ var _a;
40309
+ const messagePreviewSetting = await getMessagePreviewSetting();
40310
+ if (messagePreviewSetting === "no-message-preview" /* Amity.MessagePreviewSetting.NO_MESSAGE_PREVIEW */)
40311
+ return;
40312
+ handleMessageCreated(message);
40313
+ if (this.shouldAbort(message.channelId))
40314
+ return;
40315
+ const channel = (_a = pullFromCache([
40316
+ 'channel',
40317
+ 'get',
40318
+ message.channelId,
40319
+ ])) === null || _a === void 0 ? void 0 : _a.data;
40320
+ if (!channel)
40321
+ return;
40322
+ updateChannelCache(channel, {
40323
+ messagePreviewId: message.messageId,
40324
+ });
40325
+ callback(message);
40326
+ };
40327
+ return onMessageCreatedLocal(updateMessagePreview);
40328
+ }, 'channelId', 'channel'),
40329
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40330
+ },
40331
+ {
40332
+ fn: convertEventPayload((callback) => {
40333
+ const updateMessagePreview = async (message) => {
40334
+ const messagePreviewSetting = await getMessagePreviewSetting();
40335
+ if (messagePreviewSetting === "no-message-preview" /* Amity.MessagePreviewSetting.NO_MESSAGE_PREVIEW */)
40336
+ return;
40337
+ handleMessageUpdated(message);
40338
+ if (this.shouldAbort(message.channelId))
40339
+ return;
40340
+ callback(message);
40341
+ };
40342
+ return onMessageUpdated(updateMessagePreview);
40343
+ }, 'channelId', 'channel'),
40344
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40345
+ },
40346
+ {
40347
+ fn: convertEventPayload((callback) => {
40348
+ const updateMessagePreview = async (message) => {
40349
+ const messagePreviewSetting = await getMessagePreviewSetting();
40350
+ if (messagePreviewSetting === "no-message-preview" /* Amity.MessagePreviewSetting.NO_MESSAGE_PREVIEW */)
40351
+ return;
40352
+ if (messagePreviewSetting ===
40353
+ "message-preview-include-deleted" /* Amity.MessagePreviewSetting.MESSAGE_PREVIEW_INCLUDE_DELETED */)
40354
+ await handleMessageUpdated(message);
40355
+ if (this.shouldAbort(message.channelId))
40356
+ return;
40357
+ if (messagePreviewSetting ===
40358
+ "message-preview-not-include-deleted" /* Amity.MessagePreviewSetting.MESSAGE_PREVIEW_NOT_INCLUDE_DELETED */) {
40359
+ await getChannel$1(message.channelId);
40360
+ }
40361
+ callback(message);
40362
+ };
40363
+ return onMessageDeleted(updateMessagePreview);
40364
+ }, 'channelId', 'channel'),
40365
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40366
+ },
40367
+ {
40368
+ fn: convertEventPayload((callback) => {
40369
+ const updateMessagePreview = async (subChannel) => {
40370
+ var _a;
40371
+ const collections = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40372
+ if (!collections)
40373
+ return;
40374
+ const channelId = collections.data.find(channel => {
40375
+ const messagePreviewCache = getChannelMessagePreview(channel);
40376
+ return (messagePreviewCache === null || messagePreviewCache === void 0 ? void 0 : messagePreviewCache.subChannelId) === subChannel.subChannelId;
40377
+ });
40378
+ if (!channelId)
40379
+ return;
40380
+ await getChannel$1(subChannel.channelId);
40381
+ callback(subChannel);
40382
+ };
40383
+ return onSubChannelDeleted(updateMessagePreview);
40384
+ }, 'channelId', 'channel'),
40385
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40386
+ },
40387
+ {
40388
+ fn: convertEventPayload((callback) => {
40389
+ const updateMessagePreview = async (subChannel) => {
40390
+ var _a;
40391
+ const messagePreviewSetting = await getMessagePreviewSetting();
40392
+ if (messagePreviewSetting === "no-message-preview" /* Amity.MessagePreviewSetting.NO_MESSAGE_PREVIEW */)
40393
+ return;
40394
+ const collections = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
40395
+ if (!collections)
40396
+ return;
40397
+ await handleSubChannelUpdated(subChannel);
40398
+ if (this.shouldAbort(subChannel.channelId))
40399
+ return;
40400
+ callback(subChannel);
40401
+ };
40402
+ return onSubChannelUpdated(updateMessagePreview);
40403
+ }, 'channelId', 'channel'),
40404
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40405
+ },
40406
+ {
40407
+ fn: (callback) => {
40408
+ const handleUserFeedMarkerResolved = async (marker) => {
40409
+ if (marker.feedMarkers) {
40410
+ const channels = marker.feedMarkers
40411
+ .map(feedMarker => {
40412
+ var _a;
40413
+ return (_a = pullFromCache([
40414
+ 'channel',
40415
+ 'get',
40416
+ feedMarker.entityId,
40417
+ ])) === null || _a === void 0 ? void 0 : _a.data;
40418
+ })
40419
+ .filter(Boolean);
40420
+ callback(channels);
40421
+ }
40422
+ };
40423
+ return onUserMessageFeedMarkerResolved(handleUserFeedMarkerResolved);
40424
+ },
40425
+ action: "OnResolveUnread" /* Amity.ChannelActionType.OnResolveUnread */,
40426
+ },
40427
+ {
40428
+ fn: convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
40429
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40430
+ },
40431
+ {
40432
+ fn: convertEventPayload((callback) => {
40433
+ const processPayload = (payloads) => {
40434
+ payloads.forEach(callback);
40435
+ };
40436
+ return onChannelUnreadUpdatedLocal(processPayload);
40437
+ }, 'channelId', 'channel'),
40438
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
40439
+ },
40440
+ ];
38449
40441
  }
38450
40442
  }
38451
40443
 
38452
- /* eslint-disable no-use-before-define */
38453
40444
  /* begin_public_function
38454
- id: channel.query
40445
+ id: channel.search
38455
40446
  */
38456
40447
  /**
38457
40448
  * ```js
38458
- * import { getChannels } from '@amityco/ts-sdk-react-native'
40449
+ * import { ChannelRepository } from '@amityco/ts-sdk';
38459
40450
  *
38460
- * let channels = []
38461
- * const unsub = getChannels({
38462
- * displayName: Amity.Channel['displayName'],
38463
- * }, response => merge(channels, response.data))
40451
+ * const unsubscribe = ChannelRepository.searchChannels(
40452
+ * { query: 'hello' },
40453
+ * response => response.data,
40454
+ * );
38464
40455
  * ```
38465
40456
  *
38466
- * Observe all mutations on a list of {@link Amity.Channel}s
40457
+ * Live collection of {@link Amity.Channel}s matching the search query. Backed by
40458
+ * `GET /api/v2/search/channels`.
38467
40459
  *
38468
- * @param params for querying channels
38469
- * @param callback the function to call when new data are available
38470
- * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the channels
40460
+ * @param params Search parameters.
40461
+ * @param callback Called whenever new data are available.
40462
+ * @returns An {@link Amity.Unsubscriber} function to stop observing.
38471
40463
  *
38472
40464
  * @category Channel Live Collection
38473
40465
  */
38474
- const getChannels = (params, callback, config) => {
38475
- const { log, cache, userId } = getActiveClient();
38476
- if (!cache) {
40466
+ const searchChannels = (params, callback) => {
40467
+ const { log, cache } = getActiveClient();
40468
+ if (!cache)
38477
40469
  console.log(ENABLE_CACHE_MESSAGE);
38478
- }
38479
40470
  const timestamp = Date.now();
38480
- log(`getChannels(tmpid: ${timestamp}) > listen`);
38481
- const channelLiveCollection = new ChannelLiveCollectionController(params, callback);
38482
- const disposers = channelLiveCollection.startSubscription();
38483
- const cacheKey = channelLiveCollection.getCacheKey();
40471
+ log(`searchChannels(tmpid: ${timestamp}) > listen`);
40472
+ const searchChannelLiveCollection = new SearchChannelLiveCollectionController(params, callback);
40473
+ const disposers = searchChannelLiveCollection.startSubscription();
40474
+ const cacheKey = searchChannelLiveCollection.getCacheKey();
38484
40475
  disposers.push(() => {
38485
40476
  dropFromCache(cacheKey);
38486
40477
  });
38487
40478
  return () => {
38488
- log(`getChannels(tmpid: ${timestamp}) > dispose`);
40479
+ log(`searchChannels(tmpid: ${timestamp}) > dispose`);
38489
40480
  disposers.forEach(fn => fn());
38490
40481
  };
38491
40482
  };
38492
40483
  /* end_public_function */
38493
40484
 
38494
- /**
38495
- *
38496
- * Calculate user unread from {@link Amity.ChannelUnread} objects
38497
- *
38498
- * @returns the {@link Amity.UserUnread} objects
38499
- *
38500
- * @category Channel API
38501
- * @async
38502
- */
38503
- const getTotalChannelsUnread$1 = () => {
38504
- var _a;
38505
- const client = getActiveClient();
38506
- client.log('channel/getTotalChannelsUnread.locally');
38507
- const cachedChannelsUnread = ((_a = queryCache(['channelUnread', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
38508
- return !data.isDeleted;
38509
- })) || [];
38510
- const totalChannelsUnread = (cachedChannelsUnread === null || cachedChannelsUnread === void 0 ? void 0 : cachedChannelsUnread.reduce((acc, { data }) => {
38511
- acc.unreadCount += data.unreadCount;
38512
- acc.isMentioned = acc.isMentioned || data.isMentioned;
38513
- return acc;
38514
- }, { unreadCount: 0, isMentioned: false })) || { unreadCount: 0, isMentioned: false };
38515
- const cachedAt = client.cache && Date.now();
38516
- return {
38517
- data: totalChannelsUnread,
38518
- cachedAt,
38519
- };
38520
- };
38521
-
38522
- /* begin_public_function
38523
- id: totalChannelsUnread.get
38524
- */
38525
- /**
38526
- * ```js
38527
- * import { ChannelRepository } from '@amityco/ts-sdk-react-native';
38528
- *
38529
- * let totalChannelsUnread;
38530
- *
38531
- * const unsubscribe = ChannelRepository.getTotalChannelsUnread(response => {
38532
- * unread = response.data;
38533
- * });
38534
- * ```
38535
- *
38536
- * Observe all mutation on a given {@link Amity.UserUnread}
38537
- *
38538
- * @returns An {@link Amity.UserUnread} function to run when willing to stop observing the message
38539
- *
38540
- * @category User Unread Live Object
38541
- *
38542
- */
38543
- const getTotalChannelsUnread = (callback) => {
38544
- const { _id: userId } = getActiveUser();
38545
- if (!userId)
38546
- throw new ASCError('The _id has not been defined in ActiveUser', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
38547
- const { log, cache } = getActiveClient();
38548
- if (!cache) {
38549
- console.log('For using Live Object feature you need to enable Cache!');
38550
- }
38551
- const timestamp = Date.now();
38552
- log(`liveTotalChannelsUnread(tmpid: ${timestamp}) > listen`);
38553
- const disposers = [];
38554
- let isUnsyncedModel = false; // for messages
38555
- let model;
38556
- const dispatcher = (data) => {
38557
- const { data: userUnread } = data;
38558
- const callbackModel = userUnread
38559
- ? {
38560
- unreadCount: userUnread.unreadCount,
38561
- isMentioned: userUnread.isMentioned,
38562
- }
38563
- : undefined;
38564
- model = callbackModel ? convertGetterPropsToStatic(callbackModel) : callbackModel;
38565
- callback({
38566
- data: callbackModel
38567
- ? Object.assign(Object.assign({}, callbackModel), { isMentioned: callbackModel.isMentioned }) : callbackModel,
38568
- loading: data.loading,
38569
- error: data.error,
38570
- });
38571
- };
38572
- const realtimeRouter = (_) => {
38573
- const { data: userUnread } = getTotalChannelsUnread$1();
38574
- if (isEqual(model, userUnread))
38575
- return;
38576
- dispatcher({
38577
- loading: false,
38578
- data: userUnread,
38579
- });
38580
- };
38581
- const onFetch = () => {
38582
- const query = createQuery(async () => getTotalChannelsUnread$1());
38583
- runQuery(query, ({ error, data, loading, origin, cachedAt }) => {
38584
- if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
38585
- dispatcher({
38586
- data,
38587
- origin,
38588
- loading: false,
38589
- error: new ASCApiError(UNSYNCED_OBJECT_CACHED_AT_MESSAGE, 800800 /* Amity.ClientError.DISALOOW_UNSYNCED_OBJECT */, "error" /* Amity.ErrorLevel.ERROR */),
38590
- });
38591
- isUnsyncedModel = true;
38592
- disposers.forEach(fn => fn());
38593
- }
38594
- else if (!isUnsyncedModel) {
38595
- dispatcher({ loading, data, origin, error });
38596
- }
38597
- if (error) {
38598
- disposers.forEach(fn => fn());
38599
- }
38600
- });
38601
- };
38602
- disposers.push(onChannelUnreadUpdatedLocal(realtimeRouter));
38603
- onFetch();
38604
- return () => {
38605
- disposers.forEach(fn => fn());
38606
- };
38607
- };
38608
-
38609
40485
  /* begin_public_function
38610
40486
  id: channel.member.add
38611
40487
  */
@@ -38737,7 +40613,9 @@ class ChannelMemberQueryStreamController extends QueryStreamController {
38737
40613
  channelId: this.query.channelId,
38738
40614
  userId: channelMember.userId,
38739
40615
  });
38740
- if (channelMember.membership === 'none') {
40616
+ const membershipFilter = this.query.memberships;
40617
+ const isInFilter = !membershipFilter || membershipFilter.includes(channelMember.membership);
40618
+ if (channelMember.membership === 'none' || !isInFilter) {
38741
40619
  collection.data = collection.data.filter(m => m !== channelMemberCacheId);
38742
40620
  }
38743
40621
  else if (!collection.data.includes(channelMemberCacheId)) {
@@ -39073,6 +40951,7 @@ const banMembers$1 = async (channelId, userIds) => {
39073
40951
  const cachedAt = client.cache && Date.now();
39074
40952
  if (client.cache)
39075
40953
  ingestInCache(preparedPayload, { cachedAt });
40954
+ fireEvent('channel.banned', payload);
39076
40955
  return {
39077
40956
  data: channelUsers === null || channelUsers === void 0 ? void 0 : channelUsers.filter(user => user.membership === 'banned'),
39078
40957
  cachedAt,
@@ -39107,6 +40986,7 @@ const unbanMembers$1 = async (channelId, userIds) => {
39107
40986
  const cachedAt = client.cache && Date.now();
39108
40987
  if (client.cache)
39109
40988
  ingestInCache(preparedPayload, { cachedAt });
40989
+ fireEvent('channel.unbanned', payload);
39110
40990
  const { channelUsers } = preparedPayload;
39111
40991
  return {
39112
40992
  data: channelUsers === null || channelUsers === void 0 ? void 0 : channelUsers.filter(user => user.membership === 'member'),
@@ -39135,6 +41015,7 @@ const MUTE_FOREVER = -1;
39135
41015
  * @async
39136
41016
  * */
39137
41017
  const muteMembers = async (channelId, userIds, mutePeriod = MUTE_FOREVER) => {
41018
+ var _a;
39138
41019
  const client = getActiveClient();
39139
41020
  client.log('channel/muteMembers', { userIds, channelId, mutePeriod });
39140
41021
  const { data } = await client.http.put(`/api/v2/channel/${channelId}/users/mute`, {
@@ -39142,6 +41023,15 @@ const muteMembers = async (channelId, userIds, mutePeriod = MUTE_FOREVER) => {
39142
41023
  mutePeriod: mutePeriod === MUTE_FOREVER ? mutePeriod : mutePeriod * 1000,
39143
41024
  });
39144
41025
  const { success } = data;
41026
+ const muteTimeout = mutePeriod === MUTE_FOREVER
41027
+ ? new Date('9999-12-31T23:59:59.999Z').toISOString()
41028
+ : new Date(Date.now() + mutePeriod * 1000).toISOString();
41029
+ fireEvent('channel.setMutedUsers', {
41030
+ channelId,
41031
+ userIds,
41032
+ muteTimeout,
41033
+ actor: (_a = client.userId) !== null && _a !== void 0 ? _a : '',
41034
+ });
39145
41035
  return success;
39146
41036
  };
39147
41037
  /* end_public_function */
@@ -39164,6 +41054,7 @@ const muteMembers = async (channelId, userIds, mutePeriod = MUTE_FOREVER) => {
39164
41054
  * @async
39165
41055
  * */
39166
41056
  const unmuteMembers = async (channelId, userIds) => {
41057
+ var _a;
39167
41058
  const client = getActiveClient();
39168
41059
  client.log('channel/unmuteMembers', { userIds, channelId });
39169
41060
  const { data } = await client.http.put(`/api/v2/channel/${encodeURIComponent(channelId)}/users/mute`, {
@@ -39171,6 +41062,12 @@ const unmuteMembers = async (channelId, userIds) => {
39171
41062
  mutePeriod: 0,
39172
41063
  });
39173
41064
  const { success } = data;
41065
+ fireEvent('channel.setMutedUsers', {
41066
+ channelId,
41067
+ userIds,
41068
+ muteTimeout: new Date(0).toISOString(),
41069
+ actor: (_a = client.userId) !== null && _a !== void 0 ? _a : '',
41070
+ });
39174
41071
  return success;
39175
41072
  };
39176
41073
  /* end_public_function */
@@ -39197,6 +41094,9 @@ var index$j = /*#__PURE__*/Object.freeze({
39197
41094
  leaveChannel: leaveChannel,
39198
41095
  muteChannel: muteChannel,
39199
41096
  unmuteChannel: unmuteChannel,
41097
+ archiveChannel: archiveChannel,
41098
+ unarchiveChannel: unarchiveChannel,
41099
+ getArchivedChannelIds: getArchivedChannelIds,
39200
41100
  onChannelCreated: onChannelCreated,
39201
41101
  onChannelUpdated: onChannelUpdated,
39202
41102
  onChannelDeleted: onChannelDeleted,
@@ -39209,9 +41109,13 @@ var index$j = /*#__PURE__*/Object.freeze({
39209
41109
  onChannelMemberUnbanned: onChannelMemberUnbanned,
39210
41110
  onChannelMemberRoleAdded: onChannelMemberRoleAdded,
39211
41111
  onChannelMemberRoleRemoved: onChannelMemberRoleRemoved,
41112
+ onChannelArchived: onChannelArchived,
41113
+ onChannelUnarchived: onChannelUnarchived,
39212
41114
  getChannel: getChannel,
39213
41115
  getChannels: getChannels,
39214
41116
  getTotalChannelsUnread: getTotalChannelsUnread,
41117
+ getArchivedChannels: getArchivedChannels,
41118
+ searchChannels: searchChannels,
39215
41119
  MARKER_INCLUDED_CHANNEL_TYPE: MARKER_INCLUDED_CHANNEL_TYPE,
39216
41120
  isUnreadCountSupport: isUnreadCountSupport,
39217
41121
  convertFromRaw: convertFromRaw,
@@ -43108,7 +45012,7 @@ class CommentLiveCollectionController extends LiveCollectionController {
43108
45012
  this.queryStreamController.appendToQueryStream(response, direction, refresh);
43109
45013
  }
43110
45014
  startSubscription() {
43111
- return this.queryStreamController.subscribeRTE([
45015
+ const disposers = this.queryStreamController.subscribeRTE([
43112
45016
  { fn: onCommentCreatedLocal, action: EnumCommentActions.OnCommentCreated },
43113
45017
  { fn: onCommentDeleteLocal, action: EnumCommentActions.OnCommentDeleted },
43114
45018
  { fn: onCommentCreated, action: EnumCommentActions.OnCommentCreated },
@@ -43121,6 +45025,11 @@ class CommentLiveCollectionController extends LiveCollectionController {
43121
45025
  { fn: onLocalCommentReactionAdded, action: EnumCommentActions.OnCommentReactionAdded },
43122
45026
  { fn: onLocalCommentReactionRemoved, action: EnumCommentActions.OnCommentReactionRemoved },
43123
45027
  ]);
45028
+ if (this.query.excludeBlockUserComments) {
45029
+ const refresh = () => this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
45030
+ disposers.push(onUserDidBlock(refresh), onUserDidUnblock(refresh));
45031
+ }
45032
+ return disposers;
43124
45033
  }
43125
45034
  notifyChange({ origin, loading, error }) {
43126
45035
  var _a, _b;
@@ -43173,6 +45082,9 @@ class CommentLiveCollectionController extends LiveCollectionController {
43173
45082
  comments = comments.filter(comment => { var _a; return (_a = this.query.dataTypes) === null || _a === void 0 ? void 0 : _a.values.some(value => { var _a; return (_a = comment.dataTypes) === null || _a === void 0 ? void 0 : _a.includes(value); }); });
43174
45083
  }
43175
45084
  }
45085
+ if (this.query.excludeBlockUserComments) {
45086
+ comments = filterCommentsByBlockUsers(comments);
45087
+ }
43176
45088
  switch (this.query.sortBy) {
43177
45089
  case 'firstCreated':
43178
45090
  comments = comments.sort(sortByFirstCreated);
@@ -44258,13 +46170,253 @@ const getCommunityFeed = (params, callback, config) => {
44258
46170
  };
44259
46171
  /* end_public_function */
44260
46172
 
46173
+ /**
46174
+ * Thrown by `getForYouFeed` when the network has the For You feature
46175
+ * disabled. Mapped from HTTP 404 NOT_FOUND. Distinct from a generic
46176
+ * not-found so consumers can hide the For You tab without retrying.
46177
+ *
46178
+ * @category Errors
46179
+ */
46180
+ class AmityForYouFeedDisabledError extends ASCApiError {
46181
+ constructor(message = 'For You feed is not enabled for this network') {
46182
+ super(message, 400400 /* Amity.ServerError.ITEM_NOT_FOUND */, "error" /* Amity.ErrorLevel.ERROR */);
46183
+ this.type = 'AmityForYouFeedDisabledError';
46184
+ }
46185
+ }
46186
+
46187
+ class ForYouFeedPaginationController extends PaginationController {
46188
+ constructor(query) {
46189
+ super(query);
46190
+ this.checkedDisk = false;
46191
+ this.hasDeliveredPost = false;
46192
+ this.cursor = CursorController.current();
46193
+ }
46194
+ async getRequest(_queryParams, token) {
46195
+ var _a, _b, _c, _d, _e;
46196
+ const isFirstPage = token === undefined;
46197
+ let stored = null;
46198
+ // On the first page of a fresh collection, load the saved cursor from disk once.
46199
+ // Drop it if the snapshot has already expired so we start fresh.
46200
+ if (isFirstPage && !this.checkedDisk && this.cursor) {
46201
+ this.checkedDisk = true;
46202
+ stored = await this.cursor.get();
46203
+ if (stored && CursorController.isExpired(stored.expiredAt)) {
46204
+ await this.cursor.clear();
46205
+ stored = null;
46206
+ }
46207
+ }
46208
+ // Already paged to the end before. Ask the BE fresh (no cursor) and check if it's
46209
+ // still the same snapshot the user finished.
46210
+ if (isFirstPage && (stored === null || stored === void 0 ? void 0 : stored.reachedEndOfFeed)) {
46211
+ const fresh = await this.fetch();
46212
+ const freshExpiredAt = Date.parse((_b = (_a = fresh.paging) === null || _a === void 0 ? void 0 : _a.expiredAt) !== null && _b !== void 0 ? _b : '');
46213
+ const rolledOver = !Number.isNaN(freshExpiredAt) && freshExpiredAt !== stored.expiredAt;
46214
+ // New snapshot → serve it. Same snapshot → user has seen it all, show empty.
46215
+ if (rolledOver) {
46216
+ await this.persistCursor(fresh);
46217
+ if (fresh.posts.length > 0)
46218
+ this.hasDeliveredPost = true;
46219
+ return fresh;
46220
+ }
46221
+ return Object.assign(Object.assign({}, fresh), { posts: [], paging: {} });
46222
+ }
46223
+ // Resume from the saved cursor on re-entry; otherwise use the live-collection token.
46224
+ const effectiveToken = isFirstPage && stored ? stored.cursor : token;
46225
+ const response = await this.fetch(effectiveToken);
46226
+ if (response.posts.length > 0)
46227
+ this.hasDeliveredPost = true;
46228
+ if ((_c = response.paging) === null || _c === void 0 ? void 0 : _c.next) {
46229
+ // More pages left → advance the saved cursor.
46230
+ await this.persistCursor(response);
46231
+ }
46232
+ else if (this.hasDeliveredPost && this.cursor) {
46233
+ // Reached the end and mark end of feed
46234
+ const expiredAt = Date.parse((_e = (_d = response.paging) === null || _d === void 0 ? void 0 : _d.expiredAt) !== null && _e !== void 0 ? _e : '');
46235
+ if (!Number.isNaN(expiredAt))
46236
+ await this.cursor.markReachedEndOfFeed(expiredAt);
46237
+ }
46238
+ return response;
46239
+ }
46240
+ async fetch(token) {
46241
+ const options = { limit: COLLECTION_DEFAULT_PAGINATION_SIZE };
46242
+ if (token)
46243
+ options.token = token;
46244
+ try {
46245
+ const { data } = await this.http.get(API_ENDPOINTS.forYouFeed, {
46246
+ params: { options },
46247
+ });
46248
+ return data;
46249
+ }
46250
+ catch (error) {
46251
+ if (error instanceof ASCApiError && error.code === 400300 /* Amity.ServerError.FORBIDDEN */) {
46252
+ throw new AmityForYouFeedDisabledError();
46253
+ }
46254
+ const recoverable = error instanceof ASCApiError && error.code === 400322 /* Amity.ServerError.FEED_SNAPSHOT_EXPIRED */;
46255
+ if (recoverable && token !== undefined) {
46256
+ if (this.cursor)
46257
+ await this.cursor.clear();
46258
+ const { data } = await this.http.get(API_ENDPOINTS.forYouFeed, {
46259
+ params: { options: { limit: COLLECTION_DEFAULT_PAGINATION_SIZE } },
46260
+ });
46261
+ return data;
46262
+ }
46263
+ throw error;
46264
+ }
46265
+ }
46266
+ async persistCursor(response) {
46267
+ var _a, _b;
46268
+ if (!this.cursor)
46269
+ return;
46270
+ const cursor = (_a = response.paging) === null || _a === void 0 ? void 0 : _a.next;
46271
+ const expiredAtIso = (_b = response.paging) === null || _b === void 0 ? void 0 : _b.expiredAt;
46272
+ if (!cursor || !expiredAtIso)
46273
+ return;
46274
+ const expiredAt = Date.parse(expiredAtIso);
46275
+ if (Number.isNaN(expiredAt))
46276
+ return;
46277
+ await this.cursor.set({ cursor, expiredAt });
46278
+ }
46279
+ }
46280
+
46281
+ class ForYouFeedQueryStreamController extends QueryStreamController {
46282
+ constructor(query, cacheKey, notifyChange, preparePayload) {
46283
+ super(query, cacheKey);
46284
+ this.notifyChange = notifyChange;
46285
+ this.preparePayload = preparePayload;
46286
+ }
46287
+ async saveToMainDB(response) {
46288
+ const processedPayload = await this.preparePayload(response);
46289
+ const client = getActiveClient();
46290
+ const cachedAt = client.cache && Date.now();
46291
+ if (client.cache)
46292
+ ingestInCache(processedPayload, { cachedAt });
46293
+ }
46294
+ appendToQueryStream(response, _direction, refresh = false) {
46295
+ var _a, _b;
46296
+ if (refresh) {
46297
+ pushToCache(this.cacheKey, {
46298
+ data: response.posts.map(getResolver('post')),
46299
+ });
46300
+ }
46301
+ else {
46302
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
46303
+ const posts = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
46304
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [...new Set([...posts, ...response.posts.map(getResolver('post'))])] }));
46305
+ }
46306
+ }
46307
+ reactor(action) {
46308
+ return (post) => {
46309
+ var _a;
46310
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
46311
+ if (!collection)
46312
+ return;
46313
+ if (post.parentPostId && !collection.data.includes(post.parentPostId))
46314
+ return;
46315
+ if (action === EnumPostActions.OnPostDeleted || action === EnumPostActions.OnPostDeclined) {
46316
+ collection.data = collection.data.filter(postId => postId !== post.postId);
46317
+ }
46318
+ pushToCache(this.cacheKey, collection);
46319
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
46320
+ };
46321
+ }
46322
+ subscribeRTE(createSubscriber) {
46323
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
46324
+ }
46325
+ }
46326
+
46327
+ const FOR_YOU_FEED_CACHE_KEY = ['forYouFeed', 'collection'];
46328
+ class ForYouFeedLiveCollectionController extends LiveCollectionController {
46329
+ constructor(callback) {
46330
+ const queryStreamId = `for-you-feed-${getActiveClient().userId}`;
46331
+ const query = {};
46332
+ const paginationController = new ForYouFeedPaginationController(query);
46333
+ super(paginationController, queryStreamId, FOR_YOU_FEED_CACHE_KEY, callback);
46334
+ this.queryStreamController = new ForYouFeedQueryStreamController(query, this.cacheKey, this.notifyChange.bind(this), preparePostPayload);
46335
+ this.callback = callback.bind(this);
46336
+ this.loadPage({ initial: true });
46337
+ }
46338
+ setup() {
46339
+ var _a;
46340
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
46341
+ if (!collection)
46342
+ pushToCache(this.cacheKey, { data: [], params: {} });
46343
+ }
46344
+ async persistModel(payload) {
46345
+ await this.queryStreamController.saveToMainDB(payload);
46346
+ }
46347
+ persistQueryStream({ response, direction, refresh, }) {
46348
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
46349
+ }
46350
+ startSubscription() {
46351
+ return this.queryStreamController.subscribeRTE(getGlobalFeedSubscriptions(this.cacheKey));
46352
+ }
46353
+ notifyChange({ origin, loading, error }) {
46354
+ var _a, _b;
46355
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
46356
+ if (!collection)
46357
+ return;
46358
+ const data = ((_b = collection.data
46359
+ .map(id => pullFromCache(['post', 'get', id]))
46360
+ .filter(isNonNullable)
46361
+ .map(({ data }) => data)) !== null && _b !== void 0 ? _b : []).map(LinkedObject.post);
46362
+ if (!this.shouldNotify(data) && origin === 'event')
46363
+ return;
46364
+ this.callback({
46365
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
46366
+ data,
46367
+ hasNextPage: !!this.paginationController.getNextToken(),
46368
+ loading,
46369
+ error,
46370
+ });
46371
+ }
46372
+ }
46373
+
46374
+ /* begin_public_function
46375
+ id: feed.query.for_you_feed
46376
+ */
46377
+ /**
46378
+ * ```js
46379
+ * import { FeedRepository } from '@amityco/ts-sdk'
46380
+ *
46381
+ * const unsub = FeedRepository.getForYouFeed(({ data, loading, error, hasNextPage, onNextPage }) => {
46382
+ * // render posts; call onNextPage() to load the next page (20 posts)
46383
+ * })
46384
+ * ```
46385
+ *
46386
+ * Observe the For You feed — a personalized, server-ranked
46387
+ * {@link Amity.LiveCollection} of {@link Amity.Post}.
46388
+ *
46389
+ * @param callback the function to call when new data is available
46390
+ * @returns an {@link Amity.Unsubscriber} function to stop observing
46391
+ *
46392
+ * @category Posts Live Collection
46393
+ */
46394
+ const getForYouFeed = (callback) => {
46395
+ const { log, cache } = getActiveClient();
46396
+ if (!cache)
46397
+ console.log(ENABLE_CACHE_MESSAGE);
46398
+ const timestamp = Date.now();
46399
+ log(`getForYouFeed(tmpid: ${timestamp}) > listen`);
46400
+ const forYouFeedLiveCollection = new ForYouFeedLiveCollectionController(callback);
46401
+ const disposers = forYouFeedLiveCollection.startSubscription();
46402
+ const cacheKey = forYouFeedLiveCollection.getCacheKey();
46403
+ disposers.push(() => dropFromCache(cacheKey));
46404
+ return () => {
46405
+ log(`getForYouFeed(tmpid: ${timestamp}) > dispose`);
46406
+ disposers.forEach(fn => fn());
46407
+ };
46408
+ };
46409
+ /* end_public_function */
46410
+
44261
46411
  var index$d = /*#__PURE__*/Object.freeze({
44262
46412
  __proto__: null,
44263
46413
  queryGlobalFeed: queryGlobalFeed,
44264
46414
  getCustomRankingGlobalFeed: getCustomRankingGlobalFeed,
44265
46415
  getGlobalFeed: getGlobalFeed,
44266
46416
  getUserFeed: getUserFeed,
44267
- getCommunityFeed: getCommunityFeed
46417
+ getCommunityFeed: getCommunityFeed,
46418
+ getForYouFeed: getForYouFeed,
46419
+ AmityForYouFeedDisabledError: AmityForYouFeedDisabledError
44268
46420
  });
44269
46421
 
44270
46422
  /* begin_public_function
@@ -45277,7 +47429,12 @@ class PostLiveCollectionController extends LiveCollectionController {
45277
47429
  this.queryStreamController.appendToQueryStream(response, direction, refresh);
45278
47430
  }
45279
47431
  startSubscription() {
45280
- return this.queryStreamController.subscribeRTE(getPostSubscription(this.cacheKey));
47432
+ const disposers = this.queryStreamController.subscribeRTE(getPostSubscription(this.cacheKey));
47433
+ if (this.query.excludeBlockUserPosts) {
47434
+ const refresh = () => this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
47435
+ disposers.push(onUserDidBlock(refresh), onUserDidUnblock(refresh));
47436
+ }
47437
+ return disposers;
45281
47438
  }
45282
47439
  notifyChange({ origin, loading, error }) {
45283
47440
  var _a, _b;
@@ -45323,6 +47480,9 @@ class PostLiveCollectionController extends LiveCollectionController {
45323
47480
  const sortBy = this.query.sortBy || 'lastCreated';
45324
47481
  posts = posts.filter(post => !exceedsUntilAtBoundary(post.createdAt, validatedUntilAt, sortBy));
45325
47482
  }
47483
+ if (this.query.excludeBlockUserPosts) {
47484
+ posts = filterPostsByBlockUsers(posts);
47485
+ }
45326
47486
  switch (this.query.sortBy) {
45327
47487
  case 'firstCreated':
45328
47488
  posts = posts.sort(sortByFirstCreated);
@@ -51980,4 +54140,4 @@ class AmityAttachmentProductTags {
51980
54140
  }
51981
54141
  }
51982
54142
 
51983
- export { API_REGIONS, index$5 as AdRepository, AmityAttachmentProductTags, AmityCommunityType, AmityEventOrderOption, AmityEventOriginType, AmityEventResponseStatus, AmityEventSortOption, AmityEventStatus, AmityEventType, AnalyticsSourceTypeEnum, index$f as CategoryRepository, index$j as ChannelRepository, index$s as Client, index$e as CommentRepository, CommunityPostSettingMaps, CommunityPostSettings, index$g as CommunityRepository, ContentFeedType, ContentFlagReasonEnum, DefaultCommunityPostSetting, index$1 as EventRepository, FeedDataTypeEnum, index$d as FeedRepository, FeedSortByEnum, FeedSourceEnum, FeedTypeEnum, FileAccessTypeEnum, index$p as FileRepository, FileType, GET_WATCHER_URLS, index$3 as InvitationRepository, InvitationSortByEnum, InvitationStatusEnum, InvitationTargetTypeEnum, InvitationTypeEnum, JoinRequestStatusEnum, JoinResultStatusEnum, index$2 as LiveReactionRepository, index$7 as LiveStreamPlayer, MembershipAcceptanceTypeEnum, MessageContentType, index$n as MessageRepository, index$8 as PollRepository, PostContentType, index$b as PostRepository, PostStructureType, index as ProductRepository, index$o as ReactionRepository, index$9 as RoomPresenceRepository, index$c as RoomRepository, SearchUsersByEnum, index$6 as StoryRepository, index$a as StreamRepository, index$m as SubChannelRepository, SubscriptionLevels, index$q as UserRepository, UserTypeEnum, VERSION, VideoResolution, VideoSize, VideoTranscodingStatus, backupCache, createQuery, createReport, createUserToken, deleteReport, disableCache, dropFromCache, enableCache, exceedsUntilAtBoundary, filterByChannelMembership, filterByCommunityMembership, filterByFeedType, filterByPostDataTypes, filterByPropEquality, filterByPropInclusion, filterByPropIntersection, filterBySearchTerm, filterByStringComparePartially, filterByUntilAt, getChannelTopic, getCommentTopic, getCommunityStoriesTopic, getCommunityTopic, getLiveReactionTopic, getLiveStreamTopic, getMarkedMessageTopic, getMarkerUserFeedTopic, getMessageTopic, getMyFollowersTopic, getMyFollowingsTopic, getNetworkTopic, getPostTopic, getRole, getRoomStreamerTopic, getRoomWatcherTopic, getSmartFeedChannelTopic, getSmartFeedMessageTopic, getSmartFeedSubChannelTopic, getStoryTopic, getSubChannelTopic, getUserTopic, isAfterBefore, isAfterBeforeRaw, isCachable, isFetcher, isFresh, isLocal, isMutator, isOffline, isPaged, isReportedByMe, isSkip, mergeInCache, index$4 as notificationTray, onChannelMarkerFetched, onFeedMarkerFetched, onFeedMarkerUpdated, onMessageMarked, onMessageMarkerFetched, onSubChannelMarkerFetched, onSubChannelMarkerUpdated, onUserMarkerFetched, onUserMarkerFetchedLegacy, pullFromCache, pushToCache, queryCache, queryOptions, queryRoles, restoreCache, runQuery, sortByChannelSegment, sortByDisplayName, sortByFirstCreated, sortByFirstUpdated, sortByLastActivity, sortByLastCreated, sortByLastUpdated, sortByLocalSortingDate, sortByName, sortBySegmentNumber, subscribeTopic, toPage, toPageRaw, toToken, upsertInCache, validateUntilAt, wipeCache };
54143
+ export { API_REGIONS, index$5 as AdRepository, AmityAttachmentProductTags, AmityAutoSubscription, AmityChannelNotificationModeEnum, AmityCommunityType, AmityEventOrderOption, AmityEventOriginType, AmityEventResponseStatus, AmityEventSortOption, AmityEventStatus, AmityEventType, AmitySharableContentType, AnalyticsSourceTypeEnum, index$f as CategoryRepository, index$j as ChannelRepository, index$s as Client, index$e as CommentRepository, CommunityNotificationEventNameEnum, CommunityPostSettingMaps, CommunityPostSettings, index$g as CommunityRepository, ContentFeedType, ContentFlagReasonEnum, DefaultCommunityPostSetting, index$1 as EventRepository, FeedDataTypeEnum, index$d as FeedRepository, FeedSortByEnum, FeedSourceEnum, FeedTypeEnum, FileAccessTypeEnum, index$p as FileRepository, FileType, GET_WATCHER_URLS, index$3 as InvitationRepository, InvitationSortByEnum, InvitationStatusEnum, InvitationTargetTypeEnum, InvitationTypeEnum, JoinRequestStatusEnum, JoinResultStatusEnum, index$2 as LiveReactionRepository, index$7 as LiveStreamPlayer, MembershipAcceptanceTypeEnum, MessageContentType, index$n as MessageRepository, NotificationRolesFilterTypeEnum, NotificationSettingsLevelEnum, index$8 as PollRepository, PostContentType, index$b as PostRepository, PostStructureType, index as ProductRepository, index$o as ReactionRepository, index$9 as RoomPresenceRepository, index$c as RoomRepository, SearchUsersByEnum, index$6 as StoryRepository, index$a as StreamRepository, index$m as SubChannelRepository, SubscriptionLevels, UserNotificationModuleNameEnum, index$q as UserRepository, UserTypeEnum, VERSION, VideoResolution, VideoSize, VideoTranscodingStatus, backupCache, createQuery, createReport, createUserToken, deleteReport, disableCache, dropFromCache, enableCache, exceedsUntilAtBoundary, filterByChannelMembership, filterByCommunityMembership, filterByFeedType, filterByPostDataTypes, filterByPropEquality, filterByPropInclusion, filterByPropIntersection, filterBySearchTerm, filterByStringComparePartially, filterByUntilAt, filterCommentsByBlockUsers, filterPostsByBlockUsers, getBlockUsersId, getChannelTopic, getCommentTopic, getCommunityStoriesTopic, getCommunityTopic, getLiveReactionTopic, getLiveStreamTopic, getMarkedMessageTopic, getMarkerUserFeedTopic, getMessageTopic, getMyFollowersTopic, getMyFollowingsTopic, getNetworkId, getNetworkTopic, getPostTopic, getRole, getRoomStreamerTopic, getRoomWatcherTopic, getSmartFeedChannelTopic, getSmartFeedMessageTopic, getSmartFeedSubChannelTopic, getStoryTopic, getSubChannelTopic, getUserTopic, isAfterBefore, isAfterBeforeRaw, isCachable, isFetcher, isFresh, isLocal, isMutator, isOffline, isPaged, isReportedByMe, isSkip, mergeInCache, index$4 as notificationTray, onChannelMarkerFetched, onFeedMarkerFetched, onFeedMarkerUpdated, onMessageMarked, onMessageMarkerFetched, onSubChannelMarkerFetched, onSubChannelMarkerUpdated, onUserMarkerFetched, onUserMarkerFetchedLegacy, pullFromCache, pushToCache, queryCache, queryOptions, queryRoles, restoreCache, runQuery, sortByChannelSegment, sortByDisplayName, sortByFirstCreated, sortByFirstUpdated, sortByLastActivity, sortByLastCreated, sortByLastUpdated, sortByLocalSortingDate, sortByName, sortBySegmentNumber, subscribeTopic, toPage, toPageRaw, toToken, upsertInCache, validateUntilAt, wipeCache };