@stream-io/feeds-client 0.1.1 → 0.1.3
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/index.ts +13 -1
- package/CHANGELOG.md +31 -0
- package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +15 -0
- package/dist/@react-bindings/hooks/clientStateHooks.d.ts +10 -0
- package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +13 -0
- package/dist/@react-bindings/hooks/useStateStore.d.ts +1 -1
- package/dist/@react-bindings/index.d.ts +4 -0
- package/dist/@react-bindings/wrappers/StreamFeeds.d.ts +6 -0
- package/dist/index-react-bindings.browser.cjs +5411 -12
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +5407 -14
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +5411 -12
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +5407 -14
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +125 -36
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +125 -36
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +125 -36
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +125 -36
- package/dist/index.node.js.map +1 -1
- package/dist/src/Feed.d.ts +4 -2
- package/dist/src/FeedsClient.d.ts +9 -5
- package/dist/src/common/ApiClient.d.ts +1 -0
- package/dist/src/common/StateStore.d.ts +1 -0
- package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
- package/dist/src/gen/feeds/FeedsApi.d.ts +7 -1
- package/dist/src/gen/models/index.d.ts +41 -0
- package/dist/src/types.d.ts +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -6
- package/src/Feed.ts +33 -15
- package/src/FeedsClient.ts +37 -17
- package/src/common/ApiClient.ts +10 -3
- package/src/common/StateStore.ts +30 -12
- package/src/common/utils.ts +1 -1
- package/src/gen/feeds/FeedsApi.ts +51 -0
- package/src/gen/model-decoders/decoders.ts +29 -0
- package/src/gen/model-decoders/event-decoder-mapping.ts +6 -0
- package/src/gen/models/index.ts +60 -0
- package/src/types.ts +4 -0
package/dist/index.node.cjs
CHANGED
|
@@ -261,6 +261,14 @@ decoders.BookmarkDeletedEvent = (input) => {
|
|
|
261
261
|
};
|
|
262
262
|
return decode(typeMappings, input);
|
|
263
263
|
};
|
|
264
|
+
decoders.BookmarkFolderDeletedEvent = (input) => {
|
|
265
|
+
const typeMappings = {
|
|
266
|
+
created_at: { type: 'DatetimeType', isSingle: true },
|
|
267
|
+
bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
|
|
268
|
+
received_at: { type: 'DatetimeType', isSingle: true },
|
|
269
|
+
};
|
|
270
|
+
return decode(typeMappings, input);
|
|
271
|
+
};
|
|
264
272
|
decoders.BookmarkFolderResponse = (input) => {
|
|
265
273
|
const typeMappings = {
|
|
266
274
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -268,6 +276,14 @@ decoders.BookmarkFolderResponse = (input) => {
|
|
|
268
276
|
};
|
|
269
277
|
return decode(typeMappings, input);
|
|
270
278
|
};
|
|
279
|
+
decoders.BookmarkFolderUpdatedEvent = (input) => {
|
|
280
|
+
const typeMappings = {
|
|
281
|
+
created_at: { type: 'DatetimeType', isSingle: true },
|
|
282
|
+
bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
|
|
283
|
+
received_at: { type: 'DatetimeType', isSingle: true },
|
|
284
|
+
};
|
|
285
|
+
return decode(typeMappings, input);
|
|
286
|
+
};
|
|
271
287
|
decoders.BookmarkResponse = (input) => {
|
|
272
288
|
const typeMappings = {
|
|
273
289
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -1227,6 +1243,12 @@ decoders.UpdateBlockListResponse = (input) => {
|
|
|
1227
1243
|
};
|
|
1228
1244
|
return decode(typeMappings, input);
|
|
1229
1245
|
};
|
|
1246
|
+
decoders.UpdateBookmarkFolderResponse = (input) => {
|
|
1247
|
+
const typeMappings = {
|
|
1248
|
+
bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
|
|
1249
|
+
};
|
|
1250
|
+
return decode(typeMappings, input);
|
|
1251
|
+
};
|
|
1230
1252
|
decoders.UpdateBookmarkResponse = (input) => {
|
|
1231
1253
|
const typeMappings = {
|
|
1232
1254
|
bookmark: { type: 'BookmarkResponse', isSingle: true },
|
|
@@ -1647,6 +1669,26 @@ class FeedsApi {
|
|
|
1647
1669
|
decoders.QueryBookmarkFoldersResponse?.(response.body);
|
|
1648
1670
|
return { ...response.body, metadata: response.metadata };
|
|
1649
1671
|
}
|
|
1672
|
+
async deleteBookmarkFolder(request) {
|
|
1673
|
+
const pathParams = {
|
|
1674
|
+
folder_id: request?.folder_id,
|
|
1675
|
+
};
|
|
1676
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/bookmark_folders/{folder_id}', pathParams, undefined);
|
|
1677
|
+
decoders.DeleteBookmarkFolderResponse?.(response.body);
|
|
1678
|
+
return { ...response.body, metadata: response.metadata };
|
|
1679
|
+
}
|
|
1680
|
+
async updateBookmarkFolder(request) {
|
|
1681
|
+
const pathParams = {
|
|
1682
|
+
folder_id: request?.folder_id,
|
|
1683
|
+
};
|
|
1684
|
+
const body = {
|
|
1685
|
+
name: request?.name,
|
|
1686
|
+
custom: request?.custom,
|
|
1687
|
+
};
|
|
1688
|
+
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/bookmark_folders/{folder_id}', pathParams, undefined, body, 'application/json');
|
|
1689
|
+
decoders.UpdateBookmarkFolderResponse?.(response.body);
|
|
1690
|
+
return { ...response.body, metadata: response.metadata };
|
|
1691
|
+
}
|
|
1650
1692
|
async queryBookmarks(request) {
|
|
1651
1693
|
const body = {
|
|
1652
1694
|
limit: request?.limit,
|
|
@@ -2323,14 +2365,9 @@ class StateStore {
|
|
|
2323
2365
|
let previouslySelectedValues;
|
|
2324
2366
|
const wrappedHandler = (nextValue) => {
|
|
2325
2367
|
const newlySelectedValues = selector(nextValue);
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
continue;
|
|
2330
|
-
hasUpdatedValues = true;
|
|
2331
|
-
break;
|
|
2332
|
-
}
|
|
2333
|
-
if (!hasUpdatedValues)
|
|
2368
|
+
// shallow comparison of previouslySelectedValues and newlySelectedValues
|
|
2369
|
+
const selectionsAreEqual = StateStore.doSelectionsEqual(previouslySelectedValues, newlySelectedValues);
|
|
2370
|
+
if (selectionsAreEqual)
|
|
2334
2371
|
return;
|
|
2335
2372
|
// save a copy of previouslySelectedValues before running
|
|
2336
2373
|
// handler - if previouslySelectedValues are set to
|
|
@@ -2361,7 +2398,7 @@ class StateStore {
|
|
|
2361
2398
|
? newValueOrPatch(this.value)
|
|
2362
2399
|
: newValueOrPatch;
|
|
2363
2400
|
// do not notify subscribers if the value hasn't changed
|
|
2364
|
-
if (newValue
|
|
2401
|
+
if (Object.is(newValue, this.value))
|
|
2365
2402
|
return;
|
|
2366
2403
|
this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
|
|
2367
2404
|
const oldValue = this.value;
|
|
@@ -2378,6 +2415,19 @@ class StateStore {
|
|
|
2378
2415
|
this.handlers.delete(handler);
|
|
2379
2416
|
};
|
|
2380
2417
|
}
|
|
2418
|
+
static doSelectionsEqual(previouslySelectedValues, newlySelectedValues) {
|
|
2419
|
+
let selectionsAreEqual;
|
|
2420
|
+
if ((selectionsAreEqual = typeof previouslySelectedValues !== 'undefined')) {
|
|
2421
|
+
for (const key in newlySelectedValues) {
|
|
2422
|
+
if (Object.is(previouslySelectedValues[key], newlySelectedValues[key])) {
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
selectionsAreEqual = false;
|
|
2426
|
+
break;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
return selectionsAreEqual;
|
|
2430
|
+
}
|
|
2381
2431
|
/**
|
|
2382
2432
|
* Registers a preprocessor function that will be called before the state is updated.
|
|
2383
2433
|
*
|
|
@@ -2603,7 +2653,7 @@ function getRandomValuesWithMathRandom(bytes) {
|
|
|
2603
2653
|
}
|
|
2604
2654
|
}
|
|
2605
2655
|
const getRandomValues = (() => {
|
|
2606
|
-
if (typeof crypto?.getRandomValues !== 'undefined') {
|
|
2656
|
+
if (typeof crypto !== 'undefined' && typeof crypto?.getRandomValues !== 'undefined') {
|
|
2607
2657
|
return crypto.getRandomValues.bind(crypto);
|
|
2608
2658
|
}
|
|
2609
2659
|
else if (typeof msCrypto !== 'undefined') {
|
|
@@ -3495,7 +3545,10 @@ class ApiClient {
|
|
|
3495
3545
|
const encodedBody = requestContentType === 'multipart/form-data' ? new FormData() : body;
|
|
3496
3546
|
if (requestContentType === 'multipart/form-data') {
|
|
3497
3547
|
Object.keys(body).forEach((key) => {
|
|
3498
|
-
|
|
3548
|
+
const value = body[key];
|
|
3549
|
+
if (value != null) {
|
|
3550
|
+
encodedBody.append(key, value);
|
|
3551
|
+
}
|
|
3499
3552
|
});
|
|
3500
3553
|
}
|
|
3501
3554
|
try {
|
|
@@ -3504,8 +3557,11 @@ class ApiClient {
|
|
|
3504
3557
|
method,
|
|
3505
3558
|
headers,
|
|
3506
3559
|
params: queryParams,
|
|
3507
|
-
paramsSerializer: params => this.queryParamsStringify(params),
|
|
3560
|
+
paramsSerializer: (params) => this.queryParamsStringify(params),
|
|
3508
3561
|
data: encodedBody,
|
|
3562
|
+
timeout:
|
|
3563
|
+
// multipart/form-data requests should not have a timeout allowing ample time for file uploads
|
|
3564
|
+
requestContentType === 'multipart/form-data' ? 0 : this.timeout,
|
|
3509
3565
|
});
|
|
3510
3566
|
const metadata = this.getRequestMetadata(client_request_id, response);
|
|
3511
3567
|
return { body: response.data, metadata };
|
|
@@ -3569,9 +3625,9 @@ class ApiClient {
|
|
|
3569
3625
|
};
|
|
3570
3626
|
};
|
|
3571
3627
|
this.baseUrl = options?.base_url ?? 'https://video.stream-io-api.com';
|
|
3628
|
+
this.timeout = options?.timeout ?? 3000;
|
|
3572
3629
|
this.axiosInstance = axios.create({
|
|
3573
3630
|
baseURL: this.baseUrl,
|
|
3574
|
-
timeout: options?.timeout ?? 3000,
|
|
3575
3631
|
});
|
|
3576
3632
|
}
|
|
3577
3633
|
get webSocketBaseUrl() {
|
|
@@ -3612,6 +3668,8 @@ const eventDecoderMapping = {
|
|
|
3612
3668
|
'feeds.bookmark.added': (data) => decoders.BookmarkAddedEvent(data),
|
|
3613
3669
|
'feeds.bookmark.deleted': (data) => decoders.BookmarkDeletedEvent(data),
|
|
3614
3670
|
'feeds.bookmark.updated': (data) => decoders.BookmarkUpdatedEvent(data),
|
|
3671
|
+
'feeds.bookmark_folder.deleted': (data) => decoders.BookmarkFolderDeletedEvent(data),
|
|
3672
|
+
'feeds.bookmark_folder.updated': (data) => decoders.BookmarkFolderUpdatedEvent(data),
|
|
3615
3673
|
'feeds.comment.added': (data) => decoders.CommentAddedEvent(data),
|
|
3616
3674
|
'feeds.comment.deleted': (data) => decoders.CommentDeletedEvent(data),
|
|
3617
3675
|
'feeds.comment.reaction.added': (data) => decoders.CommentReactionAddedEvent(data),
|
|
@@ -4014,6 +4072,8 @@ class Feed extends FeedApi {
|
|
|
4014
4072
|
'feeds.bookmark.added': this.handleBookmarkAdded.bind(this),
|
|
4015
4073
|
'feeds.bookmark.deleted': this.handleBookmarkDeleted.bind(this),
|
|
4016
4074
|
'feeds.bookmark.updated': this.handleBookmarkUpdated.bind(this),
|
|
4075
|
+
'feeds.bookmark_folder.deleted': Feed.noop,
|
|
4076
|
+
'feeds.bookmark_folder.updated': Feed.noop,
|
|
4017
4077
|
'feeds.comment.added': (event) => {
|
|
4018
4078
|
const { comment } = event;
|
|
4019
4079
|
const forId = comment.parent_id ?? comment.object_id;
|
|
@@ -4103,16 +4163,19 @@ class Feed extends FeedApi {
|
|
|
4103
4163
|
return;
|
|
4104
4164
|
// this feed followed someone
|
|
4105
4165
|
if (event.follow.source_feed.fid === this.fid) {
|
|
4106
|
-
|
|
4107
|
-
|
|
4166
|
+
this.state.next((currentState) => {
|
|
4167
|
+
const newState = {
|
|
4108
4168
|
...currentState,
|
|
4109
4169
|
...event.follow.source_feed,
|
|
4170
|
+
};
|
|
4171
|
+
if (currentState.following_pagination?.next === END_OF_LIST) {
|
|
4110
4172
|
// TODO: respect sort
|
|
4111
|
-
following
|
|
4173
|
+
newState.following = currentState.following
|
|
4112
4174
|
? currentState.following.concat(event.follow)
|
|
4113
|
-
: [event.follow]
|
|
4114
|
-
}
|
|
4115
|
-
|
|
4175
|
+
: [event.follow];
|
|
4176
|
+
}
|
|
4177
|
+
return newState;
|
|
4178
|
+
});
|
|
4116
4179
|
}
|
|
4117
4180
|
else if (
|
|
4118
4181
|
// someone followed this feed
|
|
@@ -4122,14 +4185,14 @@ class Feed extends FeedApi {
|
|
|
4122
4185
|
this.state.next((currentState) => {
|
|
4123
4186
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4124
4187
|
if (source.created_by.id === connectedUser?.id) {
|
|
4125
|
-
newState.own_follows =
|
|
4126
|
-
?
|
|
4188
|
+
newState.own_follows = currentState.own_follows
|
|
4189
|
+
? currentState.own_follows.concat(event.follow)
|
|
4127
4190
|
: [event.follow];
|
|
4128
4191
|
}
|
|
4129
4192
|
if (currentState.followers_pagination?.next === END_OF_LIST) {
|
|
4130
4193
|
// TODO: respect sort
|
|
4131
|
-
newState.followers =
|
|
4132
|
-
?
|
|
4194
|
+
newState.followers = currentState.followers
|
|
4195
|
+
? currentState.followers.concat(event.follow)
|
|
4133
4196
|
: [event.follow];
|
|
4134
4197
|
}
|
|
4135
4198
|
return newState;
|
|
@@ -4155,9 +4218,9 @@ class Feed extends FeedApi {
|
|
|
4155
4218
|
this.state.next((currentState) => {
|
|
4156
4219
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4157
4220
|
if (source.created_by.id === connectedUser?.id) {
|
|
4158
|
-
newState.own_follows =
|
|
4221
|
+
newState.own_follows = currentState.own_follows?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4159
4222
|
}
|
|
4160
|
-
newState.followers =
|
|
4223
|
+
newState.followers = currentState.followers?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4161
4224
|
return newState;
|
|
4162
4225
|
});
|
|
4163
4226
|
}
|
|
@@ -4284,6 +4347,12 @@ class Feed extends FeedApi {
|
|
|
4284
4347
|
};
|
|
4285
4348
|
});
|
|
4286
4349
|
}
|
|
4350
|
+
async synchronize() {
|
|
4351
|
+
const { last_get_or_create_request_config } = this.state.getLatestValue();
|
|
4352
|
+
if (last_get_or_create_request_config?.watch) {
|
|
4353
|
+
await this.getOrCreate(last_get_or_create_request_config);
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4287
4356
|
async getOrCreate(request) {
|
|
4288
4357
|
if (this.currentState.is_loading_activities) {
|
|
4289
4358
|
throw new Error('Only one getOrCreate call is allowed at a time');
|
|
@@ -4349,6 +4418,7 @@ class Feed extends FeedApi {
|
|
|
4349
4418
|
if (!request?.following_pagination?.limit) {
|
|
4350
4419
|
delete nextState.following;
|
|
4351
4420
|
}
|
|
4421
|
+
nextState.last_get_or_create_request_config = request;
|
|
4352
4422
|
return nextState;
|
|
4353
4423
|
});
|
|
4354
4424
|
}
|
|
@@ -4635,7 +4705,7 @@ class Feed extends FeedApi {
|
|
|
4635
4705
|
}
|
|
4636
4706
|
async getNextPage() {
|
|
4637
4707
|
const currentState = this.currentState;
|
|
4638
|
-
|
|
4708
|
+
return await this.getOrCreate({
|
|
4639
4709
|
member_pagination: {
|
|
4640
4710
|
limit: 0,
|
|
4641
4711
|
},
|
|
@@ -4646,8 +4716,8 @@ class Feed extends FeedApi {
|
|
|
4646
4716
|
limit: 0,
|
|
4647
4717
|
},
|
|
4648
4718
|
next: currentState.next,
|
|
4719
|
+
limit: currentState.last_get_or_create_request_config?.limit ?? 20,
|
|
4649
4720
|
});
|
|
4650
|
-
return response;
|
|
4651
4721
|
}
|
|
4652
4722
|
addActivity(request) {
|
|
4653
4723
|
return this.feedsApi.addActivity({
|
|
@@ -5050,6 +5120,7 @@ class FeedsClient extends FeedsApi {
|
|
|
5050
5120
|
super(apiClient);
|
|
5051
5121
|
this.eventDispatcher = new EventDispatcher();
|
|
5052
5122
|
this.activeFeeds = {};
|
|
5123
|
+
this.healthyConnectionChangedEventCount = 0;
|
|
5053
5124
|
this.pollFromState = (id) => this.polls_by_id.get(id);
|
|
5054
5125
|
this.connectUser = async (user, tokenProvider) => {
|
|
5055
5126
|
if (this.state.getLatestValue().connectedUser !== undefined ||
|
|
@@ -5065,7 +5136,10 @@ class FeedsClient extends FeedsApi {
|
|
|
5065
5136
|
}, this.tokenManager, this.connectionIdManager, [decodeWSEvent]);
|
|
5066
5137
|
this.wsConnection.on('all', (event) => this.eventDispatcher.dispatch(event));
|
|
5067
5138
|
const connectedEvent = await this.wsConnection.connect();
|
|
5068
|
-
this.state.partialNext({
|
|
5139
|
+
this.state.partialNext({
|
|
5140
|
+
connectedUser: connectedEvent?.me,
|
|
5141
|
+
isWsConnectionHealthy: this.wsConnection.isHealthy,
|
|
5142
|
+
});
|
|
5069
5143
|
}
|
|
5070
5144
|
catch (err) {
|
|
5071
5145
|
await this.disconnectUser();
|
|
@@ -5120,13 +5194,20 @@ class FeedsClient extends FeedsApi {
|
|
|
5120
5194
|
removeConnectionEventListeners(this.updateNetworkConnectionStatus);
|
|
5121
5195
|
this.connectionIdManager.reset();
|
|
5122
5196
|
this.tokenManager.reset();
|
|
5123
|
-
this.state.partialNext({ connectedUser: undefined });
|
|
5197
|
+
this.state.partialNext({ connectedUser: undefined, isWsConnectionHealthy: false });
|
|
5124
5198
|
};
|
|
5125
5199
|
this.on = this.eventDispatcher.on;
|
|
5126
5200
|
this.off = this.eventDispatcher.off;
|
|
5127
5201
|
this.feed = (groupId, id) => {
|
|
5128
5202
|
return this.getOrCreateActiveFeed(groupId, id);
|
|
5129
5203
|
};
|
|
5204
|
+
this.updateNetworkConnectionStatus = (event) => {
|
|
5205
|
+
const networkEvent = {
|
|
5206
|
+
type: 'network.changed',
|
|
5207
|
+
online: event.type === 'online',
|
|
5208
|
+
};
|
|
5209
|
+
this.eventDispatcher.dispatch(networkEvent);
|
|
5210
|
+
};
|
|
5130
5211
|
this.getOrCreateActiveFeed = (group, id, data) => {
|
|
5131
5212
|
const fid = `${group}:${id}`;
|
|
5132
5213
|
if (this.activeFeeds[fid]) {
|
|
@@ -5138,15 +5219,9 @@ class FeedsClient extends FeedsApi {
|
|
|
5138
5219
|
return feed;
|
|
5139
5220
|
}
|
|
5140
5221
|
};
|
|
5141
|
-
this.updateNetworkConnectionStatus = (event) => {
|
|
5142
|
-
const networkEvent = {
|
|
5143
|
-
type: 'network.changed',
|
|
5144
|
-
online: event.type === 'online',
|
|
5145
|
-
};
|
|
5146
|
-
this.eventDispatcher.dispatch(networkEvent);
|
|
5147
|
-
};
|
|
5148
5222
|
this.state = new StateStore({
|
|
5149
5223
|
connectedUser: undefined,
|
|
5224
|
+
isWsConnectionHealthy: false,
|
|
5150
5225
|
});
|
|
5151
5226
|
this.moderation = new ModerationClient(apiClient);
|
|
5152
5227
|
this.tokenManager = tokenManager;
|
|
@@ -5156,6 +5231,20 @@ class FeedsClient extends FeedsApi {
|
|
|
5156
5231
|
const fid = event.fid;
|
|
5157
5232
|
const feed = typeof fid === 'string' ? this.activeFeeds[fid] : undefined;
|
|
5158
5233
|
switch (event.type) {
|
|
5234
|
+
case 'connection.changed': {
|
|
5235
|
+
const { online } = event;
|
|
5236
|
+
this.state.partialNext({ isWsConnectionHealthy: online });
|
|
5237
|
+
if (online) {
|
|
5238
|
+
this.healthyConnectionChangedEventCount++;
|
|
5239
|
+
// we skip the first event as we could potentially be querying twice
|
|
5240
|
+
if (this.healthyConnectionChangedEventCount > 1) {
|
|
5241
|
+
for (const activeFeed of Object.values(this.activeFeeds)) {
|
|
5242
|
+
activeFeed.synchronize();
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
}
|
|
5246
|
+
break;
|
|
5247
|
+
}
|
|
5159
5248
|
case 'feeds.feed.created': {
|
|
5160
5249
|
if (feed)
|
|
5161
5250
|
break;
|