@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
@@ -2789,7 +2789,7 @@ class TokenManager {
2789
2789
  }
2790
2790
  catch (e) {
2791
2791
  const numberOfFailures = ++previousFailuresCount;
2792
- await sleep(retryInterval(numberOfFailures));
2792
+ await sleep(1000);
2793
2793
  if (numberOfFailures === 3) {
2794
2794
  this.loadTokenPromise = null;
2795
2795
  return reject(new Error(`Stream error: tried to get token ${numberOfFailures} times, but it failed with ${e}. Check your token provider`, { cause: e }));
@@ -3637,7 +3637,7 @@ class ApiClient {
3637
3637
  rate_limit: getRateLimitFromResponseHeader(response_headers),
3638
3638
  };
3639
3639
  };
3640
- this.baseUrl = options?.base_url ?? 'https://video.stream-io-api.com';
3640
+ this.baseUrl = options?.base_url ?? 'https://feeds.stream-io-api.com';
3641
3641
  this.timeout = options?.timeout ?? 3000;
3642
3642
  this.axiosInstance = axios.create({
3643
3643
  baseURL: this.baseUrl,
@@ -3931,6 +3931,13 @@ const removeReactionFromActivities = (event, activities, isCurrentUser) => {
3931
3931
  return updateActivityInActivities$1(updatedActivity, activities);
3932
3932
  };
3933
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
+ };
3934
3941
  const updateActivityInActivities = (updatedActivity, activities) => {
3935
3942
  const index = activities.findIndex((a) => a.id === updatedActivity.id);
3936
3943
  if (index !== -1) {
@@ -3957,8 +3964,7 @@ const addBookmarkToActivity = (event, activity, isCurrentUser) => {
3957
3964
  const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
3958
3965
  // Update own_bookmarks if the bookmark is from the current user
3959
3966
  const ownBookmarks = isCurrentUser
3960
- ? (activity.own_bookmarks || []).filter((bookmark) => bookmark.user.id !== event.bookmark.user.id ||
3961
- bookmark.activity.id !== event.bookmark.activity.id)
3967
+ ? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
3962
3968
  : activity.own_bookmarks;
3963
3969
  return {
3964
3970
  ...activity,
@@ -3970,8 +3976,7 @@ const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
3970
3976
  // Update own_bookmarks if the bookmark is from the current user
3971
3977
  let ownBookmarks = activity.own_bookmarks || [];
3972
3978
  if (isCurrentUser) {
3973
- const bookmarkIndex = ownBookmarks.findIndex((bookmark) => bookmark.user.id === event.bookmark.user.id &&
3974
- bookmark.activity.id === event.bookmark.activity.id);
3979
+ const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
3975
3980
  if (bookmarkIndex !== -1) {
3976
3981
  ownBookmarks = [...ownBookmarks];
3977
3982
  ownBookmarks[bookmarkIndex] = event.bookmark;
@@ -4060,7 +4065,7 @@ class Feed extends FeedApi {
4060
4065
  },
4061
4066
  'feeds.activity.reaction.added': (event) => {
4062
4067
  const currentActivities = this.currentState.activities;
4063
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4068
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4064
4069
  const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
4065
4070
  const result = addReactionToActivities(event, currentActivities, isCurrentUser);
4066
4071
  if (result.changed) {
@@ -4069,7 +4074,7 @@ class Feed extends FeedApi {
4069
4074
  },
4070
4075
  'feeds.activity.reaction.deleted': (event) => {
4071
4076
  const currentActivities = this.currentState.activities;
4072
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4077
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4073
4078
  const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
4074
4079
  const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
4075
4080
  if (result.changed) {
@@ -4208,7 +4213,7 @@ class Feed extends FeedApi {
4208
4213
  // someone followed this feed
4209
4214
  event.follow.target_feed.fid === this.fid) {
4210
4215
  const source = event.follow.source_feed;
4211
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4216
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4212
4217
  this.state.next((currentState) => {
4213
4218
  const newState = { ...currentState, ...event.follow.target_feed };
4214
4219
  if (source.created_by.id === connectedUser?.id) {
@@ -4241,7 +4246,7 @@ class Feed extends FeedApi {
4241
4246
  // someone unfollowed this feed
4242
4247
  event.follow.target_feed.fid === this.fid) {
4243
4248
  const source = event.follow.source_feed;
4244
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4249
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4245
4250
  this.state.next((currentState) => {
4246
4251
  const newState = { ...currentState, ...event.follow.target_feed };
4247
4252
  if (source.created_by.id === connectedUser?.id) {
@@ -4257,7 +4262,7 @@ class Feed extends FeedApi {
4257
4262
  'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
4258
4263
  'feeds.comment.reaction.updated': Feed.noop,
4259
4264
  'feeds.feed_member.added': (event) => {
4260
- const { connectedUser } = this.client.state.getLatestValue();
4265
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4261
4266
  this.state.next((currentState) => {
4262
4267
  let newState;
4263
4268
  if (!checkHasAnotherPage(currentState.members, currentState.member_pagination?.next)) {
@@ -4278,7 +4283,7 @@ class Feed extends FeedApi {
4278
4283
  });
4279
4284
  },
4280
4285
  'feeds.feed_member.removed': (event) => {
4281
- const { connectedUser } = this.client.state.getLatestValue();
4286
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4282
4287
  this.state.next((currentState) => {
4283
4288
  const newState = {
4284
4289
  ...currentState,
@@ -4291,7 +4296,7 @@ class Feed extends FeedApi {
4291
4296
  });
4292
4297
  },
4293
4298
  'feeds.feed_member.updated': (event) => {
4294
- const { connectedUser } = this.client.state.getLatestValue();
4299
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4295
4300
  this.state.next((currentState) => {
4296
4301
  const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
4297
4302
  let newState;
@@ -4356,7 +4361,7 @@ class Feed extends FeedApi {
4356
4361
  }
4357
4362
  handleCommentReactionEvent(event) {
4358
4363
  const { comment, reaction } = event;
4359
- const connectedUser = this.client.state.getLatestValue().connectedUser;
4364
+ const connectedUser = this.client.state.getLatestValue().connected_user;
4360
4365
  this.state.next((currentState) => {
4361
4366
  const forId = comment.parent_id ?? comment.object_id;
4362
4367
  const entityState = currentState.comments_by_entity_id[forId];
@@ -4458,7 +4463,7 @@ class Feed extends FeedApi {
4458
4463
  }
4459
4464
  handleBookmarkAdded(event) {
4460
4465
  const currentActivities = this.currentState.activities;
4461
- const { connectedUser } = this.client.state.getLatestValue();
4466
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4462
4467
  const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
4463
4468
  const result = addBookmarkToActivities(event, currentActivities, isCurrentUser);
4464
4469
  if (result.changed) {
@@ -4467,7 +4472,7 @@ class Feed extends FeedApi {
4467
4472
  }
4468
4473
  handleBookmarkDeleted(event) {
4469
4474
  const currentActivities = this.currentState.activities;
4470
- const { connectedUser } = this.client.state.getLatestValue();
4475
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4471
4476
  const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
4472
4477
  const result = removeBookmarkFromActivities(event, currentActivities, isCurrentUser);
4473
4478
  if (result.changed) {
@@ -4476,7 +4481,7 @@ class Feed extends FeedApi {
4476
4481
  }
4477
4482
  handleBookmarkUpdated(event) {
4478
4483
  const currentActivities = this.currentState.activities;
4479
- const { connectedUser } = this.client.state.getLatestValue();
4484
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
4480
4485
  const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
4481
4486
  const result = updateBookmarkInActivities(event, currentActivities, isCurrentUser);
4482
4487
  if (result.changed) {
@@ -5031,7 +5036,8 @@ class StreamPoll {
5031
5036
  if (!isPollVoteCastedEvent(event))
5032
5037
  return;
5033
5038
  const currentState = this.data;
5034
- const isOwnVote = event.poll_vote.user_id === this.client.state.getLatestValue().connectedUser?.id;
5039
+ const isOwnVote = event.poll_vote.user_id ===
5040
+ this.client.state.getLatestValue().connected_user?.id;
5035
5041
  let latestAnswers = [...currentState.latest_answers];
5036
5042
  let ownAnswer = currentState.own_answer;
5037
5043
  const ownVotesByOptionId = currentState.own_votes_by_option_id;
@@ -5055,7 +5061,7 @@ class StreamPoll {
5055
5061
  else {
5056
5062
  maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
5057
5063
  }
5058
- 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;
5059
5065
  this.state.partialNext({
5060
5066
  answers_count,
5061
5067
  // @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
@@ -5076,7 +5082,8 @@ class StreamPoll {
5076
5082
  if (!isPollVoteChangedEvent(event))
5077
5083
  return;
5078
5084
  const currentState = this.data;
5079
- const isOwnVote = event.poll_vote.user_id === this.client.state.getLatestValue().connectedUser?.id;
5085
+ const isOwnVote = event.poll_vote.user_id ===
5086
+ this.client.state.getLatestValue().connected_user?.id;
5080
5087
  let latestAnswers = [...currentState.latest_answers];
5081
5088
  let ownAnswer = currentState.own_answer;
5082
5089
  let ownVotesByOptionId = currentState.own_votes_by_option_id;
@@ -5123,7 +5130,7 @@ class StreamPoll {
5123
5130
  else {
5124
5131
  maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
5125
5132
  }
5126
- 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;
5127
5134
  this.state.partialNext({
5128
5135
  answers_count,
5129
5136
  // @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
@@ -5143,7 +5150,8 @@ class StreamPoll {
5143
5150
  if (!isPollVoteRemovedEvent(event))
5144
5151
  return;
5145
5152
  const currentState = this.data;
5146
- const isOwnVote = event.poll_vote.user_id === this.client.state.getLatestValue().connectedUser?.id;
5153
+ const isOwnVote = event.poll_vote.user_id ===
5154
+ this.client.state.getLatestValue().connected_user?.id;
5147
5155
  let latestAnswers = [...currentState.latest_answers];
5148
5156
  let ownAnswer = currentState.own_answer;
5149
5157
  const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
@@ -5161,7 +5169,7 @@ class StreamPoll {
5161
5169
  delete ownVotesByOptionId[event.poll_vote.option_id];
5162
5170
  }
5163
5171
  }
5164
- 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;
5165
5173
  this.state.partialNext({
5166
5174
  answers_count,
5167
5175
  // @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
@@ -5219,7 +5227,7 @@ class FeedsClient extends FeedsApi {
5219
5227
  this.healthyConnectionChangedEventCount = 0;
5220
5228
  this.pollFromState = (id) => this.polls_by_id.get(id);
5221
5229
  this.connectUser = async (user, tokenProvider) => {
5222
- if (this.state.getLatestValue().connectedUser !== undefined ||
5230
+ if (this.state.getLatestValue().connected_user !== undefined ||
5223
5231
  this.wsConnection) {
5224
5232
  throw new Error(`Can't connect a new user, call "disconnectUser" first`);
5225
5233
  }
@@ -5233,8 +5241,8 @@ class FeedsClient extends FeedsApi {
5233
5241
  this.wsConnection.on('all', (event) => this.eventDispatcher.dispatch(event));
5234
5242
  const connectedEvent = await this.wsConnection.connect();
5235
5243
  this.state.partialNext({
5236
- connectedUser: connectedEvent?.me,
5237
- isWsConnectionHealthy: this.wsConnection.isHealthy,
5244
+ connected_user: connectedEvent?.me,
5245
+ is_ws_connection_healthy: !!this.wsConnection?.isHealthy,
5238
5246
  });
5239
5247
  }
5240
5248
  catch (err) {
@@ -5293,7 +5301,10 @@ class FeedsClient extends FeedsApi {
5293
5301
  removeConnectionEventListeners(this.updateNetworkConnectionStatus);
5294
5302
  this.connectionIdManager.reset();
5295
5303
  this.tokenManager.reset();
5296
- this.state.partialNext({ connectedUser: undefined, isWsConnectionHealthy: false });
5304
+ this.state.partialNext({
5305
+ connected_user: undefined,
5306
+ is_ws_connection_healthy: false,
5307
+ });
5297
5308
  };
5298
5309
  this.on = this.eventDispatcher.on;
5299
5310
  this.off = this.eventDispatcher.off;
@@ -5319,8 +5330,8 @@ class FeedsClient extends FeedsApi {
5319
5330
  }
5320
5331
  };
5321
5332
  this.state = new StateStore({
5322
- connectedUser: undefined,
5323
- isWsConnectionHealthy: false,
5333
+ connected_user: undefined,
5334
+ is_ws_connection_healthy: false,
5324
5335
  });
5325
5336
  this.moderation = new ModerationClient(apiClient);
5326
5337
  this.tokenManager = tokenManager;
@@ -5332,7 +5343,7 @@ class FeedsClient extends FeedsApi {
5332
5343
  switch (event.type) {
5333
5344
  case 'connection.changed': {
5334
5345
  const { online } = event;
5335
- this.state.partialNext({ isWsConnectionHealthy: online });
5346
+ this.state.partialNext({ is_ws_connection_healthy: online });
5336
5347
  if (online) {
5337
5348
  this.healthyConnectionChangedEventCount++;
5338
5349
  // we skip the first event as we could potentially be querying twice
@@ -5790,7 +5801,7 @@ class ActivitySearchSource extends BaseSearchSource {
5790
5801
  this.client = client;
5791
5802
  }
5792
5803
  async query(searchQuery) {
5793
- const { connectedUser } = this.client.state.getLatestValue();
5804
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
5794
5805
  if (!connectedUser)
5795
5806
  return { items: [] };
5796
5807
  const { activities: items, next } = await this.client.queryActivities({
@@ -5805,10 +5816,10 @@ class ActivitySearchSource extends BaseSearchSource {
5805
5816
  return items;
5806
5817
  }
5807
5818
  }
5808
- // filter: {
5809
- // 'feed.name': { $autocomplete: searchQuery }
5810
- // 'feed.description': { $autocomplete: searchQuery }
5811
- // 'created_by.name': { $autocomplete: searchQuery }
5819
+ // filter: {
5820
+ // 'feed.name': { $autocomplete: searchQuery }
5821
+ // 'feed.description': { $autocomplete: searchQuery }
5822
+ // 'created_by.name': { $autocomplete: searchQuery }
5812
5823
  // },
5813
5824
 
5814
5825
  class UserSearchSource extends BaseSearchSource {
@@ -5824,7 +5835,7 @@ class UserSearchSource extends BaseSearchSource {
5824
5835
  this.client = client;
5825
5836
  }
5826
5837
  async query(searchQuery) {
5827
- const { connectedUser } = this.client.state.getLatestValue();
5838
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
5828
5839
  if (!connectedUser)
5829
5840
  return { items: [] };
5830
5841
  // const channelFilters: ChannelFilters = {
@@ -5901,7 +5912,7 @@ class FeedSearchSource extends BaseSearchSource {
5901
5912
  this.client = client;
5902
5913
  }
5903
5914
  async query(searchQuery) {
5904
- const { connectedUser } = this.client.state.getLatestValue();
5915
+ const { connected_user: connectedUser } = this.client.state.getLatestValue();
5905
5916
  if (!connectedUser)
5906
5917
  return { items: [] };
5907
5918
  // const channelFilters: ChannelFilters = {