@stream-io/feeds-client 0.1.10 → 0.2.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 (168) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/@react-bindings/contexts/StreamFeedContext.d.ts +1 -1
  3. package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +1 -1
  4. package/dist/@react-bindings/hooks/feed-state-hooks/useComments.d.ts +1 -1
  5. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedActivities.d.ts +1 -1
  6. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedMetadata.d.ts +1 -1
  7. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowers.d.ts +1 -1
  8. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowing.d.ts +1 -1
  9. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnCapabilities.d.ts +1 -1
  10. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnFollows.d.ts +1 -1
  11. package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +1 -1
  12. package/dist/@react-bindings/wrappers/StreamFeed.d.ts +1 -1
  13. package/dist/index-react-bindings.browser.cjs +1720 -1601
  14. package/dist/index-react-bindings.browser.cjs.map +1 -1
  15. package/dist/index-react-bindings.browser.js +1720 -1601
  16. package/dist/index-react-bindings.browser.js.map +1 -1
  17. package/dist/index-react-bindings.node.cjs +1720 -1601
  18. package/dist/index-react-bindings.node.cjs.map +1 -1
  19. package/dist/index-react-bindings.node.js +1720 -1601
  20. package/dist/index-react-bindings.node.js.map +1 -1
  21. package/dist/index.browser.cjs +1724 -1602
  22. package/dist/index.browser.cjs.map +1 -1
  23. package/dist/index.browser.js +1722 -1603
  24. package/dist/index.browser.js.map +1 -1
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.node.cjs +1724 -1602
  27. package/dist/index.node.cjs.map +1 -1
  28. package/dist/index.node.js +1722 -1603
  29. package/dist/index.node.js.map +1 -1
  30. package/dist/src/common/ActivitySearchSource.d.ts +1 -1
  31. package/dist/src/common/FeedSearchSource.d.ts +2 -2
  32. package/dist/src/common/Poll.d.ts +1 -1
  33. package/dist/src/common/UserSearchSource.d.ts +1 -1
  34. package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
  35. package/dist/src/feed/event-handlers/activity/handle-activity-added.d.ts +7 -0
  36. package/dist/src/feed/event-handlers/activity/handle-activity-deleted.d.ts +8 -0
  37. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +8 -0
  38. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +8 -0
  39. package/dist/src/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts +3 -0
  40. package/dist/src/feed/event-handlers/activity/handle-activity-updated.d.ts +8 -0
  41. package/dist/src/feed/event-handlers/activity/index.d.ts +6 -0
  42. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +8 -0
  43. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +9 -0
  44. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +8 -0
  45. package/dist/src/feed/event-handlers/bookmark/index.d.ts +3 -0
  46. package/dist/src/feed/event-handlers/comment/handle-comment-added.d.ts +3 -0
  47. package/dist/src/feed/event-handlers/comment/handle-comment-deleted.d.ts +3 -0
  48. package/dist/src/feed/event-handlers/comment/handle-comment-reaction.d.ts +3 -0
  49. package/dist/src/feed/event-handlers/comment/handle-comment-updated.d.ts +3 -0
  50. package/dist/src/feed/event-handlers/comment/index.d.ts +4 -0
  51. package/dist/src/feed/event-handlers/feed/handle-feed-updated.d.ts +3 -0
  52. package/dist/src/feed/event-handlers/feed/index.d.ts +1 -0
  53. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +3 -0
  54. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +3 -0
  55. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +3 -0
  56. package/dist/src/feed/event-handlers/feed-member/index.d.ts +3 -0
  57. package/dist/src/feed/event-handlers/follow/handle-follow-created.d.ts +7 -0
  58. package/dist/src/feed/event-handlers/follow/handle-follow-deleted.d.ts +7 -0
  59. package/dist/src/feed/event-handlers/follow/handle-follow-updated.d.ts +3 -0
  60. package/dist/src/feed/event-handlers/follow/index.d.ts +3 -0
  61. package/dist/src/feed/event-handlers/index.d.ts +8 -0
  62. package/dist/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +3 -0
  63. package/dist/src/feed/event-handlers/notification-feed/index.d.ts +1 -0
  64. package/dist/src/feed/event-handlers/watch/handle-watch-started.d.ts +2 -0
  65. package/dist/src/feed/event-handlers/watch/handle-watch-stopped.d.ts +2 -0
  66. package/dist/src/feed/event-handlers/watch/index.d.ts +2 -0
  67. package/dist/src/{Feed.d.ts → feed/feed.d.ts} +16 -43
  68. package/dist/src/feed/index.d.ts +2 -0
  69. package/dist/src/feeds-client/event-handlers/index.d.ts +1 -0
  70. package/dist/src/feeds-client/event-handlers/user/handle-user-updated.d.ts +3 -0
  71. package/dist/src/feeds-client/feeds-client.d.ts +76 -0
  72. package/dist/src/feeds-client/index.d.ts +2 -0
  73. package/dist/src/gen/feeds/FeedsApi.d.ts +27 -23
  74. package/dist/src/gen/models/index.d.ts +168 -23
  75. package/dist/src/gen-imports.d.ts +1 -1
  76. package/dist/src/test-utils/index.d.ts +1 -0
  77. package/dist/src/test-utils/response-generators.d.ts +9 -0
  78. package/dist/src/types-internal.d.ts +7 -0
  79. package/dist/src/types.d.ts +1 -1
  80. package/dist/src/utils/check-has-another-page.d.ts +1 -0
  81. package/dist/src/utils/constants.d.ts +3 -0
  82. package/dist/src/utils/index.d.ts +5 -0
  83. package/dist/src/utils/state-update-queue.d.ts +6 -0
  84. package/dist/src/utils/type-assertions.d.ts +7 -0
  85. package/dist/src/utils/unique-array-merge.d.ts +1 -0
  86. package/dist/tsconfig.tsbuildinfo +1 -1
  87. package/index.ts +2 -2
  88. package/package.json +3 -2
  89. package/src/common/ActivitySearchSource.ts +1 -1
  90. package/src/common/FeedSearchSource.ts +2 -2
  91. package/src/common/Poll.ts +1 -1
  92. package/src/common/UserSearchSource.ts +1 -1
  93. package/src/{state-updates → feed/event-handlers/activity}/activity-reaction-utils.test.ts +12 -2
  94. package/src/{state-updates → feed/event-handlers/activity}/activity-utils.test.ts +3 -2
  95. package/src/{state-updates/activity-utils.ts → feed/event-handlers/activity/handle-activity-added.ts} +16 -36
  96. package/src/feed/event-handlers/activity/handle-activity-deleted.ts +30 -0
  97. package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +67 -0
  98. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +75 -0
  99. package/src/feed/event-handlers/activity/handle-activity-removed-from-feed.ts +16 -0
  100. package/src/feed/event-handlers/activity/handle-activity-updated.ts +47 -0
  101. package/src/feed/event-handlers/activity/index.ts +6 -0
  102. package/src/{state-updates → feed/event-handlers/bookmark}/bookmark-utils.test.ts +2 -2
  103. package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +63 -0
  104. package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +84 -0
  105. package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +76 -0
  106. package/src/feed/event-handlers/bookmark/index.ts +3 -0
  107. package/src/feed/event-handlers/comment/handle-comment-added.ts +38 -0
  108. package/src/feed/event-handlers/comment/handle-comment-deleted.ts +35 -0
  109. package/src/feed/event-handlers/comment/handle-comment-reaction.ts +61 -0
  110. package/src/feed/event-handlers/comment/handle-comment-updated.ts +35 -0
  111. package/src/feed/event-handlers/comment/index.ts +4 -0
  112. package/src/feed/event-handlers/feed/handle-feed-updated.ts +9 -0
  113. package/src/feed/event-handlers/feed/index.ts +1 -0
  114. package/src/feed/event-handlers/feed-member/handle-feed-member-added.ts +31 -0
  115. package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +24 -0
  116. package/src/feed/event-handlers/feed-member/handle-feed-member-updated.ts +40 -0
  117. package/src/feed/event-handlers/feed-member/index.ts +3 -0
  118. package/src/feed/event-handlers/follow/handle-follow-created.test.ts +250 -0
  119. package/src/feed/event-handlers/follow/handle-follow-created.ts +90 -0
  120. package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +268 -0
  121. package/src/feed/event-handlers/follow/handle-follow-deleted.ts +95 -0
  122. package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +174 -0
  123. package/src/feed/event-handlers/follow/handle-follow-updated.ts +85 -0
  124. package/src/feed/event-handlers/follow/index.ts +3 -0
  125. package/src/feed/event-handlers/index.ts +8 -0
  126. package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +10 -0
  127. package/src/feed/event-handlers/notification-feed/index.ts +1 -0
  128. package/src/feed/event-handlers/watch/handle-watch-started.ts +5 -0
  129. package/src/feed/event-handlers/watch/handle-watch-stopped.ts +5 -0
  130. package/src/feed/event-handlers/watch/index.ts +2 -0
  131. package/src/{Feed.ts → feed/feed.ts} +87 -516
  132. package/src/feed/index.ts +2 -0
  133. package/src/feeds-client/event-handlers/index.ts +1 -0
  134. package/src/feeds-client/event-handlers/user/handle-user-updated.test.ts +53 -0
  135. package/src/feeds-client/event-handlers/user/handle-user-updated.ts +28 -0
  136. package/src/{FeedsClient.ts → feeds-client/feeds-client.ts} +63 -36
  137. package/src/feeds-client/index.ts +2 -0
  138. package/src/gen/feeds/FeedsApi.ts +164 -138
  139. package/src/gen/model-decoders/decoders.ts +22 -0
  140. package/src/gen/models/index.ts +288 -29
  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 +101 -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/FeedsClient.d.ts +0 -75
  155. package/dist/src/state-updates/activity-reaction-utils.d.ts +0 -10
  156. package/dist/src/state-updates/activity-utils.d.ts +0 -13
  157. package/dist/src/state-updates/bookmark-utils.d.ts +0 -14
  158. package/dist/src/state-updates/follow-utils.d.ts +0 -19
  159. package/dist/src/state-updates/state-update-queue.d.ts +0 -15
  160. package/dist/src/utils.d.ts +0 -10
  161. package/src/state-updates/activity-reaction-utils.ts +0 -107
  162. package/src/state-updates/bookmark-utils.ts +0 -167
  163. package/src/state-updates/follow-utils.test.ts +0 -552
  164. package/src/state-updates/follow-utils.ts +0 -126
  165. package/src/state-updates/state-update-queue.ts +0 -35
  166. package/src/utils.ts +0 -48
  167. /package/dist/src/{ModerationClient.d.ts → moderation-client.d.ts} +0 -0
  168. /package/src/{ModerationClient.ts → moderation-client.ts} +0 -0
