@stream-io/feeds-client 0.1.5 → 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.
Files changed (40) hide show
  1. package/@react-bindings/hooks/feed-state-hooks/index.ts +2 -0
  2. package/CHANGELOG.md +15 -0
  3. package/dist/@react-bindings/hooks/client-state-hooks/useWsConnectionState.d.ts +1 -1
  4. package/dist/@react-bindings/hooks/feed-state-hooks/index.d.ts +2 -0
  5. package/dist/@react-bindings/hooks/feed-state-hooks/useComments.d.ts +2 -2
  6. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedActivities.d.ts +2 -2
  7. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedMetadata.d.ts +12 -0
  8. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowers.d.ts +2 -2
  9. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowing.d.ts +2 -2
  10. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnCapabilities.d.ts +30 -30
  11. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnFollows.d.ts +8 -0
  12. package/dist/index-react-bindings.browser.cjs +128 -85
  13. package/dist/index-react-bindings.browser.cjs.map +1 -1
  14. package/dist/index-react-bindings.browser.js +127 -86
  15. package/dist/index-react-bindings.browser.js.map +1 -1
  16. package/dist/index-react-bindings.node.cjs +128 -85
  17. package/dist/index-react-bindings.node.cjs.map +1 -1
  18. package/dist/index-react-bindings.node.js +127 -86
  19. package/dist/index-react-bindings.node.js.map +1 -1
  20. package/dist/index.browser.cjs +48 -37
  21. package/dist/index.browser.cjs.map +1 -1
  22. package/dist/index.browser.js +48 -37
  23. package/dist/index.browser.js.map +1 -1
  24. package/dist/index.node.cjs +48 -37
  25. package/dist/index.node.cjs.map +1 -1
  26. package/dist/index.node.js +48 -37
  27. package/dist/index.node.js.map +1 -1
  28. package/dist/src/FeedsClient.d.ts +2 -2
  29. package/dist/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +6 -3
  31. package/src/Feed.ts +17 -11
  32. package/src/FeedsClient.ts +15 -10
  33. package/src/common/ActivitySearchSource.ts +5 -5
  34. package/src/common/ApiClient.ts +1 -1
  35. package/src/common/FeedSearchSource.ts +1 -1
  36. package/src/common/Poll.ts +35 -10
  37. package/src/common/TokenManager.ts +2 -3
  38. package/src/common/UserSearchSource.ts +1 -1
  39. package/src/state-updates/bookmark-utils.test.ts +134 -8
  40. package/src/state-updates/bookmark-utils.ts +17 -7
@@ -2791,7 +2791,7 @@ class TokenManager {
2791
2791
  }
