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.
@@ -845,6 +845,7 @@ var messagePaginationCreatedAtAround = ({
845
845
  parentSet,
846
846
  requestedPageSize,
847
847
  returnedPage,
848
+ filteredReturnedPage,
848
849
  messagePaginationOptions
849
850
  }) => {
850
851
  const newPagination = { ...parentSet.pagination };
@@ -877,9 +878,13 @@ var messagePaginationCreatedAtAround = ({
877
878
  hasNext = hasPrev = false;
878
879
  updateHasPrev = updateHasNext = true;
879
880
  } else {
881
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
882
+ filteredReturnedPage[0],
883
+ filteredReturnedPage.slice(-1)[0]
884
+ ];
880
885
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
881
- firstPageMsg?.id && firstPageMsg.id === parentSet.messages[0]?.id,
882
- lastPageMsg?.id && lastPageMsg.id === parentSet.messages.slice(-1)[0]?.id
886
+ firstFilteredPageMsg?.id && firstFilteredPageMsg.id === parentSet.messages[0]?.id,
887
+ lastFilteredPageMsg?.id && lastFilteredPageMsg.id === parentSet.messages.slice(-1)[0]?.id
883
888
  ];
884
889
  updateHasPrev = firstPageMsgIsFirstInSet;
885
890
  updateHasNext = lastPageMsgIsLastInSet;
@@ -901,6 +906,7 @@ var messagePaginationIdAround = ({
901
906
  parentSet,
902
907
  requestedPageSize,
903
908
  returnedPage,
909
+ filteredReturnedPage,
904
910
  messagePaginationOptions
905
911
  }) => {
906
912
  const newPagination = { ...parentSet.pagination };
@@ -908,10 +914,13 @@ var messagePaginationIdAround = ({
908
914
  if (!id_around) return newPagination;
909
915
  let hasPrev;
910
916
  let hasNext;
911
- const [firstPageMsg, lastPageMsg] = [returnedPage[0], returnedPage.slice(-1)[0]];
917
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
918
+ filteredReturnedPage[0],
919
+ filteredReturnedPage.slice(-1)[0]
920
+ ];
912
921
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
913
- firstPageMsg?.id === parentSet.messages[0]?.id,
914
- lastPageMsg?.id === parentSet.messages.slice(-1)[0]?.id
922
+ firstFilteredPageMsg?.id === parentSet.messages[0]?.id,
923
+ lastFilteredPageMsg?.id === parentSet.messages.slice(-1)[0]?.id
915
924
  ];
916
925
  let updateHasPrev = firstPageMsgIsFirstInSet;
917
926
  let updateHasNext = lastPageMsgIsLastInSet;
@@ -946,15 +955,19 @@ var messagePaginationLinear = ({
946
955
  parentSet,
947
956
  requestedPageSize,
948
957
  returnedPage,
958
+ filteredReturnedPage,
949
959
  messagePaginationOptions
950
960
  }) => {
951
961
  const newPagination = { ...parentSet.pagination };
952
962
  let hasPrev;
953
963
  let hasNext;
954
- const [firstPageMsg, lastPageMsg] = [returnedPage[0], returnedPage.slice(-1)[0]];
964
+ const [firstFilteredPageMsg, lastFilteredPageMsg] = [
965
+ filteredReturnedPage[0],
966
+ filteredReturnedPage.slice(-1)[0]
967
+ ];
955
968
  const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
956
- firstPageMsg?.id && firstPageMsg.id === parentSet.messages[0]?.id,
957
- lastPageMsg?.id && lastPageMsg.id === parentSet.messages.slice(-1)[0]?.id
969
+ firstFilteredPageMsg?.id && firstFilteredPageMsg.id === parentSet.messages[0]?.id,
970
+ lastFilteredPageMsg?.id && lastFilteredPageMsg.id === parentSet.messages.slice(-1)[0]?.id
958
971
  ];
959
972
  const queriedNextMessages = messagePaginationOptions && (messagePaginationOptions.created_at_after_or_equal || messagePaginationOptions.created_at_after || messagePaginationOptions.id_gt || messagePaginationOptions.id_gte);
960
973
  const queriedPrevMessages = typeof messagePaginationOptions === "undefined" ? true : messagePaginationOptions.created_at_before_or_equal || messagePaginationOptions.created_at_before || messagePaginationOptions.id_lt || messagePaginationOptions.id_lte || messagePaginationOptions.offset;
@@ -974,8 +987,7 @@ var messagePaginationLinear = ({
974
987
  return newPagination;
975
988
  };
976
989
  var messageSetPagination = (params) => {
977
- const messagesFilteredLocally = params.returnedPage.filter(({ shadowed }) => shadowed);
978
- if (params.parentSet.messages.length + messagesFilteredLocally.length < params.returnedPage.length) {
990
+ if (params.parentSet.messages.length + (params.returnedPage.length - params.filteredReturnedPage.length) < params.returnedPage.length) {
979
991
  params.logger?.(
980
992
  "error",
981
993
  "Corrupted message set state: parent set size < returned page size"
@@ -1322,9 +1334,11 @@ var ChannelState = class {
1322
1334
  addIfDoesNotExist,
1323
1335
  messageSetToAddToIfDoesNotExist
1324
1336
  );
1337
+ const filteredMessageIds = [];
1325
1338
  for (let i = 0; i < messagesToAdd.length; i += 1) {
1326
1339
  const isFromShadowBannedUser = messagesToAdd[i].shadowed;
1327
- if (isFromShadowBannedUser) {
1340
+ if (isFromShadowBannedUser && addIfDoesNotExist) {
1341
+ filteredMessageIds.push(messagesToAdd[i].id);
1328
1342
  continue;
1329
1343
  }
1330
1344
  const isMessageFormatted = messagesToAdd[i].created_at instanceof Date;
@@ -1366,7 +1380,8 @@ var ChannelState = class {
1366
1380
  }
1367
1381
  }
1368
1382
  return {
1369
- messageSet: this.messageSets[targetMessageSetIndex]
1383
+ messageSet: this.messageSets[targetMessageSetIndex],
1384
+ filteredMessageIds
1370
1385
  };
1371
1386
  }
1372
1387
  /**
@@ -3213,12 +3228,18 @@ var _AttachmentManager = class _AttachmentManager {
3213
3228
  * Method to perform the default upload behavior without checking for custom upload functions
3214
3229
  * to prevent recursive calls
3215
3230
  */
3216
- this.doDefaultUploadRequest = async (fileLike) => {
3231
+ this.doDefaultUploadRequest = async (fileLike, options) => {
3232
+ const progressHandler = options?.onProgress ? (progressEvent) => {
3233
+ const percent = progressEvent.lengthComputable && progressEvent.total ? Math.round(progressEvent.loaded * 100 / progressEvent.total) : void 0;
3234
+ options.onProgress?.(percent);
3235
+ } : void 0;
3217
3236
  if (isFileReference(fileLike)) {
3218
3237
  return this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
3219
3238
  fileLike.uri,
3220
3239
  fileLike.name,
3221
- fileLike.type
3240
+ fileLike.type,
3241
+ void 0,
3242
+ progressHandler ? { onUploadProgress: progressHandler } : void 0
3222
3243
  );
3223
3244
  }
3224
3245
  const file = isFile(fileLike) ? fileLike : createFileFromBlobs({
@@ -3226,18 +3247,24 @@ var _AttachmentManager = class _AttachmentManager {
3226
3247
  fileName: generateFileName(fileLike.type),
3227
3248
  mimeType: fileLike.type
3228
3249
  });
3229
- const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](file);
3250
+ const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
3251
+ file,
3252
+ void 0,
3253
+ void 0,
3254
+ void 0,
3255
+ progressHandler ? { onUploadProgress: progressHandler } : void 0
3256
+ );
3230
3257
  return result;
3231
3258
  };
3232
3259
  /**
3233
3260
  * todo: docs how to customize the image and file upload by overriding do
3234
3261
  */
3235
- this.doUploadRequest = async (fileLike) => {
3262
+ this.doUploadRequest = async (fileLike, options) => {
3236
3263
  const customUploadFn = this.config.doUploadRequest;
3237
3264
  if (customUploadFn) {
3238
- return await customUploadFn(fileLike);
3265
+ return await customUploadFn(fileLike, options);
3239
3266
  }
3240
- return this.doDefaultUploadRequest(fileLike);
3267
+ return this.doDefaultUploadRequest(fileLike, options);
3241
3268
  };
3242
3269
  // @deprecated use attachmentManager.uploadFile(file)
3243
3270
  this.uploadAttachment = async (attachment) => {
@@ -3261,25 +3288,41 @@ var _AttachmentManager = class _AttachmentManager {
3261
3288
  });
3262
3289
  return localAttachment;
3263
3290
  }
3264
- this.upsertAttachments([
3265
- {
3266
- ...attachment,
3267
- localMetadata: {
3268
- ...attachment.localMetadata,
3269
- uploadState: "uploading"
3270
- }
3291
+ const shouldTrackProgress = this.config.trackUploadProgress;
3292
+ const uploadingAttachment = {
3293
+ ...attachment,
3294
+ localMetadata: {
3295
+ ...attachment.localMetadata,
3296
+ uploadState: "uploading",
3297
+ ...shouldTrackProgress && { uploadProgress: 0 }
3271
3298
  }
3272
- ]);
3299
+ };
3300
+ this.upsertAttachments([uploadingAttachment]);
3301
+ const uploadOptions = shouldTrackProgress ? {
3302
+ onProgress: (percent) => {
3303
+ this.updateAttachment({
3304
+ ...uploadingAttachment,
3305
+ localMetadata: {
3306
+ ...uploadingAttachment.localMetadata,
3307
+ uploadProgress: percent
3308
+ }
3309
+ });
3310
+ }
3311
+ } : void 0;
3273
3312
  let response;
3274
3313
  try {
3275
- response = await this.doUploadRequest(localAttachment.localMetadata.file);
3314
+ response = await this.doUploadRequest(
3315
+ localAttachment.localMetadata.file,
3316
+ uploadOptions
3317
+ );
3276
3318
  } catch (error) {
3277
3319
  const reason = error instanceof Error ? error.message : "unknown error";
3278
3320
  const failedAttachment = {
3279
3321
  ...attachment,
3280
3322
  localMetadata: {
3281
3323
  ...attachment.localMetadata,
3282
- uploadState: "failed"
3324
+ uploadState: "failed",
3325
+ uploadProgress: void 0
3283
3326
  }
3284
3327
  };
3285
3328
  this.client.notifications.addError({
@@ -3305,7 +3348,8 @@ var _AttachmentManager = class _AttachmentManager {
3305
3348
  ...attachment,
3306
3349
  localMetadata: {
3307
3350
  ...attachment.localMetadata,
3308
- uploadState: "finished"
3351
+ uploadState: "finished",
3352
+ uploadProgress: void 0
3309
3353
  }
3310
3354
  };
3311
3355
  const previewUri = uploadedAttachment.localMetadata.previewUri;
@@ -3339,18 +3383,31 @@ var _AttachmentManager = class _AttachmentManager {
3339
3383
  this.upsertAttachments([attachment]);
3340
3384
  return preUpload.state.attachment;
3341
3385
  }
3386
+ const shouldTrackProgress = this.config.trackUploadProgress;
3342
3387
  attachment = {
3343
3388
  ...attachment,
3344
3389
  localMetadata: {
3345
3390
  ...attachment.localMetadata,
3346
- uploadState: "uploading"
3391
+ uploadState: "uploading",
3392
+ ...shouldTrackProgress && { uploadProgress: 0 }
3347
3393
  }
3348
3394
  };
3349
3395
  this.upsertAttachments([attachment]);
3396
+ const uploadOptions = shouldTrackProgress ? {
3397
+ onProgress: (percent) => {
3398
+ this.updateAttachment({
3399
+ ...attachment,
3400
+ localMetadata: {
3401
+ ...attachment.localMetadata,
3402
+ uploadProgress: percent
3403
+ }
3404
+ });
3405
+ }
3406
+ } : void 0;
3350
3407
  let response;
3351
3408
  let error;
3352
3409
  try {
3353
- response = await this.doUploadRequest(file);
3410
+ response = await this.doUploadRequest(file, uploadOptions);
3354
3411
  } catch (err) {
3355
3412
  error = err instanceof Error ? err : void 0;
3356
3413
  }
@@ -3361,7 +3418,8 @@ var _AttachmentManager = class _AttachmentManager {
3361
3418
  ...attachment,
3362
3419
  localMetadata: {
3363
3420
  ...attachment.localMetadata,
3364
- uploadState: error ? "failed" : "finished"
3421
+ uploadState: error ? "failed" : "finished",
3422
+ uploadProgress: void 0
3365
3423
  }
3366
3424
  },
3367
3425
  error,
@@ -3529,7 +3587,8 @@ var DEFAULT_ATTACHMENT_MANAGER_CONFIG = {
3529
3587
  acceptedFiles: [],
3530
3588
  // an empty array means all files are accepted
3531
3589
  fileUploadFilter: () => true,
3532
- maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE
3590
+ maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE,
3591
+ trackUploadProgress: true
3533
3592
  };
3534
3593
  var DEFAULT_TEXT_COMPOSER_CONFIG = {
3535
3594
  enabled: true,
@@ -7988,22 +8047,44 @@ var Channel = class {
7988
8047
  }
7989
8048
  return await this._sendMessage(message, options);
7990
8049
  }
7991
- sendFile(uri, name, contentType, user) {
8050
+ /**
8051
+ * Upload a file to this channel’s file endpoint (multipart). Forwards to the client’s `sendFile` implementation.
8052
+ *
8053
+ * @param uri File source: URL string, `File`, `Buffer`, or readable stream (Node).
8054
+ * @param name File name sent in the multipart body.
8055
+ * @param contentType MIME type; defaults are applied when omitted.
8056
+ * @param user Optional user payload appended to the form as JSON.
8057
+ * @param axiosRequestConfig Optional Axios per-request config, merged after upload defaults (e.g. `onUploadProgress`, `signal` from `AbortController`).
8058
+ * @return Promise resolving to `{ file: string, ... }` with the CDN URL.
8059
+ */
8060
+ sendFile(uri, name, contentType, user, axiosRequestConfig) {
7992
8061
  return this.getClient().sendFile(
7993
8062
  `${this._channelURL()}/file`,
7994
8063
  uri,
7995
8064
  name,
7996
8065
  contentType,
7997
- user
8066
+ user,
8067
+ axiosRequestConfig
7998
8068
  );
7999
8069
  }
8000
- sendImage(uri, name, contentType, user) {
8070
+ /**
8071
+ * Upload an image to this channel’s image endpoint (multipart). Uses the same transport as `sendFile`.
8072
+ *
8073
+ * @param uri Image source: URL string, `File`, or readable stream (Node). For `Buffer` uploads, use `sendFile` toward the channel file endpoint instead.
8074
+ * @param name File name sent in the multipart body.
8075
+ * @param contentType MIME type.
8076
+ * @param user Optional user payload appended to the form as JSON.
8077
+ * @param axiosRequestConfig Optional Axios per-request config, merged after upload defaults (e.g. `onUploadProgress`, `signal`).
8078
+ * @return Promise resolving to `{ file: string, ... }` with the CDN URL.
8079
+ */
8080
+ sendImage(uri, name, contentType, user, axiosRequestConfig) {
8001
8081
  return this.getClient().sendFile(
8002
8082
  `${this._channelURL()}/image`,
8003
8083
  uri,
8004
8084
  name,
8005
8085
  contentType,
8006
- user
8086
+ user,
8087
+ axiosRequestConfig
8007
8088
  );
8008
8089
  }
8009
8090
  deleteFile(url) {
@@ -9036,7 +9117,10 @@ var Channel = class {
9036
9117
  location: { enabled: state.channel.config.shared_locations }
9037
9118
  });
9038
9119
  }
9039
- const { messageSet } = this._initializeState(state, messageSetToAddToIfDoesNotExist);
9120
+ const { messageSet, filteredMessageIds } = this._initializeState(
9121
+ state,
9122
+ messageSetToAddToIfDoesNotExist
9123
+ );
9040
9124
  messageSet.pagination = {
9041
9125
  ...messageSet.pagination,
9042
9126
  ...messageSetPagination({
@@ -9044,6 +9128,9 @@ var Channel = class {
9044
9128
  messagePaginationOptions: options?.messages,
9045
9129
  requestedPageSize: options?.messages?.limit ?? DEFAULT_QUERY_CHANNEL_MESSAGE_LIST_PAGE_SIZE,
9046
9130
  returnedPage: state.messages,
9131
+ filteredReturnedPage: state.messages.filter(
9132
+ (m) => !filteredMessageIds.includes(m.id)
9133
+ ),
9047
9134
  logger: this.getClient().logger
9048
9135
  })
9049
9136
  };
@@ -9663,7 +9750,7 @@ var Channel = class {
9663
9750
  if (!this.state.messages) {
9664
9751
  this.state.initMessages();
9665
9752
  }
9666
- const { messageSet } = this.state.addMessagesSorted(
9753
+ const { messageSet, filteredMessageIds } = this.state.addMessagesSorted(
9667
9754
  messages,
9668
9755
  false,
9669
9756
  true,
@@ -9715,7 +9802,8 @@ var Channel = class {
9715
9802
  this.messageReceiptsTracker.ingestInitial(state.read);
9716
9803
  }
9717
9804
  return {
9718
- messageSet
9805
+ messageSet,
9806
+ filteredMessageIds
9719
9807
  };
9720
9808
  }
9721
9809
  _extendEventWithOwnReactions(event) {
@@ -13544,7 +13632,7 @@ var StreamChat = class _StreamChat {
13544
13632
  delete(url, params) {
13545
13633
  return this.doAxiosRequest("delete", url, null, { params });
13546
13634
  }
13547
- sendFile(url, uri, name, contentType, user) {
13635
+ sendFile(url, uri, name, contentType, user, axiosRequestConfig) {
13548
13636
  const data = addFileToFormData(uri, name, contentType || "multipart/form-data");
13549
13637
  if (user != null) data.append("user", JSON.stringify(user));
13550
13638
  return this.doAxiosRequest("postForm", url, data, {
@@ -13553,7 +13641,8 @@ var StreamChat = class _StreamChat {
13553
13641
  config: {
13554
13642
  timeout: 0,
13555
13643
  maxContentLength: Infinity,
13556
- maxBodyLength: Infinity
13644
+ maxBodyLength: Infinity,
13645
+ ...axiosRequestConfig
13557
13646
  }
13558
13647
  });
13559
13648
  }
@@ -13917,12 +14006,15 @@ var StreamChat = class _StreamChat {
13917
14006
  c.initialized = !offlineMode;
13918
14007
  c.push_preferences = channelState.push_preferences;
13919
14008
  let updatedMessagesSet;
14009
+ let filteredMessageIds = [];
13920
14010
  if (skipInitialization === void 0) {
13921
- const { messageSet } = c._initializeState(channelState, "latest");
14011
+ const { messageSet, filteredMessageIds: _filteredMessageIds } = c._initializeState(channelState, "latest");
14012
+ filteredMessageIds = _filteredMessageIds;
13922
14013
  updatedMessagesSet = messageSet;
13923
14014
  } else if (!skipInitialization.includes(channelState.channel.id)) {
13924
14015
  c.state.clearMessages();
13925
- const { messageSet } = c._initializeState(channelState, "latest");
14016
+ const { messageSet, filteredMessageIds: _filteredMessageIds } = c._initializeState(channelState, "latest");
14017
+ filteredMessageIds = _filteredMessageIds;
13926
14018
  updatedMessagesSet = messageSet;
13927
14019
  }
13928
14020
  if (updatedMessagesSet) {
@@ -13932,6 +14024,9 @@ var StreamChat = class _StreamChat {
13932
14024
  parentSet: updatedMessagesSet,
13933
14025
  requestedPageSize: queryChannelsOptions?.message_limit || DEFAULT_QUERY_CHANNELS_MESSAGE_LIST_PAGE_SIZE,
13934
14026
  returnedPage: channelState.messages,
14027
+ filteredReturnedPage: channelState.messages.filter(
14028
+ (m) => !filteredMessageIds.includes(m.id)
14029
+ ),
13935
14030
  logger: this.logger
13936
14031
  })
13937
14032
  };
@@ -14982,7 +15077,7 @@ var StreamChat = class _StreamChat {
14982
15077
  if (this.userAgent) {
14983
15078
  return this.userAgent;
14984
15079
  }
14985
- const version = "9.40.0";
15080
+ const version = "9.41.1";
14986
15081
  const clientBundle = "browser-esm";
14987
15082
  let userAgentString = "";
14988
15083
  if (this.sdkIdentifier) {
@@ -16120,11 +16215,19 @@ var StreamChat = class _StreamChat {
16120
16215
  * @param {string} [name] The name of the file
16121
16216
  * @param {string} [contentType] The content type of the file
16122
16217
  * @param {UserResponse} [user] Optional user information
16218
+ * @param {AxiosRequestConfig} [axiosRequestConfig] Optional axios config (e.g. onUploadProgress for progress tracking)
16123
16219
  *
16124
16220
  * @return {Promise<SendFileAPIResponse>} Response containing the file URL
16125
16221
  */
16126
- uploadFile(uri, name, contentType, user) {
16127
- return this.sendFile(`${this.baseURL}/uploads/file`, uri, name, contentType, user);
16222
+ uploadFile(uri, name, contentType, user, axiosRequestConfig) {
16223
+ return this.sendFile(
16224
+ `${this.baseURL}/uploads/file`,
16225
+ uri,
16226
+ name,
16227
+ contentType,
16228
+ user,
16229
+ axiosRequestConfig
16230
+ );
16128
16231
  }
16129
16232
  /**
16130
16233
  * uploadImage - Uploads an image to the configured storage (defaults to Stream CDN)
@@ -16133,11 +16236,19 @@ var StreamChat = class _StreamChat {
16133
16236
  * @param {string} [name] The name of the image
16134
16237
  * @param {string} [contentType] The content type of the image
16135
16238
  * @param {UserResponse} [user] Optional user information
16239
+ * @param {AxiosRequestConfig} [axiosRequestConfig] Optional axios config (e.g. onUploadProgress for progress tracking)
16136
16240
  *
16137
16241
  * @return {Promise<SendFileAPIResponse>} Response containing the image URL
16138
16242
  */
16139
- uploadImage(uri, name, contentType, user) {
16140
- return this.sendFile(`${this.baseURL}/uploads/image`, uri, name, contentType, user);
16243
+ uploadImage(uri, name, contentType, user, axiosRequestConfig) {
16244
+ return this.sendFile(
16245
+ `${this.baseURL}/uploads/image`,
16246
+ uri,
16247
+ name,
16248
+ contentType,
16249
+ user,
16250
+ axiosRequestConfig
16251
+ );
16141
16252
  }
16142
16253
  /**
16143
16254
  * deleteFile - Deletes a file from the configured storage