@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
package/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- export * from './src/FeedsClient';
2
- export * from './src/Feed';
1
+ export * from './src/feeds-client/feeds-client';
2
+ export * from './src/feed/feed';
3
3
  export * from './src/gen/models';
4
4
  export * from './src/types';
5
5
  export * from './src/common/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/feeds-client",
3
- "version": "0.1.10",
3
+ "version": "0.2.0",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "./dist/index.node.js",
6
6
  "exports": {
@@ -63,10 +63,11 @@
63
63
  "devDependencies": {
64
64
  "@rollup/plugin-replace": "^6.0.1",
65
65
  "@rollup/plugin-typescript": "^12.1.0",
66
- "@stream-io/node-sdk": "0.5.0",
66
+ "@stream-io/node-sdk": "0.6.0",
67
67
  "@types/react": "^19.1.8",
68
68
  "@vitest/coverage-v8": "3.2.4",
69
69
  "dotenv": "^16.4.5",
70
+ "human-id": "^4.1.1",
70
71
  "react": "19.0.0",
71
72
  "rimraf": "^6.0.1",
72
73
  "rollup": "^4.24.0",
@@ -1,7 +1,7 @@
1
1
  import { BaseSearchSource } from './BaseSearchSource';
2
2
  import type { SearchSourceOptions } from './BaseSearchSource';
3
3
 
4
- import { FeedsClient } from '../FeedsClient';
4
+ import { FeedsClient } from '../feeds-client';
5
5
  import { ActivityResponse } from '../gen/models';
6
6
 
7
7
  export class ActivitySearchSource extends BaseSearchSource<ActivityResponse> {
@@ -1,8 +1,8 @@
1
1
  import { BaseSearchSource } from './BaseSearchSource';
2
2
  import type { SearchSourceOptions } from './BaseSearchSource';
3
3
 
4
- import { FeedsClient } from '../FeedsClient';
5
- import { Feed } from '../Feed';
4
+ import { FeedsClient } from '../feeds-client';
5
+ import { Feed } from '../feed';
6
6
 
7
7
  export type FeedSearchSourceOptions = SearchSourceOptions & {
8
8
  groupId?: string;
@@ -1,5 +1,5 @@
1
1
  import { StateStore } from './StateStore';
2
- import type { FeedsClient } from '../FeedsClient';
2
+ import type { FeedsClient } from '../feeds-client';
3
3
  import type {
4
4
  PollVote,
5
5
  QueryPollVotesRequest,
@@ -1,7 +1,7 @@
1
1
  import { BaseSearchSource } from './BaseSearchSource';
2
2
  import type { SearchSourceOptions } from './BaseSearchSource';
3
3
 
4
- import { FeedsClient } from '../FeedsClient';
4
+ import { FeedsClient } from '../feeds-client';
5
5
  import { UserResponse } from '../gen/models';
6
6
 
7
7
  export class UserSearchSource extends BaseSearchSource<UserResponse> {
@@ -4,13 +4,13 @@ import {
4
4
  ActivityReactionDeletedEvent,
5
5
  ActivityResponse,
6
6
  FeedsReactionResponse,
7
- } from '../gen/models';
7
+ } from '../../../gen/models';
8
8
  import {
9
9
  addReactionToActivity,
10
10
  removeReactionFromActivity,
11
11
  addReactionToActivities,
12
12
  removeReactionFromActivities,
13
- } from './activity-reaction-utils';
13
+ } from './';
14
14
 
15
15
  const createMockActivity = (id: string): ActivityResponse => ({
16
16
  id,
@@ -109,6 +109,7 @@ describe('activity-reaction-utils', () => {
109
109
  count: 1,
110
110
  first_reaction_at: reaction.created_at,
111
111
  last_reaction_at: reaction.created_at,
112
+ sum_scores: 0,
112
113
  },
113
114
  };
114
115
 
@@ -123,6 +124,7 @@ describe('activity-reaction-utils', () => {
123
124
  count: 1,
124
125
  first_reaction_at: reaction.created_at,
125
126
  last_reaction_at: reaction.created_at,
127
+ sum_scores: 0,
126
128
  });
127
129
  });
128
130
 
@@ -136,6 +138,7 @@ describe('activity-reaction-utils', () => {
136
138
  count: 1,
137
139
  first_reaction_at: reaction.created_at,
138
140
  last_reaction_at: reaction.created_at,
141
+ sum_scores: 0,
139
142
  },
140
143
  };
141
144
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -150,6 +153,7 @@ describe('activity-reaction-utils', () => {
150
153
  count: 1,
151
154
  first_reaction_at: reaction.created_at,
152
155
  last_reaction_at: reaction.created_at,
156
+ sum_scores: 0,
153
157
  });
154
158
  });
155
159
  });
