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.
@@ -1013,6 +1013,7 @@ var messagePaginationCreatedAtAround = ({
1013
1013
  parentSet,
1014
1014
  requestedPageSize,
1015
1015
  returnedPage,
1016
+ filteredReturnedPage,
1016
1017
  messagePaginationOptions
1017
1018
  }) => {
1018
1019
  const newPagination = { ...parentSet.pagination };
@@ -1045,9 +1046,13 @@ var messagePaginationCreatedAtAround = ({
1045
1046
  hasNext = hasPrev = false;
1046
1047
  updateHasPrev = updateHasNext = true;
1047
1048
  } else {
1049
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
1050
+ filteredReturnedPage[0],
1051
+ filteredReturnedPage.slice(-1)[0]
1052
+ ];
1048
1053
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
1049
- firstPageMsg?.id && firstPageMsg.id === parentSet.messages[0]?.id,
1050
- lastPageMsg?.id && lastPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1054
+ firstFilteredPageMsg?.id && firstFilteredPageMsg.id === parentSet.messages[0]?.id,
1055
+ lastFilteredPageMsg?.id && lastFilteredPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1051
1056
  ];
1052
1057
  updateHasPrev = firstPageMsgIsFirstInSet;
1053
1058
  updateHasNext = lastPageMsgIsLastInSet;
@@ -1069,6 +1074,7 @@ var messagePaginationIdAround = ({
1069
1074
  parentSet,
1070
1075
  requestedPageSize,
1071
1076
  returnedPage,
1077
+ filteredReturnedPage,
1072
1078
  messagePaginationOptions
1073
1079
  }) => {
1074
1080
  const newPagination = { ...parentSet.pagination };
@@ -1076,10 +1082,13 @@ var messagePaginationIdAround = ({
1076
1082
  if (!id_around) return newPagination;
1077
1083
  let hasPrev;
1078
1084
  let hasNext;
1079
- const [firstPageMsg, lastPageMsg] = [returnedPage[0], returnedPage.slice(-1)[0]];
1085
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
1086
+ filteredReturnedPage[0],
1087
+ filteredReturnedPage.slice(-1)[0]
1088
+ ];
1080
1089
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
1081
- firstPageMsg?.id === parentSet.messages[0]?.id,
1082
- lastPageMsg?.id === parentSet.messages.slice(-1)[0]?.id
1090
+ firstFilteredPageMsg?.id === parentSet.messages[0]?.id,
1091
+ lastFilteredPageMsg?.id === parentSet.messages.slice(-1)[0]?.id
1083
1092
  ];
1084
1093
  let updateHasPrev = firstPageMsgIsFirstInSet;
1085
1094
  let updateHasNext = lastPageMsgIsLastInSet;
@@ -1114,15 +1123,19 @@ var messagePaginationLinear = ({
1114
1123
  parentSet,
1115
1124
  requestedPageSize,
1116
1125
  returnedPage,
1126
+ filteredReturnedPage,
1117
1127
  messagePaginationOptions
1118
1128
  }) => {
1119
1129
  const newPagination = { ...parentSet.pagination };
1120
1130
  let hasPrev;
1121
1131
  let hasNext;
1122
- const [firstPageMsg, lastPageMsg] = [returnedPage[0], returnedPage.slice(-1)[0]];
1132
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
1133
+ filteredReturnedPage[0],
1134
+ filteredReturnedPage.slice(-1)[0]
1135
+ ];
1123
1136
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
1124
- firstPageMsg?.id && firstPageMsg.id === parentSet.messages[0]?.id,
1125
- lastPageMsg?.id && lastPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1137
+ firstFilteredPageMsg?.id && firstFilteredPageMsg.id === parentSet.messages[0]?.id,
1138
+ lastFilteredPageMsg?.id && lastFilteredPageMsg.id === parentSet.messages.slice(-1)[0]?.id
1126
1139
  ];
1127
1140
  const queriedNextMessages = messagePaginationOptions && (messagePaginationOptions.created_at_after_or_equal || messagePaginationOptions.created_at_after || messagePaginationOptions.id_gt || messagePaginationOptions.id_gte);
1128
1141
  const queriedPrevMessages = typeof messagePaginationOptions === "undefined" ? true : messagePaginationOptions.created_at_before_or_equal || messagePaginationOptions.created_at_before || messagePaginationOptions.id_lt || messagePaginationOptions.id_lte || messagePaginationOptions.offset;
@@ -1142,8 +1155,7 @@ var messagePaginationLinear = ({
1142
1155
  return newPagination;
1143
1156
  };
1144
1157
  var messageSetPagination = (params) => {
1145
- const messagesFilteredLocally = params.returnedPage.filter(({ shadowed }) => shadowed);
1146
- if (params.parentSet.messages.length + messagesFilteredLocally.length < params.returnedPage.length) {
1158
+ if (params.parentSet.messages.length + (params.returnedPage.length - params.filteredReturnedPage.length) < params.returnedPage.length) {
1147
1159
  params.logger?.(
1148
1160
  "error",
1149
1161
  "Corrupted message set state: parent set size < returned page size"
@@ -1490,9 +1502,11 @@ var ChannelState = class {
1490
1502
  addIfDoesNotExist,
1491
1503
  messageSetToAddToIfDoesNotExist
1492
1504
  );
1505
+ const filteredMessageIds = [];
1493
1506
  for (let i = 0; i < messagesToAdd.length; i += 1) {
1494
1507
  const isFromShadowBannedUser = messagesToAdd[i].shadowed;
1495
- if (isFromShadowBannedUser) {
1508
+ if (isFromShadowBannedUser && addIfDoesNotExist) {
1509
+ filteredMessageIds.push(messagesToAdd[i].id);
1496
1510
  continue;
1497
1511
  }
1498
1512
  const isMessageFormatted = messagesToAdd[i].created_at instanceof Date;
@@ -1534,7 +1548,8 @@ var ChannelState = class {
1534
1548
  }
1535
1549
  }
1536
1550
  return {
1537
- messageSet: this.messageSets[targetMessageSetIndex]
1551
+ messageSet: this.messageSets[targetMessageSetIndex],
1552
+ filteredMessageIds
1538
1553
  };
1539
1554
  }
1540
1555
  /**
@@ -3381,12 +3396,18 @@ var _AttachmentManager = class _AttachmentManager {
3381
3396
  * Method to perform the default upload behavior without checking for custom upload functions
3382
3397
  * to prevent recursive calls
3383
3398
  */
3384
- this.doDefaultUploadRequest = async (fileLike) => {
3399
+ this.doDefaultUploadRequest = async (fileLike, options) => {
3400
+ const progressHandler = options?.onProgress ? (progressEvent) => {
3401
+ const percent = progressEvent.lengthComputable && progressEvent.total ? Math.round(progressEvent.loaded * 100 / progressEvent.total) : void 0;
3402
+ options.onProgress?.(percent);
3403
+ } : void 0;
3385
3404
  if (isFileReference(fileLike)) {
3386
3405
  return this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
3387
3406
  fileLike.uri,
3388
3407
  fileLike.name,
3389
- fileLike.type
3408
+ fileLike.type,
3409
+ void 0,
3410
+ progressHandler ? { onUploadProgress: progressHandler } : void 0
3390
3411
  );
3391
3412
  }
3392
3413
  const file = isFile(fileLike) ? fileLike : createFileFromBlobs({
@@ -3394,18 +3415,24 @@ var _AttachmentManager = class _AttachmentManager {
3394
3415
  fileName: generateFileName(fileLike.type),
3395
3416
  mimeType: fileLike.type
3396
3417
  });
3397
- const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](file);
3418
+ const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
3419
+ file,
3420
+ void 0,
3421
+ void 0,
3422
+ void 0,
3423
+ progressHandler ? { onUploadProgress: progressHandler } : void 0
3424
+ );
3398
3425
  return result;
3399
3426
  };
3400
3427
  /**
3401
3428
  * todo: docs how to customize the image and file upload by overriding do
3402
3429
  */
3403
- this.doUploadRequest = async (fileLike) => {
3430
+ this.doUploadRequest = async (fileLike, options) => {
3404
3431
  const customUploadFn = this.config.doUploadRequest;
3405
3432
  if (customUploadFn) {
3406
- return await customUploadFn(fileLike);
3433
+ return await customUploadFn(fileLike, options);
3407
3434
  }
3408
- return this.doDefaultUploadRequest(fileLike);
3435
+ return this.doDefaultUploadRequest(fileLike, options);
3409
3436
  };
3410
3437
  // @deprecated use attachmentManager.uploadFile(file)
3411
3438
  this.uploadAttachment = async (attachment) => {
@@ -3429,25 +3456,41 @@ var _AttachmentManager = class _AttachmentManager {
3429
3456
  });
3430
3457
  return localAttachment;
3431
3458
  }
3432
- this.upsertAttachments([
3433
- {
3434
- ...attachment,
3435
- localMetadata: {
3436
- ...attachment.localMetadata,
3437
- uploadState: "uploading"
3438
- }
3459
+ const shouldTrackProgress = this.config.trackUploadProgress;
3460
+ const uploadingAttachment = {
3461
+ ...attachment,
3462
+ localMetadata: {
3463
+ ...attachment.localMetadata,
3464
+ uploadState: "uploading",
3465
+ ...shouldTrackProgress && { uploadProgress: 0 }
3439
3466
  }
3440
- ]);
3467
+ };
3468
+ this.upsertAttachments([uploadingAttachment]);
3469
+ const uploadOptions = shouldTrackProgress ? {
3470
+ onProgress: (percent) => {
3471
+ this.updateAttachment({
3472
+ ...uploadingAttachment,
3473
+ localMetadata: {
3474
+ ...uploadingAttachment.localMetadata,
3475
+ uploadProgress: percent
3476
+ }
3477
+ });
3478
+ }
3479
+ } : void 0;
3441
3480
  let response;
3442
3481
  try {
3443
- response = await this.doUploadRequest(localAttachment.localMetadata.file);
3482
+ response = await this.doUploadRequest(
3483
+ localAttachment.localMetadata.file,
3484
+ uploadOptions
3485
+ );
3444
3486
  } catch (error) {
3445
3487
  const reason = error instanceof Error ? error.message : "unknown error";
3446
3488
  const failedAttachment = {
3447
3489
  ...attachment,
3448
3490
  localMetadata: {
3449
3491
  ...attachment.localMetadata,
3450
- uploadState: "failed"
3492
+ uploadState: "failed",
3493
+ uploadProgress: void 0
3451
3494
  }
3452
3495
  };
3453
3496
  this.client.notifications.addError({
@@ -3473,7 +3516,8 @@ var _AttachmentManager = class _AttachmentManager {
3473
3516
  ...attachment,
3474
3517
  localMetadata: {
3475
3518
  ...attachment.localMetadata,
3476
- uploadState: "finished"
3519
+ uploadState: "finished",
3520
+ uploadProgress: void 0
3477
3521
  }
3478
3522
  };
3479
3523
  const previewUri = uploadedAttachment.localMetadata.previewUri;
@@ -3507,18 +3551,31 @@ var _AttachmentManager = class _AttachmentManager {
3507
3551
  this.upsertAttachments([attachment]);
3508
3552
  return preUpload.state.attachment;
3509
3553
  }
3554
+ const shouldTrackProgress = this.config.trackUploadProgress;
3510
3555
  attachment = {
3511
3556
  ...attachment,
3512
3557
  localMetadata: {
3513
3558
  ...attachment.localMetadata,
3514
- uploadState: "uploading"
3559
+ uploadState: "uploading",
3560
+ ...shouldTrackProgress && { uploadProgress: 0 }
3515
3561
  }
3516
3562
  };
3517
3563
  this.upsertAttachments([attachment]);
3564
+ const uploadOptions = shouldTrackProgress ? {
3565
+ onProgress: (percent) => {
3566
+ this.updateAttachment({
3567
+ ...attachment,
3568
+ localMetadata: {
3569
+ ...attachment.localMetadata,
3570
+ uploadProgress: percent
3571
+ }
3572
+ });
3573
+ }
3574
+ } : void 0;
3518
3575
  let response;
3519
3576
  let error;
3520
3577
  try {
3521
- response = await this.doUploadRequest(file);
3578
+ response = await this.doUploadRequest(file, uploadOptions);
3522
3579
  } catch (err) {
3523
3580
  error = err instanceof Error ? err : void 0;
3524
3581
  }
@@ -3529,7 +3586,8 @@ var _AttachmentManager = class _AttachmentManager {
3529
3586
  ...attachment,
3530
3587
  localMetadata: {
3531
3588
  ...attachment.localMetadata,
3532
- uploadState: error ? "failed" : "finished"
3589
+ uploadState: error ? "failed" : "finished",
3590
+ uploadProgress: void 0
3533
3591
  }
3534
3592
  },
3535
3593
  error,
@@ -3697,7 +3755,8 @@ var DEFAULT_ATTACHMENT_MANAGER_CONFIG = {
3697
3755
  acceptedFiles: [],
3698
3756
  // an empty array means all files are accepted
3699
3757
  fileUploadFilter: () => true,
3700
- maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE
3758
+ maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE,
3759
+ trackUploadProgress: true
3701
3760
  };
3702
3761
  var DEFAULT_TEXT_COMPOSER_CONFIG = {
3703
3762
  enabled: true,
@@ -8156,22 +8215,44 @@ var Channel = class {
8156
8215
  }
8157
8216
  return await this._sendMessage(message, options);
8158
8217
  }
8159
- sendFile(uri, name, contentType, user) {
8218
+ /**
8219
+ * Upload a file to this channel’s file endpoint (multipart). Forwards to the client’s `sendFile` implementation.
8220
+ *
8221
+ * @param uri File source: URL string, `File`, `Buffer`, or readable stream (Node).
8222
+ * @param name File name sent in the multipart body.
8223
+ * @param contentType MIME type; defaults are applied when omitted.
8224
+ * @param user Optional user payload appended to the form as JSON.
8225
+ * @param axiosRequestConfig Optional Axios per-request config, merged after upload defaults (e.g. `onUploadProgress`, `signal` from `AbortController`).
8226
+ * @return Promise resolving to `{ file: string, ... }` with the CDN URL.
8227
+ */
8228
+ sendFile(uri, name, contentType, user, axiosRequestConfig) {
8160
8229
  return this.getClient().sendFile(
8161
8230
  `${this._channelURL()}/file`,
8162
8231
  uri,
8163
8232
  name,
8164
8233
  contentType,
8165
- user
8234
+ user,
8235
+ axiosRequestConfig
8166
8236
  );
8167
8237
  }
8168
- sendImage(uri, name, contentType, user) {
8238
+ /**
8239
+ * Upload an image to this channel’s image endpoint (multipart). Uses the same transport as `sendFile`.
8240
+ *
8241
+ * @param uri Image source: URL string, `File`, or readable stream (Node). For `Buffer` uploads, use `sendFile` toward the channel file endpoint instead.
8242
+ * @param name File name sent in the multipart body.
8243
+ * @param contentType MIME type.
8244
+ * @param user Optional user payload appended to the form as JSON.
8245
+ * @param axiosRequestConfig Optional Axios per-request config, merged after upload defaults (e.g. `onUploadProgress`, `signal`).
8246
+ * @return Promise resolving to `{ file: string, ... }` with the CDN URL.
8247
+ */
8248
+ sendImage(uri, name, contentType, user, axiosRequestConfig) {
8169
8249
  return this.getClient().sendFile(
8170
8250
  `${this._channelURL()}/image`,
8171
8251
  uri,
8172
8252
  name,
8173
8253
  contentType,
8174
- user
8254
+ user,
8255
+ axiosRequestConfig
8175
8256
  );
8176
8257
  }
8177
8258
  deleteFile(url) {
@@ -9204,7 +9285,10 @@ var Channel = class {
9204
9285
  location: { enabled: state.channel.config.shared_locations }
9205
9286
  });
9206
9287
  }
9207
- const { messageSet } = this._initializeState(state, messageSetToAddToIfDoesNotExist);
9288
+ const { messageSet, filteredMessageIds } = this._initializeState(
9289
+ state,
9290
+ messageSetToAddToIfDoesNotExist
9291
+ );
9208
9292
  messageSet.pagination = {
9209
9293
  ...messageSet.pagination,
9210
9294
  ...messageSetPagination({
@@ -9212,6 +9296,9 @@ var Channel = class {
9212
9296
  messagePaginationOptions: options?.messages,
9213
9297
  requestedPageSize: options?.messages?.limit ?? DEFAULT_QUERY_CHANNEL_MESSAGE_LIST_PAGE_SIZE,
9214
9298
  returnedPage: state.messages,
9299
+ filteredReturnedPage: state.messages.filter(
9300
+ (m) => !filteredMessageIds.includes(m.id)
9301
+ ),
9215
9302
  logger: this.getClient().logger
9216
9303
  })
9217
9304
  };
@@ -9831,7 +9918,7 @@ var Channel = class {
9831
9918
  if (!this.state.messages) {
9832
9919
  this.state.initMessages();
9833
9920
  }
9834
- const { messageSet } = this.state.addMessagesSorted(
9921
+ const { messageSet, filteredMessageIds } = this.state.addMessagesSorted(
9835
9922
  messages,
9836
9923
  false,
9837
9924
  true,
@@ -9883,7 +9970,8 @@ var Channel = class {
9883
9970
  this.messageReceiptsTracker.ingestInitial(state.read);
9884
9971
  }
9885
9972
  return {
9886
- messageSet
9973
+ messageSet,
9974
+ filteredMessageIds
9887
9975
  };
9888
9976
  }
9889
9977
  _extendEventWithOwnReactions(event) {
@@ -13712,7 +13800,7 @@ var StreamChat = class _StreamChat {
13712
13800
  delete(url, params) {
13713
13801
  return this.doAxiosRequest("delete", url, null, { params });
13714
13802
  }
13715
- sendFile(url, uri, name, contentType, user) {
13803
+ sendFile(url, uri, name, contentType, user, axiosRequestConfig) {
13716
13804
  const data = addFileToFormData(uri, name, contentType || "multipart/form-data");
13717
13805
  if (user != null) data.append("user", JSON.stringify(user));
13718
13806
  return this.doAxiosRequest("postForm", url, data, {
@@ -13721,7 +13809,8 @@ var StreamChat = class _StreamChat {
13721
13809
  config: {
13722
13810
  timeout: 0,
13723
13811
  maxContentLength: Infinity,
13724
- maxBodyLength: Infinity
13812
+ maxBodyLength: Infinity,
13813
+ ...axiosRequestConfig
13725
13814
  }
13726
13815
  });
13727
13816
  }
@@ -14085,12 +14174,15 @@ var StreamChat = class _StreamChat {
14085
14174
  c.initialized = !offlineMode;
14086
14175
  c.push_preferences = channelState.push_preferences;
14087
14176
  let updatedMessagesSet;
14177
+ let filteredMessageIds = [];
14088
14178
  if (skipInitialization === void 0) {
14089
- const { messageSet } = c._initializeState(channelState, "latest");
14179
+ const { messageSet, filteredMessageIds: _filteredMessageIds } = c._initializeState(channelState, "latest");
14180
+ filteredMessageIds = _filteredMessageIds;
14090
14181
  updatedMessagesSet = messageSet;
14091
14182
  } else if (!skipInitialization.includes(channelState.channel.id)) {
14092
14183
  c.state.clearMessages();
14093
- const { messageSet } = c._initializeState(channelState, "latest");
14184
+ const { messageSet, filteredMessageIds: _filteredMessageIds } = c._initializeState(channelState, "latest");
14185
+ filteredMessageIds = _filteredMessageIds;
14094
14186
  updatedMessagesSet = messageSet;
14095
14187
  }
14096
14188
  if (updatedMessagesSet) {
@@ -14100,6 +14192,9 @@ var StreamChat = class _StreamChat {
14100
14192
  parentSet: updatedMessagesSet,
14101
14193
  requestedPageSize: queryChannelsOptions?.message_limit || DEFAULT_QUERY_CHANNELS_MESSAGE_LIST_PAGE_SIZE,
14102
14194
  returnedPage: channelState.messages,
14195
+ filteredReturnedPage: channelState.messages.filter(
14196
+ (m) => !filteredMessageIds.includes(m.id)
14197
+ ),
14103
14198
  logger: this.logger
14104
14199
  })
14105
14200
  };
@@ -15150,7 +15245,7 @@ var StreamChat = class _StreamChat {
15150
15245
  if (this.userAgent) {
15151
15246
  return this.userAgent;
15152
15247
  }
15153
- const version = "9.40.0";
15248
+ const version = "9.41.1";
15154
15249
  const clientBundle = "node-cjs";
15155
15250
  let userAgentString = "";
15156
15251
  if (this.sdkIdentifier) {
@@ -16288,11 +16383,19 @@ var StreamChat = class _StreamChat {
16288
16383
  * @param {string} [name] The name of the file
16289
16384
  * @param {string} [contentType] The content type of the file
16290
16385
  * @param {UserResponse} [user] Optional user information
16386
+ * @param {AxiosRequestConfig} [axiosRequestConfig] Optional axios config (e.g. onUploadProgress for progress tracking)
16291
16387
  *
16292
16388
  * @return {Promise<SendFileAPIResponse>} Response containing the file URL
16293
16389
  */
16294
- uploadFile(uri, name, contentType, user) {
16295
- return this.sendFile(`${this.baseURL}/uploads/file`, uri, name, contentType, user);
16390
+ uploadFile(uri, name, contentType, user, axiosRequestConfig) {
16391
+ return this.sendFile(
16392
+ `${this.baseURL}/uploads/file`,
16393
+ uri,
16394
+ name,
16395
+ contentType,
16396
+ user,
16397
+ axiosRequestConfig
16398
+ );
16296
16399
  }
16297
16400
  /**
16298
16401
  * uploadImage - Uploads an image to the configured storage (defaults to Stream CDN)
@@ -16301,11 +16404,19 @@ var StreamChat = class _StreamChat {
16301
16404
  * @param {string} [name] The name of the image
16302
16405
  * @param {string} [contentType] The content type of the image
16303
16406
  * @param {UserResponse} [user] Optional user information
16407
+ * @param {AxiosRequestConfig} [axiosRequestConfig] Optional axios config (e.g. onUploadProgress for progress tracking)
16304
16408
  *
16305
16409
  * @return {Promise<SendFileAPIResponse>} Response containing the image URL
16306
16410
  */
16307
- uploadImage(uri, name, contentType, user) {
16308
- return this.sendFile(`${this.baseURL}/uploads/image`, uri, name, contentType, user);
16411
+ uploadImage(uri, name, contentType, user, axiosRequestConfig) {
16412
+ return this.sendFile(
16413
+ `${this.baseURL}/uploads/image`,
16414
+ uri,
16415
+ name,
16416
+ contentType,
16417
+ user,
16418
+ axiosRequestConfig
16419
+ );
16309
16420
  }
16310
16421
  /**
16311
16422
  * deleteFile - Deletes a file from the configured storage