@stream-io/feeds-client 0.1.9 → 0.1.11

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 (167) hide show
  1. package/@react-bindings/hooks/search-state-hooks/index.ts +3 -0
  2. package/@react-bindings/index.ts +5 -0
  3. package/CHANGELOG.md +20 -0
  4. package/dist/@react-bindings/contexts/StreamFeedContext.d.ts +1 -1
  5. package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +1 -1
  6. package/dist/@react-bindings/contexts/StreamSearchContext.d.ts +12 -0
  7. package/dist/@react-bindings/contexts/StreamSearchResultsContext.d.ts +12 -0
  8. package/dist/@react-bindings/hooks/feed-state-hooks/useComments.d.ts +1 -1
  9. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedActivities.d.ts +1 -1
  10. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedMetadata.d.ts +1 -1
  11. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowers.d.ts +1 -1
  12. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowing.d.ts +1 -1
  13. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnCapabilities.d.ts +1 -1
  14. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnFollows.d.ts +1 -1
  15. package/dist/@react-bindings/hooks/search-state-hooks/index.d.ts +3 -0
  16. package/dist/@react-bindings/hooks/search-state-hooks/useSearchQuery.d.ts +4 -0
  17. package/dist/@react-bindings/hooks/search-state-hooks/useSearchResult.d.ts +8 -0
  18. package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +4 -0
  19. package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +1 -1
  20. package/dist/@react-bindings/index.d.ts +5 -0
  21. package/dist/@react-bindings/wrappers/StreamFeed.d.ts +1 -1
  22. package/dist/@react-bindings/wrappers/StreamSearch.d.ts +12 -0
  23. package/dist/@react-bindings/wrappers/StreamSearchResults.d.ts +12 -0
  24. package/dist/index-react-bindings.browser.cjs +1669 -1529
  25. package/dist/index-react-bindings.browser.cjs.map +1 -1
  26. package/dist/index-react-bindings.browser.js +1661 -1530
  27. package/dist/index-react-bindings.browser.js.map +1 -1
  28. package/dist/index-react-bindings.node.cjs +1669 -1529
  29. package/dist/index-react-bindings.node.cjs.map +1 -1
  30. package/dist/index-react-bindings.node.js +1661 -1530
  31. package/dist/index-react-bindings.node.js.map +1 -1
  32. package/dist/index.browser.cjs +1615 -1640
  33. package/dist/index.browser.cjs.map +1 -1
  34. package/dist/index.browser.js +1613 -1641
  35. package/dist/index.browser.js.map +1 -1
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.node.cjs +1615 -1640
  38. package/dist/index.node.cjs.map +1 -1
  39. package/dist/index.node.js +1613 -1641
  40. package/dist/index.node.js.map +1 -1
  41. package/dist/src/common/ActivitySearchSource.d.ts +1 -1
  42. package/dist/src/common/BaseSearchSource.d.ts +3 -1
  43. package/dist/src/common/FeedSearchSource.d.ts +7 -3
  44. package/dist/src/common/Poll.d.ts +1 -1
  45. package/dist/src/common/SearchController.d.ts +2 -0
  46. package/dist/src/common/UserSearchSource.d.ts +1 -1
  47. package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
  48. package/dist/src/feed/event-handlers/activity/handle-activity-added.d.ts +7 -0
  49. package/dist/src/feed/event-handlers/activity/handle-activity-deleted.d.ts +8 -0
  50. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +8 -0
  51. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +8 -0
  52. package/dist/src/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts +3 -0
  53. package/dist/src/feed/event-handlers/activity/handle-activity-updated.d.ts +8 -0
  54. package/dist/src/feed/event-handlers/activity/index.d.ts +6 -0
  55. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +8 -0
  56. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +9 -0
  57. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +8 -0
  58. package/dist/src/feed/event-handlers/bookmark/index.d.ts +3 -0
  59. package/dist/src/feed/event-handlers/comment/handle-comment-added.d.ts +3 -0
  60. package/dist/src/feed/event-handlers/comment/handle-comment-deleted.d.ts +3 -0
  61. package/dist/src/feed/event-handlers/comment/handle-comment-reaction.d.ts +3 -0
  62. package/dist/src/feed/event-handlers/comment/handle-comment-updated.d.ts +3 -0
  63. package/dist/src/feed/event-handlers/comment/index.d.ts +4 -0
  64. package/dist/src/feed/event-handlers/feed/handle-feed-updated.d.ts +3 -0
  65. package/dist/src/feed/event-handlers/feed/index.d.ts +1 -0
  66. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +3 -0
  67. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +3 -0
  68. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +3 -0
  69. package/dist/src/feed/event-handlers/feed-member/index.d.ts +3 -0
  70. package/dist/src/feed/event-handlers/follow/handle-follow-created.d.ts +7 -0
  71. package/dist/src/feed/event-handlers/follow/handle-follow-deleted.d.ts +7 -0
  72. package/dist/src/feed/event-handlers/follow/handle-follow-updated.d.ts +3 -0
  73. package/dist/src/feed/event-handlers/follow/index.d.ts +3 -0
  74. package/dist/src/feed/event-handlers/index.d.ts +7 -0
  75. package/dist/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +3 -0
  76. package/dist/src/feed/event-handlers/notification-feed/index.d.ts +1 -0
  77. package/dist/src/{Feed.d.ts → feed/feed.d.ts} +15 -34
  78. package/dist/src/feed/index.d.ts +2 -0
  79. package/dist/src/{FeedsClient.d.ts → feeds-client.d.ts} +6 -5
  80. package/dist/src/gen/models/index.d.ts +5 -0
  81. package/dist/src/gen-imports.d.ts +1 -1
  82. package/dist/src/test-utils/index.d.ts +1 -0
  83. package/dist/src/test-utils/response-generators.d.ts +9 -0
  84. package/dist/src/types-internal.d.ts +7 -0
  85. package/dist/src/types.d.ts +1 -1
  86. package/dist/src/utils/check-has-another-page.d.ts +1 -0
  87. package/dist/src/utils/constants.d.ts +3 -0
  88. package/dist/src/utils/index.d.ts +5 -0
  89. package/dist/src/utils/state-update-queue.d.ts +6 -0
  90. package/dist/src/utils/type-assertions.d.ts +7 -0
  91. package/dist/src/utils/unique-array-merge.d.ts +1 -0
  92. package/dist/tsconfig.tsbuildinfo +1 -1
  93. package/index.ts +2 -2
  94. package/package.json +2 -1
  95. package/src/common/ActivitySearchSource.ts +6 -16
  96. package/src/common/BaseSearchSource.ts +9 -9
  97. package/src/common/FeedSearchSource.ts +22 -67
  98. package/src/common/Poll.ts +1 -1
  99. package/src/common/SearchController.ts +2 -0
  100. package/src/common/UserSearchSource.ts +10 -62
  101. package/src/{state-updates → feed/event-handlers/activity}/activity-reaction-utils.test.ts +12 -2
  102. package/src/{state-updates → feed/event-handlers/activity}/activity-utils.test.ts +3 -2
  103. package/src/{state-updates/activity-utils.ts → feed/event-handlers/activity/handle-activity-added.ts} +16 -36
  104. package/src/feed/event-handlers/activity/handle-activity-deleted.ts +30 -0
  105. package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +67 -0
  106. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +75 -0
  107. package/src/feed/event-handlers/activity/handle-activity-removed-from-feed.ts +16 -0
  108. package/src/feed/event-handlers/activity/handle-activity-updated.ts +47 -0
  109. package/src/feed/event-handlers/activity/index.ts +6 -0
  110. package/src/{state-updates → feed/event-handlers/bookmark}/bookmark-utils.test.ts +2 -2
  111. package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +63 -0
  112. package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +84 -0
  113. package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +76 -0
  114. package/src/feed/event-handlers/bookmark/index.ts +3 -0
  115. package/src/feed/event-handlers/comment/handle-comment-added.ts +38 -0
  116. package/src/feed/event-handlers/comment/handle-comment-deleted.ts +35 -0
  117. package/src/feed/event-handlers/comment/handle-comment-reaction.ts +61 -0
  118. package/src/feed/event-handlers/comment/handle-comment-updated.ts +35 -0
  119. package/src/feed/event-handlers/comment/index.ts +4 -0
  120. package/src/feed/event-handlers/feed/handle-feed-updated.ts +9 -0
  121. package/src/feed/event-handlers/feed/index.ts +1 -0
  122. package/src/feed/event-handlers/feed-member/handle-feed-member-added.ts +31 -0
  123. package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +24 -0
  124. package/src/feed/event-handlers/feed-member/handle-feed-member-updated.ts +40 -0
  125. package/src/feed/event-handlers/feed-member/index.ts +3 -0
  126. package/src/feed/event-handlers/follow/handle-follow-created.test.ts +246 -0
  127. package/src/feed/event-handlers/follow/handle-follow-created.ts +93 -0
  128. package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +264 -0
  129. package/src/feed/event-handlers/follow/handle-follow-deleted.ts +95 -0
  130. package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +174 -0
  131. package/src/feed/event-handlers/follow/handle-follow-updated.ts +88 -0
  132. package/src/feed/event-handlers/follow/index.ts +3 -0
  133. package/src/feed/event-handlers/index.ts +7 -0
  134. package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +10 -0
  135. package/src/feed/event-handlers/notification-feed/index.ts +1 -0
  136. package/src/{Feed.ts → feed/feed.ts} +72 -483
  137. package/src/feed/index.ts +2 -0
  138. package/src/{FeedsClient.ts → feeds-client.ts} +26 -8
  139. package/src/gen/model-decoders/decoders.ts +7 -0
  140. package/src/gen/models/index.ts +10 -0
  141. package/src/gen-imports.ts +1 -1
  142. package/src/test-utils/index.ts +1 -0
  143. package/src/test-utils/response-generators.ts +102 -0
  144. package/src/types-internal.ts +11 -0
  145. package/src/types.ts +1 -1
  146. package/src/utils/check-has-another-page.ts +6 -0
  147. package/src/utils/constants.ts +3 -0
  148. package/src/utils/index.ts +5 -0
  149. package/src/{state-updates → utils}/state-update-queue.test.ts +6 -6
  150. package/src/utils/state-update-queue.ts +42 -0
  151. package/src/utils/type-assertions.ts +22 -0
  152. package/src/{utils.test.ts → utils/unique-array-merge.test.ts} +7 -3
  153. package/src/utils/unique-array-merge.ts +19 -0
  154. package/dist/src/state-updates/activity-reaction-utils.d.ts +0 -10
  155. package/dist/src/state-updates/activity-utils.d.ts +0 -13
  156. package/dist/src/state-updates/bookmark-utils.d.ts +0 -14
  157. package/dist/src/state-updates/follow-utils.d.ts +0 -19
  158. package/dist/src/state-updates/state-update-queue.d.ts +0 -15
  159. package/dist/src/utils.d.ts +0 -10
  160. package/src/state-updates/activity-reaction-utils.ts +0 -107
  161. package/src/state-updates/bookmark-utils.ts +0 -167
  162. package/src/state-updates/follow-utils.test.ts +0 -552
  163. package/src/state-updates/follow-utils.ts +0 -126
  164. package/src/state-updates/state-update-queue.ts +0 -35
  165. package/src/utils.ts +0 -48
  166. /package/dist/src/{ModerationClient.d.ts → moderation-client.d.ts} +0 -0
  167. /package/src/{ModerationClient.ts → moderation-client.ts} +0 -0
