@stream-io/feeds-client 0.2.7 → 0.2.9

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 (342) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/index.js +408 -0
  3. package/dist/cjs/index.js.map +1 -0
  4. package/dist/cjs/react-bindings.js +1368 -0
  5. package/dist/cjs/react-bindings.js.map +1 -0
  6. package/dist/es/index.mjs +398 -0
  7. package/dist/es/index.mjs.map +1 -0
  8. package/dist/es/react-bindings.mjs +1368 -0
  9. package/dist/es/react-bindings.mjs.map +1 -0
  10. package/dist/index-B0Mm2xFU.js +6492 -0
  11. package/dist/index-B0Mm2xFU.js.map +1 -0
  12. package/dist/index-rSXIDTdA.mjs +6476 -0
  13. package/dist/index-rSXIDTdA.mjs.map +1 -0
  14. package/dist/tsconfig.tsbuildinfo +1 -1
  15. package/dist/types/bindings/index.d.ts +2 -0
  16. package/dist/types/bindings/index.d.ts.map +1 -0
  17. package/dist/{@react-bindings → types/bindings/react}/contexts/StreamFeedContext.d.ts +2 -1
  18. package/dist/types/bindings/react/contexts/StreamFeedContext.d.ts.map +1 -0
  19. package/dist/{@react-bindings → types/bindings/react}/contexts/StreamFeedsContext.d.ts +2 -1
  20. package/dist/types/bindings/react/contexts/StreamFeedsContext.d.ts.map +1 -0
  21. package/dist/{@react-bindings → types/bindings/react}/contexts/StreamSearchContext.d.ts +2 -1
  22. package/dist/types/bindings/react/contexts/StreamSearchContext.d.ts.map +1 -0
  23. package/dist/{@react-bindings → types/bindings/react}/contexts/StreamSearchResultsContext.d.ts +2 -1
  24. package/dist/types/bindings/react/contexts/StreamSearchResultsContext.d.ts.map +1 -0
  25. package/dist/{@react-bindings → types/bindings/react}/hooks/client-state-hooks/index.d.ts +1 -0
  26. package/dist/types/bindings/react/hooks/client-state-hooks/index.d.ts.map +1 -0
  27. package/dist/types/bindings/react/hooks/client-state-hooks/useClientConnectedUser.d.ts +5 -0
  28. package/dist/types/bindings/react/hooks/client-state-hooks/useClientConnectedUser.d.ts.map +1 -0
  29. package/dist/{@react-bindings → types/bindings/react}/hooks/client-state-hooks/useWsConnectionState.d.ts +1 -0
  30. package/dist/types/bindings/react/hooks/client-state-hooks/useWsConnectionState.d.ts.map +1 -0
  31. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/index.d.ts +1 -0
  32. package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts.map +1 -0
  33. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useAggregatedActivities.d.ts +3 -2
  34. package/dist/types/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.d.ts.map +1 -0
  35. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useComments.d.ts +2 -3
  36. package/dist/types/bindings/react/hooks/feed-state-hooks/useComments.d.ts.map +1 -0
  37. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFeedActivities.d.ts +3 -2
  38. package/dist/types/bindings/react/hooks/feed-state-hooks/useFeedActivities.d.ts.map +1 -0
  39. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFeedMetadata.d.ts +3 -2
  40. package/dist/types/bindings/react/hooks/feed-state-hooks/useFeedMetadata.d.ts.map +1 -0
  41. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFollowers.d.ts +5 -4
  42. package/dist/types/bindings/react/hooks/feed-state-hooks/useFollowers.d.ts.map +1 -0
  43. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFollowing.d.ts +5 -4
  44. package/dist/types/bindings/react/hooks/feed-state-hooks/useFollowing.d.ts.map +1 -0
  45. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts +2 -2
  46. package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts.map +1 -0
  47. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts +2 -2
  48. package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts.map +1 -0
  49. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useNotificationStatus.d.ts +2 -1
  50. package/dist/types/bindings/react/hooks/feed-state-hooks/useNotificationStatus.d.ts.map +1 -0
  51. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useOwnCapabilities.d.ts +2 -1
  52. package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.d.ts.map +1 -0
  53. package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useOwnFollows.d.ts +3 -2
  54. package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnFollows.d.ts.map +1 -0
  55. package/dist/{@react-bindings → types/bindings/react}/hooks/internal/index.d.ts +1 -0
  56. package/dist/types/bindings/react/hooks/internal/index.d.ts.map +1 -0
  57. package/dist/{@react-bindings → types/bindings/react}/hooks/internal/useStableCallback.d.ts +1 -0
  58. package/dist/types/bindings/react/hooks/internal/useStableCallback.d.ts.map +1 -0
  59. package/dist/{@react-bindings → types/bindings/react}/hooks/search-state-hooks/index.d.ts +1 -0
  60. package/dist/types/bindings/react/hooks/search-state-hooks/index.d.ts.map +1 -0
  61. package/dist/{@react-bindings → types/bindings/react}/hooks/search-state-hooks/useSearchQuery.d.ts +2 -1
  62. package/dist/types/bindings/react/hooks/search-state-hooks/useSearchQuery.d.ts.map +1 -0
  63. package/dist/{@react-bindings → types/bindings/react}/hooks/search-state-hooks/useSearchResult.d.ts +2 -1
  64. package/dist/types/bindings/react/hooks/search-state-hooks/useSearchResult.d.ts.map +1 -0
  65. package/dist/types/bindings/react/hooks/search-state-hooks/useSearchSources.d.ts +5 -0
  66. package/dist/types/bindings/react/hooks/search-state-hooks/useSearchSources.d.ts.map +1 -0
  67. package/dist/{@react-bindings → types/bindings/react}/hooks/useCreateFeedsClient.d.ts +2 -4
  68. package/dist/types/bindings/react/hooks/useCreateFeedsClient.d.ts.map +1 -0
  69. package/dist/{@react-bindings → types/bindings/react}/hooks/util/index.d.ts +1 -0
  70. package/dist/types/bindings/react/hooks/util/index.d.ts.map +1 -0
  71. package/dist/{@react-bindings → types/bindings/react}/hooks/util/useBookmarkActions.d.ts +2 -1
  72. package/dist/types/bindings/react/hooks/util/useBookmarkActions.d.ts.map +1 -0
  73. package/dist/{@react-bindings → types/bindings/react}/hooks/util/useReactionActions.d.ts +2 -1
  74. package/dist/types/bindings/react/hooks/util/useReactionActions.d.ts.map +1 -0
  75. package/dist/{@react-bindings → types/bindings/react}/index.d.ts +2 -1
  76. package/dist/types/bindings/react/index.d.ts.map +1 -0
  77. package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamFeed.d.ts +2 -1
  78. package/dist/types/bindings/react/wrappers/StreamFeed.d.ts.map +1 -0
  79. package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamFeeds.d.ts +1 -0
  80. package/dist/types/bindings/react/wrappers/StreamFeeds.d.ts.map +1 -0
  81. package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamSearch.d.ts +2 -1
  82. package/dist/types/bindings/react/wrappers/StreamSearch.d.ts.map +1 -0
  83. package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamSearchResults.d.ts +2 -1
  84. package/dist/types/bindings/react/wrappers/StreamSearchResults.d.ts.map +1 -0
  85. package/dist/{src → types}/common/ApiClient.d.ts +18 -0
  86. package/dist/types/common/ApiClient.d.ts.map +1 -0
  87. package/dist/{src → types}/common/ConnectionIdManager.d.ts +1 -0
  88. package/dist/types/common/ConnectionIdManager.d.ts.map +1 -0
  89. package/dist/{src → types}/common/EventDispatcher.d.ts +1 -0
  90. package/dist/types/common/EventDispatcher.d.ts.map +1 -0
  91. package/dist/{src → types}/common/Poll.d.ts +2 -1
  92. package/dist/types/common/Poll.d.ts.map +1 -0
  93. package/dist/{src → types}/common/TokenManager.d.ts +2 -0
  94. package/dist/types/common/TokenManager.d.ts.map +1 -0
  95. package/dist/{src → types}/common/gen-imports.d.ts +1 -0
  96. package/dist/types/common/gen-imports.d.ts.map +1 -0
  97. package/dist/{src → types}/common/rate-limit.d.ts +1 -0
  98. package/dist/types/common/rate-limit.d.ts.map +1 -0
  99. package/dist/{src → types}/common/real-time/StableWSConnection.d.ts +4 -4
  100. package/dist/types/common/real-time/StableWSConnection.d.ts.map +1 -0
  101. package/dist/{src → types}/common/real-time/event-models.d.ts +1 -0
  102. package/dist/types/common/real-time/event-models.d.ts.map +1 -0
  103. package/dist/{src → types}/common/search/ActivitySearchSource.d.ts +1 -0
  104. package/dist/types/common/search/ActivitySearchSource.d.ts.map +1 -0
  105. package/dist/{src → types}/common/search/BaseSearchSource.d.ts +2 -1
  106. package/dist/types/common/search/BaseSearchSource.d.ts.map +1 -0
  107. package/dist/{src → types}/common/search/FeedSearchSource.d.ts +1 -0
  108. package/dist/types/common/search/FeedSearchSource.d.ts.map +1 -0
  109. package/dist/{src → types}/common/search/SearchController.d.ts +2 -1
  110. package/dist/types/common/search/SearchController.d.ts.map +1 -0
  111. package/dist/{src → types}/common/search/UserSearchSource.d.ts +2 -1
  112. package/dist/types/common/search/UserSearchSource.d.ts.map +1 -0
  113. package/dist/{src → types}/common/search/index.d.ts +1 -0
  114. package/dist/types/common/search/index.d.ts.map +1 -0
  115. package/dist/{src → types}/common/search/types.d.ts +1 -0
  116. package/dist/types/common/search/types.d.ts.map +1 -0
  117. package/dist/{src → types}/common/types.d.ts +3 -1
  118. package/dist/types/common/types.d.ts.map +1 -0
  119. package/dist/{src → types}/common/utils.d.ts +1 -0
  120. package/dist/types/common/utils.d.ts.map +1 -0
  121. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-added.d.ts +3 -2
  122. package/dist/types/feed/event-handlers/activity/handle-activity-added.d.ts.map +1 -0
  123. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-deleted.d.ts +3 -2
  124. package/dist/types/feed/event-handlers/activity/handle-activity-deleted.d.ts.map +1 -0
  125. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-marked.d.ts +1 -0
  126. package/dist/types/feed/event-handlers/activity/handle-activity-marked.d.ts.map +1 -0
  127. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-pinned.d.ts +1 -0
  128. package/dist/types/feed/event-handlers/activity/handle-activity-pinned.d.ts.map +1 -0
  129. package/dist/types/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +15 -0
  130. package/dist/types/feed/event-handlers/activity/handle-activity-reaction-added.d.ts.map +1 -0
  131. package/dist/types/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +15 -0
  132. package/dist/types/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts.map +1 -0
  133. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts +1 -0
  134. package/dist/types/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts.map +1 -0
  135. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-unpinned.d.ts +1 -0
  136. package/dist/types/feed/event-handlers/activity/handle-activity-unpinned.d.ts.map +1 -0
  137. package/dist/{src → types}/feed/event-handlers/activity/handle-activity-updated.d.ts +1 -0
  138. package/dist/types/feed/event-handlers/activity/handle-activity-updated.d.ts.map +1 -0
  139. package/dist/{src → types}/feed/event-handlers/activity/index.d.ts +1 -0
  140. package/dist/types/feed/event-handlers/activity/index.d.ts.map +1 -0
  141. package/dist/{src → types}/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +1 -0
  142. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-added.d.ts.map +1 -0
  143. package/dist/{src → types}/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +1 -0
  144. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts.map +1 -0
  145. package/dist/{src → types}/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +1 -0
  146. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts.map +1 -0
  147. package/dist/{src → types}/feed/event-handlers/bookmark/index.d.ts +1 -0
  148. package/dist/types/feed/event-handlers/bookmark/index.d.ts.map +1 -0
  149. package/dist/{src → types}/feed/event-handlers/comment/handle-comment-added.d.ts +1 -0
  150. package/dist/types/feed/event-handlers/comment/handle-comment-added.d.ts.map +1 -0
  151. package/dist/{src → types}/feed/event-handlers/comment/handle-comment-deleted.d.ts +1 -0
  152. package/dist/types/feed/event-handlers/comment/handle-comment-deleted.d.ts.map +1 -0
  153. package/dist/{src → types}/feed/event-handlers/comment/handle-comment-reaction.d.ts +1 -0
  154. package/dist/types/feed/event-handlers/comment/handle-comment-reaction.d.ts.map +1 -0
  155. package/dist/{src → types}/feed/event-handlers/comment/handle-comment-updated.d.ts +1 -0
  156. package/dist/types/feed/event-handlers/comment/handle-comment-updated.d.ts.map +1 -0
  157. package/dist/{src → types}/feed/event-handlers/comment/index.d.ts +1 -0
  158. package/dist/types/feed/event-handlers/comment/index.d.ts.map +1 -0
  159. package/dist/{src → types}/feed/event-handlers/feed/handle-feed-updated.d.ts +1 -0
  160. package/dist/types/feed/event-handlers/feed/handle-feed-updated.d.ts.map +1 -0
  161. package/dist/{src → types}/feed/event-handlers/feed/index.d.ts +1 -0
  162. package/dist/types/feed/event-handlers/feed/index.d.ts.map +1 -0
  163. package/dist/{src → types}/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +1 -0
  164. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-added.d.ts.map +1 -0
  165. package/dist/{src → types}/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +1 -0
  166. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts.map +1 -0
  167. package/dist/{src → types}/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +1 -0
  168. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts.map +1 -0
  169. package/dist/{src → types}/feed/event-handlers/feed-member/index.d.ts +1 -0
  170. package/dist/types/feed/event-handlers/feed-member/index.d.ts.map +1 -0
  171. package/dist/{src → types}/feed/event-handlers/follow/handle-follow-created.d.ts +3 -2
  172. package/dist/types/feed/event-handlers/follow/handle-follow-created.d.ts.map +1 -0
  173. package/dist/{src → types}/feed/event-handlers/follow/handle-follow-deleted.d.ts +2 -1
  174. package/dist/types/feed/event-handlers/follow/handle-follow-deleted.d.ts.map +1 -0
  175. package/dist/{src → types}/feed/event-handlers/follow/handle-follow-updated.d.ts +3 -2
  176. package/dist/types/feed/event-handlers/follow/handle-follow-updated.d.ts.map +1 -0
  177. package/dist/{src → types}/feed/event-handlers/follow/index.d.ts +1 -0
  178. package/dist/types/feed/event-handlers/follow/index.d.ts.map +1 -0
  179. package/dist/{src → types}/feed/event-handlers/index.d.ts +1 -0
  180. package/dist/types/feed/event-handlers/index.d.ts.map +1 -0
  181. package/dist/{src → types}/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +1 -0
  182. package/dist/types/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts.map +1 -0
  183. package/dist/{src → types}/feed/event-handlers/notification-feed/index.d.ts +1 -0
  184. package/dist/types/feed/event-handlers/notification-feed/index.d.ts.map +1 -0
  185. package/dist/{src → types}/feed/event-handlers/watch/handle-watch-started.d.ts +1 -0
  186. package/dist/types/feed/event-handlers/watch/handle-watch-started.d.ts.map +1 -0
  187. package/dist/{src → types}/feed/event-handlers/watch/handle-watch-stopped.d.ts +1 -0
  188. package/dist/types/feed/event-handlers/watch/handle-watch-stopped.d.ts.map +1 -0
  189. package/dist/{src → types}/feed/event-handlers/watch/index.d.ts +1 -0
  190. package/dist/types/feed/event-handlers/watch/index.d.ts.map +1 -0
  191. package/dist/{src → types}/feed/feed.d.ts +9 -6
  192. package/dist/types/feed/feed.d.ts.map +1 -0
  193. package/dist/{src → types}/feed/index.d.ts +1 -0
  194. package/dist/types/feed/index.d.ts.map +1 -0
  195. package/dist/{src → types}/feeds-client/event-handlers/index.d.ts +1 -0
  196. package/dist/types/feeds-client/event-handlers/index.d.ts.map +1 -0
  197. package/dist/{src → types}/feeds-client/event-handlers/user/handle-user-updated.d.ts +1 -0
  198. package/dist/types/feeds-client/event-handlers/user/handle-user-updated.d.ts.map +1 -0
  199. package/dist/{src → types}/feeds-client/feeds-client.d.ts +18 -10
  200. package/dist/types/feeds-client/feeds-client.d.ts.map +1 -0
  201. package/dist/{src → types}/feeds-client/index.d.ts +1 -0
  202. package/dist/types/feeds-client/index.d.ts.map +1 -0
  203. package/dist/{src → types}/gen/feeds/FeedApi.d.ts +1 -0
  204. package/dist/types/gen/feeds/FeedApi.d.ts.map +1 -0
  205. package/dist/{src → types}/gen/feeds/FeedsApi.d.ts +1 -0
  206. package/dist/types/gen/feeds/FeedsApi.d.ts.map +1 -0
  207. package/dist/{src → types}/gen/model-decoders/decoders.d.ts +1 -0
  208. package/dist/types/gen/model-decoders/decoders.d.ts.map +1 -0
  209. package/dist/{src → types}/gen/model-decoders/event-decoder-mapping.d.ts +1 -0
  210. package/dist/types/gen/model-decoders/event-decoder-mapping.d.ts.map +1 -0
  211. package/dist/{src → types}/gen/models/index.d.ts +43 -2
  212. package/dist/types/gen/models/index.d.ts.map +1 -0
  213. package/dist/{src → types}/gen/moderation/ModerationApi.d.ts +1 -0
  214. package/dist/types/gen/moderation/ModerationApi.d.ts.map +1 -0
  215. package/dist/{src → types}/gen-imports.d.ts +1 -0
  216. package/dist/types/gen-imports.d.ts.map +1 -0
  217. package/dist/types/index.d.ts +10 -0
  218. package/dist/types/index.d.ts.map +1 -0
  219. package/dist/{src → types}/moderation-client.d.ts +1 -0
  220. package/dist/types/moderation-client.d.ts.map +1 -0
  221. package/dist/{src → types}/types-internal.d.ts +4 -0
  222. package/dist/types/types-internal.d.ts.map +1 -0
  223. package/dist/{src → types}/types.d.ts +1 -0
  224. package/dist/types/types.d.ts.map +1 -0
  225. package/dist/{src → types}/utils/check-has-another-page.d.ts +1 -0
  226. package/dist/types/utils/check-has-another-page.d.ts.map +1 -0
  227. package/dist/{src → types}/utils/constants.d.ts +1 -0
  228. package/dist/types/utils/constants.d.ts.map +1 -0
  229. package/dist/{src → types}/utils/index.d.ts +2 -0
  230. package/dist/types/utils/index.d.ts.map +1 -0
  231. package/dist/types/utils/is-react-native.d.ts +5 -0
  232. package/dist/types/utils/is-react-native.d.ts.map +1 -0
  233. package/dist/types/utils/logger.d.ts +61 -0
  234. package/dist/types/utils/logger.d.ts.map +1 -0
  235. package/dist/types/utils/state-update-queue.d.ts +83 -0
  236. package/dist/types/utils/state-update-queue.d.ts.map +1 -0
  237. package/dist/types/utils/type-assertions.d.ts +12 -0
  238. package/dist/types/utils/type-assertions.d.ts.map +1 -0
  239. package/dist/{src → types}/utils/unique-array-merge.d.ts +1 -0
  240. package/dist/types/utils/unique-array-merge.d.ts.map +1 -0
  241. package/dist/{src → types}/utils/update-entity-in-array.d.ts +1 -0
  242. package/dist/types/utils/update-entity-in-array.d.ts.map +1 -0
  243. package/package.json +21 -33
  244. package/src/bindings/index.ts +1 -0
  245. package/src/bindings/react/contexts/StreamFeedContext.tsx +18 -0
  246. package/src/bindings/react/contexts/StreamFeedsContext.tsx +21 -0
  247. package/src/bindings/react/contexts/StreamSearchContext.tsx +18 -0
  248. package/src/bindings/react/contexts/StreamSearchResultsContext.tsx +20 -0
  249. package/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts +18 -0
  250. package/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts +18 -0
  251. package/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts +25 -0
  252. package/src/bindings/react/hooks/feed-state-hooks/useComments.ts +91 -0
  253. package/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts +36 -0
  254. package/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts +28 -0
  255. package/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts +54 -0
  256. package/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts +54 -0
  257. package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts +29 -0
  258. package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts +28 -0
  259. package/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts +28 -0
  260. package/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts +70 -0
  261. package/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts +18 -0
  262. package/src/bindings/react/hooks/internal/useStableCallback.ts +37 -0
  263. package/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts +14 -0
  264. package/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts +36 -0
  265. package/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts +17 -0
  266. package/src/bindings/react/hooks/useCreateFeedsClient.ts +73 -0
  267. package/src/bindings/react/hooks/util/useBookmarkActions.ts +40 -0
  268. package/src/bindings/react/hooks/util/useReactionActions.ts +56 -0
  269. package/{@react-bindings → src/bindings/react}/index.ts +1 -1
  270. package/src/bindings/react/wrappers/StreamFeed.tsx +23 -0
  271. package/src/bindings/react/wrappers/StreamFeeds.tsx +13 -0
  272. package/src/bindings/react/wrappers/StreamSearch.tsx +23 -0
  273. package/src/bindings/react/wrappers/StreamSearchResults.tsx +23 -0
  274. package/src/common/ApiClient.ts +86 -33
  275. package/src/common/EventDispatcher.ts +3 -6
  276. package/src/common/Poll.ts +1 -1
  277. package/src/common/TokenManager.ts +4 -0
  278. package/src/common/real-time/StableWSConnection.ts +64 -60
  279. package/src/common/search/BaseSearchSource.ts +11 -4
  280. package/src/common/search/SearchController.ts +4 -2
  281. package/src/common/types.ts +3 -2
  282. package/src/feed/event-handlers/activity/activity-utils.test.ts +40 -9
  283. package/src/feed/event-handlers/activity/handle-activity-added.test.ts +1 -1
  284. package/src/feed/event-handlers/activity/handle-activity-added.ts +7 -7
  285. package/src/feed/event-handlers/activity/handle-activity-deleted.ts +15 -12
  286. package/src/feed/event-handlers/activity/handle-activity-reaction-added.test.ts +101 -1
  287. package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +55 -29
  288. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.test.ts +118 -1
  289. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +59 -32
  290. package/src/feed/event-handlers/activity/handle-activity-removed-from-feed.ts +1 -1
  291. package/src/feed/event-handlers/follow/follow-state-update-queue.test.ts +219 -0
  292. package/src/feed/event-handlers/follow/handle-follow-created.ts +7 -2
  293. package/src/feed/event-handlers/follow/handle-follow-deleted.ts +5 -0
  294. package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +0 -43
  295. package/src/feed/event-handlers/follow/handle-follow-updated.ts +7 -2
  296. package/src/feed/feed.test.ts +90 -0
  297. package/src/feed/feed.ts +25 -4
  298. package/src/feeds-client/feeds-client.ts +35 -4
  299. package/src/gen/feeds/FeedsApi.ts +2 -0
  300. package/src/gen/model-decoders/decoders.ts +22 -0
  301. package/src/gen/models/index.ts +71 -3
  302. package/src/index.ts +9 -0
  303. package/src/test-utils/response-generators.ts +12 -3
  304. package/src/types-internal.ts +4 -0
  305. package/src/utils/index.ts +1 -0
  306. package/src/utils/is-react-native.ts +7 -0
  307. package/src/utils/logger.ts +18 -0
  308. package/src/utils/state-update-queue.test.ts +85 -9
  309. package/src/utils/state-update-queue.ts +104 -11
  310. package/src/utils/type-assertions.ts +22 -1
  311. package/dist/@react-bindings/hooks/client-state-hooks/useClientConnectedUser.d.ts +0 -4
  312. package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +0 -4
  313. package/dist/@react-bindings/hooks/useStateStore.d.ts +0 -3
  314. package/dist/index-react-bindings.browser.cjs +0 -6607
  315. package/dist/index-react-bindings.browser.cjs.map +0 -1
  316. package/dist/index-react-bindings.browser.js +0 -6574
  317. package/dist/index-react-bindings.browser.js.map +0 -1
  318. package/dist/index-react-bindings.node.cjs +0 -6607
  319. package/dist/index-react-bindings.node.cjs.map +0 -1
  320. package/dist/index-react-bindings.node.js +0 -6574
  321. package/dist/index-react-bindings.node.js.map +0 -1
  322. package/dist/index.browser.cjs +0 -6578
  323. package/dist/index.browser.cjs.map +0 -1
  324. package/dist/index.browser.js +0 -6551
  325. package/dist/index.browser.js.map +0 -1
  326. package/dist/index.d.ts +0 -9
  327. package/dist/index.node.cjs +0 -6578
  328. package/dist/index.node.cjs.map +0 -1
  329. package/dist/index.node.js +0 -6551
  330. package/dist/index.node.js.map +0 -1
  331. package/dist/src/common/StateStore.d.ts +0 -125
  332. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +0 -12
  333. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +0 -12
  334. package/dist/src/utils/state-update-queue.d.ts +0 -6
  335. package/dist/src/utils/type-assertions.d.ts +0 -7
  336. package/index.ts +0 -9
  337. package/src/common/StateStore.ts +0 -332
  338. /package/{@react-bindings → src/bindings/react}/hooks/client-state-hooks/index.ts +0 -0
  339. /package/{@react-bindings → src/bindings/react}/hooks/feed-state-hooks/index.ts +0 -0
  340. /package/{@react-bindings → src/bindings/react}/hooks/internal/index.ts +0 -0
  341. /package/{@react-bindings → src/bindings/react}/hooks/search-state-hooks/index.ts +0 -0
  342. /package/{@react-bindings → src/bindings/react}/hooks/util/index.ts +0 -0
