stream-chat 9.7.0 → 9.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.browser.cjs +200 -8
- package/dist/cjs/index.browser.cjs.map +3 -3
- package/dist/cjs/index.node.cjs +205 -8
- package/dist/cjs/index.node.cjs.map +3 -3
- package/dist/esm/index.js +200 -8
- package/dist/esm/index.js.map +3 -3
- package/dist/types/client.d.ts +17 -1
- package/dist/types/messageComposer/middleware/messageComposer/commandInjection.d.ts +4 -0
- package/dist/types/messageComposer/middleware/messageComposer/index.d.ts +1 -0
- package/dist/types/messageComposer/middleware/textComposer/activeCommandGuard.d.ts +4 -0
- package/dist/types/messageComposer/middleware/textComposer/commandStringExtraction.d.ts +5 -0
- package/dist/types/messageComposer/middleware/textComposer/index.d.ts +2 -0
- package/dist/types/messageComposer/middleware/textComposer/textMiddlewareUtils.d.ts +6 -0
- package/dist/types/messageComposer/middleware/textComposer/types.d.ts +1 -0
- package/dist/types/messageComposer/textComposer.d.ts +6 -3
- package/dist/types/pagination/BasePaginator.d.ts +1 -1
- package/dist/types/pagination/ReminderPaginator.d.ts +6 -2
- package/dist/types/reminders/ReminderManager.d.ts +3 -3
- package/dist/types/types.d.ts +26 -1
- package/package.json +1 -1
- package/src/client.ts +28 -2
- package/src/messageComposer/messageComposer.ts +1 -0
- package/src/messageComposer/middleware/messageComposer/commandInjection.ts +72 -0
- package/src/messageComposer/middleware/messageComposer/index.ts +1 -0
- package/src/messageComposer/middleware/textComposer/activeCommandGuard.ts +20 -0
- package/src/messageComposer/middleware/textComposer/commandStringExtraction.ts +56 -0
- package/src/messageComposer/middleware/textComposer/commands.ts +22 -4
- package/src/messageComposer/middleware/textComposer/index.ts +2 -0
- package/src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts +14 -0
- package/src/messageComposer/middleware/textComposer/types.ts +1 -0
- package/src/messageComposer/textComposer.ts +23 -3
- package/src/pagination/BasePaginator.ts +1 -1
- package/src/pagination/ReminderPaginator.ts +20 -2
- package/src/reminders/ReminderManager.ts +16 -2
- package/src/types.ts +30 -2
|
@@ -239,12 +239,16 @@ __export(index_exports, {
|
|
|
239
239
|
calculateLevenshtein: () => calculateLevenshtein,
|
|
240
240
|
channelManagerEventToHandlerMapping: () => channelManagerEventToHandlerMapping,
|
|
241
241
|
chatCodes: () => chatCodes,
|
|
242
|
+
createActiveCommandGuardMiddleware: () => createActiveCommandGuardMiddleware,
|
|
242
243
|
createAttachmentsCompositionMiddleware: () => createAttachmentsCompositionMiddleware,
|
|
244
|
+
createCommandInjectionMiddleware: () => createCommandInjectionMiddleware,
|
|
245
|
+
createCommandStringExtractionMiddleware: () => createCommandStringExtractionMiddleware,
|
|
243
246
|
createCommandsMiddleware: () => createCommandsMiddleware,
|
|
244
247
|
createCompositionDataCleanupMiddleware: () => createCompositionDataCleanupMiddleware,
|
|
245
248
|
createCompositionValidationMiddleware: () => createCompositionValidationMiddleware,
|
|
246
249
|
createCustomDataCompositionMiddleware: () => createCustomDataCompositionMiddleware,
|
|
247
250
|
createDraftAttachmentsCompositionMiddleware: () => createDraftAttachmentsCompositionMiddleware,
|
|
251
|
+
createDraftCommandInjectionMiddleware: () => createDraftCommandInjectionMiddleware,
|
|
248
252
|
createDraftCompositionValidationMiddleware: () => createDraftCompositionValidationMiddleware,
|
|
249
253
|
createDraftCustomDataCompositionMiddleware: () => createDraftCustomDataCompositionMiddleware,
|
|
250
254
|
createDraftLinkPreviewsCompositionMiddleware: () => createDraftLinkPreviewsCompositionMiddleware,
|
|
@@ -268,6 +272,7 @@ __export(index_exports, {
|
|
|
268
272
|
formatMessage: () => formatMessage,
|
|
269
273
|
generateFileName: () => generateFileName,
|
|
270
274
|
getAttachmentTypeFromMimeType: () => getAttachmentTypeFromMimeType,
|
|
275
|
+
getCompleteCommandInString: () => getCompleteCommandInString,
|
|
271
276
|
getExtensionFromMimeType: () => getExtensionFromMimeType,
|
|
272
277
|
getTokenizedSuggestionDisplayName: () => getTokenizedSuggestionDisplayName,
|
|
273
278
|
getTriggerCharWithToken: () => getTriggerCharWithToken,
|
|
@@ -6309,6 +6314,76 @@ var MessageDraftComposerMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
|
6309
6314
|
}
|
|
6310
6315
|
};
|
|
6311
6316
|
|
|
6317
|
+
// src/messageComposer/middleware/messageComposer/commandInjection.ts
|
|
6318
|
+
var createCommandInjectionMiddleware = (composer) => ({
|
|
6319
|
+
handlers: {
|
|
6320
|
+
compose: ({
|
|
6321
|
+
forward,
|
|
6322
|
+
next,
|
|
6323
|
+
state
|
|
6324
|
+
}) => {
|
|
6325
|
+
const command = composer.textComposer.command;
|
|
6326
|
+
if (!command) {
|
|
6327
|
+
return forward();
|
|
6328
|
+
}
|
|
6329
|
+
const { text } = state.localMessage;
|
|
6330
|
+
const injection = `/${command?.name}`;
|
|
6331
|
+
const enrichedText = `${injection} ${text}`;
|
|
6332
|
+
return next({
|
|
6333
|
+
...state,
|
|
6334
|
+
localMessage: {
|
|
6335
|
+
...state.localMessage,
|
|
6336
|
+
text: enrichedText
|
|
6337
|
+
},
|
|
6338
|
+
message: {
|
|
6339
|
+
...state.message,
|
|
6340
|
+
text: enrichedText
|
|
6341
|
+
}
|
|
6342
|
+
});
|
|
6343
|
+
}
|
|
6344
|
+
},
|
|
6345
|
+
id: "stream-io/message-composer-middleware/command-string-injection"
|
|
6346
|
+
});
|
|
6347
|
+
var createDraftCommandInjectionMiddleware = (composer) => ({
|
|
6348
|
+
handlers: {
|
|
6349
|
+
compose: ({
|
|
6350
|
+
forward,
|
|
6351
|
+
next,
|
|
6352
|
+
state
|
|
6353
|
+
}) => {
|
|
6354
|
+
const command = composer.textComposer.command;
|
|
6355
|
+
if (!command) {
|
|
6356
|
+
return forward();
|
|
6357
|
+
}
|
|
6358
|
+
const { text } = state.draft;
|
|
6359
|
+
const injection = `/${command?.name}`;
|
|
6360
|
+
const enrichedText = `${injection} ${text}`;
|
|
6361
|
+
return next({
|
|
6362
|
+
...state,
|
|
6363
|
+
draft: {
|
|
6364
|
+
...state.draft,
|
|
6365
|
+
text: enrichedText
|
|
6366
|
+
}
|
|
6367
|
+
});
|
|
6368
|
+
}
|
|
6369
|
+
},
|
|
6370
|
+
id: "stream-io/message-composer-middleware/draft-command-string-injection"
|
|
6371
|
+
});
|
|
6372
|
+
|
|
6373
|
+
// src/messageComposer/middleware/textComposer/activeCommandGuard.ts
|
|
6374
|
+
var createActiveCommandGuardMiddleware = () => ({
|
|
6375
|
+
handlers: {
|
|
6376
|
+
onChange: ({ complete, forward, state }) => {
|
|
6377
|
+
if (state.command) {
|
|
6378
|
+
return complete(state);
|
|
6379
|
+
}
|
|
6380
|
+
return forward();
|
|
6381
|
+
},
|
|
6382
|
+
onSuggestionItemSelect: ({ forward }) => forward()
|
|
6383
|
+
},
|
|
6384
|
+
id: "stream-io/text-composer/active-command-guard"
|
|
6385
|
+
});
|
|
6386
|
+
|
|
6312
6387
|
// src/search/BaseSearchSource.ts
|
|
6313
6388
|
var DEFAULT_SEARCH_SOURCE_OPTIONS = {
|
|
6314
6389
|
debounceMs: 300,
|
|
@@ -6712,6 +6787,11 @@ var getTriggerCharWithToken = ({
|
|
|
6712
6787
|
);
|
|
6713
6788
|
return match && match[match.length - 1].trim();
|
|
6714
6789
|
};
|
|
6790
|
+
var getCompleteCommandInString = (text) => {
|
|
6791
|
+
const match = text.match(/^\/(\S+)\s+.*/);
|
|
6792
|
+
const commandName = match && match[1];
|
|
6793
|
+
return commandName;
|
|
6794
|
+
};
|
|
6715
6795
|
var insertItemWithTrigger = ({
|
|
6716
6796
|
insertText,
|
|
6717
6797
|
selection,
|
|
@@ -6828,9 +6908,21 @@ var createCommandsMiddleware = (channel, options) => {
|
|
|
6828
6908
|
handlers: {
|
|
6829
6909
|
onChange: ({ state, next, complete, forward }) => {
|
|
6830
6910
|
if (!state.selection) return forward();
|
|
6911
|
+
const finalText = state.text.slice(0, state.selection.end);
|
|
6912
|
+
const commandName = getCompleteCommandInString(finalText);
|
|
6913
|
+
if (commandName) {
|
|
6914
|
+
const command = searchSource?.query(commandName).items[0];
|
|
6915
|
+
if (command) {
|
|
6916
|
+
return next({
|
|
6917
|
+
...state,
|
|
6918
|
+
command,
|
|
6919
|
+
suggestions: void 0
|
|
6920
|
+
});
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6831
6923
|
const triggerWithToken = getTriggerCharWithToken({
|
|
6832
6924
|
trigger: finalOptions.trigger,
|
|
6833
|
-
text:
|
|
6925
|
+
text: finalText,
|
|
6834
6926
|
acceptTrailingSpaces: false,
|
|
6835
6927
|
isCommand: true
|
|
6836
6928
|
});
|
|
@@ -6849,6 +6941,7 @@ var createCommandsMiddleware = (channel, options) => {
|
|
|
6849
6941
|
}
|
|
6850
6942
|
return complete({
|
|
6851
6943
|
...state,
|
|
6944
|
+
command: null,
|
|
6852
6945
|
suggestions: {
|
|
6853
6946
|
query: triggerWithToken.slice(1),
|
|
6854
6947
|
searchSource,
|
|
@@ -6856,12 +6949,12 @@ var createCommandsMiddleware = (channel, options) => {
|
|
|
6856
6949
|
}
|
|
6857
6950
|
});
|
|
6858
6951
|
},
|
|
6859
|
-
onSuggestionItemSelect: ({ state,
|
|
6952
|
+
onSuggestionItemSelect: ({ state, next, forward }) => {
|
|
6860
6953
|
const { selectedSuggestion } = state.change ?? {};
|
|
6861
6954
|
if (!selectedSuggestion || state.suggestions?.trigger !== finalOptions.trigger)
|
|
6862
6955
|
return forward();
|
|
6863
6956
|
searchSource.resetStateAndActivate();
|
|
6864
|
-
return
|
|
6957
|
+
return next({
|
|
6865
6958
|
...state,
|
|
6866
6959
|
...insertItemWithTrigger({
|
|
6867
6960
|
insertText: `/${selectedSuggestion.name} `,
|
|
@@ -6869,6 +6962,7 @@ var createCommandsMiddleware = (channel, options) => {
|
|
|
6869
6962
|
text: state.text,
|
|
6870
6963
|
trigger: finalOptions.trigger
|
|
6871
6964
|
}),
|
|
6965
|
+
command: selectedSuggestion,
|
|
6872
6966
|
suggestions: void 0
|
|
6873
6967
|
});
|
|
6874
6968
|
}
|
|
@@ -6876,6 +6970,45 @@ var createCommandsMiddleware = (channel, options) => {
|
|
|
6876
6970
|
};
|
|
6877
6971
|
};
|
|
6878
6972
|
|
|
6973
|
+
// src/messageComposer/middleware/textComposer/commandStringExtraction.ts
|
|
6974
|
+
var stripCommandFromText = (text, commandName) => text.replace(new RegExp(`^${escapeRegExp(`/${commandName}`)}\\s*`), "");
|
|
6975
|
+
var createCommandStringExtractionMiddleware = () => ({
|
|
6976
|
+
handlers: {
|
|
6977
|
+
onChange: ({ complete, forward, state }) => {
|
|
6978
|
+
const { command } = state;
|
|
6979
|
+
if (!command?.name) {
|
|
6980
|
+
return forward();
|
|
6981
|
+
}
|
|
6982
|
+
const newText = stripCommandFromText(state.text, command.name);
|
|
6983
|
+
return complete({
|
|
6984
|
+
...state,
|
|
6985
|
+
selection: {
|
|
6986
|
+
end: newText.length,
|
|
6987
|
+
start: newText.length
|
|
6988
|
+
},
|
|
6989
|
+
text: newText
|
|
6990
|
+
});
|
|
6991
|
+
},
|
|
6992
|
+
onSuggestionItemSelect: ({ next, forward, state }) => {
|
|
6993
|
+
const { command } = state;
|
|
6994
|
+
if (!command) {
|
|
6995
|
+
return forward();
|
|
6996
|
+
}
|
|
6997
|
+
const triggerWithCommand = `/${command?.name} `;
|
|
6998
|
+
const newText = state.text.slice(triggerWithCommand.length);
|
|
6999
|
+
return next({
|
|
7000
|
+
...state,
|
|
7001
|
+
selection: {
|
|
7002
|
+
end: newText.length,
|
|
7003
|
+
start: newText.length
|
|
7004
|
+
},
|
|
7005
|
+
text: newText
|
|
7006
|
+
});
|
|
7007
|
+
}
|
|
7008
|
+
},
|
|
7009
|
+
id: "stream-io/text-composer/command-string-extraction"
|
|
7010
|
+
});
|
|
7011
|
+
|
|
6879
7012
|
// src/messageComposer/middleware/textComposer/mentions.ts
|
|
6880
7013
|
var accentsMap = {
|
|
6881
7014
|
a: "\xE1|\xE0|\xE3|\xE2|\xC0|\xC1|\xC3|\xC2",
|
|
@@ -7208,6 +7341,7 @@ var initState4 = ({
|
|
|
7208
7341
|
if (!message) {
|
|
7209
7342
|
const text2 = composer.config.text.defaultValue ?? "";
|
|
7210
7343
|
return {
|
|
7344
|
+
command: null,
|
|
7211
7345
|
mentionedUsers: [],
|
|
7212
7346
|
text: text2,
|
|
7213
7347
|
selection: { start: text2.length, end: text2.length }
|
|
@@ -7246,6 +7380,10 @@ var TextComposer = class {
|
|
|
7246
7380
|
mentionedUsers.splice(existingUserIndex, 1);
|
|
7247
7381
|
this.state.partialNext({ mentionedUsers });
|
|
7248
7382
|
};
|
|
7383
|
+
this.setCommand = (command) => {
|
|
7384
|
+
if (command?.name === this.command?.name) return;
|
|
7385
|
+
this.state.partialNext({ command });
|
|
7386
|
+
};
|
|
7249
7387
|
this.setText = (text) => {
|
|
7250
7388
|
if (!this.enabled || text === this.text) return;
|
|
7251
7389
|
this.state.partialNext({ text });
|
|
@@ -7255,7 +7393,10 @@ var TextComposer = class {
|
|
|
7255
7393
|
if (!this.enabled || !selectionChanged) return;
|
|
7256
7394
|
this.state.partialNext({ selection });
|
|
7257
7395
|
};
|
|
7258
|
-
this.insertText = ({
|
|
7396
|
+
this.insertText = async ({
|
|
7397
|
+
text,
|
|
7398
|
+
selection
|
|
7399
|
+
}) => {
|
|
7259
7400
|
if (!this.enabled) return;
|
|
7260
7401
|
const finalSelection = selection ?? this.selection;
|
|
7261
7402
|
const { maxLengthOnEdit } = this.composer.config.text ?? {};
|
|
@@ -7271,7 +7412,7 @@ var TextComposer = class {
|
|
|
7271
7412
|
);
|
|
7272
7413
|
const expectedCursorPosition = currentText.slice(0, finalSelection.start).length + text.length;
|
|
7273
7414
|
const cursorPosition = expectedCursorPosition >= finalText.length ? finalText.length : currentText.slice(0, expectedCursorPosition).length;
|
|
7274
|
-
this.
|
|
7415
|
+
await this.handleChange({
|
|
7275
7416
|
text: finalText,
|
|
7276
7417
|
selection: {
|
|
7277
7418
|
start: cursorPosition,
|
|
@@ -7391,6 +7532,9 @@ var TextComposer = class {
|
|
|
7391
7532
|
this.composer.updateConfig({ text: { publishTypingEvents } });
|
|
7392
7533
|
}
|
|
7393
7534
|
// --- START STATE API ---
|
|
7535
|
+
get command() {
|
|
7536
|
+
return this.state.getLatestValue().command;
|
|
7537
|
+
}
|
|
7394
7538
|
get mentionedUsers() {
|
|
7395
7539
|
return this.state.getLatestValue().mentionedUsers;
|
|
7396
7540
|
}
|
|
@@ -7409,6 +7553,9 @@ var TextComposer = class {
|
|
|
7409
7553
|
setMentionedUsers(users) {
|
|
7410
7554
|
this.state.partialNext({ mentionedUsers: users });
|
|
7411
7555
|
}
|
|
7556
|
+
clearCommand() {
|
|
7557
|
+
this.state.partialNext({ command: null });
|
|
7558
|
+
}
|
|
7412
7559
|
// --- END TEXT PROCESSING ----
|
|
7413
7560
|
};
|
|
7414
7561
|
|
|
@@ -8160,6 +8307,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8160
8307
|
this.state.partialNext({ showReplyInChannel: !this.showReplyInChannel });
|
|
8161
8308
|
};
|
|
8162
8309
|
this.clear = () => {
|
|
8310
|
+
this.setQuotedMessage(null);
|
|
8163
8311
|
this.initState();
|
|
8164
8312
|
};
|
|
8165
8313
|
this.restore = () => {
|
|
@@ -12969,6 +13117,20 @@ var ReminderPaginator = class extends BasePaginator {
|
|
|
12969
13117
|
this.filterQueryResults = (items) => items;
|
|
12970
13118
|
this.client = client;
|
|
12971
13119
|
}
|
|
13120
|
+
get filters() {
|
|
13121
|
+
return this._filters;
|
|
13122
|
+
}
|
|
13123
|
+
get sort() {
|
|
13124
|
+
return this._sort;
|
|
13125
|
+
}
|
|
13126
|
+
set filters(filters) {
|
|
13127
|
+
this._filters = filters;
|
|
13128
|
+
this.resetState();
|
|
13129
|
+
}
|
|
13130
|
+
set sort(sort) {
|
|
13131
|
+
this._sort = sort;
|
|
13132
|
+
this.resetState();
|
|
13133
|
+
}
|
|
12972
13134
|
};
|
|
12973
13135
|
|
|
12974
13136
|
// src/reminders/ReminderManager.ts
|
|
@@ -12983,7 +13145,8 @@ var DEFAULT_REMINDER_MANAGER_CONFIG = {
|
|
|
12983
13145
|
2 * oneHour2,
|
|
12984
13146
|
8 * oneHour2,
|
|
12985
13147
|
oneDay2
|
|
12986
|
-
]
|
|
13148
|
+
],
|
|
13149
|
+
stopTimerRefreshBoundaryMs: DEFAULT_STOP_REFRESH_BOUNDARY_MS
|
|
12987
13150
|
};
|
|
12988
13151
|
var isReminderExistsError = (error) => error.message.match("already has reminder created for this message_id");
|
|
12989
13152
|
var isReminderDoesNotExistError = (error) => error.message.match("reminder does not exist");
|
|
@@ -13134,13 +13297,19 @@ var _ReminderManager = class _ReminderManager extends WithSubscriptions {
|
|
|
13134
13297
|
};
|
|
13135
13298
|
this.client = client;
|
|
13136
13299
|
this.configState = new StateStore({
|
|
13137
|
-
scheduledOffsetsMs: config?.scheduledOffsetsMs ?? DEFAULT_REMINDER_MANAGER_CONFIG.scheduledOffsetsMs
|
|
13300
|
+
scheduledOffsetsMs: config?.scheduledOffsetsMs ?? DEFAULT_REMINDER_MANAGER_CONFIG.scheduledOffsetsMs,
|
|
13301
|
+
stopTimerRefreshBoundaryMs: config?.stopTimerRefreshBoundaryMs ?? DEFAULT_REMINDER_MANAGER_CONFIG.stopTimerRefreshBoundaryMs
|
|
13138
13302
|
});
|
|
13139
13303
|
this.state = new StateStore({ reminders: /* @__PURE__ */ new Map() });
|
|
13140
13304
|
this.paginator = new ReminderPaginator(client);
|
|
13141
13305
|
}
|
|
13142
13306
|
// Config API START //
|
|
13143
13307
|
updateConfig(config) {
|
|
13308
|
+
if (typeof config.stopTimerRefreshBoundaryMs === "number" && config.stopTimerRefreshBoundaryMs !== this.stopTimerRefreshBoundaryMs) {
|
|
13309
|
+
this.reminders.forEach((reminder) => {
|
|
13310
|
+
reminder.timer.stopRefreshBoundaryMs = config?.stopTimerRefreshBoundaryMs;
|
|
13311
|
+
});
|
|
13312
|
+
}
|
|
13144
13313
|
this.configState.partialNext(config);
|
|
13145
13314
|
}
|
|
13146
13315
|
get stopTimerRefreshBoundaryMs() {
|
|
@@ -14828,6 +14997,16 @@ var StreamChat = class _StreamChat {
|
|
|
14828
14997
|
...userID ? { user_id: userID } : {}
|
|
14829
14998
|
});
|
|
14830
14999
|
}
|
|
15000
|
+
/** getSharedLocations
|
|
15001
|
+
*
|
|
15002
|
+
* @returns {Promise<ActiveLiveLocationsAPIResponse>} The server response
|
|
15003
|
+
*
|
|
15004
|
+
*/
|
|
15005
|
+
async getSharedLocations() {
|
|
15006
|
+
return await this.get(
|
|
15007
|
+
this.baseURL + `/users/live_locations`
|
|
15008
|
+
);
|
|
15009
|
+
}
|
|
14831
15010
|
/** muteUser - mutes a user
|
|
14832
15011
|
*
|
|
14833
15012
|
* @param {string} targetID
|
|
@@ -15382,7 +15561,7 @@ var StreamChat = class _StreamChat {
|
|
|
15382
15561
|
if (this.userAgent) {
|
|
15383
15562
|
return this.userAgent;
|
|
15384
15563
|
}
|
|
15385
|
-
const version = "9.
|
|
15564
|
+
const version = "9.9.0";
|
|
15386
15565
|
const clientBundle = "browser-cjs";
|
|
15387
15566
|
let userAgentString = "";
|
|
15388
15567
|
if (this.sdkIdentifier) {
|
|
@@ -16471,6 +16650,19 @@ var StreamChat = class _StreamChat {
|
|
|
16471
16650
|
...rest
|
|
16472
16651
|
});
|
|
16473
16652
|
}
|
|
16653
|
+
/**
|
|
16654
|
+
* updateLocation - Updates a location
|
|
16655
|
+
*
|
|
16656
|
+
* @param location UserLocation the location data to update
|
|
16657
|
+
*
|
|
16658
|
+
* @returns {Promise<APIResponse>} The server response
|
|
16659
|
+
*/
|
|
16660
|
+
async updateLocation(location) {
|
|
16661
|
+
return await this.put(
|
|
16662
|
+
this.baseURL + `/users/live_locations`,
|
|
16663
|
+
location
|
|
16664
|
+
);
|
|
16665
|
+
}
|
|
16474
16666
|
/**
|
|
16475
16667
|
* uploadFile - Uploads a file to the configured storage (defaults to Stream CDN)
|
|
16476
16668
|
*
|