@stream-io/feeds-client 1.0.0 → 1.1.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.
- package/CHANGELOG.md +9 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react-bindings.js +5 -19
- package/dist/cjs/react-bindings.js.map +1 -1
- package/dist/es/index.mjs +2 -2
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/react-bindings.mjs +5 -19
- package/dist/es/react-bindings.mjs.map +1 -1
- package/dist/{feeds-client-tw63OGrd.js → feeds-client-C1c6lcS3.js} +529 -155
- package/dist/feeds-client-C1c6lcS3.js.map +1 -0
- package/dist/{feeds-client-B03y08Kq.mjs → feeds-client-jtUTE4AC.mjs} +529 -155
- package/dist/feeds-client-jtUTE4AC.mjs.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts +6 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts.map +1 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts +6 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-deleted.d.ts +3 -2
- package/dist/types/feed/event-handlers/activity/handle-activity-deleted.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-feedback.d.ts +5 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-feedback.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-pinned.d.ts +3 -2
- package/dist/types/feed/event-handlers/activity/handle-activity-pinned.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-unpinned.d.ts +3 -2
- package/dist/types/feed/event-handlers/activity/handle-activity-unpinned.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/index.d.ts +3 -1
- package/dist/types/feed/event-handlers/activity/index.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity-updater.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity-updater.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/add-aggregated-activities-to-state.d.ts +1 -1
- package/dist/types/feed/event-handlers/add-aggregated-activities-to-state.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +6 -5
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-added.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +6 -5
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +6 -5
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/feed/handle-feed-deleted.d.ts +4 -0
- package/dist/types/feed/event-handlers/feed/handle-feed-deleted.d.ts.map +1 -0
- package/dist/types/feed/event-handlers/feed/handle-feed-updated.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/feed/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed/index.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +3 -2
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-added.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +3 -2
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +3 -2
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/follow/handle-follow-updated.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +3 -2
- package/dist/types/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts.map +1 -1
- package/dist/types/feed/feed.d.ts.map +1 -1
- package/dist/types/feeds-client/feeds-client.d.ts +24 -1
- package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
- package/dist/types/gen/feeds/FeedsApi.d.ts +6 -4
- package/dist/types/gen/feeds/FeedsApi.d.ts.map +1 -1
- package/dist/types/gen/models/index.d.ts +40 -2
- package/dist/types/gen/models/index.d.ts.map +1 -1
- package/dist/types/utils/state-update-queue.d.ts +11 -2
- package/dist/types/utils/state-update-queue.d.ts.map +1 -1
- package/dist/types/utils/unique-array-merge.d.ts +1 -1
- package/dist/types/utils/unique-array-merge.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts +6 -20
- package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts +6 -20
- package/src/feed/event-handlers/activity/handle-activity-deleted.ts +28 -2
- package/src/feed/event-handlers/activity/handle-activity-feedback.ts +17 -7
- package/src/feed/event-handlers/activity/handle-activity-pinned.ts +25 -3
- package/src/feed/event-handlers/activity/handle-activity-unpinned.ts +25 -2
- package/src/feed/event-handlers/activity/index.ts +3 -1
- package/src/feed/event-handlers/add-aggregated-activities-to-state.ts +11 -2
- package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +20 -11
- package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +21 -11
- package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +24 -10
- package/src/feed/event-handlers/feed/handle-feed-deleted.ts +12 -0
- package/src/feed/event-handlers/feed/handle-feed-updated.ts +8 -0
- package/src/feed/event-handlers/feed/index.ts +1 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-added.ts +25 -2
- package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +25 -2
- package/src/feed/event-handlers/feed-member/handle-feed-member-updated.ts +25 -2
- package/src/feed/event-handlers/follow/handle-follow-updated.ts +14 -0
- package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +68 -2
- package/src/feed/event-handlers/story-feeds/handle-story-feeds-updated.ts +1 -1
- package/src/feed/feed.ts +7 -5
- package/src/feeds-client/feeds-client.ts +255 -0
- package/src/gen/feeds/FeedsApi.ts +79 -12
- package/src/gen/model-decoders/decoders.ts +7 -0
- package/src/gen/models/index.ts +66 -4
- package/src/utils/state-update-queue.ts +42 -28
- package/src/utils/unique-array-merge.ts +11 -3
- package/dist/feeds-client-B03y08Kq.mjs.map +0 -1
- package/dist/feeds-client-tw63OGrd.js.map +0 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-marked.d.ts +0 -12
- package/dist/types/feed/event-handlers/activity/handle-activity-marked.d.ts.map +0 -1
- package/src/feed/event-handlers/activity/handle-activity-marked.ts +0 -68
|
@@ -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,71 @@ 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 (
|
|
75
|
+
currentActivities?.length &&
|
|
76
|
+
!currentAggregatedActivities?.length &&
|
|
77
|
+
effectiveStatus
|
|
78
|
+
) {
|
|
79
|
+
let anyChanged = false;
|
|
80
|
+
const updatedActivities = currentActivities.map((activity) => {
|
|
81
|
+
const isRead =
|
|
82
|
+
(lastReadAt != null &&
|
|
83
|
+
activity.updated_at.getTime() < lastReadAt.getTime()) ||
|
|
84
|
+
readActivities.includes(activity.id);
|
|
85
|
+
const isSeen =
|
|
86
|
+
(lastSeenAt != null &&
|
|
87
|
+
activity.updated_at.getTime() < lastSeenAt.getTime()) ||
|
|
88
|
+
seenActivities.includes(activity.id);
|
|
89
|
+
if (activity.is_read !== isRead || activity.is_seen !== isSeen) {
|
|
90
|
+
anyChanged = true;
|
|
91
|
+
return { ...activity, is_read: isRead, is_seen: isSeen };
|
|
92
|
+
}
|
|
93
|
+
return activity;
|
|
94
|
+
});
|
|
95
|
+
if (anyChanged) {
|
|
96
|
+
updates.activities = updatedActivities;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// For aggregated feeds — update aggregated_activities with is_read/is_seen
|
|
101
|
+
if (currentAggregatedActivities?.length && effectiveStatus) {
|
|
102
|
+
const baseAggregated = currentAggregatedActivities;
|
|
103
|
+
let anyChanged = false;
|
|
104
|
+
const updatedAggregated = baseAggregated.map((group) => {
|
|
105
|
+
const isRead =
|
|
106
|
+
(lastReadAt != null &&
|
|
107
|
+
group.updated_at.getTime() < lastReadAt.getTime()) ||
|
|
108
|
+
readActivities.includes(group.group);
|
|
109
|
+
const isSeen =
|
|
110
|
+
(lastSeenAt != null &&
|
|
111
|
+
group.updated_at.getTime() < lastSeenAt.getTime()) ||
|
|
112
|
+
seenActivities.includes(group.group);
|
|
113
|
+
if (group.is_read !== isRead || group.is_seen !== isSeen) {
|
|
114
|
+
anyChanged = true;
|
|
115
|
+
return { ...group, is_read: isRead, is_seen: isSeen };
|
|
116
|
+
}
|
|
117
|
+
return group;
|
|
118
|
+
});
|
|
119
|
+
if (anyChanged) {
|
|
120
|
+
updates.aggregated_activities = updatedAggregated;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Leave this to the end, because notification_status may not be 100% accurate (only includes last 100 activities)
|
|
61
125
|
if (event.aggregated_activities && currentAggregatedActivities) {
|
|
62
126
|
const aggregatedActivitiesResult = addAggregatedActivitiesToState(
|
|
63
127
|
event.aggregated_activities,
|
|
64
|
-
currentAggregatedActivities,
|
|
65
|
-
'start',
|
|
128
|
+
updates.aggregated_activities ?? currentAggregatedActivities,
|
|
129
|
+
'replace-then-start',
|
|
66
130
|
);
|
|
67
131
|
|
|
68
132
|
if (aggregatedActivitiesResult.changed) {
|
|
@@ -91,11 +155,13 @@ export function handleNotificationFeedUpdated(
|
|
|
91
155
|
event,
|
|
92
156
|
this.currentState.aggregated_activities,
|
|
93
157
|
this.currentState.notification_status,
|
|
158
|
+
this.currentState.activities,
|
|
94
159
|
);
|
|
95
160
|
if (result.changed) {
|
|
96
161
|
this.state.partialNext({
|
|
97
162
|
notification_status: result.data?.notification_status,
|
|
98
163
|
aggregated_activities: result.data?.aggregated_activities,
|
|
164
|
+
activities: result.data?.activities ?? this.currentState.activities,
|
|
99
165
|
});
|
|
100
166
|
}
|
|
101
167
|
}
|
|
@@ -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':
|
|
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':
|
|
208
|
-
'feeds.activity.unpinned':
|
|
209
|
-
'feeds.activity.marked':
|
|
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,
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { FeedsApi } from '../gen/feeds/FeedsApi';
|
|
2
2
|
import type {
|
|
3
|
+
AcceptFeedMemberInviteResponse,
|
|
4
|
+
ActivityFeedbackRequest,
|
|
5
|
+
ActivityFeedbackResponse,
|
|
3
6
|
ActivityResponse,
|
|
4
7
|
AddActivityRequest,
|
|
5
8
|
AddActivityResponse,
|
|
9
|
+
AddBookmarkRequest,
|
|
10
|
+
AddBookmarkResponse,
|
|
6
11
|
AddCommentReactionRequest,
|
|
7
12
|
AddCommentReactionResponse,
|
|
8
13
|
AddCommentRequest,
|
|
@@ -11,8 +16,11 @@ import type {
|
|
|
11
16
|
CastPollVoteRequest,
|
|
12
17
|
CreateGuestResponse,
|
|
13
18
|
DeleteActivityReactionResponse,
|
|
19
|
+
DeleteActivityResponse,
|
|
20
|
+
DeleteBookmarkResponse,
|
|
14
21
|
DeleteCommentReactionResponse,
|
|
15
22
|
DeleteCommentResponse,
|
|
23
|
+
DeleteFeedResponse,
|
|
16
24
|
FeedResponse,
|
|
17
25
|
FileUploadRequest,
|
|
18
26
|
FollowBatchRequest,
|
|
@@ -23,16 +31,24 @@ import type {
|
|
|
23
31
|
ImageSize,
|
|
24
32
|
ImageUploadRequest,
|
|
25
33
|
OwnBatchRequest,
|
|
34
|
+
PinActivityResponse,
|
|
26
35
|
PollResponse,
|
|
27
36
|
PollVoteResponse,
|
|
28
37
|
PollVotesResponse,
|
|
29
38
|
QueryFeedsRequest,
|
|
30
39
|
QueryPollVotesRequest,
|
|
40
|
+
RejectFeedMemberInviteResponse,
|
|
31
41
|
UnfollowBatchRequest,
|
|
42
|
+
UnpinActivityResponse,
|
|
43
|
+
UpdateActivityPartialResponse,
|
|
32
44
|
UpdateActivityRequest,
|
|
33
45
|
UpdateActivityResponse,
|
|
46
|
+
UpdateBookmarkRequest,
|
|
47
|
+
UpdateBookmarkResponse,
|
|
34
48
|
UpdateCommentRequest,
|
|
35
49
|
UpdateCommentResponse,
|
|
50
|
+
UpdateFeedMembersResponse,
|
|
51
|
+
UpdateFeedResponse,
|
|
36
52
|
UpdateFollowRequest,
|
|
37
53
|
UpdatePollPartialRequest,
|
|
38
54
|
UpdatePollRequest,
|
|
@@ -68,21 +84,32 @@ import { StreamPoll } from '../common/Poll';
|
|
|
68
84
|
import {
|
|
69
85
|
Feed,
|
|
70
86
|
type FeedState,
|
|
87
|
+
handleActivityDeleted,
|
|
71
88
|
handleActivityReactionAdded,
|
|
72
89
|
handleActivityReactionDeleted,
|
|
73
90
|
handleActivityReactionUpdated,
|
|
74
91
|
handleActivityUpdated,
|
|
92
|
+
handleActivityPinned,
|
|
93
|
+
handleActivityUnpinned,
|
|
94
|
+
handleBookmarkAdded,
|
|
95
|
+
handleBookmarkDeleted,
|
|
96
|
+
handleBookmarkUpdated,
|
|
75
97
|
handleCommentAdded,
|
|
76
98
|
handleCommentDeleted,
|
|
77
99
|
handleCommentReactionAdded,
|
|
78
100
|
handleCommentReactionDeleted,
|
|
79
101
|
handleCommentUpdated,
|
|
102
|
+
handleFeedDeleted,
|
|
103
|
+
handleFeedMemberAdded,
|
|
104
|
+
handleFeedMemberRemoved,
|
|
105
|
+
handleFeedMemberUpdated,
|
|
80
106
|
handleFeedUpdated,
|
|
81
107
|
handleFollowCreated,
|
|
82
108
|
handleFollowDeleted,
|
|
83
109
|
handleFollowUpdated,
|
|
84
110
|
handleWatchStarted,
|
|
85
111
|
handleWatchStopped,
|
|
112
|
+
updateActivityFromFeedback,
|
|
86
113
|
} from '../feed';
|
|
87
114
|
import { applyNewActivityToActiveFeeds } from './apply-new-activity-to-active-feeds';
|
|
88
115
|
import { handleUserUpdated } from './event-handlers';
|
|
@@ -564,6 +591,66 @@ export class FeedsClient extends FeedsApi {
|
|
|
564
591
|
return response;
|
|
565
592
|
};
|
|
566
593
|
|
|
594
|
+
updateActivityPartial = async (
|
|
595
|
+
...args: Parameters<FeedsApi['updateActivityPartial']>
|
|
596
|
+
): Promise<StreamResponse<UpdateActivityPartialResponse>> => {
|
|
597
|
+
const response = await super.updateActivityPartial(...args);
|
|
598
|
+
for (const feed of this.allActiveFeeds) {
|
|
599
|
+
handleActivityUpdated.bind(feed)(response, false);
|
|
600
|
+
}
|
|
601
|
+
return response;
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
deleteActivity = async (
|
|
605
|
+
...args: Parameters<FeedsApi['deleteActivity']>
|
|
606
|
+
): Promise<StreamResponse<DeleteActivityResponse>> => {
|
|
607
|
+
const response = await super.deleteActivity(...args);
|
|
608
|
+
const activityId = args[0].id;
|
|
609
|
+
for (const feed of this.allActiveFeeds) {
|
|
610
|
+
handleActivityDeleted.bind(feed)(
|
|
611
|
+
{ activity: { id: activityId } } as Parameters<
|
|
612
|
+
typeof handleActivityDeleted
|
|
613
|
+
>[0],
|
|
614
|
+
false,
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
this.activeActivities = this.activeActivities.filter(
|
|
618
|
+
(activity) => activity.id !== activityId,
|
|
619
|
+
);
|
|
620
|
+
return response;
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
activityFeedback = async (
|
|
624
|
+
request: ActivityFeedbackRequest & { activity_id: string },
|
|
625
|
+
): Promise<StreamResponse<ActivityFeedbackResponse>> => {
|
|
626
|
+
const response = await super.activityFeedback(request);
|
|
627
|
+
if (request.hide !== undefined) {
|
|
628
|
+
const feedback = {
|
|
629
|
+
activity_id: request.activity_id,
|
|
630
|
+
action: 'hide' as const,
|
|
631
|
+
value: request.hide ? 'true' : 'false',
|
|
632
|
+
};
|
|
633
|
+
for (const feed of this.allActiveFeeds) {
|
|
634
|
+
const {
|
|
635
|
+
activities: currentActivities,
|
|
636
|
+
pinned_activities: currentPinnedActivities,
|
|
637
|
+
} = feed.currentState;
|
|
638
|
+
const [result1, result2] = [
|
|
639
|
+
updateActivityFromFeedback(feedback, currentActivities),
|
|
640
|
+
updateActivityFromFeedback(feedback, currentPinnedActivities),
|
|
641
|
+
];
|
|
642
|
+
|
|
643
|
+
if (result1.changed || result2.changed) {
|
|
644
|
+
feed.state.partialNext({
|
|
645
|
+
activities: result1.entities,
|
|
646
|
+
pinned_activities: result2.entities,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return response;
|
|
652
|
+
};
|
|
653
|
+
|
|
567
654
|
addComment = async (
|
|
568
655
|
request: AddCommentRequest,
|
|
569
656
|
): Promise<StreamResponse<AddCommentResponse>> => {
|
|
@@ -693,6 +780,160 @@ export class FeedsClient extends FeedsApi {
|
|
|
693
780
|
return response;
|
|
694
781
|
};
|
|
695
782
|
|
|
783
|
+
addBookmark = async (
|
|
784
|
+
request: AddBookmarkRequest & { activity_id: string },
|
|
785
|
+
): Promise<StreamResponse<AddBookmarkResponse>> => {
|
|
786
|
+
const response = await super.addBookmark(request);
|
|
787
|
+
for (const feed of this.allActiveFeeds) {
|
|
788
|
+
handleBookmarkAdded.bind(feed)(response);
|
|
789
|
+
}
|
|
790
|
+
return response;
|
|
791
|
+
};
|
|
792
|
+
|
|
793
|
+
updateBookmark = async (
|
|
794
|
+
request: UpdateBookmarkRequest & { activity_id: string },
|
|
795
|
+
): Promise<StreamResponse<UpdateBookmarkResponse>> => {
|
|
796
|
+
const response = await super.updateBookmark(request);
|
|
797
|
+
for (const feed of this.allActiveFeeds) {
|
|
798
|
+
handleBookmarkUpdated.bind(feed)(response);
|
|
799
|
+
}
|
|
800
|
+
return response;
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
deleteBookmark = async (request: {
|
|
804
|
+
activity_id: string;
|
|
805
|
+
folder_id?: string;
|
|
806
|
+
}): Promise<StreamResponse<DeleteBookmarkResponse>> => {
|
|
807
|
+
const response = await super.deleteBookmark(request);
|
|
808
|
+
for (const feed of this.allActiveFeeds) {
|
|
809
|
+
handleBookmarkDeleted.bind(feed)(response);
|
|
810
|
+
}
|
|
811
|
+
return response;
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
pinActivity = async (
|
|
815
|
+
...args: Parameters<FeedsApi['pinActivity']>
|
|
816
|
+
): Promise<StreamResponse<PinActivityResponse>> => {
|
|
817
|
+
const response = await super.pinActivity(...args);
|
|
818
|
+
const feedIds =
|
|
819
|
+
response.activity?.feeds ?? (response.feed ? [response.feed] : []);
|
|
820
|
+
for (const fid of feedIds) {
|
|
821
|
+
const feed = this.activeFeeds[fid];
|
|
822
|
+
if (feed) {
|
|
823
|
+
handleActivityPinned.bind(feed)(
|
|
824
|
+
{ pinned_activity: response } as Parameters<
|
|
825
|
+
typeof handleActivityPinned
|
|
826
|
+
>[0],
|
|
827
|
+
false,
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
return response;
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
unpinActivity = async (
|
|
835
|
+
...args: Parameters<FeedsApi['unpinActivity']>
|
|
836
|
+
): Promise<StreamResponse<UnpinActivityResponse>> => {
|
|
837
|
+
const response = await super.unpinActivity(...args);
|
|
838
|
+
const feedIds =
|
|
839
|
+
response.activity?.feeds ?? (response.feed ? [response.feed] : []);
|
|
840
|
+
for (const fid of feedIds) {
|
|
841
|
+
const feed = this.activeFeeds[fid];
|
|
842
|
+
if (feed) {
|
|
843
|
+
handleActivityUnpinned.bind(feed)(
|
|
844
|
+
{
|
|
845
|
+
pinned_activity: {
|
|
846
|
+
...response,
|
|
847
|
+
created_at: new Date(),
|
|
848
|
+
},
|
|
849
|
+
} as Parameters<typeof handleActivityUnpinned>[0],
|
|
850
|
+
false,
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return response;
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
updateFeed = async (
|
|
858
|
+
...args: Parameters<FeedsApi['updateFeed']>
|
|
859
|
+
): Promise<StreamResponse<UpdateFeedResponse>> => {
|
|
860
|
+
const response = await super.updateFeed(...args);
|
|
861
|
+
const fid = `${args[0].feed_group_id}:${args[0].feed_id}`;
|
|
862
|
+
const feed = this.activeFeeds[fid];
|
|
863
|
+
if (feed) {
|
|
864
|
+
handleFeedUpdated.call(feed, { feed: response.feed } as Parameters<
|
|
865
|
+
typeof handleFeedUpdated
|
|
866
|
+
>[0]);
|
|
867
|
+
}
|
|
868
|
+
return response;
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
deleteFeed = async (
|
|
872
|
+
...args: Parameters<FeedsApi['deleteFeed']>
|
|
873
|
+
): Promise<StreamResponse<DeleteFeedResponse>> => {
|
|
874
|
+
const response = await super.deleteFeed(...args);
|
|
875
|
+
const fid = `${args[0].feed_group_id}:${args[0].feed_id}`;
|
|
876
|
+
const feed = this.activeFeeds[fid];
|
|
877
|
+
if (feed) {
|
|
878
|
+
handleFeedDeleted.call(feed, {
|
|
879
|
+
created_at: new Date(),
|
|
880
|
+
} as Parameters<typeof handleFeedDeleted>[0]);
|
|
881
|
+
// If the feed is not watched, clean up immediately (no WS event will follow).
|
|
882
|
+
// If watched, the WS handler will clean up after dispatching the event.
|
|
883
|
+
if (!feed.currentState.watch) {
|
|
884
|
+
delete this.activeFeeds[fid];
|
|
885
|
+
this.activeActivities = this.activeActivities.filter(
|
|
886
|
+
(activity) => getFeed.call(activity)?.feed !== fid,
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return response;
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
updateFeedMembers = async (
|
|
894
|
+
...args: Parameters<FeedsApi['updateFeedMembers']>
|
|
895
|
+
): Promise<StreamResponse<UpdateFeedMembersResponse>> => {
|
|
896
|
+
const response = await super.updateFeedMembers(...args);
|
|
897
|
+
const fid = `${args[0].feed_group_id}:${args[0].feed_id}`;
|
|
898
|
+
const feed = this.activeFeeds[fid];
|
|
899
|
+
if (feed) {
|
|
900
|
+
for (const member of response.added) {
|
|
901
|
+
handleFeedMemberAdded.call(feed, { member }, false);
|
|
902
|
+
}
|
|
903
|
+
for (const member of response.updated) {
|
|
904
|
+
handleFeedMemberUpdated.call(feed, { member }, false);
|
|
905
|
+
}
|
|
906
|
+
for (const memberId of response.removed_ids) {
|
|
907
|
+
handleFeedMemberRemoved.call(feed, { member_id: memberId }, false);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return response;
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
acceptFeedMemberInvite = async (
|
|
914
|
+
...args: Parameters<FeedsApi['acceptFeedMemberInvite']>
|
|
915
|
+
): Promise<StreamResponse<AcceptFeedMemberInviteResponse>> => {
|
|
916
|
+
const response = await super.acceptFeedMemberInvite(...args);
|
|
917
|
+
const fid = `${args[0].feed_group_id}:${args[0].feed_id}`;
|
|
918
|
+
const feed = this.activeFeeds[fid];
|
|
919
|
+
if (feed) {
|
|
920
|
+
handleFeedMemberUpdated.call(feed, { member: response.member }, false);
|
|
921
|
+
}
|
|
922
|
+
return response;
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
rejectFeedMemberInvite = async (
|
|
926
|
+
...args: Parameters<FeedsApi['rejectFeedMemberInvite']>
|
|
927
|
+
): Promise<StreamResponse<RejectFeedMemberInviteResponse>> => {
|
|
928
|
+
const response = await super.rejectFeedMemberInvite(...args);
|
|
929
|
+
const fid = `${args[0].feed_group_id}:${args[0].feed_id}`;
|
|
930
|
+
const feed = this.activeFeeds[fid];
|
|
931
|
+
if (feed) {
|
|
932
|
+
handleFeedMemberUpdated.call(feed, { member: response.member }, false);
|
|
933
|
+
}
|
|
934
|
+
return response;
|
|
935
|
+
};
|
|
936
|
+
|
|
696
937
|
queryPollAnswers = async (
|
|
697
938
|
request: QueryPollVotesRequest & { poll_id: string; user_id?: string },
|
|
698
939
|
): Promise<StreamResponse<PollVotesResponse>> => {
|
|
@@ -856,6 +1097,20 @@ export class FeedsClient extends FeedsApi {
|
|
|
856
1097
|
return response;
|
|
857
1098
|
}
|
|
858
1099
|
|
|
1100
|
+
async acceptFollow(...args: Parameters<FeedsApi['acceptFollow']>) {
|
|
1101
|
+
const response = await super.acceptFollow(...args);
|
|
1102
|
+
|
|
1103
|
+
[
|
|
1104
|
+
response.follow.source_feed.feed,
|
|
1105
|
+
response.follow.target_feed.feed,
|
|
1106
|
+
].forEach((fid) => {
|
|
1107
|
+
const feeds = this.findAllActiveFeedsByFid(fid);
|
|
1108
|
+
feeds.forEach((f) => handleFollowUpdated.bind(f)(response, false));
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
return response;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
859
1114
|
// For follow API endpoints we update the state after HTTP response to allow queryFeeds with watch: false
|
|
860
1115
|
async follow(request: FollowRequest) {
|
|
861
1116
|
const response = await super.follow(request);
|
|
@@ -84,6 +84,8 @@ import type {
|
|
|
84
84
|
QueryBookmarkFoldersResponse,
|
|
85
85
|
QueryBookmarksRequest,
|
|
86
86
|
QueryBookmarksResponse,
|
|
87
|
+
QueryCollectionsRequest,
|
|
88
|
+
QueryCollectionsResponse,
|
|
87
89
|
QueryCommentReactionsRequest,
|
|
88
90
|
QueryCommentReactionsResponse,
|
|
89
91
|
QueryCommentsRequest,
|
|
@@ -106,6 +108,7 @@ import type {
|
|
|
106
108
|
RejectFeedMemberInviteResponse,
|
|
107
109
|
RejectFollowRequest,
|
|
108
110
|
RejectFollowResponse,
|
|
111
|
+
RemoveUserGroupMembersRequest,
|
|
109
112
|
RemoveUserGroupMembersResponse,
|
|
110
113
|
Response,
|
|
111
114
|
RestoreActivityRequest,
|
|
@@ -114,6 +117,8 @@ import type {
|
|
|
114
117
|
SharedLocationResponse,
|
|
115
118
|
SharedLocationsResponse,
|
|
116
119
|
SingleFollowResponse,
|
|
120
|
+
TrackActivityMetricsRequest,
|
|
121
|
+
TrackActivityMetricsResponse,
|
|
117
122
|
UnblockUsersRequest,
|
|
118
123
|
UnblockUsersResponse,
|
|
119
124
|
UnfollowBatchRequest,
|
|
@@ -413,6 +418,29 @@ export class FeedsApi {
|
|
|
413
418
|
return { ...response.body, metadata: response.metadata };
|
|
414
419
|
}
|
|
415
420
|
|
|
421
|
+
async trackActivityMetrics(
|
|
422
|
+
request: TrackActivityMetricsRequest,
|
|
423
|
+
): Promise<StreamResponse<TrackActivityMetricsResponse>> {
|
|
424
|
+
const body = {
|
|
425
|
+
events: request?.events,
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const response = await this.apiClient.sendRequest<
|
|
429
|
+
StreamResponse<TrackActivityMetricsResponse>
|
|
430
|
+
>(
|
|
431
|
+
'POST',
|
|
432
|
+
'/api/v2/feeds/activities/metrics/track',
|
|
433
|
+
undefined,
|
|
434
|
+
undefined,
|
|
435
|
+
body,
|
|
436
|
+
'application/json',
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
decoders.TrackActivityMetricsResponse?.(response.body);
|
|
440
|
+
|
|
441
|
+
return { ...response.body, metadata: response.metadata };
|
|
442
|
+
}
|
|
443
|
+
|
|
416
444
|
async queryActivities(
|
|
417
445
|
request?: QueryActivitiesRequest,
|
|
418
446
|
): Promise<StreamResponse<QueryActivitiesResponse>> {
|
|
@@ -1020,6 +1048,33 @@ export class FeedsApi {
|
|
|
1020
1048
|
return { ...response.body, metadata: response.metadata };
|
|
1021
1049
|
}
|
|
1022
1050
|
|
|
1051
|
+
async queryCollections(
|
|
1052
|
+
request?: QueryCollectionsRequest,
|
|
1053
|
+
): Promise<StreamResponse<QueryCollectionsResponse>> {
|
|
1054
|
+
const body = {
|
|
1055
|
+
limit: request?.limit,
|
|
1056
|
+
next: request?.next,
|
|
1057
|
+
prev: request?.prev,
|
|
1058
|
+
sort: request?.sort,
|
|
1059
|
+
filter: request?.filter,
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
const response = await this.apiClient.sendRequest<
|
|
1063
|
+
StreamResponse<QueryCollectionsResponse>
|
|
1064
|
+
>(
|
|
1065
|
+
'POST',
|
|
1066
|
+
'/api/v2/feeds/collections/query',
|
|
1067
|
+
undefined,
|
|
1068
|
+
undefined,
|
|
1069
|
+
body,
|
|
1070
|
+
'application/json',
|
|
1071
|
+
);
|
|
1072
|
+
|
|
1073
|
+
decoders.QueryCollectionsResponse?.(response.body);
|
|
1074
|
+
|
|
1075
|
+
return { ...response.body, metadata: response.metadata };
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1023
1078
|
async getComments(request: {
|
|
1024
1079
|
object_id: string;
|
|
1025
1080
|
object_type: string;
|
|
@@ -1112,6 +1167,7 @@ export class FeedsApi {
|
|
|
1112
1167
|
): Promise<StreamResponse<QueryCommentsResponse>> {
|
|
1113
1168
|
const body = {
|
|
1114
1169
|
filter: request?.filter,
|
|
1170
|
+
id_around: request?.id_around,
|
|
1115
1171
|
limit: request?.limit,
|
|
1116
1172
|
next: request?.next,
|
|
1117
1173
|
prev: request?.prev,
|
|
@@ -2649,25 +2705,36 @@ export class FeedsApi {
|
|
|
2649
2705
|
return { ...response.body, metadata: response.metadata };
|
|
2650
2706
|
}
|
|
2651
2707
|
|
|
2652
|
-
async
|
|
2653
|
-
id: string
|
|
2654
|
-
|
|
2708
|
+
async addUserGroupMembers(
|
|
2709
|
+
request: AddUserGroupMembersRequest & { id: string },
|
|
2710
|
+
): Promise<StreamResponse<AddUserGroupMembersResponse>> {
|
|
2655
2711
|
const pathParams = {
|
|
2656
2712
|
id: request?.id,
|
|
2657
2713
|
};
|
|
2714
|
+
const body = {
|
|
2715
|
+
member_ids: request?.member_ids,
|
|
2716
|
+
team_id: request?.team_id,
|
|
2717
|
+
};
|
|
2658
2718
|
|
|
2659
2719
|
const response = await this.apiClient.sendRequest<
|
|
2660
|
-
StreamResponse<
|
|
2661
|
-
>(
|
|
2720
|
+
StreamResponse<AddUserGroupMembersResponse>
|
|
2721
|
+
>(
|
|
2722
|
+
'POST',
|
|
2723
|
+
'/api/v2/usergroups/{id}/members',
|
|
2724
|
+
pathParams,
|
|
2725
|
+
undefined,
|
|
2726
|
+
body,
|
|
2727
|
+
'application/json',
|
|
2728
|
+
);
|
|
2662
2729
|
|
|
2663
|
-
decoders.
|
|
2730
|
+
decoders.AddUserGroupMembersResponse?.(response.body);
|
|
2664
2731
|
|
|
2665
2732
|
return { ...response.body, metadata: response.metadata };
|
|
2666
2733
|
}
|
|
2667
2734
|
|
|
2668
|
-
async
|
|
2669
|
-
request:
|
|
2670
|
-
): Promise<StreamResponse<
|
|
2735
|
+
async removeUserGroupMembers(
|
|
2736
|
+
request: RemoveUserGroupMembersRequest & { id: string },
|
|
2737
|
+
): Promise<StreamResponse<RemoveUserGroupMembersResponse>> {
|
|
2671
2738
|
const pathParams = {
|
|
2672
2739
|
id: request?.id,
|
|
2673
2740
|
};
|
|
@@ -2677,17 +2744,17 @@ export class FeedsApi {
|
|
|
2677
2744
|
};
|
|
2678
2745
|
|
|
2679
2746
|
const response = await this.apiClient.sendRequest<
|
|
2680
|
-
StreamResponse<
|
|
2747
|
+
StreamResponse<RemoveUserGroupMembersResponse>
|
|
2681
2748
|
>(
|
|
2682
2749
|
'POST',
|
|
2683
|
-
'/api/v2/usergroups/{id}/members',
|
|
2750
|
+
'/api/v2/usergroups/{id}/members/delete',
|
|
2684
2751
|
pathParams,
|
|
2685
2752
|
undefined,
|
|
2686
2753
|
body,
|
|
2687
2754
|
'application/json',
|
|
2688
2755
|
);
|
|
2689
2756
|
|
|
2690
|
-
decoders.
|
|
2757
|
+
decoders.RemoveUserGroupMembersResponse?.(response.body);
|
|
2691
2758
|
|
|
2692
2759
|
return { ...response.body, metadata: response.metadata };
|
|
2693
2760
|
}
|
|
@@ -1554,6 +1554,13 @@ decoders.QueryBookmarksResponse = (input?: Record<string, any>) => {
|
|
|
1554
1554
|
return decode(typeMappings, input);
|
|
1555
1555
|
};
|
|
1556
1556
|
|
|
1557
|
+
decoders.QueryCollectionsResponse = (input?: Record<string, any>) => {
|
|
1558
|
+
const typeMappings: TypeMapping = {
|
|
1559
|
+
collections: { type: 'CollectionResponse', isSingle: false },
|
|
1560
|
+
};
|
|
1561
|
+
return decode(typeMappings, input);
|
|
1562
|
+
};
|
|
1563
|
+
|
|
1557
1564
|
decoders.QueryCommentReactionsResponse = (input?: Record<string, any>) => {
|
|
1558
1565
|
const typeMappings: TypeMapping = {
|
|
1559
1566
|
reactions: { type: 'FeedsReactionResponse', isSingle: false },
|