@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.js
CHANGED
|
@@ -2686,6 +2686,13 @@ function removeConnectionEventListeners(cb) {
|
|
|
2686
2686
|
window.removeEventListener('online', cb);
|
|
2687
2687
|
}
|
|
2688
2688
|
}
|
|
2689
|
+
const streamDevToken = (userId) => {
|
|
2690
|
+
return [
|
|
2691
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', // {"alg": "HS256", "typ": "JWT"}
|
|
2692
|
+
window.btoa(JSON.stringify({ user_id: userId })),
|
|
2693
|
+
'devtoken', // hardcoded signature
|
|
2694
|
+
].join('.');
|
|
2695
|
+
};
|
|
2689
2696
|
const debounce = (fn, timeout = 0, { leading = false, trailing = true, } = {}) => {
|
|
2690
2697
|
let runningTimeout = null;
|
|
2691
2698
|
let argsForTrailingExecution = null;
|
|
@@ -2782,7 +2789,7 @@ class TokenManager {
|
|
|
2782
2789
|
}
|
|
2783
2790
|
catch (e) {
|
|
2784
2791
|
const numberOfFailures = ++previousFailuresCount;
|
|
2785
|
-
await sleep(
|
|
2792
|
+
await sleep(1000);
|
|
2786
2793
|
if (numberOfFailures === 3) {
|
|
2787
2794
|
this.loadTokenPromise = null;
|
|
2788
2795
|
return reject(new Error(`Stream error: tried to get token ${numberOfFailures} times, but it failed with ${e}. Check your token provider`, { cause: e }));
|
|
@@ -2995,7 +3002,10 @@ class StableWSConnection {
|
|
|
2995
3002
|
this.onmessage = (wsID, event) => {
|
|
2996
3003
|
if (this.wsID !== wsID)
|
|
2997
3004
|
return;
|
|
2998
|
-
this._log('onmessage() - onmessage callback', {
|
|
3005
|
+
this._log('onmessage() - onmessage callback', {
|
|
3006
|
+
event: { ...event, data: JSON.parse(event.data) },
|
|
3007
|
+
wsID,
|
|
3008
|
+
});
|
|
2999
3009
|
let data = typeof event.data === 'string' ? JSON.parse(event.data) : null;
|
|
3000
3010
|
this.decoders.forEach((decode) => {
|
|
3001
3011
|
data = decode(data);
|
|
@@ -3627,7 +3637,7 @@ class ApiClient {
|
|
|
3627
3637
|
rate_limit: getRateLimitFromResponseHeader(response_headers),
|
|
3628
3638
|
};
|
|
3629
3639
|
};
|
|
3630
|
-
this.baseUrl = options?.base_url ?? 'https://
|
|
3640
|
+
this.baseUrl = options?.base_url ?? 'https://feeds.stream-io-api.com';
|
|
3631
3641
|
this.timeout = options?.timeout ?? 3000;
|
|
3632
3642
|
this.axiosInstance = axios.create({
|
|
3633
3643
|
baseURL: this.baseUrl,
|
|
@@ -3921,6 +3931,13 @@ const removeReactionFromActivities = (event, activities, isCurrentUser) => {
|
|
|
3921
3931
|
return updateActivityInActivities$1(updatedActivity, activities);
|
|
3922
3932
|
};
|
|
3923
3933
|
|
|
3934
|
+
// Helper function to check if two bookmarks are the same
|
|
3935
|
+
// A bookmark is identified by activity_id + folder_id + user_id
|
|
3936
|
+
const isSameBookmark = (bookmark1, bookmark2) => {
|
|
3937
|
+
return (bookmark1.user.id === bookmark2.user.id &&
|
|
3938
|
+
bookmark1.activity.id === bookmark2.activity.id &&
|
|
3939
|
+
bookmark1.folder?.id === bookmark2.folder?.id);
|
|
3940
|
+
};
|
|
3924
3941
|
const updateActivityInActivities = (updatedActivity, activities) => {
|
|
3925
3942
|
const index = activities.findIndex((a) => a.id === updatedActivity.id);
|
|
3926
3943
|
if (index !== -1) {
|
|
@@ -3947,8 +3964,7 @@ const addBookmarkToActivity = (event, activity, isCurrentUser) => {
|
|
|
3947
3964
|
const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
|
|
3948
3965
|
// Update own_bookmarks if the bookmark is from the current user
|
|
3949
3966
|
const ownBookmarks = isCurrentUser
|
|
3950
|
-
? (activity.own_bookmarks || []).filter((bookmark) => bookmark
|
|
3951
|
-
bookmark.activity.id !== event.bookmark.activity.id)
|
|
3967
|
+
? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
|
|
3952
3968
|
: activity.own_bookmarks;
|
|
3953
3969
|
return {
|
|
3954
3970
|
...activity,
|
|
@@ -3960,8 +3976,7 @@ const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
|
|
|
3960
3976
|
// Update own_bookmarks if the bookmark is from the current user
|
|
3961
3977
|
let ownBookmarks = activity.own_bookmarks || [];
|
|
3962
3978
|
if (isCurrentUser) {
|
|
3963
|
-
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => bookmark
|
|
3964
|
-
bookmark.activity.id === event.bookmark.activity.id);
|
|
3979
|
+
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
|
|
3965
3980
|
if (bookmarkIndex !== -1) {
|
|
3966
3981
|
ownBookmarks = [...ownBookmarks];
|
|
3967
3982
|
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
@@ -4010,8 +4025,22 @@ const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
|
4010
4025
|
return updateActivityInActivities(updatedActivity, activities);
|
|
4011
4026
|
};
|
|
4012
4027
|
|
|
4013
|
-
const
|
|
4014
|
-
|
|
4028
|
+
const isImageFile = (file) => {
|
|
4029
|
+
// photoshop files begin with 'image/'
|
|
4030
|
+
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
4031
|
+
};
|
|
4032
|
+
const isVideoFile = (file) => {
|
|
4033
|
+
return file.type.startsWith('video/');
|
|
4034
|
+
};
|
|
4035
|
+
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4036
|
+
typeof cursor === 'string';
|
|
4037
|
+
const isCommentResponse = (entity) => {
|
|
4038
|
+
return typeof entity?.object_id === 'string';
|
|
4039
|
+
};
|
|
4040
|
+
const Constants = {
|
|
4041
|
+
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4042
|
+
};
|
|
4043
|
+
|
|
4015
4044
|
class Feed extends FeedApi {
|
|
4016
4045
|
constructor(client, groupId, id, data) {
|
|
4017
4046
|
// Need this ugly cast because fileUpload endpoints :(
|
|
@@ -4036,7 +4065,7 @@ class Feed extends FeedApi {
|
|
|
4036
4065
|
},
|
|
4037
4066
|
'feeds.activity.reaction.added': (event) => {
|
|
4038
4067
|
const currentActivities = this.currentState.activities;
|
|
4039
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4068
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4040
4069
|
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4041
4070
|
const result = addReactionToActivities(event, currentActivities, isCurrentUser);
|
|
4042
4071
|
if (result.changed) {
|
|
@@ -4045,7 +4074,7 @@ class Feed extends FeedApi {
|
|
|
4045
4074
|
},
|
|
4046
4075
|
'feeds.activity.reaction.deleted': (event) => {
|
|
4047
4076
|
const currentActivities = this.currentState.activities;
|
|
4048
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4077
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4049
4078
|
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4050
4079
|
const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
|
|
4051
4080
|
if (result.changed) {
|
|
@@ -4084,7 +4113,7 @@ class Feed extends FeedApi {
|
|
|
4084
4113
|
const entityState = currentState.comments_by_entity_id[forId];
|
|
4085
4114
|
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4086
4115
|
if (entityState?.pagination?.sort === 'last' &&
|
|
4087
|
-
entityState?.pagination.next
|
|
4116
|
+
!checkHasAnotherPage(entityState.comments, entityState?.pagination.next)) {
|
|
4088
4117
|
newComments.unshift(comment);
|
|
4089
4118
|
}
|
|
4090
4119
|
else if (entityState?.pagination?.sort === 'first') {
|
|
@@ -4171,7 +4200,7 @@ class Feed extends FeedApi {
|
|
|
4171
4200
|
...currentState,
|
|
4172
4201
|
...event.follow.source_feed,
|
|
4173
4202
|
};
|
|
4174
|
-
if (currentState.following_pagination?.next
|
|
4203
|
+
if (!checkHasAnotherPage(currentState.following, currentState.following_pagination?.next)) {
|
|
4175
4204
|
// TODO: respect sort
|
|
4176
4205
|
newState.following = currentState.following
|
|
4177
4206
|
? currentState.following.concat(event.follow)
|
|
@@ -4184,7 +4213,7 @@ class Feed extends FeedApi {
|
|
|
4184
4213
|
// someone followed this feed
|
|
4185
4214
|
event.follow.target_feed.fid === this.fid) {
|
|
4186
4215
|
const source = event.follow.source_feed;
|
|
4187
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4216
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4188
4217
|
this.state.next((currentState) => {
|
|
4189
4218
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4190
4219
|
if (source.created_by.id === connectedUser?.id) {
|
|
@@ -4192,7 +4221,7 @@ class Feed extends FeedApi {
|
|
|
4192
4221
|
? currentState.own_follows.concat(event.follow)
|
|
4193
4222
|
: [event.follow];
|
|
4194
4223
|
}
|
|
4195
|
-
if (currentState.followers_pagination?.next
|
|
4224
|
+
if (!checkHasAnotherPage(currentState.followers, currentState.followers_pagination?.next)) {
|
|
4196
4225
|
// TODO: respect sort
|
|
4197
4226
|
newState.followers = currentState.followers
|
|
4198
4227
|
? currentState.followers.concat(event.follow)
|
|
@@ -4217,7 +4246,7 @@ class Feed extends FeedApi {
|
|
|
4217
4246
|
// someone unfollowed this feed
|
|
4218
4247
|
event.follow.target_feed.fid === this.fid) {
|
|
4219
4248
|
const source = event.follow.source_feed;
|
|
4220
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4249
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4221
4250
|
this.state.next((currentState) => {
|
|
4222
4251
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4223
4252
|
if (source.created_by.id === connectedUser?.id) {
|
|
@@ -4233,40 +4262,60 @@ class Feed extends FeedApi {
|
|
|
4233
4262
|
'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
|
|
4234
4263
|
'feeds.comment.reaction.updated': Feed.noop,
|
|
4235
4264
|
'feeds.feed_member.added': (event) => {
|
|
4236
|
-
const {
|
|
4237
|
-
// do not add a member if the pagination has reached the end of the list
|
|
4238
|
-
if (this.currentState.member_pagination?.next !== END_OF_LIST)
|
|
4239
|
-
return;
|
|
4265
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4240
4266
|
this.state.next((currentState) => {
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4267
|
+
let newState;
|
|
4268
|
+
if (!checkHasAnotherPage(currentState.members, currentState.member_pagination?.next)) {
|
|
4269
|
+
newState ?? (newState = {
|
|
4270
|
+
...currentState,
|
|
4271
|
+
});
|
|
4272
|
+
newState.members = newState.members?.concat(event.member) ?? [
|
|
4273
|
+
event.member,
|
|
4274
|
+
];
|
|
4275
|
+
}
|
|
4276
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4277
|
+
newState ?? (newState = {
|
|
4278
|
+
...currentState,
|
|
4279
|
+
});
|
|
4280
|
+
newState.own_membership = event.member;
|
|
4281
|
+
}
|
|
4282
|
+
return newState ?? currentState;
|
|
4248
4283
|
});
|
|
4249
4284
|
},
|
|
4250
4285
|
'feeds.feed_member.removed': (event) => {
|
|
4286
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4251
4287
|
this.state.next((currentState) => {
|
|
4252
|
-
|
|
4288
|
+
const newState = {
|
|
4253
4289
|
...currentState,
|
|
4254
4290
|
members: currentState.members?.filter((member) => member.user.id !== event.user?.id),
|
|
4255
4291
|
};
|
|
4292
|
+
if (connectedUser?.id === event.member_id) {
|
|
4293
|
+
delete newState.own_membership;
|
|
4294
|
+
}
|
|
4295
|
+
return newState;
|
|
4256
4296
|
});
|
|
4257
4297
|
},
|
|
4258
4298
|
'feeds.feed_member.updated': (event) => {
|
|
4299
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4259
4300
|
this.state.next((currentState) => {
|
|
4260
4301
|
const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
|
|
4302
|
+
let newState;
|
|
4261
4303
|
if (memberIndex !== -1) {
|
|
4304
|
+
// if there's an index, there's a member to update
|
|
4262
4305
|
const newMembers = [...currentState.members];
|
|
4263
4306
|
newMembers[memberIndex] = event.member;
|
|
4264
|
-
|
|
4307
|
+
newState ?? (newState = {
|
|
4265
4308
|
...currentState,
|
|
4266
|
-
|
|
4267
|
-
|
|
4309
|
+
});
|
|
4310
|
+
newState.members = newMembers;
|
|
4268
4311
|
}
|
|
4269
|
-
|
|
4312
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4313
|
+
newState ?? (newState = {
|
|
4314
|
+
...currentState,
|
|
4315
|
+
});
|
|
4316
|
+
newState.own_membership = event.member;
|
|
4317
|
+
}
|
|
4318
|
+
return newState ?? currentState;
|
|
4270
4319
|
});
|
|
4271
4320
|
},
|
|
4272
4321
|
// the poll events should be removed from here
|
|
@@ -4312,7 +4361,7 @@ class Feed extends FeedApi {
|
|
|
4312
4361
|
}
|
|
4313
4362
|
handleCommentReactionEvent(event) {
|
|
4314
4363
|
const { comment, reaction } = event;
|
|
4315
|
-
const connectedUser = this.client.state.getLatestValue().
|
|
4364
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4316
4365
|
this.state.next((currentState) => {
|
|
4317
4366
|
const forId = comment.parent_id ?? comment.object_id;
|
|
4318
4367
|
const entityState = currentState.comments_by_entity_id[forId];
|
|
@@ -4392,29 +4441,6 @@ class Feed extends FeedApi {
|
|
|
4392
4441
|
...currentState,
|
|
4393
4442
|
...responseCopy,
|
|
4394
4443
|
};
|
|
4395
|
-
// if there is no next cursor, set it to END_OF_LIST
|
|
4396
|
-
// request has to have a limit set for this to work
|
|
4397
|
-
if ((request?.followers_pagination?.limit ?? 0) > 0 &&
|
|
4398
|
-
typeof nextState.followers_pagination?.next === 'undefined') {
|
|
4399
|
-
nextState.followers_pagination = {
|
|
4400
|
-
...nextState.followers_pagination,
|
|
4401
|
-
next: END_OF_LIST,
|
|
4402
|
-
};
|
|
4403
|
-
}
|
|
4404
|
-
if ((request?.following_pagination?.limit ?? 0) > 0 &&
|
|
4405
|
-
typeof nextState.following_pagination?.next === 'undefined') {
|
|
4406
|
-
nextState.following_pagination = {
|
|
4407
|
-
...nextState.following_pagination,
|
|
4408
|
-
next: END_OF_LIST,
|
|
4409
|
-
};
|
|
4410
|
-
}
|
|
4411
|
-
if ((request?.member_pagination?.limit ?? 0) > 0 &&
|
|
4412
|
-
typeof nextState.member_pagination?.next === 'undefined') {
|
|
4413
|
-
nextState.member_pagination = {
|
|
4414
|
-
...nextState.member_pagination,
|
|
4415
|
-
next: END_OF_LIST,
|
|
4416
|
-
};
|
|
4417
|
-
}
|
|
4418
4444
|
if (!request?.followers_pagination?.limit) {
|
|
4419
4445
|
delete nextState.followers;
|
|
4420
4446
|
}
|
|
@@ -4437,7 +4463,7 @@ class Feed extends FeedApi {
|
|
|
4437
4463
|
}
|
|
4438
4464
|
handleBookmarkAdded(event) {
|
|
4439
4465
|
const currentActivities = this.currentState.activities;
|
|
4440
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
4466
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4441
4467
|
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4442
4468
|
const result = addBookmarkToActivities(event, currentActivities, isCurrentUser);
|
|
4443
4469
|
if (result.changed) {
|
|
@@ -4446,7 +4472,7 @@ class Feed extends FeedApi {
|
|
|
4446
4472
|
}
|
|
4447
4473
|
handleBookmarkDeleted(event) {
|
|
4448
4474
|
const currentActivities = this.currentState.activities;
|
|
4449
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
4475
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4450
4476
|
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4451
4477
|
const result = removeBookmarkFromActivities(event, currentActivities, isCurrentUser);
|
|
4452
4478
|
if (result.changed) {
|
|
@@ -4455,7 +4481,7 @@ class Feed extends FeedApi {
|
|
|
4455
4481
|
}
|
|
4456
4482
|
handleBookmarkUpdated(event) {
|
|
4457
4483
|
const currentActivities = this.currentState.activities;
|
|
4458
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
4484
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4459
4485
|
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4460
4486
|
const result = updateBookmarkInActivities(event, currentActivities, isCurrentUser);
|
|
4461
4487
|
if (result.changed) {
|
|
@@ -4505,6 +4531,7 @@ class Feed extends FeedApi {
|
|
|
4505
4531
|
});
|
|
4506
4532
|
}
|
|
4507
4533
|
async loadNextPageComments({ forId, base, sort, parentId, }) {
|
|
4534
|
+
let error;
|
|
4508
4535
|
try {
|
|
4509
4536
|
this.state.next((currentState) => ({
|
|
4510
4537
|
...currentState,
|
|
@@ -4519,7 +4546,7 @@ class Feed extends FeedApi {
|
|
|
4519
4546
|
},
|
|
4520
4547
|
},
|
|
4521
4548
|
}));
|
|
4522
|
-
const { next: newNextCursor
|
|
4549
|
+
const { next: newNextCursor, comments } = await base();
|
|
4523
4550
|
this.state.next((currentState) => {
|
|
4524
4551
|
const newPagination = {
|
|
4525
4552
|
...currentState.comments_by_entity_id[forId]?.pagination,
|
|
@@ -4544,9 +4571,8 @@ class Feed extends FeedApi {
|
|
|
4544
4571
|
};
|
|
4545
4572
|
});
|
|
4546
4573
|
}
|
|
4547
|
-
catch (
|
|
4548
|
-
|
|
4549
|
-
// TODO: figure out how to handle errorss
|
|
4574
|
+
catch (e) {
|
|
4575
|
+
error = e;
|
|
4550
4576
|
}
|
|
4551
4577
|
finally {
|
|
4552
4578
|
this.state.next((currentState) => ({
|
|
@@ -4563,15 +4589,21 @@ class Feed extends FeedApi {
|
|
|
4563
4589
|
},
|
|
4564
4590
|
}));
|
|
4565
4591
|
}
|
|
4592
|
+
if (error) {
|
|
4593
|
+
throw error;
|
|
4594
|
+
}
|
|
4566
4595
|
}
|
|
4567
4596
|
async loadNextPageActivityComments(activity, request) {
|
|
4568
|
-
const
|
|
4569
|
-
const
|
|
4570
|
-
const
|
|
4571
|
-
const
|
|
4572
|
-
const
|
|
4573
|
-
|
|
4597
|
+
const currentEntityState = this.currentState.comments_by_entity_id[activity.id];
|
|
4598
|
+
const currentPagination = currentEntityState?.pagination;
|
|
4599
|
+
const currentNextCursor = currentPagination?.next;
|
|
4600
|
+
const currentSort = currentPagination?.sort;
|
|
4601
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
4602
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4603
|
+
if (isLoading ||
|
|
4604
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4574
4605
|
return;
|
|
4606
|
+
}
|
|
4575
4607
|
await this.loadNextPageComments({
|
|
4576
4608
|
forId: activity.id,
|
|
4577
4609
|
base: () => this.client.getComments({
|
|
@@ -4585,20 +4617,25 @@ class Feed extends FeedApi {
|
|
|
4585
4617
|
});
|
|
4586
4618
|
}
|
|
4587
4619
|
async loadNextPageCommentReplies(comment, request) {
|
|
4588
|
-
const
|
|
4589
|
-
const
|
|
4590
|
-
const
|
|
4591
|
-
const
|
|
4592
|
-
const
|
|
4593
|
-
|
|
4620
|
+
const currentEntityState = this.currentState.comments_by_entity_id[comment.id];
|
|
4621
|
+
const currentPagination = currentEntityState?.pagination;
|
|
4622
|
+
const currentNextCursor = currentPagination?.next;
|
|
4623
|
+
const currentSort = currentPagination?.sort;
|
|
4624
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
4625
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4626
|
+
if (isLoading ||
|
|
4627
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4594
4628
|
return;
|
|
4629
|
+
}
|
|
4595
4630
|
await this.loadNextPageComments({
|
|
4596
4631
|
forId: comment.id,
|
|
4597
4632
|
base: () => this.client.getCommentReplies({
|
|
4598
4633
|
...request,
|
|
4599
4634
|
comment_id: comment.id,
|
|
4600
4635
|
// use known sort first (prevents broken pagination)
|
|
4601
|
-
sort: currentSort ??
|
|
4636
|
+
sort: currentSort ??
|
|
4637
|
+
request?.sort ??
|
|
4638
|
+
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
4602
4639
|
next: currentNextCursor,
|
|
4603
4640
|
}),
|
|
4604
4641
|
parentId: comment.parent_id ?? comment.object_id,
|
|
@@ -4608,10 +4645,14 @@ class Feed extends FeedApi {
|
|
|
4608
4645
|
async loadNextPageFollows(type, request) {
|
|
4609
4646
|
const paginationKey = `${type}_pagination`;
|
|
4610
4647
|
const method = `query${capitalize(type)}`;
|
|
4648
|
+
const currentFollows = this.currentState[type];
|
|
4611
4649
|
const currentNextCursor = this.currentState[paginationKey]?.next;
|
|
4612
4650
|
const isLoading = this.currentState[paginationKey]?.loading_next_page;
|
|
4613
|
-
|
|
4651
|
+
const sort = this.currentState[paginationKey]?.sort ?? request.sort;
|
|
4652
|
+
let error;
|
|
4653
|
+
if (isLoading || !checkHasAnotherPage(currentFollows, currentNextCursor)) {
|
|
4614
4654
|
return;
|
|
4655
|
+
}
|
|
4615
4656
|
try {
|
|
4616
4657
|
this.state.next((currentState) => {
|
|
4617
4658
|
return {
|
|
@@ -4622,9 +4663,10 @@ class Feed extends FeedApi {
|
|
|
4622
4663
|
},
|
|
4623
4664
|
};
|
|
4624
4665
|
});
|
|
4625
|
-
const { next: newNextCursor
|
|
4666
|
+
const { next: newNextCursor, follows } = await this[method]({
|
|
4626
4667
|
...request,
|
|
4627
4668
|
next: currentNextCursor,
|
|
4669
|
+
sort,
|
|
4628
4670
|
});
|
|
4629
4671
|
this.state.next((currentState) => ({
|
|
4630
4672
|
...currentState,
|
|
@@ -4634,12 +4676,12 @@ class Feed extends FeedApi {
|
|
|
4634
4676
|
[paginationKey]: {
|
|
4635
4677
|
...currentState[paginationKey],
|
|
4636
4678
|
next: newNextCursor,
|
|
4679
|
+
sort,
|
|
4637
4680
|
},
|
|
4638
4681
|
}));
|
|
4639
4682
|
}
|
|
4640
|
-
catch (
|
|
4641
|
-
|
|
4642
|
-
// TODO: figure out how to handle errorss
|
|
4683
|
+
catch (e) {
|
|
4684
|
+
error = e;
|
|
4643
4685
|
}
|
|
4644
4686
|
finally {
|
|
4645
4687
|
this.state.next((currentState) => {
|
|
@@ -4652,6 +4694,9 @@ class Feed extends FeedApi {
|
|
|
4652
4694
|
};
|
|
4653
4695
|
});
|
|
4654
4696
|
}
|
|
4697
|
+
if (error) {
|
|
4698
|
+
throw error;
|
|
4699
|
+
}
|
|
4655
4700
|
}
|
|
4656
4701
|
async loadNextPageFollowers(request) {
|
|
4657
4702
|
await this.loadNextPageFollows('followers', request);
|
|
@@ -4659,6 +4704,59 @@ class Feed extends FeedApi {
|
|
|
4659
4704
|
async loadNextPageFollowing(request) {
|
|
4660
4705
|
await this.loadNextPageFollows('following', request);
|
|
4661
4706
|
}
|
|
4707
|
+
async loadNextPageMembers(request) {
|
|
4708
|
+
const currentMembers = this.currentState.members;
|
|
4709
|
+
const currentNextCursor = this.currentState.member_pagination?.next;
|
|
4710
|
+
const isLoading = this.currentState.member_pagination?.loading_next_page;
|
|
4711
|
+
const sort = this.currentState.member_pagination?.sort ?? request.sort;
|
|
4712
|
+
let error;
|
|
4713
|
+
if (isLoading || !checkHasAnotherPage(currentMembers, currentNextCursor)) {
|
|
4714
|
+
return;
|
|
4715
|
+
}
|
|
4716
|
+
try {
|
|
4717
|
+
this.state.next((currentState) => ({
|
|
4718
|
+
...currentState,
|
|
4719
|
+
member_pagination: {
|
|
4720
|
+
...currentState.member_pagination,
|
|
4721
|
+
loading_next_page: true,
|
|
4722
|
+
},
|
|
4723
|
+
}));
|
|
4724
|
+
const { next: newNextCursor, members } = await this.client.queryFeedMembers({
|
|
4725
|
+
...request,
|
|
4726
|
+
sort,
|
|
4727
|
+
feed_id: this.id,
|
|
4728
|
+
feed_group_id: this.group,
|
|
4729
|
+
next: currentNextCursor,
|
|
4730
|
+
});
|
|
4731
|
+
this.state.next((currentState) => ({
|
|
4732
|
+
...currentState,
|
|
4733
|
+
members: currentState.members
|
|
4734
|
+
? currentState.members.concat(members)
|
|
4735
|
+
: members,
|
|
4736
|
+
member_pagination: {
|
|
4737
|
+
...currentState.member_pagination,
|
|
4738
|
+
next: newNextCursor,
|
|
4739
|
+
// set sort if not defined yet
|
|
4740
|
+
sort: currentState.member_pagination?.sort ?? request.sort,
|
|
4741
|
+
},
|
|
4742
|
+
}));
|
|
4743
|
+
}
|
|
4744
|
+
catch (e) {
|
|
4745
|
+
error = e;
|
|
4746
|
+
}
|
|
4747
|
+
finally {
|
|
4748
|
+
this.state.next((currentState) => ({
|
|
4749
|
+
...currentState,
|
|
4750
|
+
member_pagination: {
|
|
4751
|
+
...currentState.member_pagination,
|
|
4752
|
+
loading_next_page: false,
|
|
4753
|
+
},
|
|
4754
|
+
}));
|
|
4755
|
+
}
|
|
4756
|
+
if (error) {
|
|
4757
|
+
throw error;
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4662
4760
|
/**
|
|
4663
4761
|
* Method which queries followers of this feed (feeds which target this feed).
|
|
4664
4762
|
*
|
|
@@ -4938,7 +5036,8 @@ class StreamPoll {
|
|
|
4938
5036
|
if (!isPollVoteCastedEvent(event))
|
|
4939
5037
|
return;
|
|
4940
5038
|
const currentState = this.data;
|
|
4941
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5039
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
5040
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4942
5041
|
let latestAnswers = [...currentState.latest_answers];
|
|
4943
5042
|
let ownAnswer = currentState.own_answer;
|
|
4944
5043
|
const ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
@@ -4962,7 +5061,7 @@ class StreamPoll {
|
|
|
4962
5061
|
else {
|
|
4963
5062
|
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4964
5063
|
}
|
|
4965
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option } = event.poll;
|
|
5064
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4966
5065
|
this.state.partialNext({
|
|
4967
5066
|
answers_count,
|
|
4968
5067
|
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
@@ -4983,7 +5082,8 @@ class StreamPoll {
|
|
|
4983
5082
|
if (!isPollVoteChangedEvent(event))
|
|
4984
5083
|
return;
|
|
4985
5084
|
const currentState = this.data;
|
|
4986
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5085
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
5086
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4987
5087
|
let latestAnswers = [...currentState.latest_answers];
|
|
4988
5088
|
let ownAnswer = currentState.own_answer;
|
|
4989
5089
|
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
@@ -5030,7 +5130,7 @@ class StreamPoll {
|
|
|
5030
5130
|
else {
|
|
5031
5131
|
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
5032
5132
|
}
|
|
5033
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option } = event.poll;
|
|
5133
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
5034
5134
|
this.state.partialNext({
|
|
5035
5135
|
answers_count,
|
|
5036
5136
|
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
@@ -5050,7 +5150,8 @@ class StreamPoll {
|
|
|
5050
5150
|
if (!isPollVoteRemovedEvent(event))
|
|
5051
5151
|
return;
|
|
5052
5152
|
const currentState = this.data;
|
|
5053
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5153
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
5154
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
5054
5155
|
let latestAnswers = [...currentState.latest_answers];
|
|
5055
5156
|
let ownAnswer = currentState.own_answer;
|
|
5056
5157
|
const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
|
|
@@ -5068,7 +5169,7 @@ class StreamPoll {
|
|
|
5068
5169
|
delete ownVotesByOptionId[event.poll_vote.option_id];
|
|
5069
5170
|
}
|
|
5070
5171
|
}
|
|
5071
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option } = event.poll;
|
|
5172
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
5072
5173
|
this.state.partialNext({
|
|
5073
5174
|
answers_count,
|
|
5074
5175
|
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
@@ -5126,7 +5227,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5126
5227
|
this.healthyConnectionChangedEventCount = 0;
|
|
5127
5228
|
this.pollFromState = (id) => this.polls_by_id.get(id);
|
|
5128
5229
|
this.connectUser = async (user, tokenProvider) => {
|
|
5129
|
-
if (this.state.getLatestValue().
|
|
5230
|
+
if (this.state.getLatestValue().connected_user !== undefined ||
|
|
5130
5231
|
this.wsConnection) {
|
|
5131
5232
|
throw new Error(`Can't connect a new user, call "disconnectUser" first`);
|
|
5132
5233
|
}
|
|
@@ -5140,8 +5241,8 @@ class FeedsClient extends FeedsApi {
|
|
|
5140
5241
|
this.wsConnection.on('all', (event) => this.eventDispatcher.dispatch(event));
|
|
5141
5242
|
const connectedEvent = await this.wsConnection.connect();
|
|
5142
5243
|
this.state.partialNext({
|
|
5143
|
-
|
|
5144
|
-
|
|
5244
|
+
connected_user: connectedEvent?.me,
|
|
5245
|
+
is_ws_connection_healthy: !!this.wsConnection?.isHealthy,
|
|
5145
5246
|
});
|
|
5146
5247
|
}
|
|
5147
5248
|
catch (err) {
|
|
@@ -5149,6 +5250,9 @@ class FeedsClient extends FeedsApi {
|
|
|
5149
5250
|
throw err;
|
|
5150
5251
|
}
|
|
5151
5252
|
};
|
|
5253
|
+
this.devToken = (userId) => {
|
|
5254
|
+
return streamDevToken(userId);
|
|
5255
|
+
};
|
|
5152
5256
|
this.closePoll = async (request) => {
|
|
5153
5257
|
return await this.updatePollPartial({
|
|
5154
5258
|
poll_id: request.poll_id,
|
|
@@ -5197,7 +5301,10 @@ class FeedsClient extends FeedsApi {
|
|
|
5197
5301
|
removeConnectionEventListeners(this.updateNetworkConnectionStatus);
|
|
5198
5302
|
this.connectionIdManager.reset();
|
|
5199
5303
|
this.tokenManager.reset();
|
|
5200
|
-
this.state.partialNext({
|
|
5304
|
+
this.state.partialNext({
|
|
5305
|
+
connected_user: undefined,
|
|
5306
|
+
is_ws_connection_healthy: false,
|
|
5307
|
+
});
|
|
5201
5308
|
};
|
|
5202
5309
|
this.on = this.eventDispatcher.on;
|
|
5203
5310
|
this.off = this.eventDispatcher.off;
|
|
@@ -5223,8 +5330,8 @@ class FeedsClient extends FeedsApi {
|
|
|
5223
5330
|
}
|
|
5224
5331
|
};
|
|
5225
5332
|
this.state = new StateStore({
|
|
5226
|
-
|
|
5227
|
-
|
|
5333
|
+
connected_user: undefined,
|
|
5334
|
+
is_ws_connection_healthy: false,
|
|
5228
5335
|
});
|
|
5229
5336
|
this.moderation = new ModerationClient(apiClient);
|
|
5230
5337
|
this.tokenManager = tokenManager;
|
|
@@ -5236,7 +5343,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5236
5343
|
switch (event.type) {
|
|
5237
5344
|
case 'connection.changed': {
|
|
5238
5345
|
const { online } = event;
|
|
5239
|
-
this.state.partialNext({
|
|
5346
|
+
this.state.partialNext({ is_ws_connection_healthy: online });
|
|
5240
5347
|
if (online) {
|
|
5241
5348
|
this.healthyConnectionChangedEventCount++;
|
|
5242
5349
|
// we skip the first event as we could potentially be querying twice
|
|
@@ -5694,7 +5801,7 @@ class ActivitySearchSource extends BaseSearchSource {
|
|
|
5694
5801
|
this.client = client;
|
|
5695
5802
|
}
|
|
5696
5803
|
async query(searchQuery) {
|
|
5697
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
5804
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
5698
5805
|
if (!connectedUser)
|
|
5699
5806
|
return { items: [] };
|
|
5700
5807
|
const { activities: items, next } = await this.client.queryActivities({
|
|
@@ -5709,10 +5816,10 @@ class ActivitySearchSource extends BaseSearchSource {
|
|
|
5709
5816
|
return items;
|
|
5710
5817
|
}
|
|
5711
5818
|
}
|
|
5712
|
-
// filter: {
|
|
5713
|
-
// 'feed.name': { $autocomplete: searchQuery }
|
|
5714
|
-
// 'feed.description': { $autocomplete: searchQuery }
|
|
5715
|
-
// 'created_by.name': { $autocomplete: searchQuery }
|
|
5819
|
+
// filter: {
|
|
5820
|
+
// 'feed.name': { $autocomplete: searchQuery }
|
|
5821
|
+
// 'feed.description': { $autocomplete: searchQuery }
|
|
5822
|
+
// 'created_by.name': { $autocomplete: searchQuery }
|
|
5716
5823
|
// },
|
|
5717
5824
|
|
|
5718
5825
|
class UserSearchSource extends BaseSearchSource {
|
|
@@ -5728,7 +5835,7 @@ class UserSearchSource extends BaseSearchSource {
|
|
|
5728
5835
|
this.client = client;
|
|
5729
5836
|
}
|
|
5730
5837
|
async query(searchQuery) {
|
|
5731
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
5838
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
5732
5839
|
if (!connectedUser)
|
|
5733
5840
|
return { items: [] };
|
|
5734
5841
|
// const channelFilters: ChannelFilters = {
|
|
@@ -5805,7 +5912,7 @@ class FeedSearchSource extends BaseSearchSource {
|
|
|
5805
5912
|
this.client = client;
|
|
5806
5913
|
}
|
|
5807
5914
|
async query(searchQuery) {
|
|
5808
|
-
const { connectedUser } = this.client.state.getLatestValue();
|
|
5915
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
5809
5916
|
if (!connectedUser)
|
|
5810
5917
|
return { items: [] };
|
|
5811
5918
|
// const channelFilters: ChannelFilters = {
|
|
@@ -5870,10 +5977,5 @@ class FeedSearchSource extends BaseSearchSource {
|
|
|
5870
5977
|
}
|
|
5871
5978
|
}
|
|
5872
5979
|
|
|
5873
|
-
|
|
5874
|
-
// photoshop files begin with 'image/'
|
|
5875
|
-
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
5876
|
-
};
|
|
5877
|
-
|
|
5878
|
-
export { ActivitySearchSource, BaseSearchSource, ChannelOwnCapability, Feed, FeedOwnCapability, FeedSearchSource, FeedsClient, MergedStateStore, SearchController, StateStore, StreamApiError, StreamPoll, UserSearchSource, isImageFile, isPatch, isVoteAnswer };
|
|
5980
|
+
export { ActivitySearchSource, BaseSearchSource, ChannelOwnCapability, Constants, Feed, FeedOwnCapability, FeedSearchSource, FeedsClient, MergedStateStore, SearchController, StateStore, StreamApiError, StreamPoll, UserSearchSource, checkHasAnotherPage, isCommentResponse, isImageFile, isPatch, isVideoFile, isVoteAnswer };
|
|
5879
5981
|
//# sourceMappingURL=index.browser.js.map
|