@stream-io/feeds-client 0.3.46 → 0.3.48
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 +22 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react-bindings.js +56 -23
- 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 +56 -23
- package/dist/es/react-bindings.mjs.map +1 -1
- package/dist/{feeds-client-CSg4hlZ4.mjs → feeds-client-D-EFo20w.mjs} +100 -23
- package/dist/feeds-client-D-EFo20w.mjs.map +1 -0
- package/dist/{feeds-client-CF1yEox0.js → feeds-client-DuJuJuEJ.js} +100 -23
- package/dist/feeds-client-DuJuJuEJ.js.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts +1 -0
- package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts.map +1 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/useMembers.d.ts +17 -0
- package/dist/types/bindings/react/hooks/feed-state-hooks/useMembers.d.ts.map +1 -0
- package/dist/types/common/Poll.d.ts +9 -4
- package/dist/types/common/Poll.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity-updater.d.ts +2 -2
- package/dist/types/feed/event-handlers/activity-updater.d.ts.map +1 -1
- package/dist/types/feeds-client/feeds-client.d.ts +11 -1
- package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
- package/dist/types/gen/feeds/FeedApi.d.ts +2 -1
- package/dist/types/gen/feeds/FeedApi.d.ts.map +1 -1
- package/dist/types/gen/feeds/FeedsApi.d.ts +5 -1
- package/dist/types/gen/feeds/FeedsApi.d.ts.map +1 -1
- package/dist/types/gen/models/index.d.ts +13 -0
- package/dist/types/gen/models/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/bindings/react/hooks/feed-state-hooks/index.ts +1 -0
- package/src/bindings/react/hooks/feed-state-hooks/useMembers.ts +55 -0
- package/src/common/Poll.ts +47 -26
- package/src/feed/event-handlers/activity-updater.ts +2 -0
- package/src/feeds-client/feeds-client.ts +52 -11
- package/src/gen/feeds/FeedApi.ts +12 -0
- package/src/gen/feeds/FeedsApi.ts +36 -0
- package/src/gen/model-decoders/decoders.ts +7 -0
- package/src/gen/models/index.ts +22 -0
- package/dist/feeds-client-CF1yEox0.js.map +0 -1
- package/dist/feeds-client-CSg4hlZ4.mjs.map +0 -1
package/src/common/Poll.ts
CHANGED
|
@@ -6,9 +6,6 @@ import type {
|
|
|
6
6
|
PollUpdatedFeedEvent,
|
|
7
7
|
WSEvent,
|
|
8
8
|
PollClosedFeedEvent,
|
|
9
|
-
PollVoteCastedFeedEvent,
|
|
10
|
-
PollVoteChangedFeedEvent,
|
|
11
|
-
PollVoteRemovedFeedEvent,
|
|
12
9
|
PollResponseData,
|
|
13
10
|
} from '../gen/models';
|
|
14
11
|
|
|
@@ -20,21 +17,14 @@ const isPollClosedEventEvent = (
|
|
|
20
17
|
e: WSEvent,
|
|
21
18
|
): e is { type: 'feeds.poll.closed' } & PollClosedFeedEvent =>
|
|
22
19
|
e.type === 'feeds.poll.closed';
|
|
23
|
-
const isPollVoteCastedEvent = (
|
|
24
|
-
e: WSEvent,
|
|
25
|
-
): e is { type: 'feeds.poll.vote_casted' } & PollVoteCastedFeedEvent =>
|
|
26
|
-
e.type === 'feeds.poll.vote_casted';
|
|
27
|
-
const isPollVoteChangedEvent = (
|
|
28
|
-
e: WSEvent,
|
|
29
|
-
): e is { type: 'feeds.poll.vote_changed' } & PollVoteChangedFeedEvent =>
|
|
30
|
-
e.type === 'feeds.poll.vote_changed';
|
|
31
|
-
const isPollVoteRemovedEvent = (
|
|
32
|
-
e: WSEvent,
|
|
33
|
-
): e is { type: 'feeds.poll.vote_removed' } & PollVoteRemovedFeedEvent =>
|
|
34
|
-
e.type === 'feeds.poll.vote_removed';
|
|
35
20
|
|
|
36
|
-
export
|
|
37
|
-
|
|
21
|
+
export type PollVotePayload = {
|
|
22
|
+
poll: PollResponseData;
|
|
23
|
+
poll_vote: PollVoteResponseData;
|
|
24
|
+
created_at: Date;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const isVoteAnswer = (vote: PollVoteResponseData) => !!vote?.answer_text;
|
|
38
28
|
|
|
39
29
|
export type PollAnswersQueryParams = QueryPollVotesRequest & {
|
|
40
30
|
poll_id: string;
|
|
@@ -126,28 +116,43 @@ export class StreamPoll {
|
|
|
126
116
|
});
|
|
127
117
|
};
|
|
128
118
|
|
|
129
|
-
public handleVoteCasted = (event:
|
|
119
|
+
public handleVoteCasted = (event: PollVotePayload) => {
|
|
130
120
|
if (event.poll?.id && event.poll.id !== this.id) return;
|
|
131
|
-
if (!isPollVoteCastedEvent(event as WSEvent)) return;
|
|
132
121
|
const currentState = this.data;
|
|
133
122
|
const isOwnVote =
|
|
134
123
|
event.poll_vote.user_id ===
|
|
135
124
|
this.client.state.getLatestValue().connected_user?.id;
|
|
125
|
+
|
|
126
|
+
if (isOwnVote) {
|
|
127
|
+
const alreadyApplied = isVoteAnswer(event.poll_vote)
|
|
128
|
+
? currentState.own_answer?.id === event.poll_vote.id
|
|
129
|
+
: !!event.poll_vote.option_id &&
|
|
130
|
+
currentState.own_votes_by_option_id[event.poll_vote.option_id]?.id ===
|
|
131
|
+
event.poll_vote.id;
|
|
132
|
+
if (alreadyApplied) return;
|
|
133
|
+
}
|
|
134
|
+
|
|
136
135
|
let latestAnswers = [...currentState.latest_answers];
|
|
137
136
|
let ownAnswer = currentState.own_answer;
|
|
138
|
-
|
|
137
|
+
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
139
138
|
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
140
139
|
|
|
141
140
|
if (isOwnVote) {
|
|
142
141
|
if (isVoteAnswer(event.poll_vote)) {
|
|
143
142
|
ownAnswer = event.poll_vote;
|
|
144
143
|
} else if (event.poll_vote.option_id) {
|
|
145
|
-
ownVotesByOptionId
|
|
144
|
+
ownVotesByOptionId = {
|
|
145
|
+
...ownVotesByOptionId,
|
|
146
|
+
[event.poll_vote.option_id]: event.poll_vote,
|
|
147
|
+
};
|
|
146
148
|
}
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
if (isVoteAnswer(event.poll_vote)) {
|
|
150
|
-
latestAnswers = [
|
|
152
|
+
latestAnswers = [
|
|
153
|
+
event.poll_vote,
|
|
154
|
+
...latestAnswers.filter((a) => a.id !== event.poll_vote.id),
|
|
155
|
+
];
|
|
151
156
|
} else {
|
|
152
157
|
maxVotedOptionIds = getMaxVotedOptionIds(
|
|
153
158
|
event.poll.vote_counts_by_option,
|
|
@@ -173,14 +178,23 @@ export class StreamPoll {
|
|
|
173
178
|
});
|
|
174
179
|
};
|
|
175
180
|
|
|
176
|
-
public handleVoteChanged = (event:
|
|
181
|
+
public handleVoteChanged = (event: PollVotePayload) => {
|
|
177
182
|
// this event is triggered only when event.poll.enforce_unique_vote === true
|
|
178
183
|
if (event.poll?.id && event.poll.id !== this.id) return;
|
|
179
|
-
if (!isPollVoteChangedEvent(event as WSEvent)) return;
|
|
180
184
|
const currentState = this.data;
|
|
181
185
|
const isOwnVote =
|
|
182
186
|
event.poll_vote.user_id ===
|
|
183
187
|
this.client.state.getLatestValue().connected_user?.id;
|
|
188
|
+
|
|
189
|
+
if (isOwnVote) {
|
|
190
|
+
const alreadyApplied = isVoteAnswer(event.poll_vote)
|
|
191
|
+
? currentState.own_answer?.id === event.poll_vote.id
|
|
192
|
+
: !!event.poll_vote.option_id &&
|
|
193
|
+
currentState.own_votes_by_option_id[event.poll_vote.option_id]?.id ===
|
|
194
|
+
event.poll_vote.id;
|
|
195
|
+
if (alreadyApplied) return;
|
|
196
|
+
}
|
|
197
|
+
|
|
184
198
|
let latestAnswers = [...currentState.latest_answers];
|
|
185
199
|
let ownAnswer = currentState.own_answer;
|
|
186
200
|
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
@@ -246,13 +260,20 @@ export class StreamPoll {
|
|
|
246
260
|
});
|
|
247
261
|
};
|
|
248
262
|
|
|
249
|
-
public handleVoteRemoved = (event:
|
|
263
|
+
public handleVoteRemoved = (event: PollVotePayload) => {
|
|
250
264
|
if (event.poll?.id && event.poll.id !== this.id) return;
|
|
251
|
-
if (!isPollVoteRemovedEvent(event as WSEvent)) return;
|
|
252
265
|
const currentState = this.data;
|
|
253
266
|
const isOwnVote =
|
|
254
267
|
event.poll_vote.user_id ===
|
|
255
268
|
this.client.state.getLatestValue().connected_user?.id;
|
|
269
|
+
|
|
270
|
+
if (isOwnVote) {
|
|
271
|
+
const alreadyApplied = isVoteAnswer(event.poll_vote)
|
|
272
|
+
? !currentState.own_answer
|
|
273
|
+
: !!event.poll_vote.option_id &&
|
|
274
|
+
!(event.poll_vote.option_id in currentState.own_votes_by_option_id);
|
|
275
|
+
if (alreadyApplied) return;
|
|
276
|
+
}
|
|
256
277
|
let latestAnswers = [...currentState.latest_answers];
|
|
257
278
|
let ownAnswer = currentState.own_answer;
|
|
258
279
|
const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
|
|
@@ -11,5 +11,7 @@ export const updateActivity = ({
|
|
|
11
11
|
...newActivtiy,
|
|
12
12
|
own_reactions: currentActivity.own_reactions,
|
|
13
13
|
own_bookmarks: currentActivity.own_bookmarks,
|
|
14
|
+
friend_reactions: currentActivity.friend_reactions,
|
|
15
|
+
friend_reaction_count: currentActivity.friend_reaction_count,
|
|
14
16
|
};
|
|
15
17
|
};
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
AddCommentRequest,
|
|
8
8
|
AddCommentResponse,
|
|
9
9
|
AddReactionRequest,
|
|
10
|
+
CastPollVoteRequest,
|
|
10
11
|
CreateGuestResponse,
|
|
11
12
|
DeleteActivityReactionResponse,
|
|
12
13
|
DeleteCommentReactionResponse,
|
|
@@ -22,6 +23,7 @@ import type {
|
|
|
22
23
|
ImageUploadRequest,
|
|
23
24
|
OwnBatchRequest,
|
|
24
25
|
PollResponse,
|
|
26
|
+
PollVoteResponse,
|
|
25
27
|
PollVotesResponse,
|
|
26
28
|
QueryFeedsRequest,
|
|
27
29
|
QueryPollVotesRequest,
|
|
@@ -352,17 +354,16 @@ export class FeedsClient extends FeedsApi {
|
|
|
352
354
|
|
|
353
355
|
public hydratePollCache(activities: ActivityResponse[]) {
|
|
354
356
|
for (const activity of activities) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
357
|
+
const polls = [activity.poll, activity.parent?.poll].filter((p) => !!p);
|
|
358
|
+
polls.forEach((pollResponse) => {
|
|
359
|
+
const pollFromCache = this.pollFromState(pollResponse.id);
|
|
360
|
+
if (!pollFromCache) {
|
|
361
|
+
const poll = new StreamPoll({ client: this, poll: pollResponse });
|
|
362
|
+
this.polls_by_id.set(poll.id, poll);
|
|
363
|
+
} else {
|
|
364
|
+
pollFromCache.reinitializeState(pollResponse);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
366
367
|
}
|
|
367
368
|
}
|
|
368
369
|
|
|
@@ -462,6 +463,46 @@ export class FeedsClient extends FeedsApi {
|
|
|
462
463
|
});
|
|
463
464
|
};
|
|
464
465
|
|
|
466
|
+
castPollVote = async (
|
|
467
|
+
request: CastPollVoteRequest & { activity_id: string; poll_id: string },
|
|
468
|
+
): Promise<StreamResponse<PollVoteResponse>> => {
|
|
469
|
+
const poll = this.pollFromState(request.poll_id);
|
|
470
|
+
const response = await super.castPollVote(request);
|
|
471
|
+
if (response.poll && response.vote && poll) {
|
|
472
|
+
const payload = {
|
|
473
|
+
poll: response.poll,
|
|
474
|
+
poll_vote: response.vote,
|
|
475
|
+
created_at: new Date(),
|
|
476
|
+
};
|
|
477
|
+
if (
|
|
478
|
+
poll.data.enforce_unique_vote &&
|
|
479
|
+
Object.keys(poll.data.own_votes_by_option_id).length > 0
|
|
480
|
+
) {
|
|
481
|
+
poll.handleVoteChanged(payload);
|
|
482
|
+
} else {
|
|
483
|
+
poll.handleVoteCasted(payload);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return response;
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
deletePollVote = async (request: {
|
|
490
|
+
activity_id: string;
|
|
491
|
+
poll_id: string;
|
|
492
|
+
vote_id: string;
|
|
493
|
+
user_id?: string;
|
|
494
|
+
}): Promise<StreamResponse<PollVoteResponse>> => {
|
|
495
|
+
const response = await super.deletePollVote(request);
|
|
496
|
+
if (response.poll && response.vote) {
|
|
497
|
+
this.pollFromState(request.poll_id)?.handleVoteRemoved({
|
|
498
|
+
poll: response.poll,
|
|
499
|
+
poll_vote: response.vote,
|
|
500
|
+
created_at: new Date(),
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
return response;
|
|
504
|
+
};
|
|
505
|
+
|
|
465
506
|
uploadFile = (
|
|
466
507
|
request?: Omit<FileUploadRequest, 'file'> & { file?: StreamFile | string },
|
|
467
508
|
) => {
|
package/src/gen/feeds/FeedApi.ts
CHANGED
|
@@ -10,6 +10,8 @@ import type {
|
|
|
10
10
|
PinActivityResponse,
|
|
11
11
|
QueryFeedMembersRequest,
|
|
12
12
|
QueryFeedMembersResponse,
|
|
13
|
+
QueryPinnedActivitiesRequest,
|
|
14
|
+
QueryPinnedActivitiesResponse,
|
|
13
15
|
RejectFeedMemberInviteRequest,
|
|
14
16
|
RejectFeedMemberInviteResponse,
|
|
15
17
|
Response,
|
|
@@ -127,6 +129,16 @@ export class FeedApi {
|
|
|
127
129
|
});
|
|
128
130
|
}
|
|
129
131
|
|
|
132
|
+
queryPinnedActivities(
|
|
133
|
+
request?: QueryPinnedActivitiesRequest,
|
|
134
|
+
): Promise<StreamResponse<QueryPinnedActivitiesResponse>> {
|
|
135
|
+
return this.feedsApi.queryPinnedActivities({
|
|
136
|
+
feed_id: this.id,
|
|
137
|
+
feed_group_id: this.group,
|
|
138
|
+
...request,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
130
142
|
stopWatching(request?: {
|
|
131
143
|
connection_id?: string;
|
|
132
144
|
}): Promise<StreamResponse<Response>> {
|
|
@@ -88,6 +88,8 @@ import type {
|
|
|
88
88
|
QueryFeedsResponse,
|
|
89
89
|
QueryFollowsRequest,
|
|
90
90
|
QueryFollowsResponse,
|
|
91
|
+
QueryPinnedActivitiesRequest,
|
|
92
|
+
QueryPinnedActivitiesResponse,
|
|
91
93
|
QueryPollVotesRequest,
|
|
92
94
|
QueryPollsRequest,
|
|
93
95
|
QueryPollsResponse,
|
|
@@ -1611,6 +1613,40 @@ export class FeedsApi {
|
|
|
1611
1613
|
return { ...response.body, metadata: response.metadata };
|
|
1612
1614
|
}
|
|
1613
1615
|
|
|
1616
|
+
async queryPinnedActivities(
|
|
1617
|
+
request: QueryPinnedActivitiesRequest & {
|
|
1618
|
+
feed_group_id: string;
|
|
1619
|
+
feed_id: string;
|
|
1620
|
+
},
|
|
1621
|
+
): Promise<StreamResponse<QueryPinnedActivitiesResponse>> {
|
|
1622
|
+
const pathParams = {
|
|
1623
|
+
feed_group_id: request?.feed_group_id,
|
|
1624
|
+
feed_id: request?.feed_id,
|
|
1625
|
+
};
|
|
1626
|
+
const body = {
|
|
1627
|
+
limit: request?.limit,
|
|
1628
|
+
next: request?.next,
|
|
1629
|
+
prev: request?.prev,
|
|
1630
|
+
sort: request?.sort,
|
|
1631
|
+
filter: request?.filter,
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1634
|
+
const response = await this.apiClient.sendRequest<
|
|
1635
|
+
StreamResponse<QueryPinnedActivitiesResponse>
|
|
1636
|
+
>(
|
|
1637
|
+
'POST',
|
|
1638
|
+
'/api/v2/feeds/feed_groups/{feed_group_id}/feeds/{feed_id}/pinned_activities/query',
|
|
1639
|
+
pathParams,
|
|
1640
|
+
undefined,
|
|
1641
|
+
body,
|
|
1642
|
+
'application/json',
|
|
1643
|
+
);
|
|
1644
|
+
|
|
1645
|
+
decoders.QueryPinnedActivitiesResponse?.(response.body);
|
|
1646
|
+
|
|
1647
|
+
return { ...response.body, metadata: response.metadata };
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1614
1650
|
async stopWatchingFeed(request: {
|
|
1615
1651
|
feed_group_id: string;
|
|
1616
1652
|
feed_id: string;
|
|
@@ -1713,6 +1713,13 @@ decoders.QueryModerationConfigsResponse = (input?: Record<string, any>) => {
|
|
|
1713
1713
|
return decode(typeMappings, input);
|
|
1714
1714
|
};
|
|
1715
1715
|
|
|
1716
|
+
decoders.QueryPinnedActivitiesResponse = (input?: Record<string, any>) => {
|
|
1717
|
+
const typeMappings: TypeMapping = {
|
|
1718
|
+
pinned_activities: { type: 'ActivityPinResponse', isSingle: false },
|
|
1719
|
+
};
|
|
1720
|
+
return decode(typeMappings, input);
|
|
1721
|
+
};
|
|
1722
|
+
|
|
1716
1723
|
decoders.QueryPollsResponse = (input?: Record<string, any>) => {
|
|
1717
1724
|
const typeMappings: TypeMapping = {
|
|
1718
1725
|
polls: { type: 'PollResponseData', isSingle: false },
|
package/src/gen/models/index.ts
CHANGED
|
@@ -4952,6 +4952,28 @@ export interface QueryModerationConfigsResponse {
|
|
|
4952
4952
|
prev?: string;
|
|
4953
4953
|
}
|
|
4954
4954
|
|
|
4955
|
+
export interface QueryPinnedActivitiesRequest {
|
|
4956
|
+
limit?: number;
|
|
4957
|
+
|
|
4958
|
+
next?: string;
|
|
4959
|
+
|
|
4960
|
+
prev?: string;
|
|
4961
|
+
|
|
4962
|
+
sort?: SortParamRequest[];
|
|
4963
|
+
|
|
4964
|
+
filter?: Record<string, any>;
|
|
4965
|
+
}
|
|
4966
|
+
|
|
4967
|
+
export interface QueryPinnedActivitiesResponse {
|
|
4968
|
+
duration: string;
|
|
4969
|
+
|
|
4970
|
+
pinned_activities: ActivityPinResponse[];
|
|
4971
|
+
|
|
4972
|
+
next?: string;
|
|
4973
|
+
|
|
4974
|
+
prev?: string;
|
|
4975
|
+
}
|
|
4976
|
+
|
|
4955
4977
|
export interface QueryPollVotesRequest {
|
|
4956
4978
|
limit?: number;
|
|
4957
4979
|
|