@stream-io/feeds-client 0.2.1 → 0.2.3
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/feed-state-hooks/index.ts +4 -0
- package/CHANGELOG.md +16 -0
- package/dist/@react-bindings/contexts/StreamSearchContext.d.ts +1 -1
- package/dist/@react-bindings/contexts/StreamSearchResultsContext.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/index.d.ts +4 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useAggregatedActivities.d.ts +11 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts +6 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts +6 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useNotificationStatus.d.ts +13 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchQuery.d.ts +1 -1
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchResult.d.ts +1 -1
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +2 -2
- package/dist/@react-bindings/wrappers/StreamFeed.d.ts +1 -1
- package/dist/@react-bindings/wrappers/StreamSearch.d.ts +1 -1
- package/dist/@react-bindings/wrappers/StreamSearchResults.d.ts +1 -1
- package/dist/index-react-bindings.browser.cjs +178 -35
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +175 -36
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +178 -35
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +175 -36
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +328 -180
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +328 -181
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.node.cjs +328 -180
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +328 -181
- package/dist/index.node.js.map +1 -1
- package/dist/src/common/{ActivitySearchSource.d.ts → search/ActivitySearchSource.d.ts} +3 -3
- package/dist/src/common/{BaseSearchSource.d.ts → search/BaseSearchSource.d.ts} +41 -35
- package/dist/src/common/{FeedSearchSource.d.ts → search/FeedSearchSource.d.ts} +3 -3
- package/dist/src/common/{SearchController.d.ts → search/SearchController.d.ts} +1 -3
- package/dist/src/common/{UserSearchSource.d.ts → search/UserSearchSource.d.ts} +4 -4
- package/dist/src/common/search/index.d.ts +6 -0
- package/dist/src/common/search/types.d.ts +22 -0
- package/dist/src/common/types.d.ts +1 -0
- package/dist/src/feed/event-handlers/activity/handle-activity-deleted.d.ts +5 -12
- package/dist/src/feed/event-handlers/activity/handle-activity-marked.d.ts +11 -0
- package/dist/src/feed/event-handlers/activity/index.d.ts +1 -0
- package/dist/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +8 -1
- package/dist/src/feed/feed.d.ts +2 -2
- package/dist/src/gen/models/index.d.ts +58 -26
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/index.ts +1 -5
- package/package.json +1 -1
- package/src/common/{ActivitySearchSource.ts → search/ActivitySearchSource.ts} +3 -3
- package/src/common/{BaseSearchSource.ts → search/BaseSearchSource.ts} +137 -69
- package/src/common/{FeedSearchSource.ts → search/FeedSearchSource.ts} +3 -3
- package/src/common/{SearchController.ts → search/SearchController.ts} +2 -7
- package/src/common/{UserSearchSource.ts → search/UserSearchSource.ts} +3 -3
- package/src/common/search/index.ts +6 -0
- package/src/common/search/types.ts +21 -0
- package/src/common/types.ts +2 -0
- package/src/feed/event-handlers/activity/activity-marked-utils.test.ts +208 -0
- package/src/feed/event-handlers/activity/activity-utils.test.ts +2 -2
- package/src/feed/event-handlers/activity/handle-activity-added.test.ts +86 -0
- package/src/feed/event-handlers/activity/handle-activity-deleted.test.ts +117 -0
- package/src/feed/event-handlers/activity/handle-activity-deleted.ts +8 -4
- package/src/feed/event-handlers/activity/handle-activity-marked.ts +68 -0
- package/src/feed/event-handlers/activity/handle-activity-reaction-added.test.ts +15 -15
- package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.test.ts +14 -14
- package/src/feed/event-handlers/activity/handle-activity-unpinned.test.ts +4 -3
- package/src/feed/event-handlers/activity/handle-activity-updated.test.ts +4 -4
- package/src/feed/event-handlers/activity/index.ts +2 -1
- package/src/feed/event-handlers/bookmark/handle-bookmark-added.test.ts +14 -14
- package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.test.ts +14 -14
- package/src/feed/event-handlers/bookmark/handle-bookmark-updated.test.ts +16 -16
- package/src/feed/event-handlers/comment/handle-comment-added.test.ts +147 -0
- package/src/feed/event-handlers/comment/handle-comment-deleted.test.ts +133 -0
- package/src/feed/event-handlers/comment/handle-comment-deleted.ts +24 -10
- package/src/feed/event-handlers/comment/handle-comment-reaction.test.ts +315 -0
- package/src/feed/event-handlers/comment/handle-comment-updated.test.ts +131 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-added.test.ts +75 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-removed.test.ts +82 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +19 -9
- package/src/feed/event-handlers/feed-member/handle-feed-member-updated.test.ts +84 -0
- package/src/feed/event-handlers/follow/handle-follow-created.test.ts +7 -7
- package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +2 -2
- package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +1 -1
- package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.test.ts +120 -0
- package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +47 -3
- package/src/feed/feed.ts +4 -2
- package/src/gen/feeds/FeedsApi.ts +6 -0
- package/src/gen/model-decoders/decoders.ts +12 -0
- package/src/gen/models/index.ts +90 -34
- package/src/test-utils/response-generators.ts +230 -0
- package/dist/src/test-utils/index.d.ts +0 -1
- package/dist/src/test-utils/response-generators.d.ts +0 -54
|
@@ -5,3 +5,7 @@ export * from './useFollowers';
|
|
|
5
5
|
export * from './useFollowing';
|
|
6
6
|
export * from './useFeedMetadata';
|
|
7
7
|
export * from './useOwnFollows';
|
|
8
|
+
export * from './useNotificationStatus';
|
|
9
|
+
export * from './useAggregatedActivities';
|
|
10
|
+
export * from './useIsAggregatedActivityRead';
|
|
11
|
+
export * from './useIsAggregatedActivitySeen';
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [0.2.3](https://github.com/GetStream/stream-feeds-js/compare/@stream-io/feeds-client-0.2.2...@stream-io/feeds-client-0.2.3) (2025-09-01)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* add the ability to keep search items stable while searching ([#104](https://github.com/GetStream/stream-feeds-js/issues/104)) ([62a9808](https://github.com/GetStream/stream-feeds-js/commit/62a980890ce3a16e34a6d323ef8f58d58d2f8f4c))
|
|
11
|
+
* update to latest API spec ([#106](https://github.com/GetStream/stream-feeds-js/issues/106)) ([6555d15](https://github.com/GetStream/stream-feeds-js/commit/6555d15049fddace837cfd592bff2d18293a16be))
|
|
12
|
+
|
|
13
|
+
## [0.2.2](https://github.com/GetStream/stream-feeds-js/compare/@stream-io/feeds-client-0.2.1...@stream-io/feeds-client-0.2.2) (2025-08-25)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* notification feed support ([#86](https://github.com/GetStream/stream-feeds-js/issues/86)) ([9ba245e](https://github.com/GetStream/stream-feeds-js/commit/9ba245e969c77f5c241fb4f5da93491ba87c3278))
|
|
19
|
+
* notification feeds ([#102](https://github.com/GetStream/stream-feeds-js/issues/102)) ([6822da8](https://github.com/GetStream/stream-feeds-js/commit/6822da8516ef83e66fd9b74f5497136ca51f8bda))
|
|
20
|
+
|
|
5
21
|
## [0.2.1](https://github.com/GetStream/stream-feeds-js/compare/@stream-io/feeds-client-0.2.0...@stream-io/feeds-client-0.2.1) (2025-08-20)
|
|
6
22
|
|
|
7
23
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SearchController } from '../../src/common/
|
|
1
|
+
import type { SearchController } from '../../src/common/search';
|
|
2
2
|
export declare const StreamSearchContext: import("react").Context<SearchController | undefined>;
|
|
3
3
|
/**
|
|
4
4
|
* The props for the StreamSearchProvider component.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SearchSource } from '../../src/common/
|
|
1
|
+
import type { SearchSource } from '../../src/common/search';
|
|
2
2
|
export declare const StreamSearchResultsContext: import("react").Context<SearchSource<any> | undefined>;
|
|
3
3
|
/**
|
|
4
4
|
* The props for the StreamSearchResultsProvider component.
|
|
@@ -5,3 +5,7 @@ export * from './useFollowers';
|
|
|
5
5
|
export * from './useFollowing';
|
|
6
6
|
export * from './useFeedMetadata';
|
|
7
7
|
export * from './useOwnFollows';
|
|
8
|
+
export * from './useNotificationStatus';
|
|
9
|
+
export * from './useAggregatedActivities';
|
|
10
|
+
export * from './useIsAggregatedActivityRead';
|
|
11
|
+
export * from './useIsAggregatedActivitySeen';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Feed, FeedState } from '../../../src/feed';
|
|
2
|
+
declare const selector: ({ aggregated_activities }: FeedState) => {
|
|
3
|
+
aggregated_activities: import("../../..").AggregatedActivityResponse[] | undefined;
|
|
4
|
+
};
|
|
5
|
+
type UseAggregatedActivitiesReturnType = ReturnType<typeof selector>;
|
|
6
|
+
/**
|
|
7
|
+
* A React hook that returns a reactive object containing the current aggregated activities.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useAggregatedActivities(feedFromProps: Feed): UseAggregatedActivitiesReturnType;
|
|
10
|
+
export declare function useAggregatedActivities(feedFromProps?: Feed): UseAggregatedActivitiesReturnType | undefined;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AggregatedActivityResponse } from '../../../src/gen/models';
|
|
2
|
+
import { Feed } from '../../../src/feed';
|
|
3
|
+
export declare const useIsAggregatedActivityRead: ({ feed: feedFromProps, aggregatedActivity, }: {
|
|
4
|
+
feed?: Feed;
|
|
5
|
+
aggregatedActivity: AggregatedActivityResponse;
|
|
6
|
+
}) => boolean;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AggregatedActivityResponse } from '../../../src/gen/models';
|
|
2
|
+
import { Feed } from '../../../src/feed';
|
|
3
|
+
export declare const useIsAggregatedActivitySeen: ({ feed: feedFromProps, aggregatedActivity, }: {
|
|
4
|
+
feed?: Feed;
|
|
5
|
+
aggregatedActivity: AggregatedActivityResponse;
|
|
6
|
+
}) => boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Feed, FeedState } from '../../../src/feed';
|
|
2
|
+
declare const selector: ({ notification_status }: FeedState) => {
|
|
3
|
+
unread: number;
|
|
4
|
+
unseen: number;
|
|
5
|
+
last_read_at: Date | undefined;
|
|
6
|
+
last_seen_at: Date | undefined;
|
|
7
|
+
read_activities: string[] | undefined;
|
|
8
|
+
seen_activities: string[] | undefined;
|
|
9
|
+
};
|
|
10
|
+
type UseNotificationStatusReturnType = ReturnType<typeof selector>;
|
|
11
|
+
export declare function useNotificationStatus(feed: Feed): UseNotificationStatusReturnType;
|
|
12
|
+
export declare function useNotificationStatus(feed?: Feed): UseNotificationStatusReturnType | undefined;
|
|
13
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SearchController } from '../../../src/common/
|
|
1
|
+
import type { SearchController } from '../../../src/common/search';
|
|
2
2
|
export declare const useSearchQuery: (controllerFromProps?: SearchController) => {
|
|
3
3
|
searchQuery: string;
|
|
4
4
|
} | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SearchSource } from '../../../src/common/
|
|
1
|
+
import type { SearchSource } from '../../../src/common/search';
|
|
2
2
|
export declare const useSearchResult: (sourceFromProps?: SearchSource) => {
|
|
3
3
|
items: any[] | undefined;
|
|
4
4
|
error: Error | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SearchController } from '../../../src/common/
|
|
1
|
+
import type { SearchController } from '../../../src/common/search';
|
|
2
2
|
export declare const useSearchSources: (controllerFromProps?: SearchController) => {
|
|
3
|
-
sources: import("
|
|
3
|
+
sources: import("../../../src/common/search").SearchSource<any>[];
|
|
4
4
|
} | undefined;
|
|
@@ -7,6 +7,6 @@ export type StreamFeedProps = {
|
|
|
7
7
|
feed: Feed;
|
|
8
8
|
};
|
|
9
9
|
export declare const StreamFeed: {
|
|
10
|
-
({ feed, children }: PropsWithChildren<StreamFeedProps>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
({ feed, children, }: PropsWithChildren<StreamFeedProps>): import("react/jsx-runtime").JSX.Element;
|
|
11
11
|
displayName: string;
|
|
12
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
import type { SearchController } from '../../src/common/
|
|
2
|
+
import type { SearchController } from '../../src/common/search';
|
|
3
3
|
/**
|
|
4
4
|
* The props for the StreamSearch component. It accepts a `SearchController` instance.
|
|
5
5
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
import type { SearchSource } from '../../src/common/
|
|
2
|
+
import type { SearchSource } from '../../src/common/search';
|
|
3
3
|
/**
|
|
4
4
|
* The props for the StreamSearchResults component. It accepts a `SearchSource` instance.
|
|
5
5
|
*/
|
|
@@ -688,6 +688,7 @@ decoders.Command = (input) => {
|
|
|
688
688
|
decoders.CommentAddedEvent = (input) => {
|
|
689
689
|
const typeMappings = {
|
|
690
690
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
691
|
+
activity: { type: 'ActivityResponse', isSingle: true },
|
|
691
692
|
comment: { type: 'CommentResponse', isSingle: true },
|
|
692
693
|
received_at: { type: 'DatetimeType', isSingle: true },
|
|
693
694
|
};
|
|
@@ -704,6 +705,7 @@ decoders.CommentDeletedEvent = (input) => {
|
|
|
704
705
|
decoders.CommentReactionAddedEvent = (input) => {
|
|
705
706
|
const typeMappings = {
|
|
706
707
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
708
|
+
activity: { type: 'ActivityResponse', isSingle: true },
|
|
707
709
|
comment: { type: 'CommentResponse', isSingle: true },
|
|
708
710
|
reaction: { type: 'FeedsReactionResponse', isSingle: true },
|
|
709
711
|
received_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -722,6 +724,7 @@ decoders.CommentReactionDeletedEvent = (input) => {
|
|
|
722
724
|
decoders.CommentReactionUpdatedEvent = (input) => {
|
|
723
725
|
const typeMappings = {
|
|
724
726
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
727
|
+
activity: { type: 'ActivityResponse', isSingle: true },
|
|
725
728
|
comment: { type: 'CommentResponse', isSingle: true },
|
|
726
729
|
reaction: { type: 'FeedsReactionResponse', isSingle: true },
|
|
727
730
|
received_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -1084,6 +1087,7 @@ decoders.Message = (input) => {
|
|
|
1084
1087
|
pin_expires: { type: 'DatetimeType', isSingle: true },
|
|
1085
1088
|
pinned_at: { type: 'DatetimeType', isSingle: true },
|
|
1086
1089
|
thread_participants: { type: 'User', isSingle: false },
|
|
1090
|
+
member: { type: 'ChannelMember', isSingle: true },
|
|
1087
1091
|
pinned_by: { type: 'User', isSingle: true },
|
|
1088
1092
|
poll: { type: 'Poll', isSingle: true },
|
|
1089
1093
|
quoted_message: { type: 'Message', isSingle: true },
|
|
@@ -1137,6 +1141,8 @@ decoders.ModerationCustomActionEvent = (input) => {
|
|
|
1137
1141
|
};
|
|
1138
1142
|
decoders.ModerationFlagResponse = (input) => {
|
|
1139
1143
|
const typeMappings = {
|
|
1144
|
+
created_at: { type: 'DatetimeType', isSingle: true },
|
|
1145
|
+
updated_at: { type: 'DatetimeType', isSingle: true },
|
|
1140
1146
|
review_queue_item: { type: 'ReviewQueueItemResponse', isSingle: true },
|
|
1141
1147
|
user: { type: 'UserResponse', isSingle: true },
|
|
1142
1148
|
};
|
|
@@ -1903,6 +1909,7 @@ class FeedsApi {
|
|
|
1903
1909
|
const body = {
|
|
1904
1910
|
type: request?.type,
|
|
1905
1911
|
create_notification_activity: request?.create_notification_activity,
|
|
1912
|
+
skip_push: request?.skip_push,
|
|
1906
1913
|
custom: request?.custom,
|
|
1907
1914
|
};
|
|
1908
1915
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/activities/{activity_id}/reactions', pathParams, undefined, body, 'application/json');
|
|
@@ -2049,6 +2056,7 @@ class FeedsApi {
|
|
|
2049
2056
|
object_type: request?.object_type,
|
|
2050
2057
|
create_notification_activity: request?.create_notification_activity,
|
|
2051
2058
|
parent_id: request?.parent_id,
|
|
2059
|
+
skip_push: request?.skip_push,
|
|
2052
2060
|
attachments: request?.attachments,
|
|
2053
2061
|
mentioned_user_ids: request?.mentioned_user_ids,
|
|
2054
2062
|
custom: request?.custom,
|
|
@@ -2102,6 +2110,7 @@ class FeedsApi {
|
|
|
2102
2110
|
};
|
|
2103
2111
|
const body = {
|
|
2104
2112
|
comment: request?.comment,
|
|
2113
|
+
skip_push: request?.skip_push,
|
|
2105
2114
|
custom: request?.custom,
|
|
2106
2115
|
};
|
|
2107
2116
|
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/comments/{id}', pathParams, undefined, body, 'application/json');
|
|
@@ -2115,6 +2124,7 @@ class FeedsApi {
|
|
|
2115
2124
|
const body = {
|
|
2116
2125
|
type: request?.type,
|
|
2117
2126
|
create_notification_activity: request?.create_notification_activity,
|
|
2127
|
+
skip_push: request?.skip_push,
|
|
2118
2128
|
custom: request?.custom,
|
|
2119
2129
|
};
|
|
2120
2130
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{id}/reactions', pathParams, undefined, body, 'application/json');
|
|
@@ -2355,6 +2365,7 @@ class FeedsApi {
|
|
|
2355
2365
|
create_notification_activity: request?.create_notification_activity,
|
|
2356
2366
|
follower_role: request?.follower_role,
|
|
2357
2367
|
push_preference: request?.push_preference,
|
|
2368
|
+
skip_push: request?.skip_push,
|
|
2358
2369
|
custom: request?.custom,
|
|
2359
2370
|
};
|
|
2360
2371
|
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/follows', undefined, undefined, body, 'application/json');
|
|
@@ -2367,6 +2378,7 @@ class FeedsApi {
|
|
|
2367
2378
|
target: request?.target,
|
|
2368
2379
|
create_notification_activity: request?.create_notification_activity,
|
|
2369
2380
|
push_preference: request?.push_preference,
|
|
2381
|
+
skip_push: request?.skip_push,
|
|
2370
2382
|
custom: request?.custom,
|
|
2371
2383
|
};
|
|
2372
2384
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/follows', undefined, undefined, body, 'application/json');
|
|
@@ -4505,20 +4517,29 @@ function handleCommentAdded(event) {
|
|
|
4505
4517
|
function handleCommentDeleted({ comment }) {
|
|
4506
4518
|
const entityId = comment.parent_id ?? comment.object_id;
|
|
4507
4519
|
this.state.next((currentState) => {
|
|
4508
|
-
|
|
4509
|
-
...currentState.comments_by_entity_id,
|
|
4510
|
-
[entityId]: {
|
|
4511
|
-
...currentState.comments_by_entity_id[entityId],
|
|
4512
|
-
},
|
|
4513
|
-
};
|
|
4520
|
+
let newCommentsByEntityId;
|
|
4514
4521
|
const index = this.getCommentIndex(comment, currentState);
|
|
4515
|
-
if (
|
|
4522
|
+
if (index !== -1) {
|
|
4523
|
+
newCommentsByEntityId ?? (newCommentsByEntityId = {
|
|
4524
|
+
...currentState.comments_by_entity_id,
|
|
4525
|
+
[entityId]: {
|
|
4526
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4527
|
+
},
|
|
4528
|
+
});
|
|
4516
4529
|
newCommentsByEntityId[entityId].comments = [
|
|
4517
4530
|
...newCommentsByEntityId[entityId].comments,
|
|
4518
4531
|
];
|
|
4519
4532
|
newCommentsByEntityId[entityId]?.comments?.splice(index, 1);
|
|
4520
4533
|
}
|
|
4521
|
-
|
|
4534
|
+
if (typeof currentState.comments_by_entity_id[comment.id] !== 'undefined') {
|
|
4535
|
+
newCommentsByEntityId ?? (newCommentsByEntityId = {
|
|
4536
|
+
...currentState.comments_by_entity_id,
|
|
4537
|
+
});
|
|
4538
|
+
delete newCommentsByEntityId[comment.id];
|
|
4539
|
+
}
|
|
4540
|
+
if (!newCommentsByEntityId) {
|
|
4541
|
+
return currentState;
|
|
4542
|
+
}
|
|
4522
4543
|
return {
|
|
4523
4544
|
...currentState,
|
|
4524
4545
|
comments_by_entity_id: newCommentsByEntityId,
|
|
@@ -4639,14 +4660,20 @@ function handleFeedMemberUpdated(event) {
|
|
|
4639
4660
|
function handleFeedMemberRemoved(event) {
|
|
4640
4661
|
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4641
4662
|
this.state.next((currentState) => {
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4663
|
+
let newState;
|
|
4664
|
+
if (typeof currentState.members !== 'undefined') {
|
|
4665
|
+
const filtered = currentState.members.filter((member) => member.user.id !== event.member_id);
|
|
4666
|
+
if (filtered.length !== currentState.members.length) {
|
|
4667
|
+
newState ?? (newState = { ...currentState });
|
|
4668
|
+
newState.members = filtered;
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
if (connectedUser?.id === event.member_id &&
|
|
4672
|
+
typeof currentState.own_membership !== 'undefined') {
|
|
4673
|
+
newState ?? (newState = { ...currentState });
|
|
4647
4674
|
delete newState.own_membership;
|
|
4648
4675
|
}
|
|
4649
|
-
return newState;
|
|
4676
|
+
return newState ?? currentState;
|
|
4650
4677
|
});
|
|
4651
4678
|
}
|
|
4652
4679
|
|
|
@@ -4883,7 +4910,7 @@ const removePinnedActivityFromState = (activityResponse, pinnedActivities) => {
|
|
|
4883
4910
|
if (index !== -1) {
|
|
4884
4911
|
const newActivities = [...pinnedActivities];
|
|
4885
4912
|
newActivities.splice(index, 1);
|
|
4886
|
-
return { changed: true,
|
|
4913
|
+
return { changed: true, pinned_activities: newActivities };
|
|
4887
4914
|
}
|
|
4888
4915
|
else {
|
|
4889
4916
|
return { changed: false, pinned_activities: pinnedActivities };
|
|
@@ -5073,13 +5100,80 @@ function handleActivityReactionDeleted(event) {
|
|
|
5073
5100
|
}
|
|
5074
5101
|
}
|
|
5075
5102
|
|
|
5103
|
+
const updateNotificationStatusFromActivityMarked = (event, currentNotificationStatus, aggregatedActivities = []) => {
|
|
5104
|
+
if (!currentNotificationStatus) {
|
|
5105
|
+
return {
|
|
5106
|
+
changed: false,
|
|
5107
|
+
};
|
|
5108
|
+
}
|
|
5109
|
+
const newState = {
|
|
5110
|
+
...currentNotificationStatus,
|
|
5111
|
+
};
|
|
5112
|
+
if (event.mark_all_read) {
|
|
5113
|
+
const allGroupIds = aggregatedActivities.map((activity) => activity.group);
|
|
5114
|
+
newState.read_activities = [
|
|
5115
|
+
...new Set([
|
|
5116
|
+
...(currentNotificationStatus.read_activities ?? []),
|
|
5117
|
+
...allGroupIds,
|
|
5118
|
+
]),
|
|
5119
|
+
];
|
|
5120
|
+
}
|
|
5121
|
+
if (event.mark_read && event.mark_read.length > 0) {
|
|
5122
|
+
newState.read_activities = [
|
|
5123
|
+
...new Set([
|
|
5124
|
+
...(currentNotificationStatus?.read_activities ?? []),
|
|
5125
|
+
...event.mark_read,
|
|
5126
|
+
]),
|
|
5127
|
+
];
|
|
5128
|
+
}
|
|
5129
|
+
if (event.mark_all_seen) {
|
|
5130
|
+
newState.last_seen_at = new Date();
|
|
5131
|
+
}
|
|
5132
|
+
return {
|
|
5133
|
+
changed: true,
|
|
5134
|
+
data: { notification_status: newState },
|
|
5135
|
+
};
|
|
5136
|
+
};
|
|
5137
|
+
function handleActivityMarked(event) {
|
|
5138
|
+
const result = updateNotificationStatusFromActivityMarked(event, this.currentState.notification_status, this.currentState.aggregated_activities);
|
|
5139
|
+
if (result.changed) {
|
|
5140
|
+
this.state.partialNext({
|
|
5141
|
+
notification_status: result.data?.notification_status,
|
|
5142
|
+
});
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
|
|
5076
5146
|
function handleFeedUpdated(event) {
|
|
5077
5147
|
this.state.partialNext({ ...event.feed });
|
|
5078
5148
|
}
|
|
5079
5149
|
|
|
5150
|
+
const updateNotificationFeedFromEvent = (event) => {
|
|
5151
|
+
const updates = {};
|
|
5152
|
+
if (event.notification_status) {
|
|
5153
|
+
updates.notification_status = event.notification_status;
|
|
5154
|
+
}
|
|
5155
|
+
if (event.aggregated_activities) {
|
|
5156
|
+
updates.aggregated_activities = event.aggregated_activities;
|
|
5157
|
+
}
|
|
5158
|
+
// Only return changed if we have actual updates
|
|
5159
|
+
if (Object.keys(updates).length > 0) {
|
|
5160
|
+
return {
|
|
5161
|
+
changed: true,
|
|
5162
|
+
data: updates,
|
|
5163
|
+
};
|
|
5164
|
+
}
|
|
5165
|
+
return {
|
|
5166
|
+
changed: false,
|
|
5167
|
+
};
|
|
5168
|
+
};
|
|
5080
5169
|
function handleNotificationFeedUpdated(event) {
|
|
5081
|
-
|
|
5082
|
-
|
|
5170
|
+
const result = updateNotificationFeedFromEvent(event);
|
|
5171
|
+
if (result.changed) {
|
|
5172
|
+
this.state.partialNext({
|
|
5173
|
+
notification_status: result.data?.notification_status,
|
|
5174
|
+
aggregated_activities: result.data?.aggregated_activities,
|
|
5175
|
+
});
|
|
5176
|
+
}
|
|
5083
5177
|
}
|
|
5084
5178
|
|
|
5085
5179
|
function handleWatchStarted() {
|
|
@@ -5134,7 +5228,7 @@ class Feed extends FeedApi {
|
|
|
5134
5228
|
'feeds.poll.vote_removed': Feed.noop,
|
|
5135
5229
|
'feeds.activity.pinned': Feed.noop,
|
|
5136
5230
|
'feeds.activity.unpinned': Feed.noop,
|
|
5137
|
-
'feeds.activity.marked':
|
|
5231
|
+
'feeds.activity.marked': handleActivityMarked.bind(this),
|
|
5138
5232
|
'moderation.custom_action': Feed.noop,
|
|
5139
5233
|
'moderation.flagged': Feed.noop,
|
|
5140
5234
|
'moderation.mark_reviewed': Feed.noop,
|
|
@@ -6006,10 +6100,10 @@ const useFeedsClient = () => {
|
|
|
6006
6100
|
*/
|
|
6007
6101
|
const useClientConnectedUser = () => {
|
|
6008
6102
|
const client = useFeedsClient();
|
|
6009
|
-
const { user } = useStateStore(client?.state, selector$
|
|
6103
|
+
const { user } = useStateStore(client?.state, selector$c) ?? {};
|
|
6010
6104
|
return user;
|
|
6011
6105
|
};
|
|
6012
|
-
const selector$
|
|
6106
|
+
const selector$c = (nextState) => ({
|
|
6013
6107
|
user: nextState.connected_user,
|
|
6014
6108
|
});
|
|
6015
6109
|
|
|
@@ -6018,10 +6112,10 @@ const selector$a = (nextState) => ({
|
|
|
6018
6112
|
*/
|
|
6019
6113
|
const useWsConnectionState = () => {
|
|
6020
6114
|
const client = useFeedsClient();
|
|
6021
|
-
const { is_healthy } = useStateStore(client?.state, selector$
|
|
6115
|
+
const { is_healthy } = useStateStore(client?.state, selector$b) ?? {};
|
|
6022
6116
|
return { is_healthy };
|
|
6023
6117
|
};
|
|
6024
|
-
const selector$
|
|
6118
|
+
const selector$b = (nextState) => ({
|
|
6025
6119
|
is_healthy: nextState.is_ws_connection_healthy,
|
|
6026
6120
|
});
|
|
6027
6121
|
|
|
@@ -6071,7 +6165,7 @@ const useStableCallback = (callback) => {
|
|
|
6071
6165
|
const useFeedActivities = (feedFromProps) => {
|
|
6072
6166
|
const feedFromContext = useFeedContext();
|
|
6073
6167
|
const feed = feedFromProps ?? feedFromContext;
|
|
6074
|
-
const data = useStateStore(feed?.state, selector$
|
|
6168
|
+
const data = useStateStore(feed?.state, selector$a);
|
|
6075
6169
|
const loadNextPage = useStableCallback(async () => {
|
|
6076
6170
|
if (!feed || !data?.has_next_page || data?.is_loading) {
|
|
6077
6171
|
return;
|
|
@@ -6080,7 +6174,7 @@ const useFeedActivities = (feedFromProps) => {
|
|
|
6080
6174
|
});
|
|
6081
6175
|
return react.useMemo(() => ({ ...data, loadNextPage }), [data, loadNextPage]);
|
|
6082
6176
|
};
|
|
6083
|
-
const selector$
|
|
6177
|
+
const selector$a = ({ is_loading_activities, next, activities = [] }) => ({
|
|
6084
6178
|
is_loading: is_loading_activities,
|
|
6085
6179
|
has_next_page: typeof next !== 'undefined',
|
|
6086
6180
|
activities,
|
|
@@ -6153,13 +6247,13 @@ const FeedOwnCapability = {
|
|
|
6153
6247
|
};
|
|
6154
6248
|
|
|
6155
6249
|
const stableEmptyArray = [];
|
|
6156
|
-
const selector$
|
|
6250
|
+
const selector$9 = (currentState) => ({
|
|
6157
6251
|
oc: currentState.own_capabilities ?? stableEmptyArray,
|
|
6158
6252
|
});
|
|
6159
6253
|
const useOwnCapabilities = (feedFromProps) => {
|
|
6160
6254
|
const feedFromContext = useFeedContext();
|
|
6161
6255
|
const feed = feedFromProps ?? feedFromContext;
|
|
6162
|
-
const { oc = stableEmptyArray } = useStateStore(feed?.state, selector$
|
|
6256
|
+
const { oc = stableEmptyArray } = useStateStore(feed?.state, selector$9) ?? {};
|
|
6163
6257
|
return react.useMemo(() => ({
|
|
6164
6258
|
can_add_activity: oc.indexOf(FeedOwnCapability.ADD_ACTIVITY) > -1,
|
|
6165
6259
|
can_add_activity_reaction: oc.indexOf(FeedOwnCapability.ADD_ACTIVITY_REACTION) > -1,
|
|
@@ -6194,7 +6288,7 @@ const useOwnCapabilities = (feedFromProps) => {
|
|
|
6194
6288
|
}), [oc]);
|
|
6195
6289
|
};
|
|
6196
6290
|
|
|
6197
|
-
const selector$
|
|
6291
|
+
const selector$8 = ({ follower_count, followers, followers_pagination, }) => ({
|
|
6198
6292
|
follower_count,
|
|
6199
6293
|
followers,
|
|
6200
6294
|
followers_pagination,
|
|
@@ -6202,7 +6296,7 @@ const selector$6 = ({ follower_count, followers, followers_pagination, }) => ({
|
|
|
6202
6296
|
function useFollowers(feedFromProps) {
|
|
6203
6297
|
const feedFromContext = useFeedContext();
|
|
6204
6298
|
const feed = feedFromProps ?? feedFromContext;
|
|
6205
|
-
const data = useStateStore(feed?.state, selector$
|
|
6299
|
+
const data = useStateStore(feed?.state, selector$8);
|
|
6206
6300
|
const loadNextPage = react.useCallback((...options) => feed?.loadNextPageFollowers(...options), [feed]);
|
|
6207
6301
|
return react.useMemo(() => {
|
|
6208
6302
|
if (!data) {
|
|
@@ -6217,7 +6311,7 @@ function useFollowers(feedFromProps) {
|
|
|
6217
6311
|
}, [data, loadNextPage]);
|
|
6218
6312
|
}
|
|
6219
6313
|
|
|
6220
|
-
const selector$
|
|
6314
|
+
const selector$7 = ({ following_count, following, following_pagination, }) => ({
|
|
6221
6315
|
following_count,
|
|
6222
6316
|
following,
|
|
6223
6317
|
following_pagination,
|
|
@@ -6225,7 +6319,7 @@ const selector$5 = ({ following_count, following, following_pagination, }) => ({
|
|
|
6225
6319
|
function useFollowing(feedFromProps) {
|
|
6226
6320
|
const feedFromContext = useFeedContext();
|
|
6227
6321
|
const feed = feedFromProps ?? feedFromContext;
|
|
6228
|
-
const data = useStateStore(feed?.state, selector$
|
|
6322
|
+
const data = useStateStore(feed?.state, selector$7);
|
|
6229
6323
|
const loadNextPage = react.useCallback((...options) => feed?.loadNextPageFollowing(...options), [feed]);
|
|
6230
6324
|
return react.useMemo(() => {
|
|
6231
6325
|
if (!data) {
|
|
@@ -6247,9 +6341,9 @@ function useFollowing(feedFromProps) {
|
|
|
6247
6341
|
const useFeedMetadata = (feedFromProps) => {
|
|
6248
6342
|
const feedFromContext = useFeedContext();
|
|
6249
6343
|
const feed = feedFromProps ?? feedFromContext;
|
|
6250
|
-
return useStateStore(feed?.state, selector$
|
|
6344
|
+
return useStateStore(feed?.state, selector$6);
|
|
6251
6345
|
};
|
|
6252
|
-
const selector$
|
|
6346
|
+
const selector$6 = ({ follower_count = 0, following_count = 0, created_by, created_at, updated_at, }) => ({
|
|
6253
6347
|
created_by,
|
|
6254
6348
|
follower_count,
|
|
6255
6349
|
following_count,
|
|
@@ -6264,12 +6358,57 @@ const selector$4 = ({ follower_count = 0, following_count = 0, created_by, creat
|
|
|
6264
6358
|
const useOwnFollows = (feedFromProps) => {
|
|
6265
6359
|
const feedFromContext = useFeedContext();
|
|
6266
6360
|
const feed = feedFromProps ?? feedFromContext;
|
|
6267
|
-
return useStateStore(feed?.state, selector$
|
|
6361
|
+
return useStateStore(feed?.state, selector$5);
|
|
6268
6362
|
};
|
|
6269
|
-
const selector$
|
|
6363
|
+
const selector$5 = ({ own_follows }) => ({
|
|
6270
6364
|
own_follows,
|
|
6271
6365
|
});
|
|
6272
6366
|
|
|
6367
|
+
const selector$4 = ({ notification_status }) => ({
|
|
6368
|
+
unread: notification_status?.unread ?? 0,
|
|
6369
|
+
unseen: notification_status?.unseen ?? 0,
|
|
6370
|
+
last_read_at: notification_status?.last_read_at,
|
|
6371
|
+
last_seen_at: notification_status?.last_seen_at,
|
|
6372
|
+
read_activities: notification_status?.read_activities,
|
|
6373
|
+
seen_activities: notification_status?.seen_activities,
|
|
6374
|
+
});
|
|
6375
|
+
function useNotificationStatus(feedFromProps) {
|
|
6376
|
+
const feedFromContext = useFeedContext();
|
|
6377
|
+
const feed = feedFromProps ?? feedFromContext;
|
|
6378
|
+
return useStateStore(feed?.state, selector$4);
|
|
6379
|
+
}
|
|
6380
|
+
|
|
6381
|
+
const selector$3 = ({ aggregated_activities }) => ({
|
|
6382
|
+
aggregated_activities,
|
|
6383
|
+
});
|
|
6384
|
+
function useAggregatedActivities(feedFromProps) {
|
|
6385
|
+
const feedFromContext = useFeedContext();
|
|
6386
|
+
const feed = feedFromProps ?? feedFromContext;
|
|
6387
|
+
return useStateStore(feed?.state, selector$3);
|
|
6388
|
+
}
|
|
6389
|
+
|
|
6390
|
+
const useIsAggregatedActivityRead = ({ feed: feedFromProps, aggregatedActivity, }) => {
|
|
6391
|
+
const feedFromContext = useFeedContext();
|
|
6392
|
+
const feed = feedFromProps ?? feedFromContext;
|
|
6393
|
+
const { read_activities: readActivities, /* last_read_at: lastReadAt */ } = useNotificationStatus(feed) ?? {};
|
|
6394
|
+
const group = aggregatedActivity.group;
|
|
6395
|
+
return react.useMemo(() =>
|
|
6396
|
+
// FIXME: This part of the condition does not work as marking individual groups as read also updates the last_read_at. Should be uncommented once it's fixed on the backend.
|
|
6397
|
+
// (lastReadAt &&
|
|
6398
|
+
// aggregatedActivity.updated_at.getTime() <= lastReadAt.getTime()) ||
|
|
6399
|
+
(readActivities ?? []).includes(group), [readActivities, group]);
|
|
6400
|
+
};
|
|
6401
|
+
|
|
6402
|
+
const useIsAggregatedActivitySeen = ({ feed: feedFromProps, aggregatedActivity, }) => {
|
|
6403
|
+
const feedFromContext = useFeedContext();
|
|
6404
|
+
const feed = feedFromProps ?? feedFromContext;
|
|
6405
|
+
const { seen_activities: seenActivities, last_seen_at: lastSeenAt } = useNotificationStatus(feed) ?? {};
|
|
6406
|
+
const group = aggregatedActivity.group;
|
|
6407
|
+
return react.useMemo(() => (lastSeenAt &&
|
|
6408
|
+
aggregatedActivity.updated_at.getTime() < lastSeenAt.getTime()) ||
|
|
6409
|
+
(seenActivities ?? []).includes(group), [lastSeenAt, aggregatedActivity.updated_at, seenActivities, group]);
|
|
6410
|
+
};
|
|
6411
|
+
|
|
6273
6412
|
const StreamSearchResultsContext = react.createContext(undefined);
|
|
6274
6413
|
/**
|
|
6275
6414
|
* Hook to access the nearest SearchSource instance.
|
|
@@ -6386,7 +6525,7 @@ const StreamFeeds = ({ client, children }) => {
|
|
|
6386
6525
|
};
|
|
6387
6526
|
StreamFeeds.displayName = 'StreamFeeds';
|
|
6388
6527
|
|
|
6389
|
-
const StreamFeed = ({ feed, children }) => {
|
|
6528
|
+
const StreamFeed = ({ feed, children, }) => {
|
|
6390
6529
|
return (jsxRuntime.jsx(StreamFeedContext.Provider, { value: feed, children: children }));
|
|
6391
6530
|
};
|
|
6392
6531
|
StreamFeed.displayName = 'StreamFeed';
|
|
@@ -6409,6 +6548,7 @@ exports.StreamSearch = StreamSearch;
|
|
|
6409
6548
|
exports.StreamSearchContext = StreamSearchContext;
|
|
6410
6549
|
exports.StreamSearchResults = StreamSearchResults;
|
|
6411
6550
|
exports.StreamSearchResultsContext = StreamSearchResultsContext;
|
|
6551
|
+
exports.useAggregatedActivities = useAggregatedActivities;
|
|
6412
6552
|
exports.useBookmarkActions = useBookmarkActions;
|
|
6413
6553
|
exports.useClientConnectedUser = useClientConnectedUser;
|
|
6414
6554
|
exports.useComments = useComments;
|
|
@@ -6419,6 +6559,9 @@ exports.useFeedMetadata = useFeedMetadata;
|
|
|
6419
6559
|
exports.useFeedsClient = useFeedsClient;
|
|
6420
6560
|
exports.useFollowers = useFollowers;
|
|
6421
6561
|
exports.useFollowing = useFollowing;
|
|
6562
|
+
exports.useIsAggregatedActivityRead = useIsAggregatedActivityRead;
|
|
6563
|
+
exports.useIsAggregatedActivitySeen = useIsAggregatedActivitySeen;
|
|
6564
|
+
exports.useNotificationStatus = useNotificationStatus;
|
|
6422
6565
|
exports.useOwnCapabilities = useOwnCapabilities;
|
|
6423
6566
|
exports.useOwnFollows = useOwnFollows;
|
|
6424
6567
|
exports.useReactionActions = useReactionActions;
|