@stream-io/feeds-client 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@react-bindings/hooks/search-state-hooks/index.ts +3 -0
- package/@react-bindings/hooks/util/index.ts +1 -0
- package/@react-bindings/index.ts +5 -0
- package/CHANGELOG.md +22 -0
- package/dist/@react-bindings/contexts/StreamSearchContext.d.ts +12 -0
- package/dist/@react-bindings/contexts/StreamSearchResultsContext.d.ts +12 -0
- package/dist/@react-bindings/hooks/search-state-hooks/index.d.ts +3 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchQuery.d.ts +4 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchResult.d.ts +8 -0
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +4 -0
- package/dist/@react-bindings/hooks/util/index.d.ts +1 -0
- package/dist/@react-bindings/hooks/util/useBookmarkActions.d.ts +13 -0
- package/dist/@react-bindings/hooks/util/useReactionActions.d.ts +1 -1
- package/dist/@react-bindings/index.d.ts +5 -0
- package/dist/@react-bindings/wrappers/StreamSearch.d.ts +12 -0
- package/dist/@react-bindings/wrappers/StreamSearchResults.d.ts +12 -0
- package/dist/index-react-bindings.browser.cjs +431 -156
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +422 -157
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +431 -156
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +422 -157
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +346 -264
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +346 -265
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +346 -264
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +346 -265
- package/dist/index.node.js.map +1 -1
- package/dist/src/Feed.d.ts +40 -9
- package/dist/src/FeedsClient.d.ts +8 -1
- package/dist/src/common/BaseSearchSource.d.ts +3 -1
- package/dist/src/common/FeedSearchSource.d.ts +5 -1
- package/dist/src/common/SearchController.d.ts +2 -0
- package/dist/src/gen-imports.d.ts +1 -1
- package/dist/src/state-updates/follow-utils.d.ts +19 -0
- package/dist/src/state-updates/state-update-queue.d.ts +15 -0
- package/dist/src/utils.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Feed.ts +226 -192
- package/src/FeedsClient.ts +75 -3
- package/src/common/ActivitySearchSource.ts +5 -15
- package/src/common/BaseSearchSource.ts +9 -9
- package/src/common/FeedSearchSource.ts +20 -65
- package/src/common/SearchController.ts +2 -0
- package/src/common/UserSearchSource.ts +9 -61
- package/src/gen-imports.ts +1 -1
- package/src/state-updates/activity-reaction-utils.test.ts +1 -0
- package/src/state-updates/activity-utils.test.ts +1 -0
- package/src/state-updates/follow-utils.test.ts +552 -0
- package/src/state-updates/follow-utils.ts +126 -0
- package/src/state-updates/state-update-queue.test.ts +53 -0
- package/src/state-updates/state-update-queue.ts +35 -0
- package/src/utils.test.ts +175 -0
- package/src/utils.ts +20 -0
|
@@ -4048,6 +4048,89 @@ const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
|
4048
4048
|
return updateActivityInActivities(updatedActivity, activities);
|
|
4049
4049
|
};
|
|
4050
4050
|
|
|
4051
|
+
const isFeedResponse = (follow) => {
|
|
4052
|
+
return 'created_by' in follow;
|
|
4053
|
+
};
|
|
4054
|
+
const handleFollowCreated = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4055
|
+
// filter non-accepted follows (the way getOrCreate does by default)
|
|
4056
|
+
if (follow.status !== 'accepted') {
|
|
4057
|
+
return { changed: false, data: currentState };
|
|
4058
|
+
}
|
|
4059
|
+
let newState = { ...currentState };
|
|
4060
|
+
// this feed followed someone
|
|
4061
|
+
if (follow.source_feed.fid === currentFeedId) {
|
|
4062
|
+
newState = {
|
|
4063
|
+
...newState,
|
|
4064
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4065
|
+
...follow.source_feed,
|
|
4066
|
+
};
|
|
4067
|
+
// Only update if following array already exists
|
|
4068
|
+
if (currentState.following !== undefined) {
|
|
4069
|
+
newState.following = [follow, ...currentState.following];
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
else if (
|
|
4073
|
+
// someone followed this feed
|
|
4074
|
+
follow.target_feed.fid === currentFeedId) {
|
|
4075
|
+
const source = follow.source_feed;
|
|
4076
|
+
newState = {
|
|
4077
|
+
...newState,
|
|
4078
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4079
|
+
...follow.target_feed,
|
|
4080
|
+
};
|
|
4081
|
+
if (source.created_by.id === connectedUserId) {
|
|
4082
|
+
newState.own_follows = currentState.own_follows
|
|
4083
|
+
? currentState.own_follows.concat(follow)
|
|
4084
|
+
: [follow];
|
|
4085
|
+
}
|
|
4086
|
+
// Only update if followers array already exists
|
|
4087
|
+
if (currentState.followers !== undefined) {
|
|
4088
|
+
newState.followers = [follow, ...currentState.followers];
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
return { changed: true, data: newState };
|
|
4092
|
+
};
|
|
4093
|
+
const handleFollowDeleted = (follow, currentState, currentFeedId, connectedUserId) => {
|
|
4094
|
+
let newState = { ...currentState };
|
|
4095
|
+
// this feed unfollowed someone
|
|
4096
|
+
if (follow.source_feed.fid === currentFeedId) {
|
|
4097
|
+
newState = {
|
|
4098
|
+
...newState,
|
|
4099
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4100
|
+
...follow.source_feed,
|
|
4101
|
+
};
|
|
4102
|
+
// Only update if following array already exists
|
|
4103
|
+
if (currentState.following !== undefined) {
|
|
4104
|
+
newState.following = currentState.following.filter((followItem) => followItem.target_feed.fid !== follow.target_feed.fid);
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
else if (
|
|
4108
|
+
// someone unfollowed this feed
|
|
4109
|
+
follow.target_feed.fid === currentFeedId) {
|
|
4110
|
+
const source = follow.source_feed;
|
|
4111
|
+
newState = {
|
|
4112
|
+
...newState,
|
|
4113
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4114
|
+
...follow.target_feed,
|
|
4115
|
+
};
|
|
4116
|
+
if (isFeedResponse(source) &&
|
|
4117
|
+
source.created_by.id === connectedUserId &&
|
|
4118
|
+
currentState.own_follows !== undefined) {
|
|
4119
|
+
newState.own_follows = currentState.own_follows.filter((followItem) => followItem.source_feed.fid !== follow.source_feed.fid);
|
|
4120
|
+
}
|
|
4121
|
+
// Only update if followers array already exists
|
|
4122
|
+
if (currentState.followers !== undefined) {
|
|
4123
|
+
newState.followers = currentState.followers.filter((followItem) => followItem.source_feed.fid !== follow.source_feed.fid);
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
return { changed: true, data: newState };
|
|
4127
|
+
};
|
|
4128
|
+
const handleFollowUpdated = (currentState) => {
|
|
4129
|
+
// For now, we'll treat follow updates as no-ops since the current implementation does
|
|
4130
|
+
// This can be enhanced later if needed
|
|
4131
|
+
return { changed: false, data: currentState };
|
|
4132
|
+
};
|
|
4133
|
+
|
|
4051
4134
|
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4052
4135
|
typeof cursor === 'string';
|
|
4053
4136
|
const isCommentResponse = (entity) => {
|
|
@@ -4056,11 +4139,41 @@ const isCommentResponse = (entity) => {
|
|
|
4056
4139
|
const Constants = {
|
|
4057
4140
|
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4058
4141
|
};
|
|
4142
|
+
const uniqueArrayMerge = (existingArray, arrayToMerge, getKey) => {
|
|
4143
|
+
const existing = new Set();
|
|
4144
|
+
existingArray.forEach((value) => {
|
|
4145
|
+
const key = getKey(value);
|
|
4146
|
+
existing.add(key);
|
|
4147
|
+
});
|
|
4148
|
+
const filteredArrayToMerge = arrayToMerge.filter((value) => {
|
|
4149
|
+
const key = getKey(value);
|
|
4150
|
+
return !existing.has(key);
|
|
4151
|
+
});
|
|
4152
|
+
return existingArray.concat(filteredArrayToMerge);
|
|
4153
|
+
};
|
|
4154
|
+
|
|
4155
|
+
const shouldUpdateState = ({ stateUpdateId, stateUpdateQueue, watch, }) => {
|
|
4156
|
+
if (!watch) {
|
|
4157
|
+
return true;
|
|
4158
|
+
}
|
|
4159
|
+
if (watch && stateUpdateQueue.has(stateUpdateId)) {
|
|
4160
|
+
stateUpdateQueue.delete(stateUpdateId);
|
|
4161
|
+
return false;
|
|
4162
|
+
}
|
|
4163
|
+
stateUpdateQueue.add(stateUpdateId);
|
|
4164
|
+
return true;
|
|
4165
|
+
};
|
|
4166
|
+
const getStateUpdateQueueIdForFollow = (follow) => {
|
|
4167
|
+
return `follow${follow.source_feed.fid}-${follow.target_feed.fid}`;
|
|
4168
|
+
};
|
|
4169
|
+
const getStateUpdateQueueIdForUnfollow = (follow) => {
|
|
4170
|
+
return `unfollow${follow.source_feed.fid}-${follow.target_feed.fid}`;
|
|
4171
|
+
};
|
|
4059
4172
|
|
|
4060
4173
|
class Feed extends FeedApi {
|
|
4061
|
-
constructor(client, groupId, id, data) {
|
|
4062
|
-
// Need this ugly cast because fileUpload endpoints :(
|
|
4174
|
+
constructor(client, groupId, id, data, watch = false) {
|
|
4063
4175
|
super(client, groupId, id);
|
|
4176
|
+
this.stateUpdateQueue = new Set();
|
|
4064
4177
|
this.eventHandlers = {
|
|
4065
4178
|
'feeds.activity.added': (event) => {
|
|
4066
4179
|
const currentActivities = this.currentState.activities;
|
|
@@ -4206,74 +4319,14 @@ class Feed extends FeedApi {
|
|
|
4206
4319
|
'feeds.feed_group.changed': Feed.noop,
|
|
4207
4320
|
'feeds.feed_group.deleted': Feed.noop,
|
|
4208
4321
|
'feeds.follow.created': (event) => {
|
|
4209
|
-
|
|
4210
|
-
if (event.follow.status !== 'accepted')
|
|
4211
|
-
return;
|
|
4212
|
-
// this feed followed someone
|
|
4213
|
-
if (event.follow.source_feed.fid === this.fid) {
|
|
4214
|
-
this.state.next((currentState) => {
|
|
4215
|
-
const newState = {
|
|
4216
|
-
...currentState,
|
|
4217
|
-
...event.follow.source_feed,
|
|
4218
|
-
};
|
|
4219
|
-
if (!checkHasAnotherPage(currentState.following, currentState.following_pagination?.next)) {
|
|
4220
|
-
// TODO: respect sort
|
|
4221
|
-
newState.following = currentState.following
|
|
4222
|
-
? currentState.following.concat(event.follow)
|
|
4223
|
-
: [event.follow];
|
|
4224
|
-
}
|
|
4225
|
-
return newState;
|
|
4226
|
-
});
|
|
4227
|
-
}
|
|
4228
|
-
else if (
|
|
4229
|
-
// someone followed this feed
|
|
4230
|
-
event.follow.target_feed.fid === this.fid) {
|
|
4231
|
-
const source = event.follow.source_feed;
|
|
4232
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4233
|
-
this.state.next((currentState) => {
|
|
4234
|
-
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4235
|
-
if (source.created_by.id === connectedUser?.id) {
|
|
4236
|
-
newState.own_follows = currentState.own_follows
|
|
4237
|
-
? currentState.own_follows.concat(event.follow)
|
|
4238
|
-
: [event.follow];
|
|
4239
|
-
}
|
|
4240
|
-
if (!checkHasAnotherPage(currentState.followers, currentState.followers_pagination?.next)) {
|
|
4241
|
-
// TODO: respect sort
|
|
4242
|
-
newState.followers = currentState.followers
|
|
4243
|
-
? currentState.followers.concat(event.follow)
|
|
4244
|
-
: [event.follow];
|
|
4245
|
-
}
|
|
4246
|
-
return newState;
|
|
4247
|
-
});
|
|
4248
|
-
}
|
|
4322
|
+
this.handleFollowCreated(event.follow);
|
|
4249
4323
|
},
|
|
4250
4324
|
'feeds.follow.deleted': (event) => {
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
...currentState,
|
|
4256
|
-
...event.follow.source_feed,
|
|
4257
|
-
following: currentState.following?.filter((follow) => follow.target_feed.fid !== event.follow.target_feed.fid),
|
|
4258
|
-
};
|
|
4259
|
-
});
|
|
4260
|
-
}
|
|
4261
|
-
else if (
|
|
4262
|
-
// someone unfollowed this feed
|
|
4263
|
-
event.follow.target_feed.fid === this.fid) {
|
|
4264
|
-
const source = event.follow.source_feed;
|
|
4265
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4266
|
-
this.state.next((currentState) => {
|
|
4267
|
-
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4268
|
-
if (source.created_by.id === connectedUser?.id) {
|
|
4269
|
-
newState.own_follows = currentState.own_follows?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4270
|
-
}
|
|
4271
|
-
newState.followers = currentState.followers?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4272
|
-
return newState;
|
|
4273
|
-
});
|
|
4274
|
-
}
|
|
4325
|
+
this.handleFollowDeleted(event.follow);
|
|
4326
|
+
},
|
|
4327
|
+
'feeds.follow.updated': (_event) => {
|
|
4328
|
+
handleFollowUpdated(this.currentState);
|
|
4275
4329
|
},
|
|
4276
|
-
'feeds.follow.updated': Feed.noop,
|
|
4277
4330
|
'feeds.comment.reaction.added': this.handleCommentReactionEvent.bind(this),
|
|
4278
4331
|
'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
|
|
4279
4332
|
'feeds.comment.reaction.updated': Feed.noop,
|
|
@@ -4281,13 +4334,11 @@ class Feed extends FeedApi {
|
|
|
4281
4334
|
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4282
4335
|
this.state.next((currentState) => {
|
|
4283
4336
|
let newState;
|
|
4284
|
-
if (
|
|
4337
|
+
if (typeof currentState.members !== 'undefined') {
|
|
4285
4338
|
newState ?? (newState = {
|
|
4286
4339
|
...currentState,
|
|
4287
4340
|
});
|
|
4288
|
-
newState.members =
|
|
4289
|
-
event.member,
|
|
4290
|
-
];
|
|
4341
|
+
newState.members = [event.member, ...currentState.members];
|
|
4291
4342
|
}
|
|
4292
4343
|
if (connectedUser?.id === event.member.user.id) {
|
|
4293
4344
|
newState ?? (newState = {
|
|
@@ -4370,6 +4421,7 @@ class Feed extends FeedApi {
|
|
|
4370
4421
|
is_loading: false,
|
|
4371
4422
|
is_loading_activities: false,
|
|
4372
4423
|
comments_by_entity_id: {},
|
|
4424
|
+
watch,
|
|
4373
4425
|
});
|
|
4374
4426
|
this.client = client;
|
|
4375
4427
|
}
|
|
@@ -4449,6 +4501,8 @@ class Feed extends FeedApi {
|
|
|
4449
4501
|
}
|
|
4450
4502
|
}
|
|
4451
4503
|
else {
|
|
4504
|
+
// Empty queue when reinitializing the state
|
|
4505
|
+
this.stateUpdateQueue.clear();
|
|
4452
4506
|
const responseCopy = {
|
|
4453
4507
|
...response,
|
|
4454
4508
|
...response.feed,
|
|
@@ -4467,7 +4521,11 @@ class Feed extends FeedApi {
|
|
|
4467
4521
|
if (!request?.following_pagination?.limit) {
|
|
4468
4522
|
delete nextState.following;
|
|
4469
4523
|
}
|
|
4524
|
+
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
4525
|
+
delete nextState.members;
|
|
4526
|
+
}
|
|
4470
4527
|
nextState.last_get_or_create_request_config = request;
|
|
4528
|
+
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
4471
4529
|
return nextState;
|
|
4472
4530
|
});
|
|
4473
4531
|
}
|
|
@@ -4481,6 +4539,56 @@ class Feed extends FeedApi {
|
|
|
4481
4539
|
});
|
|
4482
4540
|
}
|
|
4483
4541
|
}
|
|
4542
|
+
/**
|
|
4543
|
+
* @internal
|
|
4544
|
+
*/
|
|
4545
|
+
handleFollowCreated(follow) {
|
|
4546
|
+
if (!shouldUpdateState({
|
|
4547
|
+
stateUpdateId: getStateUpdateQueueIdForFollow(follow),
|
|
4548
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4549
|
+
watch: this.currentState.watch,
|
|
4550
|
+
})) {
|
|
4551
|
+
return;
|
|
4552
|
+
}
|
|
4553
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4554
|
+
const result = handleFollowCreated(follow, this.currentState, this.fid, connectedUser?.id);
|
|
4555
|
+
if (result.changed) {
|
|
4556
|
+
this.state.next(result.data);
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
/**
|
|
4560
|
+
* @internal
|
|
4561
|
+
*/
|
|
4562
|
+
handleFollowDeleted(follow) {
|
|
4563
|
+
if (!shouldUpdateState({
|
|
4564
|
+
stateUpdateId: getStateUpdateQueueIdForUnfollow(follow),
|
|
4565
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4566
|
+
watch: this.currentState.watch,
|
|
4567
|
+
})) {
|
|
4568
|
+
return;
|
|
4569
|
+
}
|
|
4570
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4571
|
+
const result = handleFollowDeleted(follow, this.currentState, this.fid, connectedUser?.id);
|
|
4572
|
+
{
|
|
4573
|
+
this.state.next(result.data);
|
|
4574
|
+
}
|
|
4575
|
+
}
|
|
4576
|
+
/**
|
|
4577
|
+
* @internal
|
|
4578
|
+
*/
|
|
4579
|
+
handleWatchStopped() {
|
|
4580
|
+
this.state.partialNext({
|
|
4581
|
+
watch: false,
|
|
4582
|
+
});
|
|
4583
|
+
}
|
|
4584
|
+
/**
|
|
4585
|
+
* @internal
|
|
4586
|
+
*/
|
|
4587
|
+
handleWatchStarted() {
|
|
4588
|
+
this.state.partialNext({
|
|
4589
|
+
watch: true,
|
|
4590
|
+
});
|
|
4591
|
+
}
|
|
4484
4592
|
handleBookmarkAdded(event) {
|
|
4485
4593
|
const currentActivities = this.currentState.activities;
|
|
4486
4594
|
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
@@ -4525,70 +4633,85 @@ class Feed extends FeedApi {
|
|
|
4525
4633
|
}
|
|
4526
4634
|
return commentIndex;
|
|
4527
4635
|
}
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4636
|
+
/**
|
|
4637
|
+
* Load child comments of entity (activity or comment) into the state, if the target entity is comment,
|
|
4638
|
+
* `entityParentId` should be provided (`CommentResponse.parent_id ?? CommentResponse.object_id`).
|
|
4639
|
+
*/
|
|
4640
|
+
loadCommentsIntoState(data) {
|
|
4641
|
+
// add initial (top level) object for processing
|
|
4642
|
+
const traverseArray = [
|
|
4643
|
+
{
|
|
4644
|
+
entityId: data.entityId,
|
|
4645
|
+
entityParentId: data.entityParentId,
|
|
4646
|
+
comments: data.comments,
|
|
4647
|
+
next: data.next,
|
|
4648
|
+
},
|
|
4649
|
+
];
|
|
4541
4650
|
this.state.next((currentState) => {
|
|
4542
|
-
const
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4651
|
+
const newCommentsByEntityId = {
|
|
4652
|
+
...currentState.comments_by_entity_id,
|
|
4653
|
+
};
|
|
4654
|
+
while (traverseArray.length) {
|
|
4655
|
+
const item = traverseArray.pop();
|
|
4656
|
+
const entityId = item.entityId;
|
|
4657
|
+
// go over entity comments and generate new objects
|
|
4658
|
+
// for further processing if there are any replies
|
|
4659
|
+
item.comments.forEach((comment) => {
|
|
4660
|
+
if (!comment.replies?.length)
|
|
4661
|
+
return;
|
|
4662
|
+
traverseArray.push({
|
|
4663
|
+
entityId: comment.id,
|
|
4664
|
+
entityParentId: entityId,
|
|
4665
|
+
comments: comment.replies,
|
|
4666
|
+
next: comment.meta?.next_cursor,
|
|
4667
|
+
});
|
|
4668
|
+
});
|
|
4669
|
+
// omit replies & meta from the comments (transform ThreadedCommentResponse to CommentResponse)
|
|
4670
|
+
// this is somehow faster than copying the whole
|
|
4671
|
+
// object and deleting the desired properties
|
|
4672
|
+
const newComments = item.comments.map(({ replies: _r, meta: _m, ...restOfTheCommentResponse }) => restOfTheCommentResponse);
|
|
4673
|
+
newCommentsByEntityId[entityId] = {
|
|
4674
|
+
...newCommentsByEntityId[entityId],
|
|
4675
|
+
entity_parent_id: item.entityParentId,
|
|
4676
|
+
pagination: {
|
|
4677
|
+
...newCommentsByEntityId[entityId]?.pagination,
|
|
4678
|
+
next: item.next,
|
|
4679
|
+
sort: data.sort,
|
|
4680
|
+
},
|
|
4681
|
+
comments: newCommentsByEntityId[entityId]?.comments
|
|
4682
|
+
? newCommentsByEntityId[entityId].comments?.concat(newComments)
|
|
4683
|
+
: newComments,
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4547
4686
|
return {
|
|
4548
4687
|
...currentState,
|
|
4549
|
-
|
|
4688
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
4550
4689
|
};
|
|
4551
4690
|
});
|
|
4552
4691
|
}
|
|
4553
|
-
async loadNextPageComments({
|
|
4692
|
+
async loadNextPageComments({ entityId, base, sort, entityParentId, }) {
|
|
4554
4693
|
let error;
|
|
4555
4694
|
try {
|
|
4556
4695
|
this.state.next((currentState) => ({
|
|
4557
4696
|
...currentState,
|
|
4558
4697
|
comments_by_entity_id: {
|
|
4559
4698
|
...currentState.comments_by_entity_id,
|
|
4560
|
-
[
|
|
4561
|
-
...currentState.comments_by_entity_id[
|
|
4699
|
+
[entityId]: {
|
|
4700
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4562
4701
|
pagination: {
|
|
4563
|
-
...currentState.comments_by_entity_id[
|
|
4702
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4564
4703
|
loading_next_page: true,
|
|
4565
4704
|
},
|
|
4566
4705
|
},
|
|
4567
4706
|
},
|
|
4568
4707
|
}));
|
|
4569
|
-
const { next
|
|
4570
|
-
this.
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
newPagination.sort = sort;
|
|
4577
|
-
}
|
|
4578
|
-
return {
|
|
4579
|
-
...currentState,
|
|
4580
|
-
comments_by_entity_id: {
|
|
4581
|
-
...currentState.comments_by_entity_id,
|
|
4582
|
-
[forId]: {
|
|
4583
|
-
...currentState.comments_by_entity_id[forId],
|
|
4584
|
-
parent_id: parentId,
|
|
4585
|
-
pagination: newPagination,
|
|
4586
|
-
comments: currentState.comments_by_entity_id[forId]?.comments
|
|
4587
|
-
? currentState.comments_by_entity_id[forId].comments?.concat(comments)
|
|
4588
|
-
: comments,
|
|
4589
|
-
},
|
|
4590
|
-
},
|
|
4591
|
-
};
|
|
4708
|
+
const { next, comments } = await base();
|
|
4709
|
+
this.loadCommentsIntoState({
|
|
4710
|
+
entityId,
|
|
4711
|
+
comments,
|
|
4712
|
+
entityParentId,
|
|
4713
|
+
next,
|
|
4714
|
+
sort,
|
|
4592
4715
|
});
|
|
4593
4716
|
}
|
|
4594
4717
|
catch (e) {
|
|
@@ -4599,10 +4722,10 @@ class Feed extends FeedApi {
|
|
|
4599
4722
|
...currentState,
|
|
4600
4723
|
comments_by_entity_id: {
|
|
4601
4724
|
...currentState.comments_by_entity_id,
|
|
4602
|
-
[
|
|
4603
|
-
...currentState.comments_by_entity_id[
|
|
4725
|
+
[entityId]: {
|
|
4726
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4604
4727
|
pagination: {
|
|
4605
|
-
...currentState.comments_by_entity_id[
|
|
4728
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4606
4729
|
loading_next_page: false,
|
|
4607
4730
|
},
|
|
4608
4731
|
},
|
|
@@ -4625,7 +4748,7 @@ class Feed extends FeedApi {
|
|
|
4625
4748
|
return;
|
|
4626
4749
|
}
|
|
4627
4750
|
await this.loadNextPageComments({
|
|
4628
|
-
|
|
4751
|
+
entityId: activity.id,
|
|
4629
4752
|
base: () => this.client.getComments({
|
|
4630
4753
|
...request,
|
|
4631
4754
|
sort,
|
|
@@ -4648,7 +4771,7 @@ class Feed extends FeedApi {
|
|
|
4648
4771
|
return;
|
|
4649
4772
|
}
|
|
4650
4773
|
await this.loadNextPageComments({
|
|
4651
|
-
|
|
4774
|
+
entityId: comment.id,
|
|
4652
4775
|
base: () => this.client.getCommentReplies({
|
|
4653
4776
|
...request,
|
|
4654
4777
|
comment_id: comment.id,
|
|
@@ -4658,7 +4781,7 @@ class Feed extends FeedApi {
|
|
|
4658
4781
|
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
4659
4782
|
next: currentNextCursor,
|
|
4660
4783
|
}),
|
|
4661
|
-
|
|
4784
|
+
entityParentId: comment.parent_id ?? comment.object_id,
|
|
4662
4785
|
sort,
|
|
4663
4786
|
});
|
|
4664
4787
|
}
|
|
@@ -4688,17 +4811,19 @@ class Feed extends FeedApi {
|
|
|
4688
4811
|
next: currentNextCursor,
|
|
4689
4812
|
sort,
|
|
4690
4813
|
});
|
|
4691
|
-
this.state.next((currentState) =>
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4814
|
+
this.state.next((currentState) => {
|
|
4815
|
+
return {
|
|
4816
|
+
...currentState,
|
|
4817
|
+
[type]: currentState[type] === undefined
|
|
4818
|
+
? follows
|
|
4819
|
+
: uniqueArrayMerge(currentState[type], follows, (follow) => `${follow.source_feed.fid}-${follow.target_feed.fid}`),
|
|
4820
|
+
[paginationKey]: {
|
|
4821
|
+
...currentState[paginationKey],
|
|
4822
|
+
next: newNextCursor,
|
|
4823
|
+
sort,
|
|
4824
|
+
},
|
|
4825
|
+
};
|
|
4826
|
+
});
|
|
4702
4827
|
}
|
|
4703
4828
|
catch (e) {
|
|
4704
4829
|
error = e;
|
|
@@ -4751,7 +4876,7 @@ class Feed extends FeedApi {
|
|
|
4751
4876
|
this.state.next((currentState) => ({
|
|
4752
4877
|
...currentState,
|
|
4753
4878
|
members: currentState.members
|
|
4754
|
-
? currentState.members
|
|
4879
|
+
? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
|
|
4755
4880
|
: members,
|
|
4756
4881
|
member_pagination: {
|
|
4757
4882
|
...currentState.member_pagination,
|
|
@@ -5338,13 +5463,17 @@ class FeedsClient extends FeedsApi {
|
|
|
5338
5463
|
};
|
|
5339
5464
|
this.eventDispatcher.dispatch(networkEvent);
|
|
5340
5465
|
};
|
|
5341
|
-
this.getOrCreateActiveFeed = (group, id, data) => {
|
|
5466
|
+
this.getOrCreateActiveFeed = (group, id, data, watch) => {
|
|
5342
5467
|
const fid = `${group}:${id}`;
|
|
5343
5468
|
if (this.activeFeeds[fid]) {
|
|
5344
|
-
|
|
5469
|
+
const feed = this.activeFeeds[fid];
|
|
5470
|
+
if (watch && !feed.currentState.watch) {
|
|
5471
|
+
feed.handleWatchStarted();
|
|
5472
|
+
}
|
|
5473
|
+
return feed;
|
|
5345
5474
|
}
|
|
5346
5475
|
else {
|
|
5347
|
-
const feed = new Feed(this, group, id, data);
|
|
5476
|
+
const feed = new Feed(this, group, id, data, watch);
|
|
5348
5477
|
this.activeFeeds[fid] = feed;
|
|
5349
5478
|
return feed;
|
|
5350
5479
|
}
|
|
@@ -5373,6 +5502,11 @@ class FeedsClient extends FeedsApi {
|
|
|
5373
5502
|
}
|
|
5374
5503
|
}
|
|
5375
5504
|
}
|
|
5505
|
+
else {
|
|
5506
|
+
for (const activeFeed of Object.values(this.activeFeeds)) {
|
|
5507
|
+
activeFeed.handleWatchStopped();
|
|
5508
|
+
}
|
|
5509
|
+
}
|
|
5376
5510
|
break;
|
|
5377
5511
|
}
|
|
5378
5512
|
case 'feeds.feed.created': {
|
|
@@ -5476,7 +5610,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5476
5610
|
}
|
|
5477
5611
|
async queryFeeds(request) {
|
|
5478
5612
|
const response = await this.feedsQueryFeeds(request);
|
|
5479
|
-
const feeds = response.feeds.map((f) => this.getOrCreateActiveFeed(f.group_id, f.id, f));
|
|
5613
|
+
const feeds = response.feeds.map((f) => this.getOrCreateActiveFeed(f.group_id, f.id, f, request?.watch));
|
|
5480
5614
|
return {
|
|
5481
5615
|
feeds,
|
|
5482
5616
|
next: response.next,
|
|
@@ -5485,6 +5619,52 @@ class FeedsClient extends FeedsApi {
|
|
|
5485
5619
|
duration: response.duration,
|
|
5486
5620
|
};
|
|
5487
5621
|
}
|
|
5622
|
+
// For follow API endpoints we update the state after HTTP response to allow queryFeeds with watch: false
|
|
5623
|
+
async follow(request) {
|
|
5624
|
+
const response = await super.follow(request);
|
|
5625
|
+
[response.follow.source_feed.fid, response.follow.target_feed.fid].forEach((fid) => {
|
|
5626
|
+
const feed = this.activeFeeds[fid];
|
|
5627
|
+
if (feed) {
|
|
5628
|
+
feed.handleFollowCreated(response.follow);
|
|
5629
|
+
}
|
|
5630
|
+
});
|
|
5631
|
+
return response;
|
|
5632
|
+
}
|
|
5633
|
+
async followBatch(request) {
|
|
5634
|
+
const response = await super.followBatch(request);
|
|
5635
|
+
response.follows.forEach((follow) => {
|
|
5636
|
+
const feed = this.activeFeeds[follow.source_feed.fid];
|
|
5637
|
+
if (feed) {
|
|
5638
|
+
feed.handleFollowCreated(follow);
|
|
5639
|
+
}
|
|
5640
|
+
});
|
|
5641
|
+
return response;
|
|
5642
|
+
}
|
|
5643
|
+
async unfollow(request) {
|
|
5644
|
+
const response = await super.unfollow(request);
|
|
5645
|
+
[request.source, request.target].forEach((fid) => {
|
|
5646
|
+
const feed = this.activeFeeds[fid];
|
|
5647
|
+
if (feed) {
|
|
5648
|
+
feed.handleFollowDeleted({
|
|
5649
|
+
source_feed: { fid: request.source },
|
|
5650
|
+
target_feed: { fid: request.target },
|
|
5651
|
+
});
|
|
5652
|
+
}
|
|
5653
|
+
});
|
|
5654
|
+
return response;
|
|
5655
|
+
}
|
|
5656
|
+
async stopWatchingFeed(request) {
|
|
5657
|
+
const connectionId = await this.connectionIdManager.getConnectionId();
|
|
5658
|
+
const response = await super.stopWatchingFeed({
|
|
5659
|
+
...request,
|
|
5660
|
+
connection_id: connectionId,
|
|
5661
|
+
});
|
|
5662
|
+
const feed = this.activeFeeds[`${request.feed_group_id}:${request.feed_id}`];
|
|
5663
|
+
if (feed) {
|
|
5664
|
+
feed.handleWatchStopped();
|
|
5665
|
+
}
|
|
5666
|
+
return response;
|
|
5667
|
+
}
|
|
5488
5668
|
findActiveFeedByActivityId(activityId) {
|
|
5489
5669
|
return Object.values(this.activeFeeds).filter((feed) => feed.currentState.activities?.some((activity) => activity.id === activityId));
|
|
5490
5670
|
}
|
|
@@ -5547,10 +5727,10 @@ const useFeedsClient = () => {
|
|
|
5547
5727
|
*/
|
|
5548
5728
|
const useClientConnectedUser = () => {
|
|
5549
5729
|
const client = useFeedsClient();
|
|
5550
|
-
const { user } = useStateStore(client?.state, selector$
|
|
5730
|
+
const { user } = useStateStore(client?.state, selector$a) ?? {};
|
|
5551
5731
|
return user;
|
|
5552
5732
|
};
|
|
5553
|
-
const selector$
|
|
5733
|
+
const selector$a = (nextState) => ({
|
|
5554
5734
|
user: nextState.connected_user,
|
|
5555
5735
|
});
|
|
5556
5736
|
|
|
@@ -5559,10 +5739,10 @@ const selector$7 = (nextState) => ({
|
|
|
5559
5739
|
*/
|
|
5560
5740
|
const useWsConnectionState = () => {
|
|
5561
5741
|
const client = useFeedsClient();
|
|
5562
|
-
const { is_healthy } = useStateStore(client?.state, selector$
|
|
5742
|
+
const { is_healthy } = useStateStore(client?.state, selector$9) ?? {};
|
|
5563
5743
|
return { is_healthy };
|
|
5564
5744
|
};
|
|
5565
|
-
const selector$
|
|
5745
|
+
const selector$9 = (nextState) => ({
|
|
5566
5746
|
is_healthy: nextState.is_ws_connection_healthy,
|
|
5567
5747
|
});
|
|
5568
5748
|
|
|
@@ -5612,7 +5792,7 @@ const useStableCallback = (callback) => {
|
|
|
5612
5792
|
const useFeedActivities = (feedFromProps) => {
|
|
5613
5793
|
const feedFromContext = useFeedContext();
|
|
5614
5794
|
const feed = feedFromProps ?? feedFromContext;
|
|
5615
|
-
const data = useStateStore(feed?.state, selector$
|
|
5795
|
+
const data = useStateStore(feed?.state, selector$8);
|
|
5616
5796
|
const loadNextPage = useStableCallback(async () => {
|
|
5617
5797
|
if (!feed || !data?.has_next_page || data?.is_loading) {
|
|
5618
5798
|
return;
|
|
@@ -5621,7 +5801,7 @@ const useFeedActivities = (feedFromProps) => {
|
|
|
5621
5801
|
});
|
|
5622
5802
|
return useMemo(() => ({ ...data, loadNextPage }), [data, loadNextPage]);
|
|
5623
5803
|
};
|
|
5624
|
-
const selector$
|
|
5804
|
+
const selector$8 = ({ is_loading_activities, next, activities = [] }) => ({
|
|
5625
5805
|
is_loading: is_loading_activities,
|
|
5626
5806
|
has_next_page: typeof next !== 'undefined',
|
|
5627
5807
|
activities,
|
|
@@ -5694,13 +5874,13 @@ const FeedOwnCapability = {
|
|
|
5694
5874
|
};
|
|
5695
5875
|
|
|
5696
5876
|
const stableEmptyArray = [];
|
|
5697
|
-
const selector$
|
|
5877
|
+
const selector$7 = (currentState) => ({
|
|
5698
5878
|
oc: currentState.own_capabilities ?? stableEmptyArray,
|
|
5699
5879
|
});
|
|
5700
5880
|
const useOwnCapabilities = (feedFromProps) => {
|
|
5701
5881
|
const feedFromContext = useFeedContext();
|
|
5702
5882
|
const feed = feedFromProps ?? feedFromContext;
|
|
5703
|
-
const { oc = stableEmptyArray } = useStateStore(feed?.state, selector$
|
|
5883
|
+
const { oc = stableEmptyArray } = useStateStore(feed?.state, selector$7) ?? {};
|
|
5704
5884
|
return useMemo(() => ({
|
|
5705
5885
|
can_add_activity: oc.indexOf(FeedOwnCapability.ADD_ACTIVITY) > -1,
|
|
5706
5886
|
can_add_activity_reaction: oc.indexOf(FeedOwnCapability.ADD_ACTIVITY_REACTION) > -1,
|
|
@@ -5735,7 +5915,7 @@ const useOwnCapabilities = (feedFromProps) => {
|
|
|
5735
5915
|
}), [oc]);
|
|
5736
5916
|
};
|
|
5737
5917
|
|
|
5738
|
-
const selector$
|
|
5918
|
+
const selector$6 = ({ follower_count, followers, followers_pagination, }) => ({
|
|
5739
5919
|
follower_count,
|
|
5740
5920
|
followers,
|
|
5741
5921
|
followers_pagination,
|
|
@@ -5743,7 +5923,7 @@ const selector$3 = ({ follower_count, followers, followers_pagination, }) => ({
|
|
|
5743
5923
|
function useFollowers(feedFromProps) {
|
|
5744
5924
|
const feedFromContext = useFeedContext();
|
|
5745
5925
|
const feed = feedFromProps ?? feedFromContext;
|
|
5746
|
-
const data = useStateStore(feed?.state, selector$
|
|
5926
|
+
const data = useStateStore(feed?.state, selector$6);
|
|
5747
5927
|
const loadNextPage = useCallback((...options) => feed?.loadNextPageFollowers(...options), [feed]);
|
|
5748
5928
|
return useMemo(() => {
|
|
5749
5929
|
if (!data) {
|
|
@@ -5758,7 +5938,7 @@ function useFollowers(feedFromProps) {
|
|
|
5758
5938
|
}, [data, loadNextPage]);
|
|
5759
5939
|
}
|
|
5760
5940
|
|
|
5761
|
-
const selector$
|
|
5941
|
+
const selector$5 = ({ following_count, following, following_pagination, }) => ({
|
|
5762
5942
|
following_count,
|
|
5763
5943
|
following,
|
|
5764
5944
|
following_pagination,
|
|
@@ -5766,7 +5946,7 @@ const selector$2 = ({ following_count, following, following_pagination, }) => ({
|
|
|
5766
5946
|
function useFollowing(feedFromProps) {
|
|
5767
5947
|
const feedFromContext = useFeedContext();
|
|
5768
5948
|
const feed = feedFromProps ?? feedFromContext;
|
|
5769
|
-
const data = useStateStore(feed?.state, selector$
|
|
5949
|
+
const data = useStateStore(feed?.state, selector$5);
|
|
5770
5950
|
const loadNextPage = useCallback((...options) => feed?.loadNextPageFollowing(...options), [feed]);
|
|
5771
5951
|
return useMemo(() => {
|
|
5772
5952
|
if (!data) {
|
|
@@ -5788,9 +5968,9 @@ function useFollowing(feedFromProps) {
|
|
|
5788
5968
|
const useFeedMetadata = (feedFromProps) => {
|
|
5789
5969
|
const feedFromContext = useFeedContext();
|
|
5790
5970
|
const feed = feedFromProps ?? feedFromContext;
|
|
5791
|
-
return useStateStore(feed?.state, selector$
|
|
5971
|
+
return useStateStore(feed?.state, selector$4);
|
|
5792
5972
|
};
|
|
5793
|
-
const selector$
|
|
5973
|
+
const selector$4 = ({ follower_count = 0, following_count = 0, created_by, created_at, updated_at, }) => ({
|
|
5794
5974
|
created_by,
|
|
5795
5975
|
follower_count,
|
|
5796
5976
|
following_count,
|
|
@@ -5805,18 +5985,68 @@ const selector$1 = ({ follower_count = 0, following_count = 0, created_by, creat
|
|
|
5805
5985
|
const useOwnFollows = (feedFromProps) => {
|
|
5806
5986
|
const feedFromContext = useFeedContext();
|
|
5807
5987
|
const feed = feedFromProps ?? feedFromContext;
|
|
5808
|
-
return useStateStore(feed?.state, selector);
|
|
5988
|
+
return useStateStore(feed?.state, selector$3);
|
|
5809
5989
|
};
|
|
5810
|
-
const selector = ({ own_follows }) => ({
|
|
5990
|
+
const selector$3 = ({ own_follows }) => ({
|
|
5811
5991
|
own_follows,
|
|
5812
5992
|
});
|
|
5813
5993
|
|
|
5994
|
+
const StreamSearchResultsContext = createContext(undefined);
|
|
5995
|
+
/**
|
|
5996
|
+
* Hook to access the nearest SearchSource instance.
|
|
5997
|
+
*/
|
|
5998
|
+
const useSearchResultsContext = () => {
|
|
5999
|
+
return useContext(StreamSearchResultsContext);
|
|
6000
|
+
};
|
|
6001
|
+
|
|
6002
|
+
const useSearchResult = (sourceFromProps) => {
|
|
6003
|
+
const sourceFromContext = useSearchResultsContext();
|
|
6004
|
+
const source = sourceFromProps ?? sourceFromContext;
|
|
6005
|
+
const { items, error, isLoading, hasNext } = useStateStore(source?.state, selector$2) ?? {};
|
|
6006
|
+
const loadMore = useStableCallback(async () => {
|
|
6007
|
+
source?.search();
|
|
6008
|
+
});
|
|
6009
|
+
return useMemo(() => ({ items, error, isLoading, hasNext, loadMore }), [error, hasNext, isLoading, items, loadMore]);
|
|
6010
|
+
};
|
|
6011
|
+
const selector$2 = ({ items, isLoading, hasNext, lastQueryError, }) => ({
|
|
6012
|
+
items,
|
|
6013
|
+
isLoading,
|
|
6014
|
+
hasNext,
|
|
6015
|
+
error: lastQueryError,
|
|
6016
|
+
});
|
|
6017
|
+
|
|
6018
|
+
const StreamSearchContext = createContext(undefined);
|
|
6019
|
+
/**
|
|
6020
|
+
* Hook to access the nearest SearchController instance.
|
|
6021
|
+
*/
|
|
6022
|
+
const useSearchContext = () => {
|
|
6023
|
+
return useContext(StreamSearchContext);
|
|
6024
|
+
};
|
|
6025
|
+
|
|
6026
|
+
const useSearchQuery = (controllerFromProps) => {
|
|
6027
|
+
const controllerFromState = useSearchContext();
|
|
6028
|
+
const controller = controllerFromProps ?? controllerFromState;
|
|
6029
|
+
return useStateStore(controller?.state, selector$1);
|
|
6030
|
+
};
|
|
6031
|
+
const selector$1 = ({ searchQuery }) => ({
|
|
6032
|
+
searchQuery,
|
|
6033
|
+
});
|
|
6034
|
+
|
|
6035
|
+
const useSearchSources = (controllerFromProps) => {
|
|
6036
|
+
const controllerFromState = useSearchContext();
|
|
6037
|
+
const controller = controllerFromProps ?? controllerFromState;
|
|
6038
|
+
return useStateStore(controller?.state, selector);
|
|
6039
|
+
};
|
|
6040
|
+
const selector = ({ sources }) => ({
|
|
6041
|
+
sources,
|
|
6042
|
+
});
|
|
6043
|
+
|
|
5814
6044
|
/**
|
|
5815
6045
|
* A utility hook that takes in an entity and a reaction type, and creates reaction actions
|
|
5816
6046
|
* that can then be used on the UI. The entity can be either an ActivityResponse or a CommentResponse
|
|
5817
6047
|
* as the hook determines internally which APIs it is supposed to use, while taking the
|
|
5818
6048
|
* correct ownCapabilities into account.
|
|
5819
|
-
* @param entity - The entity to which we want to
|
|
6049
|
+
* @param entity - The entity to which we want to apply reaction actions, can be either ActivityResponse or CommentResponse.
|
|
5820
6050
|
* @param type - The type of reaction we want to add or remove.
|
|
5821
6051
|
*/
|
|
5822
6052
|
const useReactionActions = ({ entity, type, }) => {
|
|
@@ -5847,6 +6077,31 @@ const useReactionActions = ({ entity, type, }) => {
|
|
|
5847
6077
|
return useMemo(() => ({ addReaction, removeReaction, toggleReaction }), [addReaction, removeReaction, toggleReaction]);
|
|
5848
6078
|
};
|
|
5849
6079
|
|
|
6080
|
+
/**
|
|
6081
|
+
* A utility hook that takes in an entity and creates bookmark actions
|
|
6082
|
+
* that can then be used on the UI. The entity is expected to be an ActivityResponse.
|
|
6083
|
+
* @param entity - The entity to which we want to apply reaction actions, expects an ActivityResponse.
|
|
6084
|
+
*/
|
|
6085
|
+
const useBookmarkActions = ({ entity, }) => {
|
|
6086
|
+
const client = useFeedsClient();
|
|
6087
|
+
const hasOwnBookmark = entity.own_bookmarks?.length > 0;
|
|
6088
|
+
const addBookmark = useStableCallback(async () => {
|
|
6089
|
+
await client?.addBookmark({ activity_id: entity.id });
|
|
6090
|
+
});
|
|
6091
|
+
const removeBookmark = useStableCallback(async () => {
|
|
6092
|
+
await client?.deleteBookmark({ activity_id: entity.id });
|
|
6093
|
+
});
|
|
6094
|
+
const toggleBookmark = useStableCallback(async () => {
|
|
6095
|
+
if (hasOwnBookmark) {
|
|
6096
|
+
await removeBookmark();
|
|
6097
|
+
}
|
|
6098
|
+
else {
|
|
6099
|
+
await addBookmark();
|
|
6100
|
+
}
|
|
6101
|
+
});
|
|
6102
|
+
return useMemo(() => ({ addBookmark, removeBookmark, toggleBookmark }), [addBookmark, removeBookmark, toggleBookmark]);
|
|
6103
|
+
};
|
|
6104
|
+
|
|
5850
6105
|
const StreamFeeds = ({ client, children }) => {
|
|
5851
6106
|
return (jsx(StreamFeedsContext.Provider, { value: client, children: children }));
|
|
5852
6107
|
};
|
|
@@ -5857,5 +6112,15 @@ const StreamFeed = ({ feed, children }) => {
|
|
|
5857
6112
|
};
|
|
5858
6113
|
StreamFeed.displayName = 'StreamFeed';
|
|
5859
6114
|
|
|
5860
|
-
|
|
6115
|
+
const StreamSearch = ({ searchController, children, }) => {
|
|
6116
|
+
return (jsx(StreamSearchContext.Provider, { value: searchController, children: children }));
|
|
6117
|
+
};
|
|
6118
|
+
StreamSearch.displayName = 'StreamSearch';
|
|
6119
|
+
|
|
6120
|
+
const StreamSearchResults = ({ source, children, }) => {
|
|
6121
|
+
return (jsx(StreamSearchResultsContext.Provider, { value: source, children: children }));
|
|
6122
|
+
};
|
|
6123
|
+
StreamSearchResults.displayName = 'StreamSearchResults';
|
|
6124
|
+
|
|
6125
|
+
export { StreamFeed, StreamFeedContext, StreamFeeds, StreamFeedsContext, StreamSearch, StreamSearchContext, StreamSearchResults, StreamSearchResultsContext, useBookmarkActions, useClientConnectedUser, useComments, useCreateFeedsClient, useFeedActivities, useFeedContext, useFeedMetadata, useFeedsClient, useFollowers, useFollowing, useOwnCapabilities, useOwnFollows, useReactionActions, useSearchContext, useSearchQuery, useSearchResult, useSearchResultsContext, useSearchSources, useStateStore, useWsConnectionState };
|
|
5861
6126
|
//# sourceMappingURL=index-react-bindings.browser.js.map
|