@stream-io/feeds-client 0.1.7 → 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 +20 -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 +363 -141
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +363 -142
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +363 -141
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +363 -142
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +337 -140
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +337 -141
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +337 -140
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +337 -141
- package/dist/index.node.js.map +1 -1
- package/dist/src/Feed.d.ts +42 -11
- package/dist/src/FeedsClient.d.ts +10 -3
- package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
- package/dist/src/gen/models/index.d.ts +25 -2
- 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 +230 -192
- package/src/FeedsClient.ts +75 -3
- package/src/gen/feeds/FeedsApi.ts +0 -1
- package/src/gen/model-decoders/decoders.ts +16 -0
- package/src/gen/model-decoders/event-decoder-mapping.ts +3 -0
- package/src/gen/models/index.ts +42 -4
- 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) {
|
|
@@ -501,6 +426,10 @@ export class Feed extends FeedApi {
|
|
|
501
426
|
return newState ?? currentState;
|
|
502
427
|
});
|
|
503
428
|
},
|
|
429
|
+
'feeds.notification_feed.updated': (event) => {
|
|
430
|
+
console.info('notification feed updated', event);
|
|
431
|
+
// TODO: handle notification feed updates
|
|
432
|
+
},
|
|
504
433
|
// the poll events should be removed from here
|
|
505
434
|
'feeds.poll.closed': Feed.noop,
|
|
506
435
|
'feeds.poll.deleted': Feed.noop,
|
|
@@ -531,9 +460,9 @@ export class Feed extends FeedApi {
|
|
|
531
460
|
groupId: 'user' | 'timeline' | (string & {}),
|
|
532
461
|
id: string,
|
|
533
462
|
data?: FeedResponse,
|
|
463
|
+
watch = false,
|
|
534
464
|
) {
|
|
535
|
-
|
|
536
|
-
super(client as unknown as FeedsApi, groupId, id);
|
|
465
|
+
super(client, groupId, id);
|
|
537
466
|
this.state = new StateStore<FeedState>({
|
|
538
467
|
fid: `${groupId}:${id}`,
|
|
539
468
|
group_id: groupId,
|
|
@@ -542,6 +471,7 @@ export class Feed extends FeedApi {
|
|
|
542
471
|
is_loading: false,
|
|
543
472
|
is_loading_activities: false,
|
|
544
473
|
comments_by_entity_id: {},
|
|
474
|
+
watch,
|
|
545
475
|
});
|
|
546
476
|
this.client = client;
|
|
547
477
|
}
|
|
@@ -652,6 +582,8 @@ export class Feed extends FeedApi {
|
|
|
652
582
|
});
|
|
653
583
|
}
|
|
654
584
|
} else {
|
|
585
|
+
// Empty queue when reinitializing the state
|
|
586
|
+
this.stateUpdateQueue.clear();
|
|
655
587
|
const responseCopy: Partial<
|
|
656
588
|
StreamResponse<GetOrCreateFeedResponse>['feed'] &
|
|
657
589
|
StreamResponse<GetOrCreateFeedResponse>
|
|
@@ -676,8 +608,12 @@ export class Feed extends FeedApi {
|
|
|
676
608
|
if (!request?.following_pagination?.limit) {
|
|
677
609
|
delete nextState.following;
|
|
678
610
|
}
|
|
611
|
+
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
612
|
+
delete nextState.members;
|
|
613
|
+
}
|
|
679
614
|
|
|
680
615
|
nextState.last_get_or_create_request_config = request;
|
|
616
|
+
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
681
617
|
|
|
682
618
|
return nextState;
|
|
683
619
|
});
|
|
@@ -694,6 +630,80 @@ export class Feed extends FeedApi {
|
|
|
694
630
|
}
|
|
695
631
|
}
|
|
696
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
|
+
|
|
697
707
|
private handleBookmarkAdded(event: BookmarkAddedEvent) {
|
|
698
708
|
const currentActivities = this.currentState.activities;
|
|
699
709
|
const { connected_user: connectedUser } =
|
|
@@ -771,57 +781,93 @@ export class Feed extends FeedApi {
|
|
|
771
781
|
return commentIndex;
|
|
772
782
|
}
|
|
773
783
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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
|
+
];
|
|
780
804
|
|
|
781
|
-
|
|
805
|
+
this.state.next((currentState) => {
|
|
806
|
+
const newCommentsByEntityId = {
|
|
807
|
+
...currentState.comments_by_entity_id,
|
|
808
|
+
};
|
|
782
809
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
activityIndex = activities.findIndex(
|
|
786
|
-
(activity_) => activity_.id === activity.id,
|
|
787
|
-
);
|
|
788
|
-
}
|
|
810
|
+
while (traverseArray.length) {
|
|
811
|
+
const item = traverseArray.pop()!;
|
|
789
812
|
|
|
790
|
-
|
|
791
|
-
}
|
|
813
|
+
const entityId = item.entityId;
|
|
792
814
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
this.state.next((currentState) => {
|
|
798
|
-
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;
|
|
799
819
|
|
|
800
|
-
|
|
820
|
+
traverseArray.push({
|
|
821
|
+
entityId: comment.id,
|
|
822
|
+
entityParentId: entityId,
|
|
823
|
+
comments: comment.replies,
|
|
824
|
+
next: comment.meta?.next_cursor,
|
|
825
|
+
});
|
|
826
|
+
});
|
|
801
827
|
|
|
802
|
-
|
|
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
|
+
);
|
|
803
835
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
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
|
+
}
|
|
807
849
|
|
|
808
850
|
return {
|
|
809
851
|
...currentState,
|
|
810
|
-
|
|
852
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
811
853
|
};
|
|
812
854
|
});
|
|
813
855
|
}
|
|
814
856
|
|
|
815
857
|
private async loadNextPageComments({
|
|
816
|
-
|
|
858
|
+
entityId,
|
|
817
859
|
base,
|
|
818
860
|
sort,
|
|
819
|
-
|
|
861
|
+
entityParentId,
|
|
820
862
|
}: {
|
|
821
|
-
|
|
822
|
-
|
|
863
|
+
entityParentId?: string;
|
|
864
|
+
entityId: string;
|
|
823
865
|
sort: string;
|
|
824
|
-
base: () => Promise<
|
|
866
|
+
base: () => Promise<
|
|
867
|
+
PagerResponse & {
|
|
868
|
+
comments: Array<CommentResponse & ThreadedCommentResponse>;
|
|
869
|
+
}
|
|
870
|
+
>;
|
|
825
871
|
}) {
|
|
826
872
|
let error: unknown;
|
|
827
873
|
|
|
@@ -830,44 +876,24 @@ export class Feed extends FeedApi {
|
|
|
830
876
|
...currentState,
|
|
831
877
|
comments_by_entity_id: {
|
|
832
878
|
...currentState.comments_by_entity_id,
|
|
833
|
-
[
|
|
834
|
-
...currentState.comments_by_entity_id[
|
|
879
|
+
[entityId]: {
|
|
880
|
+
...currentState.comments_by_entity_id[entityId],
|
|
835
881
|
pagination: {
|
|
836
|
-
...currentState.comments_by_entity_id[
|
|
882
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
837
883
|
loading_next_page: true,
|
|
838
884
|
},
|
|
839
885
|
},
|
|
840
886
|
},
|
|
841
887
|
}));
|
|
842
888
|
|
|
843
|
-
const { next
|
|
889
|
+
const { next, comments } = await base();
|
|
844
890
|
|
|
845
|
-
this.
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
if (typeof newPagination.sort === 'undefined') {
|
|
852
|
-
newPagination.sort = sort;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
return {
|
|
856
|
-
...currentState,
|
|
857
|
-
comments_by_entity_id: {
|
|
858
|
-
...currentState.comments_by_entity_id,
|
|
859
|
-
[forId]: {
|
|
860
|
-
...currentState.comments_by_entity_id[forId],
|
|
861
|
-
parent_id: parentId,
|
|
862
|
-
pagination: newPagination,
|
|
863
|
-
comments: currentState.comments_by_entity_id[forId]?.comments
|
|
864
|
-
? currentState.comments_by_entity_id[forId].comments?.concat(
|
|
865
|
-
comments,
|
|
866
|
-
)
|
|
867
|
-
: comments,
|
|
868
|
-
},
|
|
869
|
-
},
|
|
870
|
-
};
|
|
891
|
+
this.loadCommentsIntoState({
|
|
892
|
+
entityId,
|
|
893
|
+
comments,
|
|
894
|
+
entityParentId,
|
|
895
|
+
next,
|
|
896
|
+
sort,
|
|
871
897
|
});
|
|
872
898
|
} catch (e) {
|
|
873
899
|
error = e;
|
|
@@ -876,10 +902,10 @@ export class Feed extends FeedApi {
|
|
|
876
902
|
...currentState,
|
|
877
903
|
comments_by_entity_id: {
|
|
878
904
|
...currentState.comments_by_entity_id,
|
|
879
|
-
[
|
|
880
|
-
...currentState.comments_by_entity_id[
|
|
905
|
+
[entityId]: {
|
|
906
|
+
...currentState.comments_by_entity_id[entityId],
|
|
881
907
|
pagination: {
|
|
882
|
-
...currentState.comments_by_entity_id[
|
|
908
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
883
909
|
loading_next_page: false,
|
|
884
910
|
},
|
|
885
911
|
},
|
|
@@ -916,7 +942,7 @@ export class Feed extends FeedApi {
|
|
|
916
942
|
}
|
|
917
943
|
|
|
918
944
|
await this.loadNextPageComments({
|
|
919
|
-
|
|
945
|
+
entityId: activity.id,
|
|
920
946
|
base: () =>
|
|
921
947
|
this.client.getComments({
|
|
922
948
|
...request,
|
|
@@ -951,7 +977,7 @@ export class Feed extends FeedApi {
|
|
|
951
977
|
}
|
|
952
978
|
|
|
953
979
|
await this.loadNextPageComments({
|
|
954
|
-
|
|
980
|
+
entityId: comment.id,
|
|
955
981
|
base: () =>
|
|
956
982
|
this.client.getCommentReplies({
|
|
957
983
|
...request,
|
|
@@ -963,7 +989,7 @@ export class Feed extends FeedApi {
|
|
|
963
989
|
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
964
990
|
next: currentNextCursor,
|
|
965
991
|
}),
|
|
966
|
-
|
|
992
|
+
entityParentId: comment.parent_id ?? comment.object_id,
|
|
967
993
|
sort,
|
|
968
994
|
});
|
|
969
995
|
}
|
|
@@ -1002,17 +1028,25 @@ export class Feed extends FeedApi {
|
|
|
1002
1028
|
sort,
|
|
1003
1029
|
});
|
|
1004
1030
|
|
|
1005
|
-
this.state.next((currentState) =>
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
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
|
+
});
|
|
1016
1050
|
} catch (e) {
|
|
1017
1051
|
error = e;
|
|
1018
1052
|
} finally {
|
|
@@ -1032,11 +1066,15 @@ export class Feed extends FeedApi {
|
|
|
1032
1066
|
}
|
|
1033
1067
|
}
|
|
1034
1068
|
|
|
1035
|
-
async loadNextPageFollowers(
|
|
1069
|
+
async loadNextPageFollowers(
|
|
1070
|
+
request: Pick<QueryFollowsRequest, 'limit' | 'sort'>,
|
|
1071
|
+
) {
|
|
1036
1072
|
await this.loadNextPageFollows('followers', request);
|
|
1037
1073
|
}
|
|
1038
1074
|
|
|
1039
|
-
async loadNextPageFollowing(
|
|
1075
|
+
async loadNextPageFollowing(
|
|
1076
|
+
request: Pick<QueryFollowsRequest, 'limit' | 'sort'>,
|
|
1077
|
+
) {
|
|
1040
1078
|
await this.loadNextPageFollows('following', request);
|
|
1041
1079
|
}
|
|
1042
1080
|
|
|
@@ -1074,7 +1112,7 @@ export class Feed extends FeedApi {
|
|
|
1074
1112
|
this.state.next((currentState) => ({
|
|
1075
1113
|
...currentState,
|
|
1076
1114
|
members: currentState.members
|
|
1077
|
-
? currentState.members
|
|
1115
|
+
? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
|
|
1078
1116
|
: members,
|
|
1079
1117
|
member_pagination: {
|
|
1080
1118
|
...currentState.member_pagination,
|