@stream-io/feeds-client 0.1.4 → 0.1.6
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/@react-bindings/hooks/client-state-hooks/index.ts +2 -0
- package/@react-bindings/hooks/feed-state-hooks/index.ts +7 -0
- package/@react-bindings/hooks/internal/index.ts +1 -0
- package/@react-bindings/hooks/util/index.ts +1 -0
- package/@react-bindings/index.ts +6 -3
- package/CHANGELOG.md +31 -0
- package/dist/@react-bindings/contexts/StreamFeedContext.d.ts +12 -0
- package/dist/@react-bindings/hooks/client-state-hooks/index.d.ts +2 -0
- package/dist/@react-bindings/hooks/client-state-hooks/useClientConnectedUser.d.ts +4 -0
- package/dist/@react-bindings/hooks/client-state-hooks/useWsConnectionState.d.ts +6 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/index.d.ts +7 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useComments.d.ts +19 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useFeedActivities.d.ts +11 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useFeedMetadata.d.ts +12 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useFollowers.d.ts +16 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useFollowing.d.ts +16 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useOwnCapabilities.d.ts +33 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useOwnFollows.d.ts +8 -0
- package/dist/@react-bindings/hooks/internal/index.d.ts +1 -0
- package/dist/@react-bindings/hooks/internal/useStableCallback.d.ts +25 -0
- package/dist/@react-bindings/hooks/util/index.d.ts +1 -0
- package/dist/@react-bindings/hooks/util/useReactionActions.d.ts +17 -0
- package/dist/@react-bindings/index.d.ts +5 -3
- package/dist/@react-bindings/wrappers/StreamFeed.d.ts +12 -0
- package/dist/index-react-bindings.browser.cjs +521 -210
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +514 -212
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +521 -210
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +514 -212
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +212 -106
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +209 -107
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +212 -106
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +209 -107
- package/dist/index.node.js.map +1 -1
- package/dist/src/Feed.d.ts +7 -3
- package/dist/src/FeedsClient.d.ts +6 -5
- package/dist/src/types.d.ts +7 -0
- package/dist/src/utils.d.ts +9 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -2
- package/src/Feed.ts +214 -97
- package/src/FeedsClient.ts +22 -12
- package/src/common/ActivitySearchSource.ts +5 -5
- package/src/common/ApiClient.ts +1 -1
- package/src/common/FeedSearchSource.ts +1 -1
- package/src/common/Poll.ts +35 -10
- package/src/common/TokenManager.ts +2 -3
- package/src/common/UserSearchSource.ts +1 -1
- package/src/common/real-time/StableWSConnection.ts +4 -1
- package/src/state-updates/bookmark-utils.test.ts +134 -8
- package/src/state-updates/bookmark-utils.ts +17 -7
- package/src/types.ts +12 -1
- package/src/utils.ts +25 -1
- package/dist/@react-bindings/hooks/clientStateHooks.d.ts +0 -10
- package/dist/@react-bindings/hooks/useComments.d.ts +0 -12
- package/dist/@react-bindings/hooks/useOwnCapabilities.d.ts +0 -33
package/dist/index.browser.cjs
CHANGED
|
@@ -2688,6 +2688,13 @@ function removeConnectionEventListeners(cb) {
|
|
|
2688
2688
|
window.removeEventListener('online', cb);
|
|
2689
2689
|
}
|
|
2690
2690
|
}
|
|
2691
|
+
const streamDevToken = (userId) => {
|
|
2692
|
+
return [
|
|
2693
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', // {"alg": "HS256", "typ": "JWT"}
|
|
2694
|
+
window.btoa(JSON.stringify({ user_id: userId })),
|
|
2695
|
+
'devtoken', // hardcoded signature
|
|
2696
|
+
].join('.');
|
|
2697
|
+
};
|
|
2691
2698
|
const debounce = (fn, timeout = 0, { leading = false, trailing = true, } = {}) => {
|
|
2692
2699
|
let runningTimeout = null;
|
|
2693
2700
|
let argsForTrailingExecution = null;
|
|
@@ -2784,7 +2791,7 @@ class TokenManager {
|
|
|
2784
2791
|
}
|
|
2785
2792
|
catch (e) {
|
|
2786
2793
|
const numberOfFailures = ++previousFailuresCount;
|
|
2787
|
-
await sleep(
|
|
2794
|
+
await sleep(1000);
|
|
2788
2795
|
if (numberOfFailures === 3) {
|
|
2789
2796
|
this.loadTokenPromise = null;
|
|
2790
2797
|
return reject(new Error(`Stream error: tried to get token ${numberOfFailures} times, but it failed with ${e}. Check your token provider`, { cause: e }));
|
|
@@ -2997,7 +3004,10 @@ class StableWSConnection {
|
|
|
2997
3004
|
this.onmessage = (wsID, event) => {
|
|
2998
3005
|
if (this.wsID !== wsID)
|
|
2999
3006
|
return;
|
|
3000
|
-
this._log('onmessage() - onmessage callback', {
|
|
3007
|
+
this._log('onmessage() - onmessage callback', {
|
|
3008
|
+
event: { ...event, data: JSON.parse(event.data) },
|
|
3009
|
+
wsID,
|
|
3010
|
+
});
|
|
3001
3011
|
let data = typeof event.data === 'string' ? JSON.parse(event.data) : null;
|
|
3002
3012
|
this.decoders.forEach((decode) => {
|
|
3003
3013
|
data = decode(data);
|
|
@@ -3629,7 +3639,7 @@ class ApiClient {
|
|
|
3629
3639
|
rate_limit: getRateLimitFromResponseHeader(response_headers),
|
|
3630
3640
|
};
|
|
3631
3641
|
};
|
|
3632
|
-
this.baseUrl = options?.base_url ?? 'https://
|
|
3642
|
+
this.baseUrl = options?.base_url ?? 'https://feeds.stream-io-api.com';
|
|
3633
3643
|
this.timeout = options?.timeout ?? 3000;
|
|
3634
3644
|
this.axiosInstance = axios.create({
|
|
3635
3645
|
baseURL: this.baseUrl,
|
|
@@ -3923,6 +3933,13 @@ const removeReactionFromActivities = (event, activities, isCurrentUser) => {
|
|
|
3923
3933
|
return updateActivityInActivities$1(updatedActivity, activities);
|
|
3924
3934
|
};
|
|
3925
3935
|
|
|
3936
|
+
// Helper function to check if two bookmarks are the same
|
|
3937
|
+
// A bookmark is identified by activity_id + folder_id + user_id
|
|
3938
|
+
const isSameBookmark = (bookmark1, bookmark2) => {
|
|
3939
|
+
return (bookmark1.user.id === bookmark2.user.id &&
|
|
3940
|
+
bookmark1.activity.id === bookmark2.activity.id &&
|
|
3941
|
+
bookmark1.folder?.id === bookmark2.folder?.id);
|
|
3942
|
+
};
|
|
3926
3943
|
const updateActivityInActivities = (updatedActivity, activities) => {
|
|
3927
3944
|
const index = activities.findIndex((a) => a.id === updatedActivity.id);
|
|
3928
3945
|
if (index !== -1) {
|
|
@@ -3949,8 +3966,7 @@ const addBookmarkToActivity = (event, activity, isCurrentUser) => {
|
|
|
3949
3966
|
const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
|
|
3950
3967
|
// Update own_bookmarks if the bookmark is from the current user
|
|
3951
3968
|
const ownBookmarks = isCurrentUser
|
|
3952
|
-
? (activity.own_bookmarks || []).filter((bookmark) => bookmark
|
|
3953
|
-
bookmark.activity.id !== event.bookmark.activity.id)
|
|
3969
|
+
? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
|
|
3954
3970
|
: activity.own_bookmarks;
|
|
3955
3971
|
return {
|
|
3956
3972
|
...activity,
|
|
@@ -3962,8 +3978,7 @@ const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
|
|
|
3962
3978
|
// Update own_bookmarks if the bookmark is from the current user
|
|
3963
3979
|
let ownBookmarks = activity.own_bookmarks || [];
|
|
3964
3980
|
if (isCurrentUser) {
|
|
3965
|
-
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => bookmark
|
|
3966
|
-
bookmark.activity.id === event.bookmark.activity.id);
|
|
3981
|
+
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
|
|
3967
3982
|
if (bookmarkIndex !== -1) {
|
|
3968
3983
|
ownBookmarks = [...ownBookmarks];
|
|
3969
3984
|
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
@@ -4012,8 +4027,22 @@ const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
|
4012
4027
|
return updateActivityInActivities(updatedActivity, activities);
|
|
4013
4028
|
};
|
|
4014
4029
|
|
|
4015
|
-
const
|
|
4016
|
-
|
|
4030
|
+
const isImageFile = (file) => {
|
|
4031
|
+
// photoshop files begin with 'image/'
|
|
4032
|
+
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
4033
|
+
};
|
|
4034
|
+
const isVideoFile = (file) => {
|
|
4035
|
+
return file.type.startsWith('video/');
|
|
4036
|
+
};
|
|
4037
|
+
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4038
|
+
typeof cursor === 'string';
|
|
4039
|
+
const isCommentResponse = (entity) => {
|
|
4040
|
+
return typeof entity?.object_id === 'string';
|
|
4041
|
+
};
|
|
4042
|
+
const Constants = {
|
|
4043
|
+
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4044
|
+
};
|
|
4045
|
+
|
|
4017
4046
|
class Feed extends FeedApi {
|
|
4018
4047
|
constructor(client, groupId, id, data) {
|
|
4019
4048
|
// Need this ugly cast because fileUpload endpoints :(
|
|
@@ -4038,7 +4067,7 @@ class Feed extends FeedApi {
|
|
|
4038
4067
|
},
|
|
4039
4068
|
'feeds.activity.reaction.added': (event) => {
|
|
4040
4069
|
const currentActivities = this.currentState.activities;
|
|
4041
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4070
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4042
4071
|
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4043
4072
|
const result = addReactionToActivities(event, currentActivities, isCurrentUser);
|
|
4044
4073
|
if (result.changed) {
|
|
@@ -4047,7 +4076,7 @@ class Feed extends FeedApi {
|
|
|
4047
4076
|
},
|
|
4048
4077
|
'feeds.activity.reaction.deleted': (event) => {
|
|
4049
4078
|
const currentActivities = this.currentState.activities;
|
|
4050
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4079
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4051
4080
|
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4052
4081
|
const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
|
|
4053
4082
|
if (result.changed) {
|
|
@@ -4086,7 +4115,7 @@ class Feed extends FeedApi {
|
|
|
4086
4115
|
const entityState = currentState.comments_by_entity_id[forId];
|
|
4087
4116
|
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4088
4117
|
if (entityState?.pagination?.sort === 'last' &&
|
|
4089
|
-
entityState?.pagination.next
|
|
4118
|
+
!checkHasAnotherPage(entityState.comments, entityState?.pagination.next)) {
|
|
4090
4119
|
newComments.unshift(comment);
|
|
4091
4120
|
}
|
|
4092
4121
|
else if (entityState?.pagination?.sort === 'first') {
|
|
@@ -4173,7 +4202,7 @@ class Feed extends FeedApi {
|
|
|
4173
4202
|
...currentState,
|
|
4174
4203
|
...event.follow.source_feed,
|
|
4175
4204
|
};
|
|
4176
|
-
if (currentState.following_pagination?.next
|
|
4205
|
+
if (!checkHasAnotherPage(currentState.following, currentState.following_pagination?.next)) {
|
|
4177
4206
|
// TODO: respect sort
|
|
4178
4207
|
newState.following = currentState.following
|
|
4179
4208
|
? currentState.following.concat(event.follow)
|
|
@@ -4186,7 +4215,7 @@ class Feed extends FeedApi {
|
|
|
4186
4215
|
// someone followed this feed
|
|
4187
4216
|
event.follow.target_feed.fid === this.fid) {
|
|
4188
4217
|
const source = event.follow.source_feed;
|
|
4189
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4218
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4190
4219
|
this.state.next((currentState) => {
|
|
4191
4220
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4192
4221
|
if (source.created_by.id === connectedUser?.id) {
|
|
@@ -4194,7 +4223,7 @@ class Feed extends FeedApi {
|
|
|
4194
4223
|
? currentState.own_follows.concat(event.follow)
|
|
4195
4224
|
: [event.follow];
|
|
4196
4225
|
}
|
|
4197
|
-
if (currentState.followers_pagination?.next
|
|
4226
|
+
if (!checkHasAnotherPage(currentState.followers, currentState.followers_pagination?.next)) {
|
|
4198
4227
|
// TODO: respect sort
|
|
4199
4228
|
newState.followers = currentState.followers
|
|
4200
4229
|
? currentState.followers.concat(event.follow)
|
|
@@ -4219,7 +4248,7 @@ class Feed extends FeedApi {
|
|
|
4219
4248
|
// someone unfollowed this feed
|
|
4220
4249
|
event.follow.target_feed.fid === this.fid) {
|
|
4221
4250
|
const source = event.follow.source_feed;
|
|
4222
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4251
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4223
4252
|
this.state.next((currentState) => {
|
|
4224
4253
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4225
4254
|
if (source.created_by.id === connectedUser?.id) {
|
|
@@ -4235,40 +4264,60 @@ class Feed extends FeedApi {
|
|
|
4235
4264
|
'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
|
|
4236
4265
|
'feeds.comment.reaction.updated': Feed.noop,
|
|
4237
4266
|
'feeds.feed_member.added': (event) => {
|
|
4238
|
-
const {
|
|
4239
|
-
// do not add a member if the pagination has reached the end of the list
|
|
4240
|
-
if (this.currentState.member_pagination?.next !== END_OF_LIST)
|
|
4241
|
-
return;
|
|
4267
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4242
4268
|
this.state.next((currentState) => {
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4269
|
+
let newState;
|
|
4270
|
+
if (!checkHasAnotherPage(currentState.members, currentState.member_pagination?.next)) {
|
|
4271
|
+
newState ?? (newState = {
|
|
4272
|
+
...currentState,
|
|
4273
|
+
});
|
|
4274
|
+
newState.members = newState.members?.concat(event.member) ?? [
|
|
4275
|
+
event.member,
|
|
4276
|
+
];
|
|
4277
|
+
}
|
|
4278
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4279
|
+
newState ?? (newState = {
|
|
4280
|
+
...currentState,
|
|
4281
|
+
});
|
|
4282
|
+
newState.own_membership = event.member;
|
|
4283
|
+
}
|
|
4284
|
+
return newState ?? currentState;
|
|
4250
4285
|
});
|
|
4251
4286
|
},
|
|
4252
4287
|
'feeds.feed_member.removed': (event) => {
|
|
4288
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4253
4289
|
this.state.next((currentState) => {
|
|
4254
|
-
|
|
4290
|
+
const newState = {
|
|
4255
4291
|
...currentState,
|
|
4256
4292
|
members: currentState.members?.filter((member) => member.user.id !== event.user?.id),
|
|
4257
4293
|
};
|
|
4294
|
+
if (connectedUser?.id === event.member_id) {
|
|
4295
|
+
delete newState.own_membership;
|
|
4296
|
+
}
|
|
4297
|
+
return newState;
|
|
4258
4298
|
});
|
|
4259
4299
|
},
|
|
4260
4300
|
'feeds.feed_member.updated': (event) => {
|
|
4301
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4261
4302
|
this.state.next((currentState) => {
|
|
4262
4303
|
const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
|
|
4304
|
+
let newState;
|
|
4263
4305
|
if (memberIndex !== -1) {
|
|
4306
|
+
// if there's an index, there's a member to update
|
|
4264
4307
|
const newMembers = [...currentState.members];
|
|
4265
4308
|
newMembers[memberIndex] = event.member;
|
|
4266
|
-
|
|
4309
|
+
newState ?? (newState = {
|
|
4267
4310
|
...currentState,
|
|
4268
|
-
|
|
4269
|
-
|
|
4311
|
+
});
|
|
4312
|
+
newState.members = newMembers;
|
|
4270
4313
|
}
|
|
4271
|
-
|
|
4314
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4315
|
+
newState ?? (newState = {
|
|
4316
|
+
...currentState,
|
|
4317
|
+
});
|
|
4318
|
+
newState.own_membership = event.member;
|
|
4319
|
+
}
|
|
4320
|
+
return newState ?? currentState;
|
|
4272
4321
|
});
|
|
4273
4322
|
},
|
|
4274
4323
|
// the poll events should be removed from here
|
|
@@ -4314,7 +4363,7 @@ class Feed extends FeedApi {
|
|
|
4314
4363
|
}
|
|
4315
4364
|
handleCommentReactionEvent(event) {
|
|
4316
4365
|
const { comment, reaction } = event;
|
|
4317
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4366
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4318
4367
|
this.state.next((currentState) => {
|
|
4319
4368
|
const forId = comment.parent_id ?? comment.object_id;
|
|
4320
4369
|
const entityState = currentState.comments_by_entity_id[forId];
|
|
@@ -4394,29 +4443,6 @@ class Feed extends FeedApi {
|
|
|
4394
4443
|
...currentState,
|
|
4395
4444
|
...responseCopy,
|
|
4396
4445
|
};
|
|
4397
|
-
// if there is no next cursor, set it to END_OF_LIST
|
|
4398
|
-
// request has to have a limit set for this to work
|
|
4399
|
-
if ((request?.followers_pagination?.limit ?? 0) > 0 &&
|
|
4400
|
-
typeof nextState.followers_pagination?.next === 'undefined') {
|
|
4401
|
-
nextState.followers_pagination = {
|
|
4402
|
-
...nextState.followers_pagination,
|
|
4403
|
-
next: END_OF_LIST,
|
|
4404
|
-
};
|
|
4405
|
-
}
|
|
4406
|
-
if ((request?.following_pagination?.limit ?? 0) > 0 &&
|
|
4407
|
-
typeof nextState.following_pagination?.next === 'undefined') {
|
|
4408
|
-
nextState.following_pagination = {
|
|
4409
|
-
...nextState.following_pagination,
|
|
4410
|
-
next: END_OF_LIST,
|
|
4411
|
-
};
|
|
4412
|
-
}
|
|
4413
|
-
if ((request?.member_pagination?.limit ?? 0) > 0 &&
|
|
4414
|
-
typeof nextState.member_pagination?.next === 'undefined') {
|
|
4415
|
-
nextState.member_pagination = {
|
|
4416
|
-
...nextState.member_pagination,
|
|
4417
|
-
next: END_OF_LIST,
|
|
4418
|
-
};
|
|
4419
|
-
}
|
|
4420
4446
|
if (!request?.followers_pagination?.limit) {
|
|
4421
4447
|
delete nextState.followers;
|
|
4422
4448
|
}
|
|
@@ -4439,7 +4465,7 @@ class Feed extends FeedApi {
|
|
|
4439
4465
|
}
|
|
4440
4466
|
handleBookmarkAdded(event) {
|
|
4441
4467
|
const currentActivities = this.currentState.activities;
|
|
4442
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
4468
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4443
4469
|
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4444
4470
|
const result = addBookmarkToActivities(event, currentActivities, isCurrentUser);
|
|
4445
4471
|
if (result.changed) {
|
|
@@ -4448,7 +4474,7 @@ class Feed extends FeedApi {
|
|
|
4448
4474
|
}
|
|
4449
4475
|
handleBookmarkDeleted(event) {
|
|
4450
4476
|
const currentActivities = this.currentState.activities;
|
|
4451
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
4477
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4452
4478
|
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4453
4479
|
const result = removeBookmarkFromActivities(event, currentActivities, isCurrentUser);
|
|
4454
4480
|
if (result.changed) {
|
|
@@ -4457,7 +4483,7 @@ class Feed extends FeedApi {
|
|
|
4457
4483
|
}
|
|
4458
4484
|
handleBookmarkUpdated(event) {
|
|
4459
4485
|
const currentActivities = this.currentState.activities;
|
|
4460
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
4486
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4461
4487
|
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4462
4488
|
const result = updateBookmarkInActivities(event, currentActivities, isCurrentUser);
|
|
4463
4489
|
if (result.changed) {
|
|
@@ -4507,6 +4533,7 @@ class Feed extends FeedApi {
|
|
|
4507
4533
|
});
|
|
4508
4534
|
}
|
|
4509
4535
|
async loadNextPageComments({ forId, base, sort, parentId, }) {
|
|
4536
|
+
let error;
|
|
4510
4537
|
try {
|
|
4511
4538
|
this.state.next((currentState) => ({
|
|
4512
4539
|
...currentState,
|
|
@@ -4521,7 +4548,7 @@ class Feed extends FeedApi {
|
|
|
4521
4548
|
},
|
|
4522
4549
|
},
|
|
4523
4550
|
}));
|
|
4524
|
-
const { next: newNextCursor
|
|
4551
|
+
const { next: newNextCursor, comments } = await base();
|
|
4525
4552
|
this.state.next((currentState) => {
|
|
4526
4553
|
const newPagination = {
|
|
4527
4554
|
...currentState.comments_by_entity_id[forId]?.pagination,
|
|
@@ -4546,9 +4573,8 @@ class Feed extends FeedApi {
|
|
|
4546
4573
|
};
|
|
4547
4574
|
});
|
|
4548
4575
|
}
|
|
4549
|
-
catch (
|
|
4550
|
-
|
|
4551
|
-
// TODO: figure out how to handle errorss
|
|
4576
|
+
catch (e) {
|
|
4577
|
+
error = e;
|
|
4552
4578
|
}
|
|
4553
4579
|
finally {
|
|
4554
4580
|
this.state.next((currentState) => ({
|
|
@@ -4565,15 +4591,21 @@ class Feed extends FeedApi {
|
|
|
4565
4591
|
},
|
|
4566
4592
|
}));
|
|
4567
4593
|
}
|
|
4594
|
+
if (error) {
|
|
4595
|
+
throw error;
|
|
4596
|
+
}
|
|
4568
4597
|
}
|
|
4569
4598
|
async loadNextPageActivityComments(activity, request) {
|
|
4570
|
-
const
|
|
4571
|
-
const
|
|
4572
|
-
const
|
|
4573
|
-
const
|
|
4574
|
-
const
|
|
4575
|
-
|
|
4599
|
+
const currentEntityState = this.currentState.comments_by_entity_id[activity.id];
|
|
4600
|
+
const currentPagination = currentEntityState?.pagination;
|
|
4601
|
+
const currentNextCursor = currentPagination?.next;
|
|
4602
|
+
const currentSort = currentPagination?.sort;
|
|
4603
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
4604
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4605
|
+
if (isLoading ||
|
|
4606
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4576
4607
|
return;
|
|
4608
|
+
}
|
|
4577
4609
|
await this.loadNextPageComments({
|
|
4578
4610
|
forId: activity.id,
|
|
4579
4611
|
base: () => this.client.getComments({
|
|
@@ -4587,20 +4619,25 @@ class Feed extends FeedApi {
|
|
|
4587
4619
|
});
|
|
4588
4620
|
}
|
|
4589
4621
|
async loadNextPageCommentReplies(comment, request) {
|
|
4590
|
-
const
|
|
4591
|
-
const
|
|
4592
|
-
const
|
|
4593
|
-
const
|
|
4594
|
-
const
|
|
4595
|
-
|
|
4622
|
+
const currentEntityState = this.currentState.comments_by_entity_id[comment.id];
|
|
4623
|
+
const currentPagination = currentEntityState?.pagination;
|
|
4624
|
+
const currentNextCursor = currentPagination?.next;
|
|
4625
|
+
const currentSort = currentPagination?.sort;
|
|
4626
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
4627
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4628
|
+
if (isLoading ||
|
|
4629
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4596
4630
|
return;
|
|
4631
|
+
}
|
|
4597
4632
|
await this.loadNextPageComments({
|
|
4598
4633
|
forId: comment.id,
|
|
4599
4634
|
base: () => this.client.getCommentReplies({
|
|
4600
4635
|
...request,
|
|
4601
4636
|
comment_id: comment.id,
|
|
4602
4637
|
// use known sort first (prevents broken pagination)
|
|
4603
|
-
sort: currentSort ??
|
|
4638
|
+
sort: currentSort ??
|
|
4639
|
+
request?.sort ??
|
|
4640
|
+
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
4604
4641
|
next: currentNextCursor,
|
|
4605
4642
|
}),
|
|
4606
4643
|
parentId: comment.parent_id ?? comment.object_id,
|
|
@@ -4610,10 +4647,14 @@ class Feed extends FeedApi {
|
|
|
4610
4647
|
async loadNextPageFollows(type, request) {
|
|
4611
4648
|
const paginationKey = `${type}_pagination`;
|
|
4612
4649
|
const method = `query${capitalize(type)}`;
|
|
4650
|
+
const currentFollows = this.currentState[type];
|
|
4613
4651
|
const currentNextCursor = this.currentState[paginationKey]?.next;
|
|
4614
4652
|
const isLoading = this.currentState[paginationKey]?.loading_next_page;
|
|
4615
|
-
|
|
4653
|
+
const sort = this.currentState[paginationKey]?.sort ?? request.sort;
|
|
4654
|
+
let error;
|
|
4655
|
+
if (isLoading || !checkHasAnotherPage(currentFollows, currentNextCursor)) {
|
|
4616
4656
|
return;
|
|
4657
|
+
}
|
|
4617
4658
|
try {
|
|
4618
4659
|
this.state.next((currentState) => {
|
|
4619
4660
|
return {
|
|
@@ -4624,9 +4665,10 @@ class Feed extends FeedApi {
|
|
|
4624
4665
|
},
|
|
4625
4666
|
};
|
|
4626
4667
|
});
|
|
4627
|
-
const { next: newNextCursor
|
|
4668
|
+
const { next: newNextCursor, follows } = await this[method]({
|
|
4628
4669
|
...request,
|
|
4629
4670
|
next: currentNextCursor,
|
|
4671
|
+
sort,
|
|
4630
4672
|
});
|
|
4631
4673
|
this.state.next((currentState) => ({
|
|
4632
4674
|
...currentState,
|
|
@@ -4636,12 +4678,12 @@ class Feed extends FeedApi {
|
|
|
4636
4678
|
[paginationKey]: {
|
|
4637
4679
|
...currentState[paginationKey],
|
|
4638
4680
|
next: newNextCursor,
|
|
4681
|
+
sort,
|
|
4639
4682
|
},
|
|
4640
4683
|
}));
|
|
4641
4684
|
}
|
|
4642
|
-
catch (
|
|
4643
|
-
|
|
4644
|
-
// TODO: figure out how to handle errorss
|
|
4685
|
+
catch (e) {
|
|
4686
|
+
error = e;
|
|
4645
4687
|
}
|
|
4646
4688
|
finally {
|
|
4647
4689
|
this.state.next((currentState) => {
|
|
@@ -4654,6 +4696,9 @@ class Feed extends FeedApi {
|
|
|
4654
4696
|
};
|
|
4655
4697
|
});
|
|
4656
4698
|
}
|
|
4699
|
+
if (error) {
|
|
4700
|
+
throw error;
|
|
4701
|
+
}
|
|
4657
4702
|
}
|
|
4658
4703
|
async loadNextPageFollowers(request) {
|
|
4659
4704
|
await this.loadNextPageFollows('followers', request);
|
|
@@ -4661,6 +4706,59 @@ class Feed extends FeedApi {
|
|
|
4661
4706
|
async loadNextPageFollowing(request) {
|
|
4662
4707
|
await this.loadNextPageFollows('following', request);
|
|
4663
4708
|
}
|
|
4709
|
+
async loadNextPageMembers(request) {
|
|
4710
|
+
const currentMembers = this.currentState.members;
|
|
4711
|
+
const currentNextCursor = this.currentState.member_pagination?.next;
|
|
4712
|
+
const isLoading = this.currentState.member_pagination?.loading_next_page;
|
|
4713
|
+
const sort = this.currentState.member_pagination?.sort ?? request.sort;
|
|
4714
|
+
let error;
|
|
4715
|
+
if (isLoading || !checkHasAnotherPage(currentMembers, currentNextCursor)) {
|
|
4716
|
+
return;
|
|
4717
|
+
}
|
|
4718
|
+
try {
|
|
4719
|
+
this.state.next((currentState) => ({
|
|
4720
|
+
...currentState,
|
|
4721
|
+
member_pagination: {
|
|
4722
|
+
...currentState.member_pagination,
|
|
4723
|
+
loading_next_page: true,
|
|
4724
|
+
},
|
|
4725
|
+
}));
|
|
4726
|
+
const { next: newNextCursor, members } = await this.client.queryFeedMembers({
|
|
4727
|
+
...request,
|
|
4728
|
+
sort,
|
|
4729
|
+
feed_id: this.id,
|
|
4730
|
+
feed_group_id: this.group,
|
|
4731
|
+
next: currentNextCursor,
|
|
4732
|
+
});
|
|
4733
|
+
this.state.next((currentState) => ({
|
|
4734
|
+
...currentState,
|
|
4735
|
+
members: currentState.members
|
|
4736
|
+
? currentState.members.concat(members)
|
|
4737
|
+
: members,
|
|
4738
|
+
member_pagination: {
|
|
4739
|
+
...currentState.member_pagination,
|
|
4740
|
+
next: newNextCursor,
|
|
4741
|
+
// set sort if not defined yet
|
|
4742
|
+
sort: currentState.member_pagination?.sort ?? request.sort,
|
|
4743
|
+
},
|
|
4744
|
+
}));
|
|
4745
|
+
}
|
|
4746
|
+
catch (e) {
|
|
4747
|
+
error = e;
|
|
4748
|
+
}
|
|
4749
|
+
finally {
|
|
4750
|
+
this.state.next((currentState) => ({
|
|
4751
|
+
...currentState,
|
|
4752
|
+
member_pagination: {
|
|
4753
|
+
...currentState.member_pagination,
|
|
4754
|
+
loading_next_page: false,
|
|
4755
|
+
},
|
|
4756
|
+
}));
|
|
4757
|
+
}
|
|
4758
|
+
if (error) {
|
|
4759
|
+
throw error;
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4664
4762
|
/**
|
|
4665
4763
|
* Method which queries followers of this feed (feeds which target this feed).
|
|
4666
4764
|
*
|
|
@@ -4940,7 +5038,8 @@ class StreamPoll {
|
|
|
4940
5038
|
if (!isPollVoteCastedEvent(event))
|
|
4941
5039
|
return;
|
|
4942
5040
|
const currentState = this.data;
|
|
4943
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5041
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
5042
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4944
5043
|
let latestAnswers = [...currentState.latest_answers];
|
|
4945
5044
|
let ownAnswer = currentState.own_answer;
|
|
4946
5045
|
const ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
@@ -4964,7 +5063,7 @@ class StreamPoll {
|
|
|
4964
5063
|
else {
|
|
4965
5064
|
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4966
5065
|
}
|
|
4967
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option } = event.poll;
|
|
5066
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4968
5067
|
this.state.partialNext({
|
|
4969
5068
|
answers_count,
|
|
4970
5069
|
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
@@ -4985,7 +5084,8 @@ class StreamPoll {
|
|
|
4985
5084
|
if (!isPollVoteChangedEvent(event))
|
|
4986
5085
|
return;
|
|
4987
5086
|
const currentState = this.data;
|
|
4988
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5087
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
5088
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4989
5089
|
let latestAnswers = [...currentState.latest_answers];
|
|
4990
5090
|
let ownAnswer = currentState.own_answer;
|
|
4991
5091
|
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
@@ -5032,7 +5132,7 @@ class StreamPoll {
|
|
|
5032
5132
|
else {
|
|
5033
5133
|
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
5034
5134
|
}
|
|
5035
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option } = event.poll;
|
|
5135
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
5036
5136
|
this.state.partialNext({
|
|
5037
5137
|
answers_count,
|
|
5038
5138
|
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
@@ -5052,7 +5152,8 @@ class StreamPoll {
|
|
|
5052
5152
|
if (!isPollVoteRemovedEvent(event))
|
|
5053
5153
|
return;
|
|
5054
5154
|
const currentState = this.data;
|
|
5055
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5155
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
5156
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
5056
5157
|
let latestAnswers = [...currentState.latest_answers];
|
|
5057
5158
|
let ownAnswer = currentState.own_answer;
|
|
5058
5159
|
const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
|
|
@@ -5070,7 +5171,7 @@ class StreamPoll {
|
|
|
5070
5171
|
delete ownVotesByOptionId[event.poll_vote.option_id];
|
|
5071
5172
|
}
|
|
5072
5173
|
}
|
|
5073
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option } = event.poll;
|
|
5174
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
5074
5175
|
this.state.partialNext({
|
|
5075
5176
|
answers_count,
|
|
5076
5177
|
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
@@ -5128,7 +5229,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5128
5229
|
this.healthyConnectionChangedEventCount = 0;
|
|
5129
5230
|
this.pollFromState = (id) => this.polls_by_id.get(id);
|
|
5130
5231
|
this.connectUser = async (user, tokenProvider) => {
|
|
5131
|
-
if (this.state.getLatestValue().
|
|
5232
|
+
if (this.state.getLatestValue().connected_user !== undefined ||
|
|
5132
5233
|
this.wsConnection) {
|
|
5133
5234
|
throw new Error(`Can't connect a new user, call "disconnectUser" first`);
|
|
5134
5235
|
}
|
|
@@ -5142,8 +5243,8 @@ class FeedsClient extends FeedsApi {
|
|
|
5142
5243
|
this.wsConnection.on('all', (event) => this.eventDispatcher.dispatch(event));
|
|
5143
5244
|
const connectedEvent = await this.wsConnection.connect();
|
|
5144
5245
|
this.state.partialNext({
|
|
5145
|
-
|
|
5146
|
-
|
|
5246
|
+
connected_user: connectedEvent?.me,
|
|
5247
|
+
is_ws_connection_healthy: !!this.wsConnection?.isHealthy,
|
|
5147
5248
|
});
|
|
5148
5249
|
}
|
|
5149
5250
|
catch (err) {
|
|
@@ -5151,6 +5252,9 @@ class FeedsClient extends FeedsApi {
|
|
|
5151
5252
|
throw err;
|
|
5152
5253
|
}
|
|
5153
5254
|
};
|
|
5255
|
+
this.devToken = (userId) => {
|
|
5256
|
+
return streamDevToken(userId);
|
|
5257
|
+
};
|
|
5154
5258
|
this.closePoll = async (request) => {
|
|
5155
5259
|
return await this.updatePollPartial({
|
|
5156
5260
|
poll_id: request.poll_id,
|
|
@@ -5199,7 +5303,10 @@ class FeedsClient extends FeedsApi {
|
|
|
5199
5303
|
removeConnectionEventListeners(this.updateNetworkConnectionStatus);
|
|
5200
5304
|
this.connectionIdManager.reset();
|
|
5201
5305
|
this.tokenManager.reset();
|
|
5202
|
-
this.state.partialNext({
|
|
5306
|
+
this.state.partialNext({
|
|
5307
|
+
connected_user: undefined,
|
|
5308
|
+
is_ws_connection_healthy: false,
|
|
5309
|
+
});
|
|
5203
5310
|
};
|
|
5204
5311
|
this.on = this.eventDispatcher.on;
|
|
5205
5312
|
this.off = this.eventDispatcher.off;
|
|
@@ -5225,8 +5332,8 @@ class FeedsClient extends FeedsApi {
|
|
|
5225
5332
|
}
|
|
5226
5333
|
};
|
|
5227
5334
|
this.state = new StateStore({
|
|
5228
|
-
|
|
5229
|
-
|
|
5335
|
+
connected_user: undefined,
|
|
5336
|
+
is_ws_connection_healthy: false,
|
|
5230
5337
|
});
|
|
5231
5338
|
this.moderation = new ModerationClient(apiClient);
|
|
5232
5339
|
this.tokenManager = tokenManager;
|
|
@@ -5238,7 +5345,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5238
5345
|
switch (event.type) {
|
|
5239
5346
|
case 'connection.changed': {
|
|
5240
5347
|
const { online } = event;
|
|
5241
|
-
this.state.partialNext({
|
|
5348
|
+
this.state.partialNext({ is_ws_connection_healthy: online });
|
|
5242
5349
|
if (online) {
|
|
5243
5350
|
this.healthyConnectionChangedEventCount++;
|
|
5244
5351
|
// we skip the first event as we could potentially be querying twice
|
|
@@ -5696,7 +5803,7 @@ class ActivitySearchSource extends BaseSearchSource {
|
|
|
5696
5803
|
this.client = client;
|
|
5697
5804
|
}
|
|
5698
5805
|
async query(searchQuery) {
|
|
5699
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
5806
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
5700
5807
|
if (!connectedUser)
|
|
5701
5808
|
return { items: [] };
|
|
5702
5809
|
const { activities: items, next } = await this.client.queryActivities({
|
|
@@ -5711,10 +5818,10 @@ class ActivitySearchSource extends BaseSearchSource {
|
|
|
5711
5818
|
return items;
|
|
5712
5819
|
}
|
|
5713
5820
|
}
|
|
5714
|
-
// filter: {
|
|
5715
|
-
// 'feed.name': { $autocomplete: searchQuery }
|
|
5716
|
-
// 'feed.description': { $autocomplete: searchQuery }
|
|
5717
|
-
// 'created_by.name': { $autocomplete: searchQuery }
|
|
5821
|
+
// filter: {
|
|
5822
|
+
// 'feed.name': { $autocomplete: searchQuery }
|
|
5823
|
+
// 'feed.description': { $autocomplete: searchQuery }
|
|
5824
|
+
// 'created_by.name': { $autocomplete: searchQuery }
|
|
5718
5825
|
// },
|
|
5719
5826
|
|
|
5720
5827
|
class UserSearchSource extends BaseSearchSource {
|
|
@@ -5730,7 +5837,7 @@ class UserSearchSource extends BaseSearchSource {
|
|
|
5730
5837
|
this.client = client;
|
|
5731
5838
|
}
|
|
5732
5839
|
async query(searchQuery) {
|
|
5733
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
5840
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
5734
5841
|
if (!connectedUser)
|
|
5735
5842
|
return { items: [] };
|
|
5736
5843
|
// const channelFilters: ChannelFilters = {
|
|
@@ -5807,7 +5914,7 @@ class FeedSearchSource extends BaseSearchSource {
|
|
|
5807
5914
|
this.client = client;
|
|
5808
5915
|
}
|
|
5809
5916
|
async query(searchQuery) {
|
|
5810
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
5917
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
5811
5918
|
if (!connectedUser)
|
|
5812
5919
|
return { items: [] };
|
|
5813
5920
|
// const channelFilters: ChannelFilters = {
|
|
@@ -5872,14 +5979,10 @@ class FeedSearchSource extends BaseSearchSource {
|
|
|
5872
5979
|
}
|
|
5873
5980
|
}
|
|
5874
5981
|
|
|
5875
|
-
const isImageFile = (file) => {
|
|
5876
|
-
// photoshop files begin with 'image/'
|
|
5877
|
-
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
5878
|
-
};
|
|
5879
|
-
|
|
5880
5982
|
exports.ActivitySearchSource = ActivitySearchSource;
|
|
5881
5983
|
exports.BaseSearchSource = BaseSearchSource;
|
|
5882
5984
|
exports.ChannelOwnCapability = ChannelOwnCapability;
|
|
5985
|
+
exports.Constants = Constants;
|
|
5883
5986
|
exports.Feed = Feed;
|
|
5884
5987
|
exports.FeedOwnCapability = FeedOwnCapability;
|
|
5885
5988
|
exports.FeedSearchSource = FeedSearchSource;
|
|
@@ -5890,7 +5993,10 @@ exports.StateStore = StateStore;
|
|
|
5890
5993
|
exports.StreamApiError = StreamApiError;
|
|
5891
5994
|
exports.StreamPoll = StreamPoll;
|
|
5892
5995
|
exports.UserSearchSource = UserSearchSource;
|
|
5996
|
+
exports.checkHasAnotherPage = checkHasAnotherPage;
|
|
5997
|
+
exports.isCommentResponse = isCommentResponse;
|
|
5893
5998
|
exports.isImageFile = isImageFile;
|
|
5894
5999
|
exports.isPatch = isPatch;
|
|
6000
|
+
exports.isVideoFile = isVideoFile;
|
|
5895
6001
|
exports.isVoteAnswer = isVoteAnswer;
|
|
5896
6002
|
//# sourceMappingURL=index.browser.cjs.map
|