@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
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
QueryFeedsRequest,
|
|
12
12
|
QueryPollVotesRequest,
|
|
13
13
|
SingleFollowRequest,
|
|
14
|
+
UpdateFollowRequest,
|
|
14
15
|
UserRequest,
|
|
15
16
|
WSEvent,
|
|
16
17
|
} from './gen/models';
|
|
@@ -27,14 +28,19 @@ import {
|
|
|
27
28
|
streamDevToken,
|
|
28
29
|
} from './common/utils';
|
|
29
30
|
import { decodeWSEvent } from './gen/model-decoders/event-decoder-mapping';
|
|
30
|
-
import { Feed } from './Feed';
|
|
31
31
|
import {
|
|
32
32
|
FeedsClientOptions,
|
|
33
33
|
NetworkChangedEvent,
|
|
34
34
|
StreamResponse,
|
|
35
35
|
} from './common/types';
|
|
36
|
-
import { ModerationClient } from './
|
|
36
|
+
import { ModerationClient } from './moderation-client';
|
|
37
37
|
import { StreamPoll } from './common/Poll';
|
|
38
|
+
import {
|
|
39
|
+
Feed,
|
|
40
|
+
handleFollowCreated,
|
|
41
|
+
handleFollowDeleted,
|
|
42
|
+
handleFollowUpdated,
|
|
43
|
+
} from './feed';
|
|
38
44
|
|
|
39
45
|
export type FeedsClientState = {
|
|
40
46
|
connected_user: OwnUser | undefined;
|
|
@@ -363,6 +369,21 @@ export class FeedsClient extends FeedsApi {
|
|
|
363
369
|
this.eventDispatcher.dispatch(networkEvent);
|
|
364
370
|
};
|
|
365
371
|
|
|
372
|
+
async updateFollow(request: UpdateFollowRequest) {
|
|
373
|
+
const response = await super.updateFollow(request);
|
|
374
|
+
|
|
375
|
+
[response.follow.source_feed.fid, response.follow.target_feed.fid].forEach(
|
|
376
|
+
(fid) => {
|
|
377
|
+
const feed = this.activeFeeds[fid];
|
|
378
|
+
if (feed) {
|
|
379
|
+
handleFollowUpdated.bind(feed)(response);
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
return response;
|
|
385
|
+
}
|
|
386
|
+
|
|
366
387
|
// For follow API endpoints we update the state after HTTP response to allow queryFeeds with watch: false
|
|
367
388
|
async follow(request: SingleFollowRequest) {
|
|
368
389
|
const response = await super.follow(request);
|
|
@@ -371,7 +392,7 @@ export class FeedsClient extends FeedsApi {
|
|
|
371
392
|
(fid) => {
|
|
372
393
|
const feed = this.activeFeeds[fid];
|
|
373
394
|
if (feed) {
|
|
374
|
-
|
|
395
|
+
handleFollowCreated.bind(feed)(response);
|
|
375
396
|
}
|
|
376
397
|
},
|
|
377
398
|
);
|
|
@@ -385,7 +406,7 @@ export class FeedsClient extends FeedsApi {
|
|
|
385
406
|
response.follows.forEach((follow) => {
|
|
386
407
|
const feed = this.activeFeeds[follow.source_feed.fid];
|
|
387
408
|
if (feed) {
|
|
388
|
-
|
|
409
|
+
handleFollowCreated.bind(feed)({ follow });
|
|
389
410
|
}
|
|
390
411
|
});
|
|
391
412
|
|
|
@@ -398,10 +419,7 @@ export class FeedsClient extends FeedsApi {
|
|
|
398
419
|
[request.source, request.target].forEach((fid) => {
|
|
399
420
|
const feed = this.activeFeeds[fid];
|
|
400
421
|
if (feed) {
|
|
401
|
-
|
|
402
|
-
source_feed: { fid: request.source },
|
|
403
|
-
target_feed: { fid: request.target },
|
|
404
|
-
});
|
|
422
|
+
handleFollowDeleted.bind(feed)(response);
|
|
405
423
|
}
|
|
406
424
|
});
|
|
407
425
|
|
|
@@ -1709,6 +1709,13 @@ decoders.ThreadedCommentResponse = (input?: Record<string, any>) => {
|
|
|
1709
1709
|
return decode(typeMappings, input);
|
|
1710
1710
|
};
|
|
1711
1711
|
|
|
1712
|
+
decoders.UnfollowResponse = (input?: Record<string, any>) => {
|
|
1713
|
+
const typeMappings: TypeMapping = {
|
|
1714
|
+
follow: { type: 'FollowResponse', isSingle: true },
|
|
1715
|
+
};
|
|
1716
|
+
return decode(typeMappings, input);
|
|
1717
|
+
};
|
|
1718
|
+
|
|
1712
1719
|
decoders.UnpinActivityResponse = (input?: Record<string, any>) => {
|
|
1713
1720
|
const typeMappings: TypeMapping = {
|
|
1714
1721
|
activity: { type: 'ActivityResponse', isSingle: true },
|
package/src/gen/models/index.ts
CHANGED
|
@@ -4752,12 +4752,20 @@ export interface ReviewQueueItem {
|
|
|
4752
4752
|
|
|
4753
4753
|
bans: Ban[];
|
|
4754
4754
|
|
|
4755
|
+
flag_labels: string[];
|
|
4756
|
+
|
|
4757
|
+
flag_types: string[];
|
|
4758
|
+
|
|
4755
4759
|
flags: Flag[];
|
|
4756
4760
|
|
|
4757
4761
|
languages: string[];
|
|
4758
4762
|
|
|
4763
|
+
reporter_ids: string[];
|
|
4764
|
+
|
|
4759
4765
|
teams: string[];
|
|
4760
4766
|
|
|
4767
|
+
archived_at: NullTime;
|
|
4768
|
+
|
|
4761
4769
|
completed_at: NullTime;
|
|
4762
4770
|
|
|
4763
4771
|
reviewed_at: NullTime;
|
|
@@ -5348,6 +5356,8 @@ export interface UnblockUsersResponse {
|
|
|
5348
5356
|
|
|
5349
5357
|
export interface UnfollowResponse {
|
|
5350
5358
|
duration: string;
|
|
5359
|
+
|
|
5360
|
+
follow: FollowResponse;
|
|
5351
5361
|
}
|
|
5352
5362
|
|
|
5353
5363
|
export interface UnpinActivityResponse {
|
package/src/gen-imports.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './response-generators';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FeedResponse,
|
|
3
|
+
FollowResponse,
|
|
4
|
+
OwnUser,
|
|
5
|
+
OwnUserResponse,
|
|
6
|
+
UserResponse,
|
|
7
|
+
} from '../gen/models';
|
|
8
|
+
import { humanId } from 'human-id';
|
|
9
|
+
|
|
10
|
+
export const getHumanId = () => humanId({ capitalize: false, separator: '-' });
|
|
11
|
+
|
|
12
|
+
export const generateUserResponse = (
|
|
13
|
+
overrides: Partial<UserResponse> = {},
|
|
14
|
+
): UserResponse => ({
|
|
15
|
+
id: `user-${getHumanId()}`,
|
|
16
|
+
created_at: new Date(),
|
|
17
|
+
updated_at: new Date(),
|
|
18
|
+
banned: false,
|
|
19
|
+
language: 'en',
|
|
20
|
+
online: false,
|
|
21
|
+
role: 'user',
|
|
22
|
+
blocked_user_ids: [],
|
|
23
|
+
teams: [],
|
|
24
|
+
custom: {},
|
|
25
|
+
...overrides,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const generateOwnUserResponse = (
|
|
29
|
+
overrides: Partial<OwnUserResponse> = {},
|
|
30
|
+
): OwnUserResponse => ({
|
|
31
|
+
...generateUserResponse({
|
|
32
|
+
id: `own-user-${getHumanId()}`,
|
|
33
|
+
}),
|
|
34
|
+
invisible: false,
|
|
35
|
+
total_unread_count: 0,
|
|
36
|
+
unread_channels: 0,
|
|
37
|
+
unread_count: 0,
|
|
38
|
+
unread_threads: 0,
|
|
39
|
+
channel_mutes: [],
|
|
40
|
+
devices: [],
|
|
41
|
+
mutes: [],
|
|
42
|
+
...overrides,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const generateOwnUser = (overrides: Partial<OwnUser> = {}): OwnUser => ({
|
|
46
|
+
...generateOwnUserResponse(),
|
|
47
|
+
devices: [],
|
|
48
|
+
mutes: [],
|
|
49
|
+
total_unread_count_by_team: {},
|
|
50
|
+
...overrides,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const generateFeedResponse = (
|
|
54
|
+
overrides: Omit<Partial<FeedResponse>, 'created_by' | 'fid'> & {
|
|
55
|
+
created_by?: Partial<UserResponse>;
|
|
56
|
+
} = {},
|
|
57
|
+
): FeedResponse => {
|
|
58
|
+
const id = overrides.id || `feed-${getHumanId()}`;
|
|
59
|
+
const groupId = overrides.group_id || 'user';
|
|
60
|
+
const fid = `${groupId}:${id}`;
|
|
61
|
+
const createdBy = generateUserResponse(overrides.created_by);
|
|
62
|
+
const description = humanId({
|
|
63
|
+
addAdverb: true,
|
|
64
|
+
adjectiveCount: 4,
|
|
65
|
+
});
|
|
66
|
+
const name = humanId();
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
id,
|
|
70
|
+
group_id: groupId,
|
|
71
|
+
created_at: new Date(),
|
|
72
|
+
updated_at: new Date(),
|
|
73
|
+
description,
|
|
74
|
+
fid,
|
|
75
|
+
follower_count: 0,
|
|
76
|
+
following_count: 0,
|
|
77
|
+
member_count: 0,
|
|
78
|
+
name,
|
|
79
|
+
pin_count: 0,
|
|
80
|
+
custom: {},
|
|
81
|
+
...overrides,
|
|
82
|
+
created_by: createdBy,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const generateFollowResponse = (
|
|
87
|
+
overrides: Partial<FollowResponse> = {},
|
|
88
|
+
): FollowResponse => {
|
|
89
|
+
const sourceFeedResponse = generateFeedResponse();
|
|
90
|
+
const targetFeedResponse = generateFeedResponse();
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
created_at: new Date(),
|
|
94
|
+
updated_at: new Date(),
|
|
95
|
+
follower_role: 'user',
|
|
96
|
+
push_preference: 'all',
|
|
97
|
+
status: 'accepted',
|
|
98
|
+
source_feed: sourceFeedResponse,
|
|
99
|
+
target_feed: targetFeedResponse,
|
|
100
|
+
...overrides,
|
|
101
|
+
};
|
|
102
|
+
};
|
package/src/types-internal.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import { WSEvent } from './gen/models';
|
|
2
|
+
|
|
1
3
|
export type UpdateStateResult<T> = T & {
|
|
2
4
|
changed: boolean;
|
|
3
5
|
};
|
|
4
6
|
|
|
5
7
|
export type FromArray<T> = T extends Array<infer L> ? L : never;
|
|
8
|
+
|
|
9
|
+
export type EventPayload<T extends WSEvent['type']> = Extract<
|
|
10
|
+
WSEvent,
|
|
11
|
+
{ type: T }
|
|
12
|
+
>;
|
|
13
|
+
|
|
14
|
+
export type PartializeAllBut<T, K extends keyof T> = Pick<T, K> & {
|
|
15
|
+
[key in K]?: T[key];
|
|
16
|
+
};
|
package/src/types.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
ActivityResponse,
|
|
9
9
|
CommentResponse,
|
|
10
10
|
} from './gen/models';
|
|
11
|
-
import { FeedsClient } from './
|
|
11
|
+
import { FeedsClient } from './feeds-client';
|
|
12
12
|
|
|
13
13
|
export type FeedsEvent = WSEvent | ConnectionChangedEvent | NetworkChangedEvent;
|
|
14
14
|
export type ActivityIdOrCommentId = string;
|
|
@@ -6,7 +6,7 @@ describe('state-update-queue', () => {
|
|
|
6
6
|
describe('shouldUpdateState', () => {
|
|
7
7
|
it('should return true when watch is false', () => {
|
|
8
8
|
const result = shouldUpdateState({
|
|
9
|
-
|
|
9
|
+
stateUpdateQueueId: 'test-id',
|
|
10
10
|
stateUpdateQueue: new Set(['other-id']),
|
|
11
11
|
watch: false,
|
|
12
12
|
});
|
|
@@ -14,11 +14,11 @@ describe('state-update-queue', () => {
|
|
|
14
14
|
expect(result).toBe(true);
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it('should return true when watch is true but
|
|
17
|
+
it('should return true when watch is true but queueId is not in queue', () => {
|
|
18
18
|
const stateUpdateQueue = new Set(['other-id-1', 'other-id-2']);
|
|
19
19
|
|
|
20
20
|
const result = shouldUpdateState({
|
|
21
|
-
|
|
21
|
+
stateUpdateQueueId: 'test-id',
|
|
22
22
|
stateUpdateQueue: stateUpdateQueue,
|
|
23
23
|
watch: true,
|
|
24
24
|
});
|
|
@@ -27,11 +27,11 @@ describe('state-update-queue', () => {
|
|
|
27
27
|
expect(result).toBe(true);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
it('should return false and remove
|
|
30
|
+
it('should return false and remove queueId from queue when watch is true and queueId is in queue', () => {
|
|
31
31
|
const stateUpdateQueue = new Set(['test-id', 'other-id']);
|
|
32
32
|
|
|
33
33
|
const result = shouldUpdateState({
|
|
34
|
-
|
|
34
|
+
stateUpdateQueueId: 'test-id',
|
|
35
35
|
stateUpdateQueue,
|
|
36
36
|
watch: true,
|
|
37
37
|
});
|
|
@@ -42,7 +42,7 @@ describe('state-update-queue', () => {
|
|
|
42
42
|
|
|
43
43
|
it('should handle empty queue when watch is true', () => {
|
|
44
44
|
const result = shouldUpdateState({
|
|
45
|
-
|
|
45
|
+
stateUpdateQueueId: 'test-id',
|
|
46
46
|
stateUpdateQueue: new Set(),
|
|
47
47
|
watch: true,
|
|
48
48
|
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { isFollowResponse } from './type-assertions';
|
|
2
|
+
|
|
3
|
+
export const shouldUpdateState = ({
|
|
4
|
+
stateUpdateQueueId,
|
|
5
|
+
stateUpdateQueue,
|
|
6
|
+
watch,
|
|
7
|
+
}: {
|
|
8
|
+
stateUpdateQueueId: string;
|
|
9
|
+
stateUpdateQueue: Set<string>;
|
|
10
|
+
watch: boolean;
|
|
11
|
+
}) => {
|
|
12
|
+
if (!watch) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (watch && stateUpdateQueue.has(stateUpdateQueueId)) {
|
|
17
|
+
stateUpdateQueue.delete(stateUpdateQueueId);
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
stateUpdateQueue.add(stateUpdateQueueId);
|
|
22
|
+
return true;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function getStateUpdateQueueId(
|
|
26
|
+
data: object,
|
|
27
|
+
prefix?: 'deleted' | 'updated' | 'created' | (string & {}),
|
|
28
|
+
) {
|
|
29
|
+
if (isFollowResponse(data)) {
|
|
30
|
+
const toJoin = [data.source_feed.fid, data.target_feed.fid];
|
|
31
|
+
if (prefix) {
|
|
32
|
+
toJoin.unshift(prefix);
|
|
33
|
+
}
|
|
34
|
+
return toJoin.join('-');
|
|
35
|
+
}
|
|
36
|
+
// else if (isMemberResponse(data)) {
|
|
37
|
+
// }
|
|
38
|
+
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Cannot create state update queueId for data: ${JSON.stringify(data)}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CommentResponse, FollowResponse } from '../gen/models';
|
|
2
|
+
import { StreamFile } from '../types';
|
|
3
|
+
import { CommentParent } from '../types';
|
|
4
|
+
|
|
5
|
+
export const isFollowResponse = (data: object): data is FollowResponse => {
|
|
6
|
+
return 'source_feed' in data && 'target_feed' in data;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const isCommentResponse = (
|
|
10
|
+
entity: CommentParent,
|
|
11
|
+
): entity is CommentResponse => {
|
|
12
|
+
return typeof (entity as CommentResponse)?.object_id === 'string';
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const isImageFile = (file: StreamFile) => {
|
|
16
|
+
// photoshop files begin with 'image/'
|
|
17
|
+
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const isVideoFile = (file: StreamFile) => {
|
|
21
|
+
return file.type.startsWith('video/');
|
|
22
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { uniqueArrayMerge } from './
|
|
3
|
+
import { uniqueArrayMerge } from './unique-array-merge';
|
|
4
4
|
|
|
5
5
|
describe('utils', () => {
|
|
6
|
-
describe(
|
|
6
|
+
describe(uniqueArrayMerge.name, () => {
|
|
7
7
|
it('should merge arrays with unique objects based on key', () => {
|
|
8
8
|
const existingArray = [
|
|
9
9
|
{ id: '1', name: 'Alice' },
|
|
@@ -123,7 +123,11 @@ describe('utils', () => {
|
|
|
123
123
|
email: string;
|
|
124
124
|
}) => item.email;
|
|
125
125
|
|
|
126
|
-
const result = uniqueArrayMerge(
|
|
126
|
+
const result = uniqueArrayMerge(
|
|
127
|
+
existingArray,
|
|
128
|
+
arrayToMerge,
|
|
129
|
+
getKeyByEmail,
|
|
130
|
+
);
|
|
127
131
|
|
|
128
132
|
expect(result).toEqual([
|
|
129
133
|
{ id: '1', name: 'Alice', email: 'alice@example.com' },
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const uniqueArrayMerge = <T>(
|
|
2
|
+
existingArray: T[],
|
|
3
|
+
arrayToMerge: T[],
|
|
4
|
+
getKey: (v: T) => string,
|
|
5
|
+
) => {
|
|
6
|
+
const existing = new Set<string>();
|
|
7
|
+
|
|
8
|
+
existingArray.forEach((value) => {
|
|
9
|
+
const key = getKey(value);
|
|
10
|
+
existing.add(key);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const filteredArrayToMerge = arrayToMerge.filter((value) => {
|
|
14
|
+
const key = getKey(value);
|
|
15
|
+
return !existing.has(key);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return existingArray.concat(filteredArrayToMerge);
|
|
19
|
+
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ActivityReactionAddedEvent, ActivityReactionDeletedEvent, ActivityResponse } from '../gen/models';
|
|
2
|
-
import { UpdateStateResult } from '../types-internal';
|
|
3
|
-
export declare const addReactionToActivity: (event: ActivityReactionAddedEvent, activity: ActivityResponse, isCurrentUser: boolean) => UpdateStateResult<ActivityResponse>;
|
|
4
|
-
export declare const removeReactionFromActivity: (event: ActivityReactionDeletedEvent, activity: ActivityResponse, isCurrentUser: boolean) => UpdateStateResult<ActivityResponse>;
|
|
5
|
-
export declare const addReactionToActivities: (event: ActivityReactionAddedEvent, activities: ActivityResponse[] | undefined, isCurrentUser: boolean) => UpdateStateResult<{
|
|
6
|
-
activities: ActivityResponse[];
|
|
7
|
-
}>;
|
|
8
|
-
export declare const removeReactionFromActivities: (event: ActivityReactionDeletedEvent, activities: ActivityResponse[] | undefined, isCurrentUser: boolean) => UpdateStateResult<{
|
|
9
|
-
activities: ActivityResponse[];
|
|
10
|
-
}>;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ActivityResponse } from '../gen/models';
|
|
2
|
-
import { UpdateStateResult } from '../types-internal';
|
|
3
|
-
export declare const addActivitiesToState: (newActivities: ActivityResponse[], activities: ActivityResponse[] | undefined, position: "start" | "end") => UpdateStateResult<{
|
|
4
|
-
activities: ActivityResponse[];
|
|
5
|
-
}>;
|
|
6
|
-
export declare const updateActivityInState: (updatedActivityResponse: ActivityResponse, activities: ActivityResponse[]) => {
|
|
7
|
-
changed: boolean;
|
|
8
|
-
activities: ActivityResponse[];
|
|
9
|
-
};
|
|
10
|
-
export declare const removeActivityFromState: (activityResponse: ActivityResponse, activities: ActivityResponse[]) => {
|
|
11
|
-
changed: boolean;
|
|
12
|
-
activities: ActivityResponse[];
|
|
13
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { BookmarkAddedEvent, BookmarkDeletedEvent, BookmarkUpdatedEvent, ActivityResponse } from '../gen/models';
|
|
2
|
-
import { UpdateStateResult } from '../types-internal';
|
|
3
|
-
export declare const addBookmarkToActivity: (event: BookmarkAddedEvent, activity: ActivityResponse, isCurrentUser: boolean) => UpdateStateResult<ActivityResponse>;
|
|
4
|
-
export declare const removeBookmarkFromActivity: (event: BookmarkDeletedEvent, activity: ActivityResponse, isCurrentUser: boolean) => UpdateStateResult<ActivityResponse>;
|
|
5
|
-
export declare const updateBookmarkInActivity: (event: BookmarkUpdatedEvent, activity: ActivityResponse, isCurrentUser: boolean) => UpdateStateResult<ActivityResponse>;
|
|
6
|
-
export declare const addBookmarkToActivities: (event: BookmarkAddedEvent, activities: ActivityResponse[] | undefined, isCurrentUser: boolean) => UpdateStateResult<{
|
|
7
|
-
activities: ActivityResponse[];
|
|
8
|
-
}>;
|
|
9
|
-
export declare const removeBookmarkFromActivities: (event: BookmarkDeletedEvent, activities: ActivityResponse[] | undefined, isCurrentUser: boolean) => UpdateStateResult<{
|
|
10
|
-
activities: ActivityResponse[];
|
|
11
|
-
}>;
|
|
12
|
-
export declare const updateBookmarkInActivities: (event: BookmarkUpdatedEvent, activities: ActivityResponse[] | undefined, isCurrentUser: boolean) => UpdateStateResult<{
|
|
13
|
-
activities: ActivityResponse[];
|
|
14
|
-
}>;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { FeedState } from '../Feed';
|
|
2
|
-
import { FollowResponse } from '../gen/models';
|
|
3
|
-
import { UpdateStateResult } from '../types-internal';
|
|
4
|
-
export declare const handleFollowCreated: (follow: FollowResponse, currentState: FeedState, currentFeedId: string, connectedUserId?: string) => UpdateStateResult<{
|
|
5
|
-
data: FeedState;
|
|
6
|
-
}>;
|
|
7
|
-
export declare const handleFollowDeleted: (follow: FollowResponse | {
|
|
8
|
-
source_feed: {
|
|
9
|
-
fid: string;
|
|
10
|
-
};
|
|
11
|
-
target_feed: {
|
|
12
|
-
fid: string;
|
|
13
|
-
};
|
|
14
|
-
}, currentState: FeedState, currentFeedId: string, connectedUserId?: string) => UpdateStateResult<{
|
|
15
|
-
data: FeedState;
|
|
16
|
-
}>;
|
|
17
|
-
export declare const handleFollowUpdated: (currentState: FeedState) => UpdateStateResult<{
|
|
18
|
-
data: FeedState;
|
|
19
|
-
}>;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { FollowResponse } from '../gen/models';
|
|
2
|
-
export declare const shouldUpdateState: ({ stateUpdateId, stateUpdateQueue, watch, }: {
|
|
3
|
-
stateUpdateId: string;
|
|
4
|
-
stateUpdateQueue: Set<string>;
|
|
5
|
-
watch: boolean;
|
|
6
|
-
}) => boolean;
|
|
7
|
-
export declare const getStateUpdateQueueIdForFollow: (follow: FollowResponse) => string;
|
|
8
|
-
export declare const getStateUpdateQueueIdForUnfollow: (follow: FollowResponse | {
|
|
9
|
-
source_feed: {
|
|
10
|
-
fid: string;
|
|
11
|
-
};
|
|
12
|
-
target_feed: {
|
|
13
|
-
fid: string;
|
|
14
|
-
};
|
|
15
|
-
}) => string;
|
package/dist/src/utils.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { CommentParent, StreamFile } from './types';
|
|
2
|
-
import type { CommentResponse } from './gen/models';
|
|
3
|
-
export declare const isImageFile: (file: StreamFile) => boolean;
|
|
4
|
-
export declare const isVideoFile: (file: StreamFile) => boolean;
|
|
5
|
-
export declare const checkHasAnotherPage: <T extends unknown | undefined>(v: T, cursor: string | undefined) => boolean;
|
|
6
|
-
export declare const isCommentResponse: (entity: CommentParent) => entity is CommentResponse;
|
|
7
|
-
export declare const Constants: {
|
|
8
|
-
readonly DEFAULT_COMMENT_PAGINATION: "first";
|
|
9
|
-
};
|
|
10
|
-
export declare const uniqueArrayMerge: <T>(existingArray: T[], arrayToMerge: T[], getKey: (v: T) => string) => T[];
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ActivityReactionAddedEvent,
|
|
3
|
-
ActivityReactionDeletedEvent,
|
|
4
|
-
ActivityResponse,
|
|
5
|
-
} from '../gen/models';
|
|
6
|
-
import { UpdateStateResult } from '../types-internal';
|
|
7
|
-
|
|
8
|
-
const updateActivityInActivities = (
|
|
9
|
-
updatedActivity: ActivityResponse,
|
|
10
|
-
activities: ActivityResponse[],
|
|
11
|
-
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
12
|
-
const index = activities.findIndex((a) => a.id === updatedActivity.id);
|
|
13
|
-
if (index !== -1) {
|
|
14
|
-
const newActivities = [...activities];
|
|
15
|
-
newActivities[index] = updatedActivity;
|
|
16
|
-
return { changed: true, activities: newActivities };
|
|
17
|
-
} else {
|
|
18
|
-
return { changed: false, activities };
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const addReactionToActivity = (
|
|
23
|
-
event: ActivityReactionAddedEvent,
|
|
24
|
-
activity: ActivityResponse,
|
|
25
|
-
isCurrentUser: boolean,
|
|
26
|
-
): UpdateStateResult<ActivityResponse> => {
|
|
27
|
-
// Update own_reactions if the reaction is from the current user
|
|
28
|
-
const ownReactions = [...(activity.own_reactions || [])];
|
|
29
|
-
if (isCurrentUser) {
|
|
30
|
-
ownReactions.push(event.reaction);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
...activity,
|
|
35
|
-
own_reactions: ownReactions,
|
|
36
|
-
latest_reactions: event.activity.latest_reactions,
|
|
37
|
-
reaction_groups: event.activity.reaction_groups,
|
|
38
|
-
changed: true,
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const removeReactionFromActivity = (
|
|
43
|
-
event: ActivityReactionDeletedEvent,
|
|
44
|
-
activity: ActivityResponse,
|
|
45
|
-
isCurrentUser: boolean,
|
|
46
|
-
): UpdateStateResult<ActivityResponse> => {
|
|
47
|
-
// Update own_reactions if the reaction is from the current user
|
|
48
|
-
const ownReactions = isCurrentUser
|
|
49
|
-
? (activity.own_reactions || []).filter(
|
|
50
|
-
(r) =>
|
|
51
|
-
!(
|
|
52
|
-
r.type === event.reaction.type &&
|
|
53
|
-
r.user.id === event.reaction.user.id
|
|
54
|
-
),
|
|
55
|
-
)
|
|
56
|
-
: activity.own_reactions;
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
...activity,
|
|
60
|
-
own_reactions: ownReactions,
|
|
61
|
-
latest_reactions: event.activity.latest_reactions,
|
|
62
|
-
reaction_groups: event.activity.reaction_groups,
|
|
63
|
-
changed: true,
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export const addReactionToActivities = (
|
|
68
|
-
event: ActivityReactionAddedEvent,
|
|
69
|
-
activities: ActivityResponse[] | undefined,
|
|
70
|
-
isCurrentUser: boolean,
|
|
71
|
-
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
72
|
-
if (!activities) {
|
|
73
|
-
return { changed: false, activities: [] };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
77
|
-
if (activityIndex === -1) {
|
|
78
|
-
return { changed: false, activities };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const activity = activities[activityIndex];
|
|
82
|
-
const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
|
|
83
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export const removeReactionFromActivities = (
|
|
87
|
-
event: ActivityReactionDeletedEvent,
|
|
88
|
-
activities: ActivityResponse[] | undefined,
|
|
89
|
-
isCurrentUser: boolean,
|
|
90
|
-
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
91
|
-
if (!activities) {
|
|
92
|
-
return { changed: false, activities: [] };
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
96
|
-
if (activityIndex === -1) {
|
|
97
|
-
return { changed: false, activities };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const activity = activities[activityIndex];
|
|
101
|
-
const updatedActivity = removeReactionFromActivity(
|
|
102
|
-
event,
|
|
103
|
-
activity,
|
|
104
|
-
isCurrentUser,
|
|
105
|
-
);
|
|
106
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
107
|
-
};
|