@@ -165,6 +169,7 @@ describe('activity-reaction-utils', () => {
165
169
  count: 1,
166
170
  first_reaction_at: reaction.created_at,
167
171
  last_reaction_at: reaction.created_at,
172
+ sum_scores: 0,
168
173
  },
169
174
  };
170
175
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -196,6 +201,7 @@ describe('activity-reaction-utils', () => {
196
201
  count: 1,
197
202
  first_reaction_at: reaction.created_at,
198
203
  last_reaction_at: reaction.created_at,
204
+ sum_scores: 0,
199
205
  },
200
206
  };
201
207
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -230,6 +236,7 @@ describe('activity-reaction-utils', () => {
230
236
  count: 1,
231
237
  first_reaction_at: reaction.created_at,
232
238
  last_reaction_at: reaction.created_at,
239
+ sum_scores: 0,
233
240
  },
234
241
  };
235
242
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -253,6 +260,7 @@ describe('activity-reaction-utils', () => {
253
260
  count: 1,
254
261
  first_reaction_at: reaction.created_at,
255
262
  last_reaction_at: reaction.created_at,
263
+ sum_scores: 0,
256
264
  },
257
265
  };
258
266
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -274,6 +282,7 @@ describe('activity-reaction-utils', () => {
274
282
  count: 1,
275
283
  first_reaction_at: reaction.created_at,
276
284
  last_reaction_at: reaction.created_at,
285
+ sum_scores: 0,
277
286
  },
278
287
  };
279
288
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -296,6 +305,7 @@ describe('activity-reaction-utils', () => {
296
305
  count: 1,
297
306
  first_reaction_at: reaction.created_at,
298
307
  last_reaction_at: reaction.created_at,
308
+ sum_scores: 0,
299
309
  },
300
310
  };
301
311
  const event = createMockAddedEvent(reaction, eventActivity);
@@ -1,10 +1,10 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { ActivityResponse, FeedsReactionResponse } from '../gen/models';
2
+ import { ActivityResponse, FeedsReactionResponse } from '../../../gen/models';
3
3
  import {
4
4
  addActivitiesToState,
5
5
  updateActivityInState,
6
6
  removeActivityFromState,
7
- } from './activity-utils';
7
+ } from './';
8
8
 
9
9
  const createMockActivity = (id: string, text?: string): ActivityResponse =>