@@ -9,54 +9,48 @@ import {
9
9
  CommentResponse,
10
10
  PagerResponse,
11
11
  SingleFollowRequest,
12
- CommentReactionAddedEvent,
13
- CommentReactionDeletedEvent,
14
- BookmarkAddedEvent,
15
- BookmarkDeletedEvent,
16
- BookmarkUpdatedEvent,
17
12
  QueryFeedMembersRequest,
18
13
  SortParamRequest,
19
- FollowResponse,
20
14
  ThreadedCommentResponse,
21
- } from './gen/models';
22
- import { StateStore } from './common/StateStore';
23
- import { EventDispatcher } from './common/EventDispatcher';
24
- import { FeedApi } from './gen/feeds/FeedApi';
25
- import { FeedsClient } from './FeedsClient';
26
- import {
27
- addActivitiesToState,
28
- updateActivityInState,
29
- removeActivityFromState,
30
- } from './state-updates/activity-utils';
31
- import {
32
- addReactionToActivities,
33
- removeReactionFromActivities,
34
- } from './state-updates/activity-reaction-utils';
35
- import {
36
- addBookmarkToActivities,
37
- removeBookmarkFromActivities,
38
- updateBookmarkInActivities,
39
- } from './state-updates/bookmark-utils';
15
+ } from '../gen/models';
16
+ import { StreamResponse } from '../gen-imports';
17
+ import { StateStore } from '../common/StateStore';
18
+ import { EventDispatcher } from '../common/EventDispatcher';
19
+ import { FeedApi } from '../gen/feeds/FeedApi';
20
+ import { FeedsClient } from '../feeds-client';
40
21
  import {
22
+ handleFollowUpdated,
41
23
  handleFollowCreated,
42
24
  handleFollowDeleted,
43
- handleFollowUpdated,
44
- } from './state-updates/follow-utils';
45
- import { StreamResponse } from './gen-imports';
46
- import { capitalize } from './common/utils';
25
+ handleCommentAdded,
26
+ handleCommentDeleted,
27
+ handleCommentUpdated,
28
+ handleBookmarkDeleted,
29
+ handleBookmarkUpdated,
30
+ handleActivityAdded,
31
+ addActivitiesToState,
32
+ handleActivityUpdated,
33
+ handleFeedMemberAdded,
34
+ handleFeedMemberRemoved,
35
+ handleFeedMemberUpdated,
36
+ handleCommentReaction,
37
+ handleBookmarkAdded,
38
+ handleActivityDeleted,
39
+ handleActivityRemovedFromFeed,
40
+ handleActivityReactionDeleted,
41
+ handleActivityReactionAdded,
42
+ handleFeedUpdated,
43
+ handleNotificationFeedUpdated,
44
+ } from './event-handlers';
45
+ import { capitalize } from '../common/utils';
47
46
  import type {
48
47
  ActivityIdOrCommentId,
49
48
  GetCommentsRepliesRequest,
50
49
  GetCommentsRequest,
51
50
  LoadingStates,
52
51
  PagerResponseWithLoadingStates,
53
- } from './types';
54
- import { checkHasAnotherPage, Constants, uniqueArrayMerge } from './utils';
55
- import {
56
- getStateUpdateQueueIdForFollow,
57
- getStateUpdateQueueIdForUnfollow,
58
- shouldUpdateState,
59
- } from './state-updates/state-update-queue';
52
+ } from '../types';
53
+ import { checkHasAnotherPage, Constants, uniqueArrayMerge } from '../utils';
60
54
 
