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