@stream-io/feeds-client 0.3.7 → 0.3.9

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 (54) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/index.js +2 -1
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/react-bindings.js +76 -14
  5. package/dist/cjs/react-bindings.js.map +1 -1
  6. package/dist/es/index.mjs +3 -2
  7. package/dist/es/react-bindings.mjs +76 -14
  8. package/dist/es/react-bindings.mjs.map +1 -1
  9. package/dist/{feeds-client-3aXF89xy.mjs → feeds-client-CI-WG0y0.mjs} +280 -52
  10. package/dist/feeds-client-CI-WG0y0.mjs.map +1 -0
  11. package/dist/{feeds-client-DLiLkrA0.js → feeds-client-DvR7ZYd1.js} +280 -52
  12. package/dist/feeds-client-DvR7ZYd1.js.map +1 -0
  13. package/dist/types/activity-with-state-updates/activity-with-state-updates.d.ts +49 -0
  14. package/dist/types/activity-with-state-updates/activity-with-state-updates.d.ts.map +1 -0
  15. package/dist/types/activity-with-state-updates/get-feed.d.ts +3 -0
  16. package/dist/types/activity-with-state-updates/get-feed.d.ts.map +1 -0
  17. package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts +1 -0
  18. package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts.map +1 -1
  19. package/dist/types/bindings/react/hooks/feed-state-hooks/useActivityComments.d.ts +32 -0
  20. package/dist/types/bindings/react/hooks/feed-state-hooks/useActivityComments.d.ts.map +1 -0
  21. package/dist/types/bindings/react/hooks/feed-state-hooks/useComments.d.ts +4 -0
  22. package/dist/types/bindings/react/hooks/feed-state-hooks/useComments.d.ts.map +1 -1
  23. package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.d.ts.map +1 -1
  24. package/dist/types/bindings/react/hooks/useCreateFeedsClient.d.ts.map +1 -1
  25. package/dist/types/common/real-time/event-models.d.ts +1 -0
  26. package/dist/types/common/real-time/event-models.d.ts.map +1 -1
  27. package/dist/types/feed/event-handlers/activity/handle-activity-updated.d.ts.map +1 -1
  28. package/dist/types/feed/feed.d.ts +1 -1
  29. package/dist/types/feed/feed.d.ts.map +1 -1
  30. package/dist/types/feeds-client/active-activity.d.ts +8 -0
  31. package/dist/types/feeds-client/active-activity.d.ts.map +1 -0
  32. package/dist/types/feeds-client/feeds-client.d.ts +36 -3
  33. package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/dist/types/types.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/activity-with-state-updates/activity-with-state-updates.ts +190 -0
  39. package/src/activity-with-state-updates/get-feed.ts +5 -0
  40. package/src/bindings/react/hooks/feed-state-hooks/index.ts +1 -0
  41. package/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts +113 -0
  42. package/src/bindings/react/hooks/feed-state-hooks/useComments.ts +4 -0
  43. package/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts +12 -9
  44. package/src/bindings/react/hooks/useCreateFeedsClient.ts +0 -6
  45. package/src/common/real-time/event-models.ts +5 -1
  46. package/src/feed/event-handlers/activity/handle-activity-updated.ts +11 -0
  47. package/src/feed/feed.ts +16 -6
  48. package/src/feeds-client/active-activity.ts +42 -0
  49. package/src/feeds-client/feeds-client.ts +162 -53
  50. package/src/index.ts +1 -0
  51. package/src/test-utils/response-generators.ts +1 -0
  52. package/src/types.ts +8 -10
  53. package/dist/feeds-client-3aXF89xy.mjs.map +0 -1
  54. package/dist/feeds-client-DLiLkrA0.js.map +0 -1
@@ -3862,7 +3862,7 @@ const getRateLimitFromResponseHeader = (response_headers) => {
3862
3862
  };
3863
3863
  return result;
3864
3864
  };