2792
2792
  catch (e) {
2793
2793
  const numberOfFailures = ++previousFailuresCount;
2794
- await sleep(retryInterval(numberOfFailures));
2794
+ await sleep(1000);
2795
2795
  if (numberOfFailures === 3) {
2796
2796
  this.loadTokenPromise = null;
2797
2797
  return reject(new Error(`Stream error: tried to get token ${numberOfFailures} times, but it failed with ${e}. Check your token provider`, { cause: e }));
@@ -3639,7 +3639,7 @@ class ApiClient {
3639
3639
  rate_limit: getRateLimitFromResponseHeader(response_headers),
3640
3640
  };
3641
3641
  };
3642
- this.baseUrl = options?.base_url ?? 'https://video.stream-io-api.com';
3642
+ this.baseUrl = options?.base_url ?? 'https://feeds.stream-io-api.com';
3643
3643
  this.timeout = options?.timeout ?? 3000;
3644
3644
  this.axiosInstance = axios.create({
3645
3645
  baseURL: this.baseUrl,
@@ -3933,6 +3933,13 @@ const removeReactionFromActivities = (event, activities, isCurrentUser) => {
3933
3933
  return updateActivityInActivities$1(updatedActivity, activities);
3934
3934
  };
3935
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
+ };
3936
3943
  const updateActivityInActivities = (updatedActivity, activities) => {
3937
3944
  const index = activities.findIndex((a) => a.id === updatedActivity.id);
3938
3945
  if (index !== -1) {
@@ -3959,8 +3966,7 @@ const addBookmarkToActivity = (event, activity, isCurrentUser) => {
3959
3966
  const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
3960
3967
  // Update own_bookmarks if the bookmark is from the current user
3961
3968
  const ownBookmarks = isCurrentUser
3962
- ? (activity.own_bookmarks || []).filter((bookmark) => bookmark.user.id !== event.bookmark.user.id ||
3963
- bookmark.activity.id !== event.bookmark.activity.id)
3969
+ ? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
3964
3970
  : activity.own_bookmarks;
3965
3971
  return {
3966
3972
  ...activity,
@@ -3972,8 +3978,7 @@ const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
3972
3978
  // Update own_bookmarks if the bookmark is from the current user
3973
3979
  let ownBookmarks = activity.own_bookmarks || [];
3974
3980
  if (isCurrentUser) {
3975
- const bookmarkIndex = ownBookmarks.findIndex((bookmark) => bookmark.user.id === event.bookmark.user.id &&
3976
- bookmark.activity.id === event.bookmark.activity.id);
3981
+ const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
3977
3982
  if (bookmarkIndex !== -1) {
3978
3983
  ownBookmarks = [...ownBookmarks];
3979
3984
  ownBookmarks[bookmarkIndex] = event.bookmark;
@@ -4062,7 +4067,7 @@ class Feed extends FeedApi {
4062
4067
  },
4063
4068
  'feeds.activity.reaction.added': (event) => {
4064
4069
  const currentActivities = this.currentState.activities;
4065
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4070
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4066
4071
  const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
4067
4072
  const result = addReactionToActivities(event, currentActivities, isCurrentUser);
4068
4073
  if (result.changed) {
@@ -4071,7 +4076,7 @@ class Feed extends FeedApi {
4071
4076
  },
4072
4077
  'feeds.activity.reaction.deleted': (event) => {
4073
4078
  const currentActivities = this.currentState.activities;
4074
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4079
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4075
4080
  const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
4076
4081
  const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
4077
4082
  if (result.changed) {
@@ -4210,7 +4215,7 @@ class Feed extends FeedApi {
4210
4215
  // someone followed this feed
4211
4216
  event.follow.target_feed.fid === this.fid) {
4212
4217
  const source = event.follow.source_feed;
4213
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4218
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4214
4219
  this.state.next((currentState) => {
4215
4220
  const newState = { ...currentState, ...event.follow.target_feed };
4216
4221
  if (source.created_by.id === connectedUser?.id) {
@@ -4243,7 +4248,7 @@ class Feed extends FeedApi {
4243
4248
  // someone unfollowed this feed
4244
4249
  event.follow.target_feed.fid === this.fid) {
4245
4250
  const source = event.follow.source_feed;
4246
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4251
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4247
4252
  this.state.next((currentState) => {
4248
4253
  const newState = { ...currentState, ...event.follow.target_feed };
4249
4254
  if (source.created_by.id === connectedUser?.id) {
@@ -4259,7 +4264,7 @@ class Feed extends FeedApi {
4259
4264
  'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
4260
4265
  'feeds.comment.reaction.updated': Feed.noop,
4261
4266
  'feeds.feed_member.added': (event) => {
4262
- const { connectedUser } = this.client.state.getLatestValue();
4267
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4263
4268
  this.state.next((currentState) => {
4264
4269
  let newState;
4265
4270
  if (!checkHasAnotherPage(currentState.members, currentState.member_pagination?.next)) {
@@ -4280,7 +4285,7 @@ class Feed extends FeedApi {
4280
4285
  });
4281
4286
  },
4282
4287
  'feeds.feed_member.removed': (event) => {
4283
- const { connectedUser } = this.client.state.getLatestValue();
4288
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4284
4289
  this.state.next((currentState) => {
4285
4290
  const newState = {
4286
4291
  ...currentState,
@@ -4293,7 +4298,7 @@ class Feed extends FeedApi {
4293
4298
  });
4294
4299
  },
4295
4300
  'feeds.feed_member.updated': (event) => {
4296
- const { connectedUser } = this.client.state.getLatestValue();
4301
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4297
4302
  this.state.next((currentState) => {
4298
4303
  const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
4299
4304
  let newState;
@@ -4358,7 +4363,7 @@ class Feed extends FeedApi {
4358
4363
  }
4359
4364
  handleCommentReactionEvent(event) {
4360
4365
  const { comment, reaction } = event;
4361
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4366
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4362
4367
  this.state.next((currentState) => {
4363
4368
  const forId = comment.parent_id ?? comment.object_id;
4364
4369
  const entityState = currentState.comments_by_entity_id[forId];
@@ -4460,7 +4465,7 @@ class Feed extends FeedApi {
4460
4465
  }
4461
4466
  handleBookmarkAdded(event) {
4462
4467
  const currentActivities = this.currentState.activities;
4463
- const { connectedUser } = this.client.state.getLatestValue();
4468
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4464
4469
  const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
4465
4470
  const result = addBookmarkToActivities(event, currentActivities, isCurrentUser);
4466
4471
  if (result.changed) {
@@ -4469,7 +4474,7 @@ class Feed extends FeedApi {
4469
4474
  }
4470
4475
  handleBookmarkDeleted(event) {
4471
4476
  const currentActivities = this.currentState.activities;
4472
- const { connectedUser } = this.client.state.getLatestValue();
4477
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4473
4478
  const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
4474
4479
  const result = removeBookmarkFromActivities(event, currentActivities, isCurrentUser);
4475
4480
  if (result.changed) {
@@ -4478,7 +4483,7 @@ class Feed extends FeedApi {
4478
4483
  }
4479
4484
  handleBookmarkUpdated(event) {
4480
4485
  const currentActivities = this.currentState.activities;
4481
- const { connectedUser } = this.client.state.getLatestValue();
4486
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4482
4487
  const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
4483
4488
  const result = updateBookmarkInActivities(event, currentActivities, isCurrentUser);
4484
4489
  if (result.changed) {
@@ -5033,7 +5038,8 @@ class StreamPoll {
5033
5038
  if (!isPollVoteCastedEvent(event))
5034
5039
  return;
5035
5040
  const currentState = this.data;
5036
- const isOwnVote = event.poll_vote.user_id === this.client.state.getLatestValue().connectedUser?.id;
5041
+ const isOwnVote = event.poll_vote.user_id ===
5042
+ this.client.state.getLatestValue().connected_user?.id;
5037
5043
  let latestAnswers = [...currentState.latest_answers];
5038
5044
  let ownAnswer = currentState.own_answer;
5039
5045
  const ownVotesByOptionId = currentState.own_votes_by_option_id;
@@ -5057,7 +5063,7 @@ class StreamPoll {
5057
5063
  else {
5058
5064
  maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
5059
5065
  }
5060
- 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;
5061
5067
  this.state.partialNext({
5062
5068
  answers_count,
5063
5069
  // @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
@@ -5078,7 +5084,8 @@ class StreamPoll {
5078
5084
  if (!isPollVoteChangedEvent(event))
5079
5085
  return;
5080
5086
  const currentState = this.data;
5081
- const isOwnVote = event.poll_vote.user_id === this.client.state.getLatestValue().connectedUser?.id;
5087
+ const isOwnVote = event.poll_vote.user_id ===
5088
+ this.client.state.getLatestValue().connected_user?.id;
5082
5089
  let latestAnswers = [...currentState.latest_answers];
5083
5090
  let ownAnswer = currentState.own_answer;
5084
5091
  let ownVotesByOptionId = currentState.own_votes_by_option_id;
@@ -5125,7 +5132,7 @@ class StreamPoll {
5125
5132
  else {
5126
5133
  maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
5127
5134
  }
5128
- 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;
5129
5136
  this.state.partialNext({
5130
5137
  answers_count,
5131
5138
  // @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
@@ -5145,7 +5152,8 @@ class StreamPoll {
5145
5152
  if (!isPollVoteRemovedEvent(event))
5146
5153
  return;
5147
5154
  const currentState = this.data;
5148
- const isOwnVote = event.poll_vote.user_id === this.client.state.getLatestValue().connectedUser?.id;
5155
+ const isOwnVote = event.poll_vote.user_id ===
5156
+ this.client.state.getLatestValue().connected_user?.id;
5149
5157
  let latestAnswers = [...currentState.latest_answers];
5150
5158
  let ownAnswer = currentState.own_answer;
5151
5159
  const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
@@ -5163,7 +5171,7 @@ class StreamPoll {
5163
5171
  delete ownVotesByOptionId[event.poll_vote.option_id];
5164
5172
  }
5165
5173
  }
5166
- 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;
5167
5175
  this.state.partialNext({
5168
5176
  answers_count,
5169
5177
  // @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
@@ -5221,7 +5229,7 @@ class FeedsClient extends FeedsApi {
5221
5229
  this.healthyConnectionChangedEventCount = 0;
5222
5230
  this.pollFromState = (id) => this.polls_by_id.get(id);
5223
5231
  this.connectUser = async (user, tokenProvider) => {
5224
- if (this.state.getLatestValue().connectedUser !== undefined ||
5232
+ if (this.state.getLatestValue().connected_user !== undefined ||
5225
5233
  this.wsConnection) {
5226
5234
  throw new Error(`Can't connect a new user, call "disconnectUser" first`);
5227
5235
  }
@@ -5235,8 +5243,8 @@ class FeedsClient extends FeedsApi {
5235
5243
  this.wsConnection.on('all', (event) => this.eventDispatcher.dispatch(event));
5236
5244
  const connectedEvent = await this.wsConnection.connect();
5237
5245
  this.state.partialNext({
5238
- connectedUser: connectedEvent?.me,
5239
- isWsConnectionHealthy: this.wsConnection.isHealthy,
5246
+ connected_user: connectedEvent?.me,
5247
+ is_ws_connection_healthy: !!this.wsConnection?.isHealthy,
5240
5248
  });
5241
5249
  }
5242
5250
  catch (err) {
@@ -5295,7 +5303,10 @@ class FeedsClient extends FeedsApi {
5295
5303
  removeConnectionEventListeners(this.updateNetworkConnectionStatus);
5296
5304
  this.connectionIdManager.reset();
5297
5305
  this.tokenManager.reset();
5298
- this.state.partialNext({ connectedUser: undefined, isWsConnectionHealthy: false });
5306
+ this.state.partialNext({
5307
+ connected_user: undefined,
5308
+ is_ws_connection_healthy: false,
5309
+ });
5299
5310
  };
5300
5311
  this.on = this.eventDispatcher.on;
5301
5312
  this.off = this.eventDispatcher.off;
@@ -5321,8 +5332,8 @@ class FeedsClient extends FeedsApi {
5321
5332
  }
5322
5333
  };
5323
5334
  this.state = new StateStore({
5324
- connectedUser: undefined,
5325
- isWsConnectionHealthy: false,
5335
+ connected_user: undefined,
5336
+ is_ws_connection_healthy: false,
5326
5337
  });
5327
5338
  this.moderation = new ModerationClient(apiClient);
5328
5339
  this.tokenManager = tokenManager;
@@ -5334,7 +5345,7 @@ class FeedsClient extends FeedsApi {
5334
5345
  switch (event.type) {
5335
5346
  case 'connection.changed': {
5336
5347
  const { online } = event;
5337
- this.state.partialNext({ isWsConnectionHealthy: online });
5348
+ this.state.partialNext({ is_ws_connection_healthy: online });
5338
5349
  if (online) {
5339
5350
  this.healthyConnectionChangedEventCount++;
5340
5351
  // we skip the first event as we could potentially be querying twice
@@ -5792,7 +5803,7 @@ class ActivitySearchSource extends BaseSearchSource {
5792
5803
  this.client = client;
5793
5804
  }
5794
5805
  async query(searchQuery) {
5795
- const { connectedUser } = this.client.state.getLatestValue();
5806
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
5796
5807
  if (!connectedUser)
5797
5808
  return { items: [] };
5798
5809
  const { activities: items, next } = await this.client.queryActivities({
@@ -5807,10 +5818,10 @@ class ActivitySearchSource extends BaseSearchSource {
5807
5818
  return items;
5808
5819
  }
5809
5820
  }
5810
- // filter: {
5811
- // 'feed.name': { $autocomplete: searchQuery }
5812
- // 'feed.description': { $autocomplete: searchQuery }
5813
- // 'created_by.name': { $autocomplete: searchQuery }
5821
+ // filter: {
5822
+ // 'feed.name': { $autocomplete: searchQuery }
5823
+ // 'feed.description': { $autocomplete: searchQuery }
5824
+ // 'created_by.name': { $autocomplete: searchQuery }
5814
5825
  // },
5815
5826
 
5816
5827
  class UserSearchSource extends BaseSearchSource {
@@ -5826,7 +5837,7 @@ class UserSearchSource extends BaseSearchSource {
5826
5837
  this.client = client;
5827
5838
  }
5828
5839
  async query(searchQuery) {
5829
- const { connectedUser } = this.client.state.getLatestValue();
5840
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
5830
5841
  if (!connectedUser)
5831
5842
  return { items: [] };
5832
5843
  // const channelFilters: ChannelFilters = {
@@ -5903,7 +5914,7 @@ class FeedSearchSource extends BaseSearchSource {
5903
5914
  this.client = client;
5904
5915
  }
5905
5916
  async query(searchQuery) {
5906
- const { connectedUser } = this.client.state.getLatestValue();
5917
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
5907
5918
  if (!connectedUser)
5908
5919
  return { items: [] };
5909
5920
  // const channelFilters: ChannelFilters = {