@stream-io/feeds-client 1.0.0 → 1.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 (98) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/index.js +477 -466
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/react-bindings.js +454 -463
  5. package/dist/cjs/react-bindings.js.map +1 -1
  6. package/dist/es/index.mjs +440 -466
  7. package/dist/es/index.mjs.map +1 -1
  8. package/dist/es/react-bindings.mjs +447 -493
  9. package/dist/es/react-bindings.mjs.map +1 -1
  10. package/dist/feeds-client-ACVPbpUP.mjs +8752 -0
  11. package/dist/feeds-client-ACVPbpUP.mjs.map +1 -0
  12. package/dist/feeds-client-BP0fE4NZ.js +8918 -0
  13. package/dist/feeds-client-BP0fE4NZ.js.map +1 -0
  14. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  15. package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts +6 -2
  16. package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts.map +1 -1
  17. package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts +6 -2
  18. package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts.map +1 -1
  19. package/dist/types/feed/event-handlers/activity/handle-activity-deleted.d.ts +3 -2
  20. package/dist/types/feed/event-handlers/activity/handle-activity-deleted.d.ts.map +1 -1
  21. package/dist/types/feed/event-handlers/activity/handle-activity-feedback.d.ts +5 -0
  22. package/dist/types/feed/event-handlers/activity/handle-activity-feedback.d.ts.map +1 -1
  23. package/dist/types/feed/event-handlers/activity/handle-activity-pinned.d.ts +3 -2
  24. package/dist/types/feed/event-handlers/activity/handle-activity-pinned.d.ts.map +1 -1
  25. package/dist/types/feed/event-handlers/activity/handle-activity-unpinned.d.ts +3 -2
  26. package/dist/types/feed/event-handlers/activity/handle-activity-unpinned.d.ts.map +1 -1
  27. package/dist/types/feed/event-handlers/activity/index.d.ts +3 -1
  28. package/dist/types/feed/event-handlers/activity/index.d.ts.map +1 -1
  29. package/dist/types/feed/event-handlers/activity-updater.d.ts +1 -0
  30. package/dist/types/feed/event-handlers/activity-updater.d.ts.map +1 -1
  31. package/dist/types/feed/event-handlers/add-aggregated-activities-to-state.d.ts +1 -1
  32. package/dist/types/feed/event-handlers/add-aggregated-activities-to-state.d.ts.map +1 -1
  33. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +6 -5
  34. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-added.d.ts.map +1 -1
  35. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +6 -5
  36. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts.map +1 -1
  37. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +6 -5
  38. package/dist/types/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts.map +1 -1
  39. package/dist/types/feed/event-handlers/feed/handle-feed-deleted.d.ts +4 -0
  40. package/dist/types/feed/event-handlers/feed/handle-feed-deleted.d.ts.map +1 -0
  41. package/dist/types/feed/event-handlers/feed/handle-feed-updated.d.ts.map +1 -1
  42. package/dist/types/feed/event-handlers/feed/index.d.ts +1 -0
  43. package/dist/types/feed/event-handlers/feed/index.d.ts.map +1 -1
  44. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +3 -2
  45. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-added.d.ts.map +1 -1
  46. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +3 -2
  47. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts.map +1 -1
  48. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +3 -2
  49. package/dist/types/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts.map +1 -1
  50. package/dist/types/feed/event-handlers/follow/handle-follow-updated.d.ts.map +1 -1
  51. package/dist/types/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +3 -2
  52. package/dist/types/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts.map +1 -1
  53. package/dist/types/feed/feed.d.ts.map +1 -1
  54. package/dist/types/feeds-client/feeds-client.d.ts +25 -1
  55. package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
  56. package/dist/types/gen/feeds/FeedsApi.d.ts +6 -4
  57. package/dist/types/gen/feeds/FeedsApi.d.ts.map +1 -1
  58. package/dist/types/gen/models/index.d.ts +40 -2
  59. package/dist/types/gen/models/index.d.ts.map +1 -1
  60. package/dist/types/utils/state-update-queue.d.ts +11 -2
  61. package/dist/types/utils/state-update-queue.d.ts.map +1 -1
  62. package/dist/types/utils/unique-array-merge.d.ts +1 -1
  63. package/dist/types/utils/unique-array-merge.d.ts.map +1 -1
  64. package/package.json +15 -15
  65. package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts +6 -20
  66. package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts +6 -20
  67. package/src/feed/event-handlers/activity/handle-activity-deleted.ts +28 -2
  68. package/src/feed/event-handlers/activity/handle-activity-feedback.ts +17 -7
  69. package/src/feed/event-handlers/activity/handle-activity-pinned.ts +25 -3
  70. package/src/feed/event-handlers/activity/handle-activity-unpinned.ts +25 -2
  71. package/src/feed/event-handlers/activity/index.ts +3 -1
  72. package/src/feed/event-handlers/add-aggregated-activities-to-state.ts +11 -2
  73. package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +20 -11
  74. package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +21 -11
  75. package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +24 -10
  76. package/src/feed/event-handlers/feed/handle-feed-deleted.ts +12 -0
  77. package/src/feed/event-handlers/feed/handle-feed-updated.ts +8 -0
  78. package/src/feed/event-handlers/feed/index.ts +1 -0
  79. package/src/feed/event-handlers/feed-member/handle-feed-member-added.ts +25 -2
  80. package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +25 -2
  81. package/src/feed/event-handlers/feed-member/handle-feed-member-updated.ts +25 -2
  82. package/src/feed/event-handlers/follow/handle-follow-updated.ts +14 -0
  83. package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +64 -2
  84. package/src/feed/event-handlers/story-feeds/handle-story-feeds-updated.ts +1 -1
  85. package/src/feed/feed.ts +7 -5
  86. package/src/feeds-client/feeds-client.ts +359 -45
  87. package/src/gen/feeds/FeedsApi.ts +79 -12
  88. package/src/gen/model-decoders/decoders.ts +7 -0
  89. package/src/gen/models/index.ts +66 -4
  90. package/src/utils/state-update-queue.ts +42 -28
  91. package/src/utils/unique-array-merge.ts +11 -3
  92. package/dist/feeds-client-B03y08Kq.mjs +0 -8409
  93. package/dist/feeds-client-B03y08Kq.mjs.map +0 -1
  94. package/dist/feeds-client-tw63OGrd.js +0 -8425
  95. package/dist/feeds-client-tw63OGrd.js.map +0 -1
  96. package/dist/types/feed/event-handlers/activity/handle-activity-marked.d.ts +0 -12
  97. package/dist/types/feed/event-handlers/activity/handle-activity-marked.d.ts.map +0 -1
  98. package/src/feed/event-handlers/activity/handle-activity-marked.ts +0 -68