10
10
  ({
@@ -181,6 +181,7 @@ describe('activity-utils', () => {
181
181
  ];
182
182
  originalActivity.reaction_groups = {
183
183
  like: {
184
+ sum_scores: 0,
184
185
  count: 1,
185
186
  first_reaction_at: new Date(),
186
187
  last_reaction_at: new Date(),
@@ -1,5 +1,6 @@
1
- import { ActivityResponse } from '../gen/models';
2
- import { UpdateStateResult } from '../types-internal';
1
+ import { Feed } from '../../../feed';
2
+ import { ActivityResponse } from '../../../gen/models';
3
+ import { EventPayload, UpdateStateResult } from '../../../types-internal';
3
4
 
4
5
  export const addActivitiesToState = (
5
6
  newActivities: ActivityResponse[],
@@ -42,39 +43,18 @@ export const addActivitiesToState = (
42
43
  return result;
43
44
  };
44
45
 
45
- export const updateActivityInState = (
46
- updatedActivityResponse: ActivityResponse,
47
- activities: ActivityResponse[],
48
- ) => {
49
- const index = activities.findIndex(
50
- (a) => a.id === updatedActivityResponse.id,
46
+ export function handleActivityAdded(
47
+ this: Feed,
48
+ event: EventPayload<'feeds.activity.added'>,
49
+ ) {
50
+ const currentActivities = this.currentState.activities;
51
+ const result = addActivitiesToState(
52
+ [event.activity],
53
+ currentActivities,
54
+ 'start',
51
55
  );
52
- if (index !== -1) {
53
- const newActivities = [...activities];
54
- const activity = activities[index];
55
- newActivities[index] = {
56
- ...updatedActivityResponse,
57
- own_reactions: activity.own_reactions,
58
- own_bookmarks: activity.own_bookmarks,
59
- latest_reactions: activity.latest_reactions,
60
- reaction_groups: activity.reaction_groups,
61
- };
62
- return { changed: true, activities: newActivities };
63
- } else {
64
- return { changed: false, activities };
56
+ if (result.changed) {
57
+ this.client.hydratePollCache([event.activity]);
58
+ this.state.partialNext({ activities: result.activities });
65
59
  }
66
- };
67
-
68
- export const removeActivityFromState = (
69
- activityResponse: ActivityResponse,
70
- activities: ActivityResponse[],
71
- ) => {
72
- const index = activities.findIndex((a) => a.id === activityResponse.id);
73
- if (index !== -1) {
74
- const newActivities = [...activities];
75
- newActivities.splice(index, 1);
76
- return { changed: true, activities: newActivities };
77
- } else {
78
- return { changed: false, activities };
79
- }
80
- };
60
+ }
@@ -0,0 +1,30 @@
1
+ import type { Feed } from '../../../feed';
2
+ import type { ActivityResponse } from '../../../gen/models';
3
+ import type { EventPayload } from '../../../types-internal';
4
+
5
+ export const removeActivityFromState = (
6
+ activityResponse: ActivityResponse,
7
+ activities: ActivityResponse[],
8
+ ) => {
9
+ const index = activities.findIndex((a) => a.id === activityResponse.id);
10
+ if (index !== -1) {
11
+ const newActivities = [...activities];
12
+ newActivities.splice(index, 1);
13
+ return { changed: true, activities: newActivities };
14
+ } else {
15
+ return { changed: false, activities };
16
+ }
17
+ };
18
+
19
+ export function handleActivityDeleted(
20
+ this: Feed,
21
+ event: EventPayload<'feeds.activity.deleted'>,
22
+ ) {
23
+ const currentActivities = this.currentState.activities;
24
+ if (currentActivities) {
25
+ const result = removeActivityFromState(event.activity, currentActivities);
26
+ if (result.changed) {
27
+ this.state.partialNext({ activities: result.activities });
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,67 @@
1
+ import type { Feed } from '../../../feed';
2
+ import type {
3
+ ActivityReactionAddedEvent,
4
+ ActivityResponse,
5
+ } from '../../../gen/models';
6
+ import type { EventPayload, UpdateStateResult } from '../../../types-internal';
7
+
8
+ import { updateActivityInState } from './handle-activity-updated';
9
+
10
+ export const addReactionToActivity = (
11
+ event: ActivityReactionAddedEvent,
12
+ activity: ActivityResponse,
13
+ isCurrentUser: boolean,
14
+ ): UpdateStateResult<ActivityResponse> => {
15
+ // Update own_reactions if the reaction is from the current user
16
+ const ownReactions = [...(activity.own_reactions || [])];
17
+ if (isCurrentUser) {
18
+ ownReactions.push(event.reaction);
19
+ }
20
+
21
+ return {
22
+ ...activity,
23
+ own_reactions: ownReactions,
24
+ latest_reactions: event.activity.latest_reactions,
25
+ reaction_groups: event.activity.reaction_groups,
26
+ changed: true,
27
+ };
28
+ };
29
+
30
+ export const addReactionToActivities = (
31
+ event: ActivityReactionAddedEvent,
32
+ activities: ActivityResponse[] | undefined,
33
+ isCurrentUser: boolean,
34
+ ): UpdateStateResult<{ activities: ActivityResponse[] }> => {
35
+ if (!activities) {
36
+ return { changed: false, activities: [] };
37
+ }
38
+
39
+ const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
40
+ if (activityIndex === -1) {
41
+ return { changed: false, activities };
42
+ }
43
+
44
+ const activity = activities[activityIndex];
45
+ const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
46
+ return updateActivityInState(updatedActivity, activities, true);
47
+ };
48
+
49
+ export function handleActivityReactionAdded(
50
+ this: Feed,
51
+ event: EventPayload<'feeds.activity.reaction.added'>,
52
+ ) {
53
+ const currentActivities = this.currentState.activities;
54
+ const connectedUser = this.client.state.getLatestValue().connected_user;
55
+ const isCurrentUser = Boolean(
56
+ connectedUser && event.reaction.user.id === connectedUser.id,
57
+ );
58
+
59
+ const result = addReactionToActivities(
60
+ event,
61
+ currentActivities,
62
+ isCurrentUser,
63
+ );
64
+ if (result.changed) {
65
+ this.state.partialNext({ activities: result.activities });
66
+ }
67
+ }
@@ -0,0 +1,75 @@
1
+ import type { Feed } from '../../../feed';
2
+ import type {
3
+ ActivityReactionDeletedEvent,
4
+ ActivityResponse,
5
+ } from '../../../gen/models';
6
+ import type { EventPayload, UpdateStateResult } from '../../../types-internal';
7
+
8
+ import { updateActivityInState } from './handle-activity-updated';
9
+ export const removeReactionFromActivity = (
10
+ event: ActivityReactionDeletedEvent,
11
+ activity: ActivityResponse,
12
+ isCurrentUser: boolean,
13
+ ): UpdateStateResult<ActivityResponse> => {
14
+ // Update own_reactions if the reaction is from the current user
15
+ const ownReactions = isCurrentUser
16
+ ? (activity.own_reactions || []).filter(
17
+ (r) =>
18
+ !(
19
+ r.type === event.reaction.type &&
20
+ r.user.id === event.reaction.user.id
21
+ ),
22
+ )
23
+ : activity.own_reactions;
24
+
25
+ return {
26
+ ...activity,
27
+ own_reactions: ownReactions,
28
+ latest_reactions: event.activity.latest_reactions,
29
+ reaction_groups: event.activity.reaction_groups,
30
+ changed: true,
31
+ };
32
+ };
33
+
34
+ export const removeReactionFromActivities = (
35
+ event: ActivityReactionDeletedEvent,
36
+ activities: ActivityResponse[] | undefined,
37
+ isCurrentUser: boolean,
38
+ ): UpdateStateResult<{ activities: ActivityResponse[] }> => {
39
+ if (!activities) {
40
+ return { changed: false, activities: [] };
41
+ }
42
+
43
+ const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
44
+ if (activityIndex === -1) {
45
+ return { changed: false, activities };
46
+ }
47
+
48
+ const activity = activities[activityIndex];
49
+ const updatedActivity = removeReactionFromActivity(
50
+ event,
51
+ activity,
52
+ isCurrentUser,
53
+ );
54
+ return updateActivityInState(updatedActivity, activities, true);
55
+ };
56
+
57
+ export function handleActivityReactionDeleted(
58
+ this: Feed,
59
+ event: EventPayload<'feeds.activity.reaction.deleted'>,
60
+ ) {
61
+ const currentActivities = this.currentState.activities;
62
+ const connectedUser = this.client.state.getLatestValue().connected_user;
63
+ const isCurrentUser = Boolean(
64
+ connectedUser && event.reaction.user.id === connectedUser.id,
65
+ );
66
+
67
+ const result = removeReactionFromActivities(
68
+ event,
69
+ currentActivities,
70
+ isCurrentUser,
71
+ );
72
+ if (result.changed) {
73
+ this.state.partialNext({ activities: result.activities });
74
+ }
75
+ }
@@ -0,0 +1,16 @@
1
+ import { Feed } from '../../../feed';
2
+ import { EventPayload } from '../../../types-internal';
3
+ import { removeActivityFromState } from './handle-activity-deleted';
4
+
5
+ export function handleActivityRemovedFromFeed(
6
+ this: Feed,
7
+ event: EventPayload<'feeds.activity.removed_from_feed'>,
8
+ ) {
9
+ const currentActivities = this.currentState.activities;
10
+ if (currentActivities) {
11
+ const result = removeActivityFromState(event.activity, currentActivities);
12
+ if (result.changed) {
13
+ this.state.partialNext({ activities: result.activities });
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,47 @@
1
+ import { Feed } from '../../../feed';
2
+ import { ActivityResponse } from '../../../gen/models';
3
+ import { EventPayload } from '../../../types-internal';
4
+
5
+ export const updateActivityInState = (
6
+ updatedActivityResponse: ActivityResponse,
7
+ activities: ActivityResponse[],
8
+ replaceCompletely: boolean = false,
9
+ ) => {
10
+ const index = activities.findIndex(
11
+ (a) => a.id === updatedActivityResponse.id,
12
+ );
13
+ if (index !== -1) {
14
+ const newActivities = [...activities];
15
+ const activity = activities[index];
16
+
17
+ if (replaceCompletely) {
18
+ newActivities[index] = updatedActivityResponse;
19
+ } else {
20
+ newActivities[index] = {
21
+ ...updatedActivityResponse,
22
+ own_reactions: activity.own_reactions,
23
+ own_bookmarks: activity.own_bookmarks,
24
+ latest_reactions: activity.latest_reactions,
25
+ reaction_groups: activity.reaction_groups,
26
+ };
27
+ }
28
+
29
+ return { changed: true, activities: newActivities };
30
+ } else {
31
+ return { changed: false, activities };
32
+ }
33
+ };
34
+
35
+ export function handleActivityUpdated(
36
+ this: Feed,
37
+ event: EventPayload<'feeds.activity.updated'>,
38
+ ) {
39
+ const currentActivities = this.currentState.activities;
40
+ if (currentActivities) {
41
+ const result = updateActivityInState(event.activity, currentActivities);
42
+ if (result.changed) {
43
+ this.client.hydratePollCache([event.activity]);
44
+ this.state.partialNext({ activities: result.activities });
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,6 @@
1
+ export * from './handle-activity-added';
2
+ export * from './handle-activity-deleted';
3
+ export * from './handle-activity-removed-from-feed';
4
+ export * from './handle-activity-updated';
5
+ export * from './handle-activity-reaction-added';
6
+ export * from './handle-activity-reaction-deleted';
@@ -6,7 +6,7 @@ import {
6
6
  ActivityResponse,
7
7
  BookmarkResponse,
8
8
  UserResponse,
9
- } from '../gen/models';
9
+ } from '../../../gen/models';
10
10
  import {
11
11
  addBookmarkToActivity,
12
12
  removeBookmarkFromActivity,
@@ -14,7 +14,7 @@ import {
14
14
  addBookmarkToActivities,
15
15
  removeBookmarkFromActivities,
16
16
  updateBookmarkInActivities,
17
- } from './bookmark-utils';
17
+ } from './';
18
18
 
19
19
  const createMockUser = (id: string): UserResponse => ({
20
20
  id,
@@ -0,0 +1,63 @@
1
+ import type { Feed } from '../../../feed';
2
+ import type { ActivityResponse, BookmarkAddedEvent } from '../../../gen/models';
3
+ import type { EventPayload, UpdateStateResult } from '../../../types-internal';
4
+
5
+ import { updateActivityInState } from '../activity';
6
+
7
+ export const addBookmarkToActivity = (
8
+ event: BookmarkAddedEvent,
9
+ activity: ActivityResponse,
10
+ isCurrentUser: boolean,
11
+ ): UpdateStateResult<ActivityResponse> => {
12
+ // Update own_bookmarks if the bookmark is from the current user
13
+ const ownBookmarks = [...(activity.own_bookmarks || [])];
14
+ if (isCurrentUser) {
15
+ ownBookmarks.push(event.bookmark);
16
+ }
17
+
18
+ return {
19
+ ...activity,
20
+ own_bookmarks: ownBookmarks,
21
+ changed: true,
22
+ };
23
+ };
24
+
25
+ export const addBookmarkToActivities = (
26
+ event: BookmarkAddedEvent,
27
+ activities: ActivityResponse[] | undefined,
28
+ isCurrentUser: boolean,
29
+ ): UpdateStateResult<{ activities: ActivityResponse[] }> => {
30
+ if (!activities) {
31
+ return { changed: false, activities: [] };
32
+ }
33
+
34
+ const activityIndex = activities.findIndex(
35
+ (a) => a.id === event.bookmark.activity.id,
36
+ );
37
+ if (activityIndex === -1) {
38
+ return { changed: false, activities };
39
+ }
40
+
41
+ const activity = activities[activityIndex];
42
+ const updatedActivity = addBookmarkToActivity(event, activity, isCurrentUser);
43
+ return updateActivityInState(updatedActivity, activities, true);
44
+ };
45
+
46
+ export function handleBookmarkAdded(
47
+ this: Feed,
48
+ event: EventPayload<'feeds.bookmark.added'>,
49
+ ) {
50
+ const currentActivities = this.currentState.activities;
51
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
52
+ const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
53
+
54
+ const result = addBookmarkToActivities(
55
+ event,
56
+ currentActivities,
57
+ isCurrentUser,
58
+ );
59
+
60
+ if (result.changed) {
61
+ this.state.partialNext({ activities: result.activities });
62
+ }
63
+ }
@@ -0,0 +1,84 @@
1
+ import type { Feed } from '../../../feed';
2
+ import type {
3
+ ActivityResponse,
4
+ BookmarkDeletedEvent,
5
+ BookmarkResponse,
6
+ } from '../../../gen/models';
7
+ import type { EventPayload, UpdateStateResult } from '../../../types-internal';
8
+
9
+ import { updateActivityInState } from '../activity';
10
+
11
+ // Helper function to check if two bookmarks are the same
12
+ // A bookmark is identified by activity_id + folder_id + user_id
13
+ export const isSameBookmark = (
14
+ bookmark1: BookmarkResponse,
15
+ bookmark2: BookmarkResponse,
16
+ ): boolean => {
17
+ return (
18
+ bookmark1.user.id === bookmark2.user.id &&
19
+ bookmark1.activity.id === bookmark2.activity.id &&
20
+ bookmark1.folder?.id === bookmark2.folder?.id
21
+ );
22
+ };
23
+
24
+ export const removeBookmarkFromActivities = (
25
+ event: BookmarkDeletedEvent,
26
+ activities: ActivityResponse[] | undefined,
27
+ isCurrentUser: boolean,
28
+ ): UpdateStateResult<{ activities: ActivityResponse[] }> => {
29
+ if (!activities) {
30
+ return { changed: false, activities: [] };
31
+ }
32
+
33
+ const activityIndex = activities.findIndex(
34
+ (a) => a.id === event.bookmark.activity.id,
35
+ );
36
+ if (activityIndex === -1) {
37
+ return { changed: false, activities };
38
+ }
39
+
40
+ const activity = activities[activityIndex];
41
+ const updatedActivity = removeBookmarkFromActivity(
42
+ event,
43
+ activity,
44
+ isCurrentUser,
45
+ );
46
+ return updateActivityInState(updatedActivity, activities, true);
47
+ };
48
+
49
+ export const removeBookmarkFromActivity = (
50
+ event: BookmarkDeletedEvent,
51
+ activity: ActivityResponse,
52
+ isCurrentUser: boolean,
53
+ ): UpdateStateResult<ActivityResponse> => {
54
+ // Update own_bookmarks if the bookmark is from the current user
55
+ const ownBookmarks = isCurrentUser
56
+ ? (activity.own_bookmarks || []).filter(
57
+ (bookmark) => !isSameBookmark(bookmark, event.bookmark),
58
+ )
59
+ : activity.own_bookmarks;
60
+
61
+ return {
62
+ ...activity,
63
+ own_bookmarks: ownBookmarks,
64
+ changed: true,
65
+ };
66
+ };
67
+
68
+ export function handleBookmarkDeleted(
69
+ this: Feed,
70
+ event: EventPayload<'feeds.bookmark.deleted'>,
71
+ ) {
72
+ const currentActivities = this.currentState.activities;
73
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
74
+ const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
75
+
76
+ const result = removeBookmarkFromActivities(
77
+ event,
78
+ currentActivities,
79
+ isCurrentUser,
80
+ );
81
+ if (result.changed) {
82
+ this.state.partialNext({ activities: result.activities });
83
+ }
84
+ }