@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
|
@@ -4050,6 +4050,89 @@ const updateBookmarkInActivities = (event, activities, isCurrentUser) => {
|
|
|
4050
4050
|
return updateActivityInActivities(updatedActivity, activities);
|
|
4051
4051
|
};
|
|
4052
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,
|
|
4068
|
+
};
|
|
4069
|
+
// Only update if following array already exists
|
|
4070
|
+
if (currentState.following !== undefined) {
|
|
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,
|
|
4082
|
+
};
|
|
4083
|
+
if (source.created_by.id === connectedUserId) {
|
|
4084
|
+
newState.own_follows = currentState.own_follows
|
|
4085
|
+
? currentState.own_follows.concat(follow)
|
|
4086
|
+
: [follow];
|
|
4087
|
+
}
|
|
4088
|
+
// Only update if followers array already exists
|
|
4089
|
+
if (currentState.followers !== undefined) {
|
|
4090
|
+
newState.followers = [follow, ...currentState.followers];
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
return { changed: true, data: newState };
|
|
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,
|
|
4103
|
+
};
|
|
4104
|
+
// Only update if following array already exists
|
|
4105
|
+
if (currentState.following !== undefined) {
|
|
4106
|
+
newState.following = currentState.following.filter((followItem) => followItem.target_feed.fid !== follow.target_feed.fid);
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
else if (
|
|
4110
|
+
// someone unfollowed this feed
|
|
4111
|
+
follow.target_feed.fid === currentFeedId) {
|
|
4112
|
+
const source = follow.source_feed;
|
|
4113
|
+
newState = {
|
|
4114
|
+
...newState,
|
|
4115
|
+
// Update FeedResponse fields, that has the new follower/following count
|
|
4116
|
+
...follow.target_feed,
|
|
4117
|
+
};
|
|
4118
|
+
if (isFeedResponse(source) &&
|
|
4119
|
+
source.created_by.id === connectedUserId &&
|
|
4120
|
+
currentState.own_follows !== undefined) {
|
|
4121
|
+
newState.own_follows = currentState.own_follows.filter((followItem) => followItem.source_feed.fid !== follow.source_feed.fid);
|
|
4122
|
+
}
|
|
4123
|
+
// Only update if followers array already exists
|
|
4124
|
+
if (currentState.followers !== undefined) {
|
|
4125
|
+
newState.followers = currentState.followers.filter((followItem) => followItem.source_feed.fid !== follow.source_feed.fid);
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
return { changed: true, data: newState };
|
|
4129
|
+
};
|
|
4130
|
+
const handleFollowUpdated = (currentState) => {
|
|
4131
|
+
// For now, we'll treat follow updates as no-ops since the current implementation does
|
|
4132
|
+
// This can be enhanced later if needed
|
|
4133
|
+
return { changed: false, data: currentState };
|
|
4134
|
+
};
|
|
4135
|
+
|
|
4053
4136
|
const checkHasAnotherPage = (v, cursor) => (typeof v === 'undefined' && typeof cursor === 'undefined') ||
|
|
4054
4137
|
typeof cursor === 'string';
|
|
4055
4138
|
const isCommentResponse = (entity) => {
|
|
@@ -4058,11 +4141,41 @@ const isCommentResponse = (entity) => {
|
|
|
4058
4141
|
const Constants = {
|
|
4059
4142
|
DEFAULT_COMMENT_PAGINATION: 'first',
|
|
4060
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
|
+
};
|
|
4061
4174
|
|
|
4062
4175
|
class Feed extends FeedApi {
|
|
4063
|
-
constructor(client, groupId, id, data) {
|
|
4064
|
-
// Need this ugly cast because fileUpload endpoints :(
|
|
4176
|
+
constructor(client, groupId, id, data, watch = false) {
|
|
4065
4177
|
super(client, groupId, id);
|
|
4178
|
+
this.stateUpdateQueue = new Set();
|
|
4066
4179
|
this.eventHandlers = {
|
|
4067
4180
|
'feeds.activity.added': (event) => {
|
|
4068
4181
|
const currentActivities = this.currentState.activities;
|
|
@@ -4208,74 +4321,14 @@ class Feed extends FeedApi {
|
|
|
4208
4321
|
'feeds.feed_group.changed': Feed.noop,
|
|
4209
4322
|
'feeds.feed_group.deleted': Feed.noop,
|
|
4210
4323
|
'feeds.follow.created': (event) => {
|
|
4211
|
-
|
|
4212
|
-
if (event.follow.status !== 'accepted')
|
|
4213
|
-
return;
|
|
4214
|
-
// this feed followed someone
|
|
4215
|
-
if (event.follow.source_feed.fid === this.fid) {
|
|
4216
|
-
this.state.next((currentState) => {
|
|
4217
|
-
const newState = {
|
|
4218
|
-
...currentState,
|
|
4219
|
-
...event.follow.source_feed,
|
|
4220
|
-
};
|
|
4221
|
-
if (!checkHasAnotherPage(currentState.following, currentState.following_pagination?.next)) {
|
|
4222
|
-
// TODO: respect sort
|
|
4223
|
-
newState.following = currentState.following
|
|
4224
|
-
? currentState.following.concat(event.follow)
|
|
4225
|
-
: [event.follow];
|
|
4226
|
-
}
|
|
4227
|
-
return newState;
|
|
4228
|
-
});
|
|
4229
|
-
}
|
|
4230
|
-
else if (
|
|
4231
|
-
// someone followed this feed
|
|
4232
|
-
event.follow.target_feed.fid === this.fid) {
|
|
4233
|
-
const source = event.follow.source_feed;
|
|
4234
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4235
|
-
this.state.next((currentState) => {
|
|
4236
|
-
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4237
|
-
if (source.created_by.id === connectedUser?.id) {
|
|
4238
|
-
newState.own_follows = currentState.own_follows
|
|
4239
|
-
? currentState.own_follows.concat(event.follow)
|
|
4240
|
-
: [event.follow];
|
|
4241
|
-
}
|
|
4242
|
-
if (!checkHasAnotherPage(currentState.followers, currentState.followers_pagination?.next)) {
|
|
4243
|
-
// TODO: respect sort
|
|
4244
|
-
newState.followers = currentState.followers
|
|
4245
|
-
? currentState.followers.concat(event.follow)
|
|
4246
|
-
: [event.follow];
|
|
4247
|
-
}
|
|
4248
|
-
return newState;
|
|
4249
|
-
});
|
|
4250
|
-
}
|
|
4324
|
+
this.handleFollowCreated(event.follow);
|
|
4251
4325
|
},
|
|
4252
4326
|
'feeds.follow.deleted': (event) => {
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
...currentState,
|
|
4258
|
-
...event.follow.source_feed,
|
|
4259
|
-
following: currentState.following?.filter((follow) => follow.target_feed.fid !== event.follow.target_feed.fid),
|
|
4260
|
-
};
|
|
4261
|
-
});
|
|
4262
|
-
}
|
|
4263
|
-
else if (
|
|
4264
|
-
// someone unfollowed this feed
|
|
4265
|
-
event.follow.target_feed.fid === this.fid) {
|
|
4266
|
-
const source = event.follow.source_feed;
|
|
4267
|
-
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4268
|
-
this.state.next((currentState) => {
|
|
4269
|
-
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4270
|
-
if (source.created_by.id === connectedUser?.id) {
|
|
4271
|
-
newState.own_follows = currentState.own_follows?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4272
|
-
}
|
|
4273
|
-
newState.followers = currentState.followers?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4274
|
-
return newState;
|
|
4275
|
-
});
|
|
4276
|
-
}
|
|
4327
|
+
this.handleFollowDeleted(event.follow);
|
|
4328
|
+
},
|
|
4329
|
+
'feeds.follow.updated': (_event) => {
|
|
4330
|
+
handleFollowUpdated(this.currentState);
|
|
4277
4331
|
},
|
|
4278
|
-
'feeds.follow.updated': Feed.noop,
|
|
4279
4332
|
'feeds.comment.reaction.added': this.handleCommentReactionEvent.bind(this),
|
|
4280
4333
|
'feeds.comment.reaction.deleted': this.handleCommentReactionEvent.bind(this),
|
|
4281
4334
|
'feeds.comment.reaction.updated': Feed.noop,
|
|
@@ -4283,13 +4336,11 @@ class Feed extends FeedApi {
|
|
|
4283
4336
|
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
4284
4337
|
this.state.next((currentState) => {
|
|
4285
4338
|
let newState;
|
|
4286
|
-
if (
|
|
4339
|
+
if (typeof currentState.members !== 'undefined') {
|
|
4287
4340
|
newState ?? (newState = {
|
|
4288
4341
|
...currentState,
|
|
4289
4342
|
});
|
|
4290
|
-
newState.members =
|
|
4291
|
-
event.member,
|
|
4292
|
-
];
|
|
4343
|
+
newState.members = [event.member, ...currentState.members];
|
|
4293
4344
|
}
|
|
4294
4345
|
if (connectedUser?.id === event.member.user.id) {
|
|
4295
4346
|
newState ?? (newState = {
|
|
@@ -4372,6 +4423,7 @@ class Feed extends FeedApi {
|
|
|
4372
4423
|
is_loading: false,
|
|
4373
4424
|
is_loading_activities: false,
|
|
4374
4425
|
comments_by_entity_id: {},
|
|
4426
|
+
watch,
|
|
4375
4427
|
});
|
|
4376
4428
|
this.client = client;
|
|
4377
4429
|
}
|
|
@@ -4451,6 +4503,8 @@ class Feed extends FeedApi {
|
|
|
4451
4503
|
}
|
|
4452
4504
|
}
|
|
4453
4505
|
else {
|
|
4506
|
+
// Empty queue when reinitializing the state
|
|
4507
|
+
this.stateUpdateQueue.clear();
|
|
4454
4508
|
const responseCopy = {
|
|
4455
4509
|
...response,
|
|
4456
4510
|
...response.feed,
|
|
@@ -4469,7 +4523,11 @@ class Feed extends FeedApi {
|
|
|
4469
4523
|
if (!request?.following_pagination?.limit) {
|
|
4470
4524
|
delete nextState.following;
|
|
4471
4525
|
}
|
|
4526
|
+
if (response.members.length === 0 && response.feed.member_count > 0) {
|
|
4527
|
+
delete nextState.members;
|
|
4528
|
+
}
|
|
4472
4529
|
nextState.last_get_or_create_request_config = request;
|
|
4530
|
+
nextState.watch = request?.watch ? request.watch : currentState.watch;
|
|
4473
4531
|
return nextState;
|
|
4474
4532
|
});
|
|
4475
4533
|
}
|
|
@@ -4483,6 +4541,56 @@ class Feed extends FeedApi {
|
|
|
4483
4541
|
});
|
|
4484
4542
|
}
|
|
4485
4543
|
}
|
|
4544
|
+
/**
|
|
4545
|
+
* @internal
|
|
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
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
/**
|
|
4562
|
+
* @internal
|
|
4563
|
+
*/
|
|
4564
|
+
handleFollowDeleted(follow) {
|
|
4565
|
+
if (!shouldUpdateState({
|
|
4566
|
+
stateUpdateId: getStateUpdateQueueIdForUnfollow(follow),
|
|
4567
|
+
stateUpdateQueue: this.stateUpdateQueue,
|
|
4568
|
+
watch: this.currentState.watch,
|
|
4569
|
+
})) {
|
|
4570
|
+
return;
|
|
4571
|
+
}
|
|
4572
|
+
const connectedUser = this.client.state.getLatestValue().connected_user;
|
|
4573
|
+
const result = handleFollowDeleted(follow, this.currentState, this.fid, connectedUser?.id);
|
|
4574
|
+
{
|
|
4575
|
+
this.state.next(result.data);
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4578
|
+
/**
|
|
4579
|
+
* @internal
|
|
4580
|
+
*/
|
|
4581
|
+
handleWatchStopped() {
|
|
4582
|
+
this.state.partialNext({
|
|
4583
|
+
watch: false,
|
|
4584
|
+
});
|
|
4585
|
+
}
|
|
4586
|
+
/**
|
|
4587
|
+
* @internal
|
|
4588
|
+
*/
|
|
4589
|
+
handleWatchStarted() {
|
|
4590
|
+
this.state.partialNext({
|
|
4591
|
+
watch: true,
|
|
4592
|
+
});
|
|
4593
|
+
}
|
|
4486
4594
|
handleBookmarkAdded(event) {
|
|
4487
4595
|
const currentActivities = this.currentState.activities;
|
|
4488
4596
|
const { connected_user: connectedUser } = this.client.state.getLatestValue();
|
|
@@ -4527,70 +4635,85 @@ class Feed extends FeedApi {
|
|
|
4527
4635
|
}
|
|
4528
4636
|
return commentIndex;
|
|
4529
4637
|
}
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4638
|
+
/**
|
|
4639
|
+
* Load child comments of entity (activity or comment) into the state, if the target entity is comment,
|
|
4640
|
+
* `entityParentId` should be provided (`CommentResponse.parent_id ?? CommentResponse.object_id`).
|
|
4641
|
+
*/
|
|
4642
|
+
loadCommentsIntoState(data) {
|
|
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
|
+
];
|
|
4543
4652
|
this.state.next((currentState) => {
|
|
4544
|
-
const
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
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
|
+
}
|
|
4549
4688
|
return {
|
|
4550
4689
|
...currentState,
|
|
4551
|
-
|
|
4690
|
+
comments_by_entity_id: newCommentsByEntityId,
|
|
4552
4691
|
};
|
|
4553
4692
|
});
|
|
4554
4693
|
}
|
|
4555
|
-
async loadNextPageComments({
|
|
4694
|
+
async loadNextPageComments({ entityId, base, sort, entityParentId, }) {
|
|
4556
4695
|
let error;
|
|
4557
4696
|
try {
|
|
4558
4697
|
this.state.next((currentState) => ({
|
|
4559
4698
|
...currentState,
|
|
4560
4699
|
comments_by_entity_id: {
|
|
4561
4700
|
...currentState.comments_by_entity_id,
|
|
4562
|
-
[
|
|
4563
|
-
...currentState.comments_by_entity_id[
|
|
4701
|
+
[entityId]: {
|
|
4702
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4564
4703
|
pagination: {
|
|
4565
|
-
...currentState.comments_by_entity_id[
|
|
4704
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4566
4705
|
loading_next_page: true,
|
|
4567
4706
|
},
|
|
4568
4707
|
},
|
|
4569
4708
|
},
|
|
4570
4709
|
}));
|
|
4571
|
-
const { next
|
|
4572
|
-
this.
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
newPagination.sort = sort;
|
|
4579
|
-
}
|
|
4580
|
-
return {
|
|
4581
|
-
...currentState,
|
|
4582
|
-
comments_by_entity_id: {
|
|
4583
|
-
...currentState.comments_by_entity_id,
|
|
4584
|
-
[forId]: {
|
|
4585
|
-
...currentState.comments_by_entity_id[forId],
|
|
4586
|
-
parent_id: parentId,
|
|
4587
|
-
pagination: newPagination,
|
|
4588
|
-
comments: currentState.comments_by_entity_id[forId]?.comments
|
|
4589
|
-
? currentState.comments_by_entity_id[forId].comments?.concat(comments)
|
|
4590
|
-
: comments,
|
|
4591
|
-
},
|
|
4592
|
-
},
|
|
4593
|
-
};
|
|
4710
|
+
const { next, comments } = await base();
|
|
4711
|
+
this.loadCommentsIntoState({
|
|
4712
|
+
entityId,
|
|
4713
|
+
comments,
|
|
4714
|
+
entityParentId,
|
|
4715
|
+
next,
|
|
4716
|
+
sort,
|
|
4594
4717
|
});
|
|
4595
4718
|
}
|
|
4596
4719
|
catch (e) {
|
|
@@ -4601,10 +4724,10 @@ class Feed extends FeedApi {
|
|
|
4601
4724
|
...currentState,
|
|
4602
4725
|
comments_by_entity_id: {
|
|
4603
4726
|
...currentState.comments_by_entity_id,
|
|
4604
|
-
[
|
|
4605
|
-
...currentState.comments_by_entity_id[
|
|
4727
|
+
[entityId]: {
|
|
4728
|
+
...currentState.comments_by_entity_id[entityId],
|
|
4606
4729
|
pagination: {
|
|
4607
|
-
...currentState.comments_by_entity_id[
|
|
4730
|
+
...currentState.comments_by_entity_id[entityId]?.pagination,
|
|
4608
4731
|
loading_next_page: false,
|
|
4609
4732
|
},
|
|
4610
4733
|
},
|
|
@@ -4627,7 +4750,7 @@ class Feed extends FeedApi {
|
|
|
4627
4750
|
return;
|
|
4628
4751
|
}
|
|
4629
4752
|
await this.loadNextPageComments({
|
|
4630
|
-
|
|
4753
|
+
entityId: activity.id,
|
|
4631
4754
|
base: () => this.client.getComments({
|
|
4632
4755
|
...request,
|
|
4633
4756
|
sort,
|
|
@@ -4650,7 +4773,7 @@ class Feed extends FeedApi {
|
|
|
4650
4773
|
return;
|
|
4651
4774
|
}
|
|
4652
4775
|
await this.loadNextPageComments({
|
|
4653
|
-
|
|
4776
|
+
entityId: comment.id,
|
|
4654
4777
|
base: () => this.client.getCommentReplies({
|
|
4655
4778
|
...request,
|
|
4656
4779
|
comment_id: comment.id,
|
|
@@ -4660,7 +4783,7 @@ class Feed extends FeedApi {
|
|
|
4660
4783
|
Constants.DEFAULT_COMMENT_PAGINATION,
|
|
4661
4784
|
next: currentNextCursor,
|
|
4662
4785
|
}),
|
|
4663
|
-
|
|
4786
|
+
entityParentId: comment.parent_id ?? comment.object_id,
|
|
4664
4787
|
sort,
|
|
4665
4788
|
});
|
|
4666
4789
|
}
|
|
@@ -4690,17 +4813,19 @@ class Feed extends FeedApi {
|
|
|
4690
4813
|
next: currentNextCursor,
|
|
4691
4814
|
sort,
|
|
4692
4815
|
});
|
|
4693
|
-
this.state.next((currentState) =>
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4816
|
+
this.state.next((currentState) => {
|
|
4817
|
+
return {
|
|
4818
|
+
...currentState,
|
|
4819
|
+
[type]: currentState[type] === undefined
|
|
4820
|
+
? follows
|
|
4821
|
+
: uniqueArrayMerge(currentState[type], follows, (follow) => `${follow.source_feed.fid}-${follow.target_feed.fid}`),
|
|
4822
|
+
[paginationKey]: {
|
|
4823
|
+
...currentState[paginationKey],
|
|
4824
|
+
next: newNextCursor,
|
|
4825
|
+
sort,
|
|
4826
|
+
},
|
|
4827
|
+
};
|
|
4828
|
+
});
|
|
4704
4829
|
}
|
|
4705
4830
|
catch (e) {
|
|
4706
4831
|
error = e;
|
|
@@ -4753,7 +4878,7 @@ class Feed extends FeedApi {
|
|
|
4753
4878
|
this.state.next((currentState) => ({
|
|
4754
4879
|
...currentState,
|
|
4755
4880
|
members: currentState.members
|
|
4756
|
-
? currentState.members
|
|
4881
|
+
? uniqueArrayMerge(currentState.members, members, ({ user }) => user.id)
|
|
4757
4882
|
: members,
|
|
4758
4883
|
member_pagination: {
|
|
4759
4884
|
...currentState.member_pagination,
|
|
@@ -5340,13 +5465,17 @@ class FeedsClient extends FeedsApi {
|
|
|
5340
5465
|
};
|
|
5341
5466
|
this.eventDispatcher.dispatch(networkEvent);
|
|
5342
5467
|
};
|
|
5343
|
-
this.getOrCreateActiveFeed = (group, id, data) => {
|
|
5468
|
+
this.getOrCreateActiveFeed = (group, id, data, watch) => {
|
|
5344
5469
|
const fid = `${group}:${id}`;
|
|
5345
5470
|
if (this.activeFeeds[fid]) {
|
|
5346
|
-
|
|
5471
|
+
const feed = this.activeFeeds[fid];
|
|
5472
|
+
if (watch && !feed.currentState.watch) {
|
|
5473
|
+
feed.handleWatchStarted();
|
|
5474
|
+
}
|
|
5475
|
+
return feed;
|
|
5347
5476
|
}
|
|
5348
5477
|
else {
|
|
5349
|
-
const feed = new Feed(this, group, id, data);
|
|
5478
|
+
const feed = new Feed(this, group, id, data, watch);
|
|
5350
5479
|
this.activeFeeds[fid] = feed;
|
|
5351
5480
|
return feed;
|
|
5352
5481
|
}
|
|
@@ -5375,6 +5504,11 @@ class FeedsClient extends FeedsApi {
|
|
|
5375
5504
|
}
|
|
5376
5505
|
}
|
|
5377
5506
|
}
|
|
5507
|
+
else {
|
|
5508
|
+
for (const activeFeed of Object.values(this.activeFeeds)) {
|
|
5509
|
+
activeFeed.handleWatchStopped();
|
|
5510
|
+
}
|
|
5511
|
+
}
|
|
5378
5512
|
break;
|
|
5379
5513
|
}
|
|
5380
5514
|
case 'feeds.feed.created': {
|
|
@@ -5478,7 +5612,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5478
5612
|
}
|
|
5479
5613
|
async queryFeeds(request) {
|
|
5480
5614
|
const response = await this.feedsQueryFeeds(request);
|
|
5481
|
-
const feeds = response.feeds.map((f) => this.getOrCreateActiveFeed(f.group_id, f.id, f));
|
|
5615
|
+
const feeds = response.feeds.map((f) => this.getOrCreateActiveFeed(f.group_id, f.id, f, request?.watch));
|
|
5482
5616
|
return {
|
|
5483
5617
|
feeds,
|
|
5484
5618
|
next: response.next,
|
|
@@ -5487,6 +5621,52 @@ class FeedsClient extends FeedsApi {
|
|
|
5487
5621
|
duration: response.duration,
|
|
5488
5622
|
};
|
|
5489
5623
|
}
|
|
5624
|
+
// For follow API endpoints we update the state after HTTP response to allow queryFeeds with watch: false
|
|
5625
|
+
async follow(request) {
|
|
5626
|
+
const response = await super.follow(request);
|
|
5627
|
+
[response.follow.source_feed.fid, response.follow.target_feed.fid].forEach((fid) => {
|
|
5628
|
+
const feed = this.activeFeeds[fid];
|
|
5629
|
+
if (feed) {
|
|
5630
|
+
feed.handleFollowCreated(response.follow);
|
|
5631
|
+
}
|
|
5632
|
+
});
|
|
5633
|
+
return response;
|
|
5634
|
+
}
|
|
5635
|
+
async followBatch(request) {
|
|
5636
|
+
const response = await super.followBatch(request);
|
|
5637
|
+
response.follows.forEach((follow) => {
|
|
5638
|
+
const feed = this.activeFeeds[follow.source_feed.fid];
|
|
5639
|
+
if (feed) {
|
|
5640
|
+
feed.handleFollowCreated(follow);
|
|
5641
|
+
}
|
|
5642
|
+
});
|
|
5643
|
+
return response;
|
|
5644
|
+
}
|
|
5645
|
+
async unfollow(request) {
|
|
5646
|
+
const response = await super.unfollow(request);
|
|
5647
|
+
[request.source, request.target].forEach((fid) => {
|
|
5648
|
+
const feed = this.activeFeeds[fid];
|
|
5649
|
+
if (feed) {
|
|
5650
|
+
feed.handleFollowDeleted({
|
|
5651
|
+
source_feed: { fid: request.source },
|
|
5652
|
+
target_feed: { fid: request.target },
|
|
5653
|
+
});
|
|
5654
|
+
}
|
|
5655
|
+
});
|
|
5656
|
+
return response;
|
|
5657
|
+
}
|
|
5658
|
+
async stopWatchingFeed(request) {
|
|
5659
|
+
const connectionId = await this.connectionIdManager.getConnectionId();
|
|
5660
|
+
const response = await super.stopWatchingFeed({
|
|
5661
|
+
...request,
|
|
5662
|
+
connection_id: connectionId,
|
|
5663
|
+
});
|
|
5664
|
+
const feed = this.activeFeeds[`${request.feed_group_id}:${request.feed_id}`];
|
|
5665
|
+
if (feed) {
|
|
5666
|
+
feed.handleWatchStopped();
|
|
5667
|
+
}
|
|
5668
|
+
return response;
|
|
5669
|
+
}
|
|
5490
5670
|
findActiveFeedByActivityId(activityId) {
|
|
5491
5671
|
return Object.values(this.activeFeeds).filter((feed) => feed.currentState.activities?.some((activity) => activity.id === activityId));
|
|
5492
5672
|
}
|
|
@@ -5549,10 +5729,10 @@ const useFeedsClient = () => {
|
|
|
5549
5729
|
*/
|
|
5550
5730
|
const useClientConnectedUser = () => {
|
|
5551
5731
|
const client = useFeedsClient();
|
|
5552
|
-
const { user } = useStateStore(client?.state, selector$
|
|
5732
|
+
const { user } = useStateStore(client?.state, selector$a) ?? {};
|
|
5553
5733
|
return user;
|
|
5554
5734
|
};
|
|
5555
|
-
const selector$
|
|
5735
|
+
const selector$a = (nextState) => ({
|
|
5556
5736
|
user: nextState.connected_user,
|
|
5557
5737
|
});
|
|
5558
5738
|
|
|
@@ -5561,10 +5741,10 @@ const selector$7 = (nextState) => ({
|
|
|
5561
5741
|
*/
|
|
5562
5742
|
const useWsConnectionState = () => {
|
|
5563
5743
|
const client = useFeedsClient();
|
|
5564
|
-
const { is_healthy } = useStateStore(client?.state, selector$
|
|
5744
|
+
const { is_healthy } = useStateStore(client?.state, selector$9) ?? {};
|
|
5565
5745
|
return { is_healthy };
|
|
5566
5746
|
};
|
|
5567
|
-
const selector$
|
|
5747
|
+
const selector$9 = (nextState) => ({
|
|
5568
5748
|
is_healthy: nextState.is_ws_connection_healthy,
|
|
5569
5749
|
});
|
|
5570
5750
|
|
|
@@ -5614,7 +5794,7 @@ const useStableCallback = (callback) => {
|
|
|
5614
5794
|
const useFeedActivities = (feedFromProps) => {
|
|
5615
5795
|
const feedFromContext = useFeedContext();
|
|
5616
5796
|
const feed = feedFromProps ?? feedFromContext;
|
|
5617
|
-
const data = useStateStore(feed?.state, selector$
|
|
5797
|
+
const data = useStateStore(feed?.state, selector$8);
|
|
5618
5798
|
const loadNextPage = useStableCallback(async () => {
|
|
5619
5799
|
if (!feed || !data?.has_next_page || data?.is_loading) {
|
|
5620
5800
|
return;
|
|
@@ -5623,7 +5803,7 @@ const useFeedActivities = (feedFromProps) => {
|
|
|
5623
5803
|
});
|
|
5624
5804
|
return react.useMemo(() => ({ ...data, loadNextPage }), [data, loadNextPage]);
|
|
5625
5805
|
};
|
|
5626
|
-
const selector$
|
|
5806
|
+
const selector$8 = ({ is_loading_activities, next, activities = [] }) => ({
|
|
5627
5807
|
is_loading: is_loading_activities,
|
|
5628
5808
|
has_next_page: typeof next !== 'undefined',
|
|
5629
5809
|
activities,
|
|
@@ -5696,13 +5876,13 @@ const FeedOwnCapability = {
|
|
|
5696
5876
|
};
|
|
5697
5877
|
|
|
5698
5878
|
const stableEmptyArray = [];
|
|
5699
|
-
const selector$
|
|
5879
|
+
const selector$7 = (currentState) => ({
|
|
5700
5880
|
oc: currentState.own_capabilities ?? stableEmptyArray,
|
|
5701
5881
|
});
|
|
5702
5882
|
const useOwnCapabilities = (feedFromProps) => {
|
|
5703
5883
|
const feedFromContext = useFeedContext();
|
|
5704
5884
|
const feed = feedFromProps ?? feedFromContext;
|
|
5705
|
-
const { oc = stableEmptyArray } = useStateStore(feed?.state, selector$
|
|
5885
|
+
const { oc = stableEmptyArray } = useStateStore(feed?.state, selector$7) ?? {};
|
|
5706
5886
|
return react.useMemo(() => ({
|
|
5707
5887
|
can_add_activity: oc.indexOf(FeedOwnCapability.ADD_ACTIVITY) > -1,
|
|
5708
5888
|
can_add_activity_reaction: oc.indexOf(FeedOwnCapability.ADD_ACTIVITY_REACTION) > -1,
|
|
@@ -5737,7 +5917,7 @@ const useOwnCapabilities = (feedFromProps) => {
|
|
|
5737
5917
|
}), [oc]);
|
|
5738
5918
|
};
|
|
5739
5919
|
|
|
5740
|
-
const selector$
|
|
5920
|
+
const selector$6 = ({ follower_count, followers, followers_pagination, }) => ({
|
|
5741
5921
|
follower_count,
|
|
5742
5922
|
followers,
|
|
5743
5923
|
followers_pagination,
|
|
@@ -5745,7 +5925,7 @@ const selector$3 = ({ follower_count, followers, followers_pagination, }) => ({
|
|
|
5745
5925
|
function useFollowers(feedFromProps) {
|
|
5746
5926
|
const feedFromContext = useFeedContext();
|
|
5747
5927
|
const feed = feedFromProps ?? feedFromContext;
|
|
5748
|
-
const data = useStateStore(feed?.state, selector$
|
|
5928
|
+
const data = useStateStore(feed?.state, selector$6);
|
|
5749
5929
|
const loadNextPage = react.useCallback((...options) => feed?.loadNextPageFollowers(...options), [feed]);
|
|
5750
5930
|
return react.useMemo(() => {
|
|
5751
5931
|
if (!data) {
|
|
@@ -5760,7 +5940,7 @@ function useFollowers(feedFromProps) {
|
|
|
5760
5940
|
}, [data, loadNextPage]);
|
|
5761
5941
|
}
|
|
5762
5942
|
|
|
5763
|
-
const selector$
|
|
5943
|
+
const selector$5 = ({ following_count, following, following_pagination, }) => ({
|
|
5764
5944
|
following_count,
|
|
5765
5945
|
following,
|
|
5766
5946
|
following_pagination,
|
|
@@ -5768,7 +5948,7 @@ const selector$2 = ({ following_count, following, following_pagination, }) => ({
|
|
|
5768
5948
|
function useFollowing(feedFromProps) {
|
|
5769
5949
|
const feedFromContext = useFeedContext();
|
|
5770
5950
|
const feed = feedFromProps ?? feedFromContext;
|
|
5771
|
-
const data = useStateStore(feed?.state, selector$
|
|
5951
|
+
const data = useStateStore(feed?.state, selector$5);
|
|
5772
5952
|
const loadNextPage = react.useCallback((...options) => feed?.loadNextPageFollowing(...options), [feed]);
|
|
5773
5953
|
return react.useMemo(() => {
|
|
5774
5954
|
if (!data) {
|
|
@@ -5790,9 +5970,9 @@ function useFollowing(feedFromProps) {
|
|
|
5790
5970
|
const useFeedMetadata = (feedFromProps) => {
|
|
5791
5971
|
const feedFromContext = useFeedContext();
|
|
5792
5972
|
const feed = feedFromProps ?? feedFromContext;
|
|
5793
|
-
return useStateStore(feed?.state, selector$
|
|
5973
|
+
return useStateStore(feed?.state, selector$4);
|
|
5794
5974
|
};
|
|
5795
|
-
const selector$
|
|
5975
|
+
const selector$4 = ({ follower_count = 0, following_count = 0, created_by, created_at, updated_at, }) => ({
|
|
5796
5976
|
created_by,
|
|
5797
5977
|
follower_count,
|
|
5798
5978
|
following_count,
|
|
@@ -5807,18 +5987,68 @@ const selector$1 = ({ follower_count = 0, following_count = 0, created_by, creat
|
|
|
5807
5987
|
const useOwnFollows = (feedFromProps) => {
|
|
5808
5988
|
const feedFromContext = useFeedContext();
|
|
5809
5989
|
const feed = feedFromProps ?? feedFromContext;
|
|
5810
|
-
return useStateStore(feed?.state, selector);
|
|
5990
|
+
return useStateStore(feed?.state, selector$3);
|
|
5811
5991
|
};
|
|
5812
|
-
const selector = ({ own_follows }) => ({
|
|
5992
|
+
const selector$3 = ({ own_follows }) => ({
|
|
5813
5993
|
own_follows,
|
|
5814
5994
|
});
|
|
5815
5995
|
|
|
5996
|
+
const StreamSearchResultsContext = react.createContext(undefined);
|
|
5997
|
+
/**
|
|
5998
|
+
* Hook to access the nearest SearchSource instance.
|
|
5999
|
+
*/
|
|
6000
|
+
const useSearchResultsContext = () => {
|
|
6001
|
+
return react.useContext(StreamSearchResultsContext);
|
|
6002
|
+
};
|
|
6003
|
+
|
|
6004
|
+
const useSearchResult = (sourceFromProps) => {
|
|
6005
|
+
const sourceFromContext = useSearchResultsContext();
|
|
6006
|
+
const source = sourceFromProps ?? sourceFromContext;
|
|
6007
|
+
const { items, error, isLoading, hasNext } = useStateStore(source?.state, selector$2) ?? {};
|
|
6008
|
+
const loadMore = useStableCallback(async () => {
|
|
6009
|
+
source?.search();
|
|
6010
|
+
});
|
|
6011
|
+
return react.useMemo(() => ({ items, error, isLoading, hasNext, loadMore }), [error, hasNext, isLoading, items, loadMore]);
|
|
6012
|
+
};
|
|
6013
|
+
const selector$2 = ({ items, isLoading, hasNext, lastQueryError, }) => ({
|
|
6014
|
+
items,
|
|
6015
|
+
isLoading,
|
|
6016
|
+
hasNext,
|
|
6017
|
+
error: lastQueryError,
|
|
6018
|
+
});
|
|
6019
|
+
|
|
6020
|
+
const StreamSearchContext = react.createContext(undefined);
|
|
6021
|
+
/**
|
|
6022
|
+
* Hook to access the nearest SearchController instance.
|
|
6023
|
+
*/
|
|
6024
|
+
const useSearchContext = () => {
|
|
6025
|
+
return react.useContext(StreamSearchContext);
|
|
6026
|
+
};
|
|
6027
|
+
|
|
6028
|
+
const useSearchQuery = (controllerFromProps) => {
|
|
6029
|
+
const controllerFromState = useSearchContext();
|
|
6030
|
+
const controller = controllerFromProps ?? controllerFromState;
|
|
6031
|
+
return useStateStore(controller?.state, selector$1);
|
|
6032
|
+
};
|
|
6033
|
+
const selector$1 = ({ searchQuery }) => ({
|
|
6034
|
+
searchQuery,
|
|
6035
|
+
});
|
|
6036
|
+
|
|
6037
|
+
const useSearchSources = (controllerFromProps) => {
|
|
6038
|
+
const controllerFromState = useSearchContext();
|
|
6039
|
+
const controller = controllerFromProps ?? controllerFromState;
|
|
6040
|
+
return useStateStore(controller?.state, selector);
|
|
6041
|
+
};
|
|
6042
|
+
const selector = ({ sources }) => ({
|
|
6043
|
+
sources,
|
|
6044
|
+
});
|
|
6045
|
+
|
|
5816
6046
|
/**
|
|
5817
6047
|
* A utility hook that takes in an entity and a reaction type, and creates reaction actions
|
|
5818
6048
|
* that can then be used on the UI. The entity can be either an ActivityResponse or a CommentResponse
|
|
5819
6049
|
* as the hook determines internally which APIs it is supposed to use, while taking the
|
|
5820
6050
|
* correct ownCapabilities into account.
|
|
5821
|
-
* @param entity - The entity to which we want to
|
|
6051
|
+
* @param entity - The entity to which we want to apply reaction actions, can be either ActivityResponse or CommentResponse.
|
|
5822
6052
|
* @param type - The type of reaction we want to add or remove.
|
|
5823
6053
|
*/
|
|
5824
6054
|
const useReactionActions = ({ entity, type, }) => {
|
|
@@ -5849,6 +6079,31 @@ const useReactionActions = ({ entity, type, }) => {
|
|
|
5849
6079
|
return react.useMemo(() => ({ addReaction, removeReaction, toggleReaction }), [addReaction, removeReaction, toggleReaction]);
|
|
5850
6080
|
};
|
|
5851
6081
|
|
|
6082
|
+
/**
|
|
6083
|
+
* A utility hook that takes in an entity and creates bookmark actions
|
|
6084
|
+
* that can then be used on the UI. The entity is expected to be an ActivityResponse.
|
|
6085
|
+
* @param entity - The entity to which we want to apply reaction actions, expects an ActivityResponse.
|
|
6086
|
+
*/
|
|
6087
|
+
const useBookmarkActions = ({ entity, }) => {
|
|
6088
|
+
const client = useFeedsClient();
|
|
6089
|
+
const hasOwnBookmark = entity.own_bookmarks?.length > 0;
|
|
6090
|
+
const addBookmark = useStableCallback(async () => {
|
|
6091
|
+
await client?.addBookmark({ activity_id: entity.id });
|
|
6092
|
+
});
|
|
6093
|
+
const removeBookmark = useStableCallback(async () => {
|
|
6094
|
+
await client?.deleteBookmark({ activity_id: entity.id });
|
|
6095
|
+
});
|
|
6096
|
+
const toggleBookmark = useStableCallback(async () => {
|
|
6097
|
+
if (hasOwnBookmark) {
|
|
6098
|
+
await removeBookmark();
|
|
6099
|
+
}
|
|
6100
|
+
else {
|
|
6101
|
+
await addBookmark();
|
|
6102
|
+
}
|
|
6103
|
+
});
|
|
6104
|
+
return react.useMemo(() => ({ addBookmark, removeBookmark, toggleBookmark }), [addBookmark, removeBookmark, toggleBookmark]);
|
|
6105
|
+
};
|
|
6106
|
+
|
|
5852
6107
|
const StreamFeeds = ({ client, children }) => {
|
|
5853
6108
|
return (jsxRuntime.jsx(StreamFeedsContext.Provider, { value: client, children: children }));
|
|
5854
6109
|
};
|
|
@@ -5859,10 +6114,25 @@ const StreamFeed = ({ feed, children }) => {
|
|
|
5859
6114
|
};
|
|
5860
6115
|
StreamFeed.displayName = 'StreamFeed';
|
|
5861
6116
|
|
|
6117
|
+
const StreamSearch = ({ searchController, children, }) => {
|
|
6118
|
+
return (jsxRuntime.jsx(StreamSearchContext.Provider, { value: searchController, children: children }));
|
|
6119
|
+
};
|
|
6120
|
+
StreamSearch.displayName = 'StreamSearch';
|
|
6121
|
+
|
|
6122
|
+
const StreamSearchResults = ({ source, children, }) => {
|
|
6123
|
+
return (jsxRuntime.jsx(StreamSearchResultsContext.Provider, { value: source, children: children }));
|
|
6124
|
+
};
|
|
6125
|
+
StreamSearchResults.displayName = 'StreamSearchResults';
|
|
6126
|
+
|
|
5862
6127
|
exports.StreamFeed = StreamFeed;
|
|
5863
6128
|
exports.StreamFeedContext = StreamFeedContext;
|
|
5864
6129
|
exports.StreamFeeds = StreamFeeds;
|
|
5865
6130
|
exports.StreamFeedsContext = StreamFeedsContext;
|
|
6131
|
+
exports.StreamSearch = StreamSearch;
|
|
6132
|
+
exports.StreamSearchContext = StreamSearchContext;
|
|
6133
|
+
exports.StreamSearchResults = StreamSearchResults;
|
|
6134
|
+
exports.StreamSearchResultsContext = StreamSearchResultsContext;
|
|
6135
|
+
exports.useBookmarkActions = useBookmarkActions;
|
|
5866
6136
|
exports.useClientConnectedUser = useClientConnectedUser;
|
|
5867
6137
|
exports.useComments = useComments;
|
|
5868
6138
|
exports.useCreateFeedsClient = useCreateFeedsClient;
|
|
@@ -5875,6 +6145,11 @@ exports.useFollowing = useFollowing;
|
|
|
5875
6145
|
exports.useOwnCapabilities = useOwnCapabilities;
|
|
5876
6146
|
exports.useOwnFollows = useOwnFollows;
|
|
5877
6147
|
exports.useReactionActions = useReactionActions;
|
|
6148
|
+
exports.useSearchContext = useSearchContext;
|
|
6149
|
+
exports.useSearchQuery = useSearchQuery;
|
|
6150
|
+
exports.useSearchResult = useSearchResult;
|
|
6151
|
+
exports.useSearchResultsContext = useSearchResultsContext;
|
|
6152
|
+
exports.useSearchSources = useSearchSources;
|
|
5878
6153
|
exports.useStateStore = useStateStore;
|
|
5879
6154
|
exports.useWsConnectionState = useWsConnectionState;
|
|
5880
6155
|
//# sourceMappingURL=index-react-bindings.node.cjs.map
|