stream-chat 9.13.0 → 9.14.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.
Files changed (37) hide show
  1. package/dist/cjs/index.browser.cjs +412 -182
  2. package/dist/cjs/index.browser.cjs.map +4 -4
  3. package/dist/cjs/index.node.cjs +1846 -439
  4. package/dist/cjs/index.node.cjs.map +4 -4
  5. package/dist/esm/index.js +412 -182
  6. package/dist/esm/index.js.map +4 -4
  7. package/dist/types/messageComposer/attachmentManager.d.ts +11 -3
  8. package/dist/types/messageComposer/configuration/types.d.ts +1 -1
  9. package/dist/types/messageComposer/middleware/attachmentManager/index.d.ts +3 -0
  10. package/dist/types/messageComposer/middleware/attachmentManager/postUpload/AttachmentPostUploadMiddlewareExecutor.d.ts +5 -0
  11. package/dist/types/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.d.ts +2 -0
  12. package/dist/types/messageComposer/middleware/attachmentManager/postUpload/index.d.ts +3 -0
  13. package/dist/types/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.d.ts +3 -0
  14. package/dist/types/messageComposer/middleware/attachmentManager/preUpload/AttachmentPreUploadMiddlewareExecutor.d.ts +5 -0
  15. package/dist/types/messageComposer/middleware/attachmentManager/preUpload/blockedUploadNotification.d.ts +3 -0
  16. package/dist/types/messageComposer/middleware/attachmentManager/preUpload/index.d.ts +3 -0
  17. package/dist/types/messageComposer/middleware/attachmentManager/preUpload/serverUploadConfigCheck.d.ts +3 -0
  18. package/dist/types/messageComposer/middleware/attachmentManager/types.d.ts +20 -0
  19. package/dist/types/messageComposer/types.d.ts +1 -0
  20. package/dist/types/middleware.d.ts +3 -2
  21. package/package.json +2 -2
  22. package/src/messageComposer/attachmentManager.ts +116 -25
  23. package/src/messageComposer/configuration/types.ts +3 -2
  24. package/src/messageComposer/messageComposer.ts +1 -1
  25. package/src/messageComposer/middleware/attachmentManager/index.ts +3 -0
  26. package/src/messageComposer/middleware/attachmentManager/postUpload/AttachmentPostUploadMiddlewareExecutor.ts +20 -0
  27. package/src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts +43 -0
  28. package/src/messageComposer/middleware/attachmentManager/postUpload/index.ts +3 -0
  29. package/src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts +39 -0
  30. package/src/messageComposer/middleware/attachmentManager/preUpload/AttachmentPreUploadMiddlewareExecutor.ts +20 -0
  31. package/src/messageComposer/middleware/attachmentManager/preUpload/blockedUploadNotification.ts +38 -0
  32. package/src/messageComposer/middleware/attachmentManager/preUpload/index.ts +3 -0
  33. package/src/messageComposer/middleware/attachmentManager/preUpload/serverUploadConfigCheck.ts +40 -0
  34. package/src/messageComposer/middleware/attachmentManager/types.ts +32 -0
  35. package/src/messageComposer/types.ts +6 -0
  36. package/src/middleware.ts +22 -10
  37. package/src/utils.ts +5 -1