@@ -8,55 +8,49 @@ import {
8
8
  ActivityResponse,
9
9
  CommentResponse,
10
10
  PagerResponse,
11
- SingleFollowRequest,
12
- CommentReactionAddedEvent,
13
- CommentReactionDeletedEvent,
14
- BookmarkAddedEvent,
15
- BookmarkDeletedEvent,
16
- BookmarkUpdatedEvent,
17
11
  QueryFeedMembersRequest,
18
12
  SortParamRequest,
19
- FollowResponse,
20
13
  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';
14
+ FollowRequest,
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,
@@ -464,7 +205,7 @@ export class Feed extends FeedApi {
464
205
  ) {
465
206
  super(client, groupId, id);
466
207
  this.state = new StateStore<FeedState>({
467
- fid: `${groupId}:${id}`,
208
+ feed: `${groupId}:${id}`,
468
209
  group_id: groupId,
469
210
  id,
470
211
  ...(data ?? {}),
@@ -476,9 +217,9 @@ 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
- get fid() {
222
+ get feed() {
482
223
  return `${this.group}:${this.id}`;
483
224
  }
484
225
 
@@ -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) {
@@ -586,7 +270,7 @@ export class Feed extends FeedApi {
586
270
  this.stateUpdateQueue.clear();
587
271
  const responseCopy: Partial<
588
272
  StreamResponse<GetOrCreateFeedResponse>['feed'] &
589
- StreamResponse<GetOrCreateFeedResponse>
273
+ StreamResponse<Omit<GetOrCreateFeedResponse, 'feed'>>
590
274
  > = {
591
275
  ...response,
592
276
  ...response.feed,
@@ -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,132 +316,10 @@ 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
- /**
690
- * @internal
691
- */
692
- handleWatchStopped() {
693
- this.state.partialNext({
694
- watch: false,
695
- });
696
- }
697
-
698
- /**
699
- * @internal
700
- */
701
- handleWatchStarted() {
702
- this.state.partialNext({
703
- watch: true,
704
- });
705
- }
706
-
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
319
  /**
756
320
  * Returns index of the provided comment object.
757
321
  */
758
- private getCommentIndex(
322
+ protected getCommentIndex(
759
323
  comment: Pick<CommentResponse, 'object_id' | 'parent_id' | 'id'>,
760
324
  state?: FeedState,
761
325
  ) {
@@ -833,6 +397,8 @@ export class Feed extends FeedApi {
833
397
  restOfTheCommentResponse,
834
398
  );
835
399
 
400
+ const existingComments = newCommentsByEntityId[entityId]?.comments;
401
+
836
402
  newCommentsByEntityId[entityId] = {
837
403
  ...newCommentsByEntityId[entityId],
838
404
  entity_parent_id: item.entityParentId,
@@ -841,8 +407,12 @@ export class Feed extends FeedApi {
841
407
  next: item.next,
842
408
  sort: data.sort,
843
409
  },
844
- comments: newCommentsByEntityId[entityId]?.comments
845
- ? newCommentsByEntityId[entityId].comments?.concat(newComments)
410
+ comments: existingComments
411
+ ? uniqueArrayMerge(
412
+ existingComments,
413
+ newComments,
414
+ (comment) => comment.id,
415
+ )
846
416
  : newComments,
847
417
  };
848
418
  }
@@ -981,12 +551,9 @@ export class Feed extends FeedApi {
981
551
  base: () =>
982
552
  this.client.getCommentReplies({
983
553
  ...request,
984
- comment_id: comment.id,
554
+ id: comment.id,
985
555
  // use known sort first (prevents broken pagination)
986
- sort:
987
- currentSort ??
988
- request?.sort ??
989
- Constants.DEFAULT_COMMENT_PAGINATION,
556
+ sort,
990
557
  next: currentNextCursor,
991
558
  }),
992
559
  entityParentId: comment.parent_id ?? comment.object_id,
@@ -1038,7 +605,7 @@ export class Feed extends FeedApi {
1038
605
  currentState[type],
1039
606
  follows,
1040
607
  (follow) =>
1041
- `${follow.source_feed.fid}-${follow.target_feed.fid}`,
608
+ `${follow.source_feed.feed}-${follow.target_feed.feed}`,
1042
609
  ),
1043
610
  [paginationKey]: {
1044
611
  ...currentState[paginationKey],
@@ -1112,7 +679,11 @@ export class Feed extends FeedApi {
1112
679
  this.state.next((currentState) => ({
1113
680
  ...currentState,
1114
681
  members: currentState.members
1115
- ? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
682
+ ? uniqueArrayMerge(
683
+ currentState.members,
684
+ members,
685
+ ({ user }) => user.id,
686
+ )
1116
687
  : members,
1117
688
  member_pagination: {
1118
689
  ...currentState.member_pagination,
@@ -1145,7 +716,7 @@ export class Feed extends FeedApi {
1145
716
  */
1146
717
  async queryFollowers(request: Omit<QueryFollowsRequest, 'filter'>) {
1147
718
  const filter: QueryFollowsRequest['filter'] = {
1148
- target_feed: this.fid,
719
+ target_feed: this.feed,
1149
720
  };
1150
721
 
1151
722
  const response = await this.client.queryFollows({
@@ -1163,7 +734,7 @@ export class Feed extends FeedApi {
1163
734
  */
1164
735
  async queryFollowing(request: Omit<QueryFollowsRequest, 'filter'>) {
1165
736
  const filter: QueryFollowsRequest['filter'] = {
1166
- source_feed: this.fid,
737
+ source_feed: this.feed,
1167
738
  };
1168
739
 
1169
740
  const response = await this.client.queryFollows({
@@ -1176,13 +747,13 @@ export class Feed extends FeedApi {
1176
747
 
1177
748
  async follow(
1178
749
  feedOrFid: Feed | string,
1179
- options?: Omit<SingleFollowRequest, 'source' | 'target'>,
750
+ options?: Omit<FollowRequest, 'source' | 'target'>,
1180
751
  ) {
1181
- const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.fid;
752
+ const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.feed;
1182
753
 
1183
754
  const response = await this.client.follow({
1184
755
  ...options,
1185
- source: this.fid,
756
+ source: this.feed,
1186
757
  target: fid,
1187
758
  });
1188
759
 
@@ -1190,10 +761,10 @@ export class Feed extends FeedApi {
1190
761
  }
1191
762
 
1192
763
  async unfollow(feedOrFid: Feed | string) {
1193
- const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.fid;
764
+ const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.feed;
1194
765
 
1195
766
  const response = await this.client.unfollow({
1196
- source: this.fid,
767
+ source: this.feed,
1197
768
  target: fid,
1198
769
  });
1199
770
 
@@ -1218,10 +789,10 @@ export class Feed extends FeedApi {
1218
789
  });
1219
790
  }
1220
791
 
1221
- addActivity(request: Omit<ActivityRequest, 'fids'>) {
792
+ addActivity(request: Omit<ActivityRequest, 'feeds'>) {
1222
793
  return this.feedsApi.addActivity({
1223
794
  ...request,
1224
- fids: [this.fid],
795
+ feeds: [this.feed],
1225
796
  });
1226
797
  }
1227
798