@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
|
@@ -905,6 +905,7 @@ decoders.FeedResponse = (input) => {
|
|
|
905
905
|
updated_at: { type: 'DatetimeType', isSingle: true },
|
|
906
906
|
created_by: { type: 'UserResponse', isSingle: true },
|
|
907
907
|
deleted_at: { type: 'DatetimeType', isSingle: true },
|
|
908
|
+
own_follows: { type: 'FollowResponse', isSingle: false },
|
|
908
909
|
};
|
|
909
910
|
return decode(typeMappings, input);
|
|
910
911
|
};
|
|
@@ -1123,6 +1124,13 @@ decoders.ModerationCustomActionEvent = (input) => {
|
|
|
1123
1124
|
};
|
|
1124
1125
|
return decode(typeMappings, input);
|
|
1125
1126
|
};
|
|
1127
|
+
decoders.ModerationFlagResponse = (input) => {
|
|
1128
|
+
const typeMappings = {
|
|
1129
|
+
review_queue_item: { type: 'ReviewQueueItemResponse', isSingle: true },
|
|
1130
|
+
user: { type: 'UserResponse', isSingle: true },
|
|
1131
|
+
};
|
|
1132
|
+
return decode(typeMappings, input);
|
|
1133
|
+
};
|
|
1126
1134
|
decoders.ModerationFlaggedEvent = (input) => {
|
|
1127
1135
|
const typeMappings = {
|
|
1128
1136
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -1159,6 +1167,7 @@ decoders.NotificationFeedUpdatedEvent = (input) => {
|
|
|
1159
1167
|
};
|
|
1160
1168
|
decoders.NotificationStatusResponse = (input) => {
|
|
1161
1169
|
const typeMappings = {
|
|
1170
|
+
last_read_at: { type: 'DatetimeType', isSingle: true },
|
|
1162
1171
|
last_seen_at: { type: 'DatetimeType', isSingle: true },
|
|
1163
1172
|
};
|
|
1164
1173
|
return decode(typeMappings, input);
|
|
@@ -1426,6 +1435,7 @@ decoders.ReviewQueueItemResponse = (input) => {
|
|
|
1426
1435
|
updated_at: { type: 'DatetimeType', isSingle: true },
|
|
1427
1436
|
actions: { type: 'ActionLogResponse', isSingle: false },
|
|
1428
1437
|
bans: { type: 'Ban', isSingle: false },
|
|
1438
|
+
flags: { type: 'ModerationFlagResponse', isSingle: false },
|
|
1429
1439
|
completed_at: { type: 'DatetimeType', isSingle: true },
|
|
1430
1440
|
reviewed_at: { type: 'DatetimeType', isSingle: true },
|
|
1431
1441
|
assigned_to: { type: 'UserResponse', isSingle: true },
|
|
@@ -1502,6 +1512,12 @@ decoders.ThreadedCommentResponse = (input) => {
|
|
|
1502
1512
|
};
|
|
1503
1513
|
return decode(typeMappings, input);
|
|
1504
1514
|
};
|
|
1515
|
+
decoders.UnfollowResponse = (input) => {
|
|
1516
|
+
const typeMappings = {
|
|
1517
|
+
follow: { type: 'FollowResponse', isSingle: true },
|
|
1518
|
+
};
|
|
1519
|
+
return decode(typeMappings, input);
|
|
1520
|
+
};
|
|
1505
1521
|
decoders.UnpinActivityResponse = (input) => {
|
|
1506
1522
|
const typeMappings = {
|
|
1507
1523
|
activity: { type: 'ActivityResponse', isSingle: true },
|
|
@@ -1742,7 +1758,7 @@ class FeedsApi {
|
|
|
1742
1758
|
async addActivity(request) {
|
|
1743
1759
|
const body = {
|
|
1744
1760
|
type: request?.type,
|
|
1745
|
-
|
|
1761
|
+
feeds: request?.feeds,
|
|
1746
1762
|
expires_at: request?.expires_at,
|
|
1747
1763
|
id: request?.id,
|
|
1748
1764
|
parent_id: request?.parent_id,
|
|
@@ -1772,7 +1788,7 @@ class FeedsApi {
|
|
|
1772
1788
|
}
|
|
1773
1789
|
async deleteActivities(request) {
|
|
1774
1790
|
const body = {
|
|
1775
|
-
|
|
1791
|
+
ids: request?.ids,
|
|
1776
1792
|
hard_delete: request?.hard_delete,
|
|
1777
1793
|
};
|
|
1778
1794
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/activities/delete', undefined, undefined, body, 'application/json');
|
|
@@ -1791,56 +1807,6 @@ class FeedsApi {
|
|
|
1791
1807
|
decoders.QueryActivitiesResponse?.(response.body);
|
|
1792
1808
|
return { ...response.body, metadata: response.metadata };
|
|
1793
1809
|
}
|
|
1794
|
-
async deleteActivity(request) {
|
|
1795
|
-
const queryParams = {
|
|
1796
|
-
hard_delete: request?.hard_delete,
|
|
1797
|
-
};
|
|
1798
|
-
const pathParams = {
|
|
1799
|
-
activity_id: request?.activity_id,
|
|
1800
|
-
};
|
|
1801
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/activities/{activity_id}', pathParams, queryParams);
|
|
1802
|
-
decoders.DeleteActivityResponse?.(response.body);
|
|
1803
|
-
return { ...response.body, metadata: response.metadata };
|
|
1804
|
-
}
|
|
1805
|
-
async getActivity(request) {
|
|
1806
|
-
const pathParams = {
|
|
1807
|
-
activity_id: request?.activity_id,
|
|
1808
|
-
};
|
|
1809
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/activities/{activity_id}', pathParams, undefined);
|
|
1810
|
-
decoders.GetActivityResponse?.(response.body);
|
|
1811
|
-
return { ...response.body, metadata: response.metadata };
|
|
1812
|
-
}
|
|
1813
|
-
async updateActivityPartial(request) {
|
|
1814
|
-
const pathParams = {
|
|
1815
|
-
activity_id: request?.activity_id,
|
|
1816
|
-
};
|
|
1817
|
-
const body = {
|
|
1818
|
-
unset: request?.unset,
|
|
1819
|
-
set: request?.set,
|
|
1820
|
-
};
|
|
1821
|
-
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/activities/{activity_id}', pathParams, undefined, body, 'application/json');
|
|
1822
|
-
decoders.UpdateActivityPartialResponse?.(response.body);
|
|
1823
|
-
return { ...response.body, metadata: response.metadata };
|
|
1824
|
-
}
|
|
1825
|
-
async updateActivity(request) {
|
|
1826
|
-
const pathParams = {
|
|
1827
|
-
activity_id: request?.activity_id,
|
|
1828
|
-
};
|
|
1829
|
-
const body = {
|
|
1830
|
-
expires_at: request?.expires_at,
|
|
1831
|
-
poll_id: request?.poll_id,
|
|
1832
|
-
text: request?.text,
|
|
1833
|
-
visibility: request?.visibility,
|
|
1834
|
-
attachments: request?.attachments,
|
|
1835
|
-
filter_tags: request?.filter_tags,
|
|
1836
|
-
interest_tags: request?.interest_tags,
|
|
1837
|
-
custom: request?.custom,
|
|
1838
|
-
location: request?.location,
|
|
1839
|
-
};
|
|
1840
|
-
const response = await this.apiClient.sendRequest('PUT', '/api/v2/feeds/activities/{activity_id}', pathParams, undefined, body, 'application/json');
|
|
1841
|
-
decoders.UpdateActivityResponse?.(response.body);
|
|
1842
|
-
return { ...response.body, metadata: response.metadata };
|
|
1843
|
-
}
|
|
1844
1810
|
async deleteBookmark(request) {
|
|
1845
1811
|
const queryParams = {
|
|
1846
1812
|
folder_id: request?.folder_id,
|
|
@@ -1879,6 +1845,21 @@ class FeedsApi {
|
|
|
1879
1845
|
decoders.AddBookmarkResponse?.(response.body);
|
|
1880
1846
|
return { ...response.body, metadata: response.metadata };
|
|
1881
1847
|
}
|
|
1848
|
+
async activityFeedback(request) {
|
|
1849
|
+
const pathParams = {
|
|
1850
|
+
activity_id: request?.activity_id,
|
|
1851
|
+
};
|
|
1852
|
+
const body = {
|
|
1853
|
+
hide: request?.hide,
|
|
1854
|
+
mute_user: request?.mute_user,
|
|
1855
|
+
reason: request?.reason,
|
|
1856
|
+
report: request?.report,
|
|
1857
|
+
show_less: request?.show_less,
|
|
1858
|
+
};
|
|
1859
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/activities/{activity_id}/feedback', pathParams, undefined, body, 'application/json');
|
|
1860
|
+
decoders.ActivityFeedbackResponse?.(response.body);
|
|
1861
|
+
return { ...response.body, metadata: response.metadata };
|
|
1862
|
+
}
|
|
1882
1863
|
async castPollVote(request) {
|
|
1883
1864
|
const pathParams = {
|
|
1884
1865
|
activity_id: request?.activity_id,
|
|
@@ -1941,6 +1922,56 @@ class FeedsApi {
|
|
|
1941
1922
|
decoders.DeleteActivityReactionResponse?.(response.body);
|
|
1942
1923
|
return { ...response.body, metadata: response.metadata };
|
|
1943
1924
|
}
|
|
1925
|
+
async deleteActivity(request) {
|
|
1926
|
+
const queryParams = {
|
|
1927
|
+
hard_delete: request?.hard_delete,
|
|
1928
|
+
};
|
|
1929
|
+
const pathParams = {
|
|
1930
|
+
id: request?.id,
|
|
1931
|
+
};
|
|
1932
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/activities/{id}', pathParams, queryParams);
|
|
1933
|
+
decoders.DeleteActivityResponse?.(response.body);
|
|
1934
|
+
return { ...response.body, metadata: response.metadata };
|
|
1935
|
+
}
|
|
1936
|
+
async getActivity(request) {
|
|
1937
|
+
const pathParams = {
|
|
1938
|
+
id: request?.id,
|
|
1939
|
+
};
|
|
1940
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/activities/{id}', pathParams, undefined);
|
|
1941
|
+
decoders.GetActivityResponse?.(response.body);
|
|
1942
|
+
return { ...response.body, metadata: response.metadata };
|
|
1943
|
+
}
|
|
1944
|
+
async updateActivityPartial(request) {
|
|
1945
|
+
const pathParams = {
|
|
1946
|
+
id: request?.id,
|
|
1947
|
+
};
|
|
1948
|
+
const body = {
|
|
1949
|
+
unset: request?.unset,
|
|
1950
|
+
set: request?.set,
|
|
1951
|
+
};
|
|
1952
|
+
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/activities/{id}', pathParams, undefined, body, 'application/json');
|
|
1953
|
+
decoders.UpdateActivityPartialResponse?.(response.body);
|
|
1954
|
+
return { ...response.body, metadata: response.metadata };
|
|
1955
|
+
}
|
|
1956
|
+
async updateActivity(request) {
|
|
1957
|
+
const pathParams = {
|
|
1958
|
+
id: request?.id,
|
|
1959
|
+
};
|
|
1960
|
+
const body = {
|
|
1961
|
+
expires_at: request?.expires_at,
|
|
1962
|
+
poll_id: request?.poll_id,
|
|
1963
|
+
text: request?.text,
|
|
1964
|
+
visibility: request?.visibility,
|
|
1965
|
+
attachments: request?.attachments,
|
|
1966
|
+
filter_tags: request?.filter_tags,
|
|
1967
|
+
interest_tags: request?.interest_tags,
|
|
1968
|
+
custom: request?.custom,
|
|
1969
|
+
location: request?.location,
|
|
1970
|
+
};
|
|
1971
|
+
const response = await this.apiClient.sendRequest('PUT', '/api/v2/feeds/activities/{id}', pathParams, undefined, body, 'application/json');
|
|
1972
|
+
decoders.UpdateActivityResponse?.(response.body);
|
|
1973
|
+
return { ...response.body, metadata: response.metadata };
|
|
1974
|
+
}
|
|
1944
1975
|
async queryBookmarkFolders(request) {
|
|
1945
1976
|
const body = {
|
|
1946
1977
|
limit: request?.limit,
|
|
@@ -2036,49 +2067,52 @@ class FeedsApi {
|
|
|
2036
2067
|
return { ...response.body, metadata: response.metadata };
|
|
2037
2068
|
}
|
|
2038
2069
|
async deleteComment(request) {
|
|
2070
|
+
const queryParams = {
|
|
2071
|
+
hard_delete: request?.hard_delete,
|
|
2072
|
+
};
|
|
2039
2073
|
const pathParams = {
|
|
2040
|
-
|
|
2074
|
+
id: request?.id,
|
|
2041
2075
|
};
|
|
2042
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{
|
|
2076
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{id}', pathParams, queryParams);
|
|
2043
2077
|
decoders.DeleteCommentResponse?.(response.body);
|
|
2044
2078
|
return { ...response.body, metadata: response.metadata };
|
|
2045
2079
|
}
|
|
2046
2080
|
async getComment(request) {
|
|
2047
2081
|
const pathParams = {
|
|
2048
|
-
|
|
2082
|
+
id: request?.id,
|
|
2049
2083
|
};
|
|
2050
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{
|
|
2084
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{id}', pathParams, undefined);
|
|
2051
2085
|
decoders.GetCommentResponse?.(response.body);
|
|
2052
2086
|
return { ...response.body, metadata: response.metadata };
|
|
2053
2087
|
}
|
|
2054
2088
|
async updateComment(request) {
|
|
2055
2089
|
const pathParams = {
|
|
2056
|
-
|
|
2090
|
+
id: request?.id,
|
|
2057
2091
|
};
|
|
2058
2092
|
const body = {
|
|
2059
2093
|
comment: request?.comment,
|
|
2060
2094
|
custom: request?.custom,
|
|
2061
2095
|
};
|
|
2062
|
-
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/comments/{
|
|
2096
|
+
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/comments/{id}', pathParams, undefined, body, 'application/json');
|
|
2063
2097
|
decoders.UpdateCommentResponse?.(response.body);
|
|
2064
2098
|
return { ...response.body, metadata: response.metadata };
|
|
2065
2099
|
}
|
|
2066
2100
|
async addCommentReaction(request) {
|
|
2067
2101
|
const pathParams = {
|
|
2068
|
-
|
|
2102
|
+
id: request?.id,
|
|
2069
2103
|
};
|
|
2070
2104
|
const body = {
|
|
2071
2105
|
type: request?.type,
|
|
2072
2106
|
create_notification_activity: request?.create_notification_activity,
|
|
2073
2107
|
custom: request?.custom,
|
|
2074
2108
|
};
|
|
2075
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{
|
|
2109
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{id}/reactions', pathParams, undefined, body, 'application/json');
|
|
2076
2110
|
decoders.AddCommentReactionResponse?.(response.body);
|
|
2077
2111
|
return { ...response.body, metadata: response.metadata };
|
|
2078
2112
|
}
|
|
2079
2113
|
async queryCommentReactions(request) {
|
|
2080
2114
|
const pathParams = {
|
|
2081
|
-
|
|
2115
|
+
id: request?.id,
|
|
2082
2116
|
};
|
|
2083
2117
|
const body = {
|
|
2084
2118
|
limit: request?.limit,
|
|
@@ -2087,16 +2121,16 @@ class FeedsApi {
|
|
|
2087
2121
|
sort: request?.sort,
|
|
2088
2122
|
filter: request?.filter,
|
|
2089
2123
|
};
|
|
2090
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{
|
|
2124
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/comments/{id}/reactions/query', pathParams, undefined, body, 'application/json');
|
|
2091
2125
|
decoders.QueryCommentReactionsResponse?.(response.body);
|
|
2092
2126
|
return { ...response.body, metadata: response.metadata };
|
|
2093
2127
|
}
|
|
2094
2128
|
async deleteCommentReaction(request) {
|
|
2095
2129
|
const pathParams = {
|
|
2096
|
-
|
|
2130
|
+
id: request?.id,
|
|
2097
2131
|
type: request?.type,
|
|
2098
2132
|
};
|
|
2099
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{
|
|
2133
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/comments/{id}/reactions/{type}', pathParams, undefined);
|
|
2100
2134
|
decoders.DeleteCommentReactionResponse?.(response.body);
|
|
2101
2135
|
return { ...response.body, metadata: response.metadata };
|
|
2102
2136
|
}
|
|
@@ -2110,9 +2144,9 @@ class FeedsApi {
|
|
|
2110
2144
|
next: request?.next,
|
|
2111
2145
|
};
|
|
2112
2146
|
const pathParams = {
|
|
2113
|
-
|
|
2147
|
+
id: request?.id,
|
|
2114
2148
|
};
|
|
2115
|
-
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{
|
|
2149
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/feeds/comments/{id}/replies', pathParams, queryParams);
|
|
2116
2150
|
decoders.GetCommentRepliesResponse?.(response.body);
|
|
2117
2151
|
return { ...response.body, metadata: response.metadata };
|
|
2118
2152
|
}
|
|
@@ -2161,7 +2195,6 @@ class FeedsApi {
|
|
|
2161
2195
|
feed_id: request?.feed_id,
|
|
2162
2196
|
};
|
|
2163
2197
|
const body = {
|
|
2164
|
-
created_by_id: request?.created_by_id,
|
|
2165
2198
|
custom: request?.custom,
|
|
2166
2199
|
};
|
|
2167
2200
|
const response = await this.apiClient.sendRequest('PUT', '/api/v2/feeds/feed_groups/{feed_group_id}/feeds/{feed_id}', pathParams, undefined, body, 'application/json');
|
|
@@ -2177,6 +2210,7 @@ class FeedsApi {
|
|
|
2177
2210
|
mark_all_read: request?.mark_all_read,
|
|
2178
2211
|
mark_all_seen: request?.mark_all_seen,
|
|
2179
2212
|
mark_read: request?.mark_read,
|
|
2213
|
+
mark_seen: request?.mark_seen,
|
|
2180
2214
|
mark_watched: request?.mark_watched,
|
|
2181
2215
|
};
|
|
2182
2216
|
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');
|
|
@@ -2287,7 +2321,7 @@ class FeedsApi {
|
|
|
2287
2321
|
decoders.CreateFeedsBatchResponse?.(response.body);
|
|
2288
2322
|
return { ...response.body, metadata: response.metadata };
|
|
2289
2323
|
}
|
|
2290
|
-
async
|
|
2324
|
+
async _queryFeeds(request) {
|
|
2291
2325
|
const queryParams = {
|
|
2292
2326
|
connection_id: request?.connection_id,
|
|
2293
2327
|
};
|
|
@@ -2330,8 +2364,8 @@ class FeedsApi {
|
|
|
2330
2364
|
}
|
|
2331
2365
|
async acceptFollow(request) {
|
|
2332
2366
|
const body = {
|
|
2333
|
-
|
|
2334
|
-
|
|
2367
|
+
source: request?.source,
|
|
2368
|
+
target: request?.target,
|
|
2335
2369
|
follower_role: request?.follower_role,
|
|
2336
2370
|
};
|
|
2337
2371
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/follows/accept', undefined, undefined, body, 'application/json');
|
|
@@ -2360,8 +2394,8 @@ class FeedsApi {
|
|
|
2360
2394
|
}
|
|
2361
2395
|
async rejectFollow(request) {
|
|
2362
2396
|
const body = {
|
|
2363
|
-
|
|
2364
|
-
|
|
2397
|
+
source: request?.source,
|
|
2398
|
+
target: request?.target,
|
|
2365
2399
|
};
|
|
2366
2400
|
const response = await this.apiClient.sendRequest('POST', '/api/v2/feeds/follows/reject', undefined, undefined, body, 'application/json');
|
|
2367
2401
|
decoders.RejectFollowResponse?.(response.body);
|
|
@@ -3741,1624 +3775,1692 @@ const decodeWSEvent = (data) => {
|
|
|
3741
3775
|
}
|
|
3742
3776
|
};
|
|
3743
3777
|
|
|
3744
|
-
class
|
|
3745
|
-
constructor(
|
|
3746
|
-
this.
|
|
3747
|
-
this.group = group;
|
|
3748
|
-
this.id = id;
|
|
3778
|
+
class ModerationApi {
|
|
3779
|
+
constructor(apiClient) {
|
|
3780
|
+
this.apiClient = apiClient;
|
|
3749
3781
|
}
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3782
|
+
async ban(request) {
|
|
3783
|
+
const body = {
|
|
3784
|
+
target_user_id: request?.target_user_id,
|
|
3785
|
+
banned_by_id: request?.banned_by_id,
|
|
3786
|
+
channel_cid: request?.channel_cid,
|
|
3787
|
+
delete_messages: request?.delete_messages,
|
|
3788
|
+
ip_ban: request?.ip_ban,
|
|
3789
|
+
reason: request?.reason,
|
|
3790
|
+
shadow: request?.shadow,
|
|
3791
|
+
timeout: request?.timeout,
|
|
3792
|
+
banned_by: request?.banned_by,
|
|
3793
|
+
};
|
|
3794
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/ban', undefined, undefined, body, 'application/json');
|
|
3795
|
+
decoders.BanResponse?.(response.body);
|
|
3796
|
+
return { ...response.body, metadata: response.metadata };
|
|
3756
3797
|
}
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3798
|
+
async upsertConfig(request) {
|
|
3799
|
+
const body = {
|
|
3800
|
+
key: request?.key,
|
|
3801
|
+
async: request?.async,
|
|
3802
|
+
team: request?.team,
|
|
3803
|
+
ai_image_config: request?.ai_image_config,
|
|
3804
|
+
ai_text_config: request?.ai_text_config,
|
|
3805
|
+
ai_video_config: request?.ai_video_config,
|
|
3806
|
+
automod_platform_circumvention_config: request?.automod_platform_circumvention_config,
|
|
3807
|
+
automod_semantic_filters_config: request?.automod_semantic_filters_config,
|
|
3808
|
+
automod_toxicity_config: request?.automod_toxicity_config,
|
|
3809
|
+
aws_rekognition_config: request?.aws_rekognition_config,
|
|
3810
|
+
block_list_config: request?.block_list_config,
|
|
3811
|
+
bodyguard_config: request?.bodyguard_config,
|
|
3812
|
+
google_vision_config: request?.google_vision_config,
|
|
3813
|
+
rule_builder_config: request?.rule_builder_config,
|
|
3814
|
+
velocity_filter_config: request?.velocity_filter_config,
|
|
3815
|
+
video_call_rule_config: request?.video_call_rule_config,
|
|
3816
|
+
};
|
|
3817
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/config', undefined, undefined, body, 'application/json');
|
|
3818
|
+
decoders.UpsertConfigResponse?.(response.body);
|
|
3819
|
+
return { ...response.body, metadata: response.metadata };
|
|
3763
3820
|
}
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3821
|
+
async deleteConfig(request) {
|
|
3822
|
+
const queryParams = {
|
|
3823
|
+
team: request?.team,
|
|
3824
|
+
};
|
|
3825
|
+
const pathParams = {
|
|
3826
|
+
key: request?.key,
|
|
3827
|
+
};
|
|
3828
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
3829
|
+
decoders.DeleteModerationConfigResponse?.(response.body);
|
|
3830
|
+
return { ...response.body, metadata: response.metadata };
|
|
3770
3831
|
}
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3832
|
+
async getConfig(request) {
|
|
3833
|
+
const queryParams = {
|
|
3834
|
+
team: request?.team,
|
|
3835
|
+
};
|
|
3836
|
+
const pathParams = {
|
|
3837
|
+
key: request?.key,
|
|
3838
|
+
};
|
|
3839
|
+
const response = await this.apiClient.sendRequest('GET', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
3840
|
+
decoders.GetConfigResponse?.(response.body);
|
|
3841
|
+
return { ...response.body, metadata: response.metadata };
|
|
3777
3842
|
}
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3843
|
+
async queryModerationConfigs(request) {
|
|
3844
|
+
const body = {
|
|
3845
|
+
limit: request?.limit,
|
|
3846
|
+
next: request?.next,
|
|
3847
|
+
prev: request?.prev,
|
|
3848
|
+
sort: request?.sort,
|
|
3849
|
+
filter: request?.filter,
|
|
3850
|
+
};
|
|
3851
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/configs', undefined, undefined, body, 'application/json');
|
|
3852
|
+
decoders.QueryModerationConfigsResponse?.(response.body);
|
|
3853
|
+
return { ...response.body, metadata: response.metadata };
|
|
3784
3854
|
}
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3855
|
+
async flag(request) {
|
|
3856
|
+
const body = {
|
|
3857
|
+
entity_id: request?.entity_id,
|
|
3858
|
+
entity_type: request?.entity_type,
|
|
3859
|
+
entity_creator_id: request?.entity_creator_id,
|
|
3860
|
+
reason: request?.reason,
|
|
3861
|
+
custom: request?.custom,
|
|
3862
|
+
moderation_payload: request?.moderation_payload,
|
|
3863
|
+
};
|
|
3864
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/flag', undefined, undefined, body, 'application/json');
|
|
3865
|
+
decoders.FlagResponse?.(response.body);
|
|
3866
|
+
return { ...response.body, metadata: response.metadata };
|
|
3791
3867
|
}
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
...request,
|
|
3797
|
-
});
|
|
3798
|
-
}
|
|
3799
|
-
acceptFeedMemberInvite(request) {
|
|
3800
|
-
return this.feedsApi.acceptFeedMemberInvite({
|
|
3801
|
-
feed_id: this.id,
|
|
3802
|
-
feed_group_id: this.group,
|
|
3803
|
-
...request,
|
|
3804
|
-
});
|
|
3805
|
-
}
|
|
3806
|
-
queryFeedMembers(request) {
|
|
3807
|
-
return this.feedsApi.queryFeedMembers({
|
|
3808
|
-
feed_id: this.id,
|
|
3809
|
-
feed_group_id: this.group,
|
|
3810
|
-
...request,
|
|
3811
|
-
});
|
|
3812
|
-
}
|
|
3813
|
-
rejectFeedMemberInvite(request) {
|
|
3814
|
-
return this.feedsApi.rejectFeedMemberInvite({
|
|
3815
|
-
feed_id: this.id,
|
|
3816
|
-
feed_group_id: this.group,
|
|
3817
|
-
...request,
|
|
3818
|
-
});
|
|
3819
|
-
}
|
|
3820
|
-
stopWatching(request) {
|
|
3821
|
-
return this.feedsApi.stopWatchingFeed({
|
|
3822
|
-
feed_id: this.id,
|
|
3823
|
-
feed_group_id: this.group,
|
|
3824
|
-
...request,
|
|
3825
|
-
});
|
|
3826
|
-
}
|
|
3827
|
-
}
|
|
3828
|
-
|
|
3829
|
-
const addActivitiesToState = (newActivities, activities, position) => {
|
|
3830
|
-
let result;
|
|
3831
|
-
if (activities === undefined) {
|
|
3832
|
-
activities = [];
|
|
3833
|
-
result = {
|
|
3834
|
-
changed: true,
|
|
3835
|
-
activities,
|
|
3868
|
+
async mute(request) {
|
|
3869
|
+
const body = {
|
|
3870
|
+
target_ids: request?.target_ids,
|
|
3871
|
+
timeout: request?.timeout,
|
|
3836
3872
|
};
|
|
3873
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/mute', undefined, undefined, body, 'application/json');
|
|
3874
|
+
decoders.MuteResponse?.(response.body);
|
|
3875
|
+
return { ...response.body, metadata: response.metadata };
|
|
3837
3876
|
}
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3877
|
+
async queryReviewQueue(request) {
|
|
3878
|
+
const body = {
|
|
3879
|
+
limit: request?.limit,
|
|
3880
|
+
lock_count: request?.lock_count,
|
|
3881
|
+
lock_duration: request?.lock_duration,
|
|
3882
|
+
lock_items: request?.lock_items,
|
|
3883
|
+
next: request?.next,
|
|
3884
|
+
prev: request?.prev,
|
|
3885
|
+
stats_only: request?.stats_only,
|
|
3886
|
+
sort: request?.sort,
|
|
3887
|
+
filter: request?.filter,
|
|
3842
3888
|
};
|
|
3889
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/review_queue', undefined, undefined, body, 'application/json');
|
|
3890
|
+
decoders.QueryReviewQueueResponse?.(response.body);
|
|
3891
|
+
return { ...response.body, metadata: response.metadata };
|
|
3843
3892
|
}
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
...activities,
|
|
3857
|
-
...(position === 'end' ? newActivitiesDeduplicated : []),
|
|
3858
|
-
];
|
|
3859
|
-
result = { changed: true, activities: updatedActivities };
|
|
3860
|
-
}
|
|
3861
|
-
return result;
|
|
3862
|
-
};
|
|
3863
|
-
const updateActivityInState = (updatedActivityResponse, activities) => {
|
|
3864
|
-
const index = activities.findIndex((a) => a.id === updatedActivityResponse.id);
|
|
3865
|
-
if (index !== -1) {
|
|
3866
|
-
const newActivities = [...activities];
|
|
3867
|
-
const activity = activities[index];
|
|
3868
|
-
newActivities[index] = {
|
|
3869
|
-
...updatedActivityResponse,
|
|
3870
|
-
own_reactions: activity.own_reactions,
|
|
3871
|
-
own_bookmarks: activity.own_bookmarks,
|
|
3872
|
-
latest_reactions: activity.latest_reactions,
|
|
3873
|
-
reaction_groups: activity.reaction_groups,
|
|
3893
|
+
async submitAction(request) {
|
|
3894
|
+
const body = {
|
|
3895
|
+
action_type: request?.action_type,
|
|
3896
|
+
item_id: request?.item_id,
|
|
3897
|
+
ban: request?.ban,
|
|
3898
|
+
custom: request?.custom,
|
|
3899
|
+
delete_activity: request?.delete_activity,
|
|
3900
|
+
delete_message: request?.delete_message,
|
|
3901
|
+
delete_reaction: request?.delete_reaction,
|
|
3902
|
+
delete_user: request?.delete_user,
|
|
3903
|
+
mark_reviewed: request?.mark_reviewed,
|
|
3904
|
+
unban: request?.unban,
|
|
3874
3905
|
};
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
return { changed: false, activities };
|
|
3879
|
-
}
|
|
3880
|
-
};
|
|
3881
|
-
const removeActivityFromState = (activityResponse, activities) => {
|
|
3882
|
-
const index = activities.findIndex((a) => a.id === activityResponse.id);
|
|
3883
|
-
if (index !== -1) {
|
|
3884
|
-
const newActivities = [...activities];
|
|
3885
|
-
newActivities.splice(index, 1);
|
|
3886
|
-
return { changed: true, activities: newActivities };
|
|
3887
|
-
}
|
|
3888
|
-
else {
|
|
3889
|
-
return { changed: false, activities };
|
|
3906
|
+
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/submit_action', undefined, undefined, body, 'application/json');
|
|
3907
|
+
decoders.SubmitActionResponse?.(response.body);
|
|
3908
|
+
return { ...response.body, metadata: response.metadata };
|
|
3890
3909
|
}
|
|
3891
|
-
}
|
|
3910
|
+
}
|
|
3892
3911
|
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
if (index !== -1) {
|
|
3896
|
-
const newActivities = [...activities];
|
|
3897
|
-
newActivities[index] = updatedActivity;
|
|
3898
|
-
return { changed: true, activities: newActivities };
|
|
3899
|
-
}
|
|
3900
|
-
else {
|
|
3901
|
-
return { changed: false, activities };
|
|
3902
|
-
}
|
|
3903
|
-
};
|
|
3904
|
-
const addReactionToActivity = (event, activity, isCurrentUser) => {
|
|
3905
|
-
// Update own_reactions if the reaction is from the current user
|
|
3906
|
-
const ownReactions = [...(activity.own_reactions || [])];
|
|
3907
|
-
if (isCurrentUser) {
|
|
3908
|
-
ownReactions.push(event.reaction);
|
|
3909
|
-
}
|
|
3910
|
-
return {
|
|
3911
|
-
...activity,
|
|
3912
|
-
own_reactions: ownReactions,
|
|
3913
|
-
latest_reactions: event.activity.latest_reactions,
|
|
3914
|
-
reaction_groups: event.activity.reaction_groups,
|
|
3915
|
-
changed: true,
|
|
3916
|
-
};
|
|
3917
|
-
};
|
|
3918
|
-
const removeReactionFromActivity = (event, activity, isCurrentUser) => {
|
|
3919
|
-
// Update own_reactions if the reaction is from the current user
|
|
3920
|
-
const ownReactions = isCurrentUser
|
|
3921
|
-
? (activity.own_reactions || []).filter((r) => !(r.type === event.reaction.type &&
|
|
3922
|
-
r.user.id === event.reaction.user.id))
|
|
3923
|
-
: activity.own_reactions;
|
|
3924
|
-
return {
|
|
3925
|
-
...activity,
|
|
3926
|
-
own_reactions: ownReactions,
|
|
3927
|
-
latest_reactions: event.activity.latest_reactions,
|
|
3928
|
-
reaction_groups: event.activity.reaction_groups,
|
|
3929
|
-
changed: true,
|
|
3930
|
-
};
|
|
3931
|
-
};
|
|
3932
|
-
const addReactionToActivities = (event, activities, isCurrentUser) => {
|
|
3933
|
-
if (!activities) {
|
|
3934
|
-
return { changed: false, activities: [] };
|
|
3935
|
-
}
|
|
3936
|
-
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
3937
|
-
if (activityIndex === -1) {
|
|
3938
|
-
return { changed: false, activities };
|
|
3939
|
-
}
|
|
3940
|
-
const activity = activities[activityIndex];
|
|
3941
|
-
const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
|
|
3942
|
-
return updateActivityInActivities$1(updatedActivity, activities);
|
|
3943
|
-
};
|
|
3944
|
-
const removeReactionFromActivities = (event, activities, isCurrentUser) => {
|
|
3945
|
-
if (!activities) {
|
|
3946
|
-
return { changed: false, activities: [] };
|
|
3947
|
-
}
|
|
3948
|
-
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
3949
|
-
if (activityIndex === -1) {
|
|
3950
|
-
return { changed: false, activities };
|
|
3951
|
-
}
|
|
3952
|
-
const activity = activities[activityIndex];
|
|
3953
|
-
const updatedActivity = removeReactionFromActivity(event, activity, isCurrentUser);
|
|
3954
|
-
return updateActivityInActivities$1(updatedActivity, activities);
|
|
3955
|
-
};
|
|
3912
|
+
class ModerationClient extends ModerationApi {
|
|
3913
|
+
}
|
|
3956
3914
|
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
const
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
own_bookmarks: ownBookmarks,
|
|
3984
|
-
changed: true,
|
|
3985
|
-
};
|
|
3986
|
-
};
|
|
3987
|
-
const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
|
|
3988
|
-
// Update own_bookmarks if the bookmark is from the current user
|
|
3989
|
-
const ownBookmarks = isCurrentUser
|
|
3990
|
-
? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
|
|
3991
|
-
: activity.own_bookmarks;
|
|
3992
|
-
return {
|
|
3993
|
-
...activity,
|
|
3994
|
-
own_bookmarks: ownBookmarks,
|
|
3995
|
-
changed: true,
|
|
3996
|
-
};
|
|
3997
|
-
};
|
|
3998
|
-
const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
|
|
3999
|
-
// Update own_bookmarks if the bookmark is from the current user
|
|
4000
|
-
let ownBookmarks = activity.own_bookmarks || [];
|
|
4001
|
-
if (isCurrentUser) {
|
|
4002
|
-
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
|
|
4003
|
-
if (bookmarkIndex !== -1) {
|
|
4004
|
-
ownBookmarks = [...ownBookmarks];
|
|
4005
|
-
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
4006
|
-
}
|
|
4007
|
-
}
|
|
4008
|
-
return {
|
|
4009
|
-
...activity,
|
|
4010
|
-
own_bookmarks: ownBookmarks,
|
|
4011
|
-
changed: true,
|
|
4012
|
-
};
|
|
4013
|
-
};
|
|
4014
|
-
const addBookmarkToActivities = (event, activities, isCurrentUser) => {
|
|
4015
|
-
if (!activities) {
|
|
4016
|
-
return { changed: false, activities: [] };
|
|
4017
|
-
}
|
|
4018
|
-
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4019
|
-
if (activityIndex === -1) {
|
|
4020
|
-
return { changed: false, activities };
|
|
4021
|
-
}
|
|
4022
|
-
const activity = activities[activityIndex];
|
|
4023
|
-
const updatedActivity = addBookmarkToActivity(event, activity, isCurrentUser);
|
|
4024
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
4025
|
-
};
|
|
4026
|
-
const removeBookmarkFromActivities = (event, activities, isCurrentUser) => {
|
|
4027
|
-
if (!activities) {
|
|
4028
|
-
return { changed: false, activities: [] };
|
|
4029
|
-
}
|
|
4030
|
-
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4031
|
-
if (activityIndex === -1) {
|
|
4032
|
-
return { changed: false, activities };
|
|
4033
|
-
}
|
|
4034
|
-
const activity = activities[activityIndex];
|
|
4035
|
-
const updatedActivity = removeBookmarkFromActivity(event, activity, isCurrentUser);
|
|
4036
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
4037
|
-
};
|
|
4038
|
-
const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
4039
|
-
if (!activities) {
|
|
4040
|
-
return { changed: false, activities: [] };
|
|
4041
|
-
}
|
|
4042
|
-
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4043
|
-
if (activityIndex === -1) {
|
|
4044
|
-
return { changed: false, activities };
|
|
4045
|
-
}
|
|
4046
|
-
const activity = activities[activityIndex];
|
|
4047
|
-
const updatedActivity = updateBookmarkInActivity(event, activity, isCurrentUser);
|
|
4048
|
-
return updateActivityInActivities(updatedActivity, activities);
|
|
4049
|
-
};
|
|
4050
|
-
|
|
4051
|
-
const isFeedResponse = (follow) => {
|
|
4052
|
-
return 'created_by' in follow;
|
|
4053
|
-
};
|
|
4054
|
-
const handleFollowCreated = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4055
|
-
// filter non-accepted follows (the way getOrCreate does by default)
|
|
4056
|
-
if (follow.status !== 'accepted') {
|
|
4057
|
-
return { changed: false, data: currentState };
|
|
4058
|
-
}
|
|
4059
|
-
let newState = { ...currentState };
|
|
4060
|
-
// this feed followed someone
|
|
4061
|
-
if (follow.source_feed.fid === currentFeedId) {
|
|
4062
|
-
newState = {
|
|
4063
|
-
...newState,
|
|
4064
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4065
|
-
...follow.source_feed,
|
|
3915
|
+
const isPollUpdatedEvent = (e) => e.type === 'feeds.poll.updated';
|
|
3916
|
+
const isPollClosedEventEvent = (e) => e.type === 'feeds.poll.closed';
|
|
3917
|
+
const isPollVoteCastedEvent = (e) => e.type === 'feeds.poll.vote_casted';
|
|
3918
|
+
const isPollVoteChangedEvent = (e) => e.type === 'feeds.poll.vote_changed';
|
|
3919
|
+
const isPollVoteRemovedEvent = (e) => e.type === 'feeds.poll.vote_removed';
|
|
3920
|
+
const isVoteAnswer = (vote) => !!vote?.answer_text;
|
|
3921
|
+
class StreamPoll {
|
|
3922
|
+
constructor({ client, poll }) {
|
|
3923
|
+
this.getInitialStateFromPollResponse = (poll) => {
|
|
3924
|
+
const { own_votes, id, ...pollResponseForState } = poll;
|
|
3925
|
+
const { ownAnswer, ownVotes } = own_votes?.reduce((acc, voteOrAnswer) => {
|
|
3926
|
+
if (isVoteAnswer(voteOrAnswer)) {
|
|
3927
|
+
acc.ownAnswer = voteOrAnswer;
|
|
3928
|
+
}
|
|
3929
|
+
else {
|
|
3930
|
+
acc.ownVotes.push(voteOrAnswer);
|
|
3931
|
+
}
|
|
3932
|
+
return acc;
|
|
3933
|
+
}, { ownVotes: [] }) ?? { ownVotes: [] };
|
|
3934
|
+
return {
|
|
3935
|
+
...pollResponseForState,
|
|
3936
|
+
last_activity_at: new Date(),
|
|
3937
|
+
max_voted_option_ids: getMaxVotedOptionIds(pollResponseForState.vote_counts_by_option),
|
|
3938
|
+
own_answer: ownAnswer,
|
|
3939
|
+
own_votes_by_option_id: getOwnVotesByOptionId(ownVotes),
|
|
3940
|
+
};
|
|
4066
3941
|
};
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
newState.following = [follow, ...currentState.following];
|
|
4070
|
-
}
|
|
4071
|
-
}
|
|
4072
|
-
else if (
|
|
4073
|
-
// someone followed this feed
|
|
4074
|
-
follow.target_feed.fid === currentFeedId) {
|
|
4075
|
-
const source = follow.source_feed;
|
|
4076
|
-
newState = {
|
|
4077
|
-
...newState,
|
|
4078
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4079
|
-
...follow.target_feed,
|
|
3942
|
+
this.reinitializeState = (poll) => {
|
|
3943
|
+
this.state.partialNext(this.getInitialStateFromPollResponse(poll));
|
|
4080
3944
|
};
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
};
|
|
4093
|
-
const handleFollowDeleted = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4094
|
-
let newState = { ...currentState };
|
|
4095
|
-
// this feed unfollowed someone
|
|
4096
|
-
if (follow.source_feed.fid === currentFeedId) {
|
|
4097
|
-
newState = {
|
|
4098
|
-
...newState,
|
|
4099
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4100
|
-
...follow.source_feed,
|
|
3945
|
+
this.handlePollUpdated = (event) => {
|
|
3946
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
3947
|
+
return;
|
|
3948
|
+
if (!isPollUpdatedEvent(event))
|
|
3949
|
+
return;
|
|
3950
|
+
const { id, ...pollData } = event.poll;
|
|
3951
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3952
|
+
this.state.partialNext({
|
|
3953
|
+
...pollData,
|
|
3954
|
+
last_activity_at: new Date(event.created_at),
|
|
3955
|
+
});
|
|
4101
3956
|
};
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
newState = {
|
|
4112
|
-
...newState,
|
|
4113
|
-
// Update FeedResponse fields, that has the new follower/following count
|
|
4114
|
-
...follow.target_feed,
|
|
3957
|
+
this.handlePollClosed = (event) => {
|
|
3958
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
3959
|
+
return;
|
|
3960
|
+
if (!isPollClosedEventEvent(event))
|
|
3961
|
+
return;
|
|
3962
|
+
this.state.partialNext({
|
|
3963
|
+
is_closed: true,
|
|
3964
|
+
last_activity_at: new Date(event.created_at),
|
|
3965
|
+
});
|
|
4115
3966
|
};
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4135
|
-
typeof cursor === 'string';
|
|
4136
|
-
const isCommentResponse = (entity) => {
|
|
4137
|
-
return typeof entity?.object_id === 'string';
|
|
4138
|
-
};
|
|
4139
|
-
const Constants = {
|
|
4140
|
-
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4141
|
-
};
|
|
4142
|
-
const uniqueArrayMerge = (existingArray, arrayToMerge, getKey) => {
|
|
4143
|
-
const existing = new Set();
|
|
4144
|
-
existingArray.forEach((value) => {
|
|
4145
|
-
const key = getKey(value);
|
|
4146
|
-
existing.add(key);
|
|
4147
|
-
});
|
|
4148
|
-
const filteredArrayToMerge = arrayToMerge.filter((value) => {
|
|
4149
|
-
const key = getKey(value);
|
|
4150
|
-
return !existing.has(key);
|
|
4151
|
-
});
|
|
4152
|
-
return existingArray.concat(filteredArrayToMerge);
|
|
4153
|
-
};
|
|
4154
|
-
|
|
4155
|
-
const shouldUpdateState = ({ stateUpdateId, stateUpdateQueue, watch, }) => {
|
|
4156
|
-
if (!watch) {
|
|
4157
|
-
return true;
|
|
4158
|
-
}
|
|
4159
|
-
if (watch && stateUpdateQueue.has(stateUpdateId)) {
|
|
4160
|
-
stateUpdateQueue.delete(stateUpdateId);
|
|
4161
|
-
return false;
|
|
4162
|
-
}
|
|
4163
|
-
stateUpdateQueue.add(stateUpdateId);
|
|
4164
|
-
return true;
|
|
4165
|
-
};
|
|
4166
|
-
const getStateUpdateQueueIdForFollow = (follow) => {
|
|
4167
|
-
return `follow${follow.source_feed.fid}-${follow.target_feed.fid}`;
|
|
4168
|
-
};
|
|
4169
|
-
const getStateUpdateQueueIdForUnfollow = (follow) => {
|
|
4170
|
-
return `unfollow${follow.source_feed.fid}-${follow.target_feed.fid}`;
|
|
4171
|
-
};
|
|
4172
|
-
|
|
4173
|
-
class Feed extends FeedApi {
|
|
4174
|
-
constructor(client, groupId, id, data, watch = false) {
|
|
4175
|
-
super(client, groupId, id);
|
|
4176
|
-
this.stateUpdateQueue = new Set();
|
|
4177
|
-
this.eventHandlers = {
|
|
4178
|
-
'feeds.activity.added': (event) => {
|
|
4179
|
-
const currentActivities = this.currentState.activities;
|
|
4180
|
-
const result = addActivitiesToState([event.activity], currentActivities, 'start');
|
|
4181
|
-
if (result.changed) {
|
|
4182
|
-
this.client.hydratePollCache([event.activity]);
|
|
4183
|
-
this.state.partialNext({ activities: result.activities });
|
|
4184
|
-
}
|
|
4185
|
-
},
|
|
4186
|
-
'feeds.activity.deleted': (event) => {
|
|
4187
|
-
const currentActivities = this.currentState.activities;
|
|
4188
|
-
if (currentActivities) {
|
|
4189
|
-
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4190
|
-
if (result.changed) {
|
|
4191
|
-
this.state.partialNext({ activities: result.activities });
|
|
4192
|
-
}
|
|
3967
|
+
this.handleVoteCasted = (event) => {
|
|
3968
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
3969
|
+
return;
|
|
3970
|
+
if (!isPollVoteCastedEvent(event))
|
|
3971
|
+
return;
|
|
3972
|
+
const currentState = this.data;
|
|
3973
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
3974
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
3975
|
+
let latestAnswers = [...currentState.latest_answers];
|
|
3976
|
+
let ownAnswer = currentState.own_answer;
|
|
3977
|
+
const ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
3978
|
+
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
3979
|
+
if (isOwnVote) {
|
|
3980
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3981
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
3982
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3983
|
+
ownAnswer = event.poll_vote;
|
|
4193
3984
|
}
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4198
|
-
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4199
|
-
const result = addReactionToActivities(event, currentActivities, isCurrentUser);
|
|
4200
|
-
if (result.changed) {
|
|
4201
|
-
this.state.partialNext({ activities: result.activities });
|
|
3985
|
+
else if (event.poll_vote.option_id) {
|
|
3986
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3987
|
+
ownVotesByOptionId[event.poll_vote.option_id] = event.poll_vote;
|
|
4202
3988
|
}
|
|
4203
|
-
}
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
3989
|
+
}
|
|
3990
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3991
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
3992
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
3993
|
+
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
3994
|
+
}
|
|
3995
|
+
else {
|
|
3996
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
3997
|
+
}
|
|
3998
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
3999
|
+
this.state.partialNext({
|
|
4000
|
+
answers_count,
|
|
4001
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4002
|
+
latest_votes_by_option,
|
|
4003
|
+
vote_count,
|
|
4004
|
+
vote_counts_by_option,
|
|
4005
|
+
latest_answers: latestAnswers,
|
|
4006
|
+
last_activity_at: new Date(event.created_at),
|
|
4007
|
+
own_answer: ownAnswer,
|
|
4008
|
+
own_votes_by_option_id: ownVotesByOptionId,
|
|
4009
|
+
max_voted_option_ids: maxVotedOptionIds,
|
|
4010
|
+
});
|
|
4011
|
+
};
|
|
4012
|
+
this.handleVoteChanged = (event) => {
|
|
4013
|
+
// this event is triggered only when event.poll.enforce_unique_vote === true
|
|
4014
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
4015
|
+
return;
|
|
4016
|
+
if (!isPollVoteChangedEvent(event))
|
|
4017
|
+
return;
|
|
4018
|
+
const currentState = this.data;
|
|
4019
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
4020
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4021
|
+
let latestAnswers = [...currentState.latest_answers];
|
|
4022
|
+
let ownAnswer = currentState.own_answer;
|
|
4023
|
+
let ownVotesByOptionId = currentState.own_votes_by_option_id;
|
|
4024
|
+
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
4025
|
+
if (isOwnVote) {
|
|
4026
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4027
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
4028
|
+
latestAnswers = [
|
|
4029
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4030
|
+
event.poll_vote,
|
|
4031
|
+
...latestAnswers.filter((answer) => answer.id !== event.poll_vote.id),
|
|
4032
|
+
];
|
|
4033
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4034
|
+
ownAnswer = event.poll_vote;
|
|
4211
4035
|
}
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
if (currentActivities) {
|
|
4217
|
-
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4218
|
-
if (result.changed) {
|
|
4219
|
-
this.state.partialNext({ activities: result.activities });
|
|
4036
|
+
else if (event.poll_vote.option_id) {
|
|
4037
|
+
if (event.poll.enforce_unique_vote) {
|
|
4038
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4039
|
+
ownVotesByOptionId = { [event.poll_vote.option_id]: event.poll_vote };
|
|
4220
4040
|
}
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4041
|
+
else {
|
|
4042
|
+
ownVotesByOptionId = Object.entries(ownVotesByOptionId).reduce((acc, [optionId, vote]) => {
|
|
4043
|
+
if (optionId !== event.poll_vote.option_id &&
|
|
4044
|
+
vote.id === event.poll_vote.id) {
|
|
4045
|
+
return acc;
|
|
4046
|
+
}
|
|
4047
|
+
acc[optionId] = vote;
|
|
4048
|
+
return acc;
|
|
4049
|
+
}, {});
|
|
4050
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4051
|
+
ownVotesByOptionId[event.poll_vote.option_id] = event.poll_vote;
|
|
4052
|
+
}
|
|
4053
|
+
if (ownAnswer?.id === event.poll_vote.id) {
|
|
4054
|
+
ownAnswer = undefined;
|
|
4230
4055
|
}
|
|
4056
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4231
4057
|
}
|
|
4232
|
-
|
|
4233
|
-
'feeds.bookmark.added': this.handleBookmarkAdded.bind(this),
|
|
4234
|
-
'feeds.bookmark.deleted': this.handleBookmarkDeleted.bind(this),
|
|
4235
|
-
'feeds.bookmark.updated': this.handleBookmarkUpdated.bind(this),
|
|
4236
|
-
'feeds.bookmark_folder.deleted': Feed.noop,
|
|
4237
|
-
'feeds.bookmark_folder.updated': Feed.noop,
|
|
4238
|
-
'feeds.comment.added': (event) => {
|
|
4239
|
-
const { comment } = event;
|
|
4240
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4241
|
-
this.state.next((currentState) => {
|
|
4242
|
-
const entityState = currentState.comments_by_entity_id[forId];
|
|
4243
|
-
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4244
|
-
if (entityState?.pagination?.sort === 'last' &&
|
|
4245
|
-
!checkHasAnotherPage(entityState.comments, entityState?.pagination.next)) {
|
|
4246
|
-
newComments.unshift(comment);
|
|
4247
|
-
}
|
|
4248
|
-
else if (entityState?.pagination?.sort === 'first') {
|
|
4249
|
-
newComments.push(comment);
|
|
4250
|
-
}
|
|
4251
|
-
else {
|
|
4252
|
-
// no other sorting option is supported yet
|
|
4253
|
-
return currentState;
|
|
4254
|
-
}
|
|
4255
|
-
return {
|
|
4256
|
-
...currentState,
|
|
4257
|
-
comments_by_entity_id: {
|
|
4258
|
-
...currentState.comments_by_entity_id,
|
|
4259
|
-
[forId]: {
|
|
4260
|
-
...currentState.comments_by_entity_id[forId],
|
|
4261
|
-
comments: newComments,
|
|
4262
|
-
},
|
|
4263
|
-
},
|
|
4264
|
-
};
|
|
4265
|
-
});
|
|
4266
|
-
},
|
|
4267
|
-
'feeds.comment.deleted': ({ comment }) => {
|
|
4268
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4269
|
-
this.state.next((currentState) => {
|
|
4270
|
-
const newCommentsByEntityId = {
|
|
4271
|
-
...currentState.comments_by_entity_id,
|
|
4272
|
-
[forId]: {
|
|
4273
|
-
...currentState.comments_by_entity_id[forId],
|
|
4274
|
-
},
|
|
4275
|
-
};
|
|
4276
|
-
const index = this.getCommentIndex(comment, currentState);
|
|
4277
|
-
if (newCommentsByEntityId?.[forId]?.comments?.length && index !== -1) {
|
|
4278
|
-
newCommentsByEntityId[forId].comments = [
|
|
4279
|
-
...newCommentsByEntityId[forId].comments,
|
|
4280
|
-
];
|
|
4281
|
-
newCommentsByEntityId[forId]?.comments?.splice(index, 1);
|
|
4282
|
-
}
|
|
4283
|
-
delete newCommentsByEntityId[comment.id];
|
|
4284
|
-
return {
|
|
4285
|
-
...currentState,
|
|
4286
|
-
comments_by_entity_id: newCommentsByEntityId,
|
|
4287
|
-
};
|
|
4288
|
-
});
|
|
4289
|
-
},
|
|
4290
|
-
'feeds.comment.updated': (event) => {
|
|
4291
|
-
const { comment } = event;
|
|
4292
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4293
|
-
this.state.next((currentState) => {
|
|
4294
|
-
const entityState = currentState.comments_by_entity_id[forId];
|
|
4295
|
-
if (!entityState?.comments?.length)
|
|
4296
|
-
return currentState;
|
|
4297
|
-
const index = this.getCommentIndex(comment, currentState);
|
|
4298
|
-
if (index === -1)
|
|
4299
|
-
return currentState;
|
|
4300
|
-
const newComments = [...entityState.comments];
|
|
4301
|
-
newComments[index] = comment;
|
|
4302
|
-
return {
|
|
4303
|
-
...currentState,
|
|
4304
|
-
comments_by_entity_id: {
|
|
4305
|
-
...currentState.comments_by_entity_id,
|
|
4306
|
-
[forId]: {
|
|
4307
|
-
...currentState.comments_by_entity_id[forId],
|
|
4308
|
-
comments: newComments,
|
|
4309
|
-
},
|
|
4310
|
-
},
|
|
4311
|
-
};
|
|
4312
|
-
});
|
|
4313
|
-
},
|
|
4314
|
-
'feeds.feed.created': Feed.noop,
|
|
4315
|
-
'feeds.feed.deleted': Feed.noop,
|
|
4316
|
-
'feeds.feed.updated': (event) => {
|
|
4317
|
-
this.state.partialNext({ ...event.feed });
|
|
4318
|
-
},
|
|
4319
|
-
'feeds.feed_group.changed': Feed.noop,
|
|
4320
|
-
'feeds.feed_group.deleted': Feed.noop,
|
|
4321
|
-
'feeds.follow.created': (event) => {
|
|
4322
|
-
this.handleFollowCreated(event.follow);
|
|
4323
|
-
},
|
|
4324
|
-
'feeds.follow.deleted': (event) => {
|
|
4325
|
-
this.handleFollowDeleted(event.follow);
|
|
4326
|
-
},
|
|
4327
|
-
'feeds.follow.updated': (_event) => {
|
|
4328
|
-
handleFollowUpdated(this.currentState);
|
|
4329
|
-
},
|
|
4330
|
-
'feeds.comment.reaction.added': this.handleCommentReactionEvent.bind(this),
|
|
4331
|
-
'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
|
|
4332
|
-
'feeds.comment.reaction.updated': Feed.noop,
|
|
4333
|
-
'feeds.feed_member.added': (event) => {
|
|
4334
|
-
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4335
|
-
this.state.next((currentState) => {
|
|
4336
|
-
let newState;
|
|
4337
|
-
if (typeof currentState.members !== 'undefined') {
|
|
4338
|
-
newState ?? (newState = {
|
|
4339
|
-
...currentState,
|
|
4340
|
-
});
|
|
4341
|
-
newState.members = [event.member, ...currentState.members];
|
|
4342
|
-
}
|
|
4343
|
-
if (connectedUser?.id === event.member.user.id) {
|
|
4344
|
-
newState ?? (newState = {
|
|
4345
|
-
...currentState,
|
|
4346
|
-
});
|
|
4347
|
-
newState.own_membership = event.member;
|
|
4348
|
-
}
|
|
4349
|
-
return newState ?? currentState;
|
|
4350
|
-
});
|
|
4351
|
-
},
|
|
4352
|
-
'feeds.feed_member.removed': (event) => {
|
|
4353
|
-
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4354
|
-
this.state.next((currentState) => {
|
|
4355
|
-
const newState = {
|
|
4356
|
-
...currentState,
|
|
4357
|
-
members: currentState.members?.filter((member) => member.user.id !== event.user?.id),
|
|
4358
|
-
};
|
|
4359
|
-
if (connectedUser?.id === event.member_id) {
|
|
4360
|
-
delete newState.own_membership;
|
|
4361
|
-
}
|
|
4362
|
-
return newState;
|
|
4363
|
-
});
|
|
4364
|
-
},
|
|
4365
|
-
'feeds.feed_member.updated': (event) => {
|
|
4366
|
-
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4367
|
-
this.state.next((currentState) => {
|
|
4368
|
-
const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
|
|
4369
|
-
let newState;
|
|
4370
|
-
if (memberIndex !== -1) {
|
|
4371
|
-
// if there's an index, there's a member to update
|
|
4372
|
-
const newMembers = [...currentState.members];
|
|
4373
|
-
newMembers[memberIndex] = event.member;
|
|
4374
|
-
newState ?? (newState = {
|
|
4375
|
-
...currentState,
|
|
4376
|
-
});
|
|
4377
|
-
newState.members = newMembers;
|
|
4378
|
-
}
|
|
4379
|
-
if (connectedUser?.id === event.member.user.id) {
|
|
4380
|
-
newState ?? (newState = {
|
|
4381
|
-
...currentState,
|
|
4382
|
-
});
|
|
4383
|
-
newState.own_membership = event.member;
|
|
4384
|
-
}
|
|
4385
|
-
return newState ?? currentState;
|
|
4386
|
-
});
|
|
4387
|
-
},
|
|
4388
|
-
'feeds.notification_feed.updated': (event) => {
|
|
4389
|
-
console.info('notification feed updated', event);
|
|
4390
|
-
// TODO: handle notification feed updates
|
|
4391
|
-
},
|
|
4392
|
-
// the poll events should be removed from here
|
|
4393
|
-
'feeds.poll.closed': Feed.noop,
|
|
4394
|
-
'feeds.poll.deleted': Feed.noop,
|
|
4395
|
-
'feeds.poll.updated': Feed.noop,
|
|
4396
|
-
'feeds.poll.vote_casted': Feed.noop,
|
|
4397
|
-
'feeds.poll.vote_changed': Feed.noop,
|
|
4398
|
-
'feeds.poll.vote_removed': Feed.noop,
|
|
4399
|
-
'feeds.activity.pinned': Feed.noop,
|
|
4400
|
-
'feeds.activity.unpinned': Feed.noop,
|
|
4401
|
-
'feeds.activity.marked': Feed.noop,
|
|
4402
|
-
'moderation.custom_action': Feed.noop,
|
|
4403
|
-
'moderation.flagged': Feed.noop,
|
|
4404
|
-
'moderation.mark_reviewed': Feed.noop,
|
|
4405
|
-
'health.check': Feed.noop,
|
|
4406
|
-
'app.updated': Feed.noop,
|
|
4407
|
-
'user.banned': Feed.noop,
|
|
4408
|
-
'user.deactivated': Feed.noop,
|
|
4409
|
-
'user.muted': Feed.noop,
|
|
4410
|
-
'user.reactivated': Feed.noop,
|
|
4411
|
-
'user.updated': Feed.noop,
|
|
4412
|
-
};
|
|
4413
|
-
this.eventDispatcher = new EventDispatcher();
|
|
4414
|
-
this.on = this.eventDispatcher.on;
|
|
4415
|
-
this.off = this.eventDispatcher.off;
|
|
4416
|
-
this.state = new StateStore({
|
|
4417
|
-
fid: `${groupId}:${id}`,
|
|
4418
|
-
group_id: groupId,
|
|
4419
|
-
id,
|
|
4420
|
-
...(data ?? {}),
|
|
4421
|
-
is_loading: false,
|
|
4422
|
-
is_loading_activities: false,
|
|
4423
|
-
comments_by_entity_id: {},
|
|
4424
|
-
watch,
|
|
4425
|
-
});
|
|
4426
|
-
this.client = client;
|
|
4427
|
-
}
|
|
4428
|
-
get fid() {
|
|
4429
|
-
return `${this.group}:${this.id}`;
|
|
4430
|
-
}
|
|
4431
|
-
get currentState() {
|
|
4432
|
-
return this.state.getLatestValue();
|
|
4433
|
-
}
|
|
4434
|
-
handleCommentReactionEvent(event) {
|
|
4435
|
-
const { comment, reaction } = event;
|
|
4436
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4437
|
-
this.state.next((currentState) => {
|
|
4438
|
-
const forId = comment.parent_id ?? comment.object_id;
|
|
4439
|
-
const entityState = currentState.comments_by_entity_id[forId];
|
|
4440
|
-
const commentIndex = this.getCommentIndex(comment, currentState);
|
|
4441
|
-
if (commentIndex === -1)
|
|
4442
|
-
return currentState;
|
|
4443
|
-
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4444
|
-
const commentCopy = { ...comment };
|
|
4445
|
-
delete commentCopy.own_reactions;
|
|
4446
|
-
const newComment = {
|
|
4447
|
-
...newComments[commentIndex],
|
|
4448
|
-
...commentCopy,
|
|
4449
|
-
// TODO: FIXME this should be handled by the backend
|
|
4450
|
-
latest_reactions: commentCopy.latest_reactions ?? [],
|
|
4451
|
-
reaction_groups: commentCopy.reaction_groups ?? {},
|
|
4452
|
-
};
|
|
4453
|
-
newComments[commentIndex] = newComment;
|
|
4454
|
-
if (reaction.user.id === connectedUser?.id) {
|
|
4455
|
-
if (event.type === 'feeds.comment.reaction.added') {
|
|
4456
|
-
newComment.own_reactions = newComment.own_reactions.concat(reaction) ?? [reaction];
|
|
4457
|
-
}
|
|
4458
|
-
else if (event.type === 'feeds.comment.reaction.deleted') {
|
|
4459
|
-
newComment.own_reactions = newComment.own_reactions.filter((r) => r.type !== reaction.type);
|
|
4460
|
-
}
|
|
4058
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4461
4059
|
}
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
});
|
|
4060
|
+
else if (isVoteAnswer(event.poll_vote)) {
|
|
4061
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4062
|
+
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
4063
|
+
}
|
|
4064
|
+
else {
|
|
4065
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4066
|
+
}
|
|
4067
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4068
|
+
this.state.partialNext({
|
|
4069
|
+
answers_count,
|
|
4070
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4071
|
+
latest_votes_by_option,
|
|
4072
|
+
vote_count,
|
|
4073
|
+
vote_counts_by_option,
|
|
4074
|
+
latest_answers: latestAnswers,
|
|
4075
|
+
last_activity_at: new Date(event.created_at),
|
|
4076
|
+
own_answer: ownAnswer,
|
|
4077
|
+
own_votes_by_option_id: ownVotesByOptionId,
|
|
4078
|
+
max_voted_option_ids: maxVotedOptionIds,
|
|
4079
|
+
});
|
|
4080
|
+
};
|
|
4081
|
+
this.handleVoteRemoved = (event) => {
|
|
4082
|
+
if (event.poll?.id && event.poll.id !== this.id)
|
|
4083
|
+
return;
|
|
4084
|
+
if (!isPollVoteRemovedEvent(event))
|
|
4085
|
+
return;
|
|
4086
|
+
const currentState = this.data;
|
|
4087
|
+
const isOwnVote = event.poll_vote.user_id ===
|
|
4088
|
+
this.client.state.getLatestValue().connected_user?.id;
|
|
4089
|
+
let latestAnswers = [...currentState.latest_answers];
|
|
4090
|
+
let ownAnswer = currentState.own_answer;
|
|
4091
|
+
const ownVotesByOptionId = { ...currentState.own_votes_by_option_id };
|
|
4092
|
+
let maxVotedOptionIds = currentState.max_voted_option_ids;
|
|
4093
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4094
|
+
if (isVoteAnswer(event.poll_vote)) {
|
|
4095
|
+
latestAnswers = latestAnswers.filter((answer) => answer.id !== event.poll_vote.id);
|
|
4096
|
+
if (isOwnVote) {
|
|
4097
|
+
ownAnswer = undefined;
|
|
4501
4098
|
}
|
|
4502
4099
|
}
|
|
4503
4100
|
else {
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
...response.feed,
|
|
4509
|
-
};
|
|
4510
|
-
delete responseCopy.feed;
|
|
4511
|
-
delete responseCopy.metadata;
|
|
4512
|
-
delete responseCopy.duration;
|
|
4513
|
-
this.state.next((currentState) => {
|
|
4514
|
-
const nextState = {
|
|
4515
|
-
...currentState,
|
|
4516
|
-
...responseCopy,
|
|
4517
|
-
};
|
|
4518
|
-
if (!request?.followers_pagination?.limit) {
|
|
4519
|
-
delete nextState.followers;
|
|
4520
|
-
}
|
|
4521
|
-
if (!request?.following_pagination?.limit) {
|
|
4522
|
-
delete nextState.following;
|
|
4523
|
-
}
|
|
4524
|
-
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
4525
|
-
delete nextState.members;
|
|
4526
|
-
}
|
|
4527
|
-
nextState.last_get_or_create_request_config = request;
|
|
4528
|
-
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
4529
|
-
return nextState;
|
|
4530
|
-
});
|
|
4101
|
+
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
4102
|
+
if (isOwnVote && event.poll_vote.option_id) {
|
|
4103
|
+
delete ownVotesByOptionId[event.poll_vote.option_id];
|
|
4104
|
+
}
|
|
4531
4105
|
}
|
|
4532
|
-
|
|
4533
|
-
return response;
|
|
4534
|
-
}
|
|
4535
|
-
finally {
|
|
4106
|
+
const { answers_count, latest_votes_by_option, vote_count, vote_counts_by_option, } = event.poll;
|
|
4536
4107
|
this.state.partialNext({
|
|
4537
|
-
|
|
4538
|
-
|
|
4108
|
+
answers_count,
|
|
4109
|
+
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
4110
|
+
latest_votes_by_option,
|
|
4111
|
+
vote_count,
|
|
4112
|
+
vote_counts_by_option,
|
|
4113
|
+
latest_answers: latestAnswers,
|
|
4114
|
+
last_activity_at: new Date(event.created_at),
|
|
4115
|
+
own_answer: ownAnswer,
|
|
4116
|
+
own_votes_by_option_id: ownVotesByOptionId,
|
|
4117
|
+
max_voted_option_ids: maxVotedOptionIds,
|
|
4539
4118
|
});
|
|
4540
|
-
}
|
|
4119
|
+
};
|
|
4120
|
+
this.client = client;
|
|
4121
|
+
this.id = poll.id;
|
|
4122
|
+
this.state = new StateStore(this.getInitialStateFromPollResponse(poll));
|
|
4541
4123
|
}
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
*/
|
|
4545
|
-
handleFollowCreated(follow) {
|
|
4546
|
-
if (!shouldUpdateState({
|
|
4547
|
-
stateUpdateId: getStateUpdateQueueIdForFollow(follow),
|
|
4548
|
-
stateUpdateQueue: this.stateUpdateQueue,
|
|
4549
|
-
watch: this.currentState.watch,
|
|
4550
|
-
})) {
|
|
4551
|
-
return;
|
|
4552
|
-
}
|
|
4553
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4554
|
-
const result = handleFollowCreated(follow, this.currentState, this.fid, connectedUser?.id);
|
|
4555
|
-
if (result.changed) {
|
|
4556
|
-
this.state.next(result.data);
|
|
4557
|
-
}
|
|
4124
|
+
get data() {
|
|
4125
|
+
return this.state.getLatestValue();
|
|
4558
4126
|
}
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
})) {
|
|
4568
|
-
return;
|
|
4127
|
+
}
|
|
4128
|
+
function getMaxVotedOptionIds(voteCountsByOption) {
|
|
4129
|
+
let maxVotes = 0;
|
|
4130
|
+
let winningOptions = [];
|
|
4131
|
+
for (const [id, count] of Object.entries(voteCountsByOption ?? {})) {
|
|
4132
|
+
if (count > maxVotes) {
|
|
4133
|
+
winningOptions = [id];
|
|
4134
|
+
maxVotes = count;
|
|
4569
4135
|
}
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
{
|
|
4573
|
-
this.state.next(result.data);
|
|
4136
|
+
else if (count === maxVotes) {
|
|
4137
|
+
winningOptions.push(id);
|
|
4574
4138
|
}
|
|
4575
4139
|
}
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4140
|
+
return winningOptions;
|
|
4141
|
+
}
|
|
4142
|
+
function getOwnVotesByOptionId(ownVotes) {
|
|
4143
|
+
return !ownVotes
|
|
4144
|
+
? {}
|
|
4145
|
+
: ownVotes.reduce((acc, vote) => {
|
|
4146
|
+
if (isVoteAnswer(vote) || !vote.option_id)
|
|
4147
|
+
return acc;
|
|
4148
|
+
acc[vote.option_id] = vote;
|
|
4149
|
+
return acc;
|
|
4150
|
+
}, {});
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
class FeedApi {
|
|
4154
|
+
constructor(feedsApi, group, id) {
|
|
4155
|
+
this.feedsApi = feedsApi;
|
|
4156
|
+
this.group = group;
|
|
4157
|
+
this.id = id;
|
|
4158
|
+
}
|
|
4159
|
+
delete(request) {
|
|
4160
|
+
return this.feedsApi.deleteFeed({
|
|
4161
|
+
feed_id: this.id,
|
|
4162
|
+
feed_group_id: this.group,
|
|
4163
|
+
...request,
|
|
4590
4164
|
});
|
|
4591
4165
|
}
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
this.state.partialNext({ activities: result.activities });
|
|
4599
|
-
}
|
|
4166
|
+
getOrCreate(request) {
|
|
4167
|
+
return this.feedsApi.getOrCreateFeed({
|
|
4168
|
+
feed_id: this.id,
|
|
4169
|
+
feed_group_id: this.group,
|
|
4170
|
+
...request,
|
|
4171
|
+
});
|
|
4600
4172
|
}
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
this.state.partialNext({ activities: result.activities });
|
|
4608
|
-
}
|
|
4173
|
+
update(request) {
|
|
4174
|
+
return this.feedsApi.updateFeed({
|
|
4175
|
+
feed_id: this.id,
|
|
4176
|
+
feed_group_id: this.group,
|
|
4177
|
+
...request,
|
|
4178
|
+
});
|
|
4609
4179
|
}
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
this.state.partialNext({ activities: result.activities });
|
|
4617
|
-
}
|
|
4180
|
+
markActivity(request) {
|
|
4181
|
+
return this.feedsApi.markActivity({
|
|
4182
|
+
feed_id: this.id,
|
|
4183
|
+
feed_group_id: this.group,
|
|
4184
|
+
...request,
|
|
4185
|
+
});
|
|
4618
4186
|
}
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
if (!currentComments?.length) {
|
|
4626
|
-
return -1;
|
|
4627
|
-
}
|
|
4628
|
-
// @ts-expect-error this will just fail if the comment is not object from state
|
|
4629
|
-
let commentIndex = currentComments.indexOf(comment);
|
|
4630
|
-
// fast lookup failed, try slower approach
|
|
4631
|
-
if (commentIndex === -1) {
|
|
4632
|
-
commentIndex = currentComments.findIndex((comment_) => comment_.id === comment.id);
|
|
4633
|
-
}
|
|
4634
|
-
return commentIndex;
|
|
4187
|
+
unpinActivity(request) {
|
|
4188
|
+
return this.feedsApi.unpinActivity({
|
|
4189
|
+
feed_id: this.id,
|
|
4190
|
+
feed_group_id: this.group,
|
|
4191
|
+
...request,
|
|
4192
|
+
});
|
|
4635
4193
|
}
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
// add initial (top level) object for processing
|
|
4642
|
-
const traverseArray = [
|
|
4643
|
-
{
|
|
4644
|
-
entityId: data.entityId,
|
|
4645
|
-
entityParentId: data.entityParentId,
|
|
4646
|
-
comments: data.comments,
|
|
4647
|
-
next: data.next,
|
|
4648
|
-
},
|
|
4649
|
-
];
|
|
4650
|
-
this.state.next((currentState) => {
|
|
4651
|
-
const newCommentsByEntityId = {
|
|
4652
|
-
...currentState.comments_by_entity_id,
|
|
4653
|
-
};
|
|
4654
|
-
while (traverseArray.length) {
|
|
4655
|
-
const item = traverseArray.pop();
|
|
4656
|
-
const entityId = item.entityId;
|
|
4657
|
-
// go over entity comments and generate new objects
|
|
4658
|
-
// for further processing if there are any replies
|
|
4659
|
-
item.comments.forEach((comment) => {
|
|
4660
|
-
if (!comment.replies?.length)
|
|
4661
|
-
return;
|
|
4662
|
-
traverseArray.push({
|
|
4663
|
-
entityId: comment.id,
|
|
4664
|
-
entityParentId: entityId,
|
|
4665
|
-
comments: comment.replies,
|
|
4666
|
-
next: comment.meta?.next_cursor,
|
|
4667
|
-
});
|
|
4668
|
-
});
|
|
4669
|
-
// omit replies & meta from the comments (transform ThreadedCommentResponse to CommentResponse)
|
|
4670
|
-
// this is somehow faster than copying the whole
|
|
4671
|
-
// object and deleting the desired properties
|
|
4672
|
-
const newComments = item.comments.map(({ replies: _r, meta: _m, ...restOfTheCommentResponse }) => restOfTheCommentResponse);
|
|
4673
|
-
newCommentsByEntityId[entityId] = {
|
|
4674
|
-
...newCommentsByEntityId[entityId],
|
|
4675
|
-
entity_parent_id: item.entityParentId,
|
|
4676
|
-
pagination: {
|
|
4677
|
-
...newCommentsByEntityId[entityId]?.pagination,
|
|
4678
|
-
next: item.next,
|
|
4679
|
-
sort: data.sort,
|
|
4680
|
-
},
|
|
4681
|
-
comments: newCommentsByEntityId[entityId]?.comments
|
|
4682
|
-
? newCommentsByEntityId[entityId].comments?.concat(newComments)
|
|
4683
|
-
: newComments,
|
|
4684
|
-
};
|
|
4685
|
-
}
|
|
4686
|
-
return {
|
|
4687
|
-
...currentState,
|
|
4688
|
-
comments_by_entity_id: newCommentsByEntityId,
|
|
4689
|
-
};
|
|
4194
|
+
pinActivity(request) {
|
|
4195
|
+
return this.feedsApi.pinActivity({
|
|
4196
|
+
feed_id: this.id,
|
|
4197
|
+
feed_group_id: this.group,
|
|
4198
|
+
...request,
|
|
4690
4199
|
});
|
|
4691
4200
|
}
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
this.
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
...currentState.comments_by_entity_id,
|
|
4699
|
-
[entityId]: {
|
|
4700
|
-
...currentState.comments_by_entity_id[entityId],
|
|
4701
|
-
pagination: {
|
|
4702
|
-
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4703
|
-
loading_next_page: true,
|
|
4704
|
-
},
|
|
4705
|
-
},
|
|
4706
|
-
},
|
|
4707
|
-
}));
|
|
4708
|
-
const { next, comments } = await base();
|
|
4709
|
-
this.loadCommentsIntoState({
|
|
4710
|
-
entityId,
|
|
4711
|
-
comments,
|
|
4712
|
-
entityParentId,
|
|
4713
|
-
next,
|
|
4714
|
-
sort,
|
|
4715
|
-
});
|
|
4716
|
-
}
|
|
4717
|
-
catch (e) {
|
|
4718
|
-
error = e;
|
|
4719
|
-
}
|
|
4720
|
-
finally {
|
|
4721
|
-
this.state.next((currentState) => ({
|
|
4722
|
-
...currentState,
|
|
4723
|
-
comments_by_entity_id: {
|
|
4724
|
-
...currentState.comments_by_entity_id,
|
|
4725
|
-
[entityId]: {
|
|
4726
|
-
...currentState.comments_by_entity_id[entityId],
|
|
4727
|
-
pagination: {
|
|
4728
|
-
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4729
|
-
loading_next_page: false,
|
|
4730
|
-
},
|
|
4731
|
-
},
|
|
4732
|
-
},
|
|
4733
|
-
}));
|
|
4734
|
-
}
|
|
4735
|
-
if (error) {
|
|
4736
|
-
throw error;
|
|
4737
|
-
}
|
|
4201
|
+
updateFeedMembers(request) {
|
|
4202
|
+
return this.feedsApi.updateFeedMembers({
|
|
4203
|
+
feed_id: this.id,
|
|
4204
|
+
feed_group_id: this.group,
|
|
4205
|
+
...request,
|
|
4206
|
+
});
|
|
4738
4207
|
}
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
const isLoading = currentPagination?.loading_next_page;
|
|
4745
|
-
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4746
|
-
if (isLoading ||
|
|
4747
|
-
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4748
|
-
return;
|
|
4749
|
-
}
|
|
4750
|
-
await this.loadNextPageComments({
|
|
4751
|
-
entityId: activity.id,
|
|
4752
|
-
base: () => this.client.getComments({
|
|
4753
|
-
...request,
|
|
4754
|
-
sort,
|
|
4755
|
-
object_id: activity.id,
|
|
4756
|
-
object_type: 'activity',
|
|
4757
|
-
next: currentNextCursor,
|
|
4758
|
-
}),
|
|
4759
|
-
sort,
|
|
4208
|
+
acceptFeedMemberInvite(request) {
|
|
4209
|
+
return this.feedsApi.acceptFeedMemberInvite({
|
|
4210
|
+
feed_id: this.id,
|
|
4211
|
+
feed_group_id: this.group,
|
|
4212
|
+
...request,
|
|
4760
4213
|
});
|
|
4761
4214
|
}
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
const isLoading = currentPagination?.loading_next_page;
|
|
4768
|
-
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
4769
|
-
if (isLoading ||
|
|
4770
|
-
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
4771
|
-
return;
|
|
4772
|
-
}
|
|
4773
|
-
await this.loadNextPageComments({
|
|
4774
|
-
entityId: comment.id,
|
|
4775
|
-
base: () => this.client.getCommentReplies({
|
|
4776
|
-
...request,
|
|
4777
|
-
comment_id: comment.id,
|
|
4778
|
-
// use known sort first (prevents broken pagination)
|
|
4779
|
-
sort: currentSort ??
|
|
4780
|
-
request?.sort ??
|
|
4781
|
-
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
4782
|
-
next: currentNextCursor,
|
|
4783
|
-
}),
|
|
4784
|
-
entityParentId: comment.parent_id ?? comment.object_id,
|
|
4785
|
-
sort,
|
|
4215
|
+
queryFeedMembers(request) {
|
|
4216
|
+
return this.feedsApi.queryFeedMembers({
|
|
4217
|
+
feed_id: this.id,
|
|
4218
|
+
feed_group_id: this.group,
|
|
4219
|
+
...request,
|
|
4786
4220
|
});
|
|
4787
4221
|
}
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4222
|
+
rejectFeedMemberInvite(request) {
|
|
4223
|
+
return this.feedsApi.rejectFeedMemberInvite({
|
|
4224
|
+
feed_id: this.id,
|
|
4225
|
+
feed_group_id: this.group,
|
|
4226
|
+
...request,
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4229
|
+
stopWatching(request) {
|
|
4230
|
+
return this.feedsApi.stopWatchingFeed({
|
|
4231
|
+
feed_id: this.id,
|
|
4232
|
+
feed_group_id: this.group,
|
|
4233
|
+
...request,
|
|
4234
|
+
});
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
|
|
4238
|
+
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4239
|
+
typeof cursor === 'string';
|
|
4240
|
+
|
|
4241
|
+
const uniqueArrayMerge = (existingArray, arrayToMerge, getKey) => {
|
|
4242
|
+
const existing = new Set();
|
|
4243
|
+
existingArray.forEach((value) => {
|
|
4244
|
+
const key = getKey(value);
|
|
4245
|
+
existing.add(key);
|
|
4246
|
+
});
|
|
4247
|
+
const filteredArrayToMerge = arrayToMerge.filter((value) => {
|
|
4248
|
+
const key = getKey(value);
|
|
4249
|
+
return !existing.has(key);
|
|
4250
|
+
});
|
|
4251
|
+
return existingArray.concat(filteredArrayToMerge);
|
|
4252
|
+
};
|
|
4253
|
+
|
|
4254
|
+
const Constants = {
|
|
4255
|
+
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4256
|
+
};
|
|
4257
|
+
|
|
4258
|
+
const isFollowResponse = (data) => {
|
|
4259
|
+
return 'source_feed' in data && 'target_feed' in data;
|
|
4260
|
+
};
|
|
4261
|
+
const isCommentResponse = (entity) => {
|
|
4262
|
+
return typeof entity?.object_id === 'string';
|
|
4263
|
+
};
|
|
4264
|
+
|
|
4265
|
+
const shouldUpdateState = ({ stateUpdateQueueId, stateUpdateQueue, watch, }) => {
|
|
4266
|
+
if (!watch) {
|
|
4267
|
+
return true;
|
|
4268
|
+
}
|
|
4269
|
+
if (watch && stateUpdateQueue.has(stateUpdateQueueId)) {
|
|
4270
|
+
stateUpdateQueue.delete(stateUpdateQueueId);
|
|
4271
|
+
return false;
|
|
4272
|
+
}
|
|
4273
|
+
stateUpdateQueue.add(stateUpdateQueueId);
|
|
4274
|
+
return true;
|
|
4275
|
+
};
|
|
4276
|
+
function getStateUpdateQueueId(data, prefix) {
|
|
4277
|
+
if (isFollowResponse(data)) {
|
|
4278
|
+
const toJoin = [data.source_feed.feed, data.target_feed.feed];
|
|
4279
|
+
if (prefix) {
|
|
4280
|
+
toJoin.unshift(prefix);
|
|
4827
4281
|
}
|
|
4828
|
-
|
|
4829
|
-
|
|
4282
|
+
return toJoin.join('-');
|
|
4283
|
+
}
|
|
4284
|
+
// else if (isMemberResponse(data)) {
|
|
4285
|
+
// }
|
|
4286
|
+
throw new Error(`Cannot create state update queueId for data: ${JSON.stringify(data)}`);
|
|
4287
|
+
}
|
|
4288
|
+
|
|
4289
|
+
const updateStateFollowCreated = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4290
|
+
// filter non-accepted follows (the way getOrCreate does by default)
|
|
4291
|
+
if (follow.status !== 'accepted') {
|
|
4292
|
+
return { changed: false, data: currentState };
|
|
4293
|
+
}
|
|
4294
|
+
let newState = { ...currentState };
|
|
4295
|
+
// this feed followed someone
|
|
4296
|
+
if (follow.source_feed.feed === currentFeedId) {
|
|
4297
|
+
newState = {
|
|
4298
|
+
...newState,
|
|
4299
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4300
|
+
...follow.source_feed,
|
|
4301
|
+
};
|
|
4302
|
+
// Only update if following array already exists
|
|
4303
|
+
if (currentState.following !== undefined) {
|
|
4304
|
+
newState.following = [follow, ...currentState.following];
|
|
4830
4305
|
}
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4306
|
+
}
|
|
4307
|
+
else if (
|
|
4308
|
+
// someone followed this feed
|
|
4309
|
+
follow.target_feed.feed === currentFeedId) {
|
|
4310
|
+
const source = follow.source_feed;
|
|
4311
|
+
newState = {
|
|
4312
|
+
...newState,
|
|
4313
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4314
|
+
...follow.target_feed,
|
|
4315
|
+
};
|
|
4316
|
+
if (source.created_by.id === connectedUserId) {
|
|
4317
|
+
newState.own_follows = currentState.own_follows
|
|
4318
|
+
? currentState.own_follows.concat(follow)
|
|
4319
|
+
: [follow];
|
|
4841
4320
|
}
|
|
4842
|
-
if
|
|
4843
|
-
|
|
4321
|
+
// Only update if followers array already exists
|
|
4322
|
+
if (currentState.followers !== undefined) {
|
|
4323
|
+
newState.followers = [follow, ...currentState.followers];
|
|
4844
4324
|
}
|
|
4845
4325
|
}
|
|
4846
|
-
|
|
4847
|
-
|
|
4326
|
+
return { changed: true, data: newState };
|
|
4327
|
+
};
|
|
4328
|
+
function handleFollowCreated(eventOrResponse) {
|
|
4329
|
+
const follow = eventOrResponse.follow;
|
|
4330
|
+
if (!shouldUpdateState({
|
|
4331
|
+
stateUpdateQueueId: getStateUpdateQueueId(follow, 'created'),
|
|
4332
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4333
|
+
watch: this.currentState.watch,
|
|
4334
|
+
})) {
|
|
4335
|
+
return;
|
|
4848
4336
|
}
|
|
4849
|
-
|
|
4850
|
-
|
|
4337
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4338
|
+
const result = updateStateFollowCreated(follow, this.currentState, this.feed, connectedUser?.id);
|
|
4339
|
+
if (result.changed) {
|
|
4340
|
+
this.state.next(result.data);
|
|
4851
4341
|
}
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4342
|
+
}
|
|
4343
|
+
|
|
4344
|
+
const updateStateFollowDeleted = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4345
|
+
let newState = { ...currentState };
|
|
4346
|
+
// this feed unfollowed someone
|
|
4347
|
+
if (follow.source_feed.feed === currentFeedId) {
|
|
4348
|
+
newState = {
|
|
4349
|
+
...newState,
|
|
4350
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4351
|
+
...follow.source_feed,
|
|
4352
|
+
};
|
|
4353
|
+
// Only update if following array already exists
|
|
4354
|
+
if (currentState.following !== undefined) {
|
|
4355
|
+
newState.following = currentState.following.filter((followItem) => followItem.target_feed.feed !== follow.target_feed.feed);
|
|
4860
4356
|
}
|
|
4861
|
-
|
|
4862
|
-
|
|
4357
|
+
}
|
|
4358
|
+
else if (
|
|
4359
|
+
// someone unfollowed this feed
|
|
4360
|
+
follow.target_feed.feed === currentFeedId) {
|
|
4361
|
+
const source = follow.source_feed;
|
|
4362
|
+
newState = {
|
|
4363
|
+
...newState,
|
|
4364
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4365
|
+
...follow.target_feed,
|
|
4366
|
+
};
|
|
4367
|
+
if (source.created_by.id === connectedUserId &&
|
|
4368
|
+
currentState.own_follows !== undefined) {
|
|
4369
|
+
newState.own_follows = currentState.own_follows.filter((followItem) => followItem.source_feed.feed !== follow.source_feed.feed);
|
|
4370
|
+
}
|
|
4371
|
+
// Only update if followers array already exists
|
|
4372
|
+
if (currentState.followers !== undefined) {
|
|
4373
|
+
newState.followers = currentState.followers.filter((followItem) => followItem.source_feed.feed !== follow.source_feed.feed);
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
return { changed: true, data: newState };
|
|
4377
|
+
};
|
|
4378
|
+
function handleFollowDeleted(eventOrResponse) {
|
|
4379
|
+
const follow = eventOrResponse.follow;
|
|
4380
|
+
if (!shouldUpdateState({
|
|
4381
|
+
stateUpdateQueueId: getStateUpdateQueueId(follow, 'deleted'),
|
|
4382
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4383
|
+
watch: this.currentState.watch,
|
|
4384
|
+
})) {
|
|
4385
|
+
return;
|
|
4386
|
+
}
|
|
4387
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4388
|
+
const result = updateStateFollowDeleted(follow, this.currentState, this.feed, connectedUser?.id);
|
|
4389
|
+
{
|
|
4390
|
+
this.state.next(result.data);
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
function handleFollowUpdated(eventOrResponse) {
|
|
4395
|
+
const follow = eventOrResponse.follow;
|
|
4396
|
+
const connectedUserId = this.client.state.getLatestValue().connected_user?.id;
|
|
4397
|
+
const currentFeedId = this.feed;
|
|
4398
|
+
if (!shouldUpdateState({
|
|
4399
|
+
stateUpdateQueueId: getStateUpdateQueueId(follow, 'updated'),
|
|
4400
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4401
|
+
watch: this.currentState.watch,
|
|
4402
|
+
})) {
|
|
4403
|
+
return;
|
|
4404
|
+
}
|
|
4405
|
+
this.state.next((currentState) => {
|
|
4406
|
+
let newState;
|
|
4407
|
+
// this feed followed someone
|
|
4408
|
+
if (follow.source_feed.feed === currentFeedId) {
|
|
4409
|
+
newState ?? (newState = {
|
|
4863
4410
|
...currentState,
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
loading_next_page: true,
|
|
4867
|
-
},
|
|
4868
|
-
}));
|
|
4869
|
-
const { next: newNextCursor, members } = await this.client.queryFeedMembers({
|
|
4870
|
-
...request,
|
|
4871
|
-
sort,
|
|
4872
|
-
feed_id: this.id,
|
|
4873
|
-
feed_group_id: this.group,
|
|
4874
|
-
next: currentNextCursor,
|
|
4411
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4412
|
+
...follow.source_feed,
|
|
4875
4413
|
});
|
|
4876
|
-
|
|
4414
|
+
const index = currentState.following?.findIndex((f) => f.target_feed.feed === follow.target_feed.feed) ?? -1;
|
|
4415
|
+
if (index >= 0) {
|
|
4416
|
+
newState.following = [...newState.following];
|
|
4417
|
+
newState.following[index] = follow;
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
else if (
|
|
4421
|
+
// someone followed this feed
|
|
4422
|
+
follow.target_feed.feed === currentFeedId) {
|
|
4423
|
+
const source = follow.source_feed;
|
|
4424
|
+
newState ?? (newState = {
|
|
4877
4425
|
...currentState,
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4426
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4427
|
+
...follow.target_feed,
|
|
4428
|
+
});
|
|
4429
|
+
if (source.created_by.id === connectedUserId &&
|
|
4430
|
+
currentState.own_follows) {
|
|
4431
|
+
const index = currentState.own_follows.findIndex((f) => f.source_feed.feed === follow.source_feed.feed);
|
|
4432
|
+
if (index >= 0) {
|
|
4433
|
+
newState.own_follows = [...currentState.own_follows];
|
|
4434
|
+
newState.own_follows[index] = follow;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
const index = currentState.followers?.findIndex((f) => f.source_feed.feed === follow.source_feed.feed) ?? -1;
|
|
4438
|
+
if (index >= 0) {
|
|
4439
|
+
newState.followers = [...newState.followers];
|
|
4440
|
+
newState.followers[index] = follow;
|
|
4441
|
+
}
|
|
4888
4442
|
}
|
|
4889
|
-
|
|
4890
|
-
|
|
4443
|
+
return newState ?? currentState;
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
|
|
4447
|
+
function handleCommentAdded(event) {
|
|
4448
|
+
const { comment } = event;
|
|
4449
|
+
const entityId = comment.parent_id ?? comment.object_id;
|
|
4450
|
+
this.state.next((currentState) => {
|
|
4451
|
+
const entityState = currentState.comments_by_entity_id[entityId];
|
|
4452
|
+
if (typeof entityState?.comments === 'undefined') {
|
|
4453
|
+
return currentState;
|
|
4891
4454
|
}
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
member_pagination: {
|
|
4896
|
-
...currentState.member_pagination,
|
|
4897
|
-
loading_next_page: false,
|
|
4898
|
-
},
|
|
4899
|
-
}));
|
|
4455
|
+
const newComments = entityState?.comments ? [...entityState.comments] : [];
|
|
4456
|
+
if (entityState.pagination?.sort === 'last') {
|
|
4457
|
+
newComments.unshift(comment);
|
|
4900
4458
|
}
|
|
4901
|
-
|
|
4902
|
-
|
|
4459
|
+
else {
|
|
4460
|
+
// 'first' and other sort options
|
|
4461
|
+
newComments.push(comment);
|
|
4903
4462
|
}
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
};
|
|
4914
|
-
const response = await this.client.queryFollows({
|
|
4915
|
-
filter,
|
|
4916
|
-
...request,
|
|
4917
|
-
});
|
|
4918
|
-
return response;
|
|
4919
|
-
}
|
|
4920
|
-
/**
|
|
4921
|
-
* Method which queries following of this feed (target feeds of this feed).
|
|
4922
|
-
*
|
|
4923
|
-
* _Note: Useful only for feeds with `groupId` of `timeline` value._
|
|
4924
|
-
*/
|
|
4925
|
-
async queryFollowing(request) {
|
|
4926
|
-
const filter = {
|
|
4927
|
-
source_feed: this.fid,
|
|
4463
|
+
return {
|
|
4464
|
+
...currentState,
|
|
4465
|
+
comments_by_entity_id: {
|
|
4466
|
+
...currentState.comments_by_entity_id,
|
|
4467
|
+
[entityId]: {
|
|
4468
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4469
|
+
comments: newComments,
|
|
4470
|
+
},
|
|
4471
|
+
},
|
|
4928
4472
|
};
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
source: this.fid,
|
|
4940
|
-
target: fid,
|
|
4941
|
-
});
|
|
4942
|
-
return response;
|
|
4943
|
-
}
|
|
4944
|
-
async unfollow(feedOrFid) {
|
|
4945
|
-
const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.fid;
|
|
4946
|
-
const response = await this.client.unfollow({
|
|
4947
|
-
source: this.fid,
|
|
4948
|
-
target: fid,
|
|
4949
|
-
});
|
|
4950
|
-
return response;
|
|
4951
|
-
}
|
|
4952
|
-
async getNextPage() {
|
|
4953
|
-
const currentState = this.currentState;
|
|
4954
|
-
return await this.getOrCreate({
|
|
4955
|
-
member_pagination: {
|
|
4956
|
-
limit: 0,
|
|
4473
|
+
});
|
|
4474
|
+
}
|
|
4475
|
+
|
|
4476
|
+
function handleCommentDeleted({ comment }) {
|
|
4477
|
+
const entityId = comment.parent_id ?? comment.object_id;
|
|
4478
|
+
this.state.next((currentState) => {
|
|
4479
|
+
const newCommentsByEntityId = {
|
|
4480
|
+
...currentState.comments_by_entity_id,
|
|
4481
|
+
[entityId]: {
|
|
4482
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4957
4483
|
},
|
|
4958
|
-
|
|
4959
|
-
|
|
4484
|
+
};
|
|
4485
|
+
const index = this.getCommentIndex(comment, currentState);
|
|
4486
|
+
if (newCommentsByEntityId?.[entityId]?.comments?.length && index !== -1) {
|
|
4487
|
+
newCommentsByEntityId[entityId].comments = [
|
|
4488
|
+
...newCommentsByEntityId[entityId].comments,
|
|
4489
|
+
];
|
|
4490
|
+
newCommentsByEntityId[entityId]?.comments?.splice(index, 1);
|
|
4491
|
+
}
|
|
4492
|
+
delete newCommentsByEntityId[comment.id];
|
|
4493
|
+
return {
|
|
4494
|
+
...currentState,
|
|
4495
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
4496
|
+
};
|
|
4497
|
+
});
|
|
4498
|
+
}
|
|
4499
|
+
|
|
4500
|
+
function handleCommentUpdated(event) {
|
|
4501
|
+
const { comment } = event;
|
|
4502
|
+
const entityId = comment.parent_id ?? comment.object_id;
|
|
4503
|
+
this.state.next((currentState) => {
|
|
4504
|
+
const entityState = currentState.comments_by_entity_id[entityId];
|
|
4505
|
+
if (!entityState?.comments?.length)
|
|
4506
|
+
return currentState;
|
|
4507
|
+
const index = this.getCommentIndex(comment, currentState);
|
|
4508
|
+
if (index === -1)
|
|
4509
|
+
return currentState;
|
|
4510
|
+
const newComments = [...entityState.comments];
|
|
4511
|
+
newComments[index] = comment;
|
|
4512
|
+
return {
|
|
4513
|
+
...currentState,
|
|
4514
|
+
comments_by_entity_id: {
|
|
4515
|
+
...currentState.comments_by_entity_id,
|
|
4516
|
+
[entityId]: {
|
|
4517
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4518
|
+
comments: newComments,
|
|
4519
|
+
},
|
|
4960
4520
|
},
|
|
4961
|
-
|
|
4962
|
-
|
|
4521
|
+
};
|
|
4522
|
+
});
|
|
4523
|
+
}
|
|
4524
|
+
|
|
4525
|
+
function handleCommentReaction(event) {
|
|
4526
|
+
const { comment, reaction } = event;
|
|
4527
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4528
|
+
this.state.next((currentState) => {
|
|
4529
|
+
const forId = comment.parent_id ?? comment.object_id;
|
|
4530
|
+
const entityState = currentState.comments_by_entity_id[forId];
|
|
4531
|
+
const commentIndex = this.getCommentIndex(comment, currentState);
|
|
4532
|
+
if (commentIndex === -1)
|
|
4533
|
+
return currentState;
|
|
4534
|
+
const newComments = entityState?.comments?.concat([]) ?? [];
|
|
4535
|
+
const commentCopy = { ...comment };
|
|
4536
|
+
delete commentCopy.own_reactions;
|
|
4537
|
+
const newComment = {
|
|
4538
|
+
...newComments[commentIndex],
|
|
4539
|
+
...commentCopy,
|
|
4540
|
+
// TODO: FIXME this should be handled by the backend
|
|
4541
|
+
latest_reactions: commentCopy.latest_reactions ?? [],
|
|
4542
|
+
reaction_groups: commentCopy.reaction_groups ?? {},
|
|
4543
|
+
};
|
|
4544
|
+
newComments[commentIndex] = newComment;
|
|
4545
|
+
if (reaction.user.id === connectedUser?.id) {
|
|
4546
|
+
if (event.type === 'feeds.comment.reaction.added') {
|
|
4547
|
+
newComment.own_reactions = newComment.own_reactions.concat(reaction) ?? [reaction];
|
|
4548
|
+
}
|
|
4549
|
+
else if (event.type === 'feeds.comment.reaction.deleted') {
|
|
4550
|
+
newComment.own_reactions = newComment.own_reactions.filter((r) => r.type !== reaction.type);
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
return {
|
|
4554
|
+
...currentState,
|
|
4555
|
+
comments_by_entity_id: {
|
|
4556
|
+
...currentState.comments_by_entity_id,
|
|
4557
|
+
[forId]: {
|
|
4558
|
+
...entityState,
|
|
4559
|
+
comments: newComments,
|
|
4560
|
+
},
|
|
4963
4561
|
},
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
if (eventHandler !== Feed.noop) {
|
|
4978
|
-
// @ts-expect-error intersection of handler arguments results to never
|
|
4979
|
-
eventHandler?.(event);
|
|
4562
|
+
};
|
|
4563
|
+
});
|
|
4564
|
+
}
|
|
4565
|
+
|
|
4566
|
+
function handleFeedMemberAdded(event) {
|
|
4567
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4568
|
+
this.state.next((currentState) => {
|
|
4569
|
+
let newState;
|
|
4570
|
+
if (typeof currentState.members !== 'undefined') {
|
|
4571
|
+
newState ?? (newState = {
|
|
4572
|
+
...currentState,
|
|
4573
|
+
});
|
|
4574
|
+
newState.members = [event.member, ...currentState.members];
|
|
4980
4575
|
}
|
|
4981
|
-
if (
|
|
4982
|
-
|
|
4576
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4577
|
+
newState ?? (newState = {
|
|
4578
|
+
...currentState,
|
|
4579
|
+
});
|
|
4580
|
+
newState.own_membership = event.member;
|
|
4983
4581
|
}
|
|
4984
|
-
|
|
4985
|
-
}
|
|
4582
|
+
return newState ?? currentState;
|
|
4583
|
+
});
|
|
4986
4584
|
}
|
|
4987
|
-
Feed.noop = () => { };
|
|
4988
4585
|
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
4586
|
+
function handleFeedMemberUpdated(event) {
|
|
4587
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4588
|
+
this.state.next((currentState) => {
|
|
4589
|
+
const memberIndex = currentState.members?.findIndex((member) => member.user.id === event.member.user.id) ?? -1;
|
|
4590
|
+
let newState;
|
|
4591
|
+
if (memberIndex !== -1) {
|
|
4592
|
+
// if there's an index, there's a member to update
|
|
4593
|
+
const newMembers = [...currentState.members];
|
|
4594
|
+
newMembers[memberIndex] = event.member;
|
|
4595
|
+
newState ?? (newState = {
|
|
4596
|
+
...currentState,
|
|
4597
|
+
});
|
|
4598
|
+
newState.members = newMembers;
|
|
4599
|
+
}
|
|
4600
|
+
if (connectedUser?.id === event.member.user.id) {
|
|
4601
|
+
newState ?? (newState = {
|
|
4602
|
+
...currentState,
|
|
4603
|
+
});
|
|
4604
|
+
newState.own_membership = event.member;
|
|
4605
|
+
}
|
|
4606
|
+
return newState ?? currentState;
|
|
4607
|
+
});
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4610
|
+
function handleFeedMemberRemoved(event) {
|
|
4611
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4612
|
+
this.state.next((currentState) => {
|
|
4613
|
+
const newState = {
|
|
4614
|
+
...currentState,
|
|
4615
|
+
members: currentState.members?.filter((member) => member.user.id !== event.user?.id),
|
|
4616
|
+
};
|
|
4617
|
+
if (connectedUser?.id === event.member_id) {
|
|
4618
|
+
delete newState.own_membership;
|
|
4619
|
+
}
|
|
4620
|
+
return newState;
|
|
4621
|
+
});
|
|
4622
|
+
}
|
|
4623
|
+
|
|
4624
|
+
const addActivitiesToState = (newActivities, activities, position) => {
|
|
4625
|
+
let result;
|
|
4626
|
+
if (activities === undefined) {
|
|
4627
|
+
activities = [];
|
|
4628
|
+
result = {
|
|
4629
|
+
changed: true,
|
|
4630
|
+
activities,
|
|
5027
4631
|
};
|
|
5028
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/config', undefined, undefined, body, 'application/json');
|
|
5029
|
-
decoders.UpsertConfigResponse?.(response.body);
|
|
5030
|
-
return { ...response.body, metadata: response.metadata };
|
|
5031
4632
|
}
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
const pathParams = {
|
|
5037
|
-
key: request?.key,
|
|
4633
|
+
else {
|
|
4634
|
+
result = {
|
|
4635
|
+
changed: false,
|
|
4636
|
+
activities,
|
|
5038
4637
|
};
|
|
5039
|
-
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/moderation/config/{key}', pathParams, queryParams);
|
|
5040
|
-
decoders.DeleteModerationConfigResponse?.(response.body);
|
|
5041
|
-
return { ...response.body, metadata: response.metadata };
|
|
5042
4638
|
}
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
4639
|
+
const newActivitiesDeduplicated = [];
|
|
4640
|
+
newActivities.forEach((newActivityResponse) => {
|
|
4641
|
+
const index = activities.findIndex((a) => a.id === newActivityResponse.id);
|
|
4642
|
+
if (index === -1) {
|
|
4643
|
+
newActivitiesDeduplicated.push(newActivityResponse);
|
|
4644
|
+
}
|
|
4645
|
+
});
|
|
4646
|
+
if (newActivitiesDeduplicated.length > 0) {
|
|
4647
|
+
// TODO: since feed activities are not necessarily ordered by created_at (personalization) we don't order by created_at
|
|
4648
|
+
// Maybe we can add a flag to the JS client to support order by created_at
|
|
4649
|
+
const updatedActivities = [
|
|
4650
|
+
...(position === 'start' ? newActivitiesDeduplicated : []),
|
|
4651
|
+
...activities,
|
|
4652
|
+
...(position === 'end' ? newActivitiesDeduplicated : []),
|
|
4653
|
+
];
|
|
4654
|
+
result = { changed: true, activities: updatedActivities };
|
|
5053
4655
|
}
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
};
|
|
5062
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/configs', undefined, undefined, body, 'application/json');
|
|
5063
|
-
decoders.QueryModerationConfigsResponse?.(response.body);
|
|
5064
|
-
return { ...response.body, metadata: response.metadata };
|
|
4656
|
+
return result;
|
|
4657
|
+
};
|
|
4658
|
+
function handleActivityAdded(event) {
|
|
4659
|
+
const currentActivities = this.currentState.activities;
|
|
4660
|
+
const result = addActivitiesToState([event.activity], currentActivities, 'start');
|
|
4661
|
+
if (result.changed) {
|
|
4662
|
+
this.client.hydratePollCache([event.activity]);
|
|
4663
|
+
this.state.partialNext({ activities: result.activities });
|
|
5065
4664
|
}
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
};
|
|
5075
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/flag', undefined, undefined, body, 'application/json');
|
|
5076
|
-
decoders.FlagResponse?.(response.body);
|
|
5077
|
-
return { ...response.body, metadata: response.metadata };
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
const removeActivityFromState = (activityResponse, activities) => {
|
|
4668
|
+
const index = activities.findIndex((a) => a.id === activityResponse.id);
|
|
4669
|
+
if (index !== -1) {
|
|
4670
|
+
const newActivities = [...activities];
|
|
4671
|
+
newActivities.splice(index, 1);
|
|
4672
|
+
return { changed: true, activities: newActivities };
|
|
5078
4673
|
}
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
target_ids: request?.target_ids,
|
|
5082
|
-
timeout: request?.timeout,
|
|
5083
|
-
};
|
|
5084
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/mute', undefined, undefined, body, 'application/json');
|
|
5085
|
-
decoders.MuteResponse?.(response.body);
|
|
5086
|
-
return { ...response.body, metadata: response.metadata };
|
|
4674
|
+
else {
|
|
4675
|
+
return { changed: false, activities };
|
|
5087
4676
|
}
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
stats_only: request?.stats_only,
|
|
5097
|
-
sort: request?.sort,
|
|
5098
|
-
filter: request?.filter,
|
|
5099
|
-
};
|
|
5100
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/review_queue', undefined, undefined, body, 'application/json');
|
|
5101
|
-
decoders.QueryReviewQueueResponse?.(response.body);
|
|
5102
|
-
return { ...response.body, metadata: response.metadata };
|
|
4677
|
+
};
|
|
4678
|
+
function handleActivityDeleted(event) {
|
|
4679
|
+
const currentActivities = this.currentState.activities;
|
|
4680
|
+
if (currentActivities) {
|
|
4681
|
+
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4682
|
+
if (result.changed) {
|
|
4683
|
+
this.state.partialNext({ activities: result.activities });
|
|
4684
|
+
}
|
|
5103
4685
|
}
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
delete_user: request?.delete_user,
|
|
5114
|
-
mark_reviewed: request?.mark_reviewed,
|
|
5115
|
-
unban: request?.unban,
|
|
5116
|
-
};
|
|
5117
|
-
const response = await this.apiClient.sendRequest('POST', '/api/v2/moderation/submit_action', undefined, undefined, body, 'application/json');
|
|
5118
|
-
decoders.SubmitActionResponse?.(response.body);
|
|
5119
|
-
return { ...response.body, metadata: response.metadata };
|
|
4686
|
+
}
|
|
4687
|
+
|
|
4688
|
+
function handleActivityRemovedFromFeed(event) {
|
|
4689
|
+
const currentActivities = this.currentState.activities;
|
|
4690
|
+
if (currentActivities) {
|
|
4691
|
+
const result = removeActivityFromState(event.activity, currentActivities);
|
|
4692
|
+
if (result.changed) {
|
|
4693
|
+
this.state.partialNext({ activities: result.activities });
|
|
4694
|
+
}
|
|
5120
4695
|
}
|
|
5121
4696
|
}
|
|
5122
4697
|
|
|
5123
|
-
|
|
4698
|
+
const updateActivityInState = (updatedActivityResponse, activities, replaceCompletely = false) => {
|
|
4699
|
+
const index = activities.findIndex((a) => a.id === updatedActivityResponse.id);
|
|
4700
|
+
if (index !== -1) {
|
|
4701
|
+
const newActivities = [...activities];
|
|
4702
|
+
const activity = activities[index];
|
|
4703
|
+
if (replaceCompletely) {
|
|
4704
|
+
newActivities[index] = updatedActivityResponse;
|
|
4705
|
+
}
|
|
4706
|
+
else {
|
|
4707
|
+
newActivities[index] = {
|
|
4708
|
+
...updatedActivityResponse,
|
|
4709
|
+
own_reactions: activity.own_reactions,
|
|
4710
|
+
own_bookmarks: activity.own_bookmarks,
|
|
4711
|
+
latest_reactions: activity.latest_reactions,
|
|
4712
|
+
reaction_groups: activity.reaction_groups,
|
|
4713
|
+
};
|
|
4714
|
+
}
|
|
4715
|
+
return { changed: true, activities: newActivities };
|
|
4716
|
+
}
|
|
4717
|
+
else {
|
|
4718
|
+
return { changed: false, activities };
|
|
4719
|
+
}
|
|
4720
|
+
};
|
|
4721
|
+
function handleActivityUpdated(event) {
|
|
4722
|
+
const currentActivities = this.currentState.activities;
|
|
4723
|
+
if (currentActivities) {
|
|
4724
|
+
const result = updateActivityInState(event.activity, currentActivities);
|
|
4725
|
+
if (result.changed) {
|
|
4726
|
+
this.client.hydratePollCache([event.activity]);
|
|
4727
|
+
this.state.partialNext({ activities: result.activities });
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
5124
4730
|
}
|
|
5125
4731
|
|
|
5126
|
-
const
|
|
5127
|
-
|
|
5128
|
-
const
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
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
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
4732
|
+
const addReactionToActivity = (event, activity, isCurrentUser) => {
|
|
4733
|
+
// Update own_reactions if the reaction is from the current user
|
|
4734
|
+
const ownReactions = [...(activity.own_reactions || [])];
|
|
4735
|
+
if (isCurrentUser) {
|
|
4736
|
+
ownReactions.push(event.reaction);
|
|
4737
|
+
}
|
|
4738
|
+
return {
|
|
4739
|
+
...activity,
|
|
4740
|
+
own_reactions: ownReactions,
|
|
4741
|
+
latest_reactions: event.activity.latest_reactions,
|
|
4742
|
+
reaction_groups: event.activity.reaction_groups,
|
|
4743
|
+
changed: true,
|
|
4744
|
+
};
|
|
4745
|
+
};
|
|
4746
|
+
const addReactionToActivities = (event, activities, isCurrentUser) => {
|
|
4747
|
+
if (!activities) {
|
|
4748
|
+
return { changed: false, activities: [] };
|
|
4749
|
+
}
|
|
4750
|
+
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
4751
|
+
if (activityIndex === -1) {
|
|
4752
|
+
return { changed: false, activities };
|
|
4753
|
+
}
|
|
4754
|
+
const activity = activities[activityIndex];
|
|
4755
|
+
const updatedActivity = addReactionToActivity(event, activity, isCurrentUser);
|
|
4756
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4757
|
+
};
|
|
4758
|
+
function handleActivityReactionAdded(event) {
|
|
4759
|
+
const currentActivities = this.currentState.activities;
|
|
4760
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4761
|
+
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4762
|
+
const result = addReactionToActivities(event, currentActivities, isCurrentUser);
|
|
4763
|
+
if (result.changed) {
|
|
4764
|
+
this.state.partialNext({ activities: result.activities });
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
|
|
4768
|
+
const removeReactionFromActivity = (event, activity, isCurrentUser) => {
|
|
4769
|
+
// Update own_reactions if the reaction is from the current user
|
|
4770
|
+
const ownReactions = isCurrentUser
|
|
4771
|
+
? (activity.own_reactions || []).filter((r) => !(r.type === event.reaction.type &&
|
|
4772
|
+
r.user.id === event.reaction.user.id))
|
|
4773
|
+
: activity.own_reactions;
|
|
4774
|
+
return {
|
|
4775
|
+
...activity,
|
|
4776
|
+
own_reactions: ownReactions,
|
|
4777
|
+
latest_reactions: event.activity.latest_reactions,
|
|
4778
|
+
reaction_groups: event.activity.reaction_groups,
|
|
4779
|
+
changed: true,
|
|
4780
|
+
};
|
|
4781
|
+
};
|
|
4782
|
+
const removeReactionFromActivities = (event, activities, isCurrentUser) => {
|
|
4783
|
+
if (!activities) {
|
|
4784
|
+
return { changed: false, activities: [] };
|
|
4785
|
+
}
|
|
4786
|
+
const activityIndex = activities.findIndex((a) => a.id === event.activity.id);
|
|
4787
|
+
if (activityIndex === -1) {
|
|
4788
|
+
return { changed: false, activities };
|
|
4789
|
+
}
|
|
4790
|
+
const activity = activities[activityIndex];
|
|
4791
|
+
const updatedActivity = removeReactionFromActivity(event, activity, isCurrentUser);
|
|
4792
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4793
|
+
};
|
|
4794
|
+
function handleActivityReactionDeleted(event) {
|
|
4795
|
+
const currentActivities = this.currentState.activities;
|
|
4796
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4797
|
+
const isCurrentUser = Boolean(connectedUser && event.reaction.user.id === connectedUser.id);
|
|
4798
|
+
const result = removeReactionFromActivities(event, currentActivities, isCurrentUser);
|
|
4799
|
+
if (result.changed) {
|
|
4800
|
+
this.state.partialNext({ activities: result.activities });
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
|
|
4804
|
+
const addBookmarkToActivity = (event, activity, isCurrentUser) => {
|
|
4805
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
4806
|
+
const ownBookmarks = [...(activity.own_bookmarks || [])];
|
|
4807
|
+
if (isCurrentUser) {
|
|
4808
|
+
ownBookmarks.push(event.bookmark);
|
|
4809
|
+
}
|
|
4810
|
+
return {
|
|
4811
|
+
...activity,
|
|
4812
|
+
own_bookmarks: ownBookmarks,
|
|
4813
|
+
changed: true,
|
|
4814
|
+
};
|
|
4815
|
+
};
|
|
4816
|
+
const addBookmarkToActivities = (event, activities, isCurrentUser) => {
|
|
4817
|
+
if (!activities) {
|
|
4818
|
+
return { changed: false, activities: [] };
|
|
4819
|
+
}
|
|
4820
|
+
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4821
|
+
if (activityIndex === -1) {
|
|
4822
|
+
return { changed: false, activities };
|
|
4823
|
+
}
|
|
4824
|
+
const activity = activities[activityIndex];
|
|
4825
|
+
const updatedActivity = addBookmarkToActivity(event, activity, isCurrentUser);
|
|
4826
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4827
|
+
};
|
|
4828
|
+
function handleBookmarkAdded(event) {
|
|
4829
|
+
const currentActivities = this.currentState.activities;
|
|
4830
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4831
|
+
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4832
|
+
const result = addBookmarkToActivities(event, currentActivities, isCurrentUser);
|
|
4833
|
+
if (result.changed) {
|
|
4834
|
+
this.state.partialNext({ activities: result.activities });
|
|
4835
|
+
}
|
|
4836
|
+
}
|
|
4837
|
+
|
|
4838
|
+
// Helper function to check if two bookmarks are the same
|
|
4839
|
+
// A bookmark is identified by activity_id + folder_id + user_id
|
|
4840
|
+
const isSameBookmark = (bookmark1, bookmark2) => {
|
|
4841
|
+
return (bookmark1.user.id === bookmark2.user.id &&
|
|
4842
|
+
bookmark1.activity.id === bookmark2.activity.id &&
|
|
4843
|
+
bookmark1.folder?.id === bookmark2.folder?.id);
|
|
4844
|
+
};
|
|
4845
|
+
const removeBookmarkFromActivities = (event, activities, isCurrentUser) => {
|
|
4846
|
+
if (!activities) {
|
|
4847
|
+
return { changed: false, activities: [] };
|
|
4848
|
+
}
|
|
4849
|
+
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4850
|
+
if (activityIndex === -1) {
|
|
4851
|
+
return { changed: false, activities };
|
|
4852
|
+
}
|
|
4853
|
+
const activity = activities[activityIndex];
|
|
4854
|
+
const updatedActivity = removeBookmarkFromActivity(event, activity, isCurrentUser);
|
|
4855
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4856
|
+
};
|
|
4857
|
+
const removeBookmarkFromActivity = (event, activity, isCurrentUser) => {
|
|
4858
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
4859
|
+
const ownBookmarks = isCurrentUser
|
|
4860
|
+
? (activity.own_bookmarks || []).filter((bookmark) => !isSameBookmark(bookmark, event.bookmark))
|
|
4861
|
+
: activity.own_bookmarks;
|
|
4862
|
+
return {
|
|
4863
|
+
...activity,
|
|
4864
|
+
own_bookmarks: ownBookmarks,
|
|
4865
|
+
changed: true,
|
|
4866
|
+
};
|
|
4867
|
+
};
|
|
4868
|
+
function handleBookmarkDeleted(event) {
|
|
4869
|
+
const currentActivities = this.currentState.activities;
|
|
4870
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4871
|
+
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4872
|
+
const result = removeBookmarkFromActivities(event, currentActivities, isCurrentUser);
|
|
4873
|
+
if (result.changed) {
|
|
4874
|
+
this.state.partialNext({ activities: result.activities });
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4877
|
+
|
|
4878
|
+
const updateBookmarkInActivity = (event, activity, isCurrentUser) => {
|
|
4879
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
4880
|
+
let ownBookmarks = activity.own_bookmarks || [];
|
|
4881
|
+
if (isCurrentUser) {
|
|
4882
|
+
const bookmarkIndex = ownBookmarks.findIndex((bookmark) => isSameBookmark(bookmark, event.bookmark));
|
|
4883
|
+
if (bookmarkIndex !== -1) {
|
|
4884
|
+
ownBookmarks = [...ownBookmarks];
|
|
4885
|
+
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
4886
|
+
}
|
|
4887
|
+
}
|
|
4888
|
+
return {
|
|
4889
|
+
...activity,
|
|
4890
|
+
own_bookmarks: ownBookmarks,
|
|
4891
|
+
changed: true,
|
|
4892
|
+
};
|
|
4893
|
+
};
|
|
4894
|
+
const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
4895
|
+
if (!activities) {
|
|
4896
|
+
return { changed: false, activities: [] };
|
|
4897
|
+
}
|
|
4898
|
+
const activityIndex = activities.findIndex((a) => a.id === event.bookmark.activity.id);
|
|
4899
|
+
if (activityIndex === -1) {
|
|
4900
|
+
return { changed: false, activities };
|
|
4901
|
+
}
|
|
4902
|
+
const activity = activities[activityIndex];
|
|
4903
|
+
const updatedActivity = updateBookmarkInActivity(event, activity, isCurrentUser);
|
|
4904
|
+
return updateActivityInState(updatedActivity, activities, true);
|
|
4905
|
+
};
|
|
4906
|
+
function handleBookmarkUpdated(event) {
|
|
4907
|
+
const currentActivities = this.currentState.activities;
|
|
4908
|
+
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4909
|
+
const isCurrentUser = event.bookmark.user.id === connectedUser?.id;
|
|
4910
|
+
const result = updateBookmarkInActivities(event, currentActivities, isCurrentUser);
|
|
4911
|
+
if (result.changed) {
|
|
4912
|
+
this.state.partialNext({ activities: result.activities });
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
|
|
4916
|
+
function handleFeedUpdated(event) {
|
|
4917
|
+
this.state.partialNext({ ...event.feed });
|
|
4918
|
+
}
|
|
4919
|
+
|
|
4920
|
+
function handleNotificationFeedUpdated(event) {
|
|
4921
|
+
console.info('notification feed updated', event);
|
|
4922
|
+
// TODO: handle notification feed updates
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
function handleWatchStarted() {
|
|
4926
|
+
this.state.partialNext({ watch: true });
|
|
4927
|
+
}
|
|
4928
|
+
|
|
4929
|
+
function handleWatchStopped() {
|
|
4930
|
+
this.state.partialNext({ watch: false });
|
|
4931
|
+
}
|
|
4932
|
+
|
|
4933
|
+
class Feed extends FeedApi {
|
|
4934
|
+
constructor(client, groupId, id, data, watch = false) {
|
|
4935
|
+
super(client, groupId, id);
|
|
4936
|
+
this.stateUpdateQueue = new Set();
|
|
4937
|
+
this.eventHandlers = {
|
|
4938
|
+
'feeds.activity.added': handleActivityAdded.bind(this),
|
|
4939
|
+
'feeds.activity.deleted': handleActivityDeleted.bind(this),
|
|
4940
|
+
'feeds.activity.reaction.added': handleActivityReactionAdded.bind(this),
|
|
4941
|
+
'feeds.activity.reaction.deleted': handleActivityReactionDeleted.bind(this),
|
|
4942
|
+
'feeds.activity.reaction.updated': Feed.noop,
|
|
4943
|
+
'feeds.activity.removed_from_feed': handleActivityRemovedFromFeed.bind(this),
|
|
4944
|
+
'feeds.activity.updated': handleActivityUpdated.bind(this),
|
|
4945
|
+
'feeds.bookmark.added': handleBookmarkAdded.bind(this),
|
|
4946
|
+
'feeds.bookmark.deleted': handleBookmarkDeleted.bind(this),
|
|
4947
|
+
'feeds.bookmark.updated': handleBookmarkUpdated.bind(this),
|
|
4948
|
+
'feeds.bookmark_folder.deleted': Feed.noop,
|
|
4949
|
+
'feeds.bookmark_folder.updated': Feed.noop,
|
|
4950
|
+
'feeds.comment.added': handleCommentAdded.bind(this),
|
|
4951
|
+
'feeds.comment.deleted': handleCommentDeleted.bind(this),
|
|
4952
|
+
'feeds.comment.updated': handleCommentUpdated.bind(this),
|
|
4953
|
+
'feeds.feed.created': Feed.noop,
|
|
4954
|
+
'feeds.feed.deleted': Feed.noop,
|
|
4955
|
+
'feeds.feed.updated': handleFeedUpdated.bind(this),
|
|
4956
|
+
'feeds.feed_group.changed': Feed.noop,
|
|
4957
|
+
'feeds.feed_group.deleted': Feed.noop,
|
|
4958
|
+
'feeds.follow.created': handleFollowCreated.bind(this),
|
|
4959
|
+
'feeds.follow.deleted': handleFollowDeleted.bind(this),
|
|
4960
|
+
'feeds.follow.updated': handleFollowUpdated.bind(this),
|
|
4961
|
+
'feeds.comment.reaction.added': handleCommentReaction.bind(this),
|
|
4962
|
+
'feeds.comment.reaction.deleted': handleCommentReaction.bind(this),
|
|
4963
|
+
'feeds.comment.reaction.updated': Feed.noop,
|
|
4964
|
+
'feeds.feed_member.added': handleFeedMemberAdded.bind(this),
|
|
4965
|
+
'feeds.feed_member.removed': handleFeedMemberRemoved.bind(this),
|
|
4966
|
+
'feeds.feed_member.updated': handleFeedMemberUpdated.bind(this),
|
|
4967
|
+
'feeds.notification_feed.updated': handleNotificationFeedUpdated.bind(this),
|
|
4968
|
+
// the poll events should be removed from here
|
|
4969
|
+
'feeds.poll.closed': Feed.noop,
|
|
4970
|
+
'feeds.poll.deleted': Feed.noop,
|
|
4971
|
+
'feeds.poll.updated': Feed.noop,
|
|
4972
|
+
'feeds.poll.vote_casted': Feed.noop,
|
|
4973
|
+
'feeds.poll.vote_changed': Feed.noop,
|
|
4974
|
+
'feeds.poll.vote_removed': Feed.noop,
|
|
4975
|
+
'feeds.activity.pinned': Feed.noop,
|
|
4976
|
+
'feeds.activity.unpinned': Feed.noop,
|
|
4977
|
+
'feeds.activity.marked': Feed.noop,
|
|
4978
|
+
'moderation.custom_action': Feed.noop,
|
|
4979
|
+
'moderation.flagged': Feed.noop,
|
|
4980
|
+
'moderation.mark_reviewed': Feed.noop,
|
|
4981
|
+
'health.check': Feed.noop,
|
|
4982
|
+
'app.updated': Feed.noop,
|
|
4983
|
+
'user.banned': Feed.noop,
|
|
4984
|
+
'user.deactivated': Feed.noop,
|
|
4985
|
+
'user.muted': Feed.noop,
|
|
4986
|
+
'user.reactivated': Feed.noop,
|
|
4987
|
+
'user.updated': Feed.noop,
|
|
5222
4988
|
};
|
|
5223
|
-
this.
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
4989
|
+
this.eventDispatcher = new EventDispatcher();
|
|
4990
|
+
this.on = this.eventDispatcher.on;
|
|
4991
|
+
this.off = this.eventDispatcher.off;
|
|
4992
|
+
this.state = new StateStore({
|
|
4993
|
+
feed: `${groupId}:${id}`,
|
|
4994
|
+
group_id: groupId,
|
|
4995
|
+
id,
|
|
4996
|
+
...(data ?? {}),
|
|
4997
|
+
is_loading: false,
|
|
4998
|
+
is_loading_activities: false,
|
|
4999
|
+
comments_by_entity_id: {},
|
|
5000
|
+
watch,
|
|
5001
|
+
});
|
|
5002
|
+
this.client = client;
|
|
5003
|
+
}
|
|
5004
|
+
get feed() {
|
|
5005
|
+
return `${this.group}:${this.id}`;
|
|
5006
|
+
}
|
|
5007
|
+
get currentState() {
|
|
5008
|
+
return this.state.getLatestValue();
|
|
5009
|
+
}
|
|
5010
|
+
async synchronize() {
|
|
5011
|
+
const { last_get_or_create_request_config } = this.state.getLatestValue();
|
|
5012
|
+
if (last_get_or_create_request_config?.watch) {
|
|
5013
|
+
await this.getOrCreate(last_get_or_create_request_config);
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
async getOrCreate(request) {
|
|
5017
|
+
if (this.currentState.is_loading_activities) {
|
|
5018
|
+
throw new Error('Only one getOrCreate call is allowed at a time');
|
|
5019
|
+
}
|
|
5020
|
+
this.state.partialNext({
|
|
5021
|
+
is_loading: !request?.next,
|
|
5022
|
+
is_loading_activities: true,
|
|
5023
|
+
});
|
|
5024
|
+
// TODO: pull comments/comment_pagination from activities and comment_sort from request
|
|
5025
|
+
// and pre-populate comments_by_entity_id (once comment_sort and comment_limit are supported)
|
|
5026
|
+
try {
|
|
5027
|
+
const response = await super.getOrCreate(request);
|
|
5028
|
+
if (request?.next) {
|
|
5029
|
+
const { activities: currentActivities = [] } = this.currentState;
|
|
5030
|
+
const result = addActivitiesToState(response.activities, currentActivities, 'end');
|
|
5031
|
+
if (result.changed) {
|
|
5032
|
+
this.state.partialNext({
|
|
5033
|
+
activities: result.activities,
|
|
5034
|
+
next: response.next,
|
|
5035
|
+
prev: response.prev,
|
|
5036
|
+
});
|
|
5246
5037
|
}
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5038
|
+
}
|
|
5039
|
+
else {
|
|
5040
|
+
// Empty queue when reinitializing the state
|
|
5041
|
+
this.stateUpdateQueue.clear();
|
|
5042
|
+
const responseCopy = {
|
|
5043
|
+
...response,
|
|
5044
|
+
...response.feed,
|
|
5045
|
+
};
|
|
5046
|
+
delete responseCopy.feed;
|
|
5047
|
+
delete responseCopy.metadata;
|
|
5048
|
+
delete responseCopy.duration;
|
|
5049
|
+
// TODO: lazy-load comments from activities when comment_sort and comment_pagination are supported
|
|
5050
|
+
this.state.next((currentState) => {
|
|
5051
|
+
const nextState = {
|
|
5052
|
+
...currentState,
|
|
5053
|
+
...responseCopy,
|
|
5054
|
+
};
|
|
5055
|
+
if (!request?.followers_pagination?.limit) {
|
|
5056
|
+
delete nextState.followers;
|
|
5251
5057
|
}
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
if (optionId !== event.poll_vote.option_id &&
|
|
5255
|
-
vote.id === event.poll_vote.id) {
|
|
5256
|
-
return acc;
|
|
5257
|
-
}
|
|
5258
|
-
acc[optionId] = vote;
|
|
5259
|
-
return acc;
|
|
5260
|
-
}, {});
|
|
5261
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5262
|
-
ownVotesByOptionId[event.poll_vote.option_id] = event.poll_vote;
|
|
5058
|
+
if (!request?.following_pagination?.limit) {
|
|
5059
|
+
delete nextState.following;
|
|
5263
5060
|
}
|
|
5264
|
-
if (
|
|
5265
|
-
|
|
5061
|
+
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
5062
|
+
delete nextState.members;
|
|
5266
5063
|
}
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
else if (isVoteAnswer(event.poll_vote)) {
|
|
5272
|
-
// @ts-expect-error Incompatibility between PollResponseData and Poll due to teams_role, remove when OpenAPI spec is fixed
|
|
5273
|
-
latestAnswers = [event.poll_vote, ...latestAnswers];
|
|
5274
|
-
}
|
|
5275
|
-
else {
|
|
5276
|
-
maxVotedOptionIds = getMaxVotedOptionIds(event.poll.vote_counts_by_option);
|
|
5064
|
+
nextState.last_get_or_create_request_config = request;
|
|
5065
|
+
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
5066
|
+
return nextState;
|
|
5067
|
+
});
|
|
5277
5068
|
}
|
|
5278
|
-
|
|
5069
|
+
this.client.hydratePollCache(response.activities);
|
|
5070
|
+
return response;
|
|
5071
|
+
}
|
|
5072
|
+
finally {
|
|
5279
5073
|
this.state.partialNext({
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5074
|
+
is_loading: false,
|
|
5075
|
+
is_loading_activities: false,
|
|
5076
|
+
});
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
5079
|
+
/**
|
|
5080
|
+
* Returns index of the provided comment object.
|
|
5081
|
+
*/
|
|
5082
|
+
getCommentIndex(comment, state) {
|
|
5083
|
+
const { comments_by_entity_id = {} } = state ?? this.currentState;
|
|
5084
|
+
const currentComments = comments_by_entity_id[comment.parent_id ?? comment.object_id]?.comments;
|
|
5085
|
+
if (!currentComments?.length) {
|
|
5086
|
+
return -1;
|
|
5087
|
+
}
|
|
5088
|
+
// @ts-expect-error this will just fail if the comment is not object from state
|
|
5089
|
+
let commentIndex = currentComments.indexOf(comment);
|
|
5090
|
+
// fast lookup failed, try slower approach
|
|
5091
|
+
if (commentIndex === -1) {
|
|
5092
|
+
commentIndex = currentComments.findIndex((comment_) => comment_.id === comment.id);
|
|
5093
|
+
}
|
|
5094
|
+
return commentIndex;
|
|
5095
|
+
}
|
|
5096
|
+
/**
|
|
5097
|
+
* Load child comments of entity (activity or comment) into the state, if the target entity is comment,
|
|
5098
|
+
* `entityParentId` should be provided (`CommentResponse.parent_id ?? CommentResponse.object_id`).
|
|
5099
|
+
*/
|
|
5100
|
+
loadCommentsIntoState(data) {
|
|
5101
|
+
// add initial (top level) object for processing
|
|
5102
|
+
const traverseArray = [
|
|
5103
|
+
{
|
|
5104
|
+
entityId: data.entityId,
|
|
5105
|
+
entityParentId: data.entityParentId,
|
|
5106
|
+
comments: data.comments,
|
|
5107
|
+
next: data.next,
|
|
5108
|
+
},
|
|
5109
|
+
];
|
|
5110
|
+
this.state.next((currentState) => {
|
|
5111
|
+
const newCommentsByEntityId = {
|
|
5112
|
+
...currentState.comments_by_entity_id,
|
|
5113
|
+
};
|
|
5114
|
+
while (traverseArray.length) {
|
|
5115
|
+
const item = traverseArray.pop();
|
|
5116
|
+
const entityId = item.entityId;
|
|
5117
|
+
// go over entity comments and generate new objects
|
|
5118
|
+
// for further processing if there are any replies
|
|
5119
|
+
item.comments.forEach((comment) => {
|
|
5120
|
+
if (!comment.replies?.length)
|
|
5121
|
+
return;
|
|
5122
|
+
traverseArray.push({
|
|
5123
|
+
entityId: comment.id,
|
|
5124
|
+
entityParentId: entityId,
|
|
5125
|
+
comments: comment.replies,
|
|
5126
|
+
next: comment.meta?.next_cursor,
|
|
5127
|
+
});
|
|
5128
|
+
});
|
|
5129
|
+
// omit replies & meta from the comments (transform ThreadedCommentResponse to CommentResponse)
|
|
5130
|
+
// this is somehow faster than copying the whole
|
|
5131
|
+
// object and deleting the desired properties
|
|
5132
|
+
const newComments = item.comments.map(({ replies: _r, meta: _m, ...restOfTheCommentResponse }) => restOfTheCommentResponse);
|
|
5133
|
+
const existingComments = newCommentsByEntityId[entityId]?.comments;
|
|
5134
|
+
newCommentsByEntityId[entityId] = {
|
|
5135
|
+
...newCommentsByEntityId[entityId],
|
|
5136
|
+
entity_parent_id: item.entityParentId,
|
|
5137
|
+
pagination: {
|
|
5138
|
+
...newCommentsByEntityId[entityId]?.pagination,
|
|
5139
|
+
next: item.next,
|
|
5140
|
+
sort: data.sort,
|
|
5141
|
+
},
|
|
5142
|
+
comments: existingComments
|
|
5143
|
+
? uniqueArrayMerge(existingComments, newComments, (comment) => comment.id)
|
|
5144
|
+
: newComments,
|
|
5145
|
+
};
|
|
5146
|
+
}
|
|
5147
|
+
return {
|
|
5148
|
+
...currentState,
|
|
5149
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
5150
|
+
};
|
|
5151
|
+
});
|
|
5152
|
+
}
|
|
5153
|
+
async loadNextPageComments({ entityId, base, sort, entityParentId, }) {
|
|
5154
|
+
let error;
|
|
5155
|
+
try {
|
|
5156
|
+
this.state.next((currentState) => ({
|
|
5157
|
+
...currentState,
|
|
5158
|
+
comments_by_entity_id: {
|
|
5159
|
+
...currentState.comments_by_entity_id,
|
|
5160
|
+
[entityId]: {
|
|
5161
|
+
...currentState.comments_by_entity_id[entityId],
|
|
5162
|
+
pagination: {
|
|
5163
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
5164
|
+
loading_next_page: true,
|
|
5165
|
+
},
|
|
5166
|
+
},
|
|
5167
|
+
},
|
|
5168
|
+
}));
|
|
5169
|
+
const { next, comments } = await base();
|
|
5170
|
+
this.loadCommentsIntoState({
|
|
5171
|
+
entityId,
|
|
5172
|
+
comments,
|
|
5173
|
+
entityParentId,
|
|
5174
|
+
next,
|
|
5175
|
+
sort,
|
|
5176
|
+
});
|
|
5177
|
+
}
|
|
5178
|
+
catch (e) {
|
|
5179
|
+
error = e;
|
|
5180
|
+
}
|
|
5181
|
+
finally {
|
|
5182
|
+
this.state.next((currentState) => ({
|
|
5183
|
+
...currentState,
|
|
5184
|
+
comments_by_entity_id: {
|
|
5185
|
+
...currentState.comments_by_entity_id,
|
|
5186
|
+
[entityId]: {
|
|
5187
|
+
...currentState.comments_by_entity_id[entityId],
|
|
5188
|
+
pagination: {
|
|
5189
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
5190
|
+
loading_next_page: false,
|
|
5191
|
+
},
|
|
5192
|
+
},
|
|
5193
|
+
},
|
|
5194
|
+
}));
|
|
5195
|
+
}
|
|
5196
|
+
if (error) {
|
|
5197
|
+
throw error;
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
async loadNextPageActivityComments(activity, request) {
|
|
5201
|
+
const currentEntityState = this.currentState.comments_by_entity_id[activity.id];
|
|
5202
|
+
const currentPagination = currentEntityState?.pagination;
|
|
5203
|
+
const currentNextCursor = currentPagination?.next;
|
|
5204
|
+
const currentSort = currentPagination?.sort;
|
|
5205
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
5206
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
5207
|
+
if (isLoading ||
|
|
5208
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
5209
|
+
return;
|
|
5210
|
+
}
|
|
5211
|
+
await this.loadNextPageComments({
|
|
5212
|
+
entityId: activity.id,
|
|
5213
|
+
base: () => this.client.getComments({
|
|
5214
|
+
...request,
|
|
5215
|
+
sort,
|
|
5216
|
+
object_id: activity.id,
|
|
5217
|
+
object_type: 'activity',
|
|
5218
|
+
next: currentNextCursor,
|
|
5219
|
+
}),
|
|
5220
|
+
sort,
|
|
5221
|
+
});
|
|
5222
|
+
}
|
|
5223
|
+
async loadNextPageCommentReplies(comment, request) {
|
|
5224
|
+
const currentEntityState = this.currentState.comments_by_entity_id[comment.id];
|
|
5225
|
+
const currentPagination = currentEntityState?.pagination;
|
|
5226
|
+
const currentNextCursor = currentPagination?.next;
|
|
5227
|
+
const currentSort = currentPagination?.sort;
|
|
5228
|
+
const isLoading = currentPagination?.loading_next_page;
|
|
5229
|
+
const sort = currentSort ?? request?.sort ?? Constants.DEFAULT_COMMENT_PAGINATION;
|
|
5230
|
+
if (isLoading ||
|
|
5231
|
+
!checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
|
|
5232
|
+
return;
|
|
5233
|
+
}
|
|
5234
|
+
await this.loadNextPageComments({
|
|
5235
|
+
entityId: comment.id,
|
|
5236
|
+
base: () => this.client.getCommentReplies({
|
|
5237
|
+
...request,
|
|
5238
|
+
id: comment.id,
|
|
5239
|
+
// use known sort first (prevents broken pagination)
|
|
5240
|
+
sort,
|
|
5241
|
+
next: currentNextCursor,
|
|
5242
|
+
}),
|
|
5243
|
+
entityParentId: comment.parent_id ?? comment.object_id,
|
|
5244
|
+
sort,
|
|
5245
|
+
});
|
|
5246
|
+
}
|
|
5247
|
+
async loadNextPageFollows(type, request) {
|
|
5248
|
+
const paginationKey = `${type}_pagination`;
|
|
5249
|
+
const method = `query${capitalize(type)}`;
|
|
5250
|
+
const currentFollows = this.currentState[type];
|
|
5251
|
+
const currentNextCursor = this.currentState[paginationKey]?.next;
|
|
5252
|
+
const isLoading = this.currentState[paginationKey]?.loading_next_page;
|
|
5253
|
+
const sort = this.currentState[paginationKey]?.sort ?? request.sort;
|
|
5254
|
+
let error;
|
|
5255
|
+
if (isLoading || !checkHasAnotherPage(currentFollows, currentNextCursor)) {
|
|
5256
|
+
return;
|
|
5257
|
+
}
|
|
5258
|
+
try {
|
|
5259
|
+
this.state.next((currentState) => {
|
|
5260
|
+
return {
|
|
5261
|
+
...currentState,
|
|
5262
|
+
[paginationKey]: {
|
|
5263
|
+
...currentState[paginationKey],
|
|
5264
|
+
loading_next_page: true,
|
|
5265
|
+
},
|
|
5266
|
+
};
|
|
5290
5267
|
});
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5268
|
+
const { next: newNextCursor, follows } = await this[method]({
|
|
5269
|
+
...request,
|
|
5270
|
+
next: currentNextCursor,
|
|
5271
|
+
sort,
|
|
5272
|
+
});
|
|
5273
|
+
this.state.next((currentState) => {
|
|
5274
|
+
return {
|
|
5275
|
+
...currentState,
|
|
5276
|
+
[type]: currentState[type] === undefined
|
|
5277
|
+
? follows
|
|
5278
|
+
: uniqueArrayMerge(currentState[type], follows, (follow) => `${follow.source_feed.feed}-${follow.target_feed.feed}`),
|
|
5279
|
+
[paginationKey]: {
|
|
5280
|
+
...currentState[paginationKey],
|
|
5281
|
+
next: newNextCursor,
|
|
5282
|
+
sort,
|
|
5283
|
+
},
|
|
5284
|
+
};
|
|
5285
|
+
});
|
|
5286
|
+
}
|
|
5287
|
+
catch (e) {
|
|
5288
|
+
error = e;
|
|
5289
|
+
}
|
|
5290
|
+
finally {
|
|
5291
|
+
this.state.next((currentState) => {
|
|
5292
|
+
return {
|
|
5293
|
+
...currentState,
|
|
5294
|
+
[paginationKey]: {
|
|
5295
|
+
...currentState[paginationKey],
|
|
5296
|
+
loading_next_page: false,
|
|
5297
|
+
},
|
|
5298
|
+
};
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
if (error) {
|
|
5302
|
+
throw error;
|
|
5303
|
+
}
|
|
5304
|
+
}
|
|
5305
|
+
async loadNextPageFollowers(request) {
|
|
5306
|
+
await this.loadNextPageFollows('followers', request);
|
|
5307
|
+
}
|
|
5308
|
+
async loadNextPageFollowing(request) {
|
|
5309
|
+
await this.loadNextPageFollows('following', request);
|
|
5310
|
+
}
|
|
5311
|
+
async loadNextPageMembers(request) {
|
|
5312
|
+
const currentMembers = this.currentState.members;
|
|
5313
|
+
const currentNextCursor = this.currentState.member_pagination?.next;
|
|
5314
|
+
const isLoading = this.currentState.member_pagination?.loading_next_page;
|
|
5315
|
+
const sort = this.currentState.member_pagination?.sort ?? request.sort;
|
|
5316
|
+
let error;
|
|
5317
|
+
if (isLoading || !checkHasAnotherPage(currentMembers, currentNextCursor)) {
|
|
5318
|
+
return;
|
|
5319
|
+
}
|
|
5320
|
+
try {
|
|
5321
|
+
this.state.next((currentState) => ({
|
|
5322
|
+
...currentState,
|
|
5323
|
+
member_pagination: {
|
|
5324
|
+
...currentState.member_pagination,
|
|
5325
|
+
loading_next_page: true,
|
|
5326
|
+
},
|
|
5327
|
+
}));
|
|
5328
|
+
const { next: newNextCursor, members } = await this.client.queryFeedMembers({
|
|
5329
|
+
...request,
|
|
5330
|
+
sort,
|
|
5331
|
+
feed_id: this.id,
|
|
5332
|
+
feed_group_id: this.group,
|
|
5333
|
+
next: currentNextCursor,
|
|
5329
5334
|
});
|
|
5335
|
+
this.state.next((currentState) => ({
|
|
5336
|
+
...currentState,
|
|
5337
|
+
members: currentState.members
|
|
5338
|
+
? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
|
|
5339
|
+
: members,
|
|
5340
|
+
member_pagination: {
|
|
5341
|
+
...currentState.member_pagination,
|
|
5342
|
+
next: newNextCursor,
|
|
5343
|
+
// set sort if not defined yet
|
|
5344
|
+
sort: currentState.member_pagination?.sort ?? request.sort,
|
|
5345
|
+
},
|
|
5346
|
+
}));
|
|
5347
|
+
}
|
|
5348
|
+
catch (e) {
|
|
5349
|
+
error = e;
|
|
5350
|
+
}
|
|
5351
|
+
finally {
|
|
5352
|
+
this.state.next((currentState) => ({
|
|
5353
|
+
...currentState,
|
|
5354
|
+
member_pagination: {
|
|
5355
|
+
...currentState.member_pagination,
|
|
5356
|
+
loading_next_page: false,
|
|
5357
|
+
},
|
|
5358
|
+
}));
|
|
5359
|
+
}
|
|
5360
|
+
if (error) {
|
|
5361
|
+
throw error;
|
|
5362
|
+
}
|
|
5363
|
+
}
|
|
5364
|
+
/**
|
|
5365
|
+
* Method which queries followers of this feed (feeds which target this feed).
|
|
5366
|
+
*
|
|
5367
|
+
* _Note: Useful only for feeds with `groupId` of `user` value._
|
|
5368
|
+
*/
|
|
5369
|
+
async queryFollowers(request) {
|
|
5370
|
+
const filter = {
|
|
5371
|
+
target_feed: this.feed,
|
|
5330
5372
|
};
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5373
|
+
const response = await this.client.queryFollows({
|
|
5374
|
+
filter,
|
|
5375
|
+
...request,
|
|
5376
|
+
});
|
|
5377
|
+
return response;
|
|
5334
5378
|
}
|
|
5335
|
-
|
|
5336
|
-
|
|
5379
|
+
/**
|
|
5380
|
+
* Method which queries following of this feed (target feeds of this feed).
|
|
5381
|
+
*
|
|
5382
|
+
* _Note: Useful only for feeds with `groupId` of `timeline` value._
|
|
5383
|
+
*/
|
|
5384
|
+
async queryFollowing(request) {
|
|
5385
|
+
const filter = {
|
|
5386
|
+
source_feed: this.feed,
|
|
5387
|
+
};
|
|
5388
|
+
const response = await this.client.queryFollows({
|
|
5389
|
+
filter,
|
|
5390
|
+
...request,
|
|
5391
|
+
});
|
|
5392
|
+
return response;
|
|
5337
5393
|
}
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5394
|
+
async follow(feedOrFid, options) {
|
|
5395
|
+
const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.feed;
|
|
5396
|
+
const response = await this.client.follow({
|
|
5397
|
+
...options,
|
|
5398
|
+
source: this.feed,
|
|
5399
|
+
target: fid,
|
|
5400
|
+
});
|
|
5401
|
+
return response;
|
|
5402
|
+
}
|
|
5403
|
+
async unfollow(feedOrFid) {
|
|
5404
|
+
const fid = typeof feedOrFid === 'string' ? feedOrFid : feedOrFid.feed;
|
|
5405
|
+
const response = await this.client.unfollow({
|
|
5406
|
+
source: this.feed,
|
|
5407
|
+
target: fid,
|
|
5408
|
+
});
|
|
5409
|
+
return response;
|
|
5410
|
+
}
|
|
5411
|
+
async getNextPage() {
|
|
5412
|
+
const currentState = this.currentState;
|
|
5413
|
+
return await this.getOrCreate({
|
|
5414
|
+
member_pagination: {
|
|
5415
|
+
limit: 0,
|
|
5416
|
+
},
|
|
5417
|
+
followers_pagination: {
|
|
5418
|
+
limit: 0,
|
|
5419
|
+
},
|
|
5420
|
+
following_pagination: {
|
|
5421
|
+
limit: 0,
|
|
5422
|
+
},
|
|
5423
|
+
next: currentState.next,
|
|
5424
|
+
limit: currentState.last_get_or_create_request_config?.limit ?? 20,
|
|
5425
|
+
});
|
|
5426
|
+
}
|
|
5427
|
+
addActivity(request) {
|
|
5428
|
+
return this.feedsApi.addActivity({
|
|
5429
|
+
...request,
|
|
5430
|
+
feeds: [this.feed],
|
|
5431
|
+
});
|
|
5432
|
+
}
|
|
5433
|
+
handleWSEvent(event) {
|
|
5434
|
+
const eventHandler = this.eventHandlers[event.type];
|
|
5435
|
+
// no need to run noop function
|
|
5436
|
+
if (eventHandler !== Feed.noop) {
|
|
5437
|
+
// @ts-expect-error intersection of handler arguments results to never
|
|
5438
|
+
eventHandler?.(event);
|
|
5346
5439
|
}
|
|
5347
|
-
|
|
5348
|
-
|
|
5440
|
+
if (typeof eventHandler === 'undefined') {
|
|
5441
|
+
console.warn(`Received unknown event type: ${event.type}`, event);
|
|
5349
5442
|
}
|
|
5443
|
+
this.eventDispatcher.dispatch(event);
|
|
5350
5444
|
}
|
|
5351
|
-
return winningOptions;
|
|
5352
5445
|
}
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5446
|
+
Feed.noop = () => { };
|
|
5447
|
+
|
|
5448
|
+
function handleUserUpdated(event) {
|
|
5449
|
+
this.state.next((currentState) => {
|
|
5450
|
+
let newState;
|
|
5451
|
+
const { connected_user } = currentState;
|
|
5452
|
+
if (connected_user && connected_user.id === event.user.id) {
|
|
5453
|
+
newState ?? (newState = {
|
|
5454
|
+
...currentState,
|
|
5455
|
+
});
|
|
5456
|
+
newState.connected_user = {
|
|
5457
|
+
...connected_user,
|
|
5458
|
+
...event.user,
|
|
5459
|
+
};
|
|
5460
|
+
}
|
|
5461
|
+
// TODO: update other users in user map (if/once applicable)
|
|
5462
|
+
return newState ?? currentState;
|
|
5463
|
+
});
|
|
5362
5464
|
}
|
|
5363
5465
|
|
|
5364
5466
|
class FeedsClient extends FeedsApi {
|
|
@@ -5468,7 +5570,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5468
5570
|
if (this.activeFeeds[fid]) {
|
|
5469
5571
|
const feed = this.activeFeeds[fid];
|
|
5470
5572
|
if (watch && !feed.currentState.watch) {
|
|
5471
|
-
|
|
5573
|
+
handleWatchStarted.bind(feed)();
|
|
5472
5574
|
}
|
|
5473
5575
|
return feed;
|
|
5474
5576
|
}
|
|
@@ -5504,7 +5606,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5504
5606
|
}
|
|
5505
5607
|
else {
|
|
5506
5608
|
for (const activeFeed of Object.values(this.activeFeeds)) {
|
|
5507
|
-
|
|
5609
|
+
handleWatchStopped.bind(activeFeed)();
|
|
5508
5610
|
}
|
|
5509
5611
|
}
|
|
5510
5612
|
break;
|
|
@@ -5584,6 +5686,10 @@ class FeedsClient extends FeedsApi {
|
|
|
5584
5686
|
feeds.forEach((f) => f.handleWSEvent(event));
|
|
5585
5687
|
break;
|
|
5586
5688
|
}
|
|
5689
|
+
case 'user.updated': {
|
|
5690
|
+
handleUserUpdated.call(this, event);
|
|
5691
|
+
break;
|
|
5692
|
+
}
|
|
5587
5693
|
default: {
|
|
5588
5694
|
feed?.handleWSEvent(event);
|
|
5589
5695
|
}
|
|
@@ -5609,7 +5715,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5609
5715
|
}
|
|
5610
5716
|
}
|
|
5611
5717
|
async queryFeeds(request) {
|
|
5612
|
-
const response = await this.
|
|
5718
|
+
const response = await this._queryFeeds(request);
|
|
5613
5719
|
const feeds = response.feeds.map((f) => this.getOrCreateActiveFeed(f.group_id, f.id, f, request?.watch));
|
|
5614
5720
|
return {
|
|
5615
5721
|
feeds,
|
|
@@ -5619,13 +5725,29 @@ class FeedsClient extends FeedsApi {
|
|
|
5619
5725
|
duration: response.duration,
|
|
5620
5726
|
};
|
|
5621
5727
|
}
|
|
5728
|
+
async updateFollow(request) {
|
|
5729
|
+
const response = await super.updateFollow(request);
|
|
5730
|
+
[
|
|
5731
|
+
response.follow.source_feed.feed,
|
|
5732
|
+
response.follow.target_feed.feed,
|
|
5733
|
+
].forEach((fid) => {
|
|
5734
|
+
const feed = this.activeFeeds[fid];
|
|
5735
|
+
if (feed) {
|
|
5736
|
+
handleFollowUpdated.bind(feed)(response);
|
|
5737
|
+
}
|
|
5738
|
+
});
|
|
5739
|
+
return response;
|
|
5740
|
+
}
|
|
5622
5741
|
// For follow API endpoints we update the state after HTTP response to allow queryFeeds with watch: false
|
|
5623
5742
|
async follow(request) {
|
|
5624
5743
|
const response = await super.follow(request);
|
|
5625
|
-
[
|
|
5744
|
+
[
|
|
5745
|
+
response.follow.source_feed.feed,
|
|
5746
|
+
response.follow.target_feed.feed,
|
|
5747
|
+
].forEach((fid) => {
|
|
5626
5748
|
const feed = this.activeFeeds[fid];
|
|
5627
5749
|
if (feed) {
|
|
5628
|
-
|
|
5750
|
+
handleFollowCreated.bind(feed)(response);
|
|
5629
5751
|
}
|
|
5630
5752
|
});
|
|
5631
5753
|
return response;
|
|
@@ -5633,9 +5755,9 @@ class FeedsClient extends FeedsApi {
|
|
|
5633
5755
|
async followBatch(request) {
|
|
5634
5756
|
const response = await super.followBatch(request);
|
|
5635
5757
|
response.follows.forEach((follow) => {
|
|
5636
|
-
const feed = this.activeFeeds[follow.source_feed.
|
|
5758
|
+
const feed = this.activeFeeds[follow.source_feed.feed];
|
|
5637
5759
|
if (feed) {
|
|
5638
|
-
|
|
5760
|
+
handleFollowCreated.bind(feed)({ follow });
|
|
5639
5761
|
}
|
|
5640
5762
|
});
|
|
5641
5763
|
return response;
|
|
@@ -5645,10 +5767,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5645
5767
|
[request.source, request.target].forEach((fid) => {
|
|
5646
5768
|
const feed = this.activeFeeds[fid];
|
|
5647
5769
|
if (feed) {
|
|
5648
|
-
|
|
5649
|
-
source_feed: { fid: request.source },
|
|
5650
|
-
target_feed: { fid: request.target },
|
|
5651
|
-
});
|
|
5770
|
+
handleFollowDeleted.bind(feed)(response);
|
|
5652
5771
|
}
|
|
5653
5772
|
});
|
|
5654
5773
|
return response;
|
|
@@ -5661,7 +5780,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5661
5780
|
});
|
|
5662
5781
|
const feed = this.activeFeeds[`${request.feed_group_id}:${request.feed_id}`];
|
|
5663
5782
|
if (feed) {
|
|
5664
|
-
|
|
5783
|
+
handleWatchStopped.bind(feed)();
|
|
5665
5784
|
}
|
|
5666
5785
|
return response;
|
|
5667
5786
|
}
|
|
@@ -6055,12 +6174,12 @@ const useReactionActions = ({ entity, type, }) => {
|
|
|
6055
6174
|
const hasOwnReaction = useMemo(() => !!entity.own_reactions?.find((r) => r.type === type), [entity.own_reactions, type]);
|
|
6056
6175
|
const addReaction = useStableCallback(async () => {
|
|
6057
6176
|
await (isComment
|
|
6058
|
-
? client?.addCommentReaction({
|
|
6177
|
+
? client?.addCommentReaction({ id: entity.id, type })
|
|
6059
6178
|
: client?.addReaction({ activity_id: entity.id, type }));
|
|
6060
6179
|
});
|
|
6061
6180
|
const removeReaction = useStableCallback(async () => {
|
|
6062
6181
|
await (isComment
|
|
6063
|
-
? client?.deleteCommentReaction({
|
|
6182
|
+
? client?.deleteCommentReaction({ id: entity.id, type })
|
|
6064
6183
|
: client?.deleteActivityReaction({
|
|
6065
6184
|
activity_id: entity.id,
|
|
6066
6185
|
type,
|