@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
@@ -0,0 +1,113 @@
1
+ import { useCallback, useMemo } from 'react';
2
+ import {
3
+ type ActivityResponse,
4
+ type CommentResponse,
5
+ type Feed,
6
+ type FeedState,
7
+ checkHasAnotherPage,
8
+ type ActivityWithStateUpdates,
9
+ type ActivityState,
10
+ type StateStore,
11
+ } from '@self';
12
+ import { useFeedContext } from '../../contexts/StreamFeedContext';
13
+ import { useStateStore } from '@stream-io/state-store/react-bindings';
14
+
15
+ const canLoadComments = (
16
+ feedOrActivity: Feed | ActivityResponse | ActivityWithStateUpdates,
17
+ ): feedOrActivity is ActivityWithStateUpdates | Feed => {
18
+ return (
19
+ 'loadNextPageCommentReplies' in feedOrActivity &&
20
+ 'loadNextPageActivityComments' in feedOrActivity
21
+ );
22
+ };
23
+
24
+ type UseCommentsReturnType<T extends ActivityResponse | CommentResponse> = {
25
+ comments: NonNullable<
26
+ FeedState['comments_by_entity_id'][T['id']]
27
+ >['comments'];
28
+ comments_pagination: NonNullable<
29
+ FeedState['comments_by_entity_id'][T['id']]
30
+ >['pagination'];
31
+ has_next_page: boolean;
32
+ is_loading_next_page: boolean;
33
+ loadNextPage: (
34
+ request?: T extends CommentResponse
35
+ ? Parameters<Feed['loadNextPageCommentReplies']>[1]
36
+ : Parameters<Feed['loadNextPageActivityComments']>[1],
37
+ ) => Promise<void>;
38
+ };
39
+
40
+ export function useActivityComments({
41
+ feed: feedFromProps,
42
+ parentComment,
43
+ activity,
44
+ }: {
45
+ feed?: Feed;
46
+ parentComment?: CommentResponse;
47
+ activity?: ActivityResponse | ActivityWithStateUpdates;
48
+ }) {
49
+ const feedFromContext = useFeedContext();
50
+ const feed = feedFromProps ?? feedFromContext;
51
+ const feedOrActivity = feed ?? activity;
52
+
53
+ if (!feedOrActivity) {
54
+ throw new Error('Feed or activity is required');
55
+ }
56
+
57
+ if (!canLoadComments(feedOrActivity)) {
58
+ throw new Error('Feed or activity does not support loading comments');
59
+ }
60
+
61
+ if (!(activity || parentComment)) {
62
+ throw new Error('Activity or parent comment is required');
63
+ }
64
+
65
+ const entityId = parentComment?.id ?? activity?.id ?? '';
66
+ const selector = useCallback(
67
+ (state: FeedState | ActivityState) => ({
68
+ comments: state.comments_by_entity_id?.[entityId]?.comments,
69
+ comments_pagination: state.comments_by_entity_id?.[entityId]?.pagination,
70
+ }),
71
+ [entityId],
72
+ );
73
+
74
+ const data = useStateStore(
75
+ feedOrActivity.state as StateStore<FeedState | ActivityState>,
76
+ selector,
77
+ );
78
+
79
+ const loadNextPage = useCallback<
80
+ UseCommentsReturnType<ActivityResponse | CommentResponse>['loadNextPage']
81
+ >(
82
+ (request) => {
83
+ if (parentComment) {
84
+ return feedOrActivity.loadNextPageCommentReplies(
85
+ parentComment,
86
+ request,
87
+ );
88
+ } else {
89
+ if (activity && canLoadComments(activity)) {
90
+ return activity.loadNextPageActivityComments(request);
91
+ } else if (feed) {
92
+ return feed.loadNextPageActivityComments(activity?.id ?? '', request);
93
+ } else {
94
+ throw new Error('Activity or feed is required');
95
+ }
96
+ }
97
+ },
98
+ [feedOrActivity, feed, parentComment, activity],
99
+ );
100
+
101
+ return useMemo(() => {
102
+ return {
103
+ ...data,
104
+ has_next_page: checkHasAnotherPage(
105
+ data.comments,
106
+ data.comments_pagination?.next,
107
+ ),
108
+ is_loading_next_page:
109
+ data?.comments_pagination?.loading_next_page ?? false,
110
+ loadNextPage,
111
+ };
112
+ }, [data, loadNextPage]);
113
+ }
@@ -27,6 +27,10 @@ type UseCommentsReturnType<T extends ActivityResponse | CommentResponse> = {
27
27
  ) => Promise<void>;
