@stream-io/feeds-client 0.1.10 → 0.2.0
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/CHANGELOG.md +30 -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/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/useCreateFeedsClient.d.ts +1 -1
- package/dist/@react-bindings/wrappers/StreamFeed.d.ts +1 -1
- package/dist/index-react-bindings.browser.cjs +1720 -1601
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +1720 -1601
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +1720 -1601
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +1720 -1601
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +1724 -1602
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +1722 -1603
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.node.cjs +1724 -1602
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +1722 -1603
- package/dist/index.node.js.map +1 -1
- package/dist/src/common/ActivitySearchSource.d.ts +1 -1
- package/dist/src/common/FeedSearchSource.d.ts +2 -2
- package/dist/src/common/Poll.d.ts +1 -1
- 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 +8 -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/event-handlers/watch/handle-watch-started.d.ts +2 -0
- package/dist/src/feed/event-handlers/watch/handle-watch-stopped.d.ts +2 -0
- package/dist/src/feed/event-handlers/watch/index.d.ts +2 -0
- package/dist/src/{Feed.d.ts → feed/feed.d.ts} +16 -43
- package/dist/src/feed/index.d.ts +2 -0
- package/dist/src/feeds-client/event-handlers/index.d.ts +1 -0
- package/dist/src/feeds-client/event-handlers/user/handle-user-updated.d.ts +3 -0
- package/dist/src/feeds-client/feeds-client.d.ts +76 -0
- package/dist/src/feeds-client/index.d.ts +2 -0
- package/dist/src/gen/feeds/FeedsApi.d.ts +27 -23
- package/dist/src/gen/models/index.d.ts +168 -23
- 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 +3 -2
- package/src/common/ActivitySearchSource.ts +1 -1
- package/src/common/FeedSearchSource.ts +2 -2
- package/src/common/Poll.ts +1 -1
- package/src/common/UserSearchSource.ts +1 -1
- 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 +250 -0
- package/src/feed/event-handlers/follow/handle-follow-created.ts +90 -0
- package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +268 -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 +85 -0
- package/src/feed/event-handlers/follow/index.ts +3 -0
- package/src/feed/event-handlers/index.ts +8 -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/event-handlers/watch/handle-watch-started.ts +5 -0
- package/src/feed/event-handlers/watch/handle-watch-stopped.ts +5 -0
- package/src/feed/event-handlers/watch/index.ts +2 -0
- package/src/{Feed.ts → feed/feed.ts} +87 -516
- package/src/feed/index.ts +2 -0
- package/src/feeds-client/event-handlers/index.ts +1 -0
- package/src/feeds-client/event-handlers/user/handle-user-updated.test.ts +53 -0
- package/src/feeds-client/event-handlers/user/handle-user-updated.ts +28 -0
- package/src/{FeedsClient.ts → feeds-client/feeds-client.ts} +63 -36
- package/src/feeds-client/index.ts +2 -0
- package/src/gen/feeds/FeedsApi.ts +164 -138
- package/src/gen/model-decoders/decoders.ts +22 -0
- package/src/gen/models/index.ts +288 -29
- package/src/gen-imports.ts +1 -1
- package/src/test-utils/index.ts +1 -0
- package/src/test-utils/response-generators.ts +101 -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/FeedsClient.d.ts +0 -75
- 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/dist/index.node.cjs
CHANGED
|
@@ -634,6 +634,7 @@ decoders.FeedResponse = (input) => {
|
|
|
634
634
|
updated_at: { type: 'DatetimeType', isSingle: true },
|
|
635
635
|
created_by: { type: 'UserResponse', isSingle: true },
|
|
636
636
|
deleted_at: { type: 'DatetimeType', isSingle: true },
|
|
637
|
+
own_follows: { type: 'FollowResponse', isSingle: false },
|
|
637
638
|
};
|
|
638
639
|
return decode(typeMappings, input);
|
|
639
640
|
};
|
|
@@ -852,6 +853,13 @@ decoders.ModerationCustomActionEvent = (input) => {
|
|
|
852
853
|
};
|
|
853
854
|
return decode(typeMappings, input);
|
|
854
855
|
};
|
|
856
|
+
decoders.ModerationFlagResponse = (input) => {
|
|
857
|
+
const typeMappings = {
|
|
858
|
+
review_queue_item: { type: 'ReviewQueueItemResponse', isSingle: true },
|
|
859
|
+
user: { type: 'UserResponse', isSingle: true },
|
|
860
|
+
};
|
|
861
|
+
return decode(typeMappings, input);
|
|
862
|
+
};
|
|
855
863
|
decoders.ModerationFlaggedEvent = (input) => {
|
|
856
864
|
const typeMappings = {
|
|
857
865
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -888,6 +896,7 @@ decoders.NotificationFeedUpdatedEvent = (input) => {
|
|
|
888
896
|
};
|
|
889
897
|
decoders.NotificationStatusResponse = (input) => {
|
|
890
898
|
const typeMappings = {
|
|
899
|
+
last_read_at: { type: 'DatetimeType', isSingle: true },
|
|
891
900
|
last_seen_at: { type: 'DatetimeType', isSingle: true },
|
|
892
901
|
};
|
|
893
902
|
return decode(typeMappings, input);
|
|
@@ -1155,6 +1164,7 @@ decoders.ReviewQueueItemResponse = (input) => {
|
|
|
1155
1164
|
updated_at: { type: 'DatetimeType', isSingle: true },
|
|
1156
1165
|
actions: { type: 'ActionLogResponse', isSingle: false },
|
|
1157
1166
|
bans: { type: 'Ban', isSingle: false },
|
|
1167
|
+
flags: { type: 'ModerationFlagResponse', isSingle: false },
|
|
1158
1168
|
completed_at: { type: 'DatetimeType', isSingle: true },
|
|
1159
1169
|
reviewed_at: { type: 'DatetimeType', isSingle: true },
|
|
1160
1170
|
assigned_to: { type: 'UserResponse', isSingle: true },
|
|
@@ -1231,6 +1241,12 @@ decoders.ThreadedCommentResponse = (input) => {
|
|
|
1231
1241
|
};
|
|
1232
1242
|
return decode(typeMappings, input);
|
|
1233
1243
|
};
|
|
1244
|
+
decoders.UnfollowResponse = (input) => {
|
|
1245
|
+
const typeMappings = {
|
|
1246
|
+
follow: { type: 'FollowResponse', isSingle: true },
|
|
1247
|
+
};
|
|
1248
|
+
return decode(typeMappings, input);
|
|
1249
|
+
};
|
|
1234
1250
|
decoders.UnpinActivityResponse = (input) => {
|
|
1235
1251
|
const typeMappings = {
|
|
1236
1252
|
activity: { type: 'ActivityResponse', isSingle: true },
|
|
@@ -1471,7 +1487,7 @@ class FeedsApi {
|
|
|
1471
1487
|
async addActivity(request) {
|
|
1472
1488
|
const body = {
|
|
1473
1489
|
type: request?.type,
|
|
1474
|
-
|
|
1490
|
+
feeds: request?.feeds,
|
|
1475
1491
|
expires_at: request?.expires_at,
|
|
1476
1492
|
id: request?.id,
|
|
1477
1493
|
parent_id: request?.parent_id,
|
|
@@ -1501,7 +1517,7 @@ class FeedsApi {
|
|
|
1501
1517
|
}
|
|
1502
1518
|
async deleteActivities(request) {
|
|
1503
1519
|
const body = {
|
|
1504
|
-
|
|
1520
|
+
ids: request?.ids,
|
|
1505
1521
|
hard_delete: request?.hard_delete,
|
|
1506
1522
|
};
|
|
1507
1523
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/activities/delete', undefined, undefined, body, 'application/json');
|
|
@@ -1520,56 +1536,6 @@ class FeedsApi {
|
|
|
1520
1536
|
decoders.QueryActivitiesResponse?.(response.body);
|
|
1521
1537
|
return { ...response.body, metadata: response.metadata };
|
|
1522
1538
|
}
|
|
1523
|
-
async deleteActivity(request) {
|
|
1524
|
-
const queryParams = {
|
|
1525
|
-
hard_delete: request?.hard_delete,
|
|
1526
|
-
};
|
|
1527
|
-
const pathParams = {
|
|
1528
|
-
activity_id: request?.activity_id,
|
|
1529
|
-
};
|
|
1530
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/activities/{activity_id}', pathParams, queryParams);
|
|
1531
|
-
decoders.DeleteActivityResponse?.(response.body);
|
|
1532
|
-
return { ...response.body, metadata: response.metadata };
|
|
1533
|
-
}
|
|
1534
|
-
async getActivity(request) {
|
|
1535
|
-
const pathParams = {
|
|
1536
|
-
activity_id: request?.activity_id,
|
|
1537
|
-
};
|
|
1538
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/activities/{activity_id}', pathParams, undefined);
|
|
1539
|
-
decoders.GetActivityResponse?.(response.body);
|
|
1540
|
-
return { ...response.body, metadata: response.metadata };
|
|
1541
|
-
}
|
|
1542
|
-
async updateActivityPartial(request) {
|
|
1543
|
-
const pathParams = {
|
|
1544
|
-
activity_id: request?.activity_id,
|
|
1545
|
-
};
|
|
1546
|
-
const body = {
|
|
1547
|
-
unset: request?.unset,
|
|
1548
|
-
set: request?.set,
|
|
1549
|
-
};
|
|
1550
|
-
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/activities/{activity_id}', pathParams, undefined, body, 'application/json');
|
|
1551
|
-
decoders.UpdateActivityPartialResponse?.(response.body);
|
|
1552
|
-
return { ...response.body, metadata: response.metadata };
|
|
1553
|
-
}
|
|
1554
|
-
async updateActivity(request) {
|
|
1555
|
-
const pathParams = {
|
|
1556
|
-
activity_id: request?.activity_id,
|
|
1557
|
-
};
|
|
1558
|
-
const body = {
|
|
1559
|
-
expires_at: request?.expires_at,
|
|
1560
|
-
poll_id: request?.poll_id,
|
|
1561
|
-
text: request?.text,
|
|
1562
|
-
visibility: request?.visibility,
|
|
1563
|
-
attachments: request?.attachments,
|
|
1564
|
-
filter_tags: request?.filter_tags,
|
|
1565
|
-
interest_tags: request?.interest_tags,
|
|
1566
|
-
custom: request?.custom,
|
|
1567
|
-
location: request?.location,
|
|
1568
|
-
};
|
|
1569
|
-
const response = await this.apiClient.sendRequest('PUT', '/api/v2/feeds/activities/{activity_id}', pathParams, undefined, body, 'application/json');
|
|
1570
|
-
decoders.UpdateActivityResponse?.(response.body);
|
|
1571
|
-
return { ...response.body, metadata: response.metadata };
|
|
1572
|
-
}
|
|
1573
1539
|
async deleteBookmark(request) {
|
|
1574
1540
|
const queryParams = {
|
|
1575
1541
|
folder_id: request?.folder_id,
|
|
@@ -1608,6 +1574,21 @@ class FeedsApi {
|
|
|
1608
1574
|
decoders.AddBookmarkResponse?.(response.body);
|
|
1609
1575
|
return { ...response.body, metadata: response.metadata };
|
|
1610
1576
|
}
|
|
1577
|
+
async activityFeedback(request) {
|
|
1578
|
+
const pathParams = {
|
|
1579
|
+
activity_id: request?.activity_id,
|
|
1580
|
+
};
|
|
1581
|
+
const body = {
|
|
1582
|
+
hide: request?.hide,
|
|
1583
|
+
mute_user: request?.mute_user,
|
|
1584
|
+
reason: request?.reason,
|
|
1585
|
+
report: request?.report,
|
|
1586
|
+
show_less: request?.show_less,
|
|
1587
|
+
};
|
|
1588
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/activities/{activity_id}/feedback', pathParams, undefined, body, 'application/json');
|
|
1589
|
+
decoders.ActivityFeedbackResponse?.(response.body);
|
|
1590
|
+
return { ...response.body, metadata: response.metadata };
|
|
1591
|
+
}
|
|
1611
1592
|
async castPollVote(request) {
|
|
1612
1593
|
const pathParams = {
|
|
1613
1594
|
activity_id: request?.activity_id,
|
|
@@ -1670,6 +1651,56 @@ class FeedsApi {
|
|
|
1670
1651
|
decoders.DeleteActivityReactionResponse?.(response.body);
|
|
1671
1652
|
return { ...response.body, metadata: response.metadata };
|
|
1672
1653
|
}
|
|
1654
|
+
async deleteActivity(request) {
|
|
1655
|
+
const queryParams = {
|
|
1656
|
+
hard_delete: request?.hard_delete,
|
|
1657
|
+
};
|
|
1658
|
+
const pathParams = {
|
|
1659
|
+
id: request?.id,
|
|
1660
|
+
};
|
|
1661
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/activities/{id}', pathParams, queryParams);
|
|
1662
|
+
decoders.DeleteActivityResponse?.(response.body);
|
|
1663
|
+
return { ...response.body, metadata: response.metadata };
|
|
1664
|
+
}
|
|
1665
|
+
async getActivity(request) {
|
|
1666
|
+
const pathParams = {
|
|
1667
|
+
id: request?.id,
|
|
1668
|
+
};
|
|
1669
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/activities/{id}', pathParams, undefined);
|
|
1670
|
+
decoders.GetActivityResponse?.(response.body);
|
|
1671
|
+
return { ...response.body, metadata: response.metadata };
|
|
1672
|
+
}
|
|
1673
|
+
async updateActivityPartial(request) {
|
|
1674
|
+
const pathParams = {
|
|
1675
|
+
id: request?.id,
|
|
1676
|
+
};
|
|
1677
|
+
const body = {
|
|
1678
|
+
unset: request?.unset,
|
|
1679
|
+
set: request?.set,
|
|
1680
|
+
};
|
|
1681
|
+
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/activities/{id}', pathParams, undefined, body, 'application/json');
|
|
1682
|
+
decoders.UpdateActivityPartialResponse?.(response.body);
|
|
1683
|
+
return { ...response.body, metadata: response.metadata };
|
|
1684
|
+
}
|
|
1685
|
+
async updateActivity(request) {
|
|
1686
|
+
const pathParams = {
|
|
1687
|
+
id: request?.id,
|
|
1688
|
+
};
|
|
1689
|
+
const body = {
|
|
1690
|
+
expires_at: request?.expires_at,
|
|
1691
|
+
poll_id: request?.poll_id,
|
|
1692
|
+
text: request?.text,
|
|
1693
|
+
visibility: request?.visibility,
|
|
1694
|
+
attachments: request?.attachments,
|
|
1695
|
+
filter_tags: request?.filter_tags,
|
|
1696
|
+
interest_tags: request?.interest_tags,
|
|
1697
|
+
custom: request?.custom,
|
|
1698
|
+
location: request?.location,
|
|
1699
|
+
};
|
|
1700
|
+
const response = await this.apiClient.sendRequest('PUT', '/api/v2/feeds/activities/{id}', pathParams, undefined, body, 'application/json');
|
|
1701
|
+
decoders.UpdateActivityResponse?.(response.body);
|
|
1702
|
+
return { ...response.body, metadata: response.metadata };
|
|
1703
|
+
}
|
|
1673
1704
|
async queryBookmarkFolders(request) {
|
|
1674
1705
|
const body = {
|
|
1675
1706
|
limit: request?.limit,
|
|
@@ -1765,49 +1796,52 @@ class FeedsApi {
|
|
|
1765
1796
|
return { ...response.body, metadata: response.metadata };
|
|
1766
1797
|
}
|
|
1767
1798
|
async deleteComment(request) {
|
|
1799
|
+
const queryParams = {
|
|
1800
|
+
hard_delete: request?.hard_delete,
|
|
1801
|
+
};
|
|
1768
1802
|
const pathParams = {
|
|
1769
|
-
|
|
1803
|
+
id: request?.id,
|
|
1770
1804
|
};
|
|
1771
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{
|
|
1805
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{id}', pathParams, queryParams);
|
|
1772
1806
|
decoders.DeleteCommentResponse?.(response.body);
|
|
1773
1807
|
return { ...response.body, metadata: response.metadata };
|
|
1774
1808
|
}
|
|
1775
1809
|
async getComment(request) {
|
|
1776
1810
|
const pathParams = {
|
|
1777
|
-
|
|
1811
|
+
id: request?.id,
|
|
1778
1812
|
};
|
|
1779
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{
|
|
1813
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{id}', pathParams, undefined);
|
|
1780
1814
|
decoders.GetCommentResponse?.(response.body);
|
|
1781
1815
|
return { ...response.body, metadata: response.metadata };
|
|
1782
1816
|
}
|
|
1783
1817
|
async updateComment(request) {
|
|
1784
1818
|
const pathParams = {
|
|
1785
|
-
|
|
1819
|
+
id: request?.id,
|
|
1786
1820
|
};
|
|
1787
1821
|
const body = {
|
|
1788
1822
|
comment: request?.comment,
|
|
1789
1823
|
custom: request?.custom,
|
|
1790
1824
|
};
|
|
1791
|
-
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/comments/{
|
|
1825
|
+
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/comments/{id}', pathParams, undefined, body, 'application/json');
|
|
1792
1826
|
decoders.UpdateCommentResponse?.(response.body);
|
|
1793
1827
|
return { ...response.body, metadata: response.metadata };
|
|
1794
1828
|
}
|
|
1795
1829
|
async addCommentReaction(request) {
|
|
1796
1830
|
const pathParams = {
|
|
1797
|
-
|
|
1831
|
+
id: request?.id,
|
|
1798
1832
|
};
|
|
1799
1833
|
const body = {
|
|
1800
1834
|
type: request?.type,
|
|
1801
1835
|
create_notification_activity: request?.create_notification_activity,
|
|
1802
1836
|
custom: request?.custom,
|
|
1803
1837
|
};
|
|
1804
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{
|
|
1838
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{id}/reactions', pathParams, undefined, body, 'application/json');
|
|
1805
1839
|
decoders.AddCommentReactionResponse?.(response.body);
|
|
1806
1840
|
return { ...response.body, metadata: response.metadata };
|
|
1807
1841
|
}
|
|
1808
1842
|
async queryCommentReactions(request) {
|
|
1809
1843
|
const pathParams = {
|
|
1810
|
-
|
|
1844
|
+
id: request?.id,
|
|
1811
1845
|
};
|
|
1812
1846
|
const body = {
|
|
1813
1847
|
limit: request?.limit,
|
|
@@ -1816,16 +1850,16 @@ class FeedsApi {
|
|
|
1816
1850
|
sort: request?.sort,
|
|
1817
1851
|
filter: request?.filter,
|
|
1818
1852
|
};
|
|
1819
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{
|
|
1853
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{id}/reactions/query', pathParams, undefined, body, 'application/json');
|
|
1820
1854
|
decoders.QueryCommentReactionsResponse?.(response.body);
|
|
1821
1855
|
return { ...response.body, metadata: response.metadata };
|
|
1822
1856
|
}
|
|
1823
1857
|
async deleteCommentReaction(request) {
|
|
1824
1858
|
const pathParams = {
|
|
1825
|
-
|
|
1859
|
+
id: request?.id,
|
|
1826
1860
|
type: request?.type,
|
|
1827
1861
|
};
|
|
1828
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{
|
|
1862
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{id}/reactions/{type}', pathParams, undefined);
|
|
1829
1863
|
decoders.DeleteCommentReactionResponse?.(response.body);
|
|
1830
1864
|
return { ...response.body, metadata: response.metadata };
|
|
1831
1865
|
}
|
|
@@ -1839,9 +1873,9 @@ class FeedsApi {
|
|
|
1839
1873
|
next: request?.next,
|
|
1840
1874
|
};
|
|
1841
1875
|
const pathParams = {
|
|
1842
|
-
|
|
1876
|
+
id: request?.id,
|
|
1843
1877
|
};
|
|
1844
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{
|
|
1878
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{id}/replies', pathParams, queryParams);
|
|
1845
1879
|
decoders.GetCommentRepliesResponse?.(response.body);
|
|
1846
1880
|
return { ...response.body, metadata: response.metadata };
|
|
1847
1881
|
}
|
|
@@ -1890,7 +1924,6 @@ class FeedsApi {
|
|
|
1890
1924
|
feed_id: request?.feed_id,
|
|
1891
1925
|
};
|
|
1892
1926
|
const body = {
|
|
1893
|
-
created_by_id: request?.created_by_id,
|
|
1894
1927
|
custom: request?.custom,
|
|
1895
1928
|
};
|
|
1896
1929
|
const response = await this.apiClient.sendRequest('PUT', '/api/v2/feeds/feed_groups/{feed_group_id}/feeds/{feed_id}', pathParams, undefined, body, 'application/json');
|
|
@@ -1906,6 +1939,7 @@ class FeedsApi {
|
|
|
1906
1939
|
mark_all_read: request?.mark_all_read,
|
|
1907
1940
|
mark_all_seen: request?.mark_all_seen,
|
|
1908
1941
|
mark_read: request?.mark_read,
|
|
1942
|
+
mark_seen: request?.mark_seen,
|
|
1909
1943
|
mark_watched: request?.mark_watched,
|
|
1910
1944
|
};
|
|
1911
1945
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/feed_groups/{feed_group_id}/feeds/{feed_id}/activities/mark/batch', pathParams, undefined, body, 'application/json');
|
|
@@ -2016,7 +2050,7 @@ class FeedsApi {
|
|
|
2016
2050
|
decoders.CreateFeedsBatchResponse?.(response.body);
|
|
2017
2051
|
return { ...response.body, metadata: response.metadata };
|
|
2018
2052
|
}
|
|
2019
|
-
async
|
|
2053
|
+
async _queryFeeds(request) {
|
|
2020
2054
|
const queryParams = {
|
|
2021
2055
|
connection_id: request?.connection_id,
|
|
2022
2056
|
};
|
|
@@ -2059,8 +2093,8 @@ class FeedsApi {
|
|
|
2059
2093
|
}
|
|
2060
2094
|
async acceptFollow(request) {
|
|
2061
2095
|
const body = {
|
|
2062
|
-
|
|
2063
|
-
|
|
2096
|
+
source: request?.source,
|
|
2097
|
+
target: request?.target,
|
|
2064
2098
|
follower_role: request?.follower_role,
|
|
2065
2099
|
};
|
|
2066
2100
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/follows/accept', undefined, undefined, body, 'application/json');
|
|
@@ -2089,8 +2123,8 @@ class FeedsApi {
|
|
|
2089
2123
|
}
|
|
2090
2124
|
async rejectFollow(request) {
|
|
2091
2125
|
const body = {
|
|
2092
|
-
|
|
2093
|
-
|
|
2126
|
+
source: request?.source,
|
|
2127
|
+
target: request?.target,
|
|
2094
2128
|
};
|
|
2095
2129
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/follows/reject', undefined, undefined, body, 'application/json');
|
|
2096
2130
|
decoders.RejectFollowResponse?.(response.body);
|
|
@@ -3751,1631 +3785,1699 @@ const decodeWSEvent = (data) => {
|
|
|
3751
3785
|
}
|
|
3752
3786
|
};
|
|
3753
3787
|
|
|
3754
|
-
class
|
|
3755
|
-
constructor(
|
|
3756
|
-
this.
|
|
3757
|
-
this.group = group;
|
|
3758
|
-
this.id = id;
|
|
3788
|
+
class ModerationApi {
|
|
3789
|
+
constructor(apiClient) {
|
|
3790
|
+
this.apiClient = apiClient;
|
|
3759
3791
|
}
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3792
|
+
async ban(request) {
|
|
3793
|
+
const body = {
|
|
3794
|
+
target_user_id: request?.target_user_id,
|
|
3795
|
+
banned_by_id: request?.banned_by_id,
|
|
3796
|
+
channel_cid: request?.channel_cid,
|
|
3797
|
+
delete_messages: request?.delete_messages,
|
|
3798
|
+
ip_ban: request?.ip_ban,
|
|
3799
|
+
reason: request?.reason,
|
|
3800
|
+
shadow: request?.shadow,
|
|
3801
|
+
timeout: request?.timeout,
|
|
3802
|
+
banned_by: request?.banned_by,
|
|
3803
|
+
};
|
|
3804
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/ban', undefined, undefined, body, 'application/json');
|
|
3805
|
+
decoders.BanResponse?.(response.body);
|
|
3806
|
+
return { ...response.body, metadata: response.metadata };
|
|
3766
3807
|
}
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3808
|
+
async upsertConfig(request) {
|
|
3809
|
+
const body = {
|
|
3810
|
+
key: request?.key,
|
|
3811
|
+
async: request?.async,
|
|
3812
|
+
team: request?.team,
|
|
3813
|
+
ai_image_config: request?.ai_image_config,
|
|
3814
|
+
ai_text_config: request?.ai_text_config,
|
|
3815
|
+
ai_video_config: request?.ai_video_config,
|
|
3816
|
+
automod_platform_circumvention_config: request?.automod_platform_circumvention_config,
|
|
3817
|
+
automod_semantic_filters_config: request?.automod_semantic_filters_config,
|
|
3818
|
+
automod_toxicity_config: request?.automod_toxicity_config,
|
|
3819
|
+
aws_rekognition_config: request?.aws_rekognition_config,
|
|
3820
|
+
block_list_config: request?.block_list_config,
|
|
3821
|
+
bodyguard_config: request?.bodyguard_config,
|
|
3822
|
+
google_vision_config: request?.google_vision_config,
|
|
3823
|
+
rule_builder_config: request?.rule_builder_config,
|
|
3824
|
+
velocity_filter_config: request?.velocity_filter_config,
|
|
3825
|
+
video_call_rule_config: request?.video_call_rule_config,
|
|
3826
|
+
};
|
|
3827
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/config', undefined, undefined, body, 'application/json');
|
|
3828
|
+
decoders.UpsertConfigResponse?.(response.body);
|
|
3829
|
+
return { ...response.body, metadata: response.metadata };
|
|
3773
3830
|
}
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3831
|
+
async deleteConfig(request) {
|
|
3832
|
+
const queryParams = {
|
|
3833
|
+
team: request?.team,
|
|
3834
|
+
};
|
|
3835
|
+
const pathParams = {
|
|
3836
|
+
key: request?.key,
|
|
3837
|
+
};
|
|
3838
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
3839
|
+
decoders.DeleteModerationConfigResponse?.(response.body);
|
|
3840
|
+
return { ...response.body, metadata: response.metadata };
|
|
3780
3841
|
}
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3842
|
+
async getConfig(request) {
|
|
3843
|
+
const queryParams = {
|
|
3844
|
+
team: request?.team,
|
|
3845
|
+
};
|
|
3846
|
+
const pathParams = {
|
|
3847
|
+
key: request?.key,
|
|
3848
|
+
};
|
|
3849
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
3850
|
+
decoders.GetConfigResponse?.(response.body);
|
|
3851
|
+
return { ...response.body, metadata: response.metadata };
|
|
3787
3852
|
}
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3853
|
+
async queryModerationConfigs(request) {
|
|
3854
|
+
const body = {
|
|
3855
|
+
limit: request?.limit,
|
|
3856
|
+
next: request?.next,
|
|
3857
|
+
prev: request?.prev,
|
|
3858
|
+
sort: request?.sort,
|
|
3859
|
+
filter: request?.filter,
|
|
3860
|
+
};
|
|
3861
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/configs', undefined, undefined, body, 'application/json');
|
|
3862
|
+
decoders.QueryModerationConfigsResponse?.(response.body);
|
|
3863
|
+
return { ...response.body, metadata: response.metadata };
|
|
3794
3864
|
}
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3865
|
+
async flag(request) {
|
|
3866
|
+
const body = {
|
|
3867
|
+
entity_id: request?.entity_id,
|
|
3868
|
+
entity_type: request?.entity_type,
|
|
3869
|
+
entity_creator_id: request?.entity_creator_id,
|
|
3870
|
+
reason: request?.reason,
|
|
3871
|
+
custom: request?.custom,
|
|
3872
|
+
moderation_payload: request?.moderation_payload,
|
|
3873
|
+
};
|
|
3874
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/flag', undefined, undefined, body, 'application/json');
|
|
3875
|
+
decoders.FlagResponse?.(response.body);
|
|
3876
|
+
return { ...response.body, metadata: response.metadata };
|
|
3801
3877
|
}
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
...request,
|
|
3807
|
-
});
|
|
3808
|
-
}
|
|
3809
|
-
acceptFeedMemberInvite(request) {
|
|
3810
|
-
return this.feedsApi.acceptFeedMemberInvite({
|
|
3811
|
-
feed_id: this.id,
|
|
3812
|
-
feed_group_id: this.group,
|
|
3813
|
-
...request,
|
|
3814
|
-
});
|
|
3815
|
-
}
|
|
3816
|
-
queryFeedMembers(request) {
|
|
3817
|
-
return this.feedsApi.queryFeedMembers({
|
|
3818
|
-
feed_id: this.id,
|
|
3819
|
-
feed_group_id: this.group,
|
|
3820
|
-
...request,
|
|
3821
|
-
});
|
|
3822
|
-
}
|
|
3823
|
-
rejectFeedMemberInvite(request) {
|
|
3824
|
-
return this.feedsApi.rejectFeedMemberInvite({
|
|
3825
|
-
feed_id: this.id,
|
|
3826
|
-
feed_group_id: this.group,
|
|
3827
|
-
...request,
|
|
3828
|
-
});
|
|
3829
|
-
}
|
|
3830
|
-
stopWatching(request) {
|
|
3831
|
-
return this.feedsApi.stopWatchingFeed({
|
|
3832
|
-
feed_id: this.id,
|
|
3833
|
-
feed_group_id: this.group,
|
|
3834
|
-
...request,
|
|
3835
|
-
});
|
|
3836
|
-
}
|
|
3837
|
-
}
|
|
3838
|
-
|
|
3839
|
-
const addActivitiesToState = (newActivities, activities, position) => {
|
|
3840
|
-
let result;
|
|
3841
|
-
if (activities === undefined) {
|
|
3842
|
-
activities = [];
|
|
3843
|
-
result = {
|
|
3844
|
-
changed: true,
|
|
3845
|
-
activities,
|
|
3878
|
+
async mute(request) {
|
|
3879
|
+
const body = {
|
|
3880
|
+
target_ids: request?.target_ids,
|
|
3881
|
+
timeout: request?.timeout,
|
|
3846
3882
|
};
|
|
3883
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/mute', undefined, undefined, body, 'application/json');
|
|
3884
|
+
decoders.MuteResponse?.(response.body);
|
|
3885
|
+
return { ...response.body, metadata: response.metadata };
|
|
3847
3886
|
}
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3887
|
+
async queryReviewQueue(request) {
|
|
3888
|
+
const body = {
|
|
3889
|
+
limit: request?.limit,
|
|
3890
|
+
lock_count: request?.lock_count,
|
|
3891
|
+
lock_duration: request?.lock_duration,
|
|
3892
|
+
lock_items: request?.lock_items,
|
|
3893
|
+
next: request?.next,
|
|
3894
|
+
prev: request?.prev,
|
|
3895
|
+
stats_only: request?.stats_only,
|
|
3896
|
+
sort: request?.sort,
|
|
3897
|
+
filter: request?.filter,
|
|
3852
3898
|
};
|
|
3899
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/review_queue', undefined, undefined, body, 'application/json');
|
|
3900
|
+
decoders.QueryReviewQueueResponse?.(response.body);
|
|
3901
|
+
return { ...response.body, metadata: response.metadata };
|
|
3853
3902
|
}
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
...activities,
|
|
3867
|
-
...(position === 'end' ? newActivitiesDeduplicated : []),
|
|
3868
|
-
];
|
|
3869
|
-
result = { changed: true, activities: updatedActivities };
|
|
3870
|
-
}
|
|
3871
|
-
return result;
|
|
3872
|
-
};
|
|
3873
|
-
const updateActivityInState = (updatedActivityResponse, activities) => {
|
|
3874
|
-
const index = activities.findIndex((a) => a.id === updatedActivityResponse.id);
|
|
3875
|
-
if (index !== -1) {
|
|
3876
|
-
const newActivities = [...activities];
|
|
3877
|
-
const activity = activities[index];
|
|
3878
|
-
newActivities[index] = {
|
|
3879
|
-
...updatedActivityResponse,
|
|
3880
|
-
own_reactions: activity.own_reactions,
|
|
3881
|
-
own_bookmarks: activity.own_bookmarks,
|
|
3882
|
-
latest_reactions: activity.latest_reactions,
|
|
3883
|
-
reaction_groups: activity.reaction_groups,
|
|
3903
|
+
async submitAction(request) {
|
|
3904
|
+
const body = {
|
|
3905
|
+
action_type: request?.action_type,
|
|
3906
|
+
item_id: request?.item_id,
|
|
3907
|
+
ban: request?.ban,
|
|
3908
|
+
custom: request?.custom,
|
|
3909
|
+
delete_activity: request?.delete_activity,
|
|
3910
|
+
delete_message: request?.delete_message,
|
|
3911
|
+
delete_reaction: request?.delete_reaction,
|
|
3912
|
+
delete_user: request?.delete_user,
|
|
3913
|
+
mark_reviewed: request?.mark_reviewed,
|
|
3914
|
+
unban: request?.unban,
|
|
3884
3915
|
};
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
return { changed: false, activities };
|
|
3889
|
-
}
|
|
3890
|
-
};
|
|
3891
|
-
const removeActivityFromState = (activityResponse, activities) => {
|
|
3892
|
-
const index = activities.findIndex((a) => a.id === activityResponse.id);
|
|
3893
|
-
if (index !== -1) {
|
|
3894
|
-
const newActivities = [...activities];
|
|
3895
|
-
newActivities.splice(index, 1);
|
|
3896
|
-
return { changed: true, activities: newActivities };
|
|
3897
|
-
}
|
|
3898
|
-
else {
|
|
3899
|
-
return { changed: false, activities };
|
|
3916
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/submit_action', undefined, undefined, body, 'application/json');
|
|
3917
|
+
decoders.SubmitActionResponse?.(response.body);
|
|
3918
|
+
return { ...response.body, metadata: response.metadata };
|
|
3900
3919
|
}
|
|
3901
|
-
}
|
|
3920
|
+
}
|
|
3902
3921
|
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
if (index !== -1) {
|
|
3906
|
-
const newActivities = [...activities];
|
|
3907
|
-
newActivities[index] = updatedActivity;
|
|
3908
|
-
return { changed: true, activities: newActivities };
|
|
3909
|
-
}
|
|
3910
|
-
else {
|
|
3911
|
-
return { changed: false, activities };
|
|
3912
|
-
}
|
|
3913
|
-
};
|
|
3914
|
-
const addReactionToActivity = (event, activity, isCurrentUser) => {
|
|
3915
|
-
// Update own_reactions if the reaction is from the current user
|
|
3916
|
-
const ownReactions = [...(activity.own_reactions || [])];
|
|
3917
|
-
if (isCurrentUser) {
|
|
3918
|
-
ownReactions.push(event.reaction);
|
|
3919
|
-
}
|
|
3920
|
-
return {
|
|
3921
|
-
...activity,
|
|
3922
|
-
own_reactions: ownReactions,
|
|
3923
|
-
latest_reactions: event.activity.latest_reactions,
|
|
3924
|
-
reaction_groups: event.activity.reaction_groups,
|
|
3925
|
-
changed: true,
|
|
3926
|
-
};
|
|
3927
|
-
};
|
|
3928
|
-
const removeReactionFromActivity = (event, activity, isCurrentUser) => {
|
|
3929
|
-
// Update own_reactions if the reaction is from the current user
|
|
3930
|
-
const ownReactions = isCurrentUser
|
|
3931
|
-
? (activity.own_reactions || []).filter((r) => !(r.type === event.reaction.type &&
|
|
3932
|
-
r.user.id === event.reaction.user.id))
|
|
3933
|
-
: activity.own_reactions;
|
|
3934
|
-
return {
|
|
3935
|
-
...activity,
|
|
3936
|
-
own_reactions: ownReactions,
|
|
3937
|
-
latest_reactions: event.activity.latest_reactions,
|
|
3938
|
-
reaction_groups: event.activity.reaction_groups,
|
|
3939
|
-
changed: true,
|
|
3940
|
-
};
|
|
3941
|
-
};
|
|
3942
|
-
const addReactionToActivities = (event, activities, isCurrentUser) => {
|
|
3943
|
-
if (!activities) {
|
|
3944
|
-
return { changed: false, activities: [] };
|
|
3945
|
-
}
|
|
3946
|
-
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
3947
|
-
if (activityIndex === -1) {
|
|
3948
|
-
return { changed: false, activities };
|
|
3949
|
-
}
|
|
3950
|
-
const activity = activities[activityIndex];
|
|
3951
|
-
const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
|
|
3952
|
-
return updateActivityInActivities$1(updatedActivity, activities);
|
|
3953
|
-
};
|
|
3954
|
-
const removeReactionFromActivities = (event, activities, isCurrentUser) => {
|
|
3955
|
-
if (!activities) {
|
|
3956
|
-
return { changed: false, activities: [] };
|
|
3957
|
-
}
|
|
3958
|
-
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
3959
|
-
if (activityIndex === -1) {
|
|
3960
|
-
return { changed: false, activities };
|
|
3961
|
-
}
|
|
3962
|
-
const activity = activities[activityIndex];
|
|
3963
|
-
const updatedActivity = removeReactionFromActivity(event, activity, isCurrentUser);
|
|
3964
|
-
return updateActivityInActivities$1(updatedActivity, activities);
|
|
3965
|
-
};
|
|
3922
|
+
class ModerationClient extends ModerationApi {
|
|
3923
|
+
}
|
|
3966
3924
|
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
const
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
own_bookmarks: ownBookmarks,
|
|
3994
|
-
changed: true,
|
|
3995
|
-
};
|
|
3996
|
-
};
|
|
3997
|
-
const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
|
|
3998
|
-
// Update own_bookmarks if the bookmark is from the current user
|
|
3999
|
-
const ownBookmarks = isCurrentUser
|
|
4000
|
-
? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
|
|
4001
|
-
: activity.own_bookmarks;
|
|
4002
|
-
return {
|
|
4003
|
-
...activity,
|
|
4004
|
-
own_bookmarks: ownBookmarks,
|
|
4005
|
-
changed: true,
|
|
4006
|
-
};
|
|
4007
|
-
};
|
|
4008
|
-
const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
|
|
4009
|
-
// Update own_bookmarks if the bookmark is from the current user
|
|
4010
|
-
let ownBookmarks = activity.own_bookmarks || [];
|
|
4011
|
-
if (isCurrentUser) {
|
|
4012
|
-
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
|
|
4013
|
-
if (bookmarkIndex !== -1) {
|
|
4014
|
-
ownBookmarks = [...ownBookmarks];
|
|
4015
|
-
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
4016
|
-
}
|
|
4017
|
-
}
|
|
4018
|
-
return {
|
|
4019
|
-
...activity,
|
|
4020
|
-
own_bookmarks: ownBookmarks,
|
|
4021
|
-
changed: true,
|
|
4022
|
-
};
|
|
4023
|
-
};
|
|
4024
|
-
const addBookmarkToActivities = (event, activities, isCurrentUser) => {
|
|
4025
|
-
if (!activities) {
|
|
4026
|
-
return { changed: false, activities: [] };
|
|
4027
|
-
}
|
|
4028
|
-
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4029
|
-
if (activityIndex === -1) {
|
|
4030
|
-
return { changed: false, activities };
|
|
4031
|
-
}
|
|
4032
|
-
const activity = activities[activityIndex];
|
|
4033
|
-
const updatedActivity = addBookmarkToActivity(event, activity, isCurrentUser);
|
|
4034
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
4035
|
-
};
|
|
4036
|
-
const removeBookmarkFromActivities = (event, activities, isCurrentUser) => {
|
|
4037
|
-
if (!activities) {
|
|
4038
|
-
return { changed: false, activities: [] };
|
|
4039
|
-
}
|
|
4040
|
-
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4041
|
-
if (activityIndex === -1) {
|
|
4042
|
-
return { changed: false, activities };
|
|
4043
|
-
}
|
|
4044
|
-
const activity = activities[activityIndex];
|
|
4045
|
-
const updatedActivity = removeBookmarkFromActivity(event, activity, isCurrentUser);
|
|
4046
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
4047
|
-
};
|
|
4048
|
-
const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
4049
|
-
if (!activities) {
|
|
4050
|
-
return { changed: false, activities: [] };
|
|
4051
|
-
}
|
|
4052
|
-
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4053
|
-
if (activityIndex === -1) {
|
|
4054
|
-
return { changed: false, activities };
|
|
4055
|
-
}
|
|
4056
|
-
const activity = activities[activityIndex];
|
|
4057
|
-
const updatedActivity = updateBookmarkInActivity(event, activity, isCurrentUser);
|
|
4058
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
4059
|
-
};
|
|
4060
|
-
|
|
4061
|
-
const isFeedResponse = (follow) => {
|
|
4062
|
-
return 'created_by' in follow;
|
|
4063
|
-
};
|
|
4064
|
-
const handleFollowCreated = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4065
|
-
// filter non-accepted follows (the way getOrCreate does by default)
|
|
4066
|
-
if (follow.status !== 'accepted') {
|
|
4067
|
-
return { changed: false, data: currentState };
|
|
4068
|
-
}
|
|
4069
|
-
let newState = { ...currentState };
|
|
4070
|
-
// this feed followed someone
|
|
4071
|
-
if (follow.source_feed.fid === currentFeedId) {
|
|
4072
|
-
newState = {
|
|
4073
|
-
...newState,
|
|
4074
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4075
|
-
...follow.source_feed,
|
|
3925
|
+
const isPollUpdatedEvent = (e) => e.type === 'feeds.poll.updated';
|
|
3926
|
+
const isPollClosedEventEvent = (e) => e.type === 'feeds.poll.closed';
|
|
3927
|
+
const isPollVoteCastedEvent = (e) => e.type === 'feeds.poll.vote_casted';
|
|
3928
|
+
const isPollVoteChangedEvent = (e) => e.type === 'feeds.poll.vote_changed';
|
|
3929
|
+
const isPollVoteRemovedEvent = (e) => e.type === 'feeds.poll.vote_removed';
|
|
3930
|
+
const isVoteAnswer = (vote) => !!vote?.answer_text;
|
|
3931
|
+
class StreamPoll {
|
|
3932
|
+
constructor({ client, poll }) {
|
|
3933
|
+
this.getInitialStateFromPollResponse = (poll) => {
|
|
3934
|
+
const { own_votes, id, ...pollResponseForState } = poll;
|
|
3935
|
+
const { ownAnswer, ownVotes } = own_votes?.reduce((acc, voteOrAnswer) => {
|
|
3936
|
+
if (isVoteAnswer(voteOrAnswer)) {
|
|
3937
|
+
acc.ownAnswer = voteOrAnswer;
|
|
3938
|
+
}
|
|
3939
|
+
else {
|
|
3940
|
+
acc.ownVotes.push(voteOrAnswer);
|
|
3941
|
+
}
|
|
3942
|
+
return acc;
|
|
3943
|
+
}, { ownVotes: [] }) ?? { ownVotes: [] };
|
|
3944
|
+
return {
|
|
3945
|
+
...pollResponseForState,
|
|
3946
|
+
last_activity_at: new Date(),
|
|
3947
|
+
max_voted_option_ids: getMaxVotedOptionIds(pollResponseForState.vote_counts_by_option),
|
|
3948
|
+
own_answer: ownAnswer,
|
|
3949
|
+
own_votes_by_option_id: getOwnVotesByOptionId(ownVotes),
|
|
3950
|
+
};
|
|
4076
3951
|
};
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
newState.following = [follow, ...currentState.following];
|
|
4080
|
-
}
|
|
4081
|
-
}
|
|
4082
|
-
else if (
|
|
4083
|
-
// someone followed this feed
|
|
4084
|
-
follow.target_feed.fid === currentFeedId) {
|
|
4085
|
-
const source = follow.source_feed;
|
|
4086
|
-
newState = {
|
|
4087
|
-
...newState,
|
|
4088
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4089
|
-
...follow.target_feed,
|
|
3952
|
+
this.reinitializeState = (poll) => {
|
|
3953
|
+
this.state.partialNext(this.getInitialStateFromPollResponse(poll));
|
|
4090
3954
|
};
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
};
|
|
4103
|
-
const handleFollowDeleted = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4104
|
-
let newState = { ...currentState };
|
|
4105
|
-
// this feed unfollowed someone
|
|
4106
|
-
if (follow.source_feed.fid === currentFeedId) {
|
|
4107
|
-
newState = {
|
|
4108
|
-
...newState,
|
|
4109
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4110
|
-
...follow.source_feed,
|
|
3955
|
+
this.handlePollUpdated = (event) => {
|
|
3956
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
3957
|
+
return;
|
|
3958
|
+
if (!isPollUpdatedEvent(event))
|
|
3959
|
+
return;
|
|
3960
|
+
const { id, ...pollData } = event.poll;
|
|
3961
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3962
|
+
this.state.partialNext({
|
|
3963
|
+
...pollData,
|
|
3964
|
+
last_activity_at: new Date(event.created_at),
|
|
3965
|
+
});
|
|
4111
3966
|
};
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
newState = {
|
|
4122
|
-
...newState,
|
|
4123
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4124
|
-
...follow.target_feed,
|
|
3967
|
+
this.handlePollClosed = (event) => {
|
|
3968
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
3969
|
+
return;
|
|
3970
|
+
if (!isPollClosedEventEvent(event))
|
|
3971
|
+
return;
|
|
3972
|
+
this.state.partialNext({
|
|
3973
|
+
is_closed: true,
|
|
3974
|
+
last_activity_at: new Date(event.created_at),
|
|
3975
|
+
});
|
|
4125
3976
|
};
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
const isImageFile = (file) => {
|
|
4145
|
-
// photoshop files begin with 'image/'
|
|
4146
|
-
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
4147
|
-
};
|
|
4148
|
-
const isVideoFile = (file) => {
|
|
4149
|
-
return file.type.startsWith('video/');
|
|
4150
|
-
};
|
|
4151
|
-
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4152
|
-
typeof cursor === 'string';
|
|
4153
|
-
const isCommentResponse = (entity) => {
|
|
4154
|
-
return typeof entity?.object_id === 'string';
|
|
4155
|
-
};
|
|
4156
|
-
const Constants = {
|
|
4157
|
-
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4158
|
-
};
|
|
4159
|
-
const uniqueArrayMerge = (existingArray, arrayToMerge, getKey) => {
|
|
4160
|
-
const existing = new Set();
|
|
4161
|
-
existingArray.forEach((value) => {
|
|
4162
|
-
const key = getKey(value);
|
|
4163
|
-
existing.add(key);
|
|
4164
|
-
});
|
|
4165
|
-
const filteredArrayToMerge = arrayToMerge.filter((value) => {
|
|
4166
|
-
const key = getKey(value);
|
|
4167
|
-
return !existing.has(key);
|
|
4168
|
-
});
|
|
4169
|
-
return existingArray.concat(filteredArrayToMerge);
|
|
4170
|
-
};
|
|
4171
|
-
|
|
4172
|
-
const shouldUpdateState = ({ stateUpdateId, stateUpdateQueue, watch, }) => {
|
|
4173
|
-
if (!watch) {
|
|
4174
|
-
return true;
|
|
4175
|
-
}
|
|
4176
|
-
if (watch && stateUpdateQueue.has(stateUpdateId)) {
|
|
4177
|
-
stateUpdateQueue.delete(stateUpdateId);
|
|
4178
|
-
return false;
|
|
4179
|
-
}
|
|
4180
|
-
stateUpdateQueue.add(stateUpdateId);
|
|
4181
|
-
return true;
|
|
4182
|
-
};
|
|
4183
|
-
const getStateUpdateQueueIdForFollow = (follow) => {
|
|
4184
|
-
return `follow${follow.source_feed.fid}-${follow.target_feed.fid}`;
|
|
4185
|
-
};
|
|
4186
|
-
const getStateUpdateQueueIdForUnfollow = (follow) => {
|
|
4187
|
-
return `unfollow${follow.source_feed.fid}-${follow.target_feed.fid}`;
|
|
4188
|
-
};
|
|
4189
|
-
|
|
4190
|
-
class Feed extends FeedApi {
|
|
4191
|
-
constructor(client, groupId, id, data, watch = false) {
|
|
4192
|
-
super(client, groupId, id);
|
|
4193
|
-
this.stateUpdateQueue = new Set();
|
|
4194
|
-
this.eventHandlers = {
|
|
4195
|
-
'feeds.activity.added': (event) => {
|
|
4196
|
-
const currentActivities = this.currentState.activities;
|
|
4197
|
-
const result = addActivitiesToState([event.activity], currentActivities, 'start');
|
|
4198
|
-
if (result.changed) {
|
|
4199
|
-
this.client.hydratePollCache([event.activity]);
|
|
4200
|
-
this.state.partialNext({ activities: result.activities });
|
|
4201
|
-
}
|
|
4202
|
-
},
|
|
4203
|
-
'feeds.activity.deleted': (event) => {
|
|
4204
|
-
const currentActivities = this.currentState.activities;
|
|
4205
|
-
if (currentActivities) {
|
|
4206
|
-
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4207
|
-
if (result.changed) {
|
|
4208
|
-
this.state.partialNext({ activities: result.activities });
|
|
4209
|
-
}
|
|
4210
|
-
}
|
|
4211
|
-
},
|
|
4212
|
-
'feeds.activity.reaction.added': (event) => {
|
|
4213
|
-
const currentActivities = this.currentState.activities;
|
|
4214
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4215
|
-
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4216
|
-
const result = addReactionToActivities(event, currentActivities, isCurrentUser);
|
|
4217
|
-
if (result.changed) {
|
|
4218
|
-
this.state.partialNext({ activities: result.activities });
|
|
4219
|
-
}
|
|
4220
|
-
},
|
|
4221
|
-
'feeds.activity.reaction.deleted': (event) => {
|
|
4222
|
-
const currentActivities = this.currentState.activities;
|
|
4223
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4224
|
-
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4225
|
-
const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
|
|
4226
|
-
if (result.changed) {
|
|
4227
|
-
this.state.partialNext({ activities: result.activities });
|
|
3977
|
+
this.handleVoteCasted = (event) => {
|
|
3978
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
3979
|
+
return;
|
|
3980
|
+
if (!isPollVoteCastedEvent(event))
|
|
3981
|
+
return;
|
|
3982
|
+
const currentState = this.data;
|
|
3983
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
3984
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
3985
|
+
let latestAnswers = [...currentState.latest_answers];
|
|
3986
|
+
let ownAnswer = currentState.own_answer;
|
|
3987
|
+
const ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
3988
|
+
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
3989
|
+
if (isOwnVote) {
|
|
3990
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3991
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
3992
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3993
|
+
ownAnswer = event.poll_vote;
|
|
4228
3994
|
}
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
const currentActivities = this.currentState.activities;
|
|
4233
|
-
if (currentActivities) {
|
|
4234
|
-
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4235
|
-
if (result.changed) {
|
|
4236
|
-
this.state.partialNext({ activities: result.activities });
|
|
4237
|
-
}
|
|
3995
|
+
else if (event.poll_vote.option_id) {
|
|
3996
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3997
|
+
ownVotesByOptionId[event.poll_vote.option_id] = event.poll_vote;
|
|
4238
3998
|
}
|
|
4239
|
-
}
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
3999
|
+
}
|
|
4000
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4001
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
4002
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4003
|
+
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
4004
|
+
}
|
|
4005
|
+
else {
|
|
4006
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4007
|
+
}
|
|
4008
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4009
|
+
this.state.partialNext({
|
|
4010
|
+
answers_count,
|
|
4011
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4012
|
+
latest_votes_by_option,
|
|
4013
|
+
vote_count,
|
|
4014
|
+
vote_counts_by_option,
|
|
4015
|
+
latest_answers: latestAnswers,
|
|
4016
|
+
last_activity_at: new Date(event.created_at),
|
|
4017
|
+
own_answer: ownAnswer,
|
|
4018
|
+
own_votes_by_option_id: ownVotesByOptionId,
|
|
4019
|
+
max_voted_option_ids: maxVotedOptionIds,
|
|
4020
|
+
});
|
|
4021
|
+
};
|
|
4022
|
+
this.handleVoteChanged = (event) => {
|
|
4023
|
+
// this event is triggered only when event.poll.enforce_unique_vote === true
|
|
4024
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
4025
|
+
return;
|
|
4026
|
+
if (!isPollVoteChangedEvent(event))
|
|
4027
|
+
return;
|
|
4028
|
+
const currentState = this.data;
|
|
4029
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
4030
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4031
|
+
let latestAnswers = [...currentState.latest_answers];
|
|
4032
|
+
let ownAnswer = currentState.own_answer;
|
|
4033
|
+
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
4034
|
+
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
4035
|
+
if (isOwnVote) {
|
|
4036
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4037
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
4038
|
+
latestAnswers = [
|
|
4039
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4040
|
+
event.poll_vote,
|
|
4041
|
+
...latestAnswers.filter((answer) => answer.id !== event.poll_vote.id),
|
|
4042
|
+
];
|
|
4043
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4044
|
+
ownAnswer = event.poll_vote;
|
|
4248
4045
|
}
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
'feeds.bookmark_folder.deleted': Feed.noop,
|
|
4254
|
-
'feeds.bookmark_folder.updated': Feed.noop,
|
|
4255
|
-
'feeds.comment.added': (event) => {
|
|
4256
|
-
const { comment } = event;
|
|
4257
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4258
|
-
this.state.next((currentState) => {
|
|
4259
|
-
const entityState = currentState.comments_by_entity_id[forId];
|
|
4260
|
-
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4261
|
-
if (entityState?.pagination?.sort === 'last' &&
|
|
4262
|
-
!checkHasAnotherPage(entityState.comments, entityState?.pagination.next)) {
|
|
4263
|
-
newComments.unshift(comment);
|
|
4264
|
-
}
|
|
4265
|
-
else if (entityState?.pagination?.sort === 'first') {
|
|
4266
|
-
newComments.push(comment);
|
|
4046
|
+
else if (event.poll_vote.option_id) {
|
|
4047
|
+
if (event.poll.enforce_unique_vote) {
|
|
4048
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4049
|
+
ownVotesByOptionId = { [event.poll_vote.option_id]: event.poll_vote };
|
|
4267
4050
|
}
|
|
4268
4051
|
else {
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
},
|
|
4280
|
-
},
|
|
4281
|
-
};
|
|
4282
|
-
});
|
|
4283
|
-
},
|
|
4284
|
-
'feeds.comment.deleted': ({ comment }) => {
|
|
4285
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4286
|
-
this.state.next((currentState) => {
|
|
4287
|
-
const newCommentsByEntityId = {
|
|
4288
|
-
...currentState.comments_by_entity_id,
|
|
4289
|
-
[forId]: {
|
|
4290
|
-
...currentState.comments_by_entity_id[forId],
|
|
4291
|
-
},
|
|
4292
|
-
};
|
|
4293
|
-
const index = this.getCommentIndex(comment, currentState);
|
|
4294
|
-
if (newCommentsByEntityId?.[forId]?.comments?.length && index !== -1) {
|
|
4295
|
-
newCommentsByEntityId[forId].comments = [
|
|
4296
|
-
...newCommentsByEntityId[forId].comments,
|
|
4297
|
-
];
|
|
4298
|
-
newCommentsByEntityId[forId]?.comments?.splice(index, 1);
|
|
4299
|
-
}
|
|
4300
|
-
delete newCommentsByEntityId[comment.id];
|
|
4301
|
-
return {
|
|
4302
|
-
...currentState,
|
|
4303
|
-
comments_by_entity_id: newCommentsByEntityId,
|
|
4304
|
-
};
|
|
4305
|
-
});
|
|
4306
|
-
},
|
|
4307
|
-
'feeds.comment.updated': (event) => {
|
|
4308
|
-
const { comment } = event;
|
|
4309
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4310
|
-
this.state.next((currentState) => {
|
|
4311
|
-
const entityState = currentState.comments_by_entity_id[forId];
|
|
4312
|
-
if (!entityState?.comments?.length)
|
|
4313
|
-
return currentState;
|
|
4314
|
-
const index = this.getCommentIndex(comment, currentState);
|
|
4315
|
-
if (index === -1)
|
|
4316
|
-
return currentState;
|
|
4317
|
-
const newComments = [...entityState.comments];
|
|
4318
|
-
newComments[index] = comment;
|
|
4319
|
-
return {
|
|
4320
|
-
...currentState,
|
|
4321
|
-
comments_by_entity_id: {
|
|
4322
|
-
...currentState.comments_by_entity_id,
|
|
4323
|
-
[forId]: {
|
|
4324
|
-
...currentState.comments_by_entity_id[forId],
|
|
4325
|
-
comments: newComments,
|
|
4326
|
-
},
|
|
4327
|
-
},
|
|
4328
|
-
};
|
|
4329
|
-
});
|
|
4330
|
-
},
|
|
4331
|
-
'feeds.feed.created': Feed.noop,
|
|
4332
|
-
'feeds.feed.deleted': Feed.noop,
|
|
4333
|
-
'feeds.feed.updated': (event) => {
|
|
4334
|
-
this.state.partialNext({ ...event.feed });
|
|
4335
|
-
},
|
|
4336
|
-
'feeds.feed_group.changed': Feed.noop,
|
|
4337
|
-
'feeds.feed_group.deleted': Feed.noop,
|
|
4338
|
-
'feeds.follow.created': (event) => {
|
|
4339
|
-
this.handleFollowCreated(event.follow);
|
|
4340
|
-
},
|
|
4341
|
-
'feeds.follow.deleted': (event) => {
|
|
4342
|
-
this.handleFollowDeleted(event.follow);
|
|
4343
|
-
},
|
|
4344
|
-
'feeds.follow.updated': (_event) => {
|
|
4345
|
-
handleFollowUpdated(this.currentState);
|
|
4346
|
-
},
|
|
4347
|
-
'feeds.comment.reaction.added': this.handleCommentReactionEvent.bind(this),
|
|
4348
|
-
'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
|
|
4349
|
-
'feeds.comment.reaction.updated': Feed.noop,
|
|
4350
|
-
'feeds.feed_member.added': (event) => {
|
|
4351
|
-
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4352
|
-
this.state.next((currentState) => {
|
|
4353
|
-
let newState;
|
|
4354
|
-
if (typeof currentState.members !== 'undefined') {
|
|
4355
|
-
newState ?? (newState = {
|
|
4356
|
-
...currentState,
|
|
4357
|
-
});
|
|
4358
|
-
newState.members = [event.member, ...currentState.members];
|
|
4359
|
-
}
|
|
4360
|
-
if (connectedUser?.id === event.member.user.id) {
|
|
4361
|
-
newState ?? (newState = {
|
|
4362
|
-
...currentState,
|
|
4363
|
-
});
|
|
4364
|
-
newState.own_membership = event.member;
|
|
4365
|
-
}
|
|
4366
|
-
return newState ?? currentState;
|
|
4367
|
-
});
|
|
4368
|
-
},
|
|
4369
|
-
'feeds.feed_member.removed': (event) => {
|
|
4370
|
-
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4371
|
-
this.state.next((currentState) => {
|
|
4372
|
-
const newState = {
|
|
4373
|
-
...currentState,
|
|
4374
|
-
members: currentState.members?.filter((member) => member.user.id !== event.user?.id),
|
|
4375
|
-
};
|
|
4376
|
-
if (connectedUser?.id === event.member_id) {
|
|
4377
|
-
delete newState.own_membership;
|
|
4378
|
-
}
|
|
4379
|
-
return newState;
|
|
4380
|
-
});
|
|
4381
|
-
},
|
|
4382
|
-
'feeds.feed_member.updated': (event) => {
|
|
4383
|
-
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4384
|
-
this.state.next((currentState) => {
|
|
4385
|
-
const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
|
|
4386
|
-
let newState;
|
|
4387
|
-
if (memberIndex !== -1) {
|
|
4388
|
-
// if there's an index, there's a member to update
|
|
4389
|
-
const newMembers = [...currentState.members];
|
|
4390
|
-
newMembers[memberIndex] = event.member;
|
|
4391
|
-
newState ?? (newState = {
|
|
4392
|
-
...currentState,
|
|
4393
|
-
});
|
|
4394
|
-
newState.members = newMembers;
|
|
4052
|
+
ownVotesByOptionId = Object.entries(ownVotesByOptionId).reduce((acc, [optionId, vote]) => {
|
|
4053
|
+
if (optionId !== event.poll_vote.option_id &&
|
|
4054
|
+
vote.id === event.poll_vote.id) {
|
|
4055
|
+
return acc;
|
|
4056
|
+
}
|
|
4057
|
+
acc[optionId] = vote;
|
|
4058
|
+
return acc;
|
|
4059
|
+
}, {});
|
|
4060
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4061
|
+
ownVotesByOptionId[event.poll_vote.option_id] = event.poll_vote;
|
|
4395
4062
|
}
|
|
4396
|
-
if (
|
|
4397
|
-
|
|
4398
|
-
...currentState,
|
|
4399
|
-
});
|
|
4400
|
-
newState.own_membership = event.member;
|
|
4063
|
+
if (ownAnswer?.id === event.poll_vote.id) {
|
|
4064
|
+
ownAnswer = undefined;
|
|
4401
4065
|
}
|
|
4402
|
-
|
|
4403
|
-
});
|
|
4404
|
-
},
|
|
4405
|
-
'feeds.notification_feed.updated': (event) => {
|
|
4406
|
-
console.info('notification feed updated', event);
|
|
4407
|
-
// TODO: handle notification feed updates
|
|
4408
|
-
},
|
|
4409
|
-
// the poll events should be removed from here
|
|
4410
|
-
'feeds.poll.closed': Feed.noop,
|
|
4411
|
-
'feeds.poll.deleted': Feed.noop,
|
|
4412
|
-
'feeds.poll.updated': Feed.noop,
|
|
4413
|
-
'feeds.poll.vote_casted': Feed.noop,
|
|
4414
|
-
'feeds.poll.vote_changed': Feed.noop,
|
|
4415
|
-
'feeds.poll.vote_removed': Feed.noop,
|
|
4416
|
-
'feeds.activity.pinned': Feed.noop,
|
|
4417
|
-
'feeds.activity.unpinned': Feed.noop,
|
|
4418
|
-
'feeds.activity.marked': Feed.noop,
|
|
4419
|
-
'moderation.custom_action': Feed.noop,
|
|
4420
|
-
'moderation.flagged': Feed.noop,
|
|
4421
|
-
'moderation.mark_reviewed': Feed.noop,
|
|
4422
|
-
'health.check': Feed.noop,
|
|
4423
|
-
'app.updated': Feed.noop,
|
|
4424
|
-
'user.banned': Feed.noop,
|
|
4425
|
-
'user.deactivated': Feed.noop,
|
|
4426
|
-
'user.muted': Feed.noop,
|
|
4427
|
-
'user.reactivated': Feed.noop,
|
|
4428
|
-
'user.updated': Feed.noop,
|
|
4429
|
-
};
|
|
4430
|
-
this.eventDispatcher = new EventDispatcher();
|
|
4431
|
-
this.on = this.eventDispatcher.on;
|
|
4432
|
-
this.off = this.eventDispatcher.off;
|
|
4433
|
-
this.state = new StateStore({
|
|
4434
|
-
fid: `${groupId}:${id}`,
|
|
4435
|
-
group_id: groupId,
|
|
4436
|
-
id,
|
|
4437
|
-
...(data ?? {}),
|
|
4438
|
-
is_loading: false,
|
|
4439
|
-
is_loading_activities: false,
|
|
4440
|
-
comments_by_entity_id: {},
|
|
4441
|
-
watch,
|
|
4442
|
-
});
|
|
4443
|
-
this.client = client;
|
|
4444
|
-
}
|
|
4445
|
-
get fid() {
|
|
4446
|
-
return `${this.group}:${this.id}`;
|
|
4447
|
-
}
|
|
4448
|
-
get currentState() {
|
|
4449
|
-
return this.state.getLatestValue();
|
|
4450
|
-
}
|
|
4451
|
-
handleCommentReactionEvent(event) {
|
|
4452
|
-
const { comment, reaction } = event;
|
|
4453
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4454
|
-
this.state.next((currentState) => {
|
|
4455
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4456
|
-
const entityState = currentState.comments_by_entity_id[forId];
|
|
4457
|
-
const commentIndex = this.getCommentIndex(comment, currentState);
|
|
4458
|
-
if (commentIndex === -1)
|
|
4459
|
-
return currentState;
|
|
4460
|
-
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4461
|
-
const commentCopy = { ...comment };
|
|
4462
|
-
delete commentCopy.own_reactions;
|
|
4463
|
-
const newComment = {
|
|
4464
|
-
...newComments[commentIndex],
|
|
4465
|
-
...commentCopy,
|
|
4466
|
-
// TODO: FIXME this should be handled by the backend
|
|
4467
|
-
latest_reactions: commentCopy.latest_reactions ?? [],
|
|
4468
|
-
reaction_groups: commentCopy.reaction_groups ?? {},
|
|
4469
|
-
};
|
|
4470
|
-
newComments[commentIndex] = newComment;
|
|
4471
|
-
if (reaction.user.id === connectedUser?.id) {
|
|
4472
|
-
if (event.type === 'feeds.comment.reaction.added') {
|
|
4473
|
-
newComment.own_reactions = newComment.own_reactions.concat(reaction) ?? [reaction];
|
|
4474
|
-
}
|
|
4475
|
-
else if (event.type === 'feeds.comment.reaction.deleted') {
|
|
4476
|
-
newComment.own_reactions = newComment.own_reactions.filter((r) => r.type !== reaction.type);
|
|
4066
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4477
4067
|
}
|
|
4068
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4478
4069
|
}
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
});
|
|
4070
|
+
else if (isVoteAnswer(event.poll_vote)) {
|
|
4071
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4072
|
+
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
4073
|
+
}
|
|
4074
|
+
else {
|
|
4075
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4076
|
+
}
|
|
4077
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4078
|
+
this.state.partialNext({
|
|
4079
|
+
answers_count,
|
|
4080
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4081
|
+
latest_votes_by_option,
|
|
4082
|
+
vote_count,
|
|
4083
|
+
vote_counts_by_option,
|
|
4084
|
+
latest_answers: latestAnswers,
|
|
4085
|
+
last_activity_at: new Date(event.created_at),
|
|
4086
|
+
own_answer: ownAnswer,
|
|
4087
|
+
own_votes_by_option_id: ownVotesByOptionId,
|
|
4088
|
+
max_voted_option_ids: maxVotedOptionIds,
|
|
4089
|
+
});
|
|
4090
|
+
};
|
|
4091
|
+
this.handleVoteRemoved = (event) => {
|
|
4092
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
4093
|
+
return;
|
|
4094
|
+
if (!isPollVoteRemovedEvent(event))
|
|
4095
|
+
return;
|
|
4096
|
+
const currentState = this.data;
|
|
4097
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
4098
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4099
|
+
let latestAnswers = [...currentState.latest_answers];
|
|
4100
|
+
let ownAnswer = currentState.own_answer;
|
|
4101
|
+
const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
|
|
4102
|
+
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
4103
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4104
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
4105
|
+
latestAnswers = latestAnswers.filter((answer) => answer.id !== event.poll_vote.id);
|
|
4106
|
+
if (isOwnVote) {
|
|
4107
|
+
ownAnswer = undefined;
|
|
4518
4108
|
}
|
|
4519
4109
|
}
|
|
4520
4110
|
else {
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
...response.feed,
|
|
4526
|
-
};
|
|
4527
|
-
delete responseCopy.feed;
|
|
4528
|
-
delete responseCopy.metadata;
|
|
4529
|
-
delete responseCopy.duration;
|
|
4530
|
-
this.state.next((currentState) => {
|
|
4531
|
-
const nextState = {
|
|
4532
|
-
...currentState,
|
|
4533
|
-
...responseCopy,
|
|
4534
|
-
};
|
|
4535
|
-
if (!request?.followers_pagination?.limit) {
|
|
4536
|
-
delete nextState.followers;
|
|
4537
|
-
}
|
|
4538
|
-
if (!request?.following_pagination?.limit) {
|
|
4539
|
-
delete nextState.following;
|
|
4540
|
-
}
|
|
4541
|
-
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
4542
|
-
delete nextState.members;
|
|
4543
|
-
}
|
|
4544
|
-
nextState.last_get_or_create_request_config = request;
|
|
4545
|
-
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
4546
|
-
return nextState;
|
|
4547
|
-
});
|
|
4111
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4112
|
+
if (isOwnVote && event.poll_vote.option_id) {
|
|
4113
|
+
delete ownVotesByOptionId[event.poll_vote.option_id];
|
|
4114
|
+
}
|
|
4548
4115
|
}
|
|
4549
|
-
|
|
4550
|
-
return response;
|
|
4551
|
-
}
|
|
4552
|
-
finally {
|
|
4116
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4553
4117
|
this.state.partialNext({
|
|
4554
|
-
|
|
4555
|
-
|
|
4118
|
+
answers_count,
|
|
4119
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4120
|
+
latest_votes_by_option,
|
|
4121
|
+
vote_count,
|
|
4122
|
+
vote_counts_by_option,
|
|
4123
|
+
latest_answers: latestAnswers,
|
|
4124
|
+
last_activity_at: new Date(event.created_at),
|
|
4125
|
+
own_answer: ownAnswer,
|
|
4126
|
+
own_votes_by_option_id: ownVotesByOptionId,
|
|
4127
|
+
max_voted_option_ids: maxVotedOptionIds,
|
|
4556
4128
|
});
|
|
4557
|
-
}
|
|
4129
|
+
};
|
|
4130
|
+
this.client = client;
|
|
4131
|
+
this.id = poll.id;
|
|
4132
|
+
this.state = new StateStore(this.getInitialStateFromPollResponse(poll));
|
|
4558
4133
|
}
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
*/
|
|
4562
|
-
handleFollowCreated(follow) {
|
|
4563
|
-
if (!shouldUpdateState({
|
|
4564
|
-
stateUpdateId: getStateUpdateQueueIdForFollow(follow),
|
|
4565
|
-
stateUpdateQueue: this.stateUpdateQueue,
|
|
4566
|
-
watch: this.currentState.watch,
|
|
4567
|
-
})) {
|
|
4568
|
-
return;
|
|
4569
|
-
}
|
|
4570
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4571
|
-
const result = handleFollowCreated(follow, this.currentState, this.fid, connectedUser?.id);
|
|
4572
|
-
if (result.changed) {
|
|
4573
|
-
this.state.next(result.data);
|
|
4574
|
-
}
|
|
4134
|
+
get data() {
|
|
4135
|
+
return this.state.getLatestValue();
|
|
4575
4136
|
}
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
})) {
|
|
4585
|
-
return;
|
|
4137
|
+
}
|
|
4138
|
+
function getMaxVotedOptionIds(voteCountsByOption) {
|
|
4139
|
+
let maxVotes = 0;
|
|
4140
|
+
let winningOptions = [];
|
|
4141
|
+
for (const [id, count] of Object.entries(voteCountsByOption ?? {})) {
|
|
4142
|
+
if (count > maxVotes) {
|
|
4143
|
+
winningOptions = [id];
|
|
4144
|
+
maxVotes = count;
|
|
4586
4145
|
}
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
{
|
|
4590
|
-
this.state.next(result.data);
|
|
4146
|
+
else if (count === maxVotes) {
|
|
4147
|
+
winningOptions.push(id);
|
|
4591
4148
|
}
|
|
4592
4149
|
}
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4150
|
+
return winningOptions;
|
|
4151
|
+
}
|
|
4152
|
+
function getOwnVotesByOptionId(ownVotes) {
|
|
4153
|
+
return !ownVotes
|
|
4154
|
+
? {}
|
|
4155
|
+
: ownVotes.reduce((acc, vote) => {
|
|
4156
|
+
if (isVoteAnswer(vote) || !vote.option_id)
|
|
4157
|
+
return acc;
|
|
4158
|
+
acc[vote.option_id] = vote;
|
|
4159
|
+
return acc;
|
|
4160
|
+
}, {});
|
|
4161
|
+
}
|
|
4162
|
+
|
|
4163
|
+
class FeedApi {
|
|
4164
|
+
constructor(feedsApi, group, id) {
|
|
4165
|
+
this.feedsApi = feedsApi;
|
|
4166
|
+
this.group = group;
|
|
4167
|
+
this.id = id;
|
|
4168
|
+
}
|
|
4169
|
+
delete(request) {
|
|
4170
|
+
return this.feedsApi.deleteFeed({
|
|
4171
|
+
feed_id: this.id,
|
|
4172
|
+
feed_group_id: this.group,
|
|
4173
|
+
...request,
|
|
4599
4174
|
});
|
|
4600
4175
|
}
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
watch: true,
|
|
4176
|
+
getOrCreate(request) {
|
|
4177
|
+
return this.feedsApi.getOrCreateFeed({
|
|
4178
|
+
feed_id: this.id,
|
|
4179
|
+
feed_group_id: this.group,
|
|
4180
|
+
...request,
|
|
4607
4181
|
});
|
|
4608
4182
|
}
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
this.state.partialNext({ activities: result.activities });
|
|
4616
|
-
}
|
|
4183
|
+
update(request) {
|
|
4184
|
+
return this.feedsApi.updateFeed({
|
|
4185
|
+
feed_id: this.id,
|
|
4186
|
+
feed_group_id: this.group,
|
|
4187
|
+
...request,
|
|
4188
|
+
});
|
|
4617
4189
|
}
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
this.state.partialNext({ activities: result.activities });
|
|
4625
|
-
}
|
|
4190
|
+
markActivity(request) {
|
|
4191
|
+
return this.feedsApi.markActivity({
|
|
4192
|
+
feed_id: this.id,
|
|
4193
|
+
feed_group_id: this.group,
|
|
4194
|
+
...request,
|
|
4195
|
+
});
|
|
4626
4196
|
}
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
this.state.partialNext({ activities: result.activities });
|
|
4634
|
-
}
|
|
4197
|
+
unpinActivity(request) {
|
|
4198
|
+
return this.feedsApi.unpinActivity({
|
|
4199
|
+
feed_id: this.id,
|
|
4200
|
+
feed_group_id: this.group,
|
|
4201
|
+
...request,
|
|
4202
|
+
});
|
|
4635
4203
|
}
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
if (!currentComments?.length) {
|
|
4643
|
-
return -1;
|
|
4644
|
-
}
|
|
4645
|
-
// @ts-expect-error this will just fail if the comment is not object from state
|
|
4646
|
-
let commentIndex = currentComments.indexOf(comment);
|
|
4647
|
-
// fast lookup failed, try slower approach
|
|
4648
|
-
if (commentIndex === -1) {
|
|
4649
|
-
commentIndex = currentComments.findIndex((comment_) => comment_.id === comment.id);
|
|
4650
|
-
}
|
|
4651
|
-
return commentIndex;
|
|
4204
|
+
pinActivity(request) {
|
|
4205
|
+
return this.feedsApi.pinActivity({
|
|
4206
|
+
feed_id: this.id,
|
|
4207
|
+
feed_group_id: this.group,
|
|
4208
|
+
...request,
|
|
4209
|
+
});
|
|
4652
4210
|
}
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
// add initial (top level) object for processing
|
|
4659
|
-
const traverseArray = [
|
|
4660
|
-
{
|
|
4661
|
-
entityId: data.entityId,
|
|
4662
|
-
entityParentId: data.entityParentId,
|
|
4663
|
-
comments: data.comments,
|
|
4664
|
-
next: data.next,
|
|
4665
|
-
},
|
|
4666
|
-
];
|
|
4667
|
-
this.state.next((currentState) => {
|
|
4668
|
-
const newCommentsByEntityId = {
|
|
4669
|
-
...currentState.comments_by_entity_id,
|
|
4670
|
-
};
|
|
4671
|
-
while (traverseArray.length) {
|
|
4672
|
-
const item = traverseArray.pop();
|
|
4673
|
-
const entityId = item.entityId;
|
|
4674
|
-
// go over entity comments and generate new objects
|
|
4675
|
-
// for further processing if there are any replies
|
|
4676
|
-
item.comments.forEach((comment) => {
|
|
4677
|
-
if (!comment.replies?.length)
|
|
4678
|
-
return;
|
|
4679
|
-
traverseArray.push({
|
|
4680
|
-
entityId: comment.id,
|
|
4681
|
-
entityParentId: entityId,
|
|
4682
|
-
comments: comment.replies,
|
|
4683
|
-
next: comment.meta?.next_cursor,
|
|
4684
|
-
});
|
|
4685
|
-
});
|
|
4686
|
-
// omit replies & meta from the comments (transform ThreadedCommentResponse to CommentResponse)
|
|
4687
|
-
// this is somehow faster than copying the whole
|
|
4688
|
-
// object and deleting the desired properties
|
|
4689
|
-
const newComments = item.comments.map(({ replies: _r, meta: _m, ...restOfTheCommentResponse }) => restOfTheCommentResponse);
|
|
4690
|
-
newCommentsByEntityId[entityId] = {
|
|
4691
|
-
...newCommentsByEntityId[entityId],
|
|
4692
|
-
entity_parent_id: item.entityParentId,
|
|
4693
|
-
pagination: {
|
|
4694
|
-
...newCommentsByEntityId[entityId]?.pagination,
|
|
4695
|
-
next: item.next,
|
|
4696
|
-
sort: data.sort,
|
|
4697
|
-
},
|
|
4698
|
-
comments: newCommentsByEntityId[entityId]?.comments
|
|
4699
|
-
? newCommentsByEntityId[entityId].comments?.concat(newComments)
|
|
4700
|
-
: newComments,
|
|
4701
|
-
};
|
|
4702
|
-
}
|
|
4703
|
-
return {
|
|
4704
|
-
...currentState,
|
|
4705
|
-
comments_by_entity_id: newCommentsByEntityId,
|
|
4706
|
-
};
|
|
4211
|
+
updateFeedMembers(request) {
|
|
4212
|
+
return this.feedsApi.updateFeedMembers({
|
|
4213
|
+
feed_id: this.id,
|
|
4214
|
+
feed_group_id: this.group,
|
|
4215
|
+
...request,
|
|
4707
4216
|
});
|
|
4708
4217
|
}
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
this.
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
...currentState.comments_by_entity_id,
|
|
4716
|
-
[entityId]: {
|
|
4717
|
-
...currentState.comments_by_entity_id[entityId],
|
|
4718
|
-
pagination: {
|
|
4719
|
-
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4720
|
-
loading_next_page: true,
|
|
4721
|
-
},
|
|
4722
|
-
},
|
|
4723
|
-
},
|
|
4724
|
-
}));
|
|
4725
|
-
const { next, comments } = await base();
|
|
4726
|
-
this.loadCommentsIntoState({
|
|
4727
|
-
entityId,
|
|
4728
|
-
comments,
|
|
4729
|
-
entityParentId,
|
|
4730
|
-
next,
|
|
4731
|
-
sort,
|
|
4732
|
-
});
|
|
4733
|
-
}
|
|
4734
|
-
catch (e) {
|
|
4735
|
-
error = e;
|
|
4736
|
-
}
|
|
4737
|
-
finally {
|
|
4738
|
-
this.state.next((currentState) => ({
|
|
4739
|
-
...currentState,
|
|
4740
|
-
comments_by_entity_id: {
|
|
4741
|
-
...currentState.comments_by_entity_id,
|
|
4742
|
-
[entityId]: {
|
|
4743
|
-
...currentState.comments_by_entity_id[entityId],
|
|
4744
|
-
pagination: {
|
|
4745
|
-
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4746
|
-
loading_next_page: false,
|
|
4747
|
-
},
|
|
4748
|
-
},
|
|
4749
|
-
},
|
|
4750
|
-
}));
|
|
4751
|
-
}
|
|
4752
|
-
if (error) {
|
|
4753
|
-
throw error;
|
|
4754
|
-
}
|
|
4218
|
+
acceptFeedMemberInvite(request) {
|
|
4219
|
+
return this.feedsApi.acceptFeedMemberInvite({
|
|
4220
|
+
feed_id: this.id,
|
|
4221
|
+
feed_group_id: this.group,
|
|
4222
|
+
...request,
|
|
4223
|
+
});
|
|
4755
4224
|
}
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
const isLoading = currentPagination?.loading_next_page;
|
|
4762
|
-
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4763
|
-
if (isLoading ||
|
|
4764
|
-
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4765
|
-
return;
|
|
4766
|
-
}
|
|
4767
|
-
await this.loadNextPageComments({
|
|
4768
|
-
entityId: activity.id,
|
|
4769
|
-
base: () => this.client.getComments({
|
|
4770
|
-
...request,
|
|
4771
|
-
sort,
|
|
4772
|
-
object_id: activity.id,
|
|
4773
|
-
object_type: 'activity',
|
|
4774
|
-
next: currentNextCursor,
|
|
4775
|
-
}),
|
|
4776
|
-
sort,
|
|
4225
|
+
queryFeedMembers(request) {
|
|
4226
|
+
return this.feedsApi.queryFeedMembers({
|
|
4227
|
+
feed_id: this.id,
|
|
4228
|
+
feed_group_id: this.group,
|
|
4229
|
+
...request,
|
|
4777
4230
|
});
|
|
4778
4231
|
}
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
const isLoading = currentPagination?.loading_next_page;
|
|
4785
|
-
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4786
|
-
if (isLoading ||
|
|
4787
|
-
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4788
|
-
return;
|
|
4789
|
-
}
|
|
4790
|
-
await this.loadNextPageComments({
|
|
4791
|
-
entityId: comment.id,
|
|
4792
|
-
base: () => this.client.getCommentReplies({
|
|
4793
|
-
...request,
|
|
4794
|
-
comment_id: comment.id,
|
|
4795
|
-
// use known sort first (prevents broken pagination)
|
|
4796
|
-
sort: currentSort ??
|
|
4797
|
-
request?.sort ??
|
|
4798
|
-
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
4799
|
-
next: currentNextCursor,
|
|
4800
|
-
}),
|
|
4801
|
-
entityParentId: comment.parent_id ?? comment.object_id,
|
|
4802
|
-
sort,
|
|
4232
|
+
rejectFeedMemberInvite(request) {
|
|
4233
|
+
return this.feedsApi.rejectFeedMemberInvite({
|
|
4234
|
+
feed_id: this.id,
|
|
4235
|
+
feed_group_id: this.group,
|
|
4236
|
+
...request,
|
|
4803
4237
|
});
|
|
4804
4238
|
}
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4239
|
+
stopWatching(request) {
|
|
4240
|
+
return this.feedsApi.stopWatchingFeed({
|
|
4241
|
+
feed_id: this.id,
|
|
4242
|
+
feed_group_id: this.group,
|
|
4243
|
+
...request,
|
|
4244
|
+
});
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4248
|
+
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4249
|
+
typeof cursor === 'string';
|
|
4250
|
+
|
|
4251
|
+
const uniqueArrayMerge = (existingArray, arrayToMerge, getKey) => {
|
|
4252
|
+
const existing = new Set();
|
|
4253
|
+
existingArray.forEach((value) => {
|
|
4254
|
+
const key = getKey(value);
|
|
4255
|
+
existing.add(key);
|
|
4256
|
+
});
|
|
4257
|
+
const filteredArrayToMerge = arrayToMerge.filter((value) => {
|
|
4258
|
+
const key = getKey(value);
|
|
4259
|
+
return !existing.has(key);
|
|
4260
|
+
});
|
|
4261
|
+
return existingArray.concat(filteredArrayToMerge);
|
|
4262
|
+
};
|
|
4263
|
+
|
|
4264
|
+
const Constants = {
|
|
4265
|
+
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4266
|
+
};
|
|
4267
|
+
|
|
4268
|
+
const isFollowResponse = (data) => {
|
|
4269
|
+
return 'source_feed' in data && 'target_feed' in data;
|
|
4270
|
+
};
|
|
4271
|
+
const isCommentResponse = (entity) => {
|
|
4272
|
+
return typeof entity?.object_id === 'string';
|
|
4273
|
+
};
|
|
4274
|
+
const isImageFile = (file) => {
|
|
4275
|
+
// photoshop files begin with 'image/'
|
|
4276
|
+
return file.type.startsWith('image/') && !file.type.endsWith('.photoshop');
|
|
4277
|
+
};
|
|
4278
|
+
const isVideoFile = (file) => {
|
|
4279
|
+
return file.type.startsWith('video/');
|
|
4280
|
+
};
|
|
4281
|
+
|
|
4282
|
+
const shouldUpdateState = ({ stateUpdateQueueId, stateUpdateQueue, watch, }) => {
|
|
4283
|
+
if (!watch) {
|
|
4284
|
+
return true;
|
|
4285
|
+
}
|
|
4286
|
+
if (watch && stateUpdateQueue.has(stateUpdateQueueId)) {
|
|
4287
|
+
stateUpdateQueue.delete(stateUpdateQueueId);
|
|
4288
|
+
return false;
|
|
4289
|
+
}
|
|
4290
|
+
stateUpdateQueue.add(stateUpdateQueueId);
|
|
4291
|
+
return true;
|
|
4292
|
+
};
|
|
4293
|
+
function getStateUpdateQueueId(data, prefix) {
|
|
4294
|
+
if (isFollowResponse(data)) {
|
|
4295
|
+
const toJoin = [data.source_feed.feed, data.target_feed.feed];
|
|
4296
|
+
if (prefix) {
|
|
4297
|
+
toJoin.unshift(prefix);
|
|
4844
4298
|
}
|
|
4845
|
-
|
|
4846
|
-
|
|
4299
|
+
return toJoin.join('-');
|
|
4300
|
+
}
|
|
4301
|
+
// else if (isMemberResponse(data)) {
|
|
4302
|
+
// }
|
|
4303
|
+
throw new Error(`Cannot create state update queueId for data: ${JSON.stringify(data)}`);
|
|
4304
|
+
}
|
|
4305
|
+
|
|
4306
|
+
const updateStateFollowCreated = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4307
|
+
// filter non-accepted follows (the way getOrCreate does by default)
|
|
4308
|
+
if (follow.status !== 'accepted') {
|
|
4309
|
+
return { changed: false, data: currentState };
|
|
4310
|
+
}
|
|
4311
|
+
let newState = { ...currentState };
|
|
4312
|
+
// this feed followed someone
|
|
4313
|
+
if (follow.source_feed.feed === currentFeedId) {
|
|
4314
|
+
newState = {
|
|
4315
|
+
...newState,
|
|
4316
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4317
|
+
...follow.source_feed,
|
|
4318
|
+
};
|
|
4319
|
+
// Only update if following array already exists
|
|
4320
|
+
if (currentState.following !== undefined) {
|
|
4321
|
+
newState.following = [follow, ...currentState.following];
|
|
4847
4322
|
}
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4323
|
+
}
|
|
4324
|
+
else if (
|
|
4325
|
+
// someone followed this feed
|
|
4326
|
+
follow.target_feed.feed === currentFeedId) {
|
|
4327
|
+
const source = follow.source_feed;
|
|
4328
|
+
newState = {
|
|
4329
|
+
...newState,
|
|
4330
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4331
|
+
...follow.target_feed,
|
|
4332
|
+
};
|
|
4333
|
+
if (source.created_by.id === connectedUserId) {
|
|
4334
|
+
newState.own_follows = currentState.own_follows
|
|
4335
|
+
? currentState.own_follows.concat(follow)
|
|
4336
|
+
: [follow];
|
|
4858
4337
|
}
|
|
4859
|
-
if
|
|
4860
|
-
|
|
4338
|
+
// Only update if followers array already exists
|
|
4339
|
+
if (currentState.followers !== undefined) {
|
|
4340
|
+
newState.followers = [follow, ...currentState.followers];
|
|
4861
4341
|
}
|
|
4862
4342
|
}
|
|
4863
|
-
|
|
4864
|
-
|
|
4343
|
+
return { changed: true, data: newState };
|
|
4344
|
+
};
|
|
4345
|
+
function handleFollowCreated(eventOrResponse) {
|
|
4346
|
+
const follow = eventOrResponse.follow;
|
|
4347
|
+
if (!shouldUpdateState({
|
|
4348
|
+
stateUpdateQueueId: getStateUpdateQueueId(follow, 'created'),
|
|
4349
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4350
|
+
watch: this.currentState.watch,
|
|
4351
|
+
})) {
|
|
4352
|
+
return;
|
|
4865
4353
|
}
|
|
4866
|
-
|
|
4867
|
-
|
|
4354
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4355
|
+
const result = updateStateFollowCreated(follow, this.currentState, this.feed, connectedUser?.id);
|
|
4356
|
+
if (result.changed) {
|
|
4357
|
+
this.state.next(result.data);
|
|
4868
4358
|
}
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4359
|
+
}
|
|
4360
|
+
|
|
4361
|
+
const updateStateFollowDeleted = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4362
|
+
let newState = { ...currentState };
|
|
4363
|
+
// this feed unfollowed someone
|
|
4364
|
+
if (follow.source_feed.feed === currentFeedId) {
|
|
4365
|
+
newState = {
|
|
4366
|
+
...newState,
|
|
4367
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4368
|
+
...follow.source_feed,
|
|
4369
|
+
};
|
|
4370
|
+
// Only update if following array already exists
|
|
4371
|
+
if (currentState.following !== undefined) {
|
|
4372
|
+
newState.following = currentState.following.filter((followItem) => followItem.target_feed.feed !== follow.target_feed.feed);
|
|
4877
4373
|
}
|
|
4878
|
-
|
|
4879
|
-
|
|
4374
|
+
}
|
|
4375
|
+
else if (
|
|
4376
|
+
// someone unfollowed this feed
|
|
4377
|
+
follow.target_feed.feed === currentFeedId) {
|
|
4378
|
+
const source = follow.source_feed;
|
|
4379
|
+
newState = {
|
|
4380
|
+
...newState,
|
|
4381
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4382
|
+
...follow.target_feed,
|
|
4383
|
+
};
|
|
4384
|
+
if (source.created_by.id === connectedUserId &&
|
|
4385
|
+
currentState.own_follows !== undefined) {
|
|
4386
|
+
newState.own_follows = currentState.own_follows.filter((followItem) => followItem.source_feed.feed !== follow.source_feed.feed);
|
|
4387
|
+
}
|
|
4388
|
+
// Only update if followers array already exists
|
|
4389
|
+
if (currentState.followers !== undefined) {
|
|
4390
|
+
newState.followers = currentState.followers.filter((followItem) => followItem.source_feed.feed !== follow.source_feed.feed);
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
return { changed: true, data: newState };
|
|
4394
|
+
};
|
|
4395
|
+
function handleFollowDeleted(eventOrResponse) {
|
|
4396
|
+
const follow = eventOrResponse.follow;
|
|
4397
|
+
if (!shouldUpdateState({
|
|
4398
|
+
stateUpdateQueueId: getStateUpdateQueueId(follow, 'deleted'),
|
|
4399
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4400
|
+
watch: this.currentState.watch,
|
|
4401
|
+
})) {
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4405
|
+
const result = updateStateFollowDeleted(follow, this.currentState, this.feed, connectedUser?.id);
|
|
4406
|
+
{
|
|
4407
|
+
this.state.next(result.data);
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4411
|
+
function handleFollowUpdated(eventOrResponse) {
|
|
4412
|
+
const follow = eventOrResponse.follow;
|
|
4413
|
+
const connectedUserId = this.client.state.getLatestValue().connected_user?.id;
|
|
4414
|
+
const currentFeedId = this.feed;
|
|
4415
|
+
if (!shouldUpdateState({
|
|
4416
|
+
stateUpdateQueueId: getStateUpdateQueueId(follow, 'updated'),
|
|
4417
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4418
|
+
watch: this.currentState.watch,
|
|
4419
|
+
})) {
|
|
4420
|
+
return;
|
|
4421
|
+
}
|
|
4422
|
+
this.state.next((currentState) => {
|
|
4423
|
+
let newState;
|
|
4424
|
+
// this feed followed someone
|
|
4425
|
+
if (follow.source_feed.feed === currentFeedId) {
|
|
4426
|
+
newState ?? (newState = {
|
|
4880
4427
|
...currentState,
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
loading_next_page: true,
|
|
4884
|
-
},
|
|
4885
|
-
}));
|
|
4886
|
-
const { next: newNextCursor, members } = await this.client.queryFeedMembers({
|
|
4887
|
-
...request,
|
|
4888
|
-
sort,
|
|
4889
|
-
feed_id: this.id,
|
|
4890
|
-
feed_group_id: this.group,
|
|
4891
|
-
next: currentNextCursor,
|
|
4428
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4429
|
+
...follow.source_feed,
|
|
4892
4430
|
});
|
|
4893
|
-
|
|
4431
|
+
const index = currentState.following?.findIndex((f) => f.target_feed.feed === follow.target_feed.feed) ?? -1;
|
|
4432
|
+
if (index >= 0) {
|
|
4433
|
+
newState.following = [...newState.following];
|
|
4434
|
+
newState.following[index] = follow;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
else if (
|
|
4438
|
+
// someone followed this feed
|
|
4439
|
+
follow.target_feed.feed === currentFeedId) {
|
|
4440
|
+
const source = follow.source_feed;
|
|
4441
|
+
newState ?? (newState = {
|
|
4894
4442
|
...currentState,
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4443
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4444
|
+
...follow.target_feed,
|
|
4445
|
+
});
|
|
4446
|
+
if (source.created_by.id === connectedUserId &&
|
|
4447
|
+
currentState.own_follows) {
|
|
4448
|
+
const index = currentState.own_follows.findIndex((f) => f.source_feed.feed === follow.source_feed.feed);
|
|
4449
|
+
if (index >= 0) {
|
|
4450
|
+
newState.own_follows = [...currentState.own_follows];
|
|
4451
|
+
newState.own_follows[index] = follow;
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
const index = currentState.followers?.findIndex((f) => f.source_feed.feed === follow.source_feed.feed) ?? -1;
|
|
4455
|
+
if (index >= 0) {
|
|
4456
|
+
newState.followers = [...newState.followers];
|
|
4457
|
+
newState.followers[index] = follow;
|
|
4458
|
+
}
|
|
4905
4459
|
}
|
|
4906
|
-
|
|
4907
|
-
|
|
4460
|
+
return newState ?? currentState;
|
|
4461
|
+
});
|
|
4462
|
+
}
|
|
4463
|
+
|
|
4464
|
+
function handleCommentAdded(event) {
|
|
4465
|
+
const { comment } = event;
|
|
4466
|
+
const entityId = comment.parent_id ?? comment.object_id;
|
|
4467
|
+
this.state.next((currentState) => {
|
|
4468
|
+
const entityState = currentState.comments_by_entity_id[entityId];
|
|
4469
|
+
if (typeof entityState?.comments === 'undefined') {
|
|
4470
|
+
return currentState;
|
|
4908
4471
|
}
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
member_pagination: {
|
|
4913
|
-
...currentState.member_pagination,
|
|
4914
|
-
loading_next_page: false,
|
|
4915
|
-
},
|
|
4916
|
-
}));
|
|
4472
|
+
const newComments = entityState?.comments ? [...entityState.comments] : [];
|
|
4473
|
+
if (entityState.pagination?.sort === 'last') {
|
|
4474
|
+
newComments.unshift(comment);
|
|
4917
4475
|
}
|
|
4918
|
-
|
|
4919
|
-
|
|
4476
|
+
else {
|
|
4477
|
+
// 'first' and other sort options
|
|
4478
|
+
newComments.push(comment);
|
|
4920
4479
|
}
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4480
|
+
return {
|
|
4481
|
+
...currentState,
|
|
4482
|
+
comments_by_entity_id: {
|
|
4483
|
+
...currentState.comments_by_entity_id,
|
|
4484
|
+
[entityId]: {
|
|
4485
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4486
|
+
comments: newComments,
|
|
4487
|
+
},
|
|
4488
|
+
},
|
|
4930
4489
|
};
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
async queryFollowing(request) {
|
|
4943
|
-
const filter = {
|
|
4944
|
-
source_feed: this.fid,
|
|
4490
|
+
});
|
|
4491
|
+
}
|
|
4492
|
+
|
|
4493
|
+
function handleCommentDeleted({ comment }) {
|
|
4494
|
+
const entityId = comment.parent_id ?? comment.object_id;
|
|
4495
|
+
this.state.next((currentState) => {
|
|
4496
|
+
const newCommentsByEntityId = {
|
|
4497
|
+
...currentState.comments_by_entity_id,
|
|
4498
|
+
[entityId]: {
|
|
4499
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4500
|
+
},
|
|
4945
4501
|
};
|
|
4946
|
-
const
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
...
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4502
|
+
const index = this.getCommentIndex(comment, currentState);
|
|
4503
|
+
if (newCommentsByEntityId?.[entityId]?.comments?.length && index !== -1) {
|
|
4504
|
+
newCommentsByEntityId[entityId].comments = [
|
|
4505
|
+
...newCommentsByEntityId[entityId].comments,
|
|
4506
|
+
];
|
|
4507
|
+
newCommentsByEntityId[entityId]?.comments?.splice(index, 1);
|
|
4508
|
+
}
|
|
4509
|
+
delete newCommentsByEntityId[comment.id];
|
|
4510
|
+
return {
|
|
4511
|
+
...currentState,
|
|
4512
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
4513
|
+
};
|
|
4514
|
+
});
|
|
4515
|
+
}
|
|
4516
|
+
|
|
4517
|
+
function handleCommentUpdated(event) {
|
|
4518
|
+
const { comment } = event;
|
|
4519
|
+
const entityId = comment.parent_id ?? comment.object_id;
|
|
4520
|
+
this.state.next((currentState) => {
|
|
4521
|
+
const entityState = currentState.comments_by_entity_id[entityId];
|
|
4522
|
+
if (!entityState?.comments?.length)
|
|
4523
|
+
return currentState;
|
|
4524
|
+
const index = this.getCommentIndex(comment, currentState);
|
|
4525
|
+
if (index === -1)
|
|
4526
|
+
return currentState;
|
|
4527
|
+
const newComments = [...entityState.comments];
|
|
4528
|
+
newComments[index] = comment;
|
|
4529
|
+
return {
|
|
4530
|
+
...currentState,
|
|
4531
|
+
comments_by_entity_id: {
|
|
4532
|
+
...currentState.comments_by_entity_id,
|
|
4533
|
+
[entityId]: {
|
|
4534
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4535
|
+
comments: newComments,
|
|
4536
|
+
},
|
|
4977
4537
|
},
|
|
4978
|
-
|
|
4979
|
-
|
|
4538
|
+
};
|
|
4539
|
+
});
|
|
4540
|
+
}
|
|
4541
|
+
|
|
4542
|
+
function handleCommentReaction(event) {
|
|
4543
|
+
const { comment, reaction } = event;
|
|
4544
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4545
|
+
this.state.next((currentState) => {
|
|
4546
|
+
const forId = comment.parent_id ?? comment.object_id;
|
|
4547
|
+
const entityState = currentState.comments_by_entity_id[forId];
|
|
4548
|
+
const commentIndex = this.getCommentIndex(comment, currentState);
|
|
4549
|
+
if (commentIndex === -1)
|
|
4550
|
+
return currentState;
|
|
4551
|
+
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4552
|
+
const commentCopy = { ...comment };
|
|
4553
|
+
delete commentCopy.own_reactions;
|
|
4554
|
+
const newComment = {
|
|
4555
|
+
...newComments[commentIndex],
|
|
4556
|
+
...commentCopy,
|
|
4557
|
+
// TODO: FIXME this should be handled by the backend
|
|
4558
|
+
latest_reactions: commentCopy.latest_reactions ?? [],
|
|
4559
|
+
reaction_groups: commentCopy.reaction_groups ?? {},
|
|
4560
|
+
};
|
|
4561
|
+
newComments[commentIndex] = newComment;
|
|
4562
|
+
if (reaction.user.id === connectedUser?.id) {
|
|
4563
|
+
if (event.type === 'feeds.comment.reaction.added') {
|
|
4564
|
+
newComment.own_reactions = newComment.own_reactions.concat(reaction) ?? [reaction];
|
|
4565
|
+
}
|
|
4566
|
+
else if (event.type === 'feeds.comment.reaction.deleted') {
|
|
4567
|
+
newComment.own_reactions = newComment.own_reactions.filter((r) => r.type !== reaction.type);
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
return {
|
|
4571
|
+
...currentState,
|
|
4572
|
+
comments_by_entity_id: {
|
|
4573
|
+
...currentState.comments_by_entity_id,
|
|
4574
|
+
[forId]: {
|
|
4575
|
+
...entityState,
|
|
4576
|
+
comments: newComments,
|
|
4577
|
+
},
|
|
4980
4578
|
},
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
if (eventHandler !== Feed.noop) {
|
|
4995
|
-
// @ts-expect-error intersection of handler arguments results to never
|
|
4996
|
-
eventHandler?.(event);
|
|
4579
|
+
};
|
|
4580
|
+
});
|
|
4581
|
+
}
|
|
4582
|
+
|
|
4583
|
+
function handleFeedMemberAdded(event) {
|
|
4584
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4585
|
+
this.state.next((currentState) => {
|
|
4586
|
+
let newState;
|
|
4587
|
+
if (typeof currentState.members !== 'undefined') {
|
|
4588
|
+
newState ?? (newState = {
|
|
4589
|
+
...currentState,
|
|
4590
|
+
});
|
|
4591
|
+
newState.members = [event.member, ...currentState.members];
|
|
4997
4592
|
}
|
|
4998
|
-
if (
|
|
4999
|
-
|
|
4593
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4594
|
+
newState ?? (newState = {
|
|
4595
|
+
...currentState,
|
|
4596
|
+
});
|
|
4597
|
+
newState.own_membership = event.member;
|
|
5000
4598
|
}
|
|
5001
|
-
|
|
5002
|
-
}
|
|
4599
|
+
return newState ?? currentState;
|
|
4600
|
+
});
|
|
5003
4601
|
}
|
|
5004
|
-
Feed.noop = () => { };
|
|
5005
4602
|
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
team: request?.team,
|
|
5052
|
-
};
|
|
5053
|
-
const pathParams = {
|
|
5054
|
-
key: request?.key,
|
|
4603
|
+
function handleFeedMemberUpdated(event) {
|
|
4604
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4605
|
+
this.state.next((currentState) => {
|
|
4606
|
+
const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
|
|
4607
|
+
let newState;
|
|
4608
|
+
if (memberIndex !== -1) {
|
|
4609
|
+
// if there's an index, there's a member to update
|
|
4610
|
+
const newMembers = [...currentState.members];
|
|
4611
|
+
newMembers[memberIndex] = event.member;
|
|
4612
|
+
newState ?? (newState = {
|
|
4613
|
+
...currentState,
|
|
4614
|
+
});
|
|
4615
|
+
newState.members = newMembers;
|
|
4616
|
+
}
|
|
4617
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4618
|
+
newState ?? (newState = {
|
|
4619
|
+
...currentState,
|
|
4620
|
+
});
|
|
4621
|
+
newState.own_membership = event.member;
|
|
4622
|
+
}
|
|
4623
|
+
return newState ?? currentState;
|
|
4624
|
+
});
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4627
|
+
function handleFeedMemberRemoved(event) {
|
|
4628
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4629
|
+
this.state.next((currentState) => {
|
|
4630
|
+
const newState = {
|
|
4631
|
+
...currentState,
|
|
4632
|
+
members: currentState.members?.filter((member) => member.user.id !== event.user?.id),
|
|
4633
|
+
};
|
|
4634
|
+
if (connectedUser?.id === event.member_id) {
|
|
4635
|
+
delete newState.own_membership;
|
|
4636
|
+
}
|
|
4637
|
+
return newState;
|
|
4638
|
+
});
|
|
4639
|
+
}
|
|
4640
|
+
|
|
4641
|
+
const addActivitiesToState = (newActivities, activities, position) => {
|
|
4642
|
+
let result;
|
|
4643
|
+
if (activities === undefined) {
|
|
4644
|
+
activities = [];
|
|
4645
|
+
result = {
|
|
4646
|
+
changed: true,
|
|
4647
|
+
activities,
|
|
5055
4648
|
};
|
|
5056
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
5057
|
-
decoders.DeleteModerationConfigResponse?.(response.body);
|
|
5058
|
-
return { ...response.body, metadata: response.metadata };
|
|
5059
4649
|
}
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
const pathParams = {
|
|
5065
|
-
key: request?.key,
|
|
4650
|
+
else {
|
|
4651
|
+
result = {
|
|
4652
|
+
changed: false,
|
|
4653
|
+
activities,
|
|
5066
4654
|
};
|
|
5067
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
5068
|
-
decoders.GetConfigResponse?.(response.body);
|
|
5069
|
-
return { ...response.body, metadata: response.metadata };
|
|
5070
4655
|
}
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
4656
|
+
const newActivitiesDeduplicated = [];
|
|
4657
|
+
newActivities.forEach((newActivityResponse) => {
|
|
4658
|
+
const index = activities.findIndex((a) => a.id === newActivityResponse.id);
|
|
4659
|
+
if (index === -1) {
|
|
4660
|
+
newActivitiesDeduplicated.push(newActivityResponse);
|
|
4661
|
+
}
|
|
4662
|
+
});
|
|
4663
|
+
if (newActivitiesDeduplicated.length > 0) {
|
|
4664
|
+
// TODO: since feed activities are not necessarily ordered by created_at (personalization) we don't order by created_at
|
|
4665
|
+
// Maybe we can add a flag to the JS client to support order by created_at
|
|
4666
|
+
const updatedActivities = [
|
|
4667
|
+
...(position === 'start' ? newActivitiesDeduplicated : []),
|
|
4668
|
+
...activities,
|
|
4669
|
+
...(position === 'end' ? newActivitiesDeduplicated : []),
|
|
4670
|
+
];
|
|
4671
|
+
result = { changed: true, activities: updatedActivities };
|
|
5082
4672
|
}
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
};
|
|
5092
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/flag', undefined, undefined, body, 'application/json');
|
|
5093
|
-
decoders.FlagResponse?.(response.body);
|
|
5094
|
-
return { ...response.body, metadata: response.metadata };
|
|
4673
|
+
return result;
|
|
4674
|
+
};
|
|
4675
|
+
function handleActivityAdded(event) {
|
|
4676
|
+
const currentActivities = this.currentState.activities;
|
|
4677
|
+
const result = addActivitiesToState([event.activity], currentActivities, 'start');
|
|
4678
|
+
if (result.changed) {
|
|
4679
|
+
this.client.hydratePollCache([event.activity]);
|
|
4680
|
+
this.state.partialNext({ activities: result.activities });
|
|
5095
4681
|
}
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
const
|
|
5102
|
-
|
|
5103
|
-
return {
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
const removeActivityFromState = (activityResponse, activities) => {
|
|
4685
|
+
const index = activities.findIndex((a) => a.id === activityResponse.id);
|
|
4686
|
+
if (index !== -1) {
|
|
4687
|
+
const newActivities = [...activities];
|
|
4688
|
+
newActivities.splice(index, 1);
|
|
4689
|
+
return { changed: true, activities: newActivities };
|
|
5104
4690
|
}
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
limit: request?.limit,
|
|
5108
|
-
lock_count: request?.lock_count,
|
|
5109
|
-
lock_duration: request?.lock_duration,
|
|
5110
|
-
lock_items: request?.lock_items,
|
|
5111
|
-
next: request?.next,
|
|
5112
|
-
prev: request?.prev,
|
|
5113
|
-
stats_only: request?.stats_only,
|
|
5114
|
-
sort: request?.sort,
|
|
5115
|
-
filter: request?.filter,
|
|
5116
|
-
};
|
|
5117
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/review_queue', undefined, undefined, body, 'application/json');
|
|
5118
|
-
decoders.QueryReviewQueueResponse?.(response.body);
|
|
5119
|
-
return { ...response.body, metadata: response.metadata };
|
|
4691
|
+
else {
|
|
4692
|
+
return { changed: false, activities };
|
|
5120
4693
|
}
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
delete_reaction: request?.delete_reaction,
|
|
5130
|
-
delete_user: request?.delete_user,
|
|
5131
|
-
mark_reviewed: request?.mark_reviewed,
|
|
5132
|
-
unban: request?.unban,
|
|
5133
|
-
};
|
|
5134
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/submit_action', undefined, undefined, body, 'application/json');
|
|
5135
|
-
decoders.SubmitActionResponse?.(response.body);
|
|
5136
|
-
return { ...response.body, metadata: response.metadata };
|
|
4694
|
+
};
|
|
4695
|
+
function handleActivityDeleted(event) {
|
|
4696
|
+
const currentActivities = this.currentState.activities;
|
|
4697
|
+
if (currentActivities) {
|
|
4698
|
+
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4699
|
+
if (result.changed) {
|
|
4700
|
+
this.state.partialNext({ activities: result.activities });
|
|
4701
|
+
}
|
|
5137
4702
|
}
|
|
5138
4703
|
}
|
|
5139
4704
|
|
|
5140
|
-
|
|
4705
|
+
function handleActivityRemovedFromFeed(event) {
|
|
4706
|
+
const currentActivities = this.currentState.activities;
|
|
4707
|
+
if (currentActivities) {
|
|
4708
|
+
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4709
|
+
if (result.changed) {
|
|
4710
|
+
this.state.partialNext({ activities: result.activities });
|
|
4711
|
+
}
|
|
4712
|
+
}
|
|
5141
4713
|
}
|
|
5142
4714
|
|
|
5143
|
-
const
|
|
5144
|
-
const
|
|
5145
|
-
|
|
5146
|
-
const
|
|
5147
|
-
const
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
acc.ownVotes.push(voteOrAnswer);
|
|
5159
|
-
}
|
|
5160
|
-
return acc;
|
|
5161
|
-
}, { ownVotes: [] }) ?? { ownVotes: [] };
|
|
5162
|
-
return {
|
|
5163
|
-
...pollResponseForState,
|
|
5164
|
-
last_activity_at: new Date(),
|
|
5165
|
-
max_voted_option_ids: getMaxVotedOptionIds(pollResponseForState.vote_counts_by_option),
|
|
5166
|
-
own_answer: ownAnswer,
|
|
5167
|
-
own_votes_by_option_id: getOwnVotesByOptionId(ownVotes),
|
|
4715
|
+
const updateActivityInState = (updatedActivityResponse, activities, replaceCompletely = false) => {
|
|
4716
|
+
const index = activities.findIndex((a) => a.id === updatedActivityResponse.id);
|
|
4717
|
+
if (index !== -1) {
|
|
4718
|
+
const newActivities = [...activities];
|
|
4719
|
+
const activity = activities[index];
|
|
4720
|
+
if (replaceCompletely) {
|
|
4721
|
+
newActivities[index] = updatedActivityResponse;
|
|
4722
|
+
}
|
|
4723
|
+
else {
|
|
4724
|
+
newActivities[index] = {
|
|
4725
|
+
...updatedActivityResponse,
|
|
4726
|
+
own_reactions: activity.own_reactions,
|
|
4727
|
+
own_bookmarks: activity.own_bookmarks,
|
|
4728
|
+
latest_reactions: activity.latest_reactions,
|
|
4729
|
+
reaction_groups: activity.reaction_groups,
|
|
5168
4730
|
};
|
|
4731
|
+
}
|
|
4732
|
+
return { changed: true, activities: newActivities };
|
|
4733
|
+
}
|
|
4734
|
+
else {
|
|
4735
|
+
return { changed: false, activities };
|
|
4736
|
+
}
|
|
4737
|
+
};
|
|
4738
|
+
function handleActivityUpdated(event) {
|
|
4739
|
+
const currentActivities = this.currentState.activities;
|
|
4740
|
+
if (currentActivities) {
|
|
4741
|
+
const result = updateActivityInState(event.activity, currentActivities);
|
|
4742
|
+
if (result.changed) {
|
|
4743
|
+
this.client.hydratePollCache([event.activity]);
|
|
4744
|
+
this.state.partialNext({ activities: result.activities });
|
|
4745
|
+
}
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4749
|
+
const addReactionToActivity = (event, activity, isCurrentUser) => {
|
|
4750
|
+
// Update own_reactions if the reaction is from the current user
|
|
4751
|
+
const ownReactions = [...(activity.own_reactions || [])];
|
|
4752
|
+
if (isCurrentUser) {
|
|
4753
|
+
ownReactions.push(event.reaction);
|
|
4754
|
+
}
|
|
4755
|
+
return {
|
|
4756
|
+
...activity,
|
|
4757
|
+
own_reactions: ownReactions,
|
|
4758
|
+
latest_reactions: event.activity.latest_reactions,
|
|
4759
|
+
reaction_groups: event.activity.reaction_groups,
|
|
4760
|
+
changed: true,
|
|
4761
|
+
};
|
|
4762
|
+
};
|
|
4763
|
+
const addReactionToActivities = (event, activities, isCurrentUser) => {
|
|
4764
|
+
if (!activities) {
|
|
4765
|
+
return { changed: false, activities: [] };
|
|
4766
|
+
}
|
|
4767
|
+
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
4768
|
+
if (activityIndex === -1) {
|
|
4769
|
+
return { changed: false, activities };
|
|
4770
|
+
}
|
|
4771
|
+
const activity = activities[activityIndex];
|
|
4772
|
+
const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
|
|
4773
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4774
|
+
};
|
|
4775
|
+
function handleActivityReactionAdded(event) {
|
|
4776
|
+
const currentActivities = this.currentState.activities;
|
|
4777
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4778
|
+
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4779
|
+
const result = addReactionToActivities(event, currentActivities, isCurrentUser);
|
|
4780
|
+
if (result.changed) {
|
|
4781
|
+
this.state.partialNext({ activities: result.activities });
|
|
4782
|
+
}
|
|
4783
|
+
}
|
|
4784
|
+
|
|
4785
|
+
const removeReactionFromActivity = (event, activity, isCurrentUser) => {
|
|
4786
|
+
// Update own_reactions if the reaction is from the current user
|
|
4787
|
+
const ownReactions = isCurrentUser
|
|
4788
|
+
? (activity.own_reactions || []).filter((r) => !(r.type === event.reaction.type &&
|
|
4789
|
+
r.user.id === event.reaction.user.id))
|
|
4790
|
+
: activity.own_reactions;
|
|
4791
|
+
return {
|
|
4792
|
+
...activity,
|
|
4793
|
+
own_reactions: ownReactions,
|
|
4794
|
+
latest_reactions: event.activity.latest_reactions,
|
|
4795
|
+
reaction_groups: event.activity.reaction_groups,
|
|
4796
|
+
changed: true,
|
|
4797
|
+
};
|
|
4798
|
+
};
|
|
4799
|
+
const removeReactionFromActivities = (event, activities, isCurrentUser) => {
|
|
4800
|
+
if (!activities) {
|
|
4801
|
+
return { changed: false, activities: [] };
|
|
4802
|
+
}
|
|
4803
|
+
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
4804
|
+
if (activityIndex === -1) {
|
|
4805
|
+
return { changed: false, activities };
|
|
4806
|
+
}
|
|
4807
|
+
const activity = activities[activityIndex];
|
|
4808
|
+
const updatedActivity = removeReactionFromActivity(event, activity, isCurrentUser);
|
|
4809
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4810
|
+
};
|
|
4811
|
+
function handleActivityReactionDeleted(event) {
|
|
4812
|
+
const currentActivities = this.currentState.activities;
|
|
4813
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4814
|
+
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4815
|
+
const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
|
|
4816
|
+
if (result.changed) {
|
|
4817
|
+
this.state.partialNext({ activities: result.activities });
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
|
|
4821
|
+
const addBookmarkToActivity = (event, activity, isCurrentUser) => {
|
|
4822
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
4823
|
+
const ownBookmarks = [...(activity.own_bookmarks || [])];
|
|
4824
|
+
if (isCurrentUser) {
|
|
4825
|
+
ownBookmarks.push(event.bookmark);
|
|
4826
|
+
}
|
|
4827
|
+
return {
|
|
4828
|
+
...activity,
|
|
4829
|
+
own_bookmarks: ownBookmarks,
|
|
4830
|
+
changed: true,
|
|
4831
|
+
};
|
|
4832
|
+
};
|
|
4833
|
+
const addBookmarkToActivities = (event, activities, isCurrentUser) => {
|
|
4834
|
+
if (!activities) {
|
|
4835
|
+
return { changed: false, activities: [] };
|
|
4836
|
+
}
|
|
4837
|
+
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4838
|
+
if (activityIndex === -1) {
|
|
4839
|
+
return { changed: false, activities };
|
|
4840
|
+
}
|
|
4841
|
+
const activity = activities[activityIndex];
|
|
4842
|
+
const updatedActivity = addBookmarkToActivity(event, activity, isCurrentUser);
|
|
4843
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4844
|
+
};
|
|
4845
|
+
function handleBookmarkAdded(event) {
|
|
4846
|
+
const currentActivities = this.currentState.activities;
|
|
4847
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4848
|
+
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4849
|
+
const result = addBookmarkToActivities(event, currentActivities, isCurrentUser);
|
|
4850
|
+
if (result.changed) {
|
|
4851
|
+
this.state.partialNext({ activities: result.activities });
|
|
4852
|
+
}
|
|
4853
|
+
}
|
|
4854
|
+
|
|
4855
|
+
// Helper function to check if two bookmarks are the same
|
|
4856
|
+
// A bookmark is identified by activity_id + folder_id + user_id
|
|
4857
|
+
const isSameBookmark = (bookmark1, bookmark2) => {
|
|
4858
|
+
return (bookmark1.user.id === bookmark2.user.id &&
|
|
4859
|
+
bookmark1.activity.id === bookmark2.activity.id &&
|
|
4860
|
+
bookmark1.folder?.id === bookmark2.folder?.id);
|
|
4861
|
+
};
|
|
4862
|
+
const removeBookmarkFromActivities = (event, activities, isCurrentUser) => {
|
|
4863
|
+
if (!activities) {
|
|
4864
|
+
return { changed: false, activities: [] };
|
|
4865
|
+
}
|
|
4866
|
+
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4867
|
+
if (activityIndex === -1) {
|
|
4868
|
+
return { changed: false, activities };
|
|
4869
|
+
}
|
|
4870
|
+
const activity = activities[activityIndex];
|
|
4871
|
+
const updatedActivity = removeBookmarkFromActivity(event, activity, isCurrentUser);
|
|
4872
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4873
|
+
};
|
|
4874
|
+
const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
|
|
4875
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
4876
|
+
const ownBookmarks = isCurrentUser
|
|
4877
|
+
? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
|
|
4878
|
+
: activity.own_bookmarks;
|
|
4879
|
+
return {
|
|
4880
|
+
...activity,
|
|
4881
|
+
own_bookmarks: ownBookmarks,
|
|
4882
|
+
changed: true,
|
|
4883
|
+
};
|
|
4884
|
+
};
|
|
4885
|
+
function handleBookmarkDeleted(event) {
|
|
4886
|
+
const currentActivities = this.currentState.activities;
|
|
4887
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4888
|
+
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4889
|
+
const result = removeBookmarkFromActivities(event, currentActivities, isCurrentUser);
|
|
4890
|
+
if (result.changed) {
|
|
4891
|
+
this.state.partialNext({ activities: result.activities });
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
|
|
4895
|
+
const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
|
|
4896
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
4897
|
+
let ownBookmarks = activity.own_bookmarks || [];
|
|
4898
|
+
if (isCurrentUser) {
|
|
4899
|
+
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
|
|
4900
|
+
if (bookmarkIndex !== -1) {
|
|
4901
|
+
ownBookmarks = [...ownBookmarks];
|
|
4902
|
+
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
return {
|
|
4906
|
+
...activity,
|
|
4907
|
+
own_bookmarks: ownBookmarks,
|
|
4908
|
+
changed: true,
|
|
4909
|
+
};
|
|
4910
|
+
};
|
|
4911
|
+
const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
4912
|
+
if (!activities) {
|
|
4913
|
+
return { changed: false, activities: [] };
|
|
4914
|
+
}
|
|
4915
|
+
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4916
|
+
if (activityIndex === -1) {
|
|
4917
|
+
return { changed: false, activities };
|
|
4918
|
+
}
|
|
4919
|
+
const activity = activities[activityIndex];
|
|
4920
|
+
const updatedActivity = updateBookmarkInActivity(event, activity, isCurrentUser);
|
|
4921
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4922
|
+
};
|
|
4923
|
+
function handleBookmarkUpdated(event) {
|
|
4924
|
+
const currentActivities = this.currentState.activities;
|
|
4925
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4926
|
+
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4927
|
+
const result = updateBookmarkInActivities(event, currentActivities, isCurrentUser);
|
|
4928
|
+
if (result.changed) {
|
|
4929
|
+
this.state.partialNext({ activities: result.activities });
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4932
|
+
|
|
4933
|
+
function handleFeedUpdated(event) {
|
|
4934
|
+
this.state.partialNext({ ...event.feed });
|
|
4935
|
+
}
|
|
4936
|
+
|
|
4937
|
+
function handleNotificationFeedUpdated(event) {
|
|
4938
|
+
console.info('notification feed updated', event);
|
|
4939
|
+
// TODO: handle notification feed updates
|
|
4940
|
+
}
|
|
4941
|
+
|
|
4942
|
+
function handleWatchStarted() {
|
|
4943
|
+
this.state.partialNext({ watch: true });
|
|
4944
|
+
}
|
|
4945
|
+
|
|
4946
|
+
function handleWatchStopped() {
|
|
4947
|
+
this.state.partialNext({ watch: false });
|
|
4948
|
+
}
|
|
4949
|
+
|
|
4950
|
+
class Feed extends FeedApi {
|
|
4951
|
+
constructor(client, groupId, id, data, watch = false) {
|
|
4952
|
+
super(client, groupId, id);
|
|
4953
|
+
this.stateUpdateQueue = new Set();
|
|
4954
|
+
this.eventHandlers = {
|
|
4955
|
+
'feeds.activity.added': handleActivityAdded.bind(this),
|
|
4956
|
+
'feeds.activity.deleted': handleActivityDeleted.bind(this),
|
|
4957
|
+
'feeds.activity.reaction.added': handleActivityReactionAdded.bind(this),
|
|
4958
|
+
'feeds.activity.reaction.deleted': handleActivityReactionDeleted.bind(this),
|
|
4959
|
+
'feeds.activity.reaction.updated': Feed.noop,
|
|
4960
|
+
'feeds.activity.removed_from_feed': handleActivityRemovedFromFeed.bind(this),
|
|
4961
|
+
'feeds.activity.updated': handleActivityUpdated.bind(this),
|
|
4962
|
+
'feeds.bookmark.added': handleBookmarkAdded.bind(this),
|
|
4963
|
+
'feeds.bookmark.deleted': handleBookmarkDeleted.bind(this),
|
|
4964
|
+
'feeds.bookmark.updated': handleBookmarkUpdated.bind(this),
|
|
4965
|
+
'feeds.bookmark_folder.deleted': Feed.noop,
|
|
4966
|
+
'feeds.bookmark_folder.updated': Feed.noop,
|
|
4967
|
+
'feeds.comment.added': handleCommentAdded.bind(this),
|
|
4968
|
+
'feeds.comment.deleted': handleCommentDeleted.bind(this),
|
|
4969
|
+
'feeds.comment.updated': handleCommentUpdated.bind(this),
|
|
4970
|
+
'feeds.feed.created': Feed.noop,
|
|
4971
|
+
'feeds.feed.deleted': Feed.noop,
|
|
4972
|
+
'feeds.feed.updated': handleFeedUpdated.bind(this),
|
|
4973
|
+
'feeds.feed_group.changed': Feed.noop,
|
|
4974
|
+
'feeds.feed_group.deleted': Feed.noop,
|
|
4975
|
+
'feeds.follow.created': handleFollowCreated.bind(this),
|
|
4976
|
+
'feeds.follow.deleted': handleFollowDeleted.bind(this),
|
|
4977
|
+
'feeds.follow.updated': handleFollowUpdated.bind(this),
|
|
4978
|
+
'feeds.comment.reaction.added': handleCommentReaction.bind(this),
|
|
4979
|
+
'feeds.comment.reaction.deleted': handleCommentReaction.bind(this),
|
|
4980
|
+
'feeds.comment.reaction.updated': Feed.noop,
|
|
4981
|
+
'feeds.feed_member.added': handleFeedMemberAdded.bind(this),
|
|
4982
|
+
'feeds.feed_member.removed': handleFeedMemberRemoved.bind(this),
|
|
4983
|
+
'feeds.feed_member.updated': handleFeedMemberUpdated.bind(this),
|
|
4984
|
+
'feeds.notification_feed.updated': handleNotificationFeedUpdated.bind(this),
|
|
4985
|
+
// the poll events should be removed from here
|
|
4986
|
+
'feeds.poll.closed': Feed.noop,
|
|
4987
|
+
'feeds.poll.deleted': Feed.noop,
|
|
4988
|
+
'feeds.poll.updated': Feed.noop,
|
|
4989
|
+
'feeds.poll.vote_casted': Feed.noop,
|
|
4990
|
+
'feeds.poll.vote_changed': Feed.noop,
|
|
4991
|
+
'feeds.poll.vote_removed': Feed.noop,
|
|
4992
|
+
'feeds.activity.pinned': Feed.noop,
|
|
4993
|
+
'feeds.activity.unpinned': Feed.noop,
|
|
4994
|
+
'feeds.activity.marked': Feed.noop,
|
|
4995
|
+
'moderation.custom_action': Feed.noop,
|
|
4996
|
+
'moderation.flagged': Feed.noop,
|
|
4997
|
+
'moderation.mark_reviewed': Feed.noop,
|
|
4998
|
+
'health.check': Feed.noop,
|
|
4999
|
+
'app.updated': Feed.noop,
|
|
5000
|
+
'user.banned': Feed.noop,
|
|
5001
|
+
'user.deactivated': Feed.noop,
|
|
5002
|
+
'user.muted': Feed.noop,
|
|
5003
|
+
'user.reactivated': Feed.noop,
|
|
5004
|
+
'user.updated': Feed.noop,
|
|
5169
5005
|
};
|
|
5170
|
-
this.
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
this.
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5219
|
-
if (isVoteAnswer(event.poll_vote)) {
|
|
5220
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5221
|
-
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
5222
|
-
}
|
|
5223
|
-
else {
|
|
5224
|
-
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
5225
|
-
}
|
|
5226
|
-
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
5227
|
-
this.state.partialNext({
|
|
5228
|
-
answers_count,
|
|
5229
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5230
|
-
latest_votes_by_option,
|
|
5231
|
-
vote_count,
|
|
5232
|
-
vote_counts_by_option,
|
|
5233
|
-
latest_answers: latestAnswers,
|
|
5234
|
-
last_activity_at: new Date(event.created_at),
|
|
5235
|
-
own_answer: ownAnswer,
|
|
5236
|
-
own_votes_by_option_id: ownVotesByOptionId,
|
|
5237
|
-
max_voted_option_ids: maxVotedOptionIds,
|
|
5238
|
-
});
|
|
5239
|
-
};
|
|
5240
|
-
this.handleVoteChanged = (event) => {
|
|
5241
|
-
// this event is triggered only when event.poll.enforce_unique_vote === true
|
|
5242
|
-
if (event.poll?.id && event.poll.id !== this.id)
|
|
5243
|
-
return;
|
|
5244
|
-
if (!isPollVoteChangedEvent(event))
|
|
5245
|
-
return;
|
|
5246
|
-
const currentState = this.data;
|
|
5247
|
-
const isOwnVote = event.poll_vote.user_id ===
|
|
5248
|
-
this.client.state.getLatestValue().connected_user?.id;
|
|
5249
|
-
let latestAnswers = [...currentState.latest_answers];
|
|
5250
|
-
let ownAnswer = currentState.own_answer;
|
|
5251
|
-
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
5252
|
-
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
5253
|
-
if (isOwnVote) {
|
|
5254
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5255
|
-
if (isVoteAnswer(event.poll_vote)) {
|
|
5256
|
-
latestAnswers = [
|
|
5257
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5258
|
-
event.poll_vote,
|
|
5259
|
-
...latestAnswers.filter((answer) => answer.id !== event.poll_vote.id),
|
|
5260
|
-
];
|
|
5261
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5262
|
-
ownAnswer = event.poll_vote;
|
|
5006
|
+
this.eventDispatcher = new EventDispatcher();
|
|
5007
|
+
this.on = this.eventDispatcher.on;
|
|
5008
|
+
this.off = this.eventDispatcher.off;
|
|
5009
|
+
this.state = new StateStore({
|
|
5010
|
+
feed: `${groupId}:${id}`,
|
|
5011
|
+
group_id: groupId,
|
|
5012
|
+
id,
|
|
5013
|
+
...(data ?? {}),
|
|
5014
|
+
is_loading: false,
|
|
5015
|
+
is_loading_activities: false,
|
|
5016
|
+
comments_by_entity_id: {},
|
|
5017
|
+
watch,
|
|
5018
|
+
});
|
|
5019
|
+
this.client = client;
|
|
5020
|
+
}
|
|
5021
|
+
get feed() {
|
|
5022
|
+
return `${this.group}:${this.id}`;
|
|
5023
|
+
}
|
|
5024
|
+
get currentState() {
|
|
5025
|
+
return this.state.getLatestValue();
|
|
5026
|
+
}
|
|
5027
|
+
async synchronize() {
|
|
5028
|
+
const { last_get_or_create_request_config } = this.state.getLatestValue();
|
|
5029
|
+
if (last_get_or_create_request_config?.watch) {
|
|
5030
|
+
await this.getOrCreate(last_get_or_create_request_config);
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
async getOrCreate(request) {
|
|
5034
|
+
if (this.currentState.is_loading_activities) {
|
|
5035
|
+
throw new Error('Only one getOrCreate call is allowed at a time');
|
|
5036
|
+
}
|
|
5037
|
+
this.state.partialNext({
|
|
5038
|
+
is_loading: !request?.next,
|
|
5039
|
+
is_loading_activities: true,
|
|
5040
|
+
});
|
|
5041
|
+
// TODO: pull comments/comment_pagination from activities and comment_sort from request
|
|
5042
|
+
// and pre-populate comments_by_entity_id (once comment_sort and comment_limit are supported)
|
|
5043
|
+
try {
|
|
5044
|
+
const response = await super.getOrCreate(request);
|
|
5045
|
+
if (request?.next) {
|
|
5046
|
+
const { activities: currentActivities = [] } = this.currentState;
|
|
5047
|
+
const result = addActivitiesToState(response.activities, currentActivities, 'end');
|
|
5048
|
+
if (result.changed) {
|
|
5049
|
+
this.state.partialNext({
|
|
5050
|
+
activities: result.activities,
|
|
5051
|
+
next: response.next,
|
|
5052
|
+
prev: response.prev,
|
|
5053
|
+
});
|
|
5263
5054
|
}
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5055
|
+
}
|
|
5056
|
+
else {
|
|
5057
|
+
// Empty queue when reinitializing the state
|
|
5058
|
+
this.stateUpdateQueue.clear();
|
|
5059
|
+
const responseCopy = {
|
|
5060
|
+
...response,
|
|
5061
|
+
...response.feed,
|
|
5062
|
+
};
|
|
5063
|
+
delete responseCopy.feed;
|
|
5064
|
+
delete responseCopy.metadata;
|
|
5065
|
+
delete responseCopy.duration;
|
|
5066
|
+
// TODO: lazy-load comments from activities when comment_sort and comment_pagination are supported
|
|
5067
|
+
this.state.next((currentState) => {
|
|
5068
|
+
const nextState = {
|
|
5069
|
+
...currentState,
|
|
5070
|
+
...responseCopy,
|
|
5071
|
+
};
|
|
5072
|
+
if (!request?.followers_pagination?.limit) {
|
|
5073
|
+
delete nextState.followers;
|
|
5268
5074
|
}
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
if (optionId !== event.poll_vote.option_id &&
|
|
5272
|
-
vote.id === event.poll_vote.id) {
|
|
5273
|
-
return acc;
|
|
5274
|
-
}
|
|
5275
|
-
acc[optionId] = vote;
|
|
5276
|
-
return acc;
|
|
5277
|
-
}, {});
|
|
5278
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5279
|
-
ownVotesByOptionId[event.poll_vote.option_id] = event.poll_vote;
|
|
5075
|
+
if (!request?.following_pagination?.limit) {
|
|
5076
|
+
delete nextState.following;
|
|
5280
5077
|
}
|
|
5281
|
-
if (
|
|
5282
|
-
|
|
5078
|
+
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
5079
|
+
delete nextState.members;
|
|
5283
5080
|
}
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
else if (isVoteAnswer(event.poll_vote)) {
|
|
5289
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5290
|
-
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
5291
|
-
}
|
|
5292
|
-
else {
|
|
5293
|
-
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
5081
|
+
nextState.last_get_or_create_request_config = request;
|
|
5082
|
+
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
5083
|
+
return nextState;
|
|
5084
|
+
});
|
|
5294
5085
|
}
|
|
5295
|
-
|
|
5086
|
+
this.client.hydratePollCache(response.activities);
|
|
5087
|
+
return response;
|
|
5088
|
+
}
|
|
5089
|
+
finally {
|
|
5296
5090
|
this.state.partialNext({
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5091
|
+
is_loading: false,
|
|
5092
|
+
is_loading_activities: false,
|
|
5093
|
+
});
|
|
5094
|
+
}
|
|
5095
|
+
}
|
|
5096
|
+
/**
|
|
5097
|
+
* Returns index of the provided comment object.
|
|
5098
|
+
*/
|
|
5099
|
+
getCommentIndex(comment, state) {
|
|
5100
|
+
const { comments_by_entity_id = {} } = state ?? this.currentState;
|
|
5101
|
+
const currentComments = comments_by_entity_id[comment.parent_id ?? comment.object_id]?.comments;
|
|
5102
|
+
if (!currentComments?.length) {
|
|
5103
|
+
return -1;
|
|
5104
|
+
}
|
|
5105
|
+
// @ts-expect-error this will just fail if the comment is not object from state
|
|
5106
|
+
let commentIndex = currentComments.indexOf(comment);
|
|
5107
|
+
// fast lookup failed, try slower approach
|
|
5108
|
+
if (commentIndex === -1) {
|
|
5109
|
+
commentIndex = currentComments.findIndex((comment_) => comment_.id === comment.id);
|
|
5110
|
+
}
|
|
5111
|
+
return commentIndex;
|
|
5112
|
+
}
|
|
5113
|
+
/**
|
|
5114
|
+
* Load child comments of entity (activity or comment) into the state, if the target entity is comment,
|
|
5115
|
+
* `entityParentId` should be provided (`CommentResponse.parent_id ?? CommentResponse.object_id`).
|
|
5116
|
+
*/
|
|
5117
|
+
loadCommentsIntoState(data) {
|
|
5118
|
+
// add initial (top level) object for processing
|
|
5119
|
+
const traverseArray = [
|
|
5120
|
+
{
|
|
5121
|
+
entityId: data.entityId,
|
|
5122
|
+
entityParentId: data.entityParentId,
|
|
5123
|
+
comments: data.comments,
|
|
5124
|
+
next: data.next,
|
|
5125
|
+
},
|
|
5126
|
+
];
|
|
5127
|
+
this.state.next((currentState) => {
|
|
5128
|
+
const newCommentsByEntityId = {
|
|
5129
|
+
...currentState.comments_by_entity_id,
|
|
5130
|
+
};
|
|
5131
|
+
while (traverseArray.length) {
|
|
5132
|
+
const item = traverseArray.pop();
|
|
5133
|
+
const entityId = item.entityId;
|
|
5134
|
+
// go over entity comments and generate new objects
|
|
5135
|
+
// for further processing if there are any replies
|
|
5136
|
+
item.comments.forEach((comment) => {
|
|
5137
|
+
if (!comment.replies?.length)
|
|
5138
|
+
return;
|
|
5139
|
+
traverseArray.push({
|
|
5140
|
+
entityId: comment.id,
|
|
5141
|
+
entityParentId: entityId,
|
|
5142
|
+
comments: comment.replies,
|
|
5143
|
+
next: comment.meta?.next_cursor,
|
|
5144
|
+
});
|
|
5145
|
+
});
|
|
5146
|
+
// omit replies & meta from the comments (transform ThreadedCommentResponse to CommentResponse)
|
|
5147
|
+
// this is somehow faster than copying the whole
|
|
5148
|
+
// object and deleting the desired properties
|
|
5149
|
+
const newComments = item.comments.map(({ replies: _r, meta: _m, ...restOfTheCommentResponse }) => restOfTheCommentResponse);
|
|
5150
|
+
const existingComments = newCommentsByEntityId[entityId]?.comments;
|
|
5151
|
+
newCommentsByEntityId[entityId] = {
|
|
5152
|
+
...newCommentsByEntityId[entityId],
|
|
5153
|
+
entity_parent_id: item.entityParentId,
|
|
5154
|
+
pagination: {
|
|
5155
|
+
...newCommentsByEntityId[entityId]?.pagination,
|
|
5156
|
+
next: item.next,
|
|
5157
|
+
sort: data.sort,
|
|
5158
|
+
},
|
|
5159
|
+
comments: existingComments
|
|
5160
|
+
? uniqueArrayMerge(existingComments, newComments, (comment) => comment.id)
|
|
5161
|
+
: newComments,
|
|
5162
|
+
};
|
|
5163
|
+
}
|
|
5164
|
+
return {
|
|
5165
|
+
...currentState,
|
|
5166
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
5167
|
+
};
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
async loadNextPageComments({ entityId, base, sort, entityParentId, }) {
|
|
5171
|
+
let error;
|
|
5172
|
+
try {
|
|
5173
|
+
this.state.next((currentState) => ({
|
|
5174
|
+
...currentState,
|
|
5175
|
+
comments_by_entity_id: {
|
|
5176
|
+
...currentState.comments_by_entity_id,
|
|
5177
|
+
[entityId]: {
|
|
5178
|
+
...currentState.comments_by_entity_id[entityId],
|
|
5179
|
+
pagination: {
|
|
5180
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
5181
|
+
loading_next_page: true,
|
|
5182
|
+
},
|
|
5183
|
+
},
|
|
5184
|
+
},
|
|
5185
|
+
}));
|
|
5186
|
+
const { next, comments } = await base();
|
|
5187
|
+
this.loadCommentsIntoState({
|
|
5188
|
+
entityId,
|
|
5189
|
+
comments,
|
|
5190
|
+
entityParentId,
|
|
5191
|
+
next,
|
|
5192
|
+
sort,
|
|
5193
|
+
});
|
|
5194
|
+
}
|
|
5195
|
+
catch (e) {
|
|
5196
|
+
error = e;
|
|
5197
|
+
}
|
|
5198
|
+
finally {
|
|
5199
|
+
this.state.next((currentState) => ({
|
|
5200
|
+
...currentState,
|
|
5201
|
+
comments_by_entity_id: {
|
|
5202
|
+
...currentState.comments_by_entity_id,
|
|
5203
|
+
[entityId]: {
|
|
5204
|
+
...currentState.comments_by_entity_id[entityId],
|
|
5205
|
+
pagination: {
|
|
5206
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
5207
|
+
loading_next_page: false,
|
|
5208
|
+
},
|
|
5209
|
+
},
|
|
5210
|
+
},
|
|
5211
|
+
}));
|
|
5212
|
+
}
|
|
5213
|
+
if (error) {
|
|
5214
|
+
throw error;
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
async loadNextPageActivityComments(activity, request) {
|
|
5218
|
+
const currentEntityState = this.currentState.comments_by_entity_id[activity.id];
|
|
5219
|
+
const currentPagination = currentEntityState?.pagination;
|
|
5220
|
+
const currentNextCursor = currentPagination?.next;
|
|
5221
|
+
const currentSort = currentPagination?.sort;
|
|
5222
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
5223
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
5224
|
+
if (isLoading ||
|
|
5225
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
5226
|
+
return;
|
|
5227
|
+
}
|
|
5228
|
+
await this.loadNextPageComments({
|
|
5229
|
+
entityId: activity.id,
|
|
5230
|
+
base: () => this.client.getComments({
|
|
5231
|
+
...request,
|
|
5232
|
+
sort,
|
|
5233
|
+
object_id: activity.id,
|
|
5234
|
+
object_type: 'activity',
|
|
5235
|
+
next: currentNextCursor,
|
|
5236
|
+
}),
|
|
5237
|
+
sort,
|
|
5238
|
+
});
|
|
5239
|
+
}
|
|
5240
|
+
async loadNextPageCommentReplies(comment, request) {
|
|
5241
|
+
const currentEntityState = this.currentState.comments_by_entity_id[comment.id];
|
|
5242
|
+
const currentPagination = currentEntityState?.pagination;
|
|
5243
|
+
const currentNextCursor = currentPagination?.next;
|
|
5244
|
+
const currentSort = currentPagination?.sort;
|
|
5245
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
5246
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
5247
|
+
if (isLoading ||
|
|
5248
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
5249
|
+
return;
|
|
5250
|
+
}
|
|
5251
|
+
await this.loadNextPageComments({
|
|
5252
|
+
entityId: comment.id,
|
|
5253
|
+
base: () => this.client.getCommentReplies({
|
|
5254
|
+
...request,
|
|
5255
|
+
id: comment.id,
|
|
5256
|
+
// use known sort first (prevents broken pagination)
|
|
5257
|
+
sort,
|
|
5258
|
+
next: currentNextCursor,
|
|
5259
|
+
}),
|
|
5260
|
+
entityParentId: comment.parent_id ?? comment.object_id,
|
|
5261
|
+
sort,
|
|
5262
|
+
});
|
|
5263
|
+
}
|
|
5264
|
+
async loadNextPageFollows(type, request) {
|
|
5265
|
+
const paginationKey = `${type}_pagination`;
|
|
5266
|
+
const method = `query${capitalize(type)}`;
|
|
5267
|
+
const currentFollows = this.currentState[type];
|
|
5268
|
+
const currentNextCursor = this.currentState[paginationKey]?.next;
|
|
5269
|
+
const isLoading = this.currentState[paginationKey]?.loading_next_page;
|
|
5270
|
+
const sort = this.currentState[paginationKey]?.sort ?? request.sort;
|
|
5271
|
+
let error;
|
|
5272
|
+
if (isLoading || !checkHasAnotherPage(currentFollows, currentNextCursor)) {
|
|
5273
|
+
return;
|
|
5274
|
+
}
|
|
5275
|
+
try {
|
|
5276
|
+
this.state.next((currentState) => {
|
|
5277
|
+
return {
|
|
5278
|
+
...currentState,
|
|
5279
|
+
[paginationKey]: {
|
|
5280
|
+
...currentState[paginationKey],
|
|
5281
|
+
loading_next_page: true,
|
|
5282
|
+
},
|
|
5283
|
+
};
|
|
5307
5284
|
});
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5285
|
+
const { next: newNextCursor, follows } = await this[method]({
|
|
5286
|
+
...request,
|
|
5287
|
+
next: currentNextCursor,
|
|
5288
|
+
sort,
|
|
5289
|
+
});
|
|
5290
|
+
this.state.next((currentState) => {
|
|
5291
|
+
return {
|
|
5292
|
+
...currentState,
|
|
5293
|
+
[type]: currentState[type] === undefined
|
|
5294
|
+
? follows
|
|
5295
|
+
: uniqueArrayMerge(currentState[type], follows, (follow) => `${follow.source_feed.feed}-${follow.target_feed.feed}`),
|
|
5296
|
+
[paginationKey]: {
|
|
5297
|
+
...currentState[paginationKey],
|
|
5298
|
+
next: newNextCursor,
|
|
5299
|
+
sort,
|
|
5300
|
+
},
|
|
5301
|
+
};
|
|
5302
|
+
});
|
|
5303
|
+
}
|
|
5304
|
+
catch (e) {
|
|
5305
|
+
error = e;
|
|
5306
|
+
}
|
|
5307
|
+
finally {
|
|
5308
|
+
this.state.next((currentState) => {
|
|
5309
|
+
return {
|
|
5310
|
+
...currentState,
|
|
5311
|
+
[paginationKey]: {
|
|
5312
|
+
...currentState[paginationKey],
|
|
5313
|
+
loading_next_page: false,
|
|
5314
|
+
},
|
|
5315
|
+
};
|
|
5316
|
+
});
|
|
5317
|
+
}
|
|
5318
|
+
if (error) {
|
|
5319
|
+
throw error;
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
async loadNextPageFollowers(request) {
|
|
5323
|
+
await this.loadNextPageFollows('followers', request);
|
|
5324
|
+
}
|
|
5325
|
+
async loadNextPageFollowing(request) {
|
|
5326
|
+
await this.loadNextPageFollows('following', request);
|
|
5327
|
+
}
|
|
5328
|
+
async loadNextPageMembers(request) {
|
|
5329
|
+
const currentMembers = this.currentState.members;
|
|
5330
|
+
const currentNextCursor = this.currentState.member_pagination?.next;
|
|
5331
|
+
const isLoading = this.currentState.member_pagination?.loading_next_page;
|
|
5332
|
+
const sort = this.currentState.member_pagination?.sort ?? request.sort;
|
|
5333
|
+
let error;
|
|
5334
|
+
if (isLoading || !checkHasAnotherPage(currentMembers, currentNextCursor)) {
|
|
5335
|
+
return;
|
|
5336
|
+
}
|
|
5337
|
+
try {
|
|
5338
|
+
this.state.next((currentState) => ({
|
|
5339
|
+
...currentState,
|
|
5340
|
+
member_pagination: {
|
|
5341
|
+
...currentState.member_pagination,
|
|
5342
|
+
loading_next_page: true,
|
|
5343
|
+
},
|
|
5344
|
+
}));
|
|
5345
|
+
const { next: newNextCursor, members } = await this.client.queryFeedMembers({
|
|
5346
|
+
...request,
|
|
5347
|
+
sort,
|
|
5348
|
+
feed_id: this.id,
|
|
5349
|
+
feed_group_id: this.group,
|
|
5350
|
+
next: currentNextCursor,
|
|
5346
5351
|
});
|
|
5352
|
+
this.state.next((currentState) => ({
|
|
5353
|
+
...currentState,
|
|
5354
|
+
members: currentState.members
|
|
5355
|
+
? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
|
|
5356
|
+
: members,
|
|
5357
|
+
member_pagination: {
|
|
5358
|
+
...currentState.member_pagination,
|
|
5359
|
+
next: newNextCursor,
|
|
5360
|
+
// set sort if not defined yet
|
|
5361
|
+
sort: currentState.member_pagination?.sort ?? request.sort,
|
|
5362
|
+
},
|
|
5363
|
+
}));
|
|
5364
|
+
}
|
|
5365
|
+
catch (e) {
|
|
5366
|
+
error = e;
|
|
5367
|
+
}
|
|
5368
|
+
finally {
|
|
5369
|
+
this.state.next((currentState) => ({
|
|
5370
|
+
...currentState,
|
|
5371
|
+
member_pagination: {
|
|
5372
|
+
...currentState.member_pagination,
|
|
5373
|
+
loading_next_page: false,
|
|
5374
|
+
},
|
|
5375
|
+
}));
|
|
5376
|
+
}
|
|
5377
|
+
if (error) {
|
|
5378
|
+
throw error;
|
|
5379
|
+
}
|
|
5380
|
+
}
|
|
5381
|
+
/**
|
|
5382
|
+
* Method which queries followers of this feed (feeds which target this feed).
|
|
5383
|
+
*
|
|
5384
|
+
* _Note: Useful only for feeds with `groupId` of `user` value._
|
|
5385
|
+
*/
|
|
5386
|
+
async queryFollowers(request) {
|
|
5387
|
+
const filter = {
|
|
5388
|
+
target_feed: this.feed,
|
|
5347
5389
|
};
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5390
|
+
const response = await this.client.queryFollows({
|
|
5391
|
+
filter,
|
|
5392
|
+
...request,
|
|
5393
|
+
});
|
|
5394
|
+
return response;
|
|
5351
5395
|
}
|
|
5352
|
-
|
|
5353
|
-
|
|
5396
|
+
/**
|
|
5397
|
+
* Method which queries following of this feed (target feeds of this feed).
|
|
5398
|
+
*
|
|
5399
|
+
* _Note: Useful only for feeds with `groupId` of `timeline` value._
|
|
5400
|
+
*/
|
|
5401
|
+
async queryFollowing(request) {
|
|
5402
|
+
const filter = {
|
|
5403
|
+
source_feed: this.feed,
|
|
5404
|
+
};
|
|
5405
|
+
const response = await this.client.queryFollows({
|
|
5406
|
+
filter,
|
|
5407
|
+
...request,
|
|
5408
|
+
});
|
|
5409
|
+
return response;
|
|
5354
5410
|
}
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5411
|
+
async follow(feedOrFid, options) {
|
|
5412
|
+
const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.feed;
|
|
5413
|
+
const response = await this.client.follow({
|
|
5414
|
+
...options,
|
|
5415
|
+
source: this.feed,
|
|
5416
|
+
target: fid,
|
|
5417
|
+
});
|
|
5418
|
+
return response;
|
|
5419
|
+
}
|
|
5420
|
+
async unfollow(feedOrFid) {
|
|
5421
|
+
const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.feed;
|
|
5422
|
+
const response = await this.client.unfollow({
|
|
5423
|
+
source: this.feed,
|
|
5424
|
+
target: fid,
|
|
5425
|
+
});
|
|
5426
|
+
return response;
|
|
5427
|
+
}
|
|
5428
|
+
async getNextPage() {
|
|
5429
|
+
const currentState = this.currentState;
|
|
5430
|
+
return await this.getOrCreate({
|
|
5431
|
+
member_pagination: {
|
|
5432
|
+
limit: 0,
|
|
5433
|
+
},
|
|
5434
|
+
followers_pagination: {
|
|
5435
|
+
limit: 0,
|
|
5436
|
+
},
|
|
5437
|
+
following_pagination: {
|
|
5438
|
+
limit: 0,
|
|
5439
|
+
},
|
|
5440
|
+
next: currentState.next,
|
|
5441
|
+
limit: currentState.last_get_or_create_request_config?.limit ?? 20,
|
|
5442
|
+
});
|
|
5443
|
+
}
|
|
5444
|
+
addActivity(request) {
|
|
5445
|
+
return this.feedsApi.addActivity({
|
|
5446
|
+
...request,
|
|
5447
|
+
feeds: [this.feed],
|
|
5448
|
+
});
|
|
5449
|
+
}
|
|
5450
|
+
handleWSEvent(event) {
|
|
5451
|
+
const eventHandler = this.eventHandlers[event.type];
|
|
5452
|
+
// no need to run noop function
|
|
5453
|
+
if (eventHandler !== Feed.noop) {
|
|
5454
|
+
// @ts-expect-error intersection of handler arguments results to never
|
|
5455
|
+
eventHandler?.(event);
|
|
5363
5456
|
}
|
|
5364
|
-
|
|
5365
|
-
|
|
5457
|
+
if (typeof eventHandler === 'undefined') {
|
|
5458
|
+
console.warn(`Received unknown event type: ${event.type}`, event);
|
|
5366
5459
|
}
|
|
5460
|
+
this.eventDispatcher.dispatch(event);
|
|
5367
5461
|
}
|
|
5368
|
-
return winningOptions;
|
|
5369
5462
|
}
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5463
|
+
Feed.noop = () => { };
|
|
5464
|
+
|
|
5465
|
+
function handleUserUpdated(event) {
|
|
5466
|
+
this.state.next((currentState) => {
|
|
5467
|
+
let newState;
|
|
5468
|
+
const { connected_user } = currentState;
|
|
5469
|
+
if (connected_user && connected_user.id === event.user.id) {
|
|
5470
|
+
newState ?? (newState = {
|
|
5471
|
+
...currentState,
|
|
5472
|
+
});
|
|
5473
|
+
newState.connected_user = {
|
|
5474
|
+
...connected_user,
|
|
5475
|
+
...event.user,
|
|
5476
|
+
};
|
|
5477
|
+
}
|
|
5478
|
+
// TODO: update other users in user map (if/once applicable)
|
|
5479
|
+
return newState ?? currentState;
|
|
5480
|
+
});
|
|
5379
5481
|
}
|
|
5380
5482
|
|
|
5381
5483
|
class FeedsClient extends FeedsApi {
|
|
@@ -5485,7 +5587,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5485
5587
|
if (this.activeFeeds[fid]) {
|
|
5486
5588
|
const feed = this.activeFeeds[fid];
|
|
5487
5589
|
if (watch && !feed.currentState.watch) {
|
|
5488
|
-
|
|
5590
|
+
handleWatchStarted.bind(feed)();
|
|
5489
5591
|
}
|
|
5490
5592
|
return feed;
|
|
5491
5593
|
}
|
|
@@ -5521,7 +5623,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5521
5623
|
}
|
|
5522
5624
|
else {
|
|
5523
5625
|
for (const activeFeed of Object.values(this.activeFeeds)) {
|
|
5524
|
-
|
|
5626
|
+
handleWatchStopped.bind(activeFeed)();
|
|
5525
5627
|
}
|
|
5526
5628
|
}
|
|
5527
5629
|
break;
|
|
@@ -5601,6 +5703,10 @@ class FeedsClient extends FeedsApi {
|
|
|
5601
5703
|
feeds.forEach((f) => f.handleWSEvent(event));
|
|
5602
5704
|
break;
|
|
5603
5705
|
}
|
|
5706
|
+
case 'user.updated': {
|
|
5707
|
+
handleUserUpdated.call(this, event);
|
|
5708
|
+
break;
|
|
5709
|
+
}
|
|
5604
5710
|
default: {
|
|
5605
5711
|
feed?.handleWSEvent(event);
|
|
5606
5712
|
}
|
|
@@ -5626,7 +5732,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5626
5732
|
}
|
|
5627
5733
|
}
|
|
5628
5734
|
async queryFeeds(request) {
|
|
5629
|
-
const response = await this.
|
|
5735
|
+
const response = await this._queryFeeds(request);
|
|
5630
5736
|
const feeds = response.feeds.map((f) => this.getOrCreateActiveFeed(f.group_id, f.id, f, request?.watch));
|
|
5631
5737
|
return {
|
|
5632
5738
|
feeds,
|
|
@@ -5636,13 +5742,29 @@ class FeedsClient extends FeedsApi {
|
|
|
5636
5742
|
duration: response.duration,
|
|
5637
5743
|
};
|
|
5638
5744
|
}
|
|
5745
|
+
async updateFollow(request) {
|
|
5746
|
+
const response = await super.updateFollow(request);
|
|
5747
|
+
[
|
|
5748
|
+
response.follow.source_feed.feed,
|
|
5749
|
+
response.follow.target_feed.feed,
|
|
5750
|
+
].forEach((fid) => {
|
|
5751
|
+
const feed = this.activeFeeds[fid];
|
|
5752
|
+
if (feed) {
|
|
5753
|
+
handleFollowUpdated.bind(feed)(response);
|
|
5754
|
+
}
|
|
5755
|
+
});
|
|
5756
|
+
return response;
|
|
5757
|
+
}
|
|
5639
5758
|
// For follow API endpoints we update the state after HTTP response to allow queryFeeds with watch: false
|
|
5640
5759
|
async follow(request) {
|
|
5641
5760
|
const response = await super.follow(request);
|
|
5642
|
-
[
|
|
5761
|
+
[
|
|
5762
|
+
response.follow.source_feed.feed,
|
|
5763
|
+
response.follow.target_feed.feed,
|
|
5764
|
+
].forEach((fid) => {
|
|
5643
5765
|
const feed = this.activeFeeds[fid];
|
|
5644
5766
|
if (feed) {
|
|
5645
|
-
|
|
5767
|
+
handleFollowCreated.bind(feed)(response);
|
|
5646
5768
|
}
|
|
5647
5769
|
});
|
|
5648
5770
|
return response;
|
|
@@ -5650,9 +5772,9 @@ class FeedsClient extends FeedsApi {
|
|
|
5650
5772
|
async followBatch(request) {
|
|
5651
5773
|
const response = await super.followBatch(request);
|
|
5652
5774
|
response.follows.forEach((follow) => {
|
|
5653
|
-
const feed = this.activeFeeds[follow.source_feed.
|
|
5775
|
+
const feed = this.activeFeeds[follow.source_feed.feed];
|
|
5654
5776
|
if (feed) {
|
|
5655
|
-
|
|
5777
|
+
handleFollowCreated.bind(feed)({ follow });
|
|
5656
5778
|
}
|
|
5657
5779
|
});
|
|
5658
5780
|
return response;
|
|
@@ -5662,10 +5784,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5662
5784
|
[request.source, request.target].forEach((fid) => {
|
|
5663
5785
|
const feed = this.activeFeeds[fid];
|
|
5664
5786
|
if (feed) {
|
|
5665
|
-
|
|
5666
|
-
source_feed: { fid: request.source },
|
|
5667
|
-
target_feed: { fid: request.target },
|
|
5668
|
-
});
|
|
5787
|
+
handleFollowDeleted.bind(feed)(response);
|
|
5669
5788
|
}
|
|
5670
5789
|
});
|
|
5671
5790
|
return response;
|
|
@@ -5678,7 +5797,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5678
5797
|
});
|
|
5679
5798
|
const feed = this.activeFeeds[`${request.feed_group_id}:${request.feed_id}`];
|
|
5680
5799
|
if (feed) {
|
|
5681
|
-
|
|
5800
|
+
handleWatchStopped.bind(feed)();
|
|
5682
5801
|
}
|
|
5683
5802
|
return response;
|
|
5684
5803
|
}
|
|
@@ -6110,10 +6229,13 @@ exports.StreamApiError = StreamApiError;
|
|
|
6110
6229
|
exports.StreamPoll = StreamPoll;
|
|
6111
6230
|
exports.UserSearchSource = UserSearchSource;
|
|
6112
6231
|
exports.checkHasAnotherPage = checkHasAnotherPage;
|
|
6232
|
+
exports.getStateUpdateQueueId = getStateUpdateQueueId;
|
|
6113
6233
|
exports.isCommentResponse = isCommentResponse;
|
|
6234
|
+
exports.isFollowResponse = isFollowResponse;
|
|
6114
6235
|
exports.isImageFile = isImageFile;
|
|
6115
6236
|
exports.isPatch = isPatch;
|
|
6116
6237
|
exports.isVideoFile = isVideoFile;
|
|
6117
6238
|
exports.isVoteAnswer = isVoteAnswer;
|
|
6239
|
+
exports.shouldUpdateState = shouldUpdateState;
|
|
6118
6240
|
exports.uniqueArrayMerge = uniqueArrayMerge;
|
|
6119
6241
|
//# sourceMappingURL=index.node.cjs.map
|