stream-chat 9.41.1 → 9.42.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.
- package/dist/cjs/index.browser.js +181 -65
- package/dist/cjs/index.browser.js.map +4 -4
- package/dist/cjs/index.node.js +182 -65
- package/dist/cjs/index.node.js.map +4 -4
- package/dist/esm/index.mjs +181 -65
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/client.d.ts +5 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/messageComposer/LocationComposer.d.ts +1 -1
- package/dist/types/messageComposer/attachmentManager.d.ts +1 -0
- package/dist/types/messageComposer/configuration/types.d.ts +6 -1
- package/dist/types/messageComposer/fileUtils.d.ts +1 -1
- package/dist/types/messageComposer/messageComposer.d.ts +4 -4
- package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +2 -2
- package/dist/types/messageComposer/pollComposer.d.ts +2 -2
- package/dist/types/messageComposer/textComposer.d.ts +2 -2
- package/dist/types/uploadManager.d.ts +45 -0
- package/dist/types/utils.d.ts +3 -3
- package/package.json +2 -2
- package/src/client.ts +7 -0
- package/src/index.ts +1 -0
- package/src/messageComposer/attachmentManager.ts +65 -69
- package/src/messageComposer/configuration/types.ts +6 -1
- package/src/messageComposer/messageComposer.ts +0 -9
- package/src/uploadManager.ts +176 -0
package/dist/esm/index.mjs
CHANGED
|
@@ -3110,11 +3110,11 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3110
3110
|
return attachments;
|
|
3111
3111
|
}
|
|
3112
3112
|
}
|
|
3113
|
-
return
|
|
3113
|
+
return stateAttachments;
|
|
3114
3114
|
};
|
|
3115
3115
|
this.updateAttachment = (attachmentToUpdate) => {
|
|
3116
3116
|
const updatedAttachments = this.prepareAttachmentUpdate(attachmentToUpdate);
|
|
3117
|
-
if (updatedAttachments) {
|
|
3117
|
+
if (updatedAttachments && updatedAttachments !== this.attachments) {
|
|
3118
3118
|
this.state.partialNext({ attachments: updatedAttachments });
|
|
3119
3119
|
}
|
|
3120
3120
|
};
|
|
@@ -3124,15 +3124,15 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3124
3124
|
let hasUpdates = false;
|
|
3125
3125
|
attachmentsToUpsert.forEach((attachment) => {
|
|
3126
3126
|
const updatedAttachments = this.prepareAttachmentUpdate(attachment);
|
|
3127
|
-
if (updatedAttachments) {
|
|
3128
|
-
attachments = updatedAttachments;
|
|
3129
|
-
hasUpdates = true;
|
|
3130
|
-
} else {
|
|
3127
|
+
if (updatedAttachments === null) {
|
|
3131
3128
|
const localAttachment = ensureIsLocalAttachment(attachment);
|
|
3132
3129
|
if (localAttachment) {
|
|
3133
3130
|
attachments.push(localAttachment);
|
|
3134
3131
|
hasUpdates = true;
|
|
3135
3132
|
}
|
|
3133
|
+
} else if (updatedAttachments !== this.attachments) {
|
|
3134
|
+
attachments = updatedAttachments;
|
|
3135
|
+
hasUpdates = true;
|
|
3136
3136
|
}
|
|
3137
3137
|
});
|
|
3138
3138
|
if (hasUpdates) {
|
|
@@ -3140,11 +3140,15 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3140
3140
|
}
|
|
3141
3141
|
};
|
|
3142
3142
|
this.removeAttachments = (localAttachmentIds) => {
|
|
3143
|
+
if (!localAttachmentIds.length) return;
|
|
3143
3144
|
this.state.partialNext({
|
|
3144
3145
|
attachments: this.attachments.filter(
|
|
3145
3146
|
(attachment) => !localAttachmentIds.includes(attachment.localMetadata?.id)
|
|
3146
3147
|
)
|
|
3147
3148
|
});
|
|
3149
|
+
for (const id of localAttachmentIds) {
|
|
3150
|
+
this.client.uploadManager.deleteUploadRecord(id);
|
|
3151
|
+
}
|
|
3148
3152
|
};
|
|
3149
3153
|
this.getUploadConfigCheck = async (fileLike) => {
|
|
3150
3154
|
const client = this.channel.getClient();
|
|
@@ -3233,13 +3237,17 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3233
3237
|
const percent = progressEvent.lengthComputable && progressEvent.total ? Math.round(progressEvent.loaded * 100 / progressEvent.total) : void 0;
|
|
3234
3238
|
options.onProgress?.(percent);
|
|
3235
3239
|
} : void 0;
|
|
3240
|
+
const axiosUploadConfig = progressHandler || options?.abortSignal ? {
|
|
3241
|
+
...progressHandler ? { onUploadProgress: progressHandler } : {},
|
|
3242
|
+
...options?.abortSignal ? { signal: options.abortSignal } : {}
|
|
3243
|
+
} : void 0;
|
|
3236
3244
|
if (isFileReference(fileLike)) {
|
|
3237
3245
|
return this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](
|
|
3238
3246
|
fileLike.uri,
|
|
3239
3247
|
fileLike.name,
|
|
3240
3248
|
fileLike.type,
|
|
3241
3249
|
void 0,
|
|
3242
|
-
|
|
3250
|
+
axiosUploadConfig
|
|
3243
3251
|
);
|
|
3244
3252
|
}
|
|
3245
3253
|
const file = isFile(fileLike) ? fileLike : createFileFromBlobs({
|
|
@@ -3247,13 +3255,7 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3247
3255
|
fileName: generateFileName(fileLike.type),
|
|
3248
3256
|
mimeType: fileLike.type
|
|
3249
3257
|
});
|
|
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
|
-
);
|
|
3258
|
+
const { duration, ...result } = await this.channel[isImageFile(fileLike) ? "sendImage" : "sendFile"](file, void 0, void 0, void 0, axiosUploadConfig);
|
|
3257
3259
|
return result;
|
|
3258
3260
|
};
|
|
3259
3261
|
/**
|
|
@@ -3288,33 +3290,9 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3288
3290
|
});
|
|
3289
3291
|
return localAttachment;
|
|
3290
3292
|
}
|
|
3291
|
-
const shouldTrackProgress = this.config.trackUploadProgress;
|
|
3292
|
-
const uploadingAttachment = {
|
|
3293
|
-
...attachment,
|
|
3294
|
-
localMetadata: {
|
|
3295
|
-
...attachment.localMetadata,
|
|
3296
|
-
uploadState: "uploading",
|
|
3297
|
-
...shouldTrackProgress && { uploadProgress: 0 }
|
|
3298
|
-
}
|
|
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;
|
|
3312
3293
|
let response;
|
|
3313
3294
|
try {
|
|
3314
|
-
response = await this.
|
|
3315
|
-
localAttachment.localMetadata.file,
|
|
3316
|
-
uploadOptions
|
|
3317
|
-
);
|
|
3295
|
+
response = await this.upload(attachment);
|
|
3318
3296
|
} catch (error) {
|
|
3319
3297
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
3320
3298
|
const failedAttachment = {
|
|
@@ -3383,31 +3361,10 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3383
3361
|
this.upsertAttachments([attachment]);
|
|
3384
3362
|
return preUpload.state.attachment;
|
|
3385
3363
|
}
|
|
3386
|
-
const shouldTrackProgress = this.config.trackUploadProgress;
|
|
3387
|
-
attachment = {
|
|
3388
|
-
...attachment,
|
|
3389
|
-
localMetadata: {
|
|
3390
|
-
...attachment.localMetadata,
|
|
3391
|
-
uploadState: "uploading",
|
|
3392
|
-
...shouldTrackProgress && { uploadProgress: 0 }
|
|
3393
|
-
}
|
|
3394
|
-
};
|
|
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;
|
|
3407
3364
|
let response;
|
|
3408
3365
|
let error;
|
|
3409
3366
|
try {
|
|
3410
|
-
response = await this.
|
|
3367
|
+
response = await this.upload(attachment);
|
|
3411
3368
|
} catch (err) {
|
|
3412
3369
|
error = err instanceof Error ? err : void 0;
|
|
3413
3370
|
}
|
|
@@ -3534,6 +3491,40 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3534
3491
|
({ localMetadata }) => localMetadata.uploadState === state
|
|
3535
3492
|
);
|
|
3536
3493
|
}
|
|
3494
|
+
upload(attachment) {
|
|
3495
|
+
const localId = attachment.localMetadata.id;
|
|
3496
|
+
this.upsertAttachments([
|
|
3497
|
+
{
|
|
3498
|
+
...attachment,
|
|
3499
|
+
localMetadata: {
|
|
3500
|
+
...attachment.localMetadata,
|
|
3501
|
+
uploadState: "uploading",
|
|
3502
|
+
uploadProgress: this.config.trackUploadProgress ? 0 : void 0
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
]);
|
|
3506
|
+
const unsubscribe = this.client.uploadManager.state.subscribeWithSelector(
|
|
3507
|
+
(s) => ({ upload: s.uploads[localId] }),
|
|
3508
|
+
({ upload: nextUpload }) => {
|
|
3509
|
+
if (!nextUpload) return;
|
|
3510
|
+
this.updateAttachment({
|
|
3511
|
+
...attachment,
|
|
3512
|
+
localMetadata: {
|
|
3513
|
+
...attachment.localMetadata,
|
|
3514
|
+
uploadState: "uploading",
|
|
3515
|
+
uploadProgress: nextUpload.uploadProgress
|
|
3516
|
+
}
|
|
3517
|
+
});
|
|
3518
|
+
}
|
|
3519
|
+
);
|
|
3520
|
+
return this.client.uploadManager.upload({
|
|
3521
|
+
id: localId,
|
|
3522
|
+
channelCid: this.channel.cid,
|
|
3523
|
+
file: attachment.localMetadata.file
|
|
3524
|
+
}).finally(() => {
|
|
3525
|
+
unsubscribe();
|
|
3526
|
+
});
|
|
3527
|
+
}
|
|
3537
3528
|
};
|
|
3538
3529
|
_AttachmentManager.toLocalUploadAttachment = (fileLike) => {
|
|
3539
3530
|
const file = isFileReference(fileLike) || isFile(fileLike) ? fileLike : createFileFromBlobs({
|
|
@@ -7386,9 +7377,6 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7386
7377
|
return this.state.getLatestValue().showReplyInChannel;
|
|
7387
7378
|
}
|
|
7388
7379
|
get hasSendableData() {
|
|
7389
|
-
if (this.client.offlineDb) {
|
|
7390
|
-
return !this.textComposer.textIsEmpty || !!this.attachmentManager.attachments.length || !!this.pollId || !!this.locationComposer.validLocation;
|
|
7391
|
-
}
|
|
7392
7380
|
return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId || !!this.locationComposer.validLocation);
|
|
7393
7381
|
}
|
|
7394
7382
|
get compositionIsEmpty() {
|
|
@@ -10410,6 +10398,131 @@ var StableWSConnection = class {
|
|
|
10410
10398
|
}
|
|
10411
10399
|
};
|
|
10412
10400
|
|
|
10401
|
+
// src/uploadManager.ts
|
|
10402
|
+
var initState7 = () => ({ uploads: {} });
|
|
10403
|
+
var upsertById = (uploads, record) => ({
|
|
10404
|
+
...uploads,
|
|
10405
|
+
[record.id]: { ...uploads[record.id], ...record }
|
|
10406
|
+
});
|
|
10407
|
+
var updateById = (uploads, record) => {
|
|
10408
|
+
if (!(record.id in uploads)) return null;
|
|
10409
|
+
const current = uploads[record.id];
|
|
10410
|
+
return { ...uploads, [record.id]: { ...current, ...record } };
|
|
10411
|
+
};
|
|
10412
|
+
var UploadManager = class {
|
|
10413
|
+
constructor(client) {
|
|
10414
|
+
this.client = client;
|
|
10415
|
+
this.inFlightUploads = /* @__PURE__ */ new Map();
|
|
10416
|
+
this.getUpload = (id) => this.uploads[id];
|
|
10417
|
+
/**
|
|
10418
|
+
* Clears all upload records.
|
|
10419
|
+
* Invoked when the user disconnects so a later session does not inherit stale upload state.
|
|
10420
|
+
* Aborts every in-flight upload request via its `UploadRequestOptions.abortSignal`.
|
|
10421
|
+
*/
|
|
10422
|
+
this.reset = () => {
|
|
10423
|
+
for (const { abortController } of this.inFlightUploads.values()) {
|
|
10424
|
+
abortController.abort();
|
|
10425
|
+
}
|
|
10426
|
+
this.inFlightUploads.clear();
|
|
10427
|
+
this.state.next(initState7());
|
|
10428
|
+
};
|
|
10429
|
+
/**
|
|
10430
|
+
* Removes the upload record for `id` if present.
|
|
10431
|
+
* If an upload is still in progress, aborts its `UploadRequestOptions.abortSignal`.
|
|
10432
|
+
*/
|
|
10433
|
+
this.deleteUploadRecord = (id) => {
|
|
10434
|
+
const flight = this.inFlightUploads.get(id);
|
|
10435
|
+
if (flight) {
|
|
10436
|
+
this.inFlightUploads.delete(id);
|
|
10437
|
+
flight.abortController.abort();
|
|
10438
|
+
}
|
|
10439
|
+
this.state.next((current) => {
|
|
10440
|
+
if (!(id in current.uploads)) return current;
|
|
10441
|
+
const uploads = { ...current.uploads };
|
|
10442
|
+
delete uploads[id];
|
|
10443
|
+
return { ...current, uploads };
|
|
10444
|
+
});
|
|
10445
|
+
};
|
|
10446
|
+
/**
|
|
10447
|
+
* Starts an upload for `id`, or returns the existing in-flight promise if one is already running.
|
|
10448
|
+
* Uses {@link StreamChat.channel}(`channelCid`) → `messageComposer.attachmentManager.doUploadRequest`.
|
|
10449
|
+
* Resolves with that result; rejects if the upload rejects (the record is removed from state either way).
|
|
10450
|
+
*/
|
|
10451
|
+
this.upload = ({
|
|
10452
|
+
id,
|
|
10453
|
+
channelCid,
|
|
10454
|
+
file
|
|
10455
|
+
}) => {
|
|
10456
|
+
const existing = this.inFlightUploads.get(id);
|
|
10457
|
+
if (existing) return existing.promise;
|
|
10458
|
+
let resolvePromise;
|
|
10459
|
+
let rejectPromise;
|
|
10460
|
+
const promise = new Promise((resolve, reject) => {
|
|
10461
|
+
resolvePromise = resolve;
|
|
10462
|
+
rejectPromise = reject;
|
|
10463
|
+
});
|
|
10464
|
+
const abortController = new AbortController();
|
|
10465
|
+
this.inFlightUploads.set(id, { promise, abortController });
|
|
10466
|
+
void (async () => {
|
|
10467
|
+
const attachmentManager = this.resolveAttachmentManager(channelCid);
|
|
10468
|
+
const trackProgress = attachmentManager.config.trackUploadProgress;
|
|
10469
|
+
try {
|
|
10470
|
+
this.upsertUpload({
|
|
10471
|
+
id,
|
|
10472
|
+
uploadProgress: trackProgress ? 0 : void 0
|
|
10473
|
+
});
|
|
10474
|
+
const onProgress = trackProgress ? (progress) => {
|
|
10475
|
+
this.updateUpload({
|
|
10476
|
+
id,
|
|
10477
|
+
uploadProgress: progress
|
|
10478
|
+
});
|
|
10479
|
+
} : void 0;
|
|
10480
|
+
const uploadRequestOptions = {
|
|
10481
|
+
abortSignal: abortController.signal,
|
|
10482
|
+
...onProgress ? { onProgress } : {}
|
|
10483
|
+
};
|
|
10484
|
+
const response = await attachmentManager.doUploadRequest(
|
|
10485
|
+
file,
|
|
10486
|
+
uploadRequestOptions
|
|
10487
|
+
);
|
|
10488
|
+
resolvePromise(response);
|
|
10489
|
+
} catch (error) {
|
|
10490
|
+
rejectPromise(error);
|
|
10491
|
+
} finally {
|
|
10492
|
+
this.inFlightUploads.delete(id);
|
|
10493
|
+
this.deleteUploadRecord(id);
|
|
10494
|
+
}
|
|
10495
|
+
})();
|
|
10496
|
+
return promise;
|
|
10497
|
+
};
|
|
10498
|
+
this.upsertUpload = (record) => {
|
|
10499
|
+
this.state.partialNext({
|
|
10500
|
+
uploads: upsertById(this.uploads, record)
|
|
10501
|
+
});
|
|
10502
|
+
};
|
|
10503
|
+
this.updateUpload = (record) => {
|
|
10504
|
+
this.state.next((current) => {
|
|
10505
|
+
const nextUploads = updateById(current.uploads, record);
|
|
10506
|
+
if (!nextUploads) return current;
|
|
10507
|
+
return { ...current, uploads: nextUploads };
|
|
10508
|
+
});
|
|
10509
|
+
};
|
|
10510
|
+
this.state = new StateStore(initState7());
|
|
10511
|
+
}
|
|
10512
|
+
resolveAttachmentManager(channelCid) {
|
|
10513
|
+
const colon = channelCid.indexOf(":");
|
|
10514
|
+
if (colon <= 0 || colon === channelCid.length - 1) {
|
|
10515
|
+
throw new Error(`Invalid channelCid: ${channelCid}`);
|
|
10516
|
+
}
|
|
10517
|
+
const channelType = channelCid.slice(0, colon);
|
|
10518
|
+
const channelId = channelCid.slice(colon + 1);
|
|
10519
|
+
return this.client.channel(channelType, channelId).messageComposer.attachmentManager;
|
|
10520
|
+
}
|
|
10521
|
+
get uploads() {
|
|
10522
|
+
return this.state.getLatestValue().uploads;
|
|
10523
|
+
}
|
|
10524
|
+
};
|
|
10525
|
+
|
|
10413
10526
|
// src/signing.ts
|
|
10414
10527
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken());
|
|
10415
10528
|
var import_crypto = __toESM(require_crypto());
|
|
@@ -12882,6 +12995,7 @@ var StreamChat = class _StreamChat {
|
|
|
12882
12995
|
this.activeChannels = {};
|
|
12883
12996
|
this.state = new ClientState({ client: this });
|
|
12884
12997
|
this.threads.resetState();
|
|
12998
|
+
this.uploadManager.reset();
|
|
12885
12999
|
closePromise.finally(() => {
|
|
12886
13000
|
this.tokenManager.reset();
|
|
12887
13001
|
}).catch((err) => console.error(err));
|
|
@@ -13288,6 +13402,7 @@ var StreamChat = class _StreamChat {
|
|
|
13288
13402
|
this.blockedUsers = new StateStore({ userIds: [] });
|
|
13289
13403
|
this.moderation = new Moderation(this);
|
|
13290
13404
|
this.notifications = options?.notifications ?? new NotificationManager();
|
|
13405
|
+
this.uploadManager = new UploadManager(this);
|
|
13291
13406
|
if (secretOrOptions && isString2(secretOrOptions)) {
|
|
13292
13407
|
this.secret = secretOrOptions;
|
|
13293
13408
|
}
|
|
@@ -15077,7 +15192,7 @@ var StreamChat = class _StreamChat {
|
|
|
15077
15192
|
if (this.userAgent) {
|
|
15078
15193
|
return this.userAgent;
|
|
15079
15194
|
}
|
|
15080
|
-
const version = "9.
|
|
15195
|
+
const version = "9.42.1";
|
|
15081
15196
|
const clientBundle = "browser-esm";
|
|
15082
15197
|
let userAgentString = "";
|
|
15083
15198
|
if (this.sdkIdentifier) {
|
|
@@ -17766,6 +17881,7 @@ export {
|
|
|
17766
17881
|
ThreadManager,
|
|
17767
17882
|
TokenManager,
|
|
17768
17883
|
UPDATE_LIVE_LOCATION_REQUEST_MIN_THROTTLE_TIMEOUT,
|
|
17884
|
+
UploadManager,
|
|
17769
17885
|
UserFromToken,
|
|
17770
17886
|
UserSearchSource,
|
|
17771
17887
|
VALID_MAX_VOTES_VALUE_REGEX,
|