28
28
  };
29
29
 
30
+ /**
31
+ * @deprecated Use `useActivityComments` instead.
32
+ * @param
33
+ */
30
34
  export function useComments<T extends CommentParent>(_: {
31
35
  feed: Feed;
32
36
  parent: T;
@@ -12,16 +12,19 @@ export const useOwnCapabilities = (feedFromProps?: Feed) => {
12
12
  const feed = feedFromProps ?? feedFromContext;
13
13
  const fid = feed?.feed;
14
14
 
15
- const selector = useCallback((currentState: FeedsClientState) => {
16
- if (!fid) {
17
- return { feedOwnCapabilities: stableEmptyArray };
18
- }
15
+ const selector = useCallback(
16
+ (currentState: FeedsClientState) => {
17
+ if (!fid) {
18
+ return { feedOwnCapabilities: stableEmptyArray };
19
+ }
19
20
 
20
- return {
21
- feedOwnCapabilities:
22
- currentState.own_capabilities_by_fid[fid] ?? stableEmptyArray,
23
- };
24
- }, [fid]);
21
+ return {
22
+ feedOwnCapabilities:
23
+ currentState.own_capabilities_by_fid[fid] ?? stableEmptyArray,
24
+ };
25
+ },
26
+ [fid],
27
+ );
25
28
 
26
29
  const { feedOwnCapabilities = stableEmptyArray } =
27
30
  useStateStore(client?.state, selector) ?? {};
@@ -43,7 +43,6 @@ export const useCreateFeedsClient = ({
43
43
  .connectUser(cachedUserData, tokenOrProvider)
44
44
  .then(() => {
45
45
  setError(null);
46
- console.log('Successfully connected user: ', cachedUserData.id);
47
46
  })
48
47
  .catch((err) => {
49
48
  setError(err);
@@ -60,11 +59,6 @@ export const useCreateFeedsClient = ({
60
59
  })
61
60
  .catch((err) => {
62
61
  setError(err);
63
- })
64
- .then(() => {
65
- console.log(
66
- `Connection for user "${cachedUserData.id}" has been closed`,
67
- );
68
62
  });
69
63
  };
70
64
  }, [apiKey, cachedUserData, cachedOptions, tokenOrProvider]);
@@ -43,7 +43,11 @@ export enum UnhandledErrorType {
43
43
  FetchingOwnCapabilitiesOnNewActivity = 'fetching-own-capabilities-on-new-activity',
44
44
  }
45
45
 
46
- export type SyncFailure = { feed: string; reason: unknown };
46
+ export type SyncFailure = {
47
+ feed: string;
48
+ reason: unknown;
49
+ activity_id?: string;
50
+ };
47
51
 
48
52
  export type UnhandledErrorEvent = {
49
53
  type: 'errors.unhandled';
@@ -82,6 +82,17 @@ export function handleActivityUpdated(
82
82
  pinned_activities: currentPinnedActivities,
83
83
  } = this.currentState;
84
84
 
85
+ const currentActivity = currentActivities?.find(
86
+ (a) => a.id === payload.activity.id,
87
+ );
88
+ if (
89
+ !payload.activity.current_feed &&
90
+ payload.activity.feeds.length === 1 &&
91
+ currentActivity?.current_feed
92
+ ) {
93
+ payload.activity.current_feed = currentActivity.current_feed;
94
+ }
95
+
85
96
  const [result1, result2] = [
86
97
  this.hasActivity(payload.activity.id)
87
98
  ? updateActivityInState(payload, currentActivities)
package/src/feed/feed.ts CHANGED
@@ -59,7 +59,12 @@ import type {
59
59
  LoadingStates,
60
60
  PagerResponseWithLoadingStates,
61
61
  } from '../types';
62
- import { checkHasAnotherPage, Constants, uniqueArrayMerge } from '../utils';
62
+ import {
63
+ checkHasAnotherPage,
64
+ Constants,
65
+ feedsLoggerSystem,
66
+ uniqueArrayMerge,
67
+ } from '../utils';
63
68
  import { handleActivityFeedback } from './event-handlers/activity/handle-activity-feedback';
64
69
  import { deepEqual } from '../utils/deep-equal';
65
70
 
@@ -595,13 +600,15 @@ export class Feed extends FeedApi {
595
600
  }
596
601
 
597
602
  public async loadNextPageActivityComments(
598
- activity: ActivityResponse,
603
+ activity: ActivityResponse | string,
599
604
  request?: Partial<
600
605
  Omit<GetCommentsRequest, 'object_id' | 'object_type' | 'next'>
601
606
  >,
602
607
  ) {
603
608
  const currentEntityState =
604
- this.currentState.comments_by_entity_id[activity.id];
609
+ this.currentState.comments_by_entity_id[
610
+ typeof activity === 'string' ? activity : activity.id
611
+ ];
605
612
  const currentPagination = currentEntityState?.pagination;
606
613
  const currentNextCursor = currentPagination?.next;
607
614
  const currentSort = currentPagination?.sort;
@@ -617,13 +624,14 @@ export class Feed extends FeedApi {
617
624
  return;
618
625
  }
619
626
 
627
+ const entityId = typeof activity === 'string' ? activity : activity.id;
620
628
  await this.loadNextPageComments({
621
- entityId: activity.id,
629
+ entityId: entityId,
622
630
  base: () =>
623
631
  this.client.getComments({
624
632
  ...request,
625
633
  sort,
626
- object_id: activity.id,
634
+ object_id: entityId,
627
635
  object_type: 'activity',
628
636
  next: currentNextCursor,
629
637
  }),
@@ -929,7 +937,9 @@ export class Feed extends FeedApi {
929
937
  }
930
938
 
931
939
  if (typeof eventHandler === 'undefined') {
932
- console.warn(`Received unknown event type: ${event.type}`, event);
940
+ feedsLoggerSystem
941
+ .getLogger('event-dispatcher')
942
+ .warn(`Received unknown feed event, type: ${event.type}`, event);
933
943
  }
934
944
 
935
945
  this.eventDispatcher.dispatch(event);
@@ -0,0 +1,42 @@
1
+ import { Feed } from '../feed';
2
+ import type { FeedsClient } from './feeds-client';
3
+
4
+ export function connectActivityToFeed(
5
+ this: FeedsClient,
6
+ {
7
+ fid,
8
+ }: {
9
+ fid: string;
10
+ },
11
+ ) {
12
+ const [group, id] = fid.split(':');
13
+ const activeFeed = this.activeFeeds[fid];
14
+
15
+ const feed = new Feed(
16
+ this,
17
+ group,
18
+ id,
19
+ undefined,
20
+ activeFeed?.currentState.watch,
21
+ );
22
+
23
+ return feed;
24
+ }
25
+
26
+ export function isAnyFeedWatched(this: FeedsClient, fids: string[]) {
27
+ for (const fid of fids) {
28
+ const feed = this.activeFeeds[fid];
29
+ if (feed && feed.currentState.last_get_or_create_request_config?.watch) {
30
+ return true;
31
+ }
32
+ }
33
+
34
+ return false;
35
+ }
36
+
37
+ export function disconnectActivityFromFeed(this: FeedsClient, id: string) {
38
+ const activeFeed = this.activeActivities[id];
39
+ if (activeFeed) {
40
+ delete this.activeActivities[id];
41
+ }
42
+ }