@@ -1,10 +1,33 @@
1
1
  import type { Feed, FeedState } from '../../../feed';
2
- import type { EventPayload } from '../../../types-internal';
2
+ import type { EventPayload, PartializeAllBut } from '../../../types-internal';
3
+ import { getStateUpdateQueueId, shouldUpdateState } from '../../../utils';
4
+ import { eventTriggeredByConnectedUser } from '../../../utils/event-triggered-by-connected-user';
5
+
6
+ export type FeedMemberUpdatedPayload = PartializeAllBut<
7
+ EventPayload<'feeds.feed_member.updated'>,
8
+ 'member'
9
+ >;
3
10
 
4
11
  export function handleFeedMemberUpdated(
5
12
  this: Feed,
6
- event: EventPayload<'feeds.feed_member.updated'>,
13
+ event: FeedMemberUpdatedPayload,
14
+ fromWs?: boolean,
7
15
  ) {
16
+ if (
17
+ !shouldUpdateState({
18
+ stateUpdateQueueId: getStateUpdateQueueId(event, 'feed-member-updated'),
19
+ stateUpdateQueue: this.stateUpdateQueue,
20
+ watch: this.currentState.watch,
21
+ fromWs,
22
+ isTriggeredByConnectedUser: eventTriggeredByConnectedUser.call(
23
+ this,
24
+ event,
25
+ ),
26
+ })
27
+ ) {
28
+ return;
29
+ }
30
+
8
31
  const { connected_user: connectedUser } = this.client.state.getLatestValue();
9
32
 
10
33
  this.state.next((currentState) => {
@@ -37,6 +37,13 @@ export function handleFollowUpdated(
37
37
  ...currentState,
38
38
  // Update FeedResponse fields, that has the new follower/following count
39
39
  ...follow.source_feed,
40
+ ...(follow.source_feed.own_capabilities !== undefined
41
+ ? {
42
+ own_capabilities: follow.source_feed.own_capabilities,
43
+ own_follows: follow.source_feed.own_follows,
44
+ own_followings: follow.source_feed.own_followings,
45
+ }
46
+ : {}),
40
47
  };
41
48
 
42
49
  const index =
@@ -58,6 +65,13 @@ export function handleFollowUpdated(
58
65
  ...currentState,
59
66
  // Update FeedResponse fields, that has the new follower/following count
60
67
  ...follow.target_feed,
68
+ ...(follow.target_feed.own_capabilities !== undefined
69
+ ? {
70
+ own_capabilities: follow.target_feed.own_capabilities,
71
+ own_follows: follow.target_feed.own_follows,
72
+ own_followings: follow.target_feed.own_followings,
73
+ }
74
+ : {}),
61
75
  };
62
76
 
63
77
  if (
@@ -1,5 +1,6 @@
1
1
  import type { Feed } from '../..';
2
2
  import type {
3
+ ActivityResponse,
3
4
  AggregatedActivityResponse,
4
5
  NotificationFeedUpdatedEvent,
5
6
  NotificationStatusResponse,
@@ -35,15 +36,18 @@ export const updateNotificationFeedFromEvent = (
35
36
  event: NotificationFeedUpdatedEvent,
36
37
  currentAggregatedActivities?: AggregatedActivityResponse[],
37
38
  currentNotificationStatus?: NotificationStatusResponse,
39
+ currentActivities?: ActivityResponse[],
38
40
  ): UpdateStateResult<{
39
41
  data?: {
40
42
  notification_status?: NotificationStatusResponse;
41
43
  aggregated_activities?: AggregatedActivityResponse[];
44
+ activities?: ActivityResponse[];
42
45
  };
43
46
  }> => {
44
47
  const updates: {
45
48
  notification_status?: NotificationStatusResponse;
46
49
  aggregated_activities?: AggregatedActivityResponse[];
50
+ activities?: ActivityResponse[];
47
51
  } = {};
48
52
 
49
53
  if (event.notification_status) {
@@ -58,11 +62,67 @@ export const updateNotificationFeedFromEvent = (
58
62
  }
59
63
  }
60
64
 
65
+ // Determine effective notification status (prefer new from event, fall back to current)
66
+ const effectiveStatus =
67
+ event.notification_status ?? currentNotificationStatus;
68
+ const lastReadAt = effectiveStatus?.last_read_at;
69
+ const lastSeenAt = effectiveStatus?.last_seen_at;
70
+ const readActivities = effectiveStatus?.read_activities ?? [];
71
+ const seenActivities = effectiveStatus?.seen_activities ?? [];
72
+
73
+ // For flat feeds — update currentActivities with is_read/is_seen
74
+ if (currentActivities?.length && effectiveStatus) {
75
+ let anyChanged = false;
76
+ const updatedActivities = currentActivities.map((activity) => {
77
+ const isRead =
78
+ (lastReadAt != null &&
79
+ activity.updated_at.getTime() < lastReadAt.getTime()) ||
80
+ readActivities.includes(activity.id);
81
+ const isSeen =
82
+ (lastSeenAt != null &&
83
+ activity.updated_at.getTime() < lastSeenAt.getTime()) ||
84
+ seenActivities.includes(activity.id);
85
+ if (activity.is_read !== isRead || activity.is_seen !== isSeen) {
86
+ anyChanged = true;
87
+ return { ...activity, is_read: isRead, is_seen: isSeen };
88
+ }
89
+ return activity;
90
+ });
91
+ if (anyChanged) {
92
+ updates.activities = updatedActivities;
93
+ }
94
+ }
95
+
96
+ // For aggregated feeds — update aggregated_activities with is_read/is_seen
97
+ if (currentAggregatedActivities?.length && effectiveStatus) {
98
+ const baseAggregated = currentAggregatedActivities;
99
+ let anyChanged = false;
100
+ const updatedAggregated = baseAggregated.map((group) => {
101
+ const isRead =
102
+ (lastReadAt != null &&
103
+ group.updated_at.getTime() < lastReadAt.getTime()) ||
104
+ readActivities.includes(group.group);
105
+ const isSeen =
106
+ (lastSeenAt != null &&
107
+ group.updated_at.getTime() < lastSeenAt.getTime()) ||
108
+ seenActivities.includes(group.group);
109
+ if (group.is_read !== isRead || group.is_seen !== isSeen) {
110
+ anyChanged = true;
111
+ return { ...group, is_read: isRead, is_seen: isSeen };
112
+ }
113
+ return group;
114
+ });
115
+ if (anyChanged) {
116
+ updates.aggregated_activities = updatedAggregated;
117
+ }
118
+ }
119
+
120
+ // Leave this to the end, because notification_status may not be 100% accurate (only includes last 100 activities)
61
121
  if (event.aggregated_activities && currentAggregatedActivities) {
62
122
  const aggregatedActivitiesResult = addAggregatedActivitiesToState(
63
123
  event.aggregated_activities,
64
- currentAggregatedActivities,
65
- 'start',
124
+ updates.aggregated_activities ?? currentAggregatedActivities,
125
+ 'replace-then-start',
66
126
  );
67
127
 
68
128
  if (aggregatedActivitiesResult.changed) {
@@ -91,11 +151,13 @@ export function handleNotificationFeedUpdated(
91
151
  event,
92
152
  this.currentState.aggregated_activities,
93
153
  this.currentState.notification_status,
154
+ this.currentState.activities,
94
155
  );
95
156
  if (result.changed) {
96
157
  this.state.partialNext({
97
158
  notification_status: result.data?.notification_status,
98
159
  aggregated_activities: result.data?.aggregated_activities,
160
+ activities: result.data?.activities ?? this.currentState.activities,
99
161
  });
100
162
  }
101
163
  }
@@ -79,7 +79,7 @@ export function updateStoriesFeedFromEvent(
79
79
  const aggregatedActivitiesResult = addAggregatedActivitiesToState(
80
80
  event.aggregated_activities,
81
81
  aggregatedActivities,
82
- 'replace',
82
+ 'replace-then-end',
83
83
  );
84
84
 
85
85
  if (aggregatedActivitiesResult.changed) {
package/src/feed/feed.ts CHANGED
@@ -38,9 +38,9 @@ import {
38
38
  handleBookmarkAdded,
39
39
  handleActivityDeleted,
40
40
  handleActivityRemovedFromFeed,
41
+ handleFeedDeleted,
41
42
  handleFeedUpdated,
42
43
  handleNotificationFeedUpdated,
43
- handleActivityMarked,
44
44
  handleActivityReactionAdded,
45
45
  handleActivityReactionDeleted,
46
46
  handleActivityReactionUpdated,
@@ -50,6 +50,8 @@ import {
50
50
  addAggregatedActivitiesToState,
51
51
  updateNotificationStatus,
52
52
  handleStoriesFeedUpdated,
53
+ handleActivityPinned,
54
+ handleActivityUnpinned,
53
55
  } from './event-handlers';
54
56
  import { capitalize } from '../common/utils';
55
57
  import type {
@@ -181,7 +183,7 @@ export class Feed extends FeedApi {
181
183
  'feeds.comment.deleted': handleCommentDeleted.bind(this),
182
184
  'feeds.comment.updated': handleCommentUpdated.bind(this),
183
185
  'feeds.feed.created': Feed.noop,
184
- 'feeds.feed.deleted': Feed.noop,
186
+ 'feeds.feed.deleted': handleFeedDeleted.bind(this),
185
187
  'feeds.feed.updated': handleFeedUpdated.bind(this),
186
188
  'feeds.feed_group.changed': Feed.noop,
187
189
  'feeds.feed_group.deleted': Feed.noop,
@@ -204,9 +206,9 @@ export class Feed extends FeedApi {
204
206
  'feeds.poll.vote_casted': Feed.noop,
205
207
  'feeds.poll.vote_changed': Feed.noop,
206
208
  'feeds.poll.vote_removed': Feed.noop,
207
- 'feeds.activity.pinned': Feed.noop,
208
- 'feeds.activity.unpinned': Feed.noop,
209
- 'feeds.activity.marked': handleActivityMarked.bind(this),
209
+ 'feeds.activity.pinned': handleActivityPinned.bind(this),
210
+ 'feeds.activity.unpinned': handleActivityUnpinned.bind(this),
211
+ 'feeds.activity.marked': Feed.noop,
210
212
  'moderation.custom_action': Feed.noop,
211
213
  'moderation.flagged': Feed.noop,
212
214
  'moderation.mark_reviewed': Feed.noop,