stream-chat 9.40.0 → 9.41.1

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.
@@ -1034,6 +1034,7 @@ var messagePaginationCreatedAtAround = ({
1034
1034
  parentSet,
1035
1035
  requestedPageSize,
1036
1036
  returnedPage,
1037
+ filteredReturnedPage,
1037
1038
  messagePaginationOptions
1038
1039
  }) => {
1039
1040
  const newPagination = { ...parentSet.pagination };
@@ -1066,9 +1067,13 @@ var messagePaginationCreatedAtAround = ({
1066
1067
  hasNext = hasPrev = false;
1067
1068
  updateHasPrev = updateHasNext = true;
1068
1069
  } else {
1070
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
1071
+ filteredReturnedPage[0],
1072
+ filteredReturnedPage.slice(-1)[0]
1073
+ ];
1069
1074
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
1070
- firstPageMsg?.id && firstPageMsg.id === parentSet.messages[0]?.id,
1071
- lastPageMsg?.id && lastPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1075
+ firstFilteredPageMsg?.id && firstFilteredPageMsg.id === parentSet.messages[0]?.id,
1076
+ lastFilteredPageMsg?.id && lastFilteredPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1072
1077
  ];
1073
1078
  updateHasPrev = firstPageMsgIsFirstInSet;
1074
1079
  updateHasNext = lastPageMsgIsLastInSet;
@@ -1090,6 +1095,7 @@ var messagePaginationIdAround = ({
1090
1095
  parentSet,
1091
1096
  requestedPageSize,
1092
1097
  returnedPage,
1098
+ filteredReturnedPage,
1093
1099
  messagePaginationOptions
1094
1100
  }) => {
1095
1101
  const newPagination = { ...parentSet.pagination };
@@ -1097,10 +1103,13 @@ var messagePaginationIdAround = ({
1097
1103
  if (!id_around) return newPagination;
1098
1104
  let hasPrev;
1099
1105
  let hasNext;
1100
- const [firstPageMsg, lastPageMsg] = [returnedPage[0], returnedPage.slice(-1)[0]];
1106
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
1107
+ filteredReturnedPage[0],
1108
+ filteredReturnedPage.slice(-1)[0]
1109
+ ];
1101
1110
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
1102
- firstPageMsg?.id === parentSet.messages[0]?.id,
1103
- lastPageMsg?.id === parentSet.messages.slice(-1)[0]?.id
1111
+ firstFilteredPageMsg?.id === parentSet.messages[0]?.id,
1112
+ lastFilteredPageMsg?.id === parentSet.messages.slice(-1)[0]?.id
1104
1113
  ];
1105
1114
  let updateHasPrev = firstPageMsgIsFirstInSet;
1106
1115
  let updateHasNext = lastPageMsgIsLastInSet;
@@ -1135,15 +1144,19 @@ var messagePaginationLinear = ({
1135
1144
  parentSet,
1136
1145
  requestedPageSize,
1137
1146
  returnedPage,
1147
+ filteredReturnedPage,
1138
1148
  messagePaginationOptions
1139
1149
  }) => {
1140
1150
  const newPagination = { ...parentSet.pagination };
1141
1151
  let hasPrev;
1142
1152
  let hasNext;
1143
- const [firstPageMsg, lastPageMsg] = [returnedPage[0], returnedPage.slice(-1)[0]];
1153
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
1154
+ filteredReturnedPage[0],
1155
+ filteredReturnedPage.slice(-1)[0]
1156
+ ];
1144
1157
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
1145
- firstPageMsg?.id && firstPageMsg.id === parentSet.messages[0]?.id,
1146
- lastPageMsg?.id && lastPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1158
+ firstFilteredPageMsg?.id && firstFilteredPageMsg.id === parentSet.messages[0]?.id,
1159
+ lastFilteredPageMsg?.id && lastFilteredPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1147
1160
  ];
1148
1161
  const queriedNextMessages = messagePaginationOptions && (messagePaginationOptions.created_at_after_or_equal || messagePaginationOptions.created_at_after || messagePaginationOptions.id_gt || messagePaginationOptions.id_gte);
1149
1162
  const queriedPrevMessages = typeof messagePaginationOptions === "undefined" ? true : messagePaginationOptions.created_at_before_or_equal || messagePaginationOptions.created_at_before || messagePaginationOptions.id_lt || messagePaginationOptions.id_lte || messagePaginationOptions.offset;
@@ -1163,8 +1176,7 @@ var messagePaginationLinear = ({
1163
1176
  return newPagination;
1164
1177
  };
1165
1178
  var messageSetPagination = (params) => {
1166
- const messagesFilteredLocally = params.returnedPage.filter(({ shadowed }) => shadowed);
1167
- if (params.parentSet.messages.length + messagesFilteredLocally.length < params.returnedPage.length) {
1179
+ if (params.parentSet.messages.length + (params.returnedPage.length - params.filteredReturnedPage.length) < params.returnedPage.length) {
1168
1180
  params.logger?.(
1169
1181
  "error",
1170
1182
  "Corrupted message set state: parent set size < returned page size"
@@ -1511,9 +1523,11 @@ var ChannelState = class {
1511
1523
  addIfDoesNotExist,
1512
1524
  messageSetToAddToIfDoesNotExist
1513
1525
  );
1526
+ const filteredMessageIds = [];
1514
1527
  for (let i = 0; i < messagesToAdd.length; i += 1) {
1515
1528
  const isFromShadowBannedUser = messagesToAdd[i].shadowed;
1516
- if (isFromShadowBannedUser) {
1529
+ if (isFromShadowBannedUser && addIfDoesNotExist) {
1530
+ filteredMessageIds.push(messagesToAdd[i].id);
1517
1531
  continue;
1518
1532
  }
1519
1533
  const isMessageFormatted = messagesToAdd[i].created_at instanceof Date;
@@ -1555,7 +1569,8 @@ var ChannelState = class {
1555
1569
  }
1556
1570
  }
1557
1571
  return {
1558
- messageSet: this.messageSets[targetMessageSetIndex]
1572
+ messageSet: this.messageSets[targetMessageSetIndex],
1573
+ filteredMessageIds
1559
1574
  };
1560
1575
  }
1561
1576
  /**
@@ -3402,12 +3417,18 @@ var _AttachmentManager = class _AttachmentManager {
3402
3417
  * Method to perform the default upload behavior without checking for custom upload functions
3403
3418
  * to prevent recursive calls
3404
3419
  */
3405
- this.doDefaultUploadRequest = async (fileLike) => {
3420
+ this.doDefaultUploadRequest = async (fileLike, options) => {
3421
+ const progressHandler = options?.onProgress ? (progressEvent) => {
3422
+ const percent = progressEvent.lengthComputable && progressEvent.total ? Math.round(progressEvent.loaded * 100 / progressEvent.total) : void 0;
3423
+ options.onProgress?.(percent);
3424
+ } : void 0;
3406
3425
  if (isFileReference(fileLike)) {
3407
3426
  return this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
3408
3427
  fileLike.uri,
3409
3428
  fileLike.name,
3410
- fileLike.type
3429
+ fileLike.type,
3430
+ void 0,
3431
+ progressHandler ? { onUploadProgress: progressHandler } : void 0
3411
3432
  );
3412
3433
  }
3413
3434
  const file = isFile(fileLike) ? fileLike : createFileFromBlobs({
@@ -3415,18 +3436,24 @@ var _AttachmentManager = class _AttachmentManager {
3415
3436
  fileName: generateFileName(fileLike.type),
3416
3437
  mimeType: fileLike.type
3417
3438
  });
3418
- const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](file);
3439
+ const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
3440
+ file,
3441
+ void 0,
3442
+ void 0,
3443
+ void 0,
3444
+ progressHandler ? { onUploadProgress: progressHandler } : void 0
3445
+ );
3419
3446
  return result;
3420
3447
  };
3421
3448
  /**
3422
3449
  * todo: docs how to customize the image and file upload by overriding do
3423
3450
  */
3424
- this.doUploadRequest = async (fileLike) => {
3451
+ this.doUploadRequest = async (fileLike, options) => {
3425
3452
  const customUploadFn = this.config.doUploadRequest;
3426
3453
  if (customUploadFn) {
3427
- return await customUploadFn(fileLike);
3454
+ return await customUploadFn(fileLike, options);
3428
3455
  }
3429
- return this.doDefaultUploadRequest(fileLike);
3456
+ return this.doDefaultUploadRequest(fileLike, options);
3430
3457
  };
3431
3458
  // @deprecated use attachmentManager.uploadFile(file)
3432
3459
  this.uploadAttachment = async (attachment) => {
@@ -3450,25 +3477,41 @@ var _AttachmentManager = class _AttachmentManager {
3450
3477
  });
3451
3478
  return localAttachment;
3452
3479
  }
3453
- this.upsertAttachments([
3454
- {
3455
- ...attachment,
3456
- localMetadata: {
3457
- ...attachment.localMetadata,
3458
- uploadState: "uploading"
3459
- }
3480
+ const shouldTrackProgress = this.config.trackUploadProgress;
3481
+ const uploadingAttachment = {
3482
+ ...attachment,
3483
+ localMetadata: {
3484
+ ...attachment.localMetadata,
3485
+ uploadState: "uploading",
3486
+ ...shouldTrackProgress && { uploadProgress: 0 }
3460
3487
  }
3461
- ]);
3488
+ };
3489
+ this.upsertAttachments([uploadingAttachment]);
3490
+ const uploadOptions = shouldTrackProgress ? {
3491
+ onProgress: (percent) => {
3492
+ this.updateAttachment({
3493
+ ...uploadingAttachment,
3494
+ localMetadata: {
3495
+ ...uploadingAttachment.localMetadata,
3496
+ uploadProgress: percent
3497
+ }
3498
+ });
3499
+ }
3500
+ } : void 0;
3462
3501
  let response;
3463
3502
  try {
3464
- response = await this.doUploadRequest(localAttachment.localMetadata.file);
3503
+ response = await this.doUploadRequest(
3504
+ localAttachment.localMetadata.file,
3505
+ uploadOptions
3506
+ );
3465
3507
  } catch (error) {
3466
3508
  const reason = error instanceof Error ? error.message : "unknown error";
3467
3509
  const failedAttachment = {
3468
3510
  ...attachment,
3469
3511
  localMetadata: {
3470
3512
  ...attachment.localMetadata,
3471
- uploadState: "failed"
3513
+ uploadState: "failed",
3514
+ uploadProgress: void 0
3472
3515
  }
3473
3516
  };
3474
3517
  this.client.notifications.addError({
@@ -3494,7 +3537,8 @@ var _AttachmentManager = class _AttachmentManager {
3494
3537
  ...attachment,
3495
3538
  localMetadata: {
3496
3539
  ...attachment.localMetadata,
3497
- uploadState: "finished"
3540
+ uploadState: "finished",
3541
+ uploadProgress: void 0
3498
3542
  }
3499
3543
  };
3500
3544
  const previewUri = uploadedAttachment.localMetadata.previewUri;
@@ -3528,18 +3572,31 @@ var _AttachmentManager = class _AttachmentManager {
3528
3572
  this.upsertAttachments([attachment]);
3529
3573
  return preUpload.state.attachment;
3530
3574
  }
3575
+ const shouldTrackProgress = this.config.trackUploadProgress;
3531
3576
  attachment = {
3532
3577
  ...attachment,
3533
3578
  localMetadata: {
3534
3579
  ...attachment.localMetadata,
3535
- uploadState: "uploading"
3580
+ uploadState: "uploading",
3581
+ ...shouldTrackProgress && { uploadProgress: 0 }
3536
3582
  }
3537
3583
  };
3538
3584
  this.upsertAttachments([attachment]);
3585
+ const uploadOptions = shouldTrackProgress ? {
3586
+ onProgress: (percent) => {
3587
+ this.updateAttachment({
3588
+ ...attachment,
3589
+ localMetadata: {
3590
+ ...attachment.localMetadata,
3591
+ uploadProgress: percent
3592
+ }
3593
+ });
3594
+ }
3595
+ } : void 0;
3539
3596
  let response;
3540
3597
  let error;
3541
3598
  try {
3542
- response = await this.doUploadRequest(file);
3599
+ response = await this.doUploadRequest(file, uploadOptions);
3543
3600
  } catch (err) {
3544
3601
  error = err instanceof Error ? err : void 0;
3545
3602
  }
@@ -3550,7 +3607,8 @@ var _AttachmentManager = class _AttachmentManager {
3550
3607
  ...attachment,
3551
3608
  localMetadata: {
3552
3609
  ...attachment.localMetadata,
3553
- uploadState: error ? "failed" : "finished"
3610
+ uploadState: error ? "failed" : "finished",
3611
+ uploadProgress: void 0
3554
3612
  }
3555
3613
  },
3556
3614
  error,
@@ -3718,7 +3776,8 @@ var DEFAULT_ATTACHMENT_MANAGER_CONFIG = {
3718
3776
  acceptedFiles: [],
3719
3777
  // an empty array means all files are accepted
3720
3778
  fileUploadFilter: () => true,
3721
- maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE
3779
+ maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE,
3780
+ trackUploadProgress: true
3722
3781
  };
3723
3782
  var DEFAULT_TEXT_COMPOSER_CONFIG = {
3724
3783
  enabled: true,
@@ -8177,22 +8236,44 @@ var Channel = class {
8177
8236
  }
8178
8237
  return await this._sendMessage(message, options);
8179
8238
  }
8180
- sendFile(uri, name, contentType, user) {
8239
+ /**
8240
+ * Upload a file to this channel’s file endpoint (multipart). Forwards to the client’s `sendFile` implementation.
8241
+ *
8242
+ * @param uri File source: URL string, `File`, `Buffer`, or readable stream (Node).
8243
+ * @param name File name sent in the multipart body.
8244
+ * @param contentType MIME type; defaults are applied when omitted.
8245
+ * @param user Optional user payload appended to the form as JSON.
8246
+ * @param axiosRequestConfig Optional Axios per-request config, merged after upload defaults (e.g. `onUploadProgress`, `signal` from `AbortController`).
8247
+ * @return Promise resolving to `{ file: string, ... }` with the CDN URL.
8248
+ */
8249
+ sendFile(uri, name, contentType, user, axiosRequestConfig) {
8181
8250
  return this.getClient().sendFile(
8182
8251
  `${this._channelURL()}/file`,
8183
8252
  uri,
8184
8253
  name,
8185
8254
  contentType,
8186
- user
8255
+ user,
8256
+ axiosRequestConfig
8187
8257
  );
8188
8258
  }
8189
- sendImage(uri, name, contentType, user) {
8259
+ /**
8260
+ * Upload an image to this channel’s image endpoint (multipart). Uses the same transport as `sendFile`.
8261
+ *
8262
+ * @param uri Image source: URL string, `File`, or readable stream (Node). For `Buffer` uploads, use `sendFile` toward the channel file endpoint instead.
8263
+ * @param name File name sent in the multipart body.
8264
+ * @param contentType MIME type.
8265
+ * @param user Optional user payload appended to the form as JSON.
8266
+ * @param axiosRequestConfig Optional Axios per-request config, merged after upload defaults (e.g. `onUploadProgress`, `signal`).
8267
+ * @return Promise resolving to `{ file: string, ... }` with the CDN URL.
8268
+ */
8269
+ sendImage(uri, name, contentType, user, axiosRequestConfig) {
8190
8270
  return this.getClient().sendFile(
8191
8271
  `${this._channelURL()}/image`,
8192
8272
  uri,
8193
8273
  name,
8194
8274
  contentType,
8195
- user
8275
+ user,
8276
+ axiosRequestConfig
8196
8277
  );
8197
8278
  }
8198
8279
  deleteFile(url) {
@@ -9225,7 +9306,10 @@ var Channel = class {
9225
9306
  location: { enabled: state.channel.config.shared_locations }
9226
9307
  });
9227
9308
  }
9228
- const { messageSet } = this._initializeState(state, messageSetToAddToIfDoesNotExist);
9309
+ const { messageSet, filteredMessageIds } = this._initializeState(
9310
+ state,
9311
+ messageSetToAddToIfDoesNotExist
9312
+ );
9229
9313
  messageSet.pagination = {
9230
9314
  ...messageSet.pagination,
9231
9315
  ...messageSetPagination({
@@ -9233,6 +9317,9 @@ var Channel = class {
9233
9317
  messagePaginationOptions: options?.messages,
9234
9318
  requestedPageSize: options?.messages?.limit ?? DEFAULT_QUERY_CHANNEL_MESSAGE_LIST_PAGE_SIZE,
9235
9319
  returnedPage: state.messages,
9320
+ filteredReturnedPage: state.messages.filter(
9321
+ (m) => !filteredMessageIds.includes(m.id)
9322
+ ),
9236
9323
  logger: this.getClient().logger
9237
9324
  })
9238
9325
  };
@@ -9852,7 +9939,7 @@ var Channel = class {
9852
9939
  if (!this.state.messages) {
9853
9940
  this.state.initMessages();
9854
9941
  }
9855
- const { messageSet } = this.state.addMessagesSorted(
9942
+ const { messageSet, filteredMessageIds } = this.state.addMessagesSorted(
9856
9943
  messages,
9857
9944
  false,
9858
9945
  true,
@@ -9904,7 +9991,8 @@ var Channel = class {
9904
9991
  this.messageReceiptsTracker.ingestInitial(state.read);
9905
9992
  }
9906
9993
  return {
9907
- messageSet
9994
+ messageSet,
9995
+ filteredMessageIds
9908
9996
  };
9909
9997
  }
9910
9998
  _extendEventWithOwnReactions(event) {
@@ -13733,7 +13821,7 @@ var StreamChat = class _StreamChat {
13733
13821
  delete(url, params) {
13734
13822
  return this.doAxiosRequest("delete", url, null, { params });
13735
13823
  }
13736
- sendFile(url, uri, name, contentType, user) {
13824
+ sendFile(url, uri, name, contentType, user, axiosRequestConfig) {
13737
13825
  const data = addFileToFormData(uri, name, contentType || "multipart/form-data");
13738
13826
  if (user != null) data.append("user", JSON.stringify(user));
13739
13827
  return this.doAxiosRequest("postForm", url, data, {
@@ -13742,7 +13830,8 @@ var StreamChat = class _StreamChat {
13742
13830
  config: {
13743
13831
  timeout: 0,
13744
13832
  maxContentLength: Infinity,
13745
- maxBodyLength: Infinity
13833
+ maxBodyLength: Infinity,
13834
+ ...axiosRequestConfig
13746
13835
  }
13747
13836
  });
13748
13837
  }
@@ -14106,12 +14195,15 @@ var StreamChat = class _StreamChat {
14106
14195
  c.initialized = !offlineMode;
14107
14196
  c.push_preferences = channelState.push_preferences;
14108
14197
  let updatedMessagesSet;
14198
+ let filteredMessageIds = [];
14109
14199
  if (skipInitialization === void 0) {
14110
- const { messageSet } = c._initializeState(channelState, "latest");
14200
+ const { messageSet, filteredMessageIds: _filteredMessageIds } = c._initializeState(channelState, "latest");
14201
+ filteredMessageIds = _filteredMessageIds;
14111
14202
  updatedMessagesSet = messageSet;
14112
14203
  } else if (!skipInitialization.includes(channelState.channel.id)) {
14113
14204
  c.state.clearMessages();
14114
- const { messageSet } = c._initializeState(channelState, "latest");
14205
+ const { messageSet, filteredMessageIds: _filteredMessageIds } = c._initializeState(channelState, "latest");
14206
+ filteredMessageIds = _filteredMessageIds;
14115
14207
  updatedMessagesSet = messageSet;
14116
14208
  }
14117
14209
  if (updatedMessagesSet) {
@@ -14121,6 +14213,9 @@ var StreamChat = class _StreamChat {
14121
14213
  parentSet: updatedMessagesSet,
14122
14214
  requestedPageSize: queryChannelsOptions?.message_limit || DEFAULT_QUERY_CHANNELS_MESSAGE_LIST_PAGE_SIZE,
14123
14215
  returnedPage: channelState.messages,
14216
+ filteredReturnedPage: channelState.messages.filter(
14217
+ (m) => !filteredMessageIds.includes(m.id)
14218
+ ),
14124
14219
  logger: this.logger
14125
14220
  })
14126
14221
  };
@@ -15171,7 +15266,7 @@ var StreamChat = class _StreamChat {
15171
15266
  if (this.userAgent) {
15172
15267
  return this.userAgent;
15173
15268
  }
15174
- const version = "9.40.0";
15269
+ const version = "9.41.1";
15175
15270
  const clientBundle = "browser-cjs";
15176
15271
  let userAgentString = "";
15177
15272
  if (this.sdkIdentifier) {
@@ -16309,11 +16404,19 @@ var StreamChat = class _StreamChat {
16309
16404
  * @param {string} [name] The name of the file
16310
16405
  * @param {string} [contentType] The content type of the file
16311
16406
  * @param {UserResponse} [user] Optional user information
16407
+ * @param {AxiosRequestConfig} [axiosRequestConfig] Optional axios config (e.g. onUploadProgress for progress tracking)
16312
16408
  *
16313
16409
  * @return {Promise<SendFileAPIResponse>} Response containing the file URL
16314
16410
  */
16315
- uploadFile(uri, name, contentType, user) {
16316
- return this.sendFile(`${this.baseURL}/uploads/file`, uri, name, contentType, user);
16411
+ uploadFile(uri, name, contentType, user, axiosRequestConfig) {
16412
+ return this.sendFile(
16413
+ `${this.baseURL}/uploads/file`,
16414
+ uri,
16415
+ name,
16416
+ contentType,
16417
+ user,
16418
+ axiosRequestConfig
16419
+ );
16317
16420
  }
16318
16421
  /**
16319
16422
  * uploadImage - Uploads an image to the configured storage (defaults to Stream CDN)
@@ -16322,11 +16425,19 @@ var StreamChat = class _StreamChat {
16322
16425
  * @param {string} [name] The name of the image
16323
16426
  * @param {string} [contentType] The content type of the image
16324
16427
  * @param {UserResponse} [user] Optional user information
16428
+ * @param {AxiosRequestConfig} [axiosRequestConfig] Optional axios config (e.g. onUploadProgress for progress tracking)
16325
16429
  *
16326
16430
  * @return {Promise<SendFileAPIResponse>} Response containing the image URL
16327
16431
  */
16328
- uploadImage(uri, name, contentType, user) {
16329
- return this.sendFile(`${this.baseURL}/uploads/image`, uri, name, contentType, user);
16432
+ uploadImage(uri, name, contentType, user, axiosRequestConfig) {
16433
+ return this.sendFile(
16434
+ `${this.baseURL}/uploads/image`,
16435
+ uri,
16436
+ name,
16437
+ contentType,
16438
+ user,
16439
+ axiosRequestConfig
16440
+ );
16330
16441
  }
16331
16442
  /**
16332
16443
  * deleteFile - Deletes a file from the configured storage