61
55
  export type FeedState = Omit<
62
56
  Partial<GetOrCreateFeedResponse & FeedResponse>,
@@ -143,293 +137,40 @@ type EventHandlerByEventType = {
143
137
  export class Feed extends FeedApi {
144
138
  readonly state: StateStore<FeedState>;
145
139
  private static readonly noop = () => {};
146
- private readonly stateUpdateQueue: Set<string> = new Set();
140
+ protected readonly stateUpdateQueue: Set<string> = new Set();
147
141
 
148
142
  private readonly eventHandlers: EventHandlerByEventType = {
149
- 'feeds.activity.added': (event) => {
150
- const currentActivities = this.currentState.activities;
151
- const result = addActivitiesToState(
152
- [event.activity],
153
- currentActivities,
154
- 'start',
155
- );
156
- if (result.changed) {
157
- this.client.hydratePollCache([event.activity]);
158
- this.state.partialNext({ activities: result.activities });
159
- }
160
- },
161
- 'feeds.activity.deleted': (event) => {
162
- const currentActivities = this.currentState.activities;
163
- if (currentActivities) {
164
- const result = removeActivityFromState(
165
- event.activity,
166
- currentActivities,
167
- );
168
- if (result.changed) {
169
- this.state.partialNext({ activities: result.activities });
170
- }
171
- }
172
- },
173
- 'feeds.activity.reaction.added': (event) => {
174
- const currentActivities = this.currentState.activities;
175
- const connectedUser = this.client.state.getLatestValue().connected_user;
176
- const isCurrentUser = Boolean(
177
- connectedUser && event.reaction.user.id === connectedUser.id,
178
- );
179
-
180
- const result = addReactionToActivities(
181
- event,
182
- currentActivities,
183
- isCurrentUser,
184
- );
185
- if (result.changed) {
186
- this.state.partialNext({ activities: result.activities });
187
- }
188
- },
189
- 'feeds.activity.reaction.deleted': (event) => {
190
- const currentActivities = this.currentState.activities;
191
- const connectedUser = this.client.state.getLatestValue().connected_user;
192
- const isCurrentUser = Boolean(
193
- connectedUser && event.reaction.user.id === connectedUser.id,
194
- );
195
-
196
- const result = removeReactionFromActivities(
197
- event,
198
- currentActivities,
199
- isCurrentUser,
200
- );
201
- if (result.changed) {
202
- this.state.partialNext({ activities: result.activities });
203
- }
204
- },
143
+ 'feeds.activity.added': handleActivityAdded.bind(this),
144
+ 'feeds.activity.deleted': handleActivityDeleted.bind(this),
145
+ 'feeds.activity.reaction.added': handleActivityReactionAdded.bind(this),
146
+ 'feeds.activity.reaction.deleted': handleActivityReactionDeleted.bind(this),
205
147
  'feeds.activity.reaction.updated': Feed.noop,
206
- 'feeds.activity.removed_from_feed': (event) => {
207
- const currentActivities = this.currentState.activities;
208
- if (currentActivities) {
209
- const result = removeActivityFromState(
210
- event.activity,
211
- currentActivities,
212
- );
213
- if (result.changed) {
214
- this.state.partialNext({ activities: result.activities });
215
- }
216
- }
217
- },
218
- 'feeds.activity.updated': (event) => {
219
- const currentActivities = this.currentState.activities;
220
- if (currentActivities) {
221
- const result = updateActivityInState(event.activity, currentActivities);
222
- if (result.changed) {
223
- this.client.hydratePollCache([event.activity]);
224
- this.state.partialNext({ activities: result.activities });
225
- }
226
- }
227
- },
228
- 'feeds.bookmark.added': this.handleBookmarkAdded.bind(this),
229
- 'feeds.bookmark.deleted': this.handleBookmarkDeleted.bind(this),
230
- 'feeds.bookmark.updated': this.handleBookmarkUpdated.bind(this),
148
+ 'feeds.activity.removed_from_feed':
149
+ handleActivityRemovedFromFeed.bind(this),
150
+ 'feeds.activity.updated': handleActivityUpdated.bind(this),
151
+ 'feeds.bookmark.added': handleBookmarkAdded.bind(this),
152
+ 'feeds.bookmark.deleted': handleBookmarkDeleted.bind(this),
153
+ 'feeds.bookmark.updated': handleBookmarkUpdated.bind(this),
231
154
  'feeds.bookmark_folder.deleted': Feed.noop,
232
155
  'feeds.bookmark_folder.updated': Feed.noop,
233
- 'feeds.comment.added': (event) => {
234
- const { comment } = event;
235
- const forId = comment.parent_id ?? comment.object_id;
236
-
237
- this.state.next((currentState) => {
238
- const entityState = currentState.comments_by_entity_id[forId];
239
- const newComments = entityState?.comments?.concat([]) ?? [];
240
-
241
- if (
242
- entityState?.pagination?.sort === 'last' &&
243
- !checkHasAnotherPage(
244
- entityState.comments,
245
- entityState?.pagination.next,
246
- )
247
- ) {
248
- newComments.unshift(comment);
249
- } else if (entityState?.pagination?.sort === 'first') {
250
- newComments.push(comment);
251
- } else {
252
- // no other sorting option is supported yet
253
- return currentState;
254
- }
255
-
256
- return {
257
- ...currentState,
258
- comments_by_entity_id: {
259
- ...currentState.comments_by_entity_id,
260
- [forId]: {
261
- ...currentState.comments_by_entity_id[forId],
262
- comments: newComments,
263
- },
264
- },
265
- };
266
- });
267
- },
268
- 'feeds.comment.deleted': ({ comment }) => {
269
- const forId = comment.parent_id ?? comment.object_id;
270
-
271
- this.state.next((currentState) => {
272
- const newCommentsByEntityId = {
273
- ...currentState.comments_by_entity_id,
274
- [forId]: {
275
- ...currentState.comments_by_entity_id[forId],
276
- },
277
- };
278
-
279
- const index = this.getCommentIndex(comment, currentState);
280
-
281
- if (newCommentsByEntityId?.[forId]?.comments?.length && index !== -1) {
282
- newCommentsByEntityId[forId].comments = [
283
- ...newCommentsByEntityId[forId].comments,
284
- ];
285
-
286
- newCommentsByEntityId[forId]?.comments?.splice(index, 1);
287
- }
288
-
289
- delete newCommentsByEntityId[comment.id];
290
-
291
- return {
292
- ...currentState,
293
- comments_by_entity_id: newCommentsByEntityId,
294
- };
295
- });
296
- },
297
- 'feeds.comment.updated': (event) => {
298
- const { comment } = event;
299
- const forId = comment.parent_id ?? comment.object_id;
300
-
301
- this.state.next((currentState) => {
302
- const entityState = currentState.comments_by_entity_id[forId];
303
-
304
- if (!entityState?.comments?.length) return currentState;
305
-
306
- const index = this.getCommentIndex(comment, currentState);
307
-
308
- if (index === -1) return currentState;
309
-
310
- const newComments = [...entityState.comments];
311
-
312
- newComments[index] = comment;
313
-
314
- return {
315
- ...currentState,
316
- comments_by_entity_id: {
317
- ...currentState.comments_by_entity_id,
318
- [forId]: {
319
- ...currentState.comments_by_entity_id[forId],
320
- comments: newComments,
321
- },
322
- },
323
- };
324
- });
325
- },
156
+ 'feeds.comment.added': handleCommentAdded.bind(this),
157
+ 'feeds.comment.deleted': handleCommentDeleted.bind(this),
158
+ 'feeds.comment.updated': handleCommentUpdated.bind(this),
326
159
  'feeds.feed.created': Feed.noop,
327
160
  'feeds.feed.deleted': Feed.noop,
328
- 'feeds.feed.updated': (event) => {
329
- this.state.partialNext({ ...event.feed });
330
- },
161
+ 'feeds.feed.updated': handleFeedUpdated.bind(this),
331
162
  'feeds.feed_group.changed': Feed.noop,
332
163
  'feeds.feed_group.deleted': Feed.noop,
333
- 'feeds.follow.created': (event) => {
334
- this.handleFollowCreated(event.follow);
335
- },
336
- 'feeds.follow.deleted': (event) => {
337
- this.handleFollowDeleted(event.follow);
338
- },
339
- 'feeds.follow.updated': (_event) => {
340
- const result = handleFollowUpdated(this.currentState);
341
- if (result.changed) {
342
- this.state.next(result.data);
343
- }
344
- },
345
- 'feeds.comment.reaction.added': this.handleCommentReactionEvent.bind(this),
346
- 'feeds.comment.reaction.deleted':
347
- this.handleCommentReactionEvent.bind(this),
164
+ 'feeds.follow.created': handleFollowCreated.bind(this),
165
+ 'feeds.follow.deleted': handleFollowDeleted.bind(this),
166
+ 'feeds.follow.updated': handleFollowUpdated.bind(this),
167
+ 'feeds.comment.reaction.added': handleCommentReaction.bind(this),
168
+ 'feeds.comment.reaction.deleted': handleCommentReaction.bind(this),
348
169
  'feeds.comment.reaction.updated': Feed.noop,
349
- 'feeds.feed_member.added': (event) => {
350
- const { connected_user: connectedUser } =
351
- this.client.state.getLatestValue();
352
-
353
- this.state.next((currentState) => {
354
- let newState: FeedState | undefined;
355
-
356
- if (typeof currentState.members !== 'undefined') {
357
- newState ??= {
358
- ...currentState,
359
- };
360
-
361
- newState.members = [event.member, ...currentState.members];
362
- }
363
-
364
- if (connectedUser?.id === event.member.user.id) {
365
- newState ??= {
366
- ...currentState,
367
- };
368
-
369
- newState.own_membership = event.member;
370
- }
371
-
372
- return newState ?? currentState;
373
- });
374
- },
375
- 'feeds.feed_member.removed': (event) => {
376
- const { connected_user: connectedUser } =
377
- this.client.state.getLatestValue();
378
-
379
- this.state.next((currentState) => {
380
- const newState = {
381
- ...currentState,
382
- members: currentState.members?.filter(
383
- (member) => member.user.id !== event.user?.id,
384
- ),
385
- };
386
-
387
- if (connectedUser?.id === event.member_id) {
388
- delete newState.own_membership;
389
- }
390
-
391
- return newState;
392
- });
393
- },
394
- 'feeds.feed_member.updated': (event) => {
395
- const { connected_user: connectedUser } =
396
- this.client.state.getLatestValue();
397
-
398
- this.state.next((currentState) => {
399
- const memberIndex =
400
- currentState.members?.findIndex(
401
- (member) => member.user.id === event.member.user.id,
402
- ) ?? -1;
403
-
404
- let newState: FeedState | undefined;
405
-
406
- if (memberIndex !== -1) {
407
- // if there's an index, there's a member to update
408
- const newMembers = [...currentState.members!];
409
- newMembers[memberIndex] = event.member;
410
-
411
- newState ??= {
412
- ...currentState,
413
- };
414
-
415
- newState.members = newMembers;
416
- }
417
-
418
- if (connectedUser?.id === event.member.user.id) {
419
- newState ??= {
420
- ...currentState,
421
- };
422
-
423
- newState.own_membership = event.member;
424
- }
425
-
426
- return newState ?? currentState;
427
- });
428
- },
429
- 'feeds.notification_feed.updated': (event) => {
430
- console.info('notification feed updated', event);
431
- // TODO: handle notification feed updates
432
- },
170
+ 'feeds.feed_member.added': handleFeedMemberAdded.bind(this),
171
+ 'feeds.feed_member.removed': handleFeedMemberRemoved.bind(this),
172
+ 'feeds.feed_member.updated': handleFeedMemberUpdated.bind(this),
173
+ 'feeds.notification_feed.updated': handleNotificationFeedUpdated.bind(this),
433
174
  // the poll events should be removed from here
434
175
  'feeds.poll.closed': Feed.noop,
435
176
  'feeds.poll.deleted': Feed.noop,
@@ -476,7 +217,7 @@ export class Feed extends FeedApi {
476
217
  this.client = client;
477
218
  }
478
219
 
479
- private readonly client: FeedsClient;
220
+ protected readonly client: FeedsClient;
480
221
 
481
222
  get fid() {
482
223
  return `${this.group}:${this.id}`;
@@ -486,63 +227,6 @@ export class Feed extends FeedApi {
486
227
  return this.state.getLatestValue();
487
228
  }
488
229
 
489
- private handleCommentReactionEvent(
490
- event: (CommentReactionAddedEvent | CommentReactionDeletedEvent) & {
491
- type: 'feeds.comment.reaction.added' | 'feeds.comment.reaction.deleted';
492
- },
493
- ) {
494
- const { comment, reaction } = event;
495
- const connectedUser = this.client.state.getLatestValue().connected_user;
496
-
497
- this.state.next((currentState) => {
498
- const forId = comment.parent_id ?? comment.object_id;
499
- const entityState = currentState.comments_by_entity_id[forId];
500
-
501
- const commentIndex = this.getCommentIndex(comment, currentState);
502
-
503
- if (commentIndex === -1) return currentState;
504
-
505
- const newComments = entityState?.comments?.concat([]) ?? [];
506
-
507
- const commentCopy: Partial<CommentResponse> = { ...comment };
508
-
509
- delete commentCopy.own_reactions;
510
-
511
- const newComment: CommentResponse = {
512
- ...newComments[commentIndex],
513
- ...commentCopy,
514
- // TODO: FIXME this should be handled by the backend
515
- latest_reactions: commentCopy.latest_reactions ?? [],
516
- reaction_groups: commentCopy.reaction_groups ?? {},
517
- };
518
-
519
- newComments[commentIndex] = newComment;
520
-
521
- if (reaction.user.id === connectedUser?.id) {
522
- if (event.type === 'feeds.comment.reaction.added') {
523
- newComment.own_reactions = newComment.own_reactions.concat(
524
- reaction,
525
- ) ?? [reaction];
526
- } else if (event.type === 'feeds.comment.reaction.deleted') {
527
- newComment.own_reactions = newComment.own_reactions.filter(
528
- (r) => r.type !== reaction.type,
529
- );
530
- }
531
- }
532
-
533
- return {
534
- ...currentState,
535
- comments_by_entity_id: {
536
- ...currentState.comments_by_entity_id,
537
- [forId]: {
538
- ...entityState,
539
- comments: newComments,
540
- },
541
- },
542
- };
543
- });
544
- }
545
-
546
230
  async synchronize() {
547
231
  const { last_get_or_create_request_config } = this.state.getLatestValue();
548
232
  if (last_get_or_create_request_config?.watch) {
@@ -596,6 +280,8 @@ export class Feed extends FeedApi {
596
280
  delete responseCopy.metadata;
597
281
  delete responseCopy.duration;
598
282
 
283
+ // TODO: lazy-load comments from activities when comment_sort and comment_pagination are supported
284
+
599
285
  this.state.next((currentState) => {
600
286
  const nextState: FeedState = {
601
287
  ...currentState,
@@ -630,62 +316,6 @@ export class Feed extends FeedApi {
630
316
  }
631
317
  }
632
318
 
633
- /**
634
- * @internal
635
- */
636
- handleFollowCreated(follow: FollowResponse) {
637
- if (
638
- !shouldUpdateState({
639
- stateUpdateId: getStateUpdateQueueIdForFollow(follow),
640
- stateUpdateQueue: this.stateUpdateQueue,
641
- watch: this.currentState.watch,
642
- })
643
- ) {
644
- return;
645
- }
646
- const connectedUser = this.client.state.getLatestValue().connected_user;
647
- const result = handleFollowCreated(
648
- follow,
649
- this.currentState,
650
- this.fid,
651
- connectedUser?.id,
652
- );
653
- if (result.changed) {
654
- this.state.next(result.data);
655
- }
656
- }
657
-
658
- /**
659
- * @internal
660
- */
661
- handleFollowDeleted(
662
- follow:
663
- | FollowResponse
664
- // Backend doesn't return the follow in delete follow response https://getstream.slack.com/archives/C06RK9WCR09/p1753176937507209
665
- | { source_feed: { fid: string }; target_feed: { fid: string } },
666
- ) {
667
- if (
668
- !shouldUpdateState({
669
- stateUpdateId: getStateUpdateQueueIdForUnfollow(follow),
670
- stateUpdateQueue: this.stateUpdateQueue,
671
- watch: this.currentState.watch,
672
- })
673
- ) {
674
- return;
675
- }
676
-
677
- const connectedUser = this.client.state.getLatestValue().connected_user;
678
- const result = handleFollowDeleted(
679
- follow,
680
- this.currentState,
681
- this.fid,
682
- connectedUser?.id,
683
- );
684
- if (result.changed) {
685
- this.state.next(result.data);
686
- }
687
- }
688
-
689
319
  /**
690
320
  * @internal
691
321
  */
@@ -704,58 +334,10 @@ export class Feed extends FeedApi {
704
334
  });
705
335
  }
706
336
 
707
- private handleBookmarkAdded(event: BookmarkAddedEvent) {
708
- const currentActivities = this.currentState.activities;
709
- const { connected_user: connectedUser } =
710
- this.client.state.getLatestValue();
711
- const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
712
-
713
- const result = addBookmarkToActivities(
714
- event,
715
- currentActivities,
716
- isCurrentUser,
717
- );
718
- if (result.changed) {
719
- this.state.partialNext({ activities: result.activities });
720
- }
721
- }
722
-
723
- private handleBookmarkDeleted(event: BookmarkDeletedEvent) {
724
- const currentActivities = this.currentState.activities;
725
- const { connected_user: connectedUser } =
726
- this.client.state.getLatestValue();
727
- const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
728
-
729
- const result = removeBookmarkFromActivities(
730
- event,
731
- currentActivities,
732
- isCurrentUser,
733
- );
734
- if (result.changed) {
735
- this.state.partialNext({ activities: result.activities });
736
- }
737
- }
738
-
739
- private handleBookmarkUpdated(event: BookmarkUpdatedEvent) {
740
- const currentActivities = this.currentState.activities;
741
- const { connected_user: connectedUser } =
742
- this.client.state.getLatestValue();
743
- const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
744
-
745
- const result = updateBookmarkInActivities(
746
- event,
747
- currentActivities,
748
- isCurrentUser,
749
- );
750
- if (result.changed) {
751
- this.state.partialNext({ activities: result.activities });
752
- }
753
- }
754
-
755
337
  /**
756
338
  * Returns index of the provided comment object.
757
339
  */
758
- private getCommentIndex(
340
+ protected getCommentIndex(
759
341
  comment: Pick<CommentResponse, 'object_id' | 'parent_id' | 'id'>,
760
342
  state?: FeedState,
761
343
  ) {
@@ -833,6 +415,8 @@ export class Feed extends FeedApi {
833
415
  restOfTheCommentResponse,
834
416
  );
835
417
 
418
+ const existingComments = newCommentsByEntityId[entityId]?.comments;
419
+
836
420
  newCommentsByEntityId[entityId] = {
837
421
  ...newCommentsByEntityId[entityId],
838
422
  entity_parent_id: item.entityParentId,
@@ -841,8 +425,12 @@ export class Feed extends FeedApi {
841
425
  next: item.next,
842
426
  sort: data.sort,
843
427
  },
844
- comments: newCommentsByEntityId[entityId]?.comments
845
- ? newCommentsByEntityId[entityId].comments?.concat(newComments)
428
+ comments: existingComments
429
+ ? uniqueArrayMerge(
430
+ existingComments,
431
+ newComments,
432
+ (comment) => comment.id,
433
+ )
846
434
  : newComments,
847
435
  };
848
436
  }
@@ -983,10 +571,7 @@ export class Feed extends FeedApi {
983
571
  ...request,
984
572
  comment_id: comment.id,
985
573
  // use known sort first (prevents broken pagination)
986
- sort:
987
- currentSort ??
988
- request?.sort ??
989
- Constants.DEFAULT_COMMENT_PAGINATION,
574
+ sort,
990
575
  next: currentNextCursor,
991
576
  }),
992
577
  entityParentId: comment.parent_id ?? comment.object_id,
@@ -1112,7 +697,11 @@ export class Feed extends FeedApi {
1112
697
  this.state.next((currentState) => ({
1113
698
  ...currentState,
1114
699
  members: currentState.members
1115
- ? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
700
+ ? uniqueArrayMerge(
701
+ currentState.members,
702
+ members,
703
+ ({ user }) => user.id,
704
+ )
1116
705
  : members,
1117
706
  member_pagination: {
1118
707
  ...currentState.member_pagination,
@@ -0,0 +1,2 @@
1
+ export * from './feed';
2
+ export * from './event-handlers';