@stream-io/feeds-client 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@react-bindings/hooks/util/index.ts +1 -0
- package/CHANGELOG.md +15 -0
- package/dist/@react-bindings/hooks/util/index.d.ts +1 -0
- package/dist/@react-bindings/hooks/util/useBookmarkActions.d.ts +13 -0
- package/dist/@react-bindings/hooks/util/useReactionActions.d.ts +1 -1
- package/dist/index-react-bindings.browser.cjs +346 -140
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +346 -141
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +346 -140
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +346 -141
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +320 -139
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +320 -140
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +320 -139
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +320 -140
- package/dist/index.node.js.map +1 -1
- package/dist/src/Feed.d.ts +40 -9
- package/dist/src/FeedsClient.d.ts +8 -1
- package/dist/src/gen-imports.d.ts +1 -1
- package/dist/src/state-updates/follow-utils.d.ts +19 -0
- package/dist/src/state-updates/state-update-queue.d.ts +15 -0
- package/dist/src/utils.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Feed.ts +226 -192
- package/src/FeedsClient.ts +75 -3
- package/src/gen-imports.ts +1 -1
- package/src/state-updates/activity-reaction-utils.test.ts +1 -0
- package/src/state-updates/activity-utils.test.ts +1 -0
- package/src/state-updates/follow-utils.test.ts +552 -0
- package/src/state-updates/follow-utils.ts +126 -0
- package/src/state-updates/state-update-queue.test.ts +53 -0
- package/src/state-updates/state-update-queue.ts +35 -0
- package/src/utils.test.ts +175 -0
- package/src/utils.ts +20 -0
package/package.json
CHANGED
package/src/Feed.ts
CHANGED
|
@@ -16,8 +16,10 @@ import {
|
|
|
16
16
|
BookmarkUpdatedEvent,
|
|
17
17
|
QueryFeedMembersRequest,
|
|
18
18
|
SortParamRequest,
|
|
19
|
+
FollowResponse,
|
|
20
|
+
ThreadedCommentResponse,
|
|
19
21
|
} from './gen/models';
|
|
20
|
-
import {
|
|
22
|
+
import { StateStore } from './common/StateStore';
|
|
21
23
|
import { EventDispatcher } from './common/EventDispatcher';
|
|
22
24
|
import { FeedApi } from './gen/feeds/FeedApi';
|
|
23
25
|
import { FeedsClient } from './FeedsClient';
|
|
@@ -35,7 +37,12 @@ import {
|
|
|
35
37
|
removeBookmarkFromActivities,
|
|
36
38
|
updateBookmarkInActivities,
|
|
37
39
|
} from './state-updates/bookmark-utils';
|
|
38
|
-
import {
|
|
40
|
+
import {
|
|
41
|
+
handleFollowCreated,
|
|
42
|
+
handleFollowDeleted,
|
|
43
|
+
handleFollowUpdated,
|
|
44
|
+
} from './state-updates/follow-utils';
|
|
45
|
+
import { StreamResponse } from './gen-imports';
|
|
39
46
|
import { capitalize } from './common/utils';
|
|
40
47
|
import type {
|
|
41
48
|
ActivityIdOrCommentId,
|
|
@@ -44,8 +51,12 @@ import type {
|
|
|
44
51
|
LoadingStates,
|
|
45
52
|
PagerResponseWithLoadingStates,
|
|
46
53
|
} from './types';
|
|
47
|
-
import
|
|
48
|
-
import {
|
|
54
|
+
import { checkHasAnotherPage, Constants, uniqueArrayMerge } from './utils';
|
|
55
|
+
import {
|
|
56
|
+
getStateUpdateQueueIdForFollow,
|
|
57
|
+
getStateUpdateQueueIdForUnfollow,
|
|
58
|
+
shouldUpdateState,
|
|
59
|
+
} from './state-updates/state-update-queue';
|
|
49
60
|
|
|
50
61
|
export type FeedState = Omit<
|
|
51
62
|
Partial<GetOrCreateFeedResponse & FeedResponse>,
|
|
@@ -90,17 +101,17 @@ export type FeedState = Omit<
|
|
|
90
101
|
* comments_by_entity_id: {
|
|
91
102
|
* 'activity-1': {
|
|
92
103
|
* comments: [comment1],
|
|
93
|
-
*
|
|
104
|
+
* entity_parent_id: undefined,
|
|
94
105
|
* },
|
|
95
106
|
* 'comment-1': {
|
|
96
107
|
* comments: [comment2],
|
|
97
|
-
*
|
|
108
|
+
* entity_parent_id: 'activity-1', // parent store where "comment-1" is located in "comments" array
|
|
98
109
|
* }
|
|
99
110
|
* }
|
|
100
111
|
* }
|
|
101
112
|
* ```
|
|
102
113
|
*/
|
|
103
|
-
|
|
114
|
+
entity_parent_id?: ActivityIdOrCommentId;
|
|
104
115
|
comments?: CommentResponse[];
|
|
105
116
|
}
|
|
106
117
|
| undefined
|
|
@@ -113,6 +124,11 @@ export type FeedState = Omit<
|
|
|
113
124
|
member_pagination?: LoadingStates & { sort?: SortParamRequest[] };
|
|
114
125
|
|
|
115
126
|
last_get_or_create_request_config?: GetOrCreateFeedRequest;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* `true` if the feed is receiving real-time updates via WebSocket
|
|
130
|
+
*/
|
|
131
|
+
watch: boolean;
|
|
116
132
|
};
|
|
117
133
|
|
|
118
134
|
type EventHandlerByEventType = {
|
|
@@ -127,6 +143,7 @@ type EventHandlerByEventType = {
|
|
|
127
143
|
export class Feed extends FeedApi {
|
|
128
144
|
readonly state: StateStore<FeedState>;
|
|
129
145
|
private static readonly noop = () => {};
|
|
146
|
+
private readonly stateUpdateQueue: Set<string> = new Set();
|
|
130
147
|
|
|
131
148
|
private readonly eventHandlers: EventHandlerByEventType = {
|
|
132
149
|
'feeds.activity.added': (event) => {
|
|
@@ -314,102 +331,17 @@ export class Feed extends FeedApi {
|
|
|
314
331
|
'feeds.feed_group.changed': Feed.noop,
|
|
315
332
|
'feeds.feed_group.deleted': Feed.noop,
|
|
316
333
|
'feeds.follow.created': (event) => {
|
|
317
|
-
|
|
318
|
-
if (event.follow.status !== 'accepted') return;
|
|
319
|
-
|
|
320
|
-
// this feed followed someone
|
|
321
|
-
if (event.follow.source_feed.fid === this.fid) {
|
|
322
|
-
this.state.next((currentState) => {
|
|
323
|
-
const newState = {
|
|
324
|
-
...currentState,
|
|
325
|
-
...event.follow.source_feed,
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
if (
|
|
329
|
-
!checkHasAnotherPage(
|
|
330
|
-
currentState.following,
|
|
331
|
-
currentState.following_pagination?.next,
|
|
332
|
-
)
|
|
333
|
-
) {
|
|
334
|
-
// TODO: respect sort
|
|
335
|
-
newState.following = currentState.following
|
|
336
|
-
? currentState.following.concat(event.follow)
|
|
337
|
-
: [event.follow];
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return newState;
|
|
341
|
-
});
|
|
342
|
-
} else if (
|
|
343
|
-
// someone followed this feed
|
|
344
|
-
event.follow.target_feed.fid === this.fid
|
|
345
|
-
) {
|
|
346
|
-
const source = event.follow.source_feed;
|
|
347
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
348
|
-
|
|
349
|
-
this.state.next((currentState) => {
|
|
350
|
-
const newState = { ...currentState, ...event.follow.target_feed };
|
|
351
|
-
|
|
352
|
-
if (source.created_by.id === connectedUser?.id) {
|
|
353
|
-
newState.own_follows = currentState.own_follows
|
|
354
|
-
? currentState.own_follows.concat(event.follow)
|
|
355
|
-
: [event.follow];
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (
|
|
359
|
-
!checkHasAnotherPage(
|
|
360
|
-
currentState.followers,
|
|
361
|
-
currentState.followers_pagination?.next,
|
|
362
|
-
)
|
|
363
|
-
) {
|
|
364
|
-
// TODO: respect sort
|
|
365
|
-
newState.followers = currentState.followers
|
|
366
|
-
? currentState.followers.concat(event.follow)
|
|
367
|
-
: [event.follow];
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
return newState;
|
|
371
|
-
});
|
|
372
|
-
}
|
|
334
|
+
this.handleFollowCreated(event.follow);
|
|
373
335
|
},
|
|
374
336
|
'feeds.follow.deleted': (event) => {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
following: currentState.following?.filter(
|
|
382
|
-
(follow) =>
|
|
383
|
-
follow.target_feed.fid !== event.follow.target_feed.fid,
|
|
384
|
-
),
|
|
385
|
-
};
|
|
386
|
-
});
|
|
387
|
-
} else if (
|
|
388
|
-
// someone unfollowed this feed
|
|
389
|
-
event.follow.target_feed.fid === this.fid
|
|
390
|
-
) {
|
|
391
|
-
const source = event.follow.source_feed;
|
|
392
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
393
|
-
|
|
394
|
-
this.state.next((currentState) => {
|
|
395
|
-
const newState = { ...currentState, ...event.follow.target_feed };
|
|
396
|
-
|
|
397
|
-
if (source.created_by.id === connectedUser?.id) {
|
|
398
|
-
newState.own_follows = currentState.own_follows?.filter(
|
|
399
|
-
(follow) =>
|
|
400
|
-
follow.source_feed.fid !== event.follow.source_feed.fid,
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
newState.followers = currentState.followers?.filter(
|
|
405
|
-
(follow) => follow.source_feed.fid !== event.follow.source_feed.fid,
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
return newState;
|
|
409
|
-
});
|
|
337
|
+
this.handleFollowDeleted(event.follow);
|
|
338
|
+
},
|
|
339
|
+
'feeds.follow.updated': (_event) => {
|
|
340
|
+
const result = handleFollowUpdated(this.currentState);
|
|
341
|
+
if (result.changed) {
|
|
342
|
+
this.state.next(result.data);
|
|
410
343
|
}
|
|
411
344
|
},
|
|
412
|
-
'feeds.follow.updated': Feed.noop,
|
|
413
345
|
'feeds.comment.reaction.added': this.handleCommentReactionEvent.bind(this),
|
|
414
346
|
'feeds.comment.reaction.deleted':
|
|
415
347
|
this.handleCommentReactionEvent.bind(this),
|
|
@@ -421,19 +353,12 @@ export class Feed extends FeedApi {
|
|
|
421
353
|
this.state.next((currentState) => {
|
|
422
354
|
let newState: FeedState | undefined;
|
|
423
355
|
|
|
424
|
-
if (
|
|
425
|
-
!checkHasAnotherPage(
|
|
426
|
-
currentState.members,
|
|
427
|
-
currentState.member_pagination?.next,
|
|
428
|
-
)
|
|
429
|
-
) {
|
|
356
|
+
if (typeof currentState.members !== 'undefined') {
|
|
430
357
|
newState ??= {
|
|
431
358
|
...currentState,
|
|
432
359
|
};
|
|
433
360
|
|
|
434
|
-
newState.members =
|
|
435
|
-
event.member,
|
|
436
|
-
];
|
|
361
|
+
newState.members = [event.member, ...currentState.members];
|
|
437
362
|
}
|
|
438
363
|
|
|
439
364
|
if (connectedUser?.id === event.member.user.id) {
|
|
@@ -535,9 +460,9 @@ export class Feed extends FeedApi {
|
|
|
535
460
|
groupId: 'user' | 'timeline' | (string & {}),
|
|
536
461
|
id: string,
|
|
537
462
|
data?: FeedResponse,
|
|
463
|
+
watch = false,
|
|
538
464
|
) {
|
|
539
|
-
|
|
540
|
-
super(client as unknown as FeedsApi, groupId, id);
|
|
465
|
+
super(client, groupId, id);
|
|
541
466
|
this.state = new StateStore<FeedState>({
|
|
542
467
|
fid: `${groupId}:${id}`,
|
|
543
468
|
group_id: groupId,
|
|
@@ -546,6 +471,7 @@ export class Feed extends FeedApi {
|
|
|
546
471
|
is_loading: false,
|
|
547
472
|
is_loading_activities: false,
|
|
548
473
|
comments_by_entity_id: {},
|
|
474
|
+
watch,
|
|
549
475
|
});
|
|
550
476
|
this.client = client;
|
|
551
477
|
}
|
|
@@ -656,6 +582,8 @@ export class Feed extends FeedApi {
|
|
|
656
582
|
});
|
|
657
583
|
}
|
|
658
584
|
} else {
|
|
585
|
+
// Empty queue when reinitializing the state
|
|
586
|
+
this.stateUpdateQueue.clear();
|
|
659
587
|
const responseCopy: Partial<
|
|
660
588
|
StreamResponse<GetOrCreateFeedResponse>['feed'] &
|
|
661
589
|
StreamResponse<GetOrCreateFeedResponse>
|
|
@@ -680,8 +608,12 @@ export class Feed extends FeedApi {
|
|
|
680
608
|
if (!request?.following_pagination?.limit) {
|
|
681
609
|
delete nextState.following;
|
|
682
610
|
}
|
|
611
|
+
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
612
|
+
delete nextState.members;
|
|
613
|
+
}
|
|
683
614
|
|
|
684
615
|
nextState.last_get_or_create_request_config = request;
|
|
616
|
+
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
685
617
|
|
|
686
618
|
return nextState;
|
|
687
619
|
});
|
|
@@ -698,6 +630,80 @@ export class Feed extends FeedApi {
|
|
|
698
630
|
}
|
|
699
631
|
}
|
|
700
632
|
|
|
633
|
+
/**
|
|
634
|
+
* @internal
|
|
635
|
+
*/
|
|
636
|
+
handleFollowCreated(follow: FollowResponse) {
|
|
637
|
+
if (
|
|
638
|
+
!shouldUpdateState({
|
|
639
|
+
stateUpdateId: getStateUpdateQueueIdForFollow(follow),
|
|
640
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
641
|
+
watch: this.currentState.watch,
|
|
642
|
+
})
|
|
643
|
+
) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
647
|
+
const result = handleFollowCreated(
|
|
648
|
+
follow,
|
|
649
|
+
this.currentState,
|
|
650
|
+
this.fid,
|
|
651
|
+
connectedUser?.id,
|
|
652
|
+
);
|
|
653
|
+
if (result.changed) {
|
|
654
|
+
this.state.next(result.data);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* @internal
|
|
660
|
+
*/
|
|
661
|
+
handleFollowDeleted(
|
|
662
|
+
follow:
|
|
663
|
+
| FollowResponse
|
|
664
|
+
// Backend doesn't return the follow in delete follow response https://getstream.slack.com/archives/C06RK9WCR09/p1753176937507209
|
|
665
|
+
| { source_feed: { fid: string }; target_feed: { fid: string } },
|
|
666
|
+
) {
|
|
667
|
+
if (
|
|
668
|
+
!shouldUpdateState({
|
|
669
|
+
stateUpdateId: getStateUpdateQueueIdForUnfollow(follow),
|
|
670
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
671
|
+
watch: this.currentState.watch,
|
|
672
|
+
})
|
|
673
|
+
) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
678
|
+
const result = handleFollowDeleted(
|
|
679
|
+
follow,
|
|
680
|
+
this.currentState,
|
|
681
|
+
this.fid,
|
|
682
|
+
connectedUser?.id,
|
|
683
|
+
);
|
|
684
|
+
if (result.changed) {
|
|
685
|
+
this.state.next(result.data);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* @internal
|
|
691
|
+
*/
|
|
692
|
+
handleWatchStopped() {
|
|
693
|
+
this.state.partialNext({
|
|
694
|
+
watch: false,
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* @internal
|
|
700
|
+
*/
|
|
701
|
+
handleWatchStarted() {
|
|
702
|
+
this.state.partialNext({
|
|
703
|
+
watch: true,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
|
|
701
707
|
private handleBookmarkAdded(event: BookmarkAddedEvent) {
|
|
702
708
|
const currentActivities = this.currentState.activities;
|
|
703
709
|
const { connected_user: connectedUser } =
|
|
@@ -775,57 +781,93 @@ export class Feed extends FeedApi {
|
|
|
775
781
|
return commentIndex;
|
|
776
782
|
}
|
|
777
783
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
+
/**
|
|
785
|
+
* Load child comments of entity (activity or comment) into the state, if the target entity is comment,
|
|
786
|
+
* `entityParentId` should be provided (`CommentResponse.parent_id ?? CommentResponse.object_id`).
|
|
787
|
+
*/
|
|
788
|
+
private loadCommentsIntoState(data: {
|
|
789
|
+
entityParentId?: string;
|
|
790
|
+
entityId: string;
|
|
791
|
+
comments: Array<CommentResponse & ThreadedCommentResponse>;
|
|
792
|
+
next?: string;
|
|
793
|
+
sort: string;
|
|
794
|
+
}) {
|
|
795
|
+
// add initial (top level) object for processing
|
|
796
|
+
const traverseArray = [
|
|
797
|
+
{
|
|
798
|
+
entityId: data.entityId,
|
|
799
|
+
entityParentId: data.entityParentId,
|
|
800
|
+
comments: data.comments,
|
|
801
|
+
next: data.next,
|
|
802
|
+
},
|
|
803
|
+
];
|
|
784
804
|
|
|
785
|
-
|
|
805
|
+
this.state.next((currentState) => {
|
|
806
|
+
const newCommentsByEntityId = {
|
|
807
|
+
...currentState.comments_by_entity_id,
|
|
808
|
+
};
|
|
786
809
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
activityIndex = activities.findIndex(
|
|
790
|
-
(activity_) => activity_.id === activity.id,
|
|
791
|
-
);
|
|
792
|
-
}
|
|
810
|
+
while (traverseArray.length) {
|
|
811
|
+
const item = traverseArray.pop()!;
|
|
793
812
|
|
|
794
|
-
|
|
795
|
-
}
|
|
813
|
+
const entityId = item.entityId;
|
|
796
814
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
this.state.next((currentState) => {
|
|
802
|
-
const activityIndex = this.getActivityIndex(activity, currentState);
|
|
815
|
+
// go over entity comments and generate new objects
|
|
816
|
+
// for further processing if there are any replies
|
|
817
|
+
item.comments.forEach((comment) => {
|
|
818
|
+
if (!comment.replies?.length) return;
|
|
803
819
|
|
|
804
|
-
|
|
820
|
+
traverseArray.push({
|
|
821
|
+
entityId: comment.id,
|
|
822
|
+
entityParentId: entityId,
|
|
823
|
+
comments: comment.replies,
|
|
824
|
+
next: comment.meta?.next_cursor,
|
|
825
|
+
});
|
|
826
|
+
});
|
|
805
827
|
|
|
806
|
-
|
|
828
|
+
// omit replies & meta from the comments (transform ThreadedCommentResponse to CommentResponse)
|
|
829
|
+
// this is somehow faster than copying the whole
|
|
830
|
+
// object and deleting the desired properties
|
|
831
|
+
const newComments: CommentResponse[] = item.comments.map(
|
|
832
|
+
({ replies: _r, meta: _m, ...restOfTheCommentResponse }) =>
|
|
833
|
+
restOfTheCommentResponse,
|
|
834
|
+
);
|
|
807
835
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
836
|
+
newCommentsByEntityId[entityId] = {
|
|
837
|
+
...newCommentsByEntityId[entityId],
|
|
838
|
+
entity_parent_id: item.entityParentId,
|
|
839
|
+
pagination: {
|
|
840
|
+
...newCommentsByEntityId[entityId]?.pagination,
|
|
841
|
+
next: item.next,
|
|
842
|
+
sort: data.sort,
|
|
843
|
+
},
|
|
844
|
+
comments: newCommentsByEntityId[entityId]?.comments
|
|
845
|
+
? newCommentsByEntityId[entityId].comments?.concat(newComments)
|
|
846
|
+
: newComments,
|
|
847
|
+
};
|
|
848
|
+
}
|
|
811
849
|
|
|
812
850
|
return {
|
|
813
851
|
...currentState,
|
|
814
|
-
|
|
852
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
815
853
|
};
|
|
816
854
|
});
|
|
817
855
|
}
|
|
818
856
|
|
|
819
857
|
private async loadNextPageComments({
|
|
820
|
-
|
|
858
|
+
entityId,
|
|
821
859
|
base,
|
|
822
860
|
sort,
|
|
823
|
-
|
|
861
|
+
entityParentId,
|
|
824
862
|
}: {
|
|
825
|
-
|
|
826
|
-
|
|
863
|
+
entityParentId?: string;
|
|
864
|
+
entityId: string;
|
|
827
865
|
sort: string;
|
|
828
|
-
base: () => Promise<
|
|
866
|
+
base: () => Promise<
|
|
867
|
+
PagerResponse & {
|
|
868
|
+
comments: Array<CommentResponse & ThreadedCommentResponse>;
|
|
869
|
+
}
|
|
870
|
+
>;
|
|
829
871
|
}) {
|
|
830
872
|
let error: unknown;
|
|
831
873
|
|
|
@@ -834,44 +876,24 @@ export class Feed extends FeedApi {
|
|
|
834
876
|
...currentState,
|
|
835
877
|
comments_by_entity_id: {
|
|
836
878
|
...currentState.comments_by_entity_id,
|
|
837
|
-
[
|
|
838
|
-
...currentState.comments_by_entity_id[
|
|
879
|
+
[entityId]: {
|
|
880
|
+
...currentState.comments_by_entity_id[entityId],
|
|
839
881
|
pagination: {
|
|
840
|
-
...currentState.comments_by_entity_id[
|
|
882
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
841
883
|
loading_next_page: true,
|
|
842
884
|
},
|
|
843
885
|
},
|
|
844
886
|
},
|
|
845
887
|
}));
|
|
846
888
|
|
|
847
|
-
const { next
|
|
889
|
+
const { next, comments } = await base();
|
|
848
890
|
|
|
849
|
-
this.
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
if (typeof newPagination.sort === 'undefined') {
|
|
856
|
-
newPagination.sort = sort;
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
return {
|
|
860
|
-
...currentState,
|
|
861
|
-
comments_by_entity_id: {
|
|
862
|
-
...currentState.comments_by_entity_id,
|
|
863
|
-
[forId]: {
|
|
864
|
-
...currentState.comments_by_entity_id[forId],
|
|
865
|
-
parent_id: parentId,
|
|
866
|
-
pagination: newPagination,
|
|
867
|
-
comments: currentState.comments_by_entity_id[forId]?.comments
|
|
868
|
-
? currentState.comments_by_entity_id[forId].comments?.concat(
|
|
869
|
-
comments,
|
|
870
|
-
)
|
|
871
|
-
: comments,
|
|
872
|
-
},
|
|
873
|
-
},
|
|
874
|
-
};
|
|
891
|
+
this.loadCommentsIntoState({
|
|
892
|
+
entityId,
|
|
893
|
+
comments,
|
|
894
|
+
entityParentId,
|
|
895
|
+
next,
|
|
896
|
+
sort,
|
|
875
897
|
});
|
|
876
898
|
} catch (e) {
|
|
877
899
|
error = e;
|
|
@@ -880,10 +902,10 @@ export class Feed extends FeedApi {
|
|
|
880
902
|
...currentState,
|
|
881
903
|
comments_by_entity_id: {
|
|
882
904
|
...currentState.comments_by_entity_id,
|
|
883
|
-
[
|
|
884
|
-
...currentState.comments_by_entity_id[
|
|
905
|
+
[entityId]: {
|
|
906
|
+
...currentState.comments_by_entity_id[entityId],
|
|
885
907
|
pagination: {
|
|
886
|
-
...currentState.comments_by_entity_id[
|
|
908
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
887
909
|
loading_next_page: false,
|
|
888
910
|
},
|
|
889
911
|
},
|
|
@@ -920,7 +942,7 @@ export class Feed extends FeedApi {
|
|
|
920
942
|
}
|
|
921
943
|
|
|
922
944
|
await this.loadNextPageComments({
|
|
923
|
-
|
|
945
|
+
entityId: activity.id,
|
|
924
946
|
base: () =>
|
|
925
947
|
this.client.getComments({
|
|
926
948
|
...request,
|
|
@@ -955,7 +977,7 @@ export class Feed extends FeedApi {
|
|
|
955
977
|
}
|
|
956
978
|
|
|
957
979
|
await this.loadNextPageComments({
|
|
958
|
-
|
|
980
|
+
entityId: comment.id,
|
|
959
981
|
base: () =>
|
|
960
982
|
this.client.getCommentReplies({
|
|
961
983
|
...request,
|
|
@@ -967,7 +989,7 @@ export class Feed extends FeedApi {
|
|
|
967
989
|
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
968
990
|
next: currentNextCursor,
|
|
969
991
|
}),
|
|
970
|
-
|
|
992
|
+
entityParentId: comment.parent_id ?? comment.object_id,
|
|
971
993
|
sort,
|
|
972
994
|
});
|
|
973
995
|
}
|
|
@@ -1006,17 +1028,25 @@ export class Feed extends FeedApi {
|
|
|
1006
1028
|
sort,
|
|
1007
1029
|
});
|
|
1008
1030
|
|
|
1009
|
-
this.state.next((currentState) =>
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1031
|
+
this.state.next((currentState) => {
|
|
1032
|
+
return {
|
|
1033
|
+
...currentState,
|
|
1034
|
+
[type]:
|
|
1035
|
+
currentState[type] === undefined
|
|
1036
|
+
? follows
|
|
1037
|
+
: uniqueArrayMerge(
|
|
1038
|
+
currentState[type],
|
|
1039
|
+
follows,
|
|
1040
|
+
(follow) =>
|
|
1041
|
+
`${follow.source_feed.fid}-${follow.target_feed.fid}`,
|
|
1042
|
+
),
|
|
1043
|
+
[paginationKey]: {
|
|
1044
|
+
...currentState[paginationKey],
|
|
1045
|
+
next: newNextCursor,
|
|
1046
|
+
sort,
|
|
1047
|
+
},
|
|
1048
|
+
};
|
|
1049
|
+
});
|
|
1020
1050
|
} catch (e) {
|
|
1021
1051
|
error = e;
|
|
1022
1052
|
} finally {
|
|
@@ -1036,11 +1066,15 @@ export class Feed extends FeedApi {
|
|
|
1036
1066
|
}
|
|
1037
1067
|
}
|
|
1038
1068
|
|
|
1039
|
-
async loadNextPageFollowers(
|
|
1069
|
+
async loadNextPageFollowers(
|
|
1070
|
+
request: Pick<QueryFollowsRequest, 'limit' | 'sort'>,
|
|
1071
|
+
) {
|
|
1040
1072
|
await this.loadNextPageFollows('followers', request);
|
|
1041
1073
|
}
|
|
1042
1074
|
|
|
1043
|
-
async loadNextPageFollowing(
|
|
1075
|
+
async loadNextPageFollowing(
|
|
1076
|
+
request: Pick<QueryFollowsRequest, 'limit' | 'sort'>,
|
|
1077
|
+
) {
|
|
1044
1078
|
await this.loadNextPageFollows('following', request);
|
|
1045
1079
|
}
|
|
1046
1080
|
|
|
@@ -1078,7 +1112,7 @@ export class Feed extends FeedApi {
|
|
|
1078
1112
|
this.state.next((currentState) => ({
|
|
1079
1113
|
...currentState,
|
|
1080
1114
|
members: currentState.members
|
|
1081
|
-
? currentState.members
|
|
1115
|
+
? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
|
|
1082
1116
|
: members,
|
|
1083
1117
|
member_pagination: {
|
|
1084
1118
|
...currentState.member_pagination,
|