@@ -0,0 +1,219 @@
1
+ import { beforeEach, describe, expect, it } from 'vitest';
2
+ import type { FollowResponse } from '../../../gen/models';
3
+ import { shouldUpdateState } from '../../../utils/state-update-queue';
4
+ import { handleFollowUpdated } from './handle-follow-updated';
5
+ import { Feed, handleFollowCreated, handleFollowDeleted } from '../../../feed';
6
+ import { FeedsClient } from '../../../feeds-client';
7
+ import {
8
+ generateFeedResponse,
9
+ generateFollowResponse,
10
+ generateOwnUser,
11
+ getHumanId,
12
+ } from '../../../test-utils';
13
+
14
+ describe(`Follow ${shouldUpdateState.name} integration`, () => {
15
+ let feed: Feed;
16
+ let client: FeedsClient;
17
+ let follow: FollowResponse;
18
+ let otherFollow: FollowResponse;
19
+ let ownFollow: FollowResponse;
20
+ let userId: string;
21
+
22
+ beforeEach(() => {
23
+ userId = getHumanId();
24
+ client = new FeedsClient('mock-api-key');
25
+
26
+ client.state.partialNext({
27
+ connected_user: generateOwnUser({ id: userId }),
28
+ });
29
+
30
+ const feedResponse = generateFeedResponse({
31
+ id: 'main',
32
+ group_id: 'user',
33
+ created_by: { id: userId },
34
+ });
35
+ feed = new Feed(client, 'user', 'main', feedResponse);
36
+ // Setup follows
37
+ follow = generateFollowResponse({
38
+ source_feed: generateFeedResponse({
39
+ id: 'main',
40
+ group_id: 'user',
41
+ created_by: { id: userId },
42
+ }),
43
+ target_feed: generateFeedResponse({
44
+ id: 'target',
45
+ group_id: 'user',
46
+ }),
47
+ });
48
+
49
+ otherFollow = generateFollowResponse({
50
+ source_feed: generateFeedResponse({
51
+ id: 'other',
52
+ group_id: 'user',
53
+ created_by: { id: getHumanId() },
54
+ }),
55
+ target_feed: generateFeedResponse({
56
+ id: 'main',
57
+ group_id: 'user',
58
+ }),
59
+ });
60
+
61
+ ownFollow = generateFollowResponse({
62
+ source_feed: generateFeedResponse({
63
+ id: 'other',
64
+ group_id: 'user',
65
+ created_by: { id: userId },
66
+ }),
67
+ target_feed: generateFeedResponse({
68
+ id: 'main',
69
+ group_id: 'user',
70
+ }),
71
+ });
72
+ // Set up initial state
73
+ feed.state.next((currentState) => ({
74
+ ...currentState,
75
+ following: [follow],
76
+ followers: [otherFollow],
77
+ own_follows: [ownFollow],
78
+ }));
79
+ });
80
+
81
+ describe.each(
82
+ [
83
+ {
84
+ handler: handleFollowCreated,
85
+ state: {
86
+ status: 'accepted',
87
+ },
88
+ count: 2,
89
+ },
90
+ {
91
+ handler: handleFollowUpdated,
92
+ state: {
93
+ status: 'accepted',
94
+ },
95
+ count: 1,
96
+ },
97
+ { handler: handleFollowDeleted, state: undefined, count: 0 },
98
+ ].map(({ handler, state, count }) => [
99
+ handler.name,
100
+ handler,
101
+ state as Partial<FollowResponse>,
102
+ count,
103
+ ]),
104
+ )(`%s`, (_name, handler, state, count) => {
105
+ it(`skips update if ${shouldUpdateState.name} returns false`, () => {
106
+ // Prepare feed, set as watched
107
+ feed.state.partialNext({ watch: true });
108
+
109
+ const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
110
+
111
+ // 1. HTTP and then WS event
112
+
113
+ // Call once as HTTP response to populate the queue
114
+ handler.call(
115
+ feed,
116
+ {
117
+ follow: { ...updatedFollow, ...state },
118
+ },
119
+ false,
120
+ );
121
+
122
+ // Call again as WS event, should be skipped
123
+ let stateBefore = feed.currentState;
124
+ handler.call(feed, { follow: updatedFollow });
125
+
126
+ // State should not change
127
+ let stateAfter = feed.currentState;
128
+ expect(stateAfter).toBe(stateBefore);
129
+ // @ts-expect-error Using Feed internals for tests only
130
+ expect(feed.stateUpdateQueue.size).toEqual(0);
131
+
132
+ // 2. WS and then HTTP
133
+
134
+ // Call once as WS event to populate the queue
135
+ handler.call(
136
+ feed,
137
+ {
138
+ follow: { ...updatedFollow, ...state },
139
+ },
140
+ );
141
+
142
+ // Call again as HTTP response, should be skipped
143
+ stateBefore = feed.currentState;
144
+ handler.call(feed, { follow: updatedFollow }, false);
145
+
146
+ // State should not change
147
+ stateAfter = feed.currentState;
148
+ expect(stateAfter).toBe(stateBefore);
149
+ // @ts-expect-error Using Feed internals for tests only
150
+ expect(feed.stateUpdateQueue.size).toEqual(0);
151
+ });
152
+
153
+ it('allows update again from WS after clearing the stateUpdateQueue', () => {
154
+ const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
155
+
156
+ handler.call(feed, { follow: updatedFollow });
157
+
158
+ // Clear the queue
159
+ (feed as any).stateUpdateQueue.clear();
160
+
161
+ // Now update should be allowed from another WS event
162
+ handler.call(feed, {
163
+ follow: { ...updatedFollow, ...state },
164
+ });
165
+
166
+ const following = feed.currentState.following!;
167
+ const [updatedFollowAfter] = following;
168
+
169
+ expect(following.length).toEqual(count);
170
+ expect(updatedFollowAfter).toMatchObject(state!);
171
+ });
172
+
173
+ it('allows update again from HTTP response after clearing the stateUpdateQueue', () => {
174
+ const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
175
+
176
+ handler.call(feed, { follow: updatedFollow }, false);
177
+
178
+ // Clear the queue
179
+ (feed as any).stateUpdateQueue.clear();
180
+
181
+ // Now update should be allowed from another HTTP response
182
+ handler.call(
183
+ feed,
184
+ {
185
+ follow: { ...updatedFollow, ...state },
186
+ },
187
+ false,
188
+ );
189
+
190
+ const following = feed.currentState.following!;
191
+ const [updatedFollowAfter] = following;
192
+
193
+ expect(following.length).toEqual(count);
194
+ expect(updatedFollowAfter).toMatchObject(state!);
195
+ });
196
+
197
+ it('should not insert anything into the stateUpdateQueue if the connected_user did not trigger the follow', () => {
198
+ const updatedFollow: FollowResponse = {
199
+ ...otherFollow,
200
+ status: 'pending',
201
+ };
202
+
203
+ handler.call(feed, { follow: updatedFollow });
204
+
205
+ expect((feed as any).stateUpdateQueue).toEqual(new Set());
206
+
207
+ handler.call(feed, {
208
+ follow: { ...updatedFollow, ...state },
209
+ });
210
+
211
+ const following = feed.currentState.following!;
212
+ const [updatedFollowAfter] = following;
213
+
214
+ expect((feed as any).stateUpdateQueue).toEqual(new Set());
215
+ expect(following.length).toEqual(1);
216
+ expect(updatedFollowAfter).toMatchObject(follow);
217
+ });
218
+ });
219
+ });
@@ -1,4 +1,4 @@
1
- import type { Feed, FeedState } from '../../../feed';
1
+ import type { Feed, FeedState } from '../../feed';
2
2
  import type { FollowResponse } from '../../../gen/models';