@@ -140,7 +140,8 @@ var require_https = __commonJS({
140
140
  // node_modules/form-data/lib/browser.js
141
141
  var require_browser = __commonJS({
142
142
  "node_modules/form-data/lib/browser.js"(exports, module2) {
143
- module2.exports = typeof self == "object" ? self.FormData : window.FormData;
143
+ "use strict";
144
+ module2.exports = typeof self === "object" ? self.FormData : window.FormData;
144
145
  }
145
146
  });
146
147
 
@@ -3151,7 +3152,8 @@ var messagePaginationLinear = ({
3151
3152
  return newPagination;
3152
3153
  };
3153
3154
  var messageSetPagination = (params) => {
3154
- if (params.parentSet.messages.length < params.returnedPage.length) {
3155
+ const messagesFilteredLocally = params.returnedPage.filter(({ shadowed }) => shadowed);
3156
+ if (params.parentSet.messages.length + messagesFilteredLocally.length < params.returnedPage.length) {
3155
3157
  params.logger?.(
3156
3158
  "error",
3157
3159
  "Corrupted message set state: parent set size < returned page size"
@@ -4088,6 +4090,294 @@ var ensureIsLocalAttachment = (attachment) => {
4088
4090
  };
4089
4091
  };
4090
4092
 
4093
+ // src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts
4094
+ var createPostUploadAttachmentEnrichmentMiddleware = () => ({
4095
+ id: "stream-io/attachment-manager-middleware/post-upload-enrichment",
4096
+ handlers: {
4097
+ postProcess: ({
4098
+ state,
4099
+ discard,
4100
+ forward,
4101
+ next
4102
+ }) => {
4103
+ const { attachment, error, response } = state;
4104
+ if (error) return forward();
4105
+ if (!attachment || !response) return discard();
4106
+ const enrichedAttachment = { ...attachment };
4107
+ if (isLocalImageAttachment(attachment)) {
4108
+ if (attachment.localMetadata.previewUri) {
4109
+ URL.revokeObjectURL(attachment.localMetadata.previewUri);
4110
+ delete enrichedAttachment.localMetadata.previewUri;
4111
+ }
4112
+ enrichedAttachment.image_url = response.file;
4113
+ } else {
4114
+ enrichedAttachment.asset_url = response.file;
4115
+ }
4116
+ if (response.thumb_url) {
4117
+ enrichedAttachment.thumb_url = response.thumb_url;
4118
+ }
4119
+ return next({
4120
+ ...state,
4121
+ attachment: enrichedAttachment
4122
+ });
4123
+ }
4124
+ }
4125
+ });
4126
+
4127
+ // src/utils/concurrency.ts
4128
+ var withoutConcurrency = createRunner(wrapWithContinuationTracking);
4129
+ var withCancellation = createRunner(wrapWithCancellation);
4130
+ var pendingPromises = /* @__PURE__ */ new Map();
4131
+ function createRunner(wrapper) {
4132
+ return function run(tag, cb) {
4133
+ const { cb: wrapped, onContinued } = wrapper(tag, cb);
4134
+ const pending = pendingPromises.get(tag);
4135
+ pending?.onContinued();
4136
+ const promise = pending ? pending.promise.then(wrapped, wrapped) : wrapped();
4137
+ pendingPromises.set(tag, { promise, onContinued });
4138
+ return promise;
4139
+ };
4140
+ }
4141
+ function wrapWithContinuationTracking(tag, cb) {
4142
+ let hasContinuation = false;
4143
+ const wrapped = () => cb().finally(() => {
4144
+ if (!hasContinuation) {
4145
+ pendingPromises.delete(tag);
4146
+ }
4147
+ });
4148
+ const onContinued = () => hasContinuation = true;
4149
+ return { cb: wrapped, onContinued };
4150
+ }
4151
+ function wrapWithCancellation(tag, cb) {
4152
+ const ac = new AbortController();
4153
+ const wrapped = () => {
4154
+ if (ac.signal.aborted) {
4155
+ return Promise.resolve("canceled");
4156
+ }
4157
+ return cb(ac.signal).finally(() => {
4158
+ if (!ac.signal.aborted) {
4159
+ pendingPromises.delete(tag);
4160
+ }
4161
+ });
4162
+ };
4163
+ const onContinued = () => ac.abort();
4164
+ return { cb: wrapped, onContinued };
4165
+ }
4166
+
4167
+ // src/middleware.ts
4168
+ var MiddlewareExecutor = class {
4169
+ constructor() {
4170
+ this.middleware = [];
4171
+ this.id = generateUUIDv4();
4172
+ }
4173
+ use(middleware) {
4174
+ this.middleware = this.middleware.concat(middleware);
4175
+ return this;
4176
+ }
4177
+ // todo: document how to re-arrange the order of middleware using replace
4178
+ replace(middleware) {
4179
+ const newMiddleware = [...this.middleware];
4180
+ middleware.forEach((upserted) => {
4181
+ const existingIndex = this.middleware.findIndex(
4182
+ (existing) => existing.id === upserted.id
4183
+ );
4184
+ if (existingIndex >= 0) {
4185
+ newMiddleware.splice(existingIndex, 1, upserted);
4186
+ } else {
4187
+ newMiddleware.push(upserted);
4188
+ }
4189
+ });
4190
+ this.middleware = newMiddleware;
4191
+ return this;
4192
+ }
4193
+ insert({
4194
+ middleware,
4195
+ position,
4196
+ unique
4197
+ }) {
4198
+ if (unique) {
4199
+ middleware.forEach((md) => {
4200
+ const existingMiddlewareIndex = this.middleware.findIndex((m) => m.id === md.id);
4201
+ if (existingMiddlewareIndex >= 0) {
4202
+ this.middleware.splice(existingMiddlewareIndex, 1);
4203
+ }
4204
+ });
4205
+ }
4206
+ const targetId = position.after || position.before;
4207
+ const targetIndex = this.middleware.findIndex((m) => m.id === targetId);
4208
+ const insertionIndex = position.after ? targetIndex + 1 : targetIndex;
4209
+ this.middleware.splice(insertionIndex, 0, ...middleware);
4210
+ return this;
4211
+ }
4212
+ setOrder(order) {
4213
+ this.middleware = order.map((id) => this.middleware.find((middleware) => middleware.id === id)).filter(Boolean);
4214
+ }
4215
+ async executeMiddlewareChain({
4216
+ eventName,
4217
+ initialValue,
4218
+ mode = "cancelable"
4219
+ }) {
4220
+ let index = -1;
4221
+ const execute = async (i, state, status) => {
4222
+ if (i <= index) {
4223
+ throw new Error("next() called multiple times");
4224
+ }
4225
+ index = i;
4226
+ const returnFromChain = i === this.middleware.length || status && ["complete", "discard"].includes(status);
4227
+ if (returnFromChain) return { state, status };
4228
+ const middleware = this.middleware[i];
4229
+ const handler = middleware.handlers[eventName];
4230
+ if (!handler) {
4231
+ return execute(i + 1, state, status);
4232
+ }
4233
+ const next = (adjustedState) => execute(i + 1, adjustedState);
4234
+ const complete = (adjustedState) => execute(i + 1, adjustedState, "complete");
4235
+ const discard = () => execute(i + 1, state, "discard");
4236
+ const forward = () => execute(i + 1, state);
4237
+ return await handler({
4238
+ state,
4239
+ next,
4240
+ complete,
4241
+ discard,
4242
+ forward
4243
+ });
4244
+ };
4245
+ const result = mode === "cancelable" ? await withCancellation(
4246
+ `middleware-execution-${this.id}-${eventName}`,
4247
+ async (abortSignal) => {
4248
+ const result2 = await execute(0, initialValue);
4249
+ if (abortSignal.aborted) {
4250
+ return "canceled";
4251
+ }
4252
+ return result2;
4253
+ }
4254
+ ) : await execute(0, initialValue);
4255
+ return result === "canceled" ? { state: initialValue, status: "discard" } : result;
4256
+ }
4257
+ async execute({
4258
+ eventName,
4259
+ initialValue: initialState,
4260
+ mode
4261
+ }) {
4262
+ return await this.executeMiddlewareChain({
4263
+ eventName,
4264
+ initialValue: initialState,
4265
+ mode
4266
+ });
4267
+ }
4268
+ };
4269
+
4270
+ // src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts
4271
+ var createUploadErrorHandlerMiddleware = (composer) => ({
4272
+ id: "stream-io/attachment-manager-middleware/upload-error",
4273
+ handlers: {
4274
+ postProcess: ({
4275
+ state,
4276
+ discard,
4277
+ forward
4278
+ }) => {
4279
+ const { attachment, error } = state;
4280
+ if (!error) return forward();
4281
+ if (!attachment) return discard();
4282
+ const reason = error instanceof Error ? error.message : "unknown error";
4283
+ composer.client.notifications.addError({
4284
+ message: "Error uploading attachment",
4285
+ origin: {
4286
+ emitter: "AttachmentManager",
4287
+ context: { attachment }
4288
+ },
4289
+ options: {
4290
+ type: "api:attachment:upload:failed",
4291
+ metadata: { reason },
4292
+ originalError: error
4293
+ }
4294
+ });
4295
+ return forward();
4296
+ }
4297
+ }
4298
+ });
4299
+
4300
+ // src/messageComposer/middleware/attachmentManager/postUpload/AttachmentPostUploadMiddlewareExecutor.ts
4301
+ var AttachmentPostUploadMiddlewareExecutor = class extends MiddlewareExecutor {
4302
+ constructor({ composer }) {
4303
+ super();
4304
+ this.use([
4305
+ createUploadErrorHandlerMiddleware(composer),
4306
+ createPostUploadAttachmentEnrichmentMiddleware()
4307
+ ]);
4308
+ }
4309
+ };
4310
+
4311
+ // src/messageComposer/middleware/attachmentManager/preUpload/serverUploadConfigCheck.ts
4312
+ var createUploadConfigCheckMiddleware = (composer) => ({
4313
+ id: "stream-io/attachment-manager-middleware/file-upload-config-check",
4314
+ handlers: {
4315
+ prepare: async ({
4316
+ state,
4317
+ next,
4318
+ discard
4319
+ }) => {
4320
+ const { attachmentManager } = composer;
4321
+ if (!attachmentManager || !state.attachment) return discard();
4322
+ const uploadPermissionCheck = await attachmentManager.getUploadConfigCheck(
4323
+ state.attachment.localMetadata.file
4324
+ );
4325
+ const attachment = {
4326
+ ...state.attachment,
4327
+ localMetadata: {
4328
+ ...state.attachment.localMetadata,
4329
+ uploadPermissionCheck,
4330
+ uploadState: uploadPermissionCheck.uploadBlocked ? "blocked" : "pending"
4331
+ }
4332
+ };
4333
+ return next({
4334
+ ...state,
4335
+ attachment
4336
+ });
4337
+ }
4338
+ }
4339
+ });
4340
+
4341
+ // src/messageComposer/middleware/attachmentManager/preUpload/blockedUploadNotification.ts
4342
+ var createBlockedAttachmentUploadNotificationMiddleware = (composer) => ({
4343
+ id: "stream-io/attachment-manager-middleware/blocked-upload-notification",
4344
+ handlers: {
4345
+ prepare: ({
4346
+ state: { attachment },
4347
+ forward
4348
+ }) => {
4349
+ if (!attachment) return forward();
4350
+ if (attachment.localMetadata.uploadPermissionCheck?.uploadBlocked) {
4351
+ composer.client.notifications.addError({
4352
+ message: `The attachment upload was blocked`,
4353
+ origin: {
4354
+ emitter: "AttachmentManager",
4355
+ context: { blockedAttachment: attachment }
4356
+ },
4357
+ options: {
4358
+ type: "validation:attachment:upload:blocked",
4359
+ metadata: {
4360
+ reason: attachment.localMetadata.uploadPermissionCheck?.reason
4361
+ }
4362
+ }
4363
+ });
4364
+ }
4365
+ return forward();
4366
+ }
4367
+ }
4368
+ });
4369
+
4370
+ // src/messageComposer/middleware/attachmentManager/preUpload/AttachmentPreUploadMiddlewareExecutor.ts
4371
+ var AttachmentPreUploadMiddlewareExecutor = class extends MiddlewareExecutor {
4372
+ constructor({ composer }) {
4373
+ super();
4374
+ this.use([
4375
+ createUploadConfigCheckMiddleware(composer),
4376
+ createBlockedAttachmentUploadNotificationMiddleware(composer)
4377
+ ]);
4378
+ }
4379
+ };
4380
+
4091
4381
  // src/store.ts
4092
4382
  var isPatch = (value) => typeof value === "function";
4093
4383
  var noop2 = () => {
@@ -4679,7 +4969,7 @@ var initState = ({
4679
4969
  };
4680
4970
  })
4681
4971
  });
4682
- var AttachmentManager = class {
4972
+ var _AttachmentManager = class _AttachmentManager {
4683
4973
  constructor({ composer, message }) {
4684
4974
  this.setCustomUploadFn = (doUploadRequest) => {
4685
4975
  this.composer.updateConfig({ attachments: { doUploadRequest } });
@@ -4786,42 +5076,18 @@ var AttachmentManager = class {
4786
5076
  }
4787
5077
  return { uploadBlocked: false };
4788
5078
  };
5079
+ // @deprecated use AttachmentManager.toLocalUploadAttachment(file)
4789
5080
  this.fileToLocalUploadAttachment = async (fileLike) => {
4790
- const file = isFileReference(fileLike) || isFile2(fileLike) ? fileLike : createFileFromBlobs({
4791
- blobsArray: [fileLike],
4792
- fileName: generateFileName(fileLike.type),
4793
- mimeType: fileLike.type
4794
- });
4795
- const uploadPermissionCheck = await this.getUploadConfigCheck(file);
4796
- const localAttachment = {
4797
- file_size: file.size,
4798
- mime_type: file.type,
4799
- localMetadata: {
4800
- file,
4801
- id: generateUUIDv4(),
4802
- uploadPermissionCheck,
4803
- uploadState: uploadPermissionCheck.uploadBlocked ? "blocked" : "pending"
4804
- },
4805
- type: getAttachmentTypeFromMimeType(file.type)
4806
- };
4807
- localAttachment[isImageFile(file) ? "fallback" : "title"] = file.name;
4808
- if (isImageFile(file)) {
4809
- localAttachment.localMetadata.previewUri = isFileReference(fileLike) ? fileLike.uri : URL.createObjectURL?.(fileLike);
4810
- if (isFileReference(fileLike) && fileLike.height && fileLike.width) {
4811
- localAttachment.original_height = fileLike.height;
4812
- localAttachment.original_width = fileLike.width;
4813
- }
4814
- }
4815
- if (isFileReference(fileLike) && fileLike.thumb_url) {
4816
- localAttachment.thumb_url = fileLike.thumb_url;
4817
- }
4818
- if (isFileReference(fileLike) && fileLike.duration) {
4819
- localAttachment.duration = fileLike.duration;
4820
- }
5081
+ const localAttachment = _AttachmentManager.toLocalUploadAttachment(fileLike);
5082
+ const uploadPermissionCheck = await this.getUploadConfigCheck(
5083
+ localAttachment.localMetadata.file
5084
+ );
5085
+ localAttachment.localMetadata.uploadPermissionCheck = uploadPermissionCheck;
5086
+ localAttachment.localMetadata.uploadState = uploadPermissionCheck.uploadBlocked ? "blocked" : "pending";
4821
5087
  return localAttachment;
4822
5088
  };
4823
5089
  this.ensureLocalUploadAttachment = async (attachment) => {
4824
- if (!attachment.localMetadata?.file || !attachment.localMetadata.id) {
5090
+ if (!attachment.localMetadata?.file) {
4825
5091
  this.client.notifications.addError({
4826
5092
  message: "File is required for upload attachment",
4827
5093
  origin: { emitter: "AttachmentManager", context: { attachment } },
@@ -4829,6 +5095,14 @@ var AttachmentManager = class {
4829
5095
  });
4830
5096
  return;
4831
5097
  }
5098
+ if (!attachment.localMetadata.id) {
5099
+ this.client.notifications.addError({
5100
+ message: "Local upload attachment missing local id",
5101
+ origin: { emitter: "AttachmentManager", context: { attachment } },
5102
+ options: { type: "validation:attachment:id:missing" }
5103
+ });
5104
+ return;
5105
+ }
4832
5106
  if (!this.fileUploadFilter(attachment)) return;
4833
5107
  const newAttachment = await this.fileToLocalUploadAttachment(
4834
5108
  attachment.localMetadata.file
@@ -4868,6 +5142,7 @@ var AttachmentManager = class {
4868
5142
  }
4869
5143
  return this.doDefaultUploadRequest(fileLike);
4870
5144
  };
5145
+ // @deprecated use attachmentManager.uploadFile(file)
4871
5146
  this.uploadAttachment = async (attachment) => {
4872
5147
  if (!this.isUploadEnabled) return;
4873
5148
  const localAttachment = await this.ensureLocalUploadAttachment(attachment);
@@ -4951,19 +5226,75 @@ var AttachmentManager = class {
4951
5226
  this.updateAttachment(uploadedAttachment);
4952
5227
  return uploadedAttachment;
4953
5228
  };
5229
+ this.uploadFile = async (file) => {
5230
+ const preUpload = await this.preUploadMiddlewareExecutor.execute({
5231
+ eventName: "prepare",
5232
+ initialValue: {
5233
+ attachment: _AttachmentManager.toLocalUploadAttachment(file)
5234
+ },
5235
+ mode: "concurrent"
5236
+ });
5237
+ let attachment = preUpload.state.attachment;
5238
+ if (preUpload.status === "discard") return attachment;
5239
+ if (!this.fileUploadFilter(attachment)) return attachment;
5240
+ if (attachment.localMetadata.uploadState === "blocked") {
5241
+ this.upsertAttachments([attachment]);
5242
+ return preUpload.state.attachment;
5243
+ }
5244
+ attachment = {
5245
+ ...attachment,
5246
+ localMetadata: {
5247
+ ...attachment.localMetadata,
5248
+ uploadState: "uploading"
5249
+ }
5250
+ };
5251
+ this.upsertAttachments([attachment]);
5252
+ let response;
5253
+ let error;
5254
+ try {
5255
+ response = await this.doUploadRequest(file);
5256
+ } catch (err) {
5257
+ error = err instanceof Error ? err : void 0;
5258
+ }
5259
+ const postUpload = await this.postUploadMiddlewareExecutor.execute({
5260
+ eventName: "postProcess",
5261
+ initialValue: {
5262
+ attachment: {
5263
+ ...attachment,
5264
+ localMetadata: {
5265
+ ...attachment.localMetadata,
5266
+ uploadState: error ? "failed" : "finished"
5267
+ }
5268
+ },
5269
+ error,
5270
+ response
5271
+ },
5272
+ mode: "concurrent"
5273
+ });
5274
+ attachment = postUpload.state.attachment;
5275
+ if (postUpload.status === "discard") {
5276
+ this.removeAttachments([attachment.localMetadata.id]);
5277
+ return attachment;
5278
+ }
5279
+ this.updateAttachment(attachment);
5280
+ return attachment;
5281
+ };
4954
5282
  this.uploadFiles = async (files) => {
4955
5283
  if (!this.isUploadEnabled) return;
4956
5284
  const iterableFiles = isFileList2(files) ? Array.from(files) : files;
4957
- const attachments = await Promise.all(
4958
- iterableFiles.map(this.fileToLocalUploadAttachment)
4959
- );
4960
- return Promise.all(
4961
- attachments.filter(this.fileUploadFilter).slice(0, this.availableUploadSlots).map(this.uploadAttachment)
5285
+ return await Promise.all(
5286
+ iterableFiles.slice(0, this.availableUploadSlots).map(this.uploadFile)
4962
5287
  );
4963
5288
  };
4964
5289
  this.composer = composer;
4965
5290
  this.state = new StateStore(initState({ message }));
4966
5291
  this.attachmentsByIdGetterCache = { attachmentsById: {}, attachments: [] };
5292
+ this.preUploadMiddlewareExecutor = new AttachmentPreUploadMiddlewareExecutor({
5293
+ composer
5294
+ });
5295
+ this.postUploadMiddlewareExecutor = new AttachmentPostUploadMiddlewareExecutor({
5296
+ composer
5297
+ });
4967
5298
  }
4968
5299
  get attachmentsById() {
4969
5300
  const { attachments } = this.state.getLatestValue();
@@ -4993,9 +5324,15 @@ var AttachmentManager = class {
4993
5324
  set acceptedFiles(acceptedFiles) {
4994
5325
  this.composer.updateConfig({ attachments: { acceptedFiles } });
4995
5326
  }
5327
+ /*
5328
+ @deprecated attachments can be filtered using injecting pre-upload middleware
5329
+ */
4996
5330
  get fileUploadFilter() {
4997
5331
  return this.config.fileUploadFilter;
4998
5332
  }
5333
+ /*
5334
+ @deprecated attachments can be filtered using injecting pre-upload middleware
5335
+ */
4999
5336
  set fileUploadFilter(fileUploadFilter) {
5000
5337
  this.composer.updateConfig({ attachments: { fileUploadFilter } });
5001
5338
  }
@@ -5042,6 +5379,39 @@ var AttachmentManager = class {
5042
5379
  );
5043
5380
  }
5044
5381
  };
5382
+ _AttachmentManager.toLocalUploadAttachment = (fileLike) => {
5383
+ const file = isFileReference(fileLike) || isFile2(fileLike) ? fileLike : createFileFromBlobs({
5384
+ blobsArray: [fileLike],
5385
+ fileName: generateFileName(fileLike.type),
5386
+ mimeType: fileLike.type
5387
+ });
5388
+ const localAttachment = {
5389
+ file_size: file.size,
5390
+ mime_type: file.type,
5391
+ localMetadata: {
5392
+ file,
5393
+ id: generateUUIDv4(),
5394
+ uploadState: "pending"
5395
+ },
5396
+ type: getAttachmentTypeFromMimeType(file.type)
5397
+ };
5398
+ localAttachment[isImageFile(file) ? "fallback" : "title"] = file.name;
5399
+ if (isImageFile(file)) {
5400
+ localAttachment.localMetadata.previewUri = isFileReference(fileLike) ? fileLike.uri : URL.createObjectURL?.(fileLike);
5401
+ if (isFileReference(fileLike) && fileLike.height && fileLike.width) {
5402
+ localAttachment.original_height = fileLike.height;
5403
+ localAttachment.original_width = fileLike.width;
5404
+ }
5405
+ }
5406
+ if (isFileReference(fileLike) && fileLike.thumb_url) {
5407
+ localAttachment.thumb_url = fileLike.thumb_url;
5408
+ }
5409
+ if (isFileReference(fileLike) && fileLike.duration) {
5410
+ localAttachment.duration = fileLike.duration;
5411
+ }
5412
+ return localAttachment;
5413
+ };
5414
+ var AttachmentManager = _AttachmentManager;
5045
5415
 
5046
5416
  // src/messageComposer/configuration/configuration.ts
5047
5417
  var import_linkifyjs = require("linkifyjs");
@@ -5381,146 +5751,6 @@ var LocationComposer = class {
5381
5751
  }
5382
5752
  };
5383
5753
 
5384
- // src/utils/concurrency.ts
5385
- var withoutConcurrency = createRunner(wrapWithContinuationTracking);
5386
- var withCancellation = createRunner(wrapWithCancellation);
5387
- var pendingPromises = /* @__PURE__ */ new Map();
5388
- function createRunner(wrapper) {
5389
- return function run(tag, cb) {
5390
- const { cb: wrapped, onContinued } = wrapper(tag, cb);
5391
- const pending = pendingPromises.get(tag);
5392
- pending?.onContinued();
5393
- const promise = pending ? pending.promise.then(wrapped, wrapped) : wrapped();
5394
- pendingPromises.set(tag, { promise, onContinued });
5395
- return promise;
5396
- };
5397
- }
5398
- function wrapWithContinuationTracking(tag, cb) {
5399
- let hasContinuation = false;
5400
- const wrapped = () => cb().finally(() => {
5401
- if (!hasContinuation) {
5402
- pendingPromises.delete(tag);
5403
- }
5404
- });
5405
- const onContinued = () => hasContinuation = true;
5406
- return { cb: wrapped, onContinued };
5407
- }
5408
- function wrapWithCancellation(tag, cb) {
5409
- const ac = new AbortController();
5410
- const wrapped = () => {
5411
- if (ac.signal.aborted) {
5412
- return Promise.resolve("canceled");
5413
- }
5414
- return cb(ac.signal).finally(() => {
5415
- if (!ac.signal.aborted) {
5416
- pendingPromises.delete(tag);
5417
- }
5418
- });
5419
- };
5420
- const onContinued = () => ac.abort();
5421
- return { cb: wrapped, onContinued };
5422
- }
5423
-
5424
- // src/middleware.ts
5425
- var MiddlewareExecutor = class {
5426
- constructor() {
5427
- this.middleware = [];
5428
- this.id = generateUUIDv4();
5429
- }
5430
- use(middleware) {
5431
- this.middleware = this.middleware.concat(middleware);
5432
- return this;
5433
- }
5434
- // todo: document how to re-arrange the order of middleware using replace
5435
- replace(middleware) {
5436
- const newMiddleware = [...this.middleware];
5437
- middleware.forEach((upserted) => {
5438
- const existingIndex = this.middleware.findIndex(
5439
- (existing) => existing.id === upserted.id
5440
- );
5441
- if (existingIndex >= 0) {
5442
- newMiddleware.splice(existingIndex, 1, upserted);
5443
- } else {
5444
- newMiddleware.push(upserted);
5445
- }
5446
- });
5447
- this.middleware = newMiddleware;
5448
- return this;
5449
- }
5450
- insert({
5451
- middleware,
5452
- position,
5453
- unique
5454
- }) {
5455
- if (unique) {
5456
- middleware.forEach((md) => {
5457
- const existingMiddlewareIndex = this.middleware.findIndex((m) => m.id === md.id);
5458
- if (existingMiddlewareIndex >= 0) {
5459
- this.middleware.splice(existingMiddlewareIndex, 1);
5460
- }
5461
- });
5462
- }
5463
- const targetId = position.after || position.before;
5464
- const targetIndex = this.middleware.findIndex((m) => m.id === targetId);
5465
- const insertionIndex = position.after ? targetIndex + 1 : targetIndex;
5466
- this.middleware.splice(insertionIndex, 0, ...middleware);
5467
- return this;
5468
- }
5469
- setOrder(order) {
5470
- this.middleware = order.map((id) => this.middleware.find((middleware) => middleware.id === id)).filter(Boolean);
5471
- }
5472
- async executeMiddlewareChain({
5473
- eventName,
5474
- initialValue
5475
- }) {
5476
- let index = -1;
5477
- const execute = async (i, state, status) => {
5478
- if (i <= index) {
5479
- throw new Error("next() called multiple times");
5480
- }
5481
- index = i;
5482
- const returnFromChain = i === this.middleware.length || status && ["complete", "discard"].includes(status);
5483
- if (returnFromChain) return { state, status };
5484
- const middleware = this.middleware[i];
5485
- const handler = middleware.handlers[eventName];
5486
- if (!handler) {
5487
- return execute(i + 1, state, status);
5488
- }
5489
- const next = (adjustedState) => execute(i + 1, adjustedState);
5490
- const complete = (adjustedState) => execute(i + 1, adjustedState, "complete");
5491
- const discard = () => execute(i + 1, state, "discard");
5492
- const forward = () => execute(i + 1, state);
5493
- return await handler({
5494
- state,
5495
- next,
5496
- complete,
5497
- discard,
5498
- forward
5499
- });
5500
- };
5501
- const result = await withCancellation(
5502
- `middleware-execution-${this.id}-${eventName}`,
5503
- async (abortSignal) => {
5504
- const result2 = await execute(0, initialValue);
5505
- if (abortSignal.aborted) {
5506
- return "canceled";
5507
- }
5508
- return result2;
5509
- }
5510
- );
5511
- return result === "canceled" ? { state: initialValue, status: "discard" } : result;
5512
- }
5513
- async execute({
5514
- eventName,
5515
- initialValue: initialState
5516
- }) {
5517
- return await this.executeMiddlewareChain({
5518
- eventName,
5519
- initialValue: initialState
5520
- });
5521
- }
5522
- };
5523
-
5524
5754
  // src/messageComposer/middleware/pollComposer/state.ts
5525
5755
  var VALID_MAX_VOTES_VALUE_REGEX = /^([2-9]|10)$/;
5526
5756
  var MAX_POLL_OPTIONS = 100;
@@ -8455,7 +8685,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
8455
8685
  id: this.id,
8456
8686
  mentioned_users: [],
8457
8687
  parent_id: this.threadId ?? void 0,
8458
- pinned_at: null,
8688
+ pinned_at: this.editedMessage?.pinned_at || null,
8459
8689
  reaction_groups: null,
8460
8690
  status: this.editedMessage ? this.editedMessage.status : "sending",
8461
8691
  text,
@@ -15774,7 +16004,7 @@ var StreamChat = class _StreamChat {
15774
16004
  if (this.userAgent) {
15775
16005
  return this.userAgent;
15776
16006
  }
15777
- const version = "9.13.0";
16007
+ const version = "9.14.0";
15778
16008
  const clientBundle = "browser-cjs";
15779
16009
  let userAgentString = "";
15780
16010
  if (this.sdkIdentifier) {