3865
- const version = "0.3.7";
3865
+ const version = "0.3.9";
3866
3866
  class ApiClient {
3867
3867
  constructor(apiKey, tokenManager, connectionIdManager, options) {
3868
3868
  this.apiKey = apiKey;
@@ -5582,6 +5582,12 @@ function handleActivityUpdated(payload, fromWs) {
5582
5582
  activities: currentActivities,
5583
5583
  pinned_activities: currentPinnedActivities
5584
5584
  } = this.currentState;
5585
+ const currentActivity = currentActivities?.find(
5586
+ (a) => a.id === payload.activity.id
5587
+ );
5588
+ if (!payload.activity.current_feed && payload.activity.feeds.length === 1 && currentActivity?.current_feed) {
5589
+ payload.activity.current_feed = currentActivity.current_feed;
5590
+ }
5585
5591
  const [result1, result2] = [
5586
5592
  this.hasActivity(payload.activity.id) ? updateActivityInState(payload, currentActivities) : void 0,
5587
5593
  updatePinnedActivityInState(payload, currentPinnedActivities)
@@ -6498,7 +6504,7 @@ const _Feed = class _Feed extends FeedApi {
6498
6504
  }
6499
6505
  }
6500
6506
  async loadNextPageActivityComments(activity, request) {
6501
- const currentEntityState = this.currentState.comments_by_entity_id[activity.id];
6507
+ const currentEntityState = this.currentState.comments_by_entity_id[typeof activity === "string" ? activity : activity.id];
6502
6508
  const currentPagination = currentEntityState?.pagination;
6503
6509
  const currentNextCursor = currentPagination?.next;
6504
6510
  const currentSort = currentPagination?.sort;
@@ -6507,12 +6513,13 @@ const _Feed = class _Feed extends FeedApi {
6507
6513
  if (isLoading || !checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
6508
6514
  return;
6509
6515
  }
6516
+ const entityId = typeof activity === "string" ? activity : activity.id;
6510
6517
  await this.loadNextPageComments({
6511
- entityId: activity.id,
6518
+ entityId,
6512
6519
  base: () => this.client.getComments({
6513
6520
  ...request,
6514
6521
  sort,
6515
- object_id: activity.id,
6522
+ object_id: entityId,
6516
6523
  object_type: "activity",
6517
6524
  next: currentNextCursor
6518
6525
  }),
@@ -6747,7 +6754,7 @@ const _Feed = class _Feed extends FeedApi {
6747
6754
  eventHandler?.(event);
6748
6755
  }
6749
6756
  if (typeof eventHandler === "undefined") {
6750
- console.warn(`Received unknown event type: ${event.type}`, event);
6757
+ feedsLoggerSystem.getLogger("event-dispatcher").warn(`Received unknown feed event, type: ${event.type}`, event);
6751
6758
  }
6752
6759
  this.eventDispatcher.dispatch(event);
6753
6760
  }
@@ -6889,6 +6896,156 @@ function queueBatchedOwnCapabilities({ feeds }) {
6889
6896
  function clearQueuedFeeds() {
6890
6897
  queuedFeeds.clear();
6891
6898
  }
6899
+ function connectActivityToFeed({
6900
+ fid
6901
+ }) {
6902
+ const [group, id] = fid.split(":");
6903
+ const activeFeed = this.activeFeeds[fid];
6904
+ const feed = new Feed(
6905
+ this,
6906
+ group,
6907
+ id,
6908
+ void 0,
6909
+ activeFeed?.currentState.watch
6910
+ );
6911
+ return feed;
6912
+ }
6913
+ function isAnyFeedWatched(fids) {
6914
+ for (const fid of fids) {
6915
+ const feed = this.activeFeeds[fid];
6916
+ if (feed && feed.currentState.last_get_or_create_request_config?.watch) {
6917
+ return true;
6918
+ }
6919
+ }
6920
+ return false;
6921
+ }
6922
+ function disconnectActivityFromFeed(id) {
6923
+ const activeFeed = this.activeActivities[id];
6924
+ if (activeFeed) {
6925
+ delete this.activeActivities[id];
6926
+ }
6927
+ }
6928
+ class ActivityWithStateUpdates {
6929
+ constructor(id, feedsClient) {
6930
+ this.id = id;
6931
+ this.feedsClient = feedsClient;
6932
+ this.state = new stateStore.StateStore({
6933
+ activity: void 0,
6934
+ comments_by_entity_id: {},
6935
+ is_loading: false
6936
+ });
6937
+ }
6938
+ get currentState() {
6939
+ return this.state.getLatestValue();
6940
+ }
6941
+ get feeds() {
6942
+ return this.currentState.activity?.feeds ?? [];
6943
+ }
6944
+ /**
6945
+ * Fetch activity and load it into state
6946
+ * @param watch - Whether to watch the feed the activity belongs to for real-time updates
6947
+ * @param feed - The feed to watch. Use only if the activity belongs to multiple feeds and you want to specify the feed explicitly.
6948
+ * @param feedSelector - A function to select the feed from the activity response. Use only if the activity belongs to multiple feeds and you want to specify the feed explicitly.
6949
+ */
6950
+ async get(request = {}) {
6951
+ if (this.inProgressGet && deepEqual(this.inProgressGet.request, request)) {
6952
+ return this.inProgressGet.promise;
6953
+ }
6954
+ const { comments } = request;
6955
+ this.state.partialNext({
6956
+ is_loading: true,
6957
+ last_get_request_config: request
6958
+ });
6959
+ const getActivityRequest = this.feedsClient.getActivity({
6960
+ id: this.id
6961
+ }).then((response) => response.activity);
6962
+ this.inProgressGet = { request, promise: getActivityRequest };
6963
+ const activityResponse = await getActivityRequest;
6964
+ this.feedsClient.hydratePollCache([activityResponse]);
6965
+ this.setFeed({
6966
+ // We set feed to first containing feed
6967
+ // But in WS event handler we match events by any of the containing feeds, so as long as any of the containing feeds are watched, we'll do a state update
6968
+ // This is a bit hacky, proper solution would be to refactor all activity event handlers and detach them from feed instance
6969
+ fid: activityResponse.feeds[0],
6970
+ initialState: activityResponse
6971
+ });
6972
+ if (this.feed) {
6973
+ this.feed.activityAddedEventFilter = () => false;
6974
+ }
6975
+ if (comments) {
6976
+ await this.loadNextPageActivityComments(comments);
6977
+ }
6978
+ this.subscribeToFeedState();
6979
+ this.inProgressGet = void 0;
6980
+ return activityResponse;
6981
+ }
6982
+ loadNextPageActivityComments(request) {
6983
+ const activity = this.feed?.currentState.activities?.[0];
6984
+ if (!activity || !this.feed) {
6985
+ throw new Error("Initialize activity first");
6986
+ }
6987
+ if (!this.currentState.last_get_request_config?.comments) {
6988
+ this.state.partialNext({
6989
+ last_get_request_config: {
6990
+ ...this.currentState.last_get_request_config,
6991
+ comments: request
6992
+ }
6993
+ });
6994
+ }
6995
+ return this.feed.loadNextPageActivityComments(activity, request);
6996
+ }
6997
+ loadNextPageCommentReplies(...params) {
6998
+ if (!this.feed) {
6999
+ throw new Error("Initialize activity first");
7000
+ }
7001
+ return this.feed.loadNextPageCommentReplies(...params);
7002
+ }
7003
+ dispose() {
7004
+ this.unsubscribeFromFeedState?.();
7005
+ disconnectActivityFromFeed.call(this.feedsClient, this.id);
7006
+ }
7007
+ /**
7008
+ * @internal
7009
+ */
7010
+ async synchronize() {
7011
+ const allFids = this.currentState.activity?.feeds ?? [];
7012
+ if (!isAnyFeedWatched.call(this.feedsClient, allFids)) {
7013
+ return;
7014
+ }
7015
+ this.inProgressGet = void 0;
7016
+ return this.get(this.currentState.last_get_request_config);
7017
+ }
7018
+ setFeed({
7019
+ fid,
7020
+ initialState
7021
+ }) {
7022
+ this.feed = connectActivityToFeed.call(this.feedsClient, { fid });
7023
+ this.feed.state.partialNext({
7024
+ activities: [initialState]
7025
+ });
7026
+ }
7027
+ subscribeToFeedState() {
7028
+ this.unsubscribeFromFeedState?.();
7029
+ this.unsubscribeFromFeedState = this.feed?.state.subscribeWithSelector(
7030
+ (state) => ({
7031
+ activity: state.activities?.find((activity) => activity.id === this.id),
7032
+ comments_by_entity_id: state.comments_by_entity_id
7033
+ }),
7034
+ (state) => {
7035
+ if (state.activity) {
7036
+ this.state.partialNext({
7037
+ activity: state.activity,
7038
+ comments_by_entity_id: state.comments_by_entity_id,
7039
+ is_loading: false
7040
+ });
7041
+ }
7042
+ }
7043
+ );
7044
+ }
7045
+ }
7046
+ function getFeed() {
7047
+ return this.feed;
7048
+ }
6892
7049
  class FeedsClient extends FeedsApi {
6893
7050
  constructor(apiKey, options) {
6894
7051
  const tokenManager = new TokenManager();
@@ -6901,6 +7058,7 @@ class FeedsClient extends FeedsApi {
6901
7058
  );
6902
7059
  super(apiClient);
6903
7060
  this.eventDispatcher = new EventDispatcher();
7061
+ this.activeActivities = {};
6904
7062
  this.activeFeeds = {};
6905
7063
  this.healthyConnectionChangedEventCount = 0;
6906
7064
  this.setGetBatchOwnCapabilitiesThrottlingInterval = (throttlingMs) => {
@@ -6929,13 +7087,20 @@ class FeedsClient extends FeedsApi {
6929
7087
  this.recoverOnReconnect = async () => {
6930
7088
  this.healthyConnectionChangedEventCount++;
6931
7089
  if (this.healthyConnectionChangedEventCount > 1) {
6932
- const entries = Object.entries(this.activeFeeds);
6933
- const results = await Promise.allSettled(
6934
- entries.map(([, feed]) => feed.synchronize())
6935
- );
6936
- const failures = results.flatMap(
6937
- (result, index) => result.status === "rejected" ? [{ feed: entries[index][0], reason: result.reason }] : []
6938
- );
7090
+ const feedEntries = Object.entries(this.activeFeeds);
7091
+ const activityEntries = Object.entries(this.activeActivities);
7092
+ const results = await Promise.allSettled([
7093
+ ...feedEntries.map(([, feed]) => feed.synchronize()),
7094
+ ...activityEntries.map(([, activity]) => activity.synchronize())
7095
+ ]);
7096
+ const failures = results.flatMap((result, index) => {
7097
+ if (result.status === "fulfilled") {
7098
+ return [];
7099
+ }
7100
+ const activity = activityEntries[index - feedEntries.length]?.[1];
7101
+ const feed = feedEntries[index]?.[0] ?? (activity && getFeed.call(activity)?.feed);
7102
+ return [{ feed, reason: result.reason, activity_id: activity?.id }];
7103
+ });
6939
7104
  this.eventDispatcher.dispatch({
6940
7105
  type: "errors.unhandled",
6941
7106
  error_type: UnhandledErrorType.ReconnectionReconciliation,
@@ -7004,7 +7169,7 @@ class FeedsClient extends FeedsApi {
7004
7169
  };
7005
7170
  this.updateActivity = async (request) => {
7006
7171
  const response = await super.updateActivity(request);
7007
- for (const feed of Object.values(this.activeFeeds)) {
7172
+ for (const feed of this.allActiveFeeds) {
7008
7173
  handleActivityUpdated.bind(feed)(response, false);
7009
7174
  }
7010
7175
  return response;
@@ -7012,7 +7177,7 @@ class FeedsClient extends FeedsApi {
7012
7177
  this.addComment = async (request) => {
7013
7178
  const response = await super.addComment(request);
7014
7179
  const { comment } = response;
7015
- for (const feed of Object.values(this.activeFeeds)) {
7180
+ for (const feed of this.allActiveFeeds) {
7016
7181
  handleCommentAdded.bind(feed)(response, false);
7017
7182
  const parentActivityId = comment.object_id;
7018
7183
  if (feed.hasActivity(parentActivityId)) {
@@ -7035,7 +7200,7 @@ class FeedsClient extends FeedsApi {
7035
7200
  };
7036
7201
  this.updateComment = async (request) => {
7037
7202
  const response = await super.updateComment(request);
7038
- for (const feed of Object.values(this.activeFeeds)) {
7203
+ for (const feed of this.allActiveFeeds) {
7039
7204
  handleCommentUpdated.bind(feed)(response, false);
7040
7205
  }
7041
7206
  return response;
@@ -7043,7 +7208,7 @@ class FeedsClient extends FeedsApi {
7043
7208
  this.deleteComment = async (request) => {
7044
7209
  const response = await super.deleteComment(request);
7045
7210
  const { activity, comment } = response;
7046
- for (const feed of Object.values(this.activeFeeds)) {
7211
+ for (const feed of this.allActiveFeeds) {
7047
7212
  handleCommentDeleted.bind(feed)({ comment }, false);
7048
7213
  updateCommentCount.bind(feed)({
7049
7214
  activity,
@@ -7056,7 +7221,7 @@ class FeedsClient extends FeedsApi {
7056
7221
  this.addActivityReaction = async (request) => {
7057
7222
  const shouldEnforceUnique = request.enforce_unique;
7058
7223
  const response = await super.addActivityReaction(request);
7059
- for (const feed of Object.values(this.activeFeeds)) {
7224
+ for (const feed of this.allActiveFeeds) {
7060
7225
  if (shouldEnforceUnique) {
7061
7226
  handleActivityReactionUpdated.bind(feed)(response, false);
7062
7227
  } else {
@@ -7070,7 +7235,7 @@ class FeedsClient extends FeedsApi {
7070
7235
  };
7071
7236
  this.deleteActivityReaction = async (request) => {
7072
7237
  const response = await super.deleteActivityReaction(request);
7073
- for (const feed of Object.values(this.activeFeeds)) {
7238
+ for (const feed of this.allActiveFeeds) {
7074
7239
  handleActivityReactionDeleted.bind(feed)(response, false);
7075
7240
  }
7076
7241
  return response;
@@ -7078,7 +7243,7 @@ class FeedsClient extends FeedsApi {
7078
7243
  this.addCommentReaction = async (request) => {
7079
7244
  const shouldEnforceUnique = request.enforce_unique;
7080
7245
  const response = await super.addCommentReaction(request);
7081
- for (const feed of Object.values(this.activeFeeds)) {
7246
+ for (const feed of this.allActiveFeeds) {
7082
7247
  if (shouldEnforceUnique) {
7083
7248
  handleCommentReactionUpdated.bind(feed)(response, false);
7084
7249
  } else {
@@ -7089,7 +7254,7 @@ class FeedsClient extends FeedsApi {
7089
7254
  };
7090
7255
  this.deleteCommentReaction = async (request) => {
7091
7256
  const response = await super.deleteCommentReaction(request);
7092
- for (const feed of Object.values(this.activeFeeds)) {
7257
+ for (const feed of this.allActiveFeeds) {
7093
7258
  handleCommentReactionDeleted.bind(feed)(response, false);
7094
7259
  }
7095
7260
  return response;
@@ -7119,6 +7284,8 @@ class FeedsClient extends FeedsApi {
7119
7284
  this.connectionIdManager.reset();
7120
7285
  this.tokenManager.reset();
7121
7286
  this.polls_by_id.clear();
7287
+ this.activeActivities = {};
7288
+ this.activeFeeds = {};
7122
7289
  this.state.partialNext({
7123
7290
  connected_user: void 0,
7124
7291
  is_ws_connection_healthy: false,
@@ -7139,6 +7306,14 @@ class FeedsClient extends FeedsApi {
7139
7306
  options2?.activityAddedEventFilter
7140
7307
  );
7141
7308
  };
7309
+ this.activityWithStateUpdates = (id) => {
7310
+ let activity = this.activeActivities[id];
7311
+ if (!activity) {
7312
+ activity = new ActivityWithStateUpdates(id, this);
7313
+ this.activeActivities[id] = activity;
7314
+ }
7315
+ return activity;
7316
+ };
7142
7317
  this.updateNetworkConnectionStatus = (event) => {
7143
7318
  const networkEvent = {
7144
7319
  type: "network.changed",
@@ -7179,7 +7354,7 @@ class FeedsClient extends FeedsApi {
7179
7354
  feedsLoggerSystem.configureLoggers(options?.configure_loggers_options);
7180
7355
  this.on("all", (event) => {
7181
7356
  const fid = event.fid;
7182
- const feed = typeof fid === "string" ? this.activeFeeds[fid] : void 0;
7357
+ const feeds = this.findAllActiveFeedsFromWSEvent(event);
7183
7358
  switch (event.type) {
7184
7359
  case "connection.changed": {
7185
7360
  const { online } = event;
@@ -7187,14 +7362,14 @@ class FeedsClient extends FeedsApi {
7187
7362
  if (online) {
7188
7363
  this.recoverOnReconnect();
7189
7364
  } else {
7190
- for (const activeFeed of Object.values(this.activeFeeds)) {
7365
+ for (const activeFeed of this.allActiveFeeds) {
7191
7366
  handleWatchStopped.bind(activeFeed)();
7192
7367
  }
7193
7368
  }
7194
7369
  break;
7195
7370
  }
7196
7371
  case "feeds.feed.created": {
7197
- if (feed) break;
7372
+ if (this.activeFeeds[event.feed.id]) break;
7198
7373
  this.getOrCreateActiveFeed(
7199
7374
  event.feed.group_id,
7200
7375
  event.feed.id,
@@ -7203,9 +7378,15 @@ class FeedsClient extends FeedsApi {
7203
7378
  break;
7204
7379
  }
7205
7380
  case "feeds.feed.deleted": {
7206
- feed?.handleWSEvent(event);
7381
+ feeds.forEach((f) => f.handleWSEvent(event));
7207
7382
  if (typeof fid === "string") {
7208
7383
  delete this.activeFeeds[fid];
7384
+ Object.keys(this.activeActivities).forEach((activityId) => {
7385
+ const activity = this.activeActivities[activityId];
7386
+ if (getFeed.call(activity)?.feed === fid) {
7387
+ delete this.activeActivities[activityId];
7388
+ }
7389
+ });
7209
7390
  }
7210
7391
  break;
7211
7392
  }
@@ -7218,7 +7399,7 @@ class FeedsClient extends FeedsApi {
7218
7399
  case "feeds.poll.deleted": {
7219
7400
  if (event.poll?.id) {
7220
7401
  this.polls_by_id.delete(event.poll.id);
7221
- for (const activeFeed of Object.values(this.activeFeeds)) {
7402
+ for (const activeFeed of this.allActiveFeeds) {
7222
7403
  const currentActivities = activeFeed.currentState.activities;
7223
7404
  if (currentActivities) {
7224
7405
  const newActivities = [];
@@ -7266,14 +7447,14 @@ class FeedsClient extends FeedsApi {
7266
7447
  case "feeds.bookmark.deleted":
7267
7448
  case "feeds.bookmark.updated": {
7268
7449
  const activityId = event.bookmark.activity.id;
7269
- const feeds = this.findActiveFeedsByActivityId(activityId);
7270
- feeds.forEach((f) => f.handleWSEvent(event));
7450
+ const allFeeds = this.findAllActiveFeedsByActivityId(activityId);
7451
+ allFeeds.forEach((f) => f.handleWSEvent(event));
7271
7452
  break;
7272
7453
  }
7273
7454
  case "feeds.activity.feedback": {
7274
7455
  const activityId = event.activity_feedback.activity_id;
7275
- const feeds = this.findActiveFeedsByActivityId(activityId);
7276
- feeds.forEach((f) => f.handleWSEvent(event));
7456
+ const allFeeds = this.findAllActiveFeedsByActivityId(activityId);
7457
+ allFeeds.forEach((f) => f.handleWSEvent(event));
7277
7458
  break;
7278
7459
  }
7279
7460
  case "user.updated": {
@@ -7281,11 +7462,20 @@ class FeedsClient extends FeedsApi {
7281
7462
  break;
7282
7463
  }
7283
7464
  default: {
7284
- feed?.handleWSEvent(event);
7465
+ feeds.forEach((f) => f.handleWSEvent(event));
7466
+ if (event.type === "feeds.activity.deleted") {
7467
+ delete this.activeActivities[event.activity.id];
7468
+ }
7285
7469
  }
7286
7470
  }
7287
7471
  });
7288
7472
  }
7473
+ get allActiveFeeds() {
7474
+ return [
7475
+ ...Object.values(this.activeFeeds),
7476
+ ...Object.values(this.activeActivities).filter((a) => !!getFeed.call(a)).map((a) => getFeed.call(a))
7477
+ ];
7478
+ }
7289
7479
  hydratePollCache(activities) {
7290
7480
  for (const activity of activities) {
7291
7481
  if (!activity.poll) {
@@ -7357,10 +7547,8 @@ class FeedsClient extends FeedsApi {
7357
7547
  response.follow.source_feed.feed,
7358
7548
  response.follow.target_feed.feed
7359
7549
  ].forEach((fid) => {
7360
- const feed = this.activeFeeds[fid];
7361
- if (feed) {
7362
- handleFollowUpdated.bind(feed)(response, false);
7363
- }
7550
+ const feeds = this.findAllActiveFeedsByFid(fid);
7551
+ feeds.forEach((f) => handleFollowUpdated.bind(f)(response, false));
7364
7552
  });
7365
7553
  return response;
7366
7554
  }
@@ -7371,30 +7559,24 @@ class FeedsClient extends FeedsApi {
7371
7559
  response.follow.source_feed.feed,
7372
7560
  response.follow.target_feed.feed
7373
7561
  ].forEach((fid) => {
7374
- const feed = this.activeFeeds[fid];
7375
- if (feed) {
7376
- handleFollowCreated.bind(feed)(response, false);
7377
- }
7562
+ const feeds = this.findAllActiveFeedsByFid(fid);
7563
+ feeds.forEach((f) => handleFollowCreated.bind(f)(response, false));
7378
7564
  });
7379
7565
  return response;
7380
7566
  }
7381
7567
  async followBatch(request) {
7382
7568
  const response = await super.followBatch(request);
7383
7569
  response.follows.forEach((follow) => {
7384
- const feed = this.activeFeeds[follow.source_feed.feed];
7385
- if (feed) {
7386
- handleFollowCreated.bind(feed)({ follow });
7387
- }
7570
+ const feeds = this.findAllActiveFeedsByFid(follow.source_feed.feed);
7571
+ feeds.forEach((f) => handleFollowCreated.bind(f)({ follow }, false));
7388
7572
  });
7389
7573
  return response;
7390
7574
  }
7391
7575
  async unfollow(request) {
7392
7576
  const response = await super.unfollow(request);
7393
7577
  [request.source, request.target].forEach((fid) => {
7394
- const feed = this.activeFeeds[fid];
7395
- if (feed) {
7396
- handleFollowDeleted.bind(feed)(response, false);
7397
- }
7578
+ const feeds = this.findAllActiveFeedsByFid(fid);
7579
+ feeds.forEach((f) => handleFollowDeleted.bind(f)(response, false));
7398
7580
  });
7399
7581
  return response;
7400
7582
  }
@@ -7404,18 +7586,64 @@ class FeedsClient extends FeedsApi {
7404
7586
  ...request,
7405
7587
  connection_id: connectionId
7406
7588
  });
7407
- const feed = this.activeFeeds[`${request.feed_group_id}:${request.feed_id}`];
7408
- if (feed) {
7409
- handleWatchStopped.bind(feed)();
7589
+ const feeds = this.findAllActiveFeedsByFid(
7590
+ `${request.feed_group_id}:${request.feed_id}`
7591
+ );
7592
+ feeds.forEach((f) => handleWatchStopped.bind(f)());
7593
+ return response;
7594
+ }
7595
+ async getOrCreateFeed(request) {
7596
+ const response = await super.getOrCreateFeed(request);
7597
+ this.hydrateCapabilitiesCache([response.feed]);
7598
+ if (request.watch) {
7599
+ const feeds = this.findAllActiveFeedsByFid(
7600
+ `${request.feed_group_id}:${request.feed_id}`
7601
+ );
7602
+ feeds.forEach((f) => handleWatchStarted.bind(f)());
7410
7603
  }
7411
7604
  return response;
7412
7605
  }
7413
- findActiveFeedsByActivityId(activityId) {
7414
- return Object.values(this.activeFeeds).filter(
7606
+ findAllActiveFeedsByActivityId(activityId) {
7607
+ return [
7608
+ ...Object.values(this.activeFeeds),
7609
+ ...Object.values(this.activeActivities).filter((a) => !!getFeed.call(a)).map((a) => getFeed.call(a))
7610
+ ].filter(
7415
7611
  (feed) => feed.hasActivity(activityId) || feed.hasPinnedActivity(activityId)
7416
7612
  );
7417
7613
  }
7614
+ findAllActiveFeedsByFid(fid) {
7615
+ if (!fid) return [];
7616
+ const activeFeed = this.activeFeeds[fid];
7617
+ return [
7618
+ ...activeFeed ? [activeFeed] : [],
7619
+ ...Object.values(this.activeActivities).filter((a) => getFeed.call(a)?.feed === fid).map((a) => getFeed.call(a))
7620
+ ];
7621
+ }
7622
+ /**
7623
+ * When updating from WS events we need a special logic:
7624
+ * - Find active feeds that match a given fid.
7625
+ * - Find active feed from activities where fid matches any of the feeds the activity is posted to.
7626
+ *
7627
+ * This logic is different from `findAllActiveFeedsByFid` which only checks the first feed an activity is posted to.
7628
+ *
7629
+ * @param fid
7630
+ * @param activityId
7631
+ * @returns
7632
+ */
7633
+ findAllActiveFeedsFromWSEvent(event) {
7634
+ const fid = "fid" in event ? event.fid : void 0;
7635
+ if (!fid) return [];
7636
+ const activeFeed = fid ? this.activeFeeds[fid] : void 0;
7637
+ return [
7638
+ ...activeFeed ? [activeFeed] : [],
7639
+ ...Object.values(this.activeActivities).filter((a) => {
7640
+ const feed = getFeed.call(a);
7641
+ return feed?.feed === fid || a.currentState.activity?.feeds.some((f) => f === fid);
7642
+ }).map((a) => getFeed.call(a))
7643
+ ];
7644
+ }
7418
7645
  }
7646
+ exports.ActivityWithStateUpdates = ActivityWithStateUpdates;
7419
7647
  exports.Constants = Constants;
7420
7648
  exports.Feed = Feed;
7421
7649
  exports.FeedsClient = FeedsClient;
@@ -7436,4 +7664,4 @@ exports.replaceUniqueArrayMerge = replaceUniqueArrayMerge;
7436
7664
  exports.shouldUpdateState = shouldUpdateState;
7437
7665
  exports.uniqueArrayMerge = uniqueArrayMerge;
7438
7666
  exports.updateEntityInArray = updateEntityInArray;
7439
- //# sourceMappingURL=feeds-client-DLiLkrA0.js.map
7667
+ //# sourceMappingURL=feeds-client-DvR7ZYd1.js.map