@stream-io/feeds-client 0.1.9 → 0.1.11
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/search-state-hooks/index.ts +3 -0
- package/@react-bindings/index.ts +5 -0
- package/CHANGELOG.md +20 -0
- package/dist/@react-bindings/contexts/StreamFeedContext.d.ts +1 -1
- package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +1 -1
- package/dist/@react-bindings/contexts/StreamSearchContext.d.ts +12 -0
- package/dist/@react-bindings/contexts/StreamSearchResultsContext.d.ts +12 -0
- package/dist/@react-bindings/hooks/feed-state-hooks/useComments.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/useFeedActivities.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/useFeedMetadata.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/useFollowers.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/useFollowing.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/useOwnCapabilities.d.ts +1 -1
- package/dist/@react-bindings/hooks/feed-state-hooks/useOwnFollows.d.ts +1 -1
- package/dist/@react-bindings/hooks/search-state-hooks/index.d.ts +3 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchQuery.d.ts +4 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchResult.d.ts +8 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +4 -0
- package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +1 -1
- package/dist/@react-bindings/index.d.ts +5 -0
- package/dist/@react-bindings/wrappers/StreamFeed.d.ts +1 -1
- package/dist/@react-bindings/wrappers/StreamSearch.d.ts +12 -0
- package/dist/@react-bindings/wrappers/StreamSearchResults.d.ts +12 -0
- package/dist/index-react-bindings.browser.cjs +1669 -1529
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +1661 -1530
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +1669 -1529
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +1661 -1530
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +1615 -1640
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +1613 -1641
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.node.cjs +1615 -1640
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +1613 -1641
- package/dist/index.node.js.map +1 -1
- package/dist/src/common/ActivitySearchSource.d.ts +1 -1
- package/dist/src/common/BaseSearchSource.d.ts +3 -1
- package/dist/src/common/FeedSearchSource.d.ts +7 -3
- package/dist/src/common/Poll.d.ts +1 -1
- package/dist/src/common/SearchController.d.ts +2 -0
- package/dist/src/common/UserSearchSource.d.ts +1 -1
- package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
- package/dist/src/feed/event-handlers/activity/handle-activity-added.d.ts +7 -0
- package/dist/src/feed/event-handlers/activity/handle-activity-deleted.d.ts +8 -0
- package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +8 -0
- package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +8 -0
- package/dist/src/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts +3 -0
- package/dist/src/feed/event-handlers/activity/handle-activity-updated.d.ts +8 -0
- package/dist/src/feed/event-handlers/activity/index.d.ts +6 -0
- package/dist/src/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +8 -0
- package/dist/src/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +9 -0
- package/dist/src/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +8 -0
- package/dist/src/feed/event-handlers/bookmark/index.d.ts +3 -0
- package/dist/src/feed/event-handlers/comment/handle-comment-added.d.ts +3 -0
- package/dist/src/feed/event-handlers/comment/handle-comment-deleted.d.ts +3 -0
- package/dist/src/feed/event-handlers/comment/handle-comment-reaction.d.ts +3 -0
- package/dist/src/feed/event-handlers/comment/handle-comment-updated.d.ts +3 -0
- package/dist/src/feed/event-handlers/comment/index.d.ts +4 -0
- package/dist/src/feed/event-handlers/feed/handle-feed-updated.d.ts +3 -0
- package/dist/src/feed/event-handlers/feed/index.d.ts +1 -0
- package/dist/src/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +3 -0
- package/dist/src/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +3 -0
- package/dist/src/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +3 -0
- package/dist/src/feed/event-handlers/feed-member/index.d.ts +3 -0
- package/dist/src/feed/event-handlers/follow/handle-follow-created.d.ts +7 -0
- package/dist/src/feed/event-handlers/follow/handle-follow-deleted.d.ts +7 -0
- package/dist/src/feed/event-handlers/follow/handle-follow-updated.d.ts +3 -0
- package/dist/src/feed/event-handlers/follow/index.d.ts +3 -0
- package/dist/src/feed/event-handlers/index.d.ts +7 -0
- package/dist/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +3 -0
- package/dist/src/feed/event-handlers/notification-feed/index.d.ts +1 -0
- package/dist/src/{Feed.d.ts → feed/feed.d.ts} +15 -34
- package/dist/src/feed/index.d.ts +2 -0
- package/dist/src/{FeedsClient.d.ts → feeds-client.d.ts} +6 -5
- package/dist/src/gen/models/index.d.ts +5 -0
- package/dist/src/gen-imports.d.ts +1 -1
- package/dist/src/test-utils/index.d.ts +1 -0
- package/dist/src/test-utils/response-generators.d.ts +9 -0
- package/dist/src/types-internal.d.ts +7 -0
- package/dist/src/types.d.ts +1 -1
- package/dist/src/utils/check-has-another-page.d.ts +1 -0
- package/dist/src/utils/constants.d.ts +3 -0
- package/dist/src/utils/index.d.ts +5 -0
- package/dist/src/utils/state-update-queue.d.ts +6 -0
- package/dist/src/utils/type-assertions.d.ts +7 -0
- package/dist/src/utils/unique-array-merge.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/index.ts +2 -2
- package/package.json +2 -1
- package/src/common/ActivitySearchSource.ts +6 -16
- package/src/common/BaseSearchSource.ts +9 -9
- package/src/common/FeedSearchSource.ts +22 -67
- package/src/common/Poll.ts +1 -1
- package/src/common/SearchController.ts +2 -0
- package/src/common/UserSearchSource.ts +10 -62
- package/src/{state-updates → feed/event-handlers/activity}/activity-reaction-utils.test.ts +12 -2
- package/src/{state-updates → feed/event-handlers/activity}/activity-utils.test.ts +3 -2
- package/src/{state-updates/activity-utils.ts → feed/event-handlers/activity/handle-activity-added.ts} +16 -36
- package/src/feed/event-handlers/activity/handle-activity-deleted.ts +30 -0
- package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +67 -0
- package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +75 -0
- package/src/feed/event-handlers/activity/handle-activity-removed-from-feed.ts +16 -0
- package/src/feed/event-handlers/activity/handle-activity-updated.ts +47 -0
- package/src/feed/event-handlers/activity/index.ts +6 -0
- package/src/{state-updates → feed/event-handlers/bookmark}/bookmark-utils.test.ts +2 -2
- package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +63 -0
- package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +84 -0
- package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +76 -0
- package/src/feed/event-handlers/bookmark/index.ts +3 -0
- package/src/feed/event-handlers/comment/handle-comment-added.ts +38 -0
- package/src/feed/event-handlers/comment/handle-comment-deleted.ts +35 -0
- package/src/feed/event-handlers/comment/handle-comment-reaction.ts +61 -0
- package/src/feed/event-handlers/comment/handle-comment-updated.ts +35 -0
- package/src/feed/event-handlers/comment/index.ts +4 -0
- package/src/feed/event-handlers/feed/handle-feed-updated.ts +9 -0
- package/src/feed/event-handlers/feed/index.ts +1 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-added.ts +31 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +24 -0
- package/src/feed/event-handlers/feed-member/handle-feed-member-updated.ts +40 -0
- package/src/feed/event-handlers/feed-member/index.ts +3 -0
- package/src/feed/event-handlers/follow/handle-follow-created.test.ts +246 -0
- package/src/feed/event-handlers/follow/handle-follow-created.ts +93 -0
- package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +264 -0
- package/src/feed/event-handlers/follow/handle-follow-deleted.ts +95 -0
- package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +174 -0
- package/src/feed/event-handlers/follow/handle-follow-updated.ts +88 -0
- package/src/feed/event-handlers/follow/index.ts +3 -0
- package/src/feed/event-handlers/index.ts +7 -0
- package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +10 -0
- package/src/feed/event-handlers/notification-feed/index.ts +1 -0
- package/src/{Feed.ts → feed/feed.ts} +72 -483
- package/src/feed/index.ts +2 -0
- package/src/{FeedsClient.ts → feeds-client.ts} +26 -8
- package/src/gen/model-decoders/decoders.ts +7 -0
- package/src/gen/models/index.ts +10 -0
- package/src/gen-imports.ts +1 -1
- package/src/test-utils/index.ts +1 -0
- package/src/test-utils/response-generators.ts +102 -0
- package/src/types-internal.ts +11 -0
- package/src/types.ts +1 -1
- package/src/utils/check-has-another-page.ts +6 -0
- package/src/utils/constants.ts +3 -0
- package/src/utils/index.ts +5 -0
- package/src/{state-updates → utils}/state-update-queue.test.ts +6 -6
- package/src/utils/state-update-queue.ts +42 -0
- package/src/utils/type-assertions.ts +22 -0
- package/src/{utils.test.ts → utils/unique-array-merge.test.ts} +7 -3
- package/src/utils/unique-array-merge.ts +19 -0
- package/dist/src/state-updates/activity-reaction-utils.d.ts +0 -10
- package/dist/src/state-updates/activity-utils.d.ts +0 -13
- package/dist/src/state-updates/bookmark-utils.d.ts +0 -14
- package/dist/src/state-updates/follow-utils.d.ts +0 -19
- package/dist/src/state-updates/state-update-queue.d.ts +0 -15
- package/dist/src/utils.d.ts +0 -10
- package/src/state-updates/activity-reaction-utils.ts +0 -107
- package/src/state-updates/bookmark-utils.ts +0 -167
- package/src/state-updates/follow-utils.test.ts +0 -552
- package/src/state-updates/follow-utils.ts +0 -126
- package/src/state-updates/state-update-queue.ts +0 -35
- package/src/utils.ts +0 -48
- /package/dist/src/{ModerationClient.d.ts → moderation-client.d.ts} +0 -0
- /package/src/{ModerationClient.ts → moderation-client.ts} +0 -0
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/feeds-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "./dist/index.node.js",
|
|
6
6
|
"exports": {
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"@types/react": "^19.1.8",
|
|
68
68
|
"@vitest/coverage-v8": "3.2.4",
|
|
69
69
|
"dotenv": "^16.4.5",
|
|
70
|
+
"human-id": "^4.1.1",
|
|
70
71
|
"react": "19.0.0",
|
|
71
72
|
"rimraf": "^6.0.1",
|
|
72
73
|
"rollup": "^4.24.0",
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { BaseSearchSource } from './BaseSearchSource';
|
|
2
2
|
import type { SearchSourceOptions } from './BaseSearchSource';
|
|
3
3
|
|
|
4
|
-
import { FeedsClient } from '../
|
|
4
|
+
import { FeedsClient } from '../feeds-client';
|
|
5
5
|
import { ActivityResponse } from '../gen/models';
|
|
6
6
|
|
|
7
7
|
export class ActivitySearchSource extends BaseSearchSource<ActivityResponse> {
|
|
8
8
|
readonly type = 'activity' as const;
|
|
9
9
|
private readonly client: FeedsClient;
|
|
10
|
-
// messageSearchChannelFilters: ChannelFilters | undefined;
|
|
11
|
-
// messageSearchFilters: MessageFilters | undefined;
|
|
12
|
-
// messageSearchSort: SearchMessageSort | undefined;
|
|
13
|
-
// channelQueryFilters: ChannelFilters | undefined;
|
|
14
|
-
// channelQuerySort: ChannelSort | undefined;
|
|
15
|
-
// channelQueryOptions: Omit<ChannelOptions, 'limit' | 'offset'> | undefined;
|
|
16
10
|
|
|
17
11
|
constructor(client: FeedsClient, options?: SearchSourceOptions) {
|
|
18
12
|
super(options);
|
|
@@ -20,12 +14,15 @@ export class ActivitySearchSource extends BaseSearchSource<ActivityResponse> {
|
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
protected async query(searchQuery: string) {
|
|
23
|
-
const { connected_user: connectedUser } =
|
|
17
|
+
const { connected_user: connectedUser } =
|
|
18
|
+
this.client.state.getLatestValue();
|
|
24
19
|
if (!connectedUser) return { items: [] };
|
|
25
20
|
|
|
26
21
|
const { activities: items, next } = await this.client.queryActivities({
|
|
27
22
|
sort: [{ direction: -1, field: 'created_at' }],
|
|
28
|
-
|
|
23
|
+
...(!this.allowEmptySearchString || searchQuery.length > 0
|
|
24
|
+
? { filter: { text: { $autocomplete: searchQuery } } }
|
|
25
|
+
: {}),
|
|
29
26
|
limit: 10,
|
|
30
27
|
next: this.next ?? undefined,
|
|
31
28
|
});
|
|
@@ -37,10 +34,3 @@ export class ActivitySearchSource extends BaseSearchSource<ActivityResponse> {
|
|
|
37
34
|
return items;
|
|
38
35
|
}
|
|
39
36
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// filter: {
|
|
43
|
-
// 'feed.name': { $autocomplete: searchQuery }
|
|
44
|
-
// 'feed.description': { $autocomplete: searchQuery }
|
|
45
|
-
// 'created_by.name': { $autocomplete: searchQuery }
|
|
46
|
-
// },
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { StateStore } from './StateStore';
|
|
2
2
|
import { debounce, type DebouncedFunc } from './utils';
|
|
3
3
|
|
|
4
|
-
export type SearchSourceType =
|
|
5
|
-
|
|
6
|
-
| 'users'
|
|
7
|
-
| 'messages'
|
|
8
|
-
| (string & {});
|
|
4
|
+
export type SearchSourceType = 'activity' | 'user' | 'feed' | (string & {});
|
|
5
|
+
|
|
9
6
|
export type QueryReturnValue<T> = { items: T[]; next?: string | null };
|
|
7
|
+
|
|
10
8
|
export type DebounceOptions = {
|
|
11
9
|
debounceMs: number;
|
|
12
10
|
};
|
|
@@ -14,7 +12,6 @@ type DebouncedExecQueryFunction = DebouncedFunc<
|
|
|
14
12
|
(searchString?: string) => Promise<void>
|
|
15
13
|
>;
|
|
16
14
|
|
|
17
|
-
|
|
18
15
|
export interface SearchSource<T = any> {
|
|
19
16
|
activate(): void;
|
|
20
17
|
|
|
@@ -46,7 +43,6 @@ export interface SearchSource<T = any> {
|
|
|
46
43
|
readonly type: SearchSourceType;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
|
|
50
46
|
export type SearchSourceState<T = any> = {
|
|
51
47
|
hasNext: boolean;
|
|
52
48
|
isActive: boolean;
|
|
@@ -61,24 +57,28 @@ export type SearchSourceOptions = {
|
|
|
61
57
|
/** The number of milliseconds to debounce the search query. The default interval is 300ms. */
|
|
62
58
|
debounceMs?: number;
|
|
63
59
|
pageSize?: number;
|
|
60
|
+
allowEmptySearchString?: boolean;
|
|
64
61
|
};
|
|
65
62
|
const DEFAULT_SEARCH_SOURCE_OPTIONS: Required<SearchSourceOptions> = {
|
|
66
63
|
debounceMs: 300,
|
|
67
64
|
pageSize: 10,
|
|
65
|
+
allowEmptySearchString: false,
|
|
68
66
|
} as const;
|
|
69
67
|
|
|
70
68
|
export abstract class BaseSearchSource<T> implements SearchSource<T> {
|
|
71
69
|
state: StateStore<SearchSourceState<T>>;
|
|
72
70
|
protected pageSize: number;
|
|
71
|
+
protected allowEmptySearchString: boolean;
|
|
73
72
|
abstract readonly type: SearchSourceType;
|
|
74
73
|
protected searchDebounced!: DebouncedExecQueryFunction;
|
|
75
74
|
|
|
76
75
|
protected constructor(options?: SearchSourceOptions) {
|
|
77
|
-
const { debounceMs, pageSize } = {
|
|
76
|
+
const { debounceMs, pageSize, allowEmptySearchString } = {
|
|
78
77
|
...DEFAULT_SEARCH_SOURCE_OPTIONS,
|
|
79
78
|
...options,
|
|
80
79
|
};
|
|
81
80
|
this.pageSize = pageSize;
|
|
81
|
+
this.allowEmptySearchString = allowEmptySearchString;
|
|
82
82
|
this.state = new StateStore<SearchSourceState<T>>(this.initialState);
|
|
83
83
|
this.setDebounceOptions({ debounceMs });
|
|
84
84
|
}
|
|
@@ -157,7 +157,7 @@ export abstract class BaseSearchSource<T> implements SearchSource<T> {
|
|
|
157
157
|
this.isActive &&
|
|
158
158
|
!this.isLoading &&
|
|
159
159
|
(this.hasNext || hasNewSearchQuery) &&
|
|
160
|
-
searchString
|
|
160
|
+
(this.allowEmptySearchString || searchString)
|
|
161
161
|
);
|
|
162
162
|
};
|
|
163
163
|
|
|
@@ -1,88 +1,43 @@
|
|
|
1
1
|
import { BaseSearchSource } from './BaseSearchSource';
|
|
2
2
|
import type { SearchSourceOptions } from './BaseSearchSource';
|
|
3
3
|
|
|
4
|
-
import { FeedsClient } from '../
|
|
5
|
-
import { Feed } from '../
|
|
4
|
+
import { FeedsClient } from '../feeds-client';
|
|
5
|
+
import { Feed } from '../feed';
|
|
6
|
+
|
|
7
|
+
export type FeedSearchSourceOptions = SearchSourceOptions & {
|
|
8
|
+
groupId?: string;
|
|
9
|
+
};
|
|
6
10
|
|
|
7
11
|
export class FeedSearchSource extends BaseSearchSource<Feed> {
|
|
8
12
|
readonly type = 'feed' as const;
|
|
9
13
|
private readonly client: FeedsClient;
|
|
10
|
-
|
|
11
|
-
// messageSearchFilters: MessageFilters | undefined;
|
|
12
|
-
// messageSearchSort: SearchMessageSort | undefined;
|
|
13
|
-
// channelQueryFilters: ChannelFilters | undefined;
|
|
14
|
-
// channelQuerySort: ChannelSort | undefined;
|
|
15
|
-
// channelQueryOptions: Omit<ChannelOptions, 'limit' | 'offset'> | undefined;
|
|
14
|
+
private readonly feedGroupId?: string | undefined;
|
|
16
15
|
|
|
17
|
-
constructor(client: FeedsClient, options?:
|
|
16
|
+
constructor(client: FeedsClient, options?: FeedSearchSourceOptions) {
|
|
18
17
|
super(options);
|
|
19
18
|
this.client = client;
|
|
19
|
+
this.feedGroupId = options?.groupId;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
protected async query(searchQuery: string) {
|
|
23
|
-
const { connected_user: connectedUser } =
|
|
23
|
+
const { connected_user: connectedUser } =
|
|
24
|
+
this.client.state.getLatestValue();
|
|
24
25
|
if (!connectedUser) return { items: [] };
|
|
25
26
|
|
|
26
|
-
// const channelFilters: ChannelFilters = {
|
|
27
|
-
// members: { $in: [this.client.userID] },
|
|
28
|
-
// ...this.messageSearchChannelFilters,
|
|
29
|
-
// } as ChannelFilters;
|
|
30
|
-
|
|
31
|
-
// const messageFilters: MessageFilters = {
|
|
32
|
-
// text: searchQuery,
|
|
33
|
-
// type: 'regular', // FIXME: type: 'reply' resp. do not filter by type and allow to jump to a message in a thread - missing support
|
|
34
|
-
// ...this.messageSearchFilters,
|
|
35
|
-
// } as MessageFilters;
|
|
36
|
-
|
|
37
|
-
// const sort: SearchMessageSort = {
|
|
38
|
-
// created_at: -1,
|
|
39
|
-
// ...this.messageSearchSort,
|
|
40
|
-
// };
|
|
41
|
-
|
|
42
|
-
// const options = {
|
|
43
|
-
// limit: this.pageSize,
|
|
44
|
-
// next: this.next,
|
|
45
|
-
// sort,
|
|
46
|
-
// } as SearchOptions;
|
|
47
|
-
|
|
48
|
-
// const { next, results } = await this.client.search(
|
|
49
|
-
// channelFilters,
|
|
50
|
-
// messageFilters,
|
|
51
|
-
// options,
|
|
52
|
-
// );
|
|
53
|
-
// const items = results.map(({ message }) => message);
|
|
54
|
-
|
|
55
|
-
// const cids = Array.from(
|
|
56
|
-
// items.reduce((acc, message) => {
|
|
57
|
-
// if (message.cid && !this.client.activeChannels[message.cid])
|
|
58
|
-
// acc.add(message.cid);
|
|
59
|
-
// return acc;
|
|
60
|
-
// }, new Set<string>()), // keep the cids unique
|
|
61
|
-
// );
|
|
62
|
-
// const allChannelsLoadedLocally = cids.length === 0;
|
|
63
|
-
// if (!allChannelsLoadedLocally) {
|
|
64
|
-
// await this.client.queryChannels(
|
|
65
|
-
// {
|
|
66
|
-
// cid: { $in: cids },
|
|
67
|
-
// ...this.channelQueryFilters,
|
|
68
|
-
// } as ChannelFilters,
|
|
69
|
-
// {
|
|
70
|
-
// last_message_at: -1,
|
|
71
|
-
// ...this.channelQuerySort,
|
|
72
|
-
// },
|
|
73
|
-
// this.channelQueryOptions,
|
|
74
|
-
// );
|
|
75
|
-
// }
|
|
76
|
-
|
|
77
27
|
const { feeds: items, next } = await this.client.queryFeeds({
|
|
78
28
|
filter: {
|
|
79
|
-
group_id:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
29
|
+
...(this.feedGroupId ? { group_id: this.feedGroupId } : {}),
|
|
30
|
+
...(!this.allowEmptySearchString || searchQuery.length > 0
|
|
31
|
+
? {
|
|
32
|
+
$or: [
|
|
33
|
+
{ name: { $autocomplete: searchQuery } },
|
|
34
|
+
{ description: { $autocomplete: searchQuery } },
|
|
35
|
+
{ 'created_by.name': { $autocomplete: searchQuery } },
|
|
36
|
+
],
|
|
37
|
+
}
|
|
38
|
+
: {}),
|
|
85
39
|
},
|
|
40
|
+
next: this.next ?? undefined,
|
|
86
41
|
});
|
|
87
42
|
|
|
88
43
|
return { items, next };
|
package/src/common/Poll.ts
CHANGED
|
@@ -23,6 +23,8 @@ export class SearchController {
|
|
|
23
23
|
/**
|
|
24
24
|
* Not intended for direct use by integrators, might be removed without notice resulting in
|
|
25
25
|
* broken integrations.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
26
28
|
*/
|
|
27
29
|
_internalState: StateStore<InternalSearchControllerState>;
|
|
28
30
|
state: StateStore<SearchControllerState>;
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { BaseSearchSource } from './BaseSearchSource';
|
|
2
2
|
import type { SearchSourceOptions } from './BaseSearchSource';
|
|
3
3
|
|
|
4
|
-
import { FeedsClient } from '../
|
|
4
|
+
import { FeedsClient } from '../feeds-client';
|
|
5
5
|
import { UserResponse } from '../gen/models';
|
|
6
6
|
|
|
7
7
|
export class UserSearchSource extends BaseSearchSource<UserResponse> {
|
|
8
8
|
readonly type = 'user' as const;
|
|
9
9
|
private readonly client: FeedsClient;
|
|
10
|
-
// messageSearchChannelFilters: ChannelFilters | undefined;
|
|
11
|
-
// messageSearchFilters: MessageFilters | undefined;
|
|
12
|
-
// messageSearchSort: SearchMessageSort | undefined;
|
|
13
|
-
// channelQueryFilters: ChannelFilters | undefined;
|
|
14
|
-
// channelQuerySort: ChannelSort | undefined;
|
|
15
|
-
// channelQueryOptions: Omit<ChannelOptions, 'limit' | 'offset'> | undefined;
|
|
16
10
|
|
|
17
11
|
constructor(client: FeedsClient, options?: SearchSourceOptions) {
|
|
18
12
|
super(options);
|
|
@@ -20,66 +14,20 @@ export class UserSearchSource extends BaseSearchSource<UserResponse> {
|
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
protected async query(searchQuery: string) {
|
|
23
|
-
const { connected_user: connectedUser } =
|
|
17
|
+
const { connected_user: connectedUser } =
|
|
18
|
+
this.client.state.getLatestValue();
|
|
24
19
|
if (!connectedUser) return { items: [] };
|
|
25
20
|
|
|
26
|
-
// const channelFilters: ChannelFilters = {
|
|
27
|
-
// members: { $in: [this.client.userID] },
|
|
28
|
-
// ...this.messageSearchChannelFilters,
|
|
29
|
-
// } as ChannelFilters;
|
|
30
|
-
|
|
31
|
-
// const messageFilters: MessageFilters = {
|
|
32
|
-
// text: searchQuery,
|
|
33
|
-
// type: 'regular', // FIXME: type: 'reply' resp. do not filter by type and allow to jump to a message in a thread - missing support
|
|
34
|
-
// ...this.messageSearchFilters,
|
|
35
|
-
// } as MessageFilters;
|
|
36
|
-
|
|
37
|
-
// const sort: SearchMessageSort = {
|
|
38
|
-
// created_at: -1,
|
|
39
|
-
// ...this.messageSearchSort,
|
|
40
|
-
// };
|
|
41
|
-
|
|
42
|
-
// const options = {
|
|
43
|
-
// limit: this.pageSize,
|
|
44
|
-
// next: this.next,
|
|
45
|
-
// sort,
|
|
46
|
-
// } as SearchOptions;
|
|
47
|
-
|
|
48
|
-
// const { next, results } = await this.client.search(
|
|
49
|
-
// channelFilters,
|
|
50
|
-
// messageFilters,
|
|
51
|
-
// options,
|
|
52
|
-
// );
|
|
53
|
-
// const items = results.map(({ message }) => message);
|
|
54
|
-
|
|
55
|
-
// const cids = Array.from(
|
|
56
|
-
// items.reduce((acc, message) => {
|
|
57
|
-
// if (message.cid && !this.client.activeChannels[message.cid])
|
|
58
|
-
// acc.add(message.cid);
|
|
59
|
-
// return acc;
|
|
60
|
-
// }, new Set<string>()), // keep the cids unique
|
|
61
|
-
// );
|
|
62
|
-
// const allChannelsLoadedLocally = cids.length === 0;
|
|
63
|
-
// if (!allChannelsLoadedLocally) {
|
|
64
|
-
// await this.client.queryChannels(
|
|
65
|
-
// {
|
|
66
|
-
// cid: { $in: cids },
|
|
67
|
-
// ...this.channelQueryFilters,
|
|
68
|
-
// } as ChannelFilters,
|
|
69
|
-
// {
|
|
70
|
-
// last_message_at: -1,
|
|
71
|
-
// ...this.channelQuerySort,
|
|
72
|
-
// },
|
|
73
|
-
// this.channelQueryOptions,
|
|
74
|
-
// );
|
|
75
|
-
// }
|
|
76
|
-
|
|
77
21
|
const { users: items } = await this.client.queryUsers({
|
|
78
22
|
payload: {
|
|
79
23
|
filter_conditions: {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
24
|
+
...(!this.allowEmptySearchString || searchQuery.length > 0
|
|
25
|
+
? {
|
|
26
|
+
name: {
|
|
27
|
+
$autocomplete: searchQuery,
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
: {}),
|
|
83
31
|
},
|
|
84
32
|
},
|
|
85
33
|
});
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
ActivityReactionDeletedEvent,
|
|
5
5
|
ActivityResponse,
|
|
6
6
|
FeedsReactionResponse,
|
|
7
|
-
} from '
|
|
7
|
+
} from '../../../gen/models';
|
|
8
8
|
import {
|
|
9
9
|
addReactionToActivity,
|
|
10
10
|
removeReactionFromActivity,
|
|
11
11
|
addReactionToActivities,
|
|
12
12
|
removeReactionFromActivities,
|
|
13
|
-
} from './
|
|
13
|
+
} from './';
|
|
14
14
|
|
|
15
15
|
const createMockActivity = (id: string): ActivityResponse => ({
|
|
16
16
|
id,
|
|
@@ -109,6 +109,7 @@ describe('activity-reaction-utils', () => {
|
|
|
109
109
|
count: 1,
|
|
110
110
|
first_reaction_at: reaction.created_at,
|
|
111
111
|
last_reaction_at: reaction.created_at,
|
|
112
|
+
sum_scores: 0,
|
|
112
113
|
},
|
|
113
114
|
};
|
|
114
115
|
|
|
@@ -123,6 +124,7 @@ describe('activity-reaction-utils', () => {
|
|
|
123
124
|
count: 1,
|
|
124
125
|
first_reaction_at: reaction.created_at,
|
|
125
126
|
last_reaction_at: reaction.created_at,
|
|
127
|
+
sum_scores: 0,
|
|
126
128
|
});
|
|
127
129
|
});
|
|
128
130
|
|
|
@@ -136,6 +138,7 @@ describe('activity-reaction-utils', () => {
|
|
|
136
138
|
count: 1,
|
|
137
139
|
first_reaction_at: reaction.created_at,
|
|
138
140
|
last_reaction_at: reaction.created_at,
|
|
141
|
+
sum_scores: 0,
|
|
139
142
|
},
|
|
140
143
|
};
|
|
141
144
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -150,6 +153,7 @@ describe('activity-reaction-utils', () => {
|
|
|
150
153
|
count: 1,
|
|
151
154
|
first_reaction_at: reaction.created_at,
|
|
152
155
|
last_reaction_at: reaction.created_at,
|
|
156
|
+
sum_scores: 0,
|
|
153
157
|
});
|
|
154
158
|
});
|
|
155
159
|
});
|
|
@@ -165,6 +169,7 @@ describe('activity-reaction-utils', () => {
|
|
|
165
169
|
count: 1,
|
|
166
170
|
first_reaction_at: reaction.created_at,
|
|
167
171
|
last_reaction_at: reaction.created_at,
|
|
172
|
+
sum_scores: 0,
|
|
168
173
|
},
|
|
169
174
|
};
|
|
170
175
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -196,6 +201,7 @@ describe('activity-reaction-utils', () => {
|
|
|
196
201
|
count: 1,
|
|
197
202
|
first_reaction_at: reaction.created_at,
|
|
198
203
|
last_reaction_at: reaction.created_at,
|
|
204
|
+
sum_scores: 0,
|
|
199
205
|
},
|
|
200
206
|
};
|
|
201
207
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -230,6 +236,7 @@ describe('activity-reaction-utils', () => {
|
|
|
230
236
|
count: 1,
|
|
231
237
|
first_reaction_at: reaction.created_at,
|
|
232
238
|
last_reaction_at: reaction.created_at,
|
|
239
|
+
sum_scores: 0,
|
|
233
240
|
},
|
|
234
241
|
};
|
|
235
242
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -253,6 +260,7 @@ describe('activity-reaction-utils', () => {
|
|
|
253
260
|
count: 1,
|
|
254
261
|
first_reaction_at: reaction.created_at,
|
|
255
262
|
last_reaction_at: reaction.created_at,
|
|
263
|
+
sum_scores: 0,
|
|
256
264
|
},
|
|
257
265
|
};
|
|
258
266
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -274,6 +282,7 @@ describe('activity-reaction-utils', () => {
|
|
|
274
282
|
count: 1,
|
|
275
283
|
first_reaction_at: reaction.created_at,
|
|
276
284
|
last_reaction_at: reaction.created_at,
|
|
285
|
+
sum_scores: 0,
|
|
277
286
|
},
|
|
278
287
|
};
|
|
279
288
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -296,6 +305,7 @@ describe('activity-reaction-utils', () => {
|
|
|
296
305
|
count: 1,
|
|
297
306
|
first_reaction_at: reaction.created_at,
|
|
298
307
|
last_reaction_at: reaction.created_at,
|
|
308
|
+
sum_scores: 0,
|
|
299
309
|
},
|
|
300
310
|
};
|
|
301
311
|
const event = createMockAddedEvent(reaction, eventActivity);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { ActivityResponse, FeedsReactionResponse } from '
|
|
2
|
+
import { ActivityResponse, FeedsReactionResponse } from '../../../gen/models';
|
|
3
3
|
import {
|
|
4
4
|
addActivitiesToState,
|
|
5
5
|
updateActivityInState,
|
|
6
6
|
removeActivityFromState,
|
|
7
|
-
} from './
|
|
7
|
+
} from './';
|
|
8
8
|
|
|
9
9
|
const createMockActivity = (id: string, text?: string): ActivityResponse =>
|
|
10
10
|
({
|
|
@@ -181,6 +181,7 @@ describe('activity-utils', () => {
|
|
|
181
181
|
];
|
|
182
182
|
originalActivity.reaction_groups = {
|
|
183
183
|
like: {
|
|
184
|
+
sum_scores: 0,
|
|
184
185
|
count: 1,
|
|
185
186
|
first_reaction_at: new Date(),
|
|
186
187
|
last_reaction_at: new Date(),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Feed } from '../../../feed';
|
|
2
|
+
import { ActivityResponse } from '../../../gen/models';
|
|
3
|
+
import { EventPayload, UpdateStateResult } from '../../../types-internal';
|
|
3
4
|
|
|
4
5
|
export const addActivitiesToState = (
|
|
5
6
|
newActivities: ActivityResponse[],
|
|
@@ -42,39 +43,18 @@ export const addActivitiesToState = (
|
|
|
42
43
|
return result;
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
)
|
|
49
|
-
const
|
|
50
|
-
|
|
46
|
+
export function handleActivityAdded(
|
|
47
|
+
this: Feed,
|
|
48
|
+
event: EventPayload<'feeds.activity.added'>,
|
|
49
|
+
) {
|
|
50
|
+
const currentActivities = this.currentState.activities;
|
|
51
|
+
const result = addActivitiesToState(
|
|
52
|
+
[event.activity],
|
|
53
|
+
currentActivities,
|
|
54
|
+
'start',
|
|
51
55
|
);
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
newActivities[index] = {
|
|
56
|
-
...updatedActivityResponse,
|
|
57
|
-
own_reactions: activity.own_reactions,
|
|
58
|
-
own_bookmarks: activity.own_bookmarks,
|
|
59
|
-
latest_reactions: activity.latest_reactions,
|
|
60
|
-
reaction_groups: activity.reaction_groups,
|
|
61
|
-
};
|
|
62
|
-
return { changed: true, activities: newActivities };
|
|
63
|
-
} else {
|
|
64
|
-
return { changed: false, activities };
|
|
56
|
+
if (result.changed) {
|
|
57
|
+
this.client.hydratePollCache([event.activity]);
|
|
58
|
+
this.state.partialNext({ activities: result.activities });
|
|
65
59
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const removeActivityFromState = (
|
|
69
|
-
activityResponse: ActivityResponse,
|
|
70
|
-
activities: ActivityResponse[],
|
|
71
|
-
) => {
|
|
72
|
-
const index = activities.findIndex((a) => a.id === activityResponse.id);
|
|
73
|
-
if (index !== -1) {
|
|
74
|
-
const newActivities = [...activities];
|
|
75
|
-
newActivities.splice(index, 1);
|
|
76
|
-
return { changed: true, activities: newActivities };
|
|
77
|
-
} else {
|
|
78
|
-
return { changed: false, activities };
|
|
79
|
-
}
|
|
80
|
-
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Feed } from '../../../feed';
|
|
2
|
+
import type { ActivityResponse } from '../../../gen/models';
|
|
3
|
+
import type { EventPayload } from '../../../types-internal';
|
|
4
|
+
|
|
5
|
+
export const removeActivityFromState = (
|
|
6
|
+
activityResponse: ActivityResponse,
|
|
7
|
+
activities: ActivityResponse[],
|
|
8
|
+
) => {
|
|
9
|
+
const index = activities.findIndex((a) => a.id === activityResponse.id);
|
|
10
|
+
if (index !== -1) {
|
|
11
|
+
const newActivities = [...activities];
|
|
12
|
+
newActivities.splice(index, 1);
|
|
13
|
+
return { changed: true, activities: newActivities };
|
|
14
|
+
} else {
|
|
15
|
+
return { changed: false, activities };
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function handleActivityDeleted(
|
|
20
|
+
this: Feed,
|
|
21
|
+
event: EventPayload<'feeds.activity.deleted'>,
|
|
22
|
+
) {
|
|
23
|
+
const currentActivities = this.currentState.activities;
|
|
24
|
+
if (currentActivities) {
|
|
25
|
+
const result = removeActivityFromState(event.activity, currentActivities);
|
|
26
|
+
if (result.changed) {
|
|
27
|
+
this.state.partialNext({ activities: result.activities });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Feed } from '../../../feed';
|
|
2
|
+
import type {
|
|
3
|
+
ActivityReactionAddedEvent,
|
|
4
|
+
ActivityResponse,
|
|
5
|
+
} from '../../../gen/models';
|
|
6
|
+
import type { EventPayload, UpdateStateResult } from '../../../types-internal';
|
|
7
|
+
|
|
8
|
+
import { updateActivityInState } from './handle-activity-updated';
|
|
9
|
+
|
|
10
|
+
export const addReactionToActivity = (
|
|
11
|
+
event: ActivityReactionAddedEvent,
|
|
12
|
+
activity: ActivityResponse,
|
|
13
|
+
isCurrentUser: boolean,
|
|
14
|
+
): UpdateStateResult<ActivityResponse> => {
|
|
15
|
+
// Update own_reactions if the reaction is from the current user
|
|
16
|
+
const ownReactions = [...(activity.own_reactions || [])];
|
|
17
|
+
if (isCurrentUser) {
|
|
18
|
+
ownReactions.push(event.reaction);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
...activity,
|
|
23
|
+
own_reactions: ownReactions,
|
|
24
|
+
latest_reactions: event.activity.latest_reactions,
|
|
25
|
+
reaction_groups: event.activity.reaction_groups,
|
|
26
|
+
changed: true,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const addReactionToActivities = (
|
|
31
|
+
event: ActivityReactionAddedEvent,
|
|
32
|
+
activities: ActivityResponse[] | undefined,
|
|
33
|
+
isCurrentUser: boolean,
|
|
34
|
+
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
35
|
+
if (!activities) {
|
|
36
|
+
return { changed: false, activities: [] };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
40
|
+
if (activityIndex === -1) {
|
|
41
|
+
return { changed: false, activities };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const activity = activities[activityIndex];
|
|
45
|
+
const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
|
|
46
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export function handleActivityReactionAdded(
|
|
50
|
+
this: Feed,
|
|
51
|
+
event: EventPayload<'feeds.activity.reaction.added'>,
|
|
52
|
+
) {
|
|
53
|
+
const currentActivities = this.currentState.activities;
|
|
54
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
55
|
+
const isCurrentUser = Boolean(
|
|
56
|
+
connectedUser && event.reaction.user.id === connectedUser.id,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const result = addReactionToActivities(
|
|
60
|
+
event,
|
|
61
|
+
currentActivities,
|
|
62
|
+
isCurrentUser,
|
|
63
|
+
);
|
|
64
|
+
if (result.changed) {
|
|
65
|
+
this.state.partialNext({ activities: result.activities });
|
|
66
|
+
}
|
|
67
|
+
}
|