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