3
3
  import type {
4
4
  EventPayload,
@@ -65,14 +65,19 @@ export function handleFollowCreated(
65
65
  EventPayload<'feeds.follow.created'>,
66
66
  'follow'
67
67
  >,
68
+ fromWs?: boolean,
68
69
  ) {
69
70
  const follow = eventOrResponse.follow;
70
71
 
71
72
  if (
72
73
  !shouldUpdateState({
73
- stateUpdateQueueId: getStateUpdateQueueId(follow, 'created'),
74
+ stateUpdateQueueId: getStateUpdateQueueId(follow, 'follow-created'),
74
75
  stateUpdateQueue: this.stateUpdateQueue,
75
76
  watch: this.currentState.watch,
77
+ fromWs,
78
+ isTriggeredByConnectedUser:
79
+ this.client.state.getLatestValue().connected_user?.id ===
80
+ follow.source_feed.created_by.id,
76
81
  })
77
82
  ) {
78
83
  return;
@@ -68,6 +68,7 @@ export function handleFollowDeleted(
68
68
  EventPayload<'feeds.follow.deleted'>,
69
69
  'follow'
70
70
  >,
71
+ fromWs?: boolean,
71
72
  ) {
72
73
  const follow = eventOrResponse.follow;
73
74
 
@@ -76,6 +77,10 @@ export function handleFollowDeleted(
76
77
  stateUpdateQueueId: getStateUpdateQueueId(follow, 'deleted'),
77
78
  stateUpdateQueue: this.stateUpdateQueue,
78
79
  watch: this.currentState.watch,
80
+ fromWs,
81
+ isTriggeredByConnectedUser:
82
+ this.client.state.getLatestValue().connected_user?.id ===
83
+ follow.source_feed.created_by.id,
79
84
  })
80
85
  ) {
81
86
  return;
@@ -9,7 +9,6 @@ import {
9
9
  generateOwnUser,
10
10
  } from '../../../test-utils/response-generators';
11
11
  import { FollowResponse } from '../../../gen/models';
12
- import { shouldUpdateState } from '../../../utils';
13
12
 
14
13
  describe(handleFollowUpdated.name, () => {
15
14
  let feed: Feed;
@@ -129,46 +128,4 @@ describe(handleFollowUpdated.name, () => {
129
128
  expect(stateAfter.following).toBe(stateBefore.following);
130
129
  expect(stateAfter.following_count).toBe(stateBefore.following_count);
131
130
  });
132
-
133
- describe(`${shouldUpdateState.name} integration`, () => {
134
- it(`skips update if ${shouldUpdateState.name} returns false`, () => {
135
- // Prepare feed, set as watched
136
- feed.state.partialNext({ watch: true });
137
-
138
- const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
139
-
140
- // Call once to populate queue
141
- handleFollowUpdated.call(feed, { follow: updatedFollow });
142
-
143
- // Call again, should be skipped
144
- const stateBefore = feed.currentState;
145
- handleFollowUpdated.call(feed, {
146
- follow: { ...updatedFollow, status: 'accepted' },
147
- });
148
-
149
- // State should not change
150
- const stateAfter = feed.currentState;
151
- expect(stateAfter).toBe(stateBefore);
152
- });
153
-
154
- it('allows update again after clearing stateUpdateQueue', () => {
155
- const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
156
-
157
- handleFollowUpdated.call(feed, { follow: updatedFollow });
158
-
159
- // Clear the queue
160
- (feed as any).stateUpdateQueue.clear();
161
-
162
- // Now update should be allowed
163
- handleFollowUpdated.call(feed, {
164
- follow: { ...updatedFollow, status: 'accepted' },
165
- });
166
-
167
- const [updatedFollowAfter] = feed.currentState.following!;
168
-
169
- expect(updatedFollowAfter).toMatchObject({
170
- status: 'accepted',
171
- });
172
- });
173
- });
174
131
  });
@@ -1,4 +1,4 @@
1
- import type { Feed, FeedState } from '../../../feed';
1
+ import type { Feed, FeedState } from '../../feed';
2
2
  import { getStateUpdateQueueId, shouldUpdateState } from '../../../utils';
3
3
  import { EventPayload, PartializeAllBut } from '../../../types-internal';
4
4
 
@@ -8,6 +8,7 @@ export function handleFollowUpdated(
8
8
  EventPayload<'feeds.follow.updated'>,
9
9
  'follow'
10
10
  >,
11
+ fromWs?: boolean,
11
12
  ) {
12
13
  const follow = eventOrResponse.follow;
13
14
  const connectedUserId = this.client.state.getLatestValue().connected_user?.id;
@@ -15,9 +16,13 @@ export function handleFollowUpdated(
15
16
 
16
17
  if (
17
18
  !shouldUpdateState({
18
- stateUpdateQueueId: getStateUpdateQueueId(follow, 'updated'),
19
+ stateUpdateQueueId: getStateUpdateQueueId(follow, 'follow-updated'),
19
20
  stateUpdateQueue: this.stateUpdateQueue,
20
21
  watch: this.currentState.watch,
22
+ fromWs,
23
+ isTriggeredByConnectedUser:
24
+ this.client.state.getLatestValue().connected_user?.id ===
25
+ follow.source_feed.created_by.id,
21
26
  })
22
27
  ) {
23
28
  return;
@@ -0,0 +1,90 @@
1
+ import { beforeEach, describe, expect, it } from 'vitest';
2
+ import { FeedsClient } from '../feeds-client';
3
+ import { Feed } from './feed';
4
+ import { ActivityResponse } from '../gen/models';
5
+ import { generateActivityResponse, generateFeedResponse } from '../test-utils';
6
+
7
+ describe('Feed derived state updates', () => {
8
+ let feed: Feed;
9
+ let client: FeedsClient;
10
+ let activities: ActivityResponse[];
11
+
12
+ beforeEach(() => {
13
+ client = new FeedsClient('mock-api-key');
14
+ const feedResponse = generateFeedResponse({ id: 'main', group_id: 'user' });
15
+ feed = new Feed(
16
+ client,
17
+ feedResponse.group_id,
18
+ feedResponse.id,
19
+ feedResponse,
20
+ );
21
+ activities = [
22
+ generateActivityResponse(),
23
+ generateActivityResponse(),
24
+ generateActivityResponse(),
25
+ ];
26
+ });
27
+
28
+ it('should update the cache if activities change in feed.state', () => {
29
+ let indexedActivityIds = (feed as any).indexedActivityIds;
30
+ expect(indexedActivityIds.size).toEqual(0);
31
+
32
+ feed.state.partialNext({ activities });
33
+
34
+ indexedActivityIds = (feed as any).indexedActivityIds;
35
+ expect(indexedActivityIds.size).toEqual(3);
36
+ for (const activity of activities) {
37
+ expect(indexedActivityIds.has(activity.id)).toBe(true);
38
+ }
39
+ });
40
+
41
+ it('should update the cache if activities are further updated', () => {
42
+ // Include all of them
43
+ feed.state.partialNext({ activities });
44
+
45
+ let indexedActivityIds = (feed as any).indexedActivityIds;
46
+ expect(indexedActivityIds.size).toEqual(3);
47
+ for (const activity of activities) {
48
+ expect(indexedActivityIds.has(activity.id)).toBe(true);
49
+ }
50
+
51
+ // Take only the last 2
52
+ const newActivities = activities.slice(1);
53
+ feed.state.partialNext({ activities: newActivities });
54
+
55
+ indexedActivityIds = (feed as any).indexedActivityIds;
56
+ expect((feed as any).indexedActivityIds.size).toEqual(2);
57
+ for (const activity of newActivities) {
58
+ expect(indexedActivityIds.has(activity.id)).toBe(true);
59
+ }
60
+
61
+ // Include all of them again
62
+ feed.state.partialNext({ activities });
63
+
64
+ indexedActivityIds = (feed as any).indexedActivityIds;
65
+ expect(indexedActivityIds.size).toEqual(3);
66
+ for (const activity of activities) {
67
+ expect(indexedActivityIds.has(activity.id)).toBe(true);
68
+ }
69
+ });
70
+
71
+ it('should not update the cache if the length of activities has not changed', () => {
72
+ feed.state.partialNext({ activities });
73
+
74
+ const indexedActivityIdsBefore = (feed as any).indexedActivityIds;
75
+ expect(indexedActivityIdsBefore.size).toEqual(3);
76
+ for (const activity of activities) {
77
+ expect(indexedActivityIdsBefore.has(activity.id)).toBe(true);
78
+ }
79
+
80
+ const reversedActivities = activities.toReversed();
81
+ feed.state.partialNext({ activities: reversedActivities });
82
+
83
+ const indexedActivityIdsAfter = (feed as any).indexedActivityIds;
84
+ expect(indexedActivityIdsAfter.size).toEqual(3);
85
+ for (const activity of activities) {
86
+ expect(indexedActivityIdsAfter.has(activity.id)).toBe(true);
87
+ }
88
+ expect(indexedActivityIdsBefore).toBe(indexedActivityIdsAfter);
89
+ });
90
+ });
package/src/feed/feed.ts CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  QueryCommentsRequest,
16
16
  } from '../gen/models';
17
17
  import { StreamResponse } from '../gen-imports';
18
- import { StateStore } from '../common/StateStore';
18
+ import { StateStore } from '@stream-io/state-store';
19
19
  import { EventDispatcher } from '../common/EventDispatcher';
20
20
  import { FeedApi } from '../gen/feeds/FeedApi';
21
21
  import { FeedsClient } from '../feeds-client';
@@ -38,11 +38,11 @@ import {
38
38
  handleBookmarkAdded,
39
39
  handleActivityDeleted,
40
40
  handleActivityRemovedFromFeed,
41
- handleActivityReactionDeleted,
42
- handleActivityReactionAdded,
43
41
  handleFeedUpdated,
44
42
  handleNotificationFeedUpdated,
45
43
  handleActivityMarked,
44
+ handleActivityReactionAdded,
45
+ handleActivityReactionDeleted,
46
46
  } from './event-handlers';
47
47
  import { capitalize } from '../common/utils';
48
48
  import type {
@@ -139,6 +139,7 @@ type EventHandlerByEventType = {
139
139
  export class Feed extends FeedApi {
140
140
  readonly state: StateStore<FeedState>;
141
141
  private static readonly noop = () => {};
142
+ protected indexedActivityIds: Set<string> = new Set();
142
143
  protected readonly stateUpdateQueue: Set<string> = new Set();
143
144
 
144
145
  private readonly eventHandlers: EventHandlerByEventType = {
@@ -217,6 +218,19 @@ export class Feed extends FeedApi {
217
218
  watch,
218
219
  });
219
220
  this.client = client;
221
+
222
+ this.state.subscribeWithSelector(
223
+ (nextState) => ({ activities: nextState.activities }),
224
+ (nextState) => {
225
+ const { activities: nextActivities = [] } = nextState;
226
+
227
+ if (this.indexedActivityIds.size !== nextActivities?.length) {
228
+ this.indexedActivityIds = new Set(
229
+ nextActivities.map((activity) => activity.id),
230
+ );
231
+ }
232
+ },
233
+ );
220
234
  }
221
235
 
222
236
  protected readonly client: FeedsClient;
@@ -229,6 +243,10 @@ export class Feed extends FeedApi {
229
243
  return this.state.getLatestValue();
230
244
  }
231
245
 
246
+ hasActivity(activityId: string) {
247
+ return this.indexedActivityIds.has(activityId);
248
+ }
249
+
232
250
  async synchronize() {
233
251
  const { last_get_or_create_request_config } = this.state.getLatestValue();
234
252
  if (last_get_or_create_request_config?.watch) {
@@ -254,7 +272,7 @@ export class Feed extends FeedApi {
254
272
  if (request?.next) {
255
273
  const { activities: currentActivities = [] } = this.currentState;
256
274
 
257
- const result = addActivitiesToState(
275
+ const result = addActivitiesToState.bind(this)(
258
276
  response.activities,
259
277
  currentActivities,
260
278
  'end',
@@ -282,6 +300,9 @@ export class Feed extends FeedApi {
282
300
  delete responseCopy.metadata;
283
301
  delete responseCopy.duration;
284
302
 
303
+ // recreate the caches so that they are updated on the next state update
304
+ this.indexedActivityIds = new Set();
305
+
285
306
  // TODO: lazy-load comments from activities when comment_sort and comment_pagination are supported
286
307
 
287
308
  this.state.next((currentState) => {
@@ -1,6 +1,8 @@
1
1
  import { FeedsApi } from '../gen/feeds/FeedsApi';
2
2
  import {
3
3
  ActivityResponse,
4
+ AddReactionRequest,
5
+ DeleteActivityReactionResponse,
4
6
  FeedResponse,
5
7
  FileUploadRequest,
6
8
  FollowBatchRequest,
@@ -16,7 +18,7 @@ import {
16
18
  WSEvent,
17
19
  } from '../gen/models';
18
20
  import { FeedsEvent, StreamFile, TokenOrProvider } from '../types';
19
- import { StateStore } from '../common/StateStore';
21
+ import { StateStore } from '@stream-io/state-store';
20
22
  import { TokenManager } from '../common/TokenManager';
21
23
  import { ConnectionIdManager } from '../common/ConnectionIdManager';
22
24
  import { StableWSConnection } from '../common/real-time/StableWSConnection';
@@ -37,6 +39,8 @@ import { ModerationClient } from '../moderation-client';
37
39
  import { StreamPoll } from '../common/Poll';
38
40
  import {
39
41
  Feed,
42
+ handleActivityReactionAdded,
43
+ handleActivityReactionDeleted,
40
44
  handleFeedUpdated,
41
45
  handleFollowCreated,
42
46
  handleFollowDeleted,
@@ -49,6 +53,7 @@ import {
49
53
  SyncFailure,
50
54
  UnhandledErrorType,
51
55
  } from '../common/real-time/event-models';
56
+ import { configureLoggers } from '../utils/logger';
52
57
 
53
58
  export type FeedsClientState = {
54
59
  connected_user: OwnUser | undefined;
@@ -93,6 +98,9 @@ export class FeedsClient extends FeedsApi {
93
98
  this.tokenManager = tokenManager;
94
99
  this.connectionIdManager = connectionIdManager;
95
100
  this.polls_by_id = new Map();
101
+
102
+ configureLoggers(options?.configure_loggers_options);
103
+
96
104
  this.on('all', (event) => {
97
105
  const fid = event.fid;
98
106
 
@@ -323,6 +331,29 @@ export class FeedsClient extends FeedsApi {
323
331
  });
324
332
  };
325
333
 
334
+ addReaction = async (
335
+ request: AddReactionRequest & {
336
+ activity_id: string;
337
+ },
338
+ ) => {
339
+ const response = await super.addReaction(request);
340
+ for (const feed of Object.values(this.activeFeeds)) {
341
+ handleActivityReactionAdded.bind(feed)(response, false);
342
+ }
343
+ return response;
344
+ };
345
+
346
+ deleteActivityReaction = async (request: {
347
+ activity_id: string;
348
+ type: string;
349
+ }): Promise<StreamResponse<DeleteActivityReactionResponse>> => {
350
+ const response = await super.deleteActivityReaction(request);
351
+ for (const feed of Object.values(this.activeFeeds)) {
352
+ handleActivityReactionDeleted.bind(feed)(response, false);
353
+ }
354
+ return response;
355
+ };
356
+
326
357
  queryPollAnswers = async (
327
358
  request: QueryPollVotesRequest & { poll_id: string; user_id?: string },
328
359
  ): Promise<StreamResponse<PollVotesResponse>> => {
@@ -413,7 +444,7 @@ export class FeedsClient extends FeedsApi {
413
444
  ].forEach((fid) => {
414
445
  const feed = this.activeFeeds[fid];
415
446
  if (feed) {
416
- handleFollowUpdated.bind(feed)(response);
447
+ handleFollowUpdated.bind(feed)(response, false);
417
448
  }
418
449
  });
419
450
 
@@ -430,7 +461,7 @@ export class FeedsClient extends FeedsApi {
430
461
  ].forEach((fid) => {
431
462
  const feed = this.activeFeeds[fid];
432
463
  if (feed) {
433
- handleFollowCreated.bind(feed)(response);
464
+ handleFollowCreated.bind(feed)(response, false);
434
465
  }
435
466
  });
436
467
 
@@ -456,7 +487,7 @@ export class FeedsClient extends FeedsApi {
456
487
  [request.source, request.target].forEach((fid) => {
457
488
  const feed = this.activeFeeds[fid];
458
489
  if (feed) {
459
- handleFollowDeleted.bind(feed)(response);
490
+ handleFollowDeleted.bind(feed)(response, false);
460
491
  }
461
492
  });
462
493
 
@@ -580,6 +580,7 @@ export class FeedsApi {
580
580
  const body = {
581
581
  type: request?.type,
582
582
  create_notification_activity: request?.create_notification_activity,
583
+ enforce_unique: request?.enforce_unique,
583
584
  skip_push: request?.skip_push,
584
585
  custom: request?.custom,
585
586
  };
@@ -1037,6 +1038,7 @@ export class FeedsApi {
1037
1038
  const body = {
1038
1039
  type: request?.type,
1039
1040
  create_notification_activity: request?.create_notification_activity,
1041
+ enforce_unique: request?.enforce_unique,
1040
1042
  skip_push: request?.skip_push,
1041
1043
  custom: request?.custom,
1042
1044
  };
@@ -481,6 +481,8 @@ decoders.Channel = (input?: Record<string, any>) => {
481
481
 
482
482
  created_by: { type: 'User', isSingle: true },
483
483
 
484
+ members_lookup: { type: 'ChannelMemberLookup', isSingle: false },
485
+
484
486
  truncated_by: { type: 'User', isSingle: true },
485
487
  };
486
488
  return decode(typeMappings, input);
@@ -529,6 +531,17 @@ decoders.ChannelMember = (input?: Record<string, any>) => {
529
531
  return decode(typeMappings, input);
530
532
  };
531
533
 
534
+ decoders.ChannelMemberLookup = (input?: Record<string, any>) => {
535
+ const typeMappings: TypeMapping = {
536
+ archived_at: { type: 'DatetimeType', isSingle: true },
537
+
538
+ ban_expires: { type: 'DatetimeType', isSingle: true },
539
+
540
+ pinned_at: { type: 'DatetimeType', isSingle: true },
541
+ };
542
+ return decode(typeMappings, input);
543
+ };
544
+
532
545
  decoders.ChannelMute = (input?: Record<string, any>) => {
533
546
  const typeMappings: TypeMapping = {
534
547
  created_at: { type: 'DatetimeType', isSingle: true },
@@ -734,6 +747,15 @@ decoders.DeleteCommentReactionResponse = (input?: Record<string, any>) => {
734
747
  return decode(typeMappings, input);
735
748
  };
736
749
 
750
+ decoders.DeleteCommentResponse = (input?: Record<string, any>) => {
751
+ const typeMappings: TypeMapping = {
752
+ activity: { type: 'ActivityResponse', isSingle: true },
753
+
754
+ comment: { type: 'CommentResponse', isSingle: true },
755
+ };
756
+ return decode(typeMappings, input);
757
+ };
758
+
737
759
  decoders.Device = (input?: Record<string, any>) => {
738
760
  const typeMappings: TypeMapping = {
739
761
  created_at: { type: 'DatetimeType', isSingle: true },