stream-chat 9.50.3 → 9.52.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.
- package/dist/cjs/index.browser.js +601 -275
- package/dist/cjs/index.browser.js.map +4 -4
- package/dist/cjs/index.node.js +610 -276
- package/dist/cjs/index.node.js.map +4 -4
- package/dist/esm/index.mjs +599 -273
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/channel.d.ts +4 -3
- package/dist/types/client.d.ts +23 -9
- package/dist/types/index.d.ts +7 -0
- package/dist/types/messageComposer/attachmentIdentity.d.ts +4 -0
- package/dist/types/messageComposer/attachmentManager.d.ts +8 -0
- package/dist/types/messageComposer/messageComposer.d.ts +13 -0
- package/dist/types/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.d.ts +20 -1
- package/dist/types/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.d.ts +6 -1
- package/dist/types/messageComposer/middleware/messageComposer/attachments.d.ts +24 -0
- package/dist/types/messageComposer/middleware/messageComposer/types.d.ts +22 -1
- package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +15 -9
- package/dist/types/messageComposer/types.d.ts +5 -0
- package/dist/types/middleware.d.ts +8 -0
- package/dist/types/offline-support/offline_support_api.d.ts +7 -1
- package/dist/types/offline-support/offline_sync_manager.d.ts +12 -1
- package/dist/types/search/BaseSearchSource.d.ts +42 -24
- package/dist/types/search/ChannelMemberSearchSource.d.ts +9 -4
- package/dist/types/search/ChannelSearchSource.d.ts +9 -3
- package/dist/types/search/MessageSearchSource.d.ts +14 -3
- package/dist/types/search/UserSearchSource.d.ts +9 -3
- package/dist/types/search/types.d.ts +14 -1
- package/dist/types/types.d.ts +12 -1
- package/dist/types/uploadManager.d.ts +30 -0
- package/dist/types/utils.d.ts +21 -2
- package/package.json +7 -7
- package/src/channel.ts +20 -8
- package/src/client.ts +71 -13
- package/src/index.ts +12 -0
- package/src/messageComposer/attachmentIdentity.ts +27 -0
- package/src/messageComposer/attachmentManager.ts +61 -12
- package/src/messageComposer/messageComposer.ts +43 -8
- package/src/messageComposer/middleware/attachmentManager/postUpload/AttachmentPostUploadMiddlewareExecutor.ts +1 -1
- package/src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts +58 -33
- package/src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts +4 -0
- package/src/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.ts +9 -0
- package/src/messageComposer/middleware/messageComposer/attachments.ts +109 -0
- package/src/messageComposer/middleware/messageComposer/types.ts +22 -1
- package/src/messageComposer/middleware/textComposer/mentions.ts +75 -23
- package/src/messageComposer/types.ts +5 -0
- package/src/middleware.ts +11 -0
- package/src/offline-support/offline_support_api.ts +21 -2
- package/src/offline-support/offline_sync_manager.ts +36 -8
- package/src/search/BaseSearchSource.ts +123 -39
- package/src/search/ChannelMemberSearchSource.ts +22 -11
- package/src/search/ChannelSearchSource.ts +16 -5
- package/src/search/MessageSearchSource.ts +36 -4
- package/src/search/UserSearchSource.ts +16 -5
- package/src/search/types.ts +14 -1
- package/src/types.ts +13 -1
- package/src/uploadManager.ts +45 -0
- package/src/utils.ts +78 -3
package/dist/esm/index.mjs
CHANGED
|
@@ -316,7 +316,7 @@ var ChannelBatchUpdater = class {
|
|
|
316
316
|
|
|
317
317
|
// src/client.ts
|
|
318
318
|
var import_https = __toESM(require_https());
|
|
319
|
-
import
|
|
319
|
+
import axios4 from "axios";
|
|
320
320
|
|
|
321
321
|
// src/utils.ts
|
|
322
322
|
import FormData from "form-data";
|
|
@@ -575,6 +575,38 @@ function unformatMessage(message) {
|
|
|
575
575
|
quoted_message: toMessageResponseBase(message.quoted_message)
|
|
576
576
|
};
|
|
577
577
|
}
|
|
578
|
+
var isRemoteUrl = (url) => !!url && /^https?:\/\//i.test(url.trim());
|
|
579
|
+
var sanitizeOutgoingAttachments = ({
|
|
580
|
+
client,
|
|
581
|
+
message
|
|
582
|
+
}) => {
|
|
583
|
+
const attachments = message.attachments;
|
|
584
|
+
if (!attachments?.length) return message;
|
|
585
|
+
const unresolved = [];
|
|
586
|
+
let changed = false;
|
|
587
|
+
const sanitized = attachments.reduce((acc, attachment) => {
|
|
588
|
+
const { localMetadata, ...rest } = attachment;
|
|
589
|
+
if (!localMetadata) {
|
|
590
|
+
acc.push(attachment);
|
|
591
|
+
return acc;
|
|
592
|
+
}
|
|
593
|
+
changed = true;
|
|
594
|
+
const hasRemoteSource = isRemoteUrl(rest.asset_url) || isRemoteUrl(rest.image_url) || isRemoteUrl(rest.og_scrape_url) || isRemoteUrl(rest.title_link);
|
|
595
|
+
if (hasRemoteSource) {
|
|
596
|
+
acc.push(rest);
|
|
597
|
+
} else {
|
|
598
|
+
unresolved.push(rest);
|
|
599
|
+
}
|
|
600
|
+
return acc;
|
|
601
|
+
}, []);
|
|
602
|
+
if (unresolved.length) {
|
|
603
|
+
const text = `Dropped ${unresolved.length} attachment(s) whose upload never completed. Composing with pending uploads requires awaiting them before sending.`;
|
|
604
|
+
const extraData = { attachments: unresolved, message, tags: ["attachments"] };
|
|
605
|
+
client.logger("warn", text, extraData);
|
|
606
|
+
console.warn(text, extraData);
|
|
607
|
+
}
|
|
608
|
+
return changed ? { ...message, attachments: sanitized } : message;
|
|
609
|
+
};
|
|
578
610
|
var localMessageToNewMessagePayload = (localMessage) => {
|
|
579
611
|
const {
|
|
580
612
|
// Remove all timestamp fields and client-specific fields.
|
|
@@ -783,7 +815,8 @@ var debounce = (fn, timeout = 0, { leading = false, trailing = true } = {}) => {
|
|
|
783
815
|
}
|
|
784
816
|
runningTimeout = null;
|
|
785
817
|
};
|
|
786
|
-
|
|
818
|
+
const delay = typeof timeout === "function" ? timeout(...args) : timeout;
|
|
819
|
+
runningTimeout = setTimeout(timeoutHandler, delay);
|
|
787
820
|
return lastResult;
|
|
788
821
|
};
|
|
789
822
|
debouncedFn.cancel = () => {
|
|
@@ -2346,6 +2379,12 @@ var CooldownTimer = class extends WithSubscriptions {
|
|
|
2346
2379
|
var isScrapedContent = (attachment) => !!attachment?.og_scrape_url || !!attachment?.title_link;
|
|
2347
2380
|
var isLocalAttachment = (attachment) => !!attachment?.localMetadata?.id;
|
|
2348
2381
|
var isLocalUploadAttachment = (attachment) => !!attachment?.localMetadata?.uploadState;
|
|
2382
|
+
var PENDING_UPLOAD_STATES = [
|
|
2383
|
+
"pending",
|
|
2384
|
+
"uploading"
|
|
2385
|
+
];
|
|
2386
|
+
var isPendingUpload = (attachment) => isLocalUploadAttachment(attachment) && PENDING_UPLOAD_STATES.includes(attachment.localMetadata.uploadState);
|
|
2387
|
+
var isFinishedUpload = (attachment) => isLocalUploadAttachment(attachment) && attachment.localMetadata.uploadState === "finished";
|
|
2349
2388
|
var isFileAttachment = (attachment, supportedVideoFormat = []) => attachment.type === "file" || !!(attachment.mime_type && supportedVideoFormat.indexOf(attachment.mime_type) === -1 && attachment.type !== "video");
|
|
2350
2389
|
var isLocalFileAttachment = (attachment) => isFileAttachment(attachment) && isLocalAttachment(attachment);
|
|
2351
2390
|
var isImageAttachment = (attachment) => attachment.type === "image" && !isScrapedContent(attachment);
|
|
@@ -2421,7 +2460,7 @@ var ensureIsLocalAttachment = (attachment) => {
|
|
|
2421
2460
|
};
|
|
2422
2461
|
|
|
2423
2462
|
// src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts
|
|
2424
|
-
var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
2463
|
+
var createPostUploadAttachmentEnrichmentMiddleware = (composer) => ({
|
|
2425
2464
|
id: "stream-io/attachment-manager-middleware/post-upload-enrichment",
|
|
2426
2465
|
handlers: {
|
|
2427
2466
|
postProcess: ({
|
|
@@ -2434,9 +2473,10 @@ var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
|
2434
2473
|
if (error) return forward();
|
|
2435
2474
|
if (!attachment || !response) return discard();
|
|
2436
2475
|
const enrichedAttachment = { ...attachment };
|
|
2437
|
-
const previewUri = attachment.localMetadata
|
|
2438
|
-
|
|
2439
|
-
|
|
2476
|
+
const { id, previewUri } = attachment.localMetadata;
|
|
2477
|
+
const attachmentIsStillInComposer = !composer || !!composer.attachmentManager.attachmentsById[id];
|
|
2478
|
+
if (previewUri && attachmentIsStillInComposer) {
|
|
2479
|
+
if (previewUri.startsWith("blob:")) URL.revokeObjectURL?.(previewUri);
|
|
2440
2480
|
delete enrichedAttachment.localMetadata.previewUri;
|
|
2441
2481
|
}
|
|
2442
2482
|
if (isLocalImageAttachment(attachment)) {
|
|
@@ -2459,6 +2499,12 @@ var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
|
2459
2499
|
var withoutConcurrency = createRunner(wrapWithContinuationTracking);
|
|
2460
2500
|
var withCancellation = createRunner(wrapWithCancellation);
|
|
2461
2501
|
var pendingPromises = /* @__PURE__ */ new Map();
|
|
2502
|
+
function hasPending(tag) {
|
|
2503
|
+
return pendingPromises.has(tag);
|
|
2504
|
+
}
|
|
2505
|
+
async function settled(tag) {
|
|
2506
|
+
await pendingPromises.get(tag)?.promise;
|
|
2507
|
+
}
|
|
2462
2508
|
function createRunner(wrapper) {
|
|
2463
2509
|
return function run(tag, cb) {
|
|
2464
2510
|
const { cb: wrapped, onContinued } = wrapper(tag, cb);
|
|
@@ -2501,6 +2547,16 @@ var MiddlewareExecutor = class {
|
|
|
2501
2547
|
this.middleware = [];
|
|
2502
2548
|
this.id = generateUUIDv4();
|
|
2503
2549
|
}
|
|
2550
|
+
/**
|
|
2551
|
+
* The middleware currently installed, in execution order.
|
|
2552
|
+
*
|
|
2553
|
+
* Read-only: use `use` / `insert` / `replace` / `setOrder` / `remove` to change the chain. It
|
|
2554
|
+
* exists so components can ask what the chain is capable of - a middleware may declare
|
|
2555
|
+
* behaviour its host has to account for, and the host has no other way to find out.
|
|
2556
|
+
*/
|
|
2557
|
+
get installedMiddleware() {
|
|
2558
|
+
return this.middleware;
|
|
2559
|
+
}
|
|
2504
2560
|
use(middleware) {
|
|
2505
2561
|
this.middleware = this.middleware.concat(middleware);
|
|
2506
2562
|
return this;
|
|
@@ -2604,6 +2660,142 @@ var MiddlewareExecutor = class {
|
|
|
2604
2660
|
}
|
|
2605
2661
|
};
|
|
2606
2662
|
|
|
2663
|
+
// src/uploadManager.ts
|
|
2664
|
+
import axios from "axios";
|
|
2665
|
+
var isUploadCancellation = (error) => axios.isCancel(error) || error instanceof Error && error.name === "AbortError";
|
|
2666
|
+
var initState = () => ({ uploads: {} });
|
|
2667
|
+
var upsertById = (uploads, record) => ({
|
|
2668
|
+
...uploads,
|
|
2669
|
+
[record.id]: { ...uploads[record.id], ...record }
|
|
2670
|
+
});
|
|
2671
|
+
var updateById = (uploads, record) => {
|
|
2672
|
+
if (!(record.id in uploads)) return null;
|
|
2673
|
+
const current = uploads[record.id];
|
|
2674
|
+
return { ...uploads, [record.id]: { ...current, ...record } };
|
|
2675
|
+
};
|
|
2676
|
+
var UploadManager = class {
|
|
2677
|
+
constructor(client) {
|
|
2678
|
+
this.client = client;
|
|
2679
|
+
this.inFlightUploads = /* @__PURE__ */ new Map();
|
|
2680
|
+
this.getUpload = (id) => this.uploads[id];
|
|
2681
|
+
/**
|
|
2682
|
+
* Clears all upload records.
|
|
2683
|
+
* Invoked when the user disconnects so a later session does not inherit stale upload state.
|
|
2684
|
+
* Aborts every in-flight upload request via its `UploadRequestOptions.abortSignal`.
|
|
2685
|
+
*/
|
|
2686
|
+
this.reset = () => {
|
|
2687
|
+
for (const { abortController } of this.inFlightUploads.values()) {
|
|
2688
|
+
abortController.abort();
|
|
2689
|
+
}
|
|
2690
|
+
this.inFlightUploads.clear();
|
|
2691
|
+
this.state.next(initState());
|
|
2692
|
+
};
|
|
2693
|
+
/**
|
|
2694
|
+
* Removes the upload record for `id` if present.
|
|
2695
|
+
* If an upload is still in progress, aborts its `UploadRequestOptions.abortSignal`.
|
|
2696
|
+
*/
|
|
2697
|
+
this.deleteUploadRecord = (id) => {
|
|
2698
|
+
const flight = this.inFlightUploads.get(id);
|
|
2699
|
+
if (flight) {
|
|
2700
|
+
this.inFlightUploads.delete(id);
|
|
2701
|
+
flight.abortController.abort();
|
|
2702
|
+
}
|
|
2703
|
+
this.state.next((current) => {
|
|
2704
|
+
if (!(id in current.uploads)) return current;
|
|
2705
|
+
const uploads = { ...current.uploads };
|
|
2706
|
+
delete uploads[id];
|
|
2707
|
+
return { ...current, uploads };
|
|
2708
|
+
});
|
|
2709
|
+
};
|
|
2710
|
+
/**
|
|
2711
|
+
* Starts an upload for `id`, or returns the existing in-flight promise if one is already running.
|
|
2712
|
+
* Uses {@link StreamChat.channel}(`channelCid`) → `messageComposer.attachmentManager.doUploadRequest`.
|
|
2713
|
+
* Resolves with that result; rejects if the upload rejects (the record is removed from state either way).
|
|
2714
|
+
*/
|
|
2715
|
+
this.upload = ({
|
|
2716
|
+
id,
|
|
2717
|
+
channelCid,
|
|
2718
|
+
file
|
|
2719
|
+
}) => {
|
|
2720
|
+
const existing = this.inFlightUploads.get(id);
|
|
2721
|
+
if (existing) return existing.promise;
|
|
2722
|
+
let resolvePromise;
|
|
2723
|
+
let rejectPromise;
|
|
2724
|
+
const promise = new Promise((resolve, reject) => {
|
|
2725
|
+
resolvePromise = resolve;
|
|
2726
|
+
rejectPromise = reject;
|
|
2727
|
+
});
|
|
2728
|
+
const abortController = new AbortController();
|
|
2729
|
+
this.inFlightUploads.set(id, { promise, abortController });
|
|
2730
|
+
void (async () => {
|
|
2731
|
+
const attachmentManager = this.resolveAttachmentManager(channelCid);
|
|
2732
|
+
const trackProgress = attachmentManager.config.trackUploadProgress;
|
|
2733
|
+
try {
|
|
2734
|
+
this.upsertUpload({
|
|
2735
|
+
uploadConfirmationPending: false,
|
|
2736
|
+
id,
|
|
2737
|
+
uploadProgress: trackProgress ? 0 : void 0
|
|
2738
|
+
});
|
|
2739
|
+
const onProgress = trackProgress ? (progress) => {
|
|
2740
|
+
this.updateUpload({
|
|
2741
|
+
id,
|
|
2742
|
+
uploadProgress: progress,
|
|
2743
|
+
// Only a number says anything about the flush, so a report without one leaves
|
|
2744
|
+
// the flag alone: `undefined` means the transport cannot measure this upload,
|
|
2745
|
+
// not that bytes were un-sent. Lowering it there would drop a UI that had
|
|
2746
|
+
// already gone indeterminate back to a determinate one with nothing to show.
|
|
2747
|
+
//
|
|
2748
|
+
// The record is removed in the `finally` below, so a record that still exists
|
|
2749
|
+
// while reporting 100% can only mean "flushed, awaiting the response".
|
|
2750
|
+
...typeof progress === "number" ? { uploadConfirmationPending: progress >= 100 } : {}
|
|
2751
|
+
});
|
|
2752
|
+
} : void 0;
|
|
2753
|
+
const uploadRequestOptions = {
|
|
2754
|
+
abortSignal: abortController.signal,
|
|
2755
|
+
...onProgress ? { onProgress } : {}
|
|
2756
|
+
};
|
|
2757
|
+
const response = await attachmentManager.doUploadRequest(
|
|
2758
|
+
file,
|
|
2759
|
+
uploadRequestOptions
|
|
2760
|
+
);
|
|
2761
|
+
resolvePromise(response);
|
|
2762
|
+
} catch (error) {
|
|
2763
|
+
rejectPromise(error);
|
|
2764
|
+
} finally {
|
|
2765
|
+
this.inFlightUploads.delete(id);
|
|
2766
|
+
this.deleteUploadRecord(id);
|
|
2767
|
+
}
|
|
2768
|
+
})();
|
|
2769
|
+
return promise;
|
|
2770
|
+
};
|
|
2771
|
+
this.upsertUpload = (record) => {
|
|
2772
|
+
this.state.partialNext({
|
|
2773
|
+
uploads: upsertById(this.uploads, record)
|
|
2774
|
+
});
|
|
2775
|
+
};
|
|
2776
|
+
this.updateUpload = (record) => {
|
|
2777
|
+
this.state.next((current) => {
|
|
2778
|
+
const nextUploads = updateById(current.uploads, record);
|
|
2779
|
+
if (!nextUploads) return current;
|
|
2780
|
+
return { ...current, uploads: nextUploads };
|
|
2781
|
+
});
|
|
2782
|
+
};
|
|
2783
|
+
this.state = new StateStore(initState());
|
|
2784
|
+
}
|
|
2785
|
+
resolveAttachmentManager(channelCid) {
|
|
2786
|
+
const colon = channelCid.indexOf(":");
|
|
2787
|
+
if (colon <= 0 || colon === channelCid.length - 1) {
|
|
2788
|
+
throw new Error(`Invalid channelCid: ${channelCid}`);
|
|
2789
|
+
}
|
|
2790
|
+
const channelType = channelCid.slice(0, colon);
|
|
2791
|
+
const channelId = channelCid.slice(colon + 1);
|
|
2792
|
+
return this.client.channel(channelType, channelId).messageComposer.attachmentManager;
|
|
2793
|
+
}
|
|
2794
|
+
get uploads() {
|
|
2795
|
+
return this.state.getLatestValue().uploads;
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2798
|
+
|
|
2607
2799
|
// src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts
|
|
2608
2800
|
var createUploadErrorHandlerMiddleware = (composer) => ({
|
|
2609
2801
|
id: "stream-io/attachment-manager-middleware/upload-error",
|
|
@@ -2616,6 +2808,7 @@ var createUploadErrorHandlerMiddleware = (composer) => ({
|
|
|
2616
2808
|
const { attachment, error } = state;
|
|
2617
2809
|
if (!error) return forward();
|
|
2618
2810
|
if (!attachment) return discard();
|
|
2811
|
+
if (isUploadCancellation(error)) return forward();
|
|
2619
2812
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2620
2813
|
composer.client.notifications.addError({
|
|
2621
2814
|
message: "Error uploading attachment",
|
|
@@ -2640,7 +2833,7 @@ var AttachmentPostUploadMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
|
2640
2833
|
super();
|
|
2641
2834
|
this.use([
|
|
2642
2835
|
createUploadErrorHandlerMiddleware(composer),
|
|
2643
|
-
createPostUploadAttachmentEnrichmentMiddleware()
|
|
2836
|
+
createPostUploadAttachmentEnrichmentMiddleware(composer)
|
|
2644
2837
|
]);
|
|
2645
2838
|
}
|
|
2646
2839
|
};
|
|
@@ -3088,7 +3281,7 @@ function mergeWithDiff(target, source, customizer) {
|
|
|
3088
3281
|
}
|
|
3089
3282
|
|
|
3090
3283
|
// src/messageComposer/attachmentManager.ts
|
|
3091
|
-
var
|
|
3284
|
+
var initState2 = ({
|
|
3092
3285
|
message
|
|
3093
3286
|
}) => ({
|
|
3094
3287
|
attachments: (message?.attachments ?? [])?.filter(({ og_scrape_url }) => !og_scrape_url).map((att) => {
|
|
@@ -3116,13 +3309,14 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3116
3309
|
...attachment,
|
|
3117
3310
|
localMetadata: {
|
|
3118
3311
|
...attachment.localMetadata,
|
|
3312
|
+
uploadConfirmationPending: false,
|
|
3119
3313
|
uploadProgress: void 0,
|
|
3120
3314
|
uploadState: "failed"
|
|
3121
3315
|
}
|
|
3122
3316
|
};
|
|
3123
3317
|
};
|
|
3124
3318
|
this.initState = ({ message } = {}) => {
|
|
3125
|
-
this.state.next(
|
|
3319
|
+
this.state.next(initState2({ message }));
|
|
3126
3320
|
};
|
|
3127
3321
|
this.getSnapshot = () => {
|
|
3128
3322
|
const state = this.state.getLatestValue();
|
|
@@ -3199,8 +3393,22 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3199
3393
|
this.state.partialNext({ attachments });
|
|
3200
3394
|
}
|
|
3201
3395
|
};
|
|
3396
|
+
/**
|
|
3397
|
+
* Releases a local preview URL the SDK minted, if it minted one.
|
|
3398
|
+
*
|
|
3399
|
+
* Only `blob:` URLs are ours to revoke: `toLocalUploadAttachment` puts a
|
|
3400
|
+
* `URL.createObjectURL` result in `previewUri` for a `File`, but for a React Native
|
|
3401
|
+
* `FileReference` it stores the caller's own native file URI, which must be left alone.
|
|
3402
|
+
*/
|
|
3403
|
+
this.revokePreviewUri = (attachment) => {
|
|
3404
|
+
const previewUri = attachment.localMetadata?.previewUri;
|
|
3405
|
+
if (previewUri?.startsWith("blob:")) URL.revokeObjectURL?.(previewUri);
|
|
3406
|
+
};
|
|
3202
3407
|
this.removeAttachments = (localAttachmentIds) => {
|
|
3203
3408
|
if (!localAttachmentIds.length) return;
|
|
3409
|
+
const removedAttachments = this.attachments.filter(
|
|
3410
|
+
(attachment) => localAttachmentIds.includes(attachment.localMetadata?.id)
|
|
3411
|
+
);
|
|
3204
3412
|
this.state.partialNext({
|
|
3205
3413
|
attachments: this.attachments.filter(
|
|
3206
3414
|
(attachment) => !localAttachmentIds.includes(attachment.localMetadata?.id)
|
|
@@ -3209,6 +3417,7 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3209
3417
|
for (const id of localAttachmentIds) {
|
|
3210
3418
|
this.client.uploadManager.deleteUploadRecord(id);
|
|
3211
3419
|
}
|
|
3420
|
+
removedAttachments.forEach(this.revokePreviewUri);
|
|
3212
3421
|
};
|
|
3213
3422
|
this.getUploadConfigCheck = async (fileLike) => {
|
|
3214
3423
|
const client = this.channel.getClient();
|
|
@@ -3360,21 +3569,27 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3360
3569
|
localMetadata: {
|
|
3361
3570
|
...attachment.localMetadata,
|
|
3362
3571
|
uploadState: "failed",
|
|
3363
|
-
uploadProgress: void 0
|
|
3572
|
+
uploadProgress: void 0,
|
|
3573
|
+
// `false`, not `undefined`: these updates go through `updateAttachment`, which merges
|
|
3574
|
+
// via `mergeWith` — and that skips `undefined` source values, so `undefined` would
|
|
3575
|
+
// leave a stale `true` in place.
|
|
3576
|
+
uploadConfirmationPending: false
|
|
3364
3577
|
}
|
|
3365
3578
|
};
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3579
|
+
if (!isUploadCancellation(error)) {
|
|
3580
|
+
this.client.notifications.addError({
|
|
3581
|
+
message: "Error uploading attachment",
|
|
3582
|
+
origin: {
|
|
3583
|
+
emitter: "AttachmentManager",
|
|
3584
|
+
context: { attachment, failedAttachment }
|
|
3585
|
+
},
|
|
3586
|
+
options: {
|
|
3587
|
+
type: "api:attachment:upload:failed",
|
|
3588
|
+
metadata: { reason },
|
|
3589
|
+
originalError: error instanceof Error ? error : void 0
|
|
3590
|
+
}
|
|
3591
|
+
});
|
|
3592
|
+
}
|
|
3378
3593
|
this.updateAttachment(failedAttachment);
|
|
3379
3594
|
return failedAttachment;
|
|
3380
3595
|
}
|
|
@@ -3387,7 +3602,9 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3387
3602
|
localMetadata: {
|
|
3388
3603
|
...attachment.localMetadata,
|
|
3389
3604
|
uploadState: "finished",
|
|
3390
|
-
uploadProgress: void 0
|
|
3605
|
+
uploadProgress: void 0,
|
|
3606
|
+
// See the note in the failure branch: `undefined` cannot clear through `mergeWith`.
|
|
3607
|
+
uploadConfirmationPending: false
|
|
3391
3608
|
}
|
|
3392
3609
|
};
|
|
3393
3610
|
const previewUri = uploadedAttachment.localMetadata.previewUri;
|
|
@@ -3436,7 +3653,9 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3436
3653
|
localMetadata: {
|
|
3437
3654
|
...attachment.localMetadata,
|
|
3438
3655
|
uploadState: error ? "failed" : "finished",
|
|
3439
|
-
uploadProgress: void 0
|
|
3656
|
+
uploadProgress: void 0,
|
|
3657
|
+
// See the note in `uploadAttachment`: `undefined` cannot clear through `mergeWith`.
|
|
3658
|
+
uploadConfirmationPending: false
|
|
3440
3659
|
}
|
|
3441
3660
|
},
|
|
3442
3661
|
error,
|
|
@@ -3461,7 +3680,7 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3461
3680
|
);
|
|
3462
3681
|
};
|
|
3463
3682
|
this.composer = composer;
|
|
3464
|
-
this.state = new StateStore(
|
|
3683
|
+
this.state = new StateStore(initState2({ message }));
|
|
3465
3684
|
this.attachmentsByIdGetterCache = { attachmentsById: {}, attachments: [] };
|
|
3466
3685
|
this.preUploadMiddlewareExecutor = new AttachmentPreUploadMiddlewareExecutor({
|
|
3467
3686
|
composer
|
|
@@ -3566,7 +3785,8 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3566
3785
|
localMetadata: {
|
|
3567
3786
|
...attachment.localMetadata,
|
|
3568
3787
|
uploadState: "uploading",
|
|
3569
|
-
uploadProgress: this.config.trackUploadProgress ? 0 : void 0
|
|
3788
|
+
uploadProgress: this.config.trackUploadProgress ? 0 : void 0,
|
|
3789
|
+
uploadConfirmationPending: false
|
|
3570
3790
|
}
|
|
3571
3791
|
}
|
|
3572
3792
|
]);
|
|
@@ -3579,7 +3799,8 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3579
3799
|
localMetadata: {
|
|
3580
3800
|
...attachment.localMetadata,
|
|
3581
3801
|
uploadState: "uploading",
|
|
3582
|
-
uploadProgress: nextUpload.uploadProgress
|
|
3802
|
+
uploadProgress: nextUpload.uploadProgress,
|
|
3803
|
+
uploadConfirmationPending: nextUpload.uploadConfirmationPending
|
|
3583
3804
|
}
|
|
3584
3805
|
});
|
|
3585
3806
|
}
|
|
@@ -3633,6 +3854,50 @@ var localAttachmentToAttachment = (localAttachment) => {
|
|
|
3633
3854
|
const { localMetadata, ...attachment } = localAttachment;
|
|
3634
3855
|
return attachment;
|
|
3635
3856
|
};
|
|
3857
|
+
var composeWithPendingUploads = ({
|
|
3858
|
+
composer,
|
|
3859
|
+
state
|
|
3860
|
+
}) => {
|
|
3861
|
+
const composerIsKeptAsDraft = !!composer.pollId;
|
|
3862
|
+
const relevantAttachments = composer.attachmentManager.attachments.filter(
|
|
3863
|
+
(attachment) => isFinishedUpload(attachment) || !composerIsKeptAsDraft && isPendingUpload(attachment)
|
|
3864
|
+
);
|
|
3865
|
+
const localAttachments = (state.localMessage.attachments ?? []).concat(
|
|
3866
|
+
relevantAttachments.map(
|
|
3867
|
+
(attachment) => isPendingUpload(attachment) ? attachment : localAttachmentToAttachment(attachment)
|
|
3868
|
+
)
|
|
3869
|
+
);
|
|
3870
|
+
const messageAttachments = (state.message.attachments ?? []).concat(
|
|
3871
|
+
relevantAttachments.filter(isFinishedUpload).map(localAttachmentToAttachment)
|
|
3872
|
+
);
|
|
3873
|
+
if (!localAttachments.length && !messageAttachments.length) return state;
|
|
3874
|
+
return {
|
|
3875
|
+
...state,
|
|
3876
|
+
localMessage: localAttachments.length ? {
|
|
3877
|
+
...state.localMessage,
|
|
3878
|
+
attachments: localAttachments
|
|
3879
|
+
} : state.localMessage,
|
|
3880
|
+
message: messageAttachments.length ? {
|
|
3881
|
+
...state.message,
|
|
3882
|
+
attachments: messageAttachments
|
|
3883
|
+
} : state.message
|
|
3884
|
+
};
|
|
3885
|
+
};
|
|
3886
|
+
var createSendWithPendingUploadsAttachmentsMiddleware = (composer) => ({
|
|
3887
|
+
allowsPendingUploads: true,
|
|
3888
|
+
id: "stream-io/message-composer-middleware/attachments",
|
|
3889
|
+
handlers: {
|
|
3890
|
+
compose: ({
|
|
3891
|
+
state,
|
|
3892
|
+
next,
|
|
3893
|
+
forward
|
|
3894
|
+
}) => {
|
|
3895
|
+
const { attachmentManager } = composer;
|
|
3896
|
+
if (!attachmentManager) return forward();
|
|
3897
|
+
return next(composeWithPendingUploads({ composer, state }));
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
});
|
|
3636
3901
|
var createAttachmentsCompositionMiddleware = (composer) => ({
|
|
3637
3902
|
id: "stream-io/message-composer-middleware/attachments",
|
|
3638
3903
|
handlers: {
|
|
@@ -3849,7 +4114,7 @@ var getInitialMentions = (message) => {
|
|
|
3849
4114
|
};
|
|
3850
4115
|
var isSameMentionEntity = (first, second) => first.id === second.id && first.mentionType === second.mentionType;
|
|
3851
4116
|
var getMentionsFromState = (state) => state.mentions ?? state.mentionedUsers.map(userResponseToMentionEntity);
|
|
3852
|
-
var
|
|
4117
|
+
var initState3 = ({
|
|
3853
4118
|
composer,
|
|
3854
4119
|
message
|
|
3855
4120
|
}) => {
|
|
@@ -3878,7 +4143,7 @@ var initState2 = ({
|
|
|
3878
4143
|
var TextComposer = class {
|
|
3879
4144
|
constructor({ composer, message }) {
|
|
3880
4145
|
this.initState = ({ message } = {}) => {
|
|
3881
|
-
this.state.next(
|
|
4146
|
+
this.state.next(initState3({ composer: this.composer, message }));
|
|
3882
4147
|
};
|
|
3883
4148
|
this.getSnapshot = (state = this.state.getLatestValue()) => state;
|
|
3884
4149
|
this.restoreSnapshot = (snapshot) => {
|
|
@@ -4071,7 +4336,7 @@ var TextComposer = class {
|
|
|
4071
4336
|
this.commitState(output.state);
|
|
4072
4337
|
};
|
|
4073
4338
|
this.composer = composer;
|
|
4074
|
-
this.state = new StateStore(
|
|
4339
|
+
this.state = new StateStore(initState3({ composer, message }));
|
|
4075
4340
|
this.middlewareExecutor = new TextComposerMiddlewareExecutor({ composer });
|
|
4076
4341
|
}
|
|
4077
4342
|
get channel() {
|
|
@@ -4221,13 +4486,41 @@ function isErrorResponse(res) {
|
|
|
4221
4486
|
|
|
4222
4487
|
// src/search/BaseSearchSource.ts
|
|
4223
4488
|
var DEFAULT_SEARCH_SOURCE_OPTIONS = {
|
|
4224
|
-
debounceMs: 300,
|
|
4225
4489
|
pageSize: 10,
|
|
4226
4490
|
allowEmptySearchString: false,
|
|
4227
4491
|
resetOnNewSearchQuery: true
|
|
4228
4492
|
};
|
|
4493
|
+
var resolveDebounceOptions = ({
|
|
4494
|
+
debounceMs,
|
|
4495
|
+
shortQueryDebounceMs,
|
|
4496
|
+
longQueryDebounceMs,
|
|
4497
|
+
shortQueryMaxLength
|
|
4498
|
+
}) => ({
|
|
4499
|
+
shortQueryDebounceMs: shortQueryDebounceMs ?? debounceMs ?? 500,
|
|
4500
|
+
longQueryDebounceMs: longQueryDebounceMs ?? debounceMs ?? 300,
|
|
4501
|
+
shortQueryMaxLength: shortQueryMaxLength ?? 2
|
|
4502
|
+
});
|
|
4229
4503
|
var BaseSearchSourceBase = class {
|
|
4230
4504
|
constructor(options) {
|
|
4505
|
+
this.setDebounceOptions = (options = {}) => {
|
|
4506
|
+
const resolved = resolveDebounceOptions(options);
|
|
4507
|
+
this.shortQueryDebounceMs = resolved.shortQueryDebounceMs;
|
|
4508
|
+
this.longQueryDebounceMs = resolved.longQueryDebounceMs;
|
|
4509
|
+
this.shortQueryMaxLength = resolved.shortQueryMaxLength;
|
|
4510
|
+
this.searchDebounced = debounce(
|
|
4511
|
+
this.executeQuery.bind(this),
|
|
4512
|
+
(searchString) => this.getDebounceMs(searchString)
|
|
4513
|
+
);
|
|
4514
|
+
};
|
|
4515
|
+
/**
|
|
4516
|
+
* Short queries match too much and are slow server-side, so they get a longer debounce.
|
|
4517
|
+
* Resolved per call, which is what lets the interval switch as the user keeps typing.
|
|
4518
|
+
*/
|
|
4519
|
+
this.getDebounceMs = (searchString) => {
|
|
4520
|
+
const { length } = searchString ?? this.searchQuery;
|
|
4521
|
+
return length <= this.shortQueryMaxLength ? this.shortQueryDebounceMs : this.longQueryDebounceMs;
|
|
4522
|
+
};
|
|
4523
|
+
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
4231
4524
|
this.activate = () => {
|
|
4232
4525
|
if (this.isActive) return;
|
|
4233
4526
|
this.state.partialNext({ isActive: true });
|
|
@@ -4239,7 +4532,7 @@ var BaseSearchSourceBase = class {
|
|
|
4239
4532
|
this.canExecuteQuery = (newSearchString) => {
|
|
4240
4533
|
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
4241
4534
|
const searchString = newSearchString ?? this.searchQuery;
|
|
4242
|
-
return !!(this.isActive &&
|
|
4535
|
+
return !!(this.isActive && this.canDispatchQuery(hasNewSearchQuery) && (this.allowEmptySearchString || searchString));
|
|
4243
4536
|
};
|
|
4244
4537
|
const { pageSize, allowEmptySearchString, resetOnNewSearchQuery } = {
|
|
4245
4538
|
...DEFAULT_SEARCH_SOURCE_OPTIONS,
|
|
@@ -4249,6 +4542,14 @@ var BaseSearchSourceBase = class {
|
|
|
4249
4542
|
this.allowEmptySearchString = allowEmptySearchString;
|
|
4250
4543
|
this.resetOnNewSearchQuery = resetOnNewSearchQuery;
|
|
4251
4544
|
this.state = new StateStore(this.initialState);
|
|
4545
|
+
this.setDebounceOptions(options ?? {});
|
|
4546
|
+
}
|
|
4547
|
+
/**
|
|
4548
|
+
* A new search query preempts an in-flight one; pagination waits for it to finish
|
|
4549
|
+
* and needs a next page to fetch.
|
|
4550
|
+
*/
|
|
4551
|
+
canDispatchQuery(hasNewSearchQuery) {
|
|
4552
|
+
return hasNewSearchQuery || !this.isLoading && this.hasNext;
|
|
4252
4553
|
}
|
|
4253
4554
|
get lastQueryError() {
|
|
4254
4555
|
return this.state.getLatestValue().lastQueryError;
|
|
@@ -4343,21 +4644,30 @@ var BaseSearchSourceBase = class {
|
|
|
4343
4644
|
}
|
|
4344
4645
|
};
|
|
4345
4646
|
var BaseSearchSource = class extends BaseSearchSourceBase {
|
|
4346
|
-
constructor(
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
this.
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
this.
|
|
4647
|
+
constructor() {
|
|
4648
|
+
super(...arguments);
|
|
4649
|
+
/** Aborts the in-flight request, if any, once a newer query is dispatched. */
|
|
4650
|
+
this.queryAbortController = null;
|
|
4651
|
+
}
|
|
4652
|
+
/** Aborts the in-flight request, if any. Returns true when one was aborted. */
|
|
4653
|
+
abortInFlightQuery() {
|
|
4654
|
+
if (!this.queryAbortController) return false;
|
|
4655
|
+
this.queryAbortController.abort();
|
|
4656
|
+
this.queryAbortController = null;
|
|
4657
|
+
return true;
|
|
4658
|
+
}
|
|
4659
|
+
resetState() {
|
|
4660
|
+
this.abortInFlightQuery();
|
|
4661
|
+
super.resetState();
|
|
4354
4662
|
}
|
|
4355
4663
|
async executeQuery(newSearchString) {
|
|
4356
4664
|
if (!this.canExecuteQuery(newSearchString)) return;
|
|
4665
|
+
this.abortInFlightQuery();
|
|
4666
|
+
const { signal } = this.queryAbortController = new AbortController();
|
|
4357
4667
|
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
4358
4668
|
let stateUpdate = {};
|
|
4359
4669
|
try {
|
|
4360
|
-
const results = await this.query(searchString);
|
|
4670
|
+
const results = await this.query(searchString, { signal });
|
|
4361
4671
|
if (!results) return;
|
|
4362
4672
|
const { items } = results;
|
|
4363
4673
|
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
@@ -4368,23 +4678,19 @@ var BaseSearchSource = class extends BaseSearchSourceBase {
|
|
|
4368
4678
|
stateUpdate.hasNext = false;
|
|
4369
4679
|
}
|
|
4370
4680
|
} finally {
|
|
4371
|
-
|
|
4681
|
+
if (!signal.aborted) {
|
|
4682
|
+
this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
|
|
4683
|
+
}
|
|
4372
4684
|
}
|
|
4373
4685
|
}
|
|
4374
4686
|
cancelScheduledQuery() {
|
|
4375
4687
|
this.searchDebounced.cancel();
|
|
4688
|
+
if (this.abortInFlightQuery() && this.isLoading) {
|
|
4689
|
+
this.state.partialNext({ isLoading: false });
|
|
4690
|
+
}
|
|
4376
4691
|
}
|
|
4377
4692
|
};
|
|
4378
4693
|
var BaseSearchSourceSync = class extends BaseSearchSourceBase {
|
|
4379
|
-
constructor(options) {
|
|
4380
|
-
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
4381
|
-
super(options);
|
|
4382
|
-
this.setDebounceOptions = ({ debounceMs }) => {
|
|
4383
|
-
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
4384
|
-
};
|
|
4385
|
-
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
4386
|
-
this.setDebounceOptions({ debounceMs });
|
|
4387
|
-
}
|
|
4388
4694
|
executeQuery(newSearchString) {
|
|
4389
4695
|
if (!this.canExecuteQuery(newSearchString)) return;
|
|
4390
4696
|
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
@@ -4680,13 +4986,13 @@ var UserGroupPaginator = class extends BasePaginator {
|
|
|
4680
4986
|
// src/search/ChannelMemberSearchSource.ts
|
|
4681
4987
|
var ChannelMemberSearchSource = class extends BaseSearchSource {
|
|
4682
4988
|
constructor(channel, options, filterBuilderOptions = {}) {
|
|
4683
|
-
|
|
4989
|
+
const { filters, sort, searchOptions, ...restOptions } = options || {};
|
|
4990
|
+
super({ ...restOptions, allowEmptySearchString: true });
|
|
4684
4991
|
this.type = "members";
|
|
4685
|
-
this.canExecuteQuery = (newSearchString) => {
|
|
4686
|
-
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
4687
|
-
return this.isActive && !this.isLoading && (this.hasNext || hasNewSearchQuery);
|
|
4688
|
-
};
|
|
4689
4992
|
this.channel = channel;
|
|
4993
|
+
this.filters = filters;
|
|
4994
|
+
this.sort = sort;
|
|
4995
|
+
this.searchOptions = searchOptions;
|
|
4690
4996
|
this.filterBuilder = new FilterBuilder({
|
|
4691
4997
|
initialFilterConfig: {
|
|
4692
4998
|
default: {
|
|
@@ -4702,7 +5008,7 @@ var ChannelMemberSearchSource = class extends BaseSearchSource {
|
|
|
4702
5008
|
...filterBuilderOptions
|
|
4703
5009
|
});
|
|
4704
5010
|
}
|
|
4705
|
-
async query(searchQuery) {
|
|
5011
|
+
async query(searchQuery, queryOptions = {}) {
|
|
4706
5012
|
const filters = this.filterBuilder.buildFilters({
|
|
4707
5013
|
baseFilters: this.filters,
|
|
4708
5014
|
context: {
|
|
@@ -4711,7 +5017,12 @@ var ChannelMemberSearchSource = class extends BaseSearchSource {
|
|
|
4711
5017
|
});
|
|
4712
5018
|
const sort = this.sort ?? [];
|
|
4713
5019
|
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
|
|
4714
|
-
const { members } = await this.channel.queryMembers(
|
|
5020
|
+
const { members } = await this.channel.queryMembers(
|
|
5021
|
+
filters ?? {},
|
|
5022
|
+
sort,
|
|
5023
|
+
options,
|
|
5024
|
+
queryOptions
|
|
5025
|
+
);
|
|
4715
5026
|
return { items: members };
|
|
4716
5027
|
}
|
|
4717
5028
|
filterQueryResults(items) {
|
|
@@ -4826,9 +5137,13 @@ var SearchController = class {
|
|
|
4826
5137
|
// src/search/UserSearchSource.ts
|
|
4827
5138
|
var UserSearchSource = class extends BaseSearchSource {
|
|
4828
5139
|
constructor(client, options, filterBuilderOptions = {}) {
|
|
4829
|
-
|
|
5140
|
+
const { filters, sort, searchOptions, ...restOptions } = options || {};
|
|
5141
|
+
super(restOptions);
|
|
4830
5142
|
this.type = "users";
|
|
4831
5143
|
this.client = client;
|
|
5144
|
+
this.filters = filters;
|
|
5145
|
+
this.sort = sort;
|
|
5146
|
+
this.searchOptions = searchOptions;
|
|
4832
5147
|
this.filterBuilder = new FilterBuilder({
|
|
4833
5148
|
initialFilterConfig: {
|
|
4834
5149
|
$or: {
|
|
@@ -4844,7 +5159,7 @@ var UserSearchSource = class extends BaseSearchSource {
|
|
|
4844
5159
|
...filterBuilderOptions
|
|
4845
5160
|
});
|
|
4846
5161
|
}
|
|
4847
|
-
async query(searchQuery) {
|
|
5162
|
+
async query(searchQuery, queryOptions = {}) {
|
|
4848
5163
|
const filters = this.filterBuilder.buildFilters({
|
|
4849
5164
|
baseFilters: this.filters,
|
|
4850
5165
|
context: { searchQuery }
|
|
@@ -4857,7 +5172,7 @@ var UserSearchSource = class extends BaseSearchSource {
|
|
|
4857
5172
|
sort = { id: 1, ...this.sort };
|
|
4858
5173
|
}
|
|
4859
5174
|
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
|
|
4860
|
-
const { users } = await this.client.queryUsers(filters, sort, options);
|
|
5175
|
+
const { users } = await this.client.queryUsers(filters, sort, options, queryOptions);
|
|
4861
5176
|
return { items: users };
|
|
4862
5177
|
}
|
|
4863
5178
|
filterQueryResults(items) {
|
|
@@ -4868,9 +5183,13 @@ var UserSearchSource = class extends BaseSearchSource {
|
|
|
4868
5183
|
// src/search/ChannelSearchSource.ts
|
|
4869
5184
|
var ChannelSearchSource = class extends BaseSearchSource {
|
|
4870
5185
|
constructor(client, options, filterBuilderOptions = {}) {
|
|
4871
|
-
|
|
5186
|
+
const { filters, sort, searchOptions, ...restOptions } = options || {};
|
|
5187
|
+
super(restOptions);
|
|
4872
5188
|
this.type = "channels";
|
|
4873
5189
|
this.client = client;
|
|
5190
|
+
this.filters = filters;
|
|
5191
|
+
this.sort = sort;
|
|
5192
|
+
this.searchOptions = searchOptions;
|
|
4874
5193
|
this.filterBuilder = new FilterBuilder({
|
|
4875
5194
|
...filterBuilderOptions,
|
|
4876
5195
|
initialFilterConfig: {
|
|
@@ -4882,7 +5201,7 @@ var ChannelSearchSource = class extends BaseSearchSource {
|
|
|
4882
5201
|
}
|
|
4883
5202
|
});
|
|
4884
5203
|
}
|
|
4885
|
-
async query(searchQuery) {
|
|
5204
|
+
async query(searchQuery, queryOptions = {}) {
|
|
4886
5205
|
const filters = this.filterBuilder.buildFilters({
|
|
4887
5206
|
baseFilters: {
|
|
4888
5207
|
...this.client.userID ? { members: { $in: [this.client.userID] } } : {},
|
|
@@ -4892,7 +5211,7 @@ var ChannelSearchSource = class extends BaseSearchSource {
|
|
|
4892
5211
|
});
|
|
4893
5212
|
const sort = this.sort ?? {};
|
|
4894
5213
|
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
|
|
4895
|
-
const items = await this.client.queryChannels(filters, sort, options);
|
|
5214
|
+
const items = await this.client.queryChannels(filters, sort, options, queryOptions);
|
|
4896
5215
|
return { items };
|
|
4897
5216
|
}
|
|
4898
5217
|
filterQueryResults(items) {
|
|
@@ -4903,9 +5222,24 @@ var ChannelSearchSource = class extends BaseSearchSource {
|
|
|
4903
5222
|
// src/search/MessageSearchSource.ts
|
|
4904
5223
|
var MessageSearchSource = class extends BaseSearchSource {
|
|
4905
5224
|
constructor(client, options, filterBuilderOptions) {
|
|
4906
|
-
|
|
5225
|
+
const {
|
|
5226
|
+
messageSearchChannelFilters,
|
|
5227
|
+
messageSearchFilters,
|
|
5228
|
+
messageSearchSort,
|
|
5229
|
+
channelQueryFilters,
|
|
5230
|
+
channelQuerySort,
|
|
5231
|
+
channelQueryOptions,
|
|
5232
|
+
...restOptions
|
|
5233
|
+
} = options || {};
|
|
5234
|
+
super(restOptions);
|
|
4907
5235
|
this.type = "messages";
|
|
4908
5236
|
this.client = client;
|
|
5237
|
+
this.messageSearchChannelFilters = messageSearchChannelFilters;
|
|
5238
|
+
this.messageSearchFilters = messageSearchFilters;
|
|
5239
|
+
this.messageSearchSort = messageSearchSort;
|
|
5240
|
+
this.channelQueryFilters = channelQueryFilters;
|
|
5241
|
+
this.channelQuerySort = channelQuerySort;
|
|
5242
|
+
this.channelQueryOptions = channelQueryOptions;
|
|
4909
5243
|
this.messageSearchChannelFilterBuilder = new FilterBuilder(filterBuilderOptions?.messageSearchChannel);
|
|
4910
5244
|
this.messageSearchFilterBuilder = new FilterBuilder({
|
|
4911
5245
|
...filterBuilderOptions?.messageSearch,
|
|
@@ -4928,7 +5262,7 @@ var MessageSearchSource = class extends BaseSearchSource {
|
|
|
4928
5262
|
}
|
|
4929
5263
|
});
|
|
4930
5264
|
}
|
|
4931
|
-
async query(searchQuery) {
|
|
5265
|
+
async query(searchQuery, queryOptions = {}) {
|
|
4932
5266
|
if (!this.client.userID || this.next === null) return { items: [] };
|
|
4933
5267
|
const channelFilters = this.messageSearchChannelFilterBuilder.buildFilters({
|
|
4934
5268
|
baseFilters: {
|
|
@@ -4956,9 +5290,11 @@ var MessageSearchSource = class extends BaseSearchSource {
|
|
|
4956
5290
|
const { next, results } = await this.client.search(
|
|
4957
5291
|
channelFilters,
|
|
4958
5292
|
messageFilters,
|
|
4959
|
-
options
|
|
5293
|
+
options,
|
|
5294
|
+
queryOptions
|
|
4960
5295
|
);
|
|
4961
5296
|
const items = results.map(({ message }) => message);
|
|
5297
|
+
if (queryOptions.signal?.aborted) return { items, next };
|
|
4962
5298
|
const cids = Array.from(
|
|
4963
5299
|
items.reduce((acc, message) => {
|
|
4964
5300
|
if (message.cid && !this.client.activeChannels[message.cid]) acc.add(message.cid);
|
|
@@ -4976,7 +5312,8 @@ var MessageSearchSource = class extends BaseSearchSource {
|
|
|
4976
5312
|
last_message_at: -1,
|
|
4977
5313
|
...this.channelQuerySort
|
|
4978
5314
|
},
|
|
4979
|
-
this.channelQueryOptions
|
|
5315
|
+
this.channelQueryOptions,
|
|
5316
|
+
queryOptions
|
|
4980
5317
|
);
|
|
4981
5318
|
}
|
|
4982
5319
|
return { items, next };
|
|
@@ -5701,6 +6038,13 @@ var MessageComposerMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
|
5701
6038
|
createCompositionDataCleanupMiddleware(composer)
|
|
5702
6039
|
]);
|
|
5703
6040
|
}
|
|
6041
|
+
/**
|
|
6042
|
+
* Narrows the base accessor to the composition middleware type, so callers can read the
|
|
6043
|
+
* declarations it carries (`allowsPendingUploads`) without casting.
|
|
6044
|
+
*/
|
|
6045
|
+
get installedMiddleware() {
|
|
6046
|
+
return super.installedMiddleware;
|
|
6047
|
+
}
|
|
5704
6048
|
};
|
|
5705
6049
|
var MessageDraftComposerMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
5706
6050
|
constructor({ composer }) {
|
|
@@ -6270,13 +6614,18 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6270
6614
|
constructor(channel, options) {
|
|
6271
6615
|
const {
|
|
6272
6616
|
mentionAllAppUsers,
|
|
6617
|
+
memberFilters,
|
|
6618
|
+
memberSort,
|
|
6619
|
+
searchOptions,
|
|
6273
6620
|
suggestionFactoryMappers,
|
|
6274
6621
|
textComposerText,
|
|
6275
6622
|
transliterate,
|
|
6276
6623
|
trigger,
|
|
6624
|
+
userFilters,
|
|
6625
|
+
userSort,
|
|
6277
6626
|
...restOptions
|
|
6278
6627
|
} = options || {};
|
|
6279
|
-
super(restOptions);
|
|
6628
|
+
super({ ...restOptions, allowEmptySearchString: true });
|
|
6280
6629
|
this.type = "mentions";
|
|
6281
6630
|
this.normalizeSearchValue = (value) => this.transliterate(removeDiacritics(value)).toLowerCase();
|
|
6282
6631
|
this.matchesSearchQuery = (value, searchQuery) => {
|
|
@@ -6314,10 +6663,6 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6314
6663
|
this.toHereMentionSuggestion = (searchToken = this.searchQuery) => this.mapMentionSuggestion("here", "here", searchToken);
|
|
6315
6664
|
this.toRoleMentionSuggestion = (role, searchToken = this.searchQuery) => this.mapMentionSuggestion("role", role, searchToken);
|
|
6316
6665
|
this.toUserGroupMentionSuggestion = (userGroup, searchToken = this.searchQuery) => this.mapMentionSuggestion("user_group", userGroup, searchToken);
|
|
6317
|
-
this.canExecuteQuery = (newSearchString) => {
|
|
6318
|
-
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
6319
|
-
return this.isActive && !this.isLoading && (hasNewSearchQuery || this.hasNext);
|
|
6320
|
-
};
|
|
6321
6666
|
this.transliterate = (text) => text;
|
|
6322
6667
|
this.getMembersAndWatchers = () => {
|
|
6323
6668
|
const memberUsers = Object.values(this.channel.state.members ?? {}).map(
|
|
@@ -6337,10 +6682,10 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6337
6682
|
...this.isMentionTypeAllowed("channel") ? [this.toChannelMentionSuggestion(searchQuery)] : [],
|
|
6338
6683
|
...this.isMentionTypeAllowed("here") ? [this.toHereMentionSuggestion(searchQuery)] : []
|
|
6339
6684
|
].filter(({ name }) => this.matchesPrefixSearchQuery(name, searchQuery));
|
|
6340
|
-
this.getRoleMentionSuggestions = async (query) => {
|
|
6685
|
+
this.getRoleMentionSuggestions = async (query, queryOptions = {}) => {
|
|
6341
6686
|
if (!this.isMentionTypeAllowed("role")) return [];
|
|
6342
6687
|
if (!query) return [];
|
|
6343
|
-
const { roles } = await this.client.searchRoles({ query });
|
|
6688
|
+
const { roles } = await this.client.searchRoles({ query }, queryOptions);
|
|
6344
6689
|
return [...roles?.map((role) => role.name) ?? []].sort((left, right) => left.localeCompare(right)).map((role) => this.toRoleMentionSuggestion(role, query));
|
|
6345
6690
|
};
|
|
6346
6691
|
this.searchMembersLocally = (searchQuery) => {
|
|
@@ -6402,20 +6747,25 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6402
6747
|
options: { ...this.searchOptions, limit: this.pageSize, offset }
|
|
6403
6748
|
};
|
|
6404
6749
|
};
|
|
6405
|
-
this.queryUsers = async (searchQuery, offset = 0) => {
|
|
6750
|
+
this.queryUsers = async (searchQuery, offset = 0, queryOptions = {}) => {
|
|
6406
6751
|
const { filters, sort, options } = this.prepareQueryUsersParams(searchQuery, offset);
|
|
6407
|
-
const { users } = await this.client.queryUsers(filters, sort, options);
|
|
6752
|
+
const { users } = await this.client.queryUsers(filters, sort, options, queryOptions);
|
|
6408
6753
|
return users;
|
|
6409
6754
|
};
|
|
6410
|
-
this.queryMembers = async (searchQuery, offset = 0) => {
|
|
6755
|
+
this.queryMembers = async (searchQuery, offset = 0, queryOptions = {}) => {
|
|
6411
6756
|
const { filters, sort, options } = this.prepareQueryMembersParams(
|
|
6412
6757
|
searchQuery,
|
|
6413
6758
|
offset
|
|
6414
6759
|
);
|
|
6415
|
-
const response = await this.channel.queryMembers(
|
|
6760
|
+
const response = await this.channel.queryMembers(
|
|
6761
|
+
filters,
|
|
6762
|
+
sort,
|
|
6763
|
+
options,
|
|
6764
|
+
queryOptions
|
|
6765
|
+
);
|
|
6416
6766
|
return response.members.map((member) => member.user);
|
|
6417
6767
|
};
|
|
6418
|
-
this.getUserSuggestionsPage = async (searchQuery, userOffset = 0) => {
|
|
6768
|
+
this.getUserSuggestionsPage = async (searchQuery, userOffset = 0, queryOptions = {}) => {
|
|
6419
6769
|
if (!this.isMentionTypeAllowed("user")) {
|
|
6420
6770
|
return {
|
|
6421
6771
|
items: [],
|
|
@@ -6425,7 +6775,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6425
6775
|
let users;
|
|
6426
6776
|
const shouldSearchLocally = this.allMembersLoadedWithInitialChannelQuery || !searchQuery;
|
|
6427
6777
|
if (this.config.mentionAllAppUsers) {
|
|
6428
|
-
users = await this.queryUsers(searchQuery, userOffset);
|
|
6778
|
+
users = await this.queryUsers(searchQuery, userOffset, queryOptions);
|
|
6429
6779
|
} else if (shouldSearchLocally) {
|
|
6430
6780
|
const localUsers = this.searchMembersLocally(searchQuery);
|
|
6431
6781
|
const items2 = localUsers.slice(userOffset, userOffset + this.pageSize).map((user) => this.toUserSuggestion(user, searchQuery));
|
|
@@ -6434,7 +6784,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6434
6784
|
nextOffset: localUsers.length > userOffset + this.pageSize ? userOffset + items2.length : void 0
|
|
6435
6785
|
};
|
|
6436
6786
|
} else {
|
|
6437
|
-
users = await this.queryMembers(searchQuery, userOffset);
|
|
6787
|
+
users = await this.queryMembers(searchQuery, userOffset, queryOptions);
|
|
6438
6788
|
}
|
|
6439
6789
|
const items = users.map((user) => this.toUserSuggestion(user, searchQuery));
|
|
6440
6790
|
return {
|
|
@@ -6451,7 +6801,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6451
6801
|
name_gt: lastItem.name
|
|
6452
6802
|
});
|
|
6453
6803
|
};
|
|
6454
|
-
this.getUserGroupSuggestionsPage = async (searchQuery, cursor) => {
|
|
6804
|
+
this.getUserGroupSuggestionsPage = async (searchQuery, cursor, queryOptions = {}) => {
|
|
6455
6805
|
if (!this.isMentionTypeAllowed("user_group")) {
|
|
6456
6806
|
return {
|
|
6457
6807
|
items: [],
|
|
@@ -6473,7 +6823,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6473
6823
|
...userGroupCursor?.id_gt ? { id_gt: userGroupCursor.id_gt } : {},
|
|
6474
6824
|
...userGroupCursor?.name_gt ? { name_gt: userGroupCursor.name_gt } : {}
|
|
6475
6825
|
};
|
|
6476
|
-
const { user_groups } = await this.client.searchUserGroups(options);
|
|
6826
|
+
const { user_groups } = await this.client.searchUserGroups(options, queryOptions);
|
|
6477
6827
|
return {
|
|
6478
6828
|
items: user_groups.map(
|
|
6479
6829
|
(userGroup) => this.toUserGroupMentionSuggestion(userGroup, searchQuery)
|
|
@@ -6483,6 +6833,11 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6483
6833
|
};
|
|
6484
6834
|
this.client = channel.getClient();
|
|
6485
6835
|
this.channel = channel;
|
|
6836
|
+
this.userFilters = userFilters;
|
|
6837
|
+
this.userSort = userSort;
|
|
6838
|
+
this.memberFilters = memberFilters;
|
|
6839
|
+
this.memberSort = memberSort;
|
|
6840
|
+
this.searchOptions = searchOptions;
|
|
6486
6841
|
this.config = {
|
|
6487
6842
|
mentionAllAppUsers,
|
|
6488
6843
|
suggestionFactoryMappers,
|
|
@@ -6515,16 +6870,21 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6515
6870
|
offset: (this.offset ?? 0) + userPaginationState.itemCount
|
|
6516
6871
|
};
|
|
6517
6872
|
}
|
|
6518
|
-
async query(searchQuery) {
|
|
6873
|
+
async query(searchQuery, queryOptions = {}) {
|
|
6519
6874
|
const userOffset = this.offset ?? 0;
|
|
6520
6875
|
const isFirstPage = userOffset === 0 && typeof this.userGroupCursor === "undefined";
|
|
6521
6876
|
const previousUserPaginationState = this.latestUserPaginationState;
|
|
6522
6877
|
const previousUserGroupCursor = this.userGroupCursor;
|
|
6523
6878
|
const [userResultsState, userGroupResultsState, roleSuggestionsState] = await Promise.allSettled([
|
|
6524
|
-
this.getUserSuggestionsPage(searchQuery, userOffset),
|
|
6525
|
-
this.getUserGroupSuggestionsPage(
|
|
6526
|
-
|
|
6879
|
+
this.getUserSuggestionsPage(searchQuery, userOffset, queryOptions),
|
|
6880
|
+
this.getUserGroupSuggestionsPage(
|
|
6881
|
+
searchQuery,
|
|
6882
|
+
previousUserGroupCursor,
|
|
6883
|
+
queryOptions
|
|
6884
|
+
),
|
|
6885
|
+
isFirstPage ? this.getRoleMentionSuggestions(searchQuery, queryOptions) : Promise.resolve([])
|
|
6527
6886
|
]);
|
|
6887
|
+
if (queryOptions.signal?.aborted) return { items: [] };
|
|
6528
6888
|
const userResults = userResultsState.status === "fulfilled" ? userResultsState.value : {
|
|
6529
6889
|
items: [],
|
|
6530
6890
|
nextOffset: isFirstPage ? void 0 : previousUserPaginationState?.nextOffset
|
|
@@ -6799,7 +7159,7 @@ var DEFAULT_COMPOSER_CONFIG = {
|
|
|
6799
7159
|
};
|
|
6800
7160
|
|
|
6801
7161
|
// src/messageComposer/CustomDataManager.ts
|
|
6802
|
-
var
|
|
7162
|
+
var initState4 = (options) => {
|
|
6803
7163
|
if (!options)
|
|
6804
7164
|
return { message: {}, custom: {} };
|
|
6805
7165
|
return { message: {}, custom: {} };
|
|
@@ -6808,14 +7168,14 @@ var CustomDataManager = class {
|
|
|
6808
7168
|
constructor({ composer, message }) {
|
|
6809
7169
|
this.isMessageDataEqual = (nextState, previousState) => JSON.stringify(nextState.message) === JSON.stringify(previousState?.message);
|
|
6810
7170
|
this.initState = ({ message } = {}) => {
|
|
6811
|
-
this.state.next(
|
|
7171
|
+
this.state.next(initState4({ composer: this.composer, message }));
|
|
6812
7172
|
};
|
|
6813
7173
|
this.getSnapshot = () => this.state.getLatestValue();
|
|
6814
7174
|
this.restoreSnapshot = (snapshot) => {
|
|
6815
7175
|
this.state.next(snapshot);
|
|
6816
7176
|
};
|
|
6817
7177
|
this.composer = composer;
|
|
6818
|
-
this.state = new StateStore(
|
|
7178
|
+
this.state = new StateStore(initState4({ composer, message }));
|
|
6819
7179
|
}
|
|
6820
7180
|
get customMessageData() {
|
|
6821
7181
|
return this.state.getLatestValue().message;
|
|
@@ -6851,7 +7211,7 @@ var LinkPreviewStatus = /* @__PURE__ */ ((LinkPreviewStatus2) => {
|
|
|
6851
7211
|
return LinkPreviewStatus2;
|
|
6852
7212
|
})(LinkPreviewStatus || {});
|
|
6853
7213
|
var linkPreviewArrayToMap = (linkPreviews) => new Map(linkPreviews.map((linkPreview) => [linkPreview.og_scrape_url, linkPreview]));
|
|
6854
|
-
var
|
|
7214
|
+
var initState5 = ({
|
|
6855
7215
|
message
|
|
6856
7216
|
}) => message ? {
|
|
6857
7217
|
previews: message.attachments?.reduce((acc, attachment) => {
|
|
@@ -6870,7 +7230,7 @@ var _LinkPreviewsManager = class _LinkPreviewsManager {
|
|
|
6870
7230
|
this.shouldDiscardEnrichQueries = false;
|
|
6871
7231
|
this.initState = ({ message } = {}) => {
|
|
6872
7232
|
this.cancelURLEnrichment();
|
|
6873
|
-
this.state.next(
|
|
7233
|
+
this.state.next(initState5({ message: this.enabled ? message : void 0 }));
|
|
6874
7234
|
};
|
|
6875
7235
|
this.getSnapshot = () => this.state.getLatestValue();
|
|
6876
7236
|
this.restoreSnapshot = (snapshot) => {
|
|
@@ -6973,7 +7333,7 @@ var _LinkPreviewsManager = class _LinkPreviewsManager {
|
|
|
6973
7333
|
};
|
|
6974
7334
|
this.composer = composer;
|
|
6975
7335
|
this.state = new StateStore(
|
|
6976
|
-
|
|
7336
|
+
initState5({ message: this.enabled ? message : void 0 })
|
|
6977
7337
|
);
|
|
6978
7338
|
this.findAndEnrichUrls = debounce(
|
|
6979
7339
|
this._findAndEnrichUrls.bind(this),
|
|
@@ -7061,7 +7421,7 @@ var LinkPreviewsManager = _LinkPreviewsManager;
|
|
|
7061
7421
|
|
|
7062
7422
|
// src/messageComposer/LocationComposer.ts
|
|
7063
7423
|
var MIN_LIVE_LOCATION_SHARE_DURATION = 60 * 1e3;
|
|
7064
|
-
var
|
|
7424
|
+
var initState6 = ({
|
|
7065
7425
|
message
|
|
7066
7426
|
}) => ({
|
|
7067
7427
|
location: message?.shared_location ?? null
|
|
@@ -7069,7 +7429,7 @@ var initState5 = ({
|
|
|
7069
7429
|
var LocationComposer = class {
|
|
7070
7430
|
constructor({ composer, message }) {
|
|
7071
7431
|
this.initState = ({ message } = {}) => {
|
|
7072
|
-
this.state.next(
|
|
7432
|
+
this.state.next(initState6({ message }));
|
|
7073
7433
|
};
|
|
7074
7434
|
this.getSnapshot = () => this.state.getLatestValue();
|
|
7075
7435
|
this.restoreSnapshot = (snapshot) => {
|
|
@@ -7087,7 +7447,7 @@ var LocationComposer = class {
|
|
|
7087
7447
|
});
|
|
7088
7448
|
};
|
|
7089
7449
|
this.composer = composer;
|
|
7090
|
-
this.state = new StateStore(
|
|
7450
|
+
this.state = new StateStore(initState6({ message }));
|
|
7091
7451
|
this._deviceId = this.config.getDeviceId();
|
|
7092
7452
|
}
|
|
7093
7453
|
get config() {
|
|
@@ -7808,7 +8168,7 @@ var initEditingAuditState = (composition) => {
|
|
|
7808
8168
|
}
|
|
7809
8169
|
};
|
|
7810
8170
|
};
|
|
7811
|
-
var
|
|
8171
|
+
var initState7 = (composition) => {
|
|
7812
8172
|
if (!composition) {
|
|
7813
8173
|
return {
|
|
7814
8174
|
draftId: null,
|
|
@@ -7895,7 +8255,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7895
8255
|
this.textComposer.initState({ message });
|
|
7896
8256
|
this.pollComposer.initState();
|
|
7897
8257
|
this.customDataManager.initState({ message });
|
|
7898
|
-
this.state.next(
|
|
8258
|
+
this.state.next(initState7(composition));
|
|
7899
8259
|
};
|
|
7900
8260
|
this.initStateFromChannelResponse = (channelApiResponse) => {
|
|
7901
8261
|
if (this.channel.cid !== channelApiResponse.channel.cid) {
|
|
@@ -8361,7 +8721,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8361
8721
|
this.editingAuditState = new StateStore(
|
|
8362
8722
|
this.initEditingAuditState(composition)
|
|
8363
8723
|
);
|
|
8364
|
-
this.state = new StateStore(
|
|
8724
|
+
this.state = new StateStore(initState7(composition));
|
|
8365
8725
|
this.compositionMiddlewareExecutor = new MessageComposerMiddlewareExecutor({
|
|
8366
8726
|
composer: this
|
|
8367
8727
|
});
|
|
@@ -8440,8 +8800,32 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8440
8800
|
const currentCommand = this.textComposer.command;
|
|
8441
8801
|
return !currentCommand || this.validateCommandSendability(currentCommand).ready;
|
|
8442
8802
|
}
|
|
8803
|
+
/**
|
|
8804
|
+
* Whether the installed composition middleware composes messages whose uploads are still in
|
|
8805
|
+
* flight — see `MessageCompositionMiddleware.allowsPendingUploads`.
|
|
8806
|
+
*
|
|
8807
|
+
* Derived from the chain rather than from config, so there is exactly one switch: the UI SDK
|
|
8808
|
+
* that implements the rest of the flow installs the middleware, and everything that has to
|
|
8809
|
+
* follow from that (starting with {@link hasSendableData}) follows on its own.
|
|
8810
|
+
*
|
|
8811
|
+
* **Temporary API.** In v10 sending with pending uploads becomes part of the composer
|
|
8812
|
+
* configuration (`MessageComposerConfig`, set through `updateConfig`), and this getter,
|
|
8813
|
+
* together with the middleware declaration it reads, is replaced by that config field.
|
|
8814
|
+
*/
|
|
8815
|
+
get allowsPendingUploads() {
|
|
8816
|
+
return this.compositionMiddlewareExecutor.installedMiddleware.some(
|
|
8817
|
+
(middleware) => middleware.allowsPendingUploads
|
|
8818
|
+
);
|
|
8819
|
+
}
|
|
8443
8820
|
get hasSendableData() {
|
|
8444
|
-
|
|
8821
|
+
if (!this.isCommandSendable) return false;
|
|
8822
|
+
if (this.allowsPendingUploads) {
|
|
8823
|
+
const hasSendableAttachment = this.attachmentManager.attachments.some(
|
|
8824
|
+
(attachment) => isFinishedUpload(attachment) || isPendingUpload(attachment)
|
|
8825
|
+
);
|
|
8826
|
+
return !!(!this.textComposer.textIsEmpty || hasSendableAttachment || this.pollId || this.locationComposer.validLocation);
|
|
8827
|
+
}
|
|
8828
|
+
return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId || !!this.locationComposer.validLocation);
|
|
8445
8829
|
}
|
|
8446
8830
|
get compositionIsEmpty() {
|
|
8447
8831
|
return !this.quotedMessage && this.contentIsEmpty;
|
|
@@ -9068,14 +9452,16 @@ var Channel = class {
|
|
|
9068
9452
|
*
|
|
9069
9453
|
* @return {Promise<SendMessageAPIResponse>} The Server Response
|
|
9070
9454
|
*/
|
|
9071
|
-
async _sendMessage(
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9455
|
+
async _sendMessage(rawMessage, options) {
|
|
9456
|
+
const client = this.getClient();
|
|
9457
|
+
const message = sanitizeOutgoingAttachments({
|
|
9458
|
+
client,
|
|
9459
|
+
message: rawMessage
|
|
9460
|
+
});
|
|
9461
|
+
return await client.post(this._channelURL() + "/message", {
|
|
9462
|
+
message,
|
|
9463
|
+
...options
|
|
9464
|
+
});
|
|
9079
9465
|
}
|
|
9080
9466
|
async sendMessage(message, options) {
|
|
9081
9467
|
try {
|
|
@@ -9200,10 +9586,11 @@ var Channel = class {
|
|
|
9200
9586
|
* @param {MemberSort} [sort] Sort options, for instance [{created_at: -1}].
|
|
9201
9587
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{name: -1}, {created_at: 1}]
|
|
9202
9588
|
* @param {{ limit?: number; offset?: number }} [options] Option object, {limit: 10, offset:10}
|
|
9589
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
9203
9590
|
*
|
|
9204
9591
|
* @return {Promise<ChannelMemberAPIResponse>} Query Members response
|
|
9205
9592
|
*/
|
|
9206
|
-
async queryMembers(filterConditions, sort = [], options = {}) {
|
|
9593
|
+
async queryMembers(filterConditions, sort = [], options = {}, requestOptions = {}) {
|
|
9207
9594
|
let id;
|
|
9208
9595
|
const type = this.type;
|
|
9209
9596
|
let members;
|
|
@@ -9223,7 +9610,8 @@ var Channel = class {
|
|
|
9223
9610
|
filter_conditions: filterConditions,
|
|
9224
9611
|
...options
|
|
9225
9612
|
}
|
|
9226
|
-
}
|
|
9613
|
+
},
|
|
9614
|
+
requestOptions
|
|
9227
9615
|
);
|
|
9228
9616
|
}
|
|
9229
9617
|
/**
|
|
@@ -10524,6 +10912,7 @@ var Channel = class {
|
|
|
10524
10912
|
// delivery-report network sync below is skipped for it.
|
|
10525
10913
|
case "message.read_locally":
|
|
10526
10914
|
case "message.read":
|
|
10915
|
+
if (event.thread) break;
|
|
10527
10916
|
if (event.user?.id && event.created_at) {
|
|
10528
10917
|
const previousReadState = channelState.read[event.user.id];
|
|
10529
10918
|
channelState.read[event.user.id] = {
|
|
@@ -10973,7 +11362,7 @@ var ClientState = class {
|
|
|
10973
11362
|
import WebSocket from "isomorphic-ws";
|
|
10974
11363
|
|
|
10975
11364
|
// src/insights.ts
|
|
10976
|
-
import
|
|
11365
|
+
import axios2 from "axios";
|
|
10977
11366
|
var InsightMetrics = class {
|
|
10978
11367
|
constructor() {
|
|
10979
11368
|
this.connectionStartTimestamp = null;
|
|
@@ -10986,7 +11375,7 @@ var postInsights = async (insightType, insights) => {
|
|
|
10986
11375
|
const maxAttempts = 3;
|
|
10987
11376
|
for (let i = 0; i < maxAttempts; i++) {
|
|
10988
11377
|
try {
|
|
10989
|
-
await
|
|
11378
|
+
await axios2.post(
|
|
10990
11379
|
`https://chat-insights.getstream.io/insights/${insightType}`,
|
|
10991
11380
|
insights
|
|
10992
11381
|
);
|
|
@@ -11494,131 +11883,6 @@ var StableWSConnection = class {
|
|
|
11494
11883
|
}
|
|
11495
11884
|
};
|
|
11496
11885
|
|
|
11497
|
-
// src/uploadManager.ts
|
|
11498
|
-
var initState7 = () => ({ uploads: {} });
|
|
11499
|
-
var upsertById = (uploads, record) => ({
|
|
11500
|
-
...uploads,
|
|
11501
|
-
[record.id]: { ...uploads[record.id], ...record }
|
|
11502
|
-
});
|
|
11503
|
-
var updateById = (uploads, record) => {
|
|
11504
|
-
if (!(record.id in uploads)) return null;
|
|
11505
|
-
const current = uploads[record.id];
|
|
11506
|
-
return { ...uploads, [record.id]: { ...current, ...record } };
|
|
11507
|
-
};
|
|
11508
|
-
var UploadManager = class {
|
|
11509
|
-
constructor(client) {
|
|
11510
|
-
this.client = client;
|
|
11511
|
-
this.inFlightUploads = /* @__PURE__ */ new Map();
|
|
11512
|
-
this.getUpload = (id) => this.uploads[id];
|
|
11513
|
-
/**
|
|
11514
|
-
* Clears all upload records.
|
|
11515
|
-
* Invoked when the user disconnects so a later session does not inherit stale upload state.
|
|
11516
|
-
* Aborts every in-flight upload request via its `UploadRequestOptions.abortSignal`.
|
|
11517
|
-
*/
|
|
11518
|
-
this.reset = () => {
|
|
11519
|
-
for (const { abortController } of this.inFlightUploads.values()) {
|
|
11520
|
-
abortController.abort();
|
|
11521
|
-
}
|
|
11522
|
-
this.inFlightUploads.clear();
|
|
11523
|
-
this.state.next(initState7());
|
|
11524
|
-
};
|
|
11525
|
-
/**
|
|
11526
|
-
* Removes the upload record for `id` if present.
|
|
11527
|
-
* If an upload is still in progress, aborts its `UploadRequestOptions.abortSignal`.
|
|
11528
|
-
*/
|
|
11529
|
-
this.deleteUploadRecord = (id) => {
|
|
11530
|
-
const flight = this.inFlightUploads.get(id);
|
|
11531
|
-
if (flight) {
|
|
11532
|
-
this.inFlightUploads.delete(id);
|
|
11533
|
-
flight.abortController.abort();
|
|
11534
|
-
}
|
|
11535
|
-
this.state.next((current) => {
|
|
11536
|
-
if (!(id in current.uploads)) return current;
|
|
11537
|
-
const uploads = { ...current.uploads };
|
|
11538
|
-
delete uploads[id];
|
|
11539
|
-
return { ...current, uploads };
|
|
11540
|
-
});
|
|
11541
|
-
};
|
|
11542
|
-
/**
|
|
11543
|
-
* Starts an upload for `id`, or returns the existing in-flight promise if one is already running.
|
|
11544
|
-
* Uses {@link StreamChat.channel}(`channelCid`) → `messageComposer.attachmentManager.doUploadRequest`.
|
|
11545
|
-
* Resolves with that result; rejects if the upload rejects (the record is removed from state either way).
|
|
11546
|
-
*/
|
|
11547
|
-
this.upload = ({
|
|
11548
|
-
id,
|
|
11549
|
-
channelCid,
|
|
11550
|
-
file
|
|
11551
|
-
}) => {
|
|
11552
|
-
const existing = this.inFlightUploads.get(id);
|
|
11553
|
-
if (existing) return existing.promise;
|
|
11554
|
-
let resolvePromise;
|
|
11555
|
-
let rejectPromise;
|
|
11556
|
-
const promise = new Promise((resolve, reject) => {
|
|
11557
|
-
resolvePromise = resolve;
|
|
11558
|
-
rejectPromise = reject;
|
|
11559
|
-
});
|
|
11560
|
-
const abortController = new AbortController();
|
|
11561
|
-
this.inFlightUploads.set(id, { promise, abortController });
|
|
11562
|
-
void (async () => {
|
|
11563
|
-
const attachmentManager = this.resolveAttachmentManager(channelCid);
|
|
11564
|
-
const trackProgress = attachmentManager.config.trackUploadProgress;
|
|
11565
|
-
try {
|
|
11566
|
-
this.upsertUpload({
|
|
11567
|
-
id,
|
|
11568
|
-
uploadProgress: trackProgress ? 0 : void 0
|
|
11569
|
-
});
|
|
11570
|
-
const onProgress = trackProgress ? (progress) => {
|
|
11571
|
-
this.updateUpload({
|
|
11572
|
-
id,
|
|
11573
|
-
uploadProgress: progress
|
|
11574
|
-
});
|
|
11575
|
-
} : void 0;
|
|
11576
|
-
const uploadRequestOptions = {
|
|
11577
|
-
abortSignal: abortController.signal,
|
|
11578
|
-
...onProgress ? { onProgress } : {}
|
|
11579
|
-
};
|
|
11580
|
-
const response = await attachmentManager.doUploadRequest(
|
|
11581
|
-
file,
|
|
11582
|
-
uploadRequestOptions
|
|
11583
|
-
);
|
|
11584
|
-
resolvePromise(response);
|
|
11585
|
-
} catch (error) {
|
|
11586
|
-
rejectPromise(error);
|
|
11587
|
-
} finally {
|
|
11588
|
-
this.inFlightUploads.delete(id);
|
|
11589
|
-
this.deleteUploadRecord(id);
|
|
11590
|
-
}
|
|
11591
|
-
})();
|
|
11592
|
-
return promise;
|
|
11593
|
-
};
|
|
11594
|
-
this.upsertUpload = (record) => {
|
|
11595
|
-
this.state.partialNext({
|
|
11596
|
-
uploads: upsertById(this.uploads, record)
|
|
11597
|
-
});
|
|
11598
|
-
};
|
|
11599
|
-
this.updateUpload = (record) => {
|
|
11600
|
-
this.state.next((current) => {
|
|
11601
|
-
const nextUploads = updateById(current.uploads, record);
|
|
11602
|
-
if (!nextUploads) return current;
|
|
11603
|
-
return { ...current, uploads: nextUploads };
|
|
11604
|
-
});
|
|
11605
|
-
};
|
|
11606
|
-
this.state = new StateStore(initState7());
|
|
11607
|
-
}
|
|
11608
|
-
resolveAttachmentManager(channelCid) {
|
|
11609
|
-
const colon = channelCid.indexOf(":");
|
|
11610
|
-
if (colon <= 0 || colon === channelCid.length - 1) {
|
|
11611
|
-
throw new Error(`Invalid channelCid: ${channelCid}`);
|
|
11612
|
-
}
|
|
11613
|
-
const channelType = channelCid.slice(0, colon);
|
|
11614
|
-
const channelId = channelCid.slice(colon + 1);
|
|
11615
|
-
return this.client.channel(channelType, channelId).messageComposer.attachmentManager;
|
|
11616
|
-
}
|
|
11617
|
-
get uploads() {
|
|
11618
|
-
return this.state.getLatestValue().uploads;
|
|
11619
|
-
}
|
|
11620
|
-
};
|
|
11621
|
-
|
|
11622
11886
|
// src/signing.ts
|
|
11623
11887
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken());
|
|
11624
11888
|
var import_crypto = __toESM(require_crypto());
|
|
@@ -11877,7 +12141,7 @@ var TokenManager = class {
|
|
|
11877
12141
|
};
|
|
11878
12142
|
|
|
11879
12143
|
// src/connection_fallback.ts
|
|
11880
|
-
import
|
|
12144
|
+
import axios3 from "axios";
|
|
11881
12145
|
var WSConnectionFallback = class {
|
|
11882
12146
|
constructor({ client }) {
|
|
11883
12147
|
/** @private */
|
|
@@ -11896,7 +12160,7 @@ var WSConnectionFallback = class {
|
|
|
11896
12160
|
/** @private */
|
|
11897
12161
|
this._req = async (params, config, retry) => {
|
|
11898
12162
|
if (!this.cancelToken && !params.close) {
|
|
11899
|
-
this.cancelToken =
|
|
12163
|
+
this.cancelToken = axios3.CancelToken.source();
|
|
11900
12164
|
}
|
|
11901
12165
|
try {
|
|
11902
12166
|
const res = await this.client.doAxiosRequest(
|
|
@@ -11932,7 +12196,7 @@ var WSConnectionFallback = class {
|
|
|
11932
12196
|
}
|
|
11933
12197
|
}
|
|
11934
12198
|
} catch (error) {
|
|
11935
|
-
if (
|
|
12199
|
+
if (axios3.isCancel(error)) {
|
|
11936
12200
|
this._log(`_poll() - axios canceled request`);
|
|
11937
12201
|
return;
|
|
11938
12202
|
}
|
|
@@ -14355,6 +14619,7 @@ var StreamChat = class _StreamChat {
|
|
|
14355
14619
|
return this.handleResponse(response);
|
|
14356
14620
|
} catch (e) {
|
|
14357
14621
|
e.client_request_id = requestConfig.headers?.["x-client-request-id"];
|
|
14622
|
+
if (axios4.isCancel(e)) throw e;
|
|
14358
14623
|
this._logApiError(type, url, e);
|
|
14359
14624
|
this.consecutiveFailures += 1;
|
|
14360
14625
|
if (e.response) {
|
|
@@ -14666,7 +14931,7 @@ var StreamChat = class _StreamChat {
|
|
|
14666
14931
|
return this.userAgent;
|
|
14667
14932
|
}
|
|
14668
14933
|
if (!this.cachedUserAgent) {
|
|
14669
|
-
const version = "9.
|
|
14934
|
+
const version = "9.52.0";
|
|
14670
14935
|
const { name: sdkName, version: sdkVersion } = this.sdkIdentifier ?? {};
|
|
14671
14936
|
const { name: appName, version: appVersion } = this.appIdentifier ?? {};
|
|
14672
14937
|
const { os, model: deviceModel } = this.deviceIdentifier ?? {};
|
|
@@ -14734,7 +14999,7 @@ var StreamChat = class _StreamChat {
|
|
|
14734
14999
|
keepAliveMsecs: 3e3
|
|
14735
15000
|
});
|
|
14736
15001
|
}
|
|
14737
|
-
this.axiosInstance =
|
|
15002
|
+
this.axiosInstance = axios4.create(this.options);
|
|
14738
15003
|
this.setBaseURL(this.options.baseURL || "https://chat.stream-io-api.com");
|
|
14739
15004
|
if (typeof process !== "undefined" && "env" in process && process.env.STREAM_LOCAL_TEST_RUN) {
|
|
14740
15005
|
this.setBaseURL("http://localhost:3030");
|
|
@@ -15042,14 +15307,14 @@ var StreamChat = class _StreamChat {
|
|
|
15042
15307
|
error
|
|
15043
15308
|
});
|
|
15044
15309
|
}
|
|
15045
|
-
get(url, params) {
|
|
15046
|
-
return this.doAxiosRequest("get", url, null, { params });
|
|
15310
|
+
get(url, params, config) {
|
|
15311
|
+
return this.doAxiosRequest("get", url, null, { params, config });
|
|
15047
15312
|
}
|
|
15048
15313
|
put(url, data) {
|
|
15049
15314
|
return this.doAxiosRequest("put", url, data);
|
|
15050
15315
|
}
|
|
15051
|
-
post(url, data) {
|
|
15052
|
-
return this.doAxiosRequest("post", url, data);
|
|
15316
|
+
post(url, data, config) {
|
|
15317
|
+
return this.doAxiosRequest("post", url, data, { config });
|
|
15053
15318
|
}
|
|
15054
15319
|
patch(url, data) {
|
|
15055
15320
|
return this.doAxiosRequest("patch", url, data);
|
|
@@ -15244,10 +15509,11 @@ var StreamChat = class _StreamChat {
|
|
|
15244
15509
|
* @param {UserSort} sort Sort options, for instance [{last_active: -1}].
|
|
15245
15510
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_active: -1}, {created_at: 1}]
|
|
15246
15511
|
* @param {UserOptions} options Option object, {presence: true}
|
|
15512
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15247
15513
|
*
|
|
15248
15514
|
* @return {Promise<{ users: Array<UserResponse> }>} User Query Response
|
|
15249
15515
|
*/
|
|
15250
|
-
async queryUsers(filterConditions, sort = [], options = {}) {
|
|
15516
|
+
async queryUsers(filterConditions, sort = [], options = {}, requestOptions = {}) {
|
|
15251
15517
|
const defaultOptions = {
|
|
15252
15518
|
presence: false
|
|
15253
15519
|
};
|
|
@@ -15264,7 +15530,8 @@ var StreamChat = class _StreamChat {
|
|
|
15264
15530
|
...defaultOptions,
|
|
15265
15531
|
...options
|
|
15266
15532
|
}
|
|
15267
|
-
}
|
|
15533
|
+
},
|
|
15534
|
+
requestOptions
|
|
15268
15535
|
);
|
|
15269
15536
|
this.state.updateUsers(data.users);
|
|
15270
15537
|
return data;
|
|
@@ -15310,13 +15577,14 @@ var StreamChat = class _StreamChat {
|
|
|
15310
15577
|
* searchUserGroups - Search user groups by prefix for autocomplete
|
|
15311
15578
|
*
|
|
15312
15579
|
* @param {SearchUserGroupsOptions} options The search options
|
|
15313
|
-
*
|
|
15580
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15314
15581
|
* @return {Promise<SearchUserGroupsResponse>} User Group Search Response
|
|
15315
15582
|
*/
|
|
15316
|
-
async searchUserGroups(options) {
|
|
15583
|
+
async searchUserGroups(options, requestOptions = {}) {
|
|
15317
15584
|
return await this.get(
|
|
15318
15585
|
this.baseURL + "/usergroups/search",
|
|
15319
|
-
options
|
|
15586
|
+
options,
|
|
15587
|
+
requestOptions
|
|
15320
15588
|
);
|
|
15321
15589
|
}
|
|
15322
15590
|
/**
|
|
@@ -15436,10 +15704,11 @@ var StreamChat = class _StreamChat {
|
|
|
15436
15704
|
* @param {ChannelSort} [sort] Sort options, for instance {created_at: -1}.
|
|
15437
15705
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_updated: -1}, {created_at: 1}]
|
|
15438
15706
|
* @param {ChannelOptions} [options] Options object. Can include predefined_filter, filter_values, and sort_values for using predefined filters.
|
|
15707
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15439
15708
|
*
|
|
15440
15709
|
* @return {Promise<QueryChannelsAPIResponse>} full search channels response
|
|
15441
15710
|
*/
|
|
15442
|
-
async queryChannelsRequestWithResponse(filterConditions, sort = [], options = {}) {
|
|
15711
|
+
async queryChannelsRequestWithResponse(filterConditions, sort = [], options = {}, requestOptions = {}) {
|
|
15443
15712
|
const defaultOptions = {
|
|
15444
15713
|
state: true,
|
|
15445
15714
|
watch: true,
|
|
@@ -15464,7 +15733,11 @@ var StreamChat = class _StreamChat {
|
|
|
15464
15733
|
...defaultOptions,
|
|
15465
15734
|
...restOptions
|
|
15466
15735
|
};
|
|
15467
|
-
return await this.post(
|
|
15736
|
+
return await this.post(
|
|
15737
|
+
this.baseURL + "/channels",
|
|
15738
|
+
payload,
|
|
15739
|
+
requestOptions
|
|
15740
|
+
);
|
|
15468
15741
|
}
|
|
15469
15742
|
/**
|
|
15470
15743
|
* queryChannelsRequest - Queries channels and returns the raw channel response list.
|
|
@@ -15493,7 +15766,9 @@ var StreamChat = class _StreamChat {
|
|
|
15493
15766
|
const queryChannelsResponse = await this.queryChannelsRequestWithResponse(
|
|
15494
15767
|
filterConditions,
|
|
15495
15768
|
sort,
|
|
15496
|
-
options
|
|
15769
|
+
options,
|
|
15770
|
+
// stateOptions is never serialized, so it carries the abort signal
|
|
15771
|
+
{ signal: stateOptions.signal }
|
|
15497
15772
|
);
|
|
15498
15773
|
const channels = queryChannelsResponse.channels;
|
|
15499
15774
|
this.dispatchEvent({
|
|
@@ -15610,10 +15885,11 @@ var StreamChat = class _StreamChat {
|
|
|
15610
15885
|
* @param {ChannelFilters} filterConditions MongoDB style filter conditions
|
|
15611
15886
|
* @param {MessageFilters | string} query search query or object MongoDB style filters
|
|
15612
15887
|
* @param {SearchOptions} [options] Option object, {user_id: 'tommaso'}
|
|
15888
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15613
15889
|
*
|
|
15614
15890
|
* @return {Promise<SearchAPIResponse>} search messages response
|
|
15615
15891
|
*/
|
|
15616
|
-
async search(filterConditions, query, options = {}) {
|
|
15892
|
+
async search(filterConditions, query, options = {}, requestOptions = {}) {
|
|
15617
15893
|
if (options.offset && options.next) {
|
|
15618
15894
|
throw Error(`Cannot specify offset with next`);
|
|
15619
15895
|
}
|
|
@@ -15630,7 +15906,11 @@ var StreamChat = class _StreamChat {
|
|
|
15630
15906
|
throw Error(`Invalid type ${typeof query} for query parameter`);
|
|
15631
15907
|
}
|
|
15632
15908
|
await this.wsPromise;
|
|
15633
|
-
return await this.get(
|
|
15909
|
+
return await this.get(
|
|
15910
|
+
this.baseURL + "/search",
|
|
15911
|
+
{ payload },
|
|
15912
|
+
requestOptions
|
|
15913
|
+
);
|
|
15634
15914
|
}
|
|
15635
15915
|
/**
|
|
15636
15916
|
* setLocalDevice - Set the device info for the current client(device) that will be sent via WS connection automatically
|
|
@@ -16071,6 +16351,11 @@ var StreamChat = class _StreamChat {
|
|
|
16071
16351
|
}
|
|
16072
16352
|
/**
|
|
16073
16353
|
* unflagMessage - unflag a message
|
|
16354
|
+
*
|
|
16355
|
+
* @deprecated The `/moderation/unflag` endpoint is deprecated and is a no-op on
|
|
16356
|
+
* the backend - calling this resolves successfully but does not remove the flag.
|
|
16357
|
+
* Use `client.moderation.submitAction()` against the review queue item instead.
|
|
16358
|
+
*
|
|
16074
16359
|
* @param {string} targetMessageID
|
|
16075
16360
|
* @param {string} [options.user_id] currentUserID, only used with serverside auth
|
|
16076
16361
|
* @returns {Promise<APIResponse>}
|
|
@@ -16083,6 +16368,11 @@ var StreamChat = class _StreamChat {
|
|
|
16083
16368
|
}
|
|
16084
16369
|
/**
|
|
16085
16370
|
* unflagUser - unflag a user
|
|
16371
|
+
*
|
|
16372
|
+
* @deprecated The `/moderation/unflag` endpoint is deprecated and is a no-op on
|
|
16373
|
+
* the backend - calling this resolves successfully but does not remove the flag.
|
|
16374
|
+
* Use `client.moderation.submitAction()` against the review queue item instead.
|
|
16375
|
+
*
|
|
16086
16376
|
* @param {string} targetID
|
|
16087
16377
|
* @param {string} [options.user_id] currentUserID, only used with serverside auth
|
|
16088
16378
|
* @returns {Promise<APIResponse>}
|
|
@@ -16367,7 +16657,10 @@ var StreamChat = class _StreamChat {
|
|
|
16367
16657
|
if (!message.id) {
|
|
16368
16658
|
throw Error("Please specify the message.id when calling updateMessage");
|
|
16369
16659
|
}
|
|
16370
|
-
const payload =
|
|
16660
|
+
const payload = sanitizeOutgoingAttachments({
|
|
16661
|
+
client: this,
|
|
16662
|
+
message: toUpdatedMessagePayload(message)
|
|
16663
|
+
});
|
|
16371
16664
|
if (typeof partialUserOrUserId === "string") {
|
|
16372
16665
|
payload.user_id = partialUserOrUserId;
|
|
16373
16666
|
} else if (typeof partialUserOrUserId?.id === "string") {
|
|
@@ -16667,6 +16960,7 @@ var StreamChat = class _StreamChat {
|
|
|
16667
16960
|
headers: axiosRequestConfigHeaders,
|
|
16668
16961
|
...axiosRequestConfigRest
|
|
16669
16962
|
} = this.options.axiosRequestConfig || {};
|
|
16963
|
+
const resolvedSignal = options.config?.signal ?? axiosRequestConfigRest.signal ?? signal;
|
|
16670
16964
|
return {
|
|
16671
16965
|
params: {
|
|
16672
16966
|
user_id: this.userID,
|
|
@@ -16682,9 +16976,9 @@ var StreamChat = class _StreamChat {
|
|
|
16682
16976
|
...options.headers,
|
|
16683
16977
|
...axiosRequestConfigHeaders || {}
|
|
16684
16978
|
},
|
|
16685
|
-
...signal ? { signal } : {},
|
|
16686
16979
|
...options.config,
|
|
16687
|
-
...axiosRequestConfigRest
|
|
16980
|
+
...axiosRequestConfigRest,
|
|
16981
|
+
...resolvedSignal ? { signal: resolvedSignal } : {}
|
|
16688
16982
|
};
|
|
16689
16983
|
}
|
|
16690
16984
|
_getToken() {
|
|
@@ -16824,8 +17118,12 @@ var StreamChat = class _StreamChat {
|
|
|
16824
17118
|
*
|
|
16825
17119
|
* @returns {Promise<APIResponse>}
|
|
16826
17120
|
*/
|
|
16827
|
-
searchRoles(options) {
|
|
16828
|
-
return this.get(
|
|
17121
|
+
searchRoles(options, requestOptions = {}) {
|
|
17122
|
+
return this.get(
|
|
17123
|
+
`${this.baseURL}/roles/search`,
|
|
17124
|
+
options,
|
|
17125
|
+
requestOptions
|
|
17126
|
+
);
|
|
16829
17127
|
}
|
|
16830
17128
|
/** deleteRole - deletes a custom role
|
|
16831
17129
|
*
|
|
@@ -18182,7 +18480,8 @@ import { isAxiosError } from "axios";
|
|
|
18182
18480
|
var OfflineDBSyncManager = class {
|
|
18183
18481
|
constructor({
|
|
18184
18482
|
client,
|
|
18185
|
-
offlineDb
|
|
18483
|
+
offlineDb,
|
|
18484
|
+
syncMaxEventCount
|
|
18186
18485
|
}) {
|
|
18187
18486
|
this.syncStatus = false;
|
|
18188
18487
|
this.connectionChangedListener = null;
|
|
@@ -18299,13 +18598,23 @@ var OfflineDBSyncManager = class {
|
|
|
18299
18598
|
await this.offlineDb.resetDB();
|
|
18300
18599
|
} else {
|
|
18301
18600
|
const result = await this.client.sync(cids, lastSyncedAtDate.toISOString());
|
|
18302
|
-
const
|
|
18303
|
-
|
|
18304
|
-
)
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18601
|
+
const { syncMaxEventCount } = this;
|
|
18602
|
+
const exceedsLimit = typeof syncMaxEventCount === "number" && syncMaxEventCount > 0 && result.events.length > syncMaxEventCount;
|
|
18603
|
+
if (exceedsLimit) {
|
|
18604
|
+
this.client.logger(
|
|
18605
|
+
"warn",
|
|
18606
|
+
`Skipping sync event replay: received ${result.events.length} events, which exceeds the configured limit of ${syncMaxEventCount}. Visible channels are refreshed on reconnect instead.`,
|
|
18607
|
+
{ tags: ["sync", "offline"] }
|
|
18608
|
+
);
|
|
18609
|
+
} else {
|
|
18610
|
+
const queryPromises = result.events.map(
|
|
18611
|
+
(event) => this.offlineDb.handleEvent({ event, execute: false })
|
|
18612
|
+
);
|
|
18613
|
+
const queriesArray = await Promise.all(queryPromises);
|
|
18614
|
+
const queries = queriesArray.flat();
|
|
18615
|
+
if (queries.length) {
|
|
18616
|
+
await this.offlineDb.executeSqlBatch(queries);
|
|
18617
|
+
}
|
|
18309
18618
|
}
|
|
18310
18619
|
}
|
|
18311
18620
|
}
|
|
@@ -18349,12 +18658,16 @@ var OfflineDBSyncManager = class {
|
|
|
18349
18658
|
};
|
|
18350
18659
|
this.client = client;
|
|
18351
18660
|
this.offlineDb = offlineDb;
|
|
18661
|
+
this.syncMaxEventCount = syncMaxEventCount;
|
|
18352
18662
|
}
|
|
18353
18663
|
};
|
|
18354
18664
|
|
|
18355
18665
|
// src/offline-support/offline_support_api.ts
|
|
18356
18666
|
var AbstractOfflineDB = class {
|
|
18357
|
-
constructor({
|
|
18667
|
+
constructor({
|
|
18668
|
+
client,
|
|
18669
|
+
syncMaxEventCount
|
|
18670
|
+
}) {
|
|
18358
18671
|
/**
|
|
18359
18672
|
* Initializes the DB as well as its syncManager for a given userId.
|
|
18360
18673
|
* It will update the DBs reactive state with initialization values.
|
|
@@ -18820,6 +19133,7 @@ var AbstractOfflineDB = class {
|
|
|
18820
19133
|
return this.handleMessageUpdatedEvent({ event, execute });
|
|
18821
19134
|
}
|
|
18822
19135
|
if (type === "message.read" || type === "notification.mark_read") {
|
|
19136
|
+
if (event.thread) return [];
|
|
18823
19137
|
return this.handleRead({ event, unreadMessages: 0, execute });
|
|
18824
19138
|
}
|
|
18825
19139
|
if (type === "message.read_locally") {
|
|
@@ -19044,7 +19358,11 @@ var AbstractOfflineDB = class {
|
|
|
19044
19358
|
}
|
|
19045
19359
|
};
|
|
19046
19360
|
this.client = client;
|
|
19047
|
-
this.syncManager = new OfflineDBSyncManager({
|
|
19361
|
+
this.syncManager = new OfflineDBSyncManager({
|
|
19362
|
+
client,
|
|
19363
|
+
offlineDb: this,
|
|
19364
|
+
syncMaxEventCount
|
|
19365
|
+
});
|
|
19048
19366
|
this.state = new StateStore({
|
|
19049
19367
|
initialized: false,
|
|
19050
19368
|
userId: this.client.userID
|
|
@@ -19382,6 +19700,7 @@ export {
|
|
|
19382
19700
|
createMessageComposerStateCompositionMiddleware,
|
|
19383
19701
|
createPollComposerStateMiddleware,
|
|
19384
19702
|
createPostUploadAttachmentEnrichmentMiddleware,
|
|
19703
|
+
createSendWithPendingUploadsAttachmentsMiddleware,
|
|
19385
19704
|
createSharedLocationCompositionMiddleware,
|
|
19386
19705
|
createTextComposerCompositionMiddleware,
|
|
19387
19706
|
createTextComposerPreValidationMiddleware,
|
|
@@ -19410,6 +19729,7 @@ export {
|
|
|
19410
19729
|
getTokenizedSuggestionDisplayName,
|
|
19411
19730
|
getTriggerCharWithToken,
|
|
19412
19731
|
gunzipPayload,
|
|
19732
|
+
hasPending,
|
|
19413
19733
|
insertItemWithTrigger,
|
|
19414
19734
|
isAudioAttachment,
|
|
19415
19735
|
isBlobButNotFile,
|
|
@@ -19417,6 +19737,7 @@ export {
|
|
|
19417
19737
|
isFileAttachment,
|
|
19418
19738
|
isFileList,
|
|
19419
19739
|
isFileReference,
|
|
19740
|
+
isFinishedUpload,
|
|
19420
19741
|
isGiphyAttachment,
|
|
19421
19742
|
isImageAttachment,
|
|
19422
19743
|
isImageFile,
|
|
@@ -19429,9 +19750,11 @@ export {
|
|
|
19429
19750
|
isLocalVoiceRecordingAttachment,
|
|
19430
19751
|
isOwnUser,
|
|
19431
19752
|
isPatch,
|
|
19753
|
+
isPendingUpload,
|
|
19432
19754
|
isScrapedContent,
|
|
19433
19755
|
isSharedLocationResponse,
|
|
19434
19756
|
isTargetedOptionTextUpdate,
|
|
19757
|
+
isUploadCancellation,
|
|
19435
19758
|
isUploadedAttachment,
|
|
19436
19759
|
isVideoAttachment,
|
|
19437
19760
|
isVoiceRecordingAttachment,
|
|
@@ -19451,11 +19774,14 @@ export {
|
|
|
19451
19774
|
readFileAsArrayBuffer,
|
|
19452
19775
|
removeDiacritics,
|
|
19453
19776
|
replaceWordWithEntity,
|
|
19777
|
+
settled,
|
|
19454
19778
|
stripCommandFromText,
|
|
19455
19779
|
stripMentionTokens,
|
|
19456
19780
|
textIsEmpty,
|
|
19457
19781
|
timeLeftMs,
|
|
19458
19782
|
verifyAndParseWebhook,
|
|
19459
|
-
verifySignature
|
|
19783
|
+
verifySignature,
|
|
19784
|
+
withCancellation,
|
|
19785
|
+
withoutConcurrency
|
|
19460
19786
|
};
|
|
19461
19787
|
//# sourceMappingURL=index.mjs.map
|