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/cjs/index.node.js
CHANGED
|
@@ -158,6 +158,7 @@ __export(index_exports, {
|
|
|
158
158
|
createMessageComposerStateCompositionMiddleware: () => createMessageComposerStateCompositionMiddleware,
|
|
159
159
|
createPollComposerStateMiddleware: () => createPollComposerStateMiddleware,
|
|
160
160
|
createPostUploadAttachmentEnrichmentMiddleware: () => createPostUploadAttachmentEnrichmentMiddleware,
|
|
161
|
+
createSendWithPendingUploadsAttachmentsMiddleware: () => createSendWithPendingUploadsAttachmentsMiddleware,
|
|
161
162
|
createSharedLocationCompositionMiddleware: () => createSharedLocationCompositionMiddleware,
|
|
162
163
|
createTextComposerCompositionMiddleware: () => createTextComposerCompositionMiddleware,
|
|
163
164
|
createTextComposerPreValidationMiddleware: () => createTextComposerPreValidationMiddleware,
|
|
@@ -186,6 +187,7 @@ __export(index_exports, {
|
|
|
186
187
|
getTokenizedSuggestionDisplayName: () => getTokenizedSuggestionDisplayName,
|
|
187
188
|
getTriggerCharWithToken: () => getTriggerCharWithToken,
|
|
188
189
|
gunzipPayload: () => gunzipPayload,
|
|
190
|
+
hasPending: () => hasPending,
|
|
189
191
|
insertItemWithTrigger: () => insertItemWithTrigger,
|
|
190
192
|
isAudioAttachment: () => isAudioAttachment,
|
|
191
193
|
isBlobButNotFile: () => isBlobButNotFile,
|
|
@@ -193,6 +195,7 @@ __export(index_exports, {
|
|
|
193
195
|
isFileAttachment: () => isFileAttachment,
|
|
194
196
|
isFileList: () => isFileList,
|
|
195
197
|
isFileReference: () => isFileReference,
|
|
198
|
+
isFinishedUpload: () => isFinishedUpload,
|
|
196
199
|
isGiphyAttachment: () => isGiphyAttachment,
|
|
197
200
|
isImageAttachment: () => isImageAttachment,
|
|
198
201
|
isImageFile: () => isImageFile,
|
|
@@ -205,9 +208,11 @@ __export(index_exports, {
|
|
|
205
208
|
isLocalVoiceRecordingAttachment: () => isLocalVoiceRecordingAttachment,
|
|
206
209
|
isOwnUser: () => isOwnUser,
|
|
207
210
|
isPatch: () => isPatch,
|
|
211
|
+
isPendingUpload: () => isPendingUpload,
|
|
208
212
|
isScrapedContent: () => isScrapedContent,
|
|
209
213
|
isSharedLocationResponse: () => isSharedLocationResponse,
|
|
210
214
|
isTargetedOptionTextUpdate: () => isTargetedOptionTextUpdate,
|
|
215
|
+
isUploadCancellation: () => isUploadCancellation,
|
|
211
216
|
isUploadedAttachment: () => isUploadedAttachment,
|
|
212
217
|
isVideoAttachment: () => isVideoAttachment,
|
|
213
218
|
isVoiceRecordingAttachment: () => isVoiceRecordingAttachment,
|
|
@@ -227,12 +232,15 @@ __export(index_exports, {
|
|
|
227
232
|
readFileAsArrayBuffer: () => readFileAsArrayBuffer,
|
|
228
233
|
removeDiacritics: () => removeDiacritics,
|
|
229
234
|
replaceWordWithEntity: () => replaceWordWithEntity,
|
|
235
|
+
settled: () => settled,
|
|
230
236
|
stripCommandFromText: () => stripCommandFromText,
|
|
231
237
|
stripMentionTokens: () => stripMentionTokens,
|
|
232
238
|
textIsEmpty: () => textIsEmpty,
|
|
233
239
|
timeLeftMs: () => timeLeftMs,
|
|
234
240
|
verifyAndParseWebhook: () => verifyAndParseWebhook,
|
|
235
|
-
verifySignature: () => verifySignature
|
|
241
|
+
verifySignature: () => verifySignature,
|
|
242
|
+
withCancellation: () => withCancellation,
|
|
243
|
+
withoutConcurrency: () => withoutConcurrency
|
|
236
244
|
});
|
|
237
245
|
module.exports = __toCommonJS(index_exports);
|
|
238
246
|
|
|
@@ -499,7 +507,7 @@ var ChannelBatchUpdater = class {
|
|
|
499
507
|
};
|
|
500
508
|
|
|
501
509
|
// src/client.ts
|
|
502
|
-
var
|
|
510
|
+
var import_axios4 = __toESM(require("axios"));
|
|
503
511
|
var import_https = __toESM(require("https"));
|
|
504
512
|
|
|
505
513
|
// src/utils.ts
|
|
@@ -759,6 +767,38 @@ function unformatMessage(message) {
|
|
|
759
767
|
quoted_message: toMessageResponseBase(message.quoted_message)
|
|
760
768
|
};
|
|
761
769
|
}
|
|
770
|
+
var isRemoteUrl = (url) => !!url && /^https?:\/\//i.test(url.trim());
|
|
771
|
+
var sanitizeOutgoingAttachments = ({
|
|
772
|
+
client,
|
|
773
|
+
message
|
|
774
|
+
}) => {
|
|
775
|
+
const attachments = message.attachments;
|
|
776
|
+
if (!attachments?.length) return message;
|
|
777
|
+
const unresolved = [];
|
|
778
|
+
let changed = false;
|
|
779
|
+
const sanitized = attachments.reduce((acc, attachment) => {
|
|
780
|
+
const { localMetadata, ...rest } = attachment;
|
|
781
|
+
if (!localMetadata) {
|
|
782
|
+
acc.push(attachment);
|
|
783
|
+
return acc;
|
|
784
|
+
}
|
|
785
|
+
changed = true;
|
|
786
|
+
const hasRemoteSource = isRemoteUrl(rest.asset_url) || isRemoteUrl(rest.image_url) || isRemoteUrl(rest.og_scrape_url) || isRemoteUrl(rest.title_link);
|
|
787
|
+
if (hasRemoteSource) {
|
|
788
|
+
acc.push(rest);
|
|
789
|
+
} else {
|
|
790
|
+
unresolved.push(rest);
|
|
791
|
+
}
|
|
792
|
+
return acc;
|
|
793
|
+
}, []);
|
|
794
|
+
if (unresolved.length) {
|
|
795
|
+
const text = `Dropped ${unresolved.length} attachment(s) whose upload never completed. Composing with pending uploads requires awaiting them before sending.`;
|
|
796
|
+
const extraData = { attachments: unresolved, message, tags: ["attachments"] };
|
|
797
|
+
client.logger("warn", text, extraData);
|
|
798
|
+
console.warn(text, extraData);
|
|
799
|
+
}
|
|
800
|
+
return changed ? { ...message, attachments: sanitized } : message;
|
|
801
|
+
};
|
|
762
802
|
var localMessageToNewMessagePayload = (localMessage) => {
|
|
763
803
|
const {
|
|
764
804
|
// Remove all timestamp fields and client-specific fields.
|
|
@@ -967,7 +1007,8 @@ var debounce = (fn, timeout = 0, { leading = false, trailing = true } = {}) => {
|
|
|
967
1007
|
}
|
|
968
1008
|
runningTimeout = null;
|
|
969
1009
|
};
|
|
970
|
-
|
|
1010
|
+
const delay = typeof timeout === "function" ? timeout(...args) : timeout;
|
|
1011
|
+
runningTimeout = setTimeout(timeoutHandler, delay);
|
|
971
1012
|
return lastResult;
|
|
972
1013
|
};
|
|
973
1014
|
debouncedFn.cancel = () => {
|
|
@@ -2530,6 +2571,12 @@ var CooldownTimer = class extends WithSubscriptions {
|
|
|
2530
2571
|
var isScrapedContent = (attachment) => !!attachment?.og_scrape_url || !!attachment?.title_link;
|
|
2531
2572
|
var isLocalAttachment = (attachment) => !!attachment?.localMetadata?.id;
|
|
2532
2573
|
var isLocalUploadAttachment = (attachment) => !!attachment?.localMetadata?.uploadState;
|
|
2574
|
+
var PENDING_UPLOAD_STATES = [
|
|
2575
|
+
"pending",
|
|
2576
|
+
"uploading"
|
|
2577
|
+
];
|
|
2578
|
+
var isPendingUpload = (attachment) => isLocalUploadAttachment(attachment) && PENDING_UPLOAD_STATES.includes(attachment.localMetadata.uploadState);
|
|
2579
|
+
var isFinishedUpload = (attachment) => isLocalUploadAttachment(attachment) && attachment.localMetadata.uploadState === "finished";
|
|
2533
2580
|
var isFileAttachment = (attachment, supportedVideoFormat = []) => attachment.type === "file" || !!(attachment.mime_type && supportedVideoFormat.indexOf(attachment.mime_type) === -1 && attachment.type !== "video");
|
|
2534
2581
|
var isLocalFileAttachment = (attachment) => isFileAttachment(attachment) && isLocalAttachment(attachment);
|
|
2535
2582
|
var isImageAttachment = (attachment) => attachment.type === "image" && !isScrapedContent(attachment);
|
|
@@ -2605,7 +2652,7 @@ var ensureIsLocalAttachment = (attachment) => {
|
|
|
2605
2652
|
};
|
|
2606
2653
|
|
|
2607
2654
|
// src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts
|
|
2608
|
-
var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
2655
|
+
var createPostUploadAttachmentEnrichmentMiddleware = (composer) => ({
|
|
2609
2656
|
id: "stream-io/attachment-manager-middleware/post-upload-enrichment",
|
|
2610
2657
|
handlers: {
|
|
2611
2658
|
postProcess: ({
|
|
@@ -2618,9 +2665,10 @@ var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
|
2618
2665
|
if (error) return forward();
|
|
2619
2666
|
if (!attachment || !response) return discard();
|
|
2620
2667
|
const enrichedAttachment = { ...attachment };
|
|
2621
|
-
const previewUri = attachment.localMetadata
|
|
2622
|
-
|
|
2623
|
-
|
|
2668
|
+
const { id, previewUri } = attachment.localMetadata;
|
|
2669
|
+
const attachmentIsStillInComposer = !composer || !!composer.attachmentManager.attachmentsById[id];
|
|
2670
|
+
if (previewUri && attachmentIsStillInComposer) {
|
|
2671
|
+
if (previewUri.startsWith("blob:")) URL.revokeObjectURL?.(previewUri);
|
|
2624
2672
|
delete enrichedAttachment.localMetadata.previewUri;
|
|
2625
2673
|
}
|
|
2626
2674
|
if (isLocalImageAttachment(attachment)) {
|
|
@@ -2643,6 +2691,12 @@ var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
|
2643
2691
|
var withoutConcurrency = createRunner(wrapWithContinuationTracking);
|
|
2644
2692
|
var withCancellation = createRunner(wrapWithCancellation);
|
|
2645
2693
|
var pendingPromises = /* @__PURE__ */ new Map();
|
|
2694
|
+
function hasPending(tag) {
|
|
2695
|
+
return pendingPromises.has(tag);
|
|
2696
|
+
}
|
|
2697
|
+
async function settled(tag) {
|
|
2698
|
+
await pendingPromises.get(tag)?.promise;
|
|
2699
|
+
}
|
|
2646
2700
|
function createRunner(wrapper) {
|
|
2647
2701
|
return function run(tag, cb) {
|
|
2648
2702
|
const { cb: wrapped, onContinued } = wrapper(tag, cb);
|
|
@@ -2685,6 +2739,16 @@ var MiddlewareExecutor = class {
|
|
|
2685
2739
|
this.middleware = [];
|
|
2686
2740
|
this.id = generateUUIDv4();
|
|
2687
2741
|
}
|
|
2742
|
+
/**
|
|
2743
|
+
* The middleware currently installed, in execution order.
|
|
2744
|
+
*
|
|
2745
|
+
* Read-only: use `use` / `insert` / `replace` / `setOrder` / `remove` to change the chain. It
|
|
2746
|
+
* exists so components can ask what the chain is capable of - a middleware may declare
|
|
2747
|
+
* behaviour its host has to account for, and the host has no other way to find out.
|
|
2748
|
+
*/
|
|
2749
|
+
get installedMiddleware() {
|
|
2750
|
+
return this.middleware;
|
|
2751
|
+
}
|
|
2688
2752
|
use(middleware) {
|
|
2689
2753
|
this.middleware = this.middleware.concat(middleware);
|
|
2690
2754
|
return this;
|
|
@@ -2788,6 +2852,142 @@ var MiddlewareExecutor = class {
|
|
|
2788
2852
|
}
|
|
2789
2853
|
};
|
|
2790
2854
|
|
|
2855
|
+
// src/uploadManager.ts
|
|
2856
|
+
var import_axios = __toESM(require("axios"));
|
|
2857
|
+
var isUploadCancellation = (error) => import_axios.default.isCancel(error) || error instanceof Error && error.name === "AbortError";
|
|
2858
|
+
var initState = () => ({ uploads: {} });
|
|
2859
|
+
var upsertById = (uploads, record) => ({
|
|
2860
|
+
...uploads,
|
|
2861
|
+
[record.id]: { ...uploads[record.id], ...record }
|
|
2862
|
+
});
|
|
2863
|
+
var updateById = (uploads, record) => {
|
|
2864
|
+
if (!(record.id in uploads)) return null;
|
|
2865
|
+
const current = uploads[record.id];
|
|
2866
|
+
return { ...uploads, [record.id]: { ...current, ...record } };
|
|
2867
|
+
};
|
|
2868
|
+
var UploadManager = class {
|
|
2869
|
+
constructor(client) {
|
|
2870
|
+
this.client = client;
|
|
2871
|
+
this.inFlightUploads = /* @__PURE__ */ new Map();
|
|
2872
|
+
this.getUpload = (id) => this.uploads[id];
|
|
2873
|
+
/**
|
|
2874
|
+
* Clears all upload records.
|
|
2875
|
+
* Invoked when the user disconnects so a later session does not inherit stale upload state.
|
|
2876
|
+
* Aborts every in-flight upload request via its `UploadRequestOptions.abortSignal`.
|
|
2877
|
+
*/
|
|
2878
|
+
this.reset = () => {
|
|
2879
|
+
for (const { abortController } of this.inFlightUploads.values()) {
|
|
2880
|
+
abortController.abort();
|
|
2881
|
+
}
|
|
2882
|
+
this.inFlightUploads.clear();
|
|
2883
|
+
this.state.next(initState());
|
|
2884
|
+
};
|
|
2885
|
+
/**
|
|
2886
|
+
* Removes the upload record for `id` if present.
|
|
2887
|
+
* If an upload is still in progress, aborts its `UploadRequestOptions.abortSignal`.
|
|
2888
|
+
*/
|
|
2889
|
+
this.deleteUploadRecord = (id) => {
|
|
2890
|
+
const flight = this.inFlightUploads.get(id);
|
|
2891
|
+
if (flight) {
|
|
2892
|
+
this.inFlightUploads.delete(id);
|
|
2893
|
+
flight.abortController.abort();
|
|
2894
|
+
}
|
|
2895
|
+
this.state.next((current) => {
|
|
2896
|
+
if (!(id in current.uploads)) return current;
|
|
2897
|
+
const uploads = { ...current.uploads };
|
|
2898
|
+
delete uploads[id];
|
|
2899
|
+
return { ...current, uploads };
|
|
2900
|
+
});
|
|
2901
|
+
};
|
|
2902
|
+
/**
|
|
2903
|
+
* Starts an upload for `id`, or returns the existing in-flight promise if one is already running.
|
|
2904
|
+
* Uses {@link StreamChat.channel}(`channelCid`) → `messageComposer.attachmentManager.doUploadRequest`.
|
|
2905
|
+
* Resolves with that result; rejects if the upload rejects (the record is removed from state either way).
|
|
2906
|
+
*/
|
|
2907
|
+
this.upload = ({
|
|
2908
|
+
id,
|
|
2909
|
+
channelCid,
|
|
2910
|
+
file
|
|
2911
|
+
}) => {
|
|
2912
|
+
const existing = this.inFlightUploads.get(id);
|
|
2913
|
+
if (existing) return existing.promise;
|
|
2914
|
+
let resolvePromise;
|
|
2915
|
+
let rejectPromise;
|
|
2916
|
+
const promise = new Promise((resolve, reject) => {
|
|
2917
|
+
resolvePromise = resolve;
|
|
2918
|
+
rejectPromise = reject;
|
|
2919
|
+
});
|
|
2920
|
+
const abortController = new AbortController();
|
|
2921
|
+
this.inFlightUploads.set(id, { promise, abortController });
|
|
2922
|
+
void (async () => {
|
|
2923
|
+
const attachmentManager = this.resolveAttachmentManager(channelCid);
|
|
2924
|
+
const trackProgress = attachmentManager.config.trackUploadProgress;
|
|
2925
|
+
try {
|
|
2926
|
+
this.upsertUpload({
|
|
2927
|
+
uploadConfirmationPending: false,
|
|
2928
|
+
id,
|
|
2929
|
+
uploadProgress: trackProgress ? 0 : void 0
|
|
2930
|
+
});
|
|
2931
|
+
const onProgress = trackProgress ? (progress) => {
|
|
2932
|
+
this.updateUpload({
|
|
2933
|
+
id,
|
|
2934
|
+
uploadProgress: progress,
|
|
2935
|
+
// Only a number says anything about the flush, so a report without one leaves
|
|
2936
|
+
// the flag alone: `undefined` means the transport cannot measure this upload,
|
|
2937
|
+
// not that bytes were un-sent. Lowering it there would drop a UI that had
|
|
2938
|
+
// already gone indeterminate back to a determinate one with nothing to show.
|
|
2939
|
+
//
|
|
2940
|
+
// The record is removed in the `finally` below, so a record that still exists
|
|
2941
|
+
// while reporting 100% can only mean "flushed, awaiting the response".
|
|
2942
|
+
...typeof progress === "number" ? { uploadConfirmationPending: progress >= 100 } : {}
|
|
2943
|
+
});
|
|
2944
|
+
} : void 0;
|
|
2945
|
+
const uploadRequestOptions = {
|
|
2946
|
+
abortSignal: abortController.signal,
|
|
2947
|
+
...onProgress ? { onProgress } : {}
|
|
2948
|
+
};
|
|
2949
|
+
const response = await attachmentManager.doUploadRequest(
|
|
2950
|
+
file,
|
|
2951
|
+
uploadRequestOptions
|
|
2952
|
+
);
|
|
2953
|
+
resolvePromise(response);
|
|
2954
|
+
} catch (error) {
|
|
2955
|
+
rejectPromise(error);
|
|
2956
|
+
} finally {
|
|
2957
|
+
this.inFlightUploads.delete(id);
|
|
2958
|
+
this.deleteUploadRecord(id);
|
|
2959
|
+
}
|
|
2960
|
+
})();
|
|
2961
|
+
return promise;
|
|
2962
|
+
};
|
|
2963
|
+
this.upsertUpload = (record) => {
|
|
2964
|
+
this.state.partialNext({
|
|
2965
|
+
uploads: upsertById(this.uploads, record)
|
|
2966
|
+
});
|
|
2967
|
+
};
|
|
2968
|
+
this.updateUpload = (record) => {
|
|
2969
|
+
this.state.next((current) => {
|
|
2970
|
+
const nextUploads = updateById(current.uploads, record);
|
|
2971
|
+
if (!nextUploads) return current;
|
|
2972
|
+
return { ...current, uploads: nextUploads };
|
|
2973
|
+
});
|
|
2974
|
+
};
|
|
2975
|
+
this.state = new StateStore(initState());
|
|
2976
|
+
}
|
|
2977
|
+
resolveAttachmentManager(channelCid) {
|
|
2978
|
+
const colon = channelCid.indexOf(":");
|
|
2979
|
+
if (colon <= 0 || colon === channelCid.length - 1) {
|
|
2980
|
+
throw new Error(`Invalid channelCid: ${channelCid}`);
|
|
2981
|
+
}
|
|
2982
|
+
const channelType = channelCid.slice(0, colon);
|
|
2983
|
+
const channelId = channelCid.slice(colon + 1);
|
|
2984
|
+
return this.client.channel(channelType, channelId).messageComposer.attachmentManager;
|
|
2985
|
+
}
|
|
2986
|
+
get uploads() {
|
|
2987
|
+
return this.state.getLatestValue().uploads;
|
|
2988
|
+
}
|
|
2989
|
+
};
|
|
2990
|
+
|
|
2791
2991
|
// src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts
|
|
2792
2992
|
var createUploadErrorHandlerMiddleware = (composer) => ({
|
|
2793
2993
|
id: "stream-io/attachment-manager-middleware/upload-error",
|
|
@@ -2800,6 +3000,7 @@ var createUploadErrorHandlerMiddleware = (composer) => ({
|
|
|
2800
3000
|
const { attachment, error } = state;
|
|
2801
3001
|
if (!error) return forward();
|
|
2802
3002
|
if (!attachment) return discard();
|
|
3003
|
+
if (isUploadCancellation(error)) return forward();
|
|
2803
3004
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2804
3005
|
composer.client.notifications.addError({
|
|
2805
3006
|
message: "Error uploading attachment",
|
|
@@ -2824,7 +3025,7 @@ var AttachmentPostUploadMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
|
2824
3025
|
super();
|
|
2825
3026
|
this.use([
|
|
2826
3027
|
createUploadErrorHandlerMiddleware(composer),
|
|
2827
|
-
createPostUploadAttachmentEnrichmentMiddleware()
|
|
3028
|
+
createPostUploadAttachmentEnrichmentMiddleware(composer)
|
|
2828
3029
|
]);
|
|
2829
3030
|
}
|
|
2830
3031
|
};
|
|
@@ -3272,7 +3473,7 @@ function mergeWithDiff(target, source, customizer) {
|
|
|
3272
3473
|
}
|
|
3273
3474
|
|
|
3274
3475
|
// src/messageComposer/attachmentManager.ts
|
|
3275
|
-
var
|
|
3476
|
+
var initState2 = ({
|
|
3276
3477
|
message
|
|
3277
3478
|
}) => ({
|
|
3278
3479
|
attachments: (message?.attachments ?? [])?.filter(({ og_scrape_url }) => !og_scrape_url).map((att) => {
|
|
@@ -3300,13 +3501,14 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3300
3501
|
...attachment,
|
|
3301
3502
|
localMetadata: {
|
|
3302
3503
|
...attachment.localMetadata,
|
|
3504
|
+
uploadConfirmationPending: false,
|
|
3303
3505
|
uploadProgress: void 0,
|
|
3304
3506
|
uploadState: "failed"
|
|
3305
3507
|
}
|
|
3306
3508
|
};
|
|
3307
3509
|
};
|
|
3308
3510
|
this.initState = ({ message } = {}) => {
|
|
3309
|
-
this.state.next(
|
|
3511
|
+
this.state.next(initState2({ message }));
|
|
3310
3512
|
};
|
|
3311
3513
|
this.getSnapshot = () => {
|
|
3312
3514
|
const state = this.state.getLatestValue();
|
|
@@ -3383,8 +3585,22 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3383
3585
|
this.state.partialNext({ attachments });
|
|
3384
3586
|
}
|
|
3385
3587
|
};
|
|
3588
|
+
/**
|
|
3589
|
+
* Releases a local preview URL the SDK minted, if it minted one.
|
|
3590
|
+
*
|
|
3591
|
+
* Only `blob:` URLs are ours to revoke: `toLocalUploadAttachment` puts a
|
|
3592
|
+
* `URL.createObjectURL` result in `previewUri` for a `File`, but for a React Native
|
|
3593
|
+
* `FileReference` it stores the caller's own native file URI, which must be left alone.
|
|
3594
|
+
*/
|
|
3595
|
+
this.revokePreviewUri = (attachment) => {
|
|
3596
|
+
const previewUri = attachment.localMetadata?.previewUri;
|
|
3597
|
+
if (previewUri?.startsWith("blob:")) URL.revokeObjectURL?.(previewUri);
|
|
3598
|
+
};
|
|
3386
3599
|
this.removeAttachments = (localAttachmentIds) => {
|
|
3387
3600
|
if (!localAttachmentIds.length) return;
|
|
3601
|
+
const removedAttachments = this.attachments.filter(
|
|
3602
|
+
(attachment) => localAttachmentIds.includes(attachment.localMetadata?.id)
|
|
3603
|
+
);
|
|
3388
3604
|
this.state.partialNext({
|
|
3389
3605
|
attachments: this.attachments.filter(
|
|
3390
3606
|
(attachment) => !localAttachmentIds.includes(attachment.localMetadata?.id)
|
|
@@ -3393,6 +3609,7 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3393
3609
|
for (const id of localAttachmentIds) {
|
|
3394
3610
|
this.client.uploadManager.deleteUploadRecord(id);
|
|
3395
3611
|
}
|
|
3612
|
+
removedAttachments.forEach(this.revokePreviewUri);
|
|
3396
3613
|
};
|
|
3397
3614
|
this.getUploadConfigCheck = async (fileLike) => {
|
|
3398
3615
|
const client = this.channel.getClient();
|
|
@@ -3544,21 +3761,27 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3544
3761
|
localMetadata: {
|
|
3545
3762
|
...attachment.localMetadata,
|
|
3546
3763
|
uploadState: "failed",
|
|
3547
|
-
uploadProgress: void 0
|
|
3764
|
+
uploadProgress: void 0,
|
|
3765
|
+
// `false`, not `undefined`: these updates go through `updateAttachment`, which merges
|
|
3766
|
+
// via `mergeWith` — and that skips `undefined` source values, so `undefined` would
|
|
3767
|
+
// leave a stale `true` in place.
|
|
3768
|
+
uploadConfirmationPending: false
|
|
3548
3769
|
}
|
|
3549
3770
|
};
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3771
|
+
if (!isUploadCancellation(error)) {
|
|
3772
|
+
this.client.notifications.addError({
|
|
3773
|
+
message: "Error uploading attachment",
|
|
3774
|
+
origin: {
|
|
3775
|
+
emitter: "AttachmentManager",
|
|
3776
|
+
context: { attachment, failedAttachment }
|
|
3777
|
+
},
|
|
3778
|
+
options: {
|
|
3779
|
+
type: "api:attachment:upload:failed",
|
|
3780
|
+
metadata: { reason },
|
|
3781
|
+
originalError: error instanceof Error ? error : void 0
|
|
3782
|
+
}
|
|
3783
|
+
});
|
|
3784
|
+
}
|
|
3562
3785
|
this.updateAttachment(failedAttachment);
|
|
3563
3786
|
return failedAttachment;
|
|
3564
3787
|
}
|
|
@@ -3571,7 +3794,9 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3571
3794
|
localMetadata: {
|
|
3572
3795
|
...attachment.localMetadata,
|
|
3573
3796
|
uploadState: "finished",
|
|
3574
|
-
uploadProgress: void 0
|
|
3797
|
+
uploadProgress: void 0,
|
|
3798
|
+
// See the note in the failure branch: `undefined` cannot clear through `mergeWith`.
|
|
3799
|
+
uploadConfirmationPending: false
|
|
3575
3800
|
}
|
|
3576
3801
|
};
|
|
3577
3802
|
const previewUri = uploadedAttachment.localMetadata.previewUri;
|
|
@@ -3620,7 +3845,9 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3620
3845
|
localMetadata: {
|
|
3621
3846
|
...attachment.localMetadata,
|
|
3622
3847
|
uploadState: error ? "failed" : "finished",
|
|
3623
|
-
uploadProgress: void 0
|
|
3848
|
+
uploadProgress: void 0,
|
|
3849
|
+
// See the note in `uploadAttachment`: `undefined` cannot clear through `mergeWith`.
|
|
3850
|
+
uploadConfirmationPending: false
|
|
3624
3851
|
}
|
|
3625
3852
|
},
|
|
3626
3853
|
error,
|
|
@@ -3645,7 +3872,7 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3645
3872
|
);
|
|
3646
3873
|
};
|
|
3647
3874
|
this.composer = composer;
|
|
3648
|
-
this.state = new StateStore(
|
|
3875
|
+
this.state = new StateStore(initState2({ message }));
|
|
3649
3876
|
this.attachmentsByIdGetterCache = { attachmentsById: {}, attachments: [] };
|
|
3650
3877
|
this.preUploadMiddlewareExecutor = new AttachmentPreUploadMiddlewareExecutor({
|
|
3651
3878
|
composer
|
|
@@ -3750,7 +3977,8 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3750
3977
|
localMetadata: {
|
|
3751
3978
|
...attachment.localMetadata,
|
|
3752
3979
|
uploadState: "uploading",
|
|
3753
|
-
uploadProgress: this.config.trackUploadProgress ? 0 : void 0
|
|
3980
|
+
uploadProgress: this.config.trackUploadProgress ? 0 : void 0,
|
|
3981
|
+
uploadConfirmationPending: false
|
|
3754
3982
|
}
|
|
3755
3983
|
}
|
|
3756
3984
|
]);
|
|
@@ -3763,7 +3991,8 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3763
3991
|
localMetadata: {
|
|
3764
3992
|
...attachment.localMetadata,
|
|
3765
3993
|
uploadState: "uploading",
|
|
3766
|
-
uploadProgress: nextUpload.uploadProgress
|
|
3994
|
+
uploadProgress: nextUpload.uploadProgress,
|
|
3995
|
+
uploadConfirmationPending: nextUpload.uploadConfirmationPending
|
|
3767
3996
|
}
|
|
3768
3997
|
});
|
|
3769
3998
|
}
|
|
@@ -3817,6 +4046,50 @@ var localAttachmentToAttachment = (localAttachment) => {
|
|
|
3817
4046
|
const { localMetadata, ...attachment } = localAttachment;
|
|
3818
4047
|
return attachment;
|
|
3819
4048
|
};
|
|
4049
|
+
var composeWithPendingUploads = ({
|
|
4050
|
+
composer,
|
|
4051
|
+
state
|
|
4052
|
+
}) => {
|
|
4053
|
+
const composerIsKeptAsDraft = !!composer.pollId;
|
|
4054
|
+
const relevantAttachments = composer.attachmentManager.attachments.filter(
|
|
4055
|
+
(attachment) => isFinishedUpload(attachment) || !composerIsKeptAsDraft && isPendingUpload(attachment)
|
|
4056
|
+
);
|
|
4057
|
+
const localAttachments = (state.localMessage.attachments ?? []).concat(
|
|
4058
|
+
relevantAttachments.map(
|
|
4059
|
+
(attachment) => isPendingUpload(attachment) ? attachment : localAttachmentToAttachment(attachment)
|
|
4060
|
+
)
|
|
4061
|
+
);
|
|
4062
|
+
const messageAttachments = (state.message.attachments ?? []).concat(
|
|
4063
|
+
relevantAttachments.filter(isFinishedUpload).map(localAttachmentToAttachment)
|
|
4064
|
+
);
|
|
4065
|
+
if (!localAttachments.length && !messageAttachments.length) return state;
|
|
4066
|
+
return {
|
|
4067
|
+
...state,
|
|
4068
|
+
localMessage: localAttachments.length ? {
|
|
4069
|
+
...state.localMessage,
|
|
4070
|
+
attachments: localAttachments
|
|
4071
|
+
} : state.localMessage,
|
|
4072
|
+
message: messageAttachments.length ? {
|
|
4073
|
+
...state.message,
|
|
4074
|
+
attachments: messageAttachments
|
|
4075
|
+
} : state.message
|
|
4076
|
+
};
|
|
4077
|
+
};
|
|
4078
|
+
var createSendWithPendingUploadsAttachmentsMiddleware = (composer) => ({
|
|
4079
|
+
allowsPendingUploads: true,
|
|
4080
|
+
id: "stream-io/message-composer-middleware/attachments",
|
|
4081
|
+
handlers: {
|
|
4082
|
+
compose: ({
|
|
4083
|
+
state,
|
|
4084
|
+
next,
|
|
4085
|
+
forward
|
|
4086
|
+
}) => {
|
|
4087
|
+
const { attachmentManager } = composer;
|
|
4088
|
+
if (!attachmentManager) return forward();
|
|
4089
|
+
return next(composeWithPendingUploads({ composer, state }));
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
});
|
|
3820
4093
|
var createAttachmentsCompositionMiddleware = (composer) => ({
|
|
3821
4094
|
id: "stream-io/message-composer-middleware/attachments",
|
|
3822
4095
|
handlers: {
|
|
@@ -4033,7 +4306,7 @@ var getInitialMentions = (message) => {
|
|
|
4033
4306
|
};
|
|
4034
4307
|
var isSameMentionEntity = (first, second) => first.id === second.id && first.mentionType === second.mentionType;
|
|
4035
4308
|
var getMentionsFromState = (state) => state.mentions ?? state.mentionedUsers.map(userResponseToMentionEntity);
|
|
4036
|
-
var
|
|
4309
|
+
var initState3 = ({
|
|
4037
4310
|
composer,
|
|
4038
4311
|
message
|
|
4039
4312
|
}) => {
|
|
@@ -4062,7 +4335,7 @@ var initState2 = ({
|
|
|
4062
4335
|
var TextComposer = class {
|
|
4063
4336
|
constructor({ composer, message }) {
|
|
4064
4337
|
this.initState = ({ message } = {}) => {
|
|
4065
|
-
this.state.next(
|
|
4338
|
+
this.state.next(initState3({ composer: this.composer, message }));
|
|
4066
4339
|
};
|
|
4067
4340
|
this.getSnapshot = (state = this.state.getLatestValue()) => state;
|
|
4068
4341
|
this.restoreSnapshot = (snapshot) => {
|
|
@@ -4255,7 +4528,7 @@ var TextComposer = class {
|
|
|
4255
4528
|
this.commitState(output.state);
|
|
4256
4529
|
};
|
|
4257
4530
|
this.composer = composer;
|
|
4258
|
-
this.state = new StateStore(
|
|
4531
|
+
this.state = new StateStore(initState3({ composer, message }));
|
|
4259
4532
|
this.middlewareExecutor = new TextComposerMiddlewareExecutor({ composer });
|
|
4260
4533
|
}
|
|
4261
4534
|
get channel() {
|
|
@@ -4405,13 +4678,41 @@ function isErrorResponse(res) {
|
|
|
4405
4678
|
|
|
4406
4679
|
// src/search/BaseSearchSource.ts
|
|
4407
4680
|
var DEFAULT_SEARCH_SOURCE_OPTIONS = {
|
|
4408
|
-
debounceMs: 300,
|
|
4409
4681
|
pageSize: 10,
|
|
4410
4682
|
allowEmptySearchString: false,
|
|
4411
4683
|
resetOnNewSearchQuery: true
|
|
4412
4684
|
};
|
|
4685
|
+
var resolveDebounceOptions = ({
|
|
4686
|
+
debounceMs,
|
|
4687
|
+
shortQueryDebounceMs,
|
|
4688
|
+
longQueryDebounceMs,
|
|
4689
|
+
shortQueryMaxLength
|
|
4690
|
+
}) => ({
|
|
4691
|
+
shortQueryDebounceMs: shortQueryDebounceMs ?? debounceMs ?? 500,
|
|
4692
|
+
longQueryDebounceMs: longQueryDebounceMs ?? debounceMs ?? 300,
|
|
4693
|
+
shortQueryMaxLength: shortQueryMaxLength ?? 2
|
|
4694
|
+
});
|
|
4413
4695
|
var BaseSearchSourceBase = class {
|
|
4414
4696
|
constructor(options) {
|
|
4697
|
+
this.setDebounceOptions = (options = {}) => {
|
|
4698
|
+
const resolved = resolveDebounceOptions(options);
|
|
4699
|
+
this.shortQueryDebounceMs = resolved.shortQueryDebounceMs;
|
|
4700
|
+
this.longQueryDebounceMs = resolved.longQueryDebounceMs;
|
|
4701
|
+
this.shortQueryMaxLength = resolved.shortQueryMaxLength;
|
|
4702
|
+
this.searchDebounced = debounce(
|
|
4703
|
+
this.executeQuery.bind(this),
|
|
4704
|
+
(searchString) => this.getDebounceMs(searchString)
|
|
4705
|
+
);
|
|
4706
|
+
};
|
|
4707
|
+
/**
|
|
4708
|
+
* Short queries match too much and are slow server-side, so they get a longer debounce.
|
|
4709
|
+
* Resolved per call, which is what lets the interval switch as the user keeps typing.
|
|
4710
|
+
*/
|
|
4711
|
+
this.getDebounceMs = (searchString) => {
|
|
4712
|
+
const { length } = searchString ?? this.searchQuery;
|
|
4713
|
+
return length <= this.shortQueryMaxLength ? this.shortQueryDebounceMs : this.longQueryDebounceMs;
|
|
4714
|
+
};
|
|
4715
|
+
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
4415
4716
|
this.activate = () => {
|
|
4416
4717
|
if (this.isActive) return;
|
|
4417
4718
|
this.state.partialNext({ isActive: true });
|
|
@@ -4423,7 +4724,7 @@ var BaseSearchSourceBase = class {
|
|
|
4423
4724
|
this.canExecuteQuery = (newSearchString) => {
|
|
4424
4725
|
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
4425
4726
|
const searchString = newSearchString ?? this.searchQuery;
|
|
4426
|
-
return !!(this.isActive &&
|
|
4727
|
+
return !!(this.isActive && this.canDispatchQuery(hasNewSearchQuery) && (this.allowEmptySearchString || searchString));
|
|
4427
4728
|
};
|
|
4428
4729
|
const { pageSize, allowEmptySearchString, resetOnNewSearchQuery } = {
|
|
4429
4730
|
...DEFAULT_SEARCH_SOURCE_OPTIONS,
|
|
@@ -4433,6 +4734,14 @@ var BaseSearchSourceBase = class {
|
|
|
4433
4734
|
this.allowEmptySearchString = allowEmptySearchString;
|
|
4434
4735
|
this.resetOnNewSearchQuery = resetOnNewSearchQuery;
|
|
4435
4736
|
this.state = new StateStore(this.initialState);
|
|
4737
|
+
this.setDebounceOptions(options ?? {});
|
|
4738
|
+
}
|
|
4739
|
+
/**
|
|
4740
|
+
* A new search query preempts an in-flight one; pagination waits for it to finish
|
|
4741
|
+
* and needs a next page to fetch.
|
|
4742
|
+
*/
|
|
4743
|
+
canDispatchQuery(hasNewSearchQuery) {
|
|
4744
|
+
return hasNewSearchQuery || !this.isLoading && this.hasNext;
|
|
4436
4745
|
}
|
|
4437
4746
|
get lastQueryError() {
|
|
4438
4747
|
return this.state.getLatestValue().lastQueryError;
|
|
@@ -4527,21 +4836,30 @@ var BaseSearchSourceBase = class {
|
|
|
4527
4836
|
}
|
|
4528
4837
|
};
|
|
4529
4838
|
var BaseSearchSource = class extends BaseSearchSourceBase {
|
|
4530
|
-
constructor(
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
this.
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
this.
|
|
4839
|
+
constructor() {
|
|
4840
|
+
super(...arguments);
|
|
4841
|
+
/** Aborts the in-flight request, if any, once a newer query is dispatched. */
|
|
4842
|
+
this.queryAbortController = null;
|
|
4843
|
+
}
|
|
4844
|
+
/** Aborts the in-flight request, if any. Returns true when one was aborted. */
|
|
4845
|
+
abortInFlightQuery() {
|
|
4846
|
+
if (!this.queryAbortController) return false;
|
|
4847
|
+
this.queryAbortController.abort();
|
|
4848
|
+
this.queryAbortController = null;
|
|
4849
|
+
return true;
|
|
4850
|
+
}
|
|
4851
|
+
resetState() {
|
|
4852
|
+
this.abortInFlightQuery();
|
|
4853
|
+
super.resetState();
|
|
4538
4854
|
}
|
|
4539
4855
|
async executeQuery(newSearchString) {
|
|
4540
4856
|
if (!this.canExecuteQuery(newSearchString)) return;
|
|
4857
|
+
this.abortInFlightQuery();
|
|
4858
|
+
const { signal } = this.queryAbortController = new AbortController();
|
|
4541
4859
|
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
4542
4860
|
let stateUpdate = {};
|
|
4543
4861
|
try {
|
|
4544
|
-
const results = await this.query(searchString);
|
|
4862
|
+
const results = await this.query(searchString, { signal });
|
|
4545
4863
|
if (!results) return;
|
|
4546
4864
|
const { items } = results;
|
|
4547
4865
|
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
@@ -4552,23 +4870,19 @@ var BaseSearchSource = class extends BaseSearchSourceBase {
|
|
|
4552
4870
|
stateUpdate.hasNext = false;
|
|
4553
4871
|
}
|
|
4554
4872
|
} finally {
|
|
4555
|
-
|
|
4873
|
+
if (!signal.aborted) {
|
|
4874
|
+
this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
|
|
4875
|
+
}
|
|
4556
4876
|
}
|
|
4557
4877
|
}
|
|
4558
4878
|
cancelScheduledQuery() {
|
|
4559
4879
|
this.searchDebounced.cancel();
|
|
4880
|
+
if (this.abortInFlightQuery() && this.isLoading) {
|
|
4881
|
+
this.state.partialNext({ isLoading: false });
|
|
4882
|
+
}
|
|
4560
4883
|
}
|
|
4561
4884
|
};
|
|
4562
4885
|
var BaseSearchSourceSync = class extends BaseSearchSourceBase {
|
|
4563
|
-
constructor(options) {
|
|
4564
|
-
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
4565
|
-
super(options);
|
|
4566
|
-
this.setDebounceOptions = ({ debounceMs }) => {
|
|
4567
|
-
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
4568
|
-
};
|
|
4569
|
-
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
4570
|
-
this.setDebounceOptions({ debounceMs });
|
|
4571
|
-
}
|
|
4572
4886
|
executeQuery(newSearchString) {
|
|
4573
4887
|
if (!this.canExecuteQuery(newSearchString)) return;
|
|
4574
4888
|
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
@@ -4864,13 +5178,13 @@ var UserGroupPaginator = class extends BasePaginator {
|
|
|
4864
5178
|
// src/search/ChannelMemberSearchSource.ts
|
|
4865
5179
|
var ChannelMemberSearchSource = class extends BaseSearchSource {
|
|
4866
5180
|
constructor(channel, options, filterBuilderOptions = {}) {
|
|
4867
|
-
|
|
5181
|
+
const { filters, sort, searchOptions, ...restOptions } = options || {};
|
|
5182
|
+
super({ ...restOptions, allowEmptySearchString: true });
|
|
4868
5183
|
this.type = "members";
|
|
4869
|
-
this.canExecuteQuery = (newSearchString) => {
|
|
4870
|
-
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
4871
|
-
return this.isActive && !this.isLoading && (this.hasNext || hasNewSearchQuery);
|
|
4872
|
-
};
|
|
4873
5184
|
this.channel = channel;
|
|
5185
|
+
this.filters = filters;
|
|
5186
|
+
this.sort = sort;
|
|
5187
|
+
this.searchOptions = searchOptions;
|
|
4874
5188
|
this.filterBuilder = new FilterBuilder({
|
|
4875
5189
|
initialFilterConfig: {
|
|
4876
5190
|
default: {
|
|
@@ -4886,7 +5200,7 @@ var ChannelMemberSearchSource = class extends BaseSearchSource {
|
|
|
4886
5200
|
...filterBuilderOptions
|
|
4887
5201
|
});
|
|
4888
5202
|
}
|
|
4889
|
-
async query(searchQuery) {
|
|
5203
|
+
async query(searchQuery, queryOptions = {}) {
|
|
4890
5204
|
const filters = this.filterBuilder.buildFilters({
|
|
4891
5205
|
baseFilters: this.filters,
|
|
4892
5206
|
context: {
|
|
@@ -4895,7 +5209,12 @@ var ChannelMemberSearchSource = class extends BaseSearchSource {
|
|
|
4895
5209
|
});
|
|
4896
5210
|
const sort = this.sort ?? [];
|
|
4897
5211
|
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
|
|
4898
|
-
const { members } = await this.channel.queryMembers(
|
|
5212
|
+
const { members } = await this.channel.queryMembers(
|
|
5213
|
+
filters ?? {},
|
|
5214
|
+
sort,
|
|
5215
|
+
options,
|
|
5216
|
+
queryOptions
|
|
5217
|
+
);
|
|
4899
5218
|
return { items: members };
|
|
4900
5219
|
}
|
|
4901
5220
|
filterQueryResults(items) {
|
|
@@ -5010,9 +5329,13 @@ var SearchController = class {
|
|
|
5010
5329
|
// src/search/UserSearchSource.ts
|
|
5011
5330
|
var UserSearchSource = class extends BaseSearchSource {
|
|
5012
5331
|
constructor(client, options, filterBuilderOptions = {}) {
|
|
5013
|
-
|
|
5332
|
+
const { filters, sort, searchOptions, ...restOptions } = options || {};
|
|
5333
|
+
super(restOptions);
|
|
5014
5334
|
this.type = "users";
|
|
5015
5335
|
this.client = client;
|
|
5336
|
+
this.filters = filters;
|
|
5337
|
+
this.sort = sort;
|
|
5338
|
+
this.searchOptions = searchOptions;
|
|
5016
5339
|
this.filterBuilder = new FilterBuilder({
|
|
5017
5340
|
initialFilterConfig: {
|
|
5018
5341
|
$or: {
|
|
@@ -5028,7 +5351,7 @@ var UserSearchSource = class extends BaseSearchSource {
|
|
|
5028
5351
|
...filterBuilderOptions
|
|
5029
5352
|
});
|
|
5030
5353
|
}
|
|
5031
|
-
async query(searchQuery) {
|
|
5354
|
+
async query(searchQuery, queryOptions = {}) {
|
|
5032
5355
|
const filters = this.filterBuilder.buildFilters({
|
|
5033
5356
|
baseFilters: this.filters,
|
|
5034
5357
|
context: { searchQuery }
|
|
@@ -5041,7 +5364,7 @@ var UserSearchSource = class extends BaseSearchSource {
|
|
|
5041
5364
|
sort = { id: 1, ...this.sort };
|
|
5042
5365
|
}
|
|
5043
5366
|
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
|
|
5044
|
-
const { users } = await this.client.queryUsers(filters, sort, options);
|
|
5367
|
+
const { users } = await this.client.queryUsers(filters, sort, options, queryOptions);
|
|
5045
5368
|
return { items: users };
|
|
5046
5369
|
}
|
|
5047
5370
|
filterQueryResults(items) {
|
|
@@ -5052,9 +5375,13 @@ var UserSearchSource = class extends BaseSearchSource {
|
|
|
5052
5375
|
// src/search/ChannelSearchSource.ts
|
|
5053
5376
|
var ChannelSearchSource = class extends BaseSearchSource {
|
|
5054
5377
|
constructor(client, options, filterBuilderOptions = {}) {
|
|
5055
|
-
|
|
5378
|
+
const { filters, sort, searchOptions, ...restOptions } = options || {};
|
|
5379
|
+
super(restOptions);
|
|
5056
5380
|
this.type = "channels";
|
|
5057
5381
|
this.client = client;
|
|
5382
|
+
this.filters = filters;
|
|
5383
|
+
this.sort = sort;
|
|
5384
|
+
this.searchOptions = searchOptions;
|
|
5058
5385
|
this.filterBuilder = new FilterBuilder({
|
|
5059
5386
|
...filterBuilderOptions,
|
|
5060
5387
|
initialFilterConfig: {
|
|
@@ -5066,7 +5393,7 @@ var ChannelSearchSource = class extends BaseSearchSource {
|
|
|
5066
5393
|
}
|
|
5067
5394
|
});
|
|
5068
5395
|
}
|
|
5069
|
-
async query(searchQuery) {
|
|
5396
|
+
async query(searchQuery, queryOptions = {}) {
|
|
5070
5397
|
const filters = this.filterBuilder.buildFilters({
|
|
5071
5398
|
baseFilters: {
|
|
5072
5399
|
...this.client.userID ? { members: { $in: [this.client.userID] } } : {},
|
|
@@ -5076,7 +5403,7 @@ var ChannelSearchSource = class extends BaseSearchSource {
|
|
|
5076
5403
|
});
|
|
5077
5404
|
const sort = this.sort ?? {};
|
|
5078
5405
|
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
|
|
5079
|
-
const items = await this.client.queryChannels(filters, sort, options);
|
|
5406
|
+
const items = await this.client.queryChannels(filters, sort, options, queryOptions);
|
|
5080
5407
|
return { items };
|
|
5081
5408
|
}
|
|
5082
5409
|
filterQueryResults(items) {
|
|
@@ -5087,9 +5414,24 @@ var ChannelSearchSource = class extends BaseSearchSource {
|
|
|
5087
5414
|
// src/search/MessageSearchSource.ts
|
|
5088
5415
|
var MessageSearchSource = class extends BaseSearchSource {
|
|
5089
5416
|
constructor(client, options, filterBuilderOptions) {
|
|
5090
|
-
|
|
5417
|
+
const {
|
|
5418
|
+
messageSearchChannelFilters,
|
|
5419
|
+
messageSearchFilters,
|
|
5420
|
+
messageSearchSort,
|
|
5421
|
+
channelQueryFilters,
|
|
5422
|
+
channelQuerySort,
|
|
5423
|
+
channelQueryOptions,
|
|
5424
|
+
...restOptions
|
|
5425
|
+
} = options || {};
|
|
5426
|
+
super(restOptions);
|
|
5091
5427
|
this.type = "messages";
|
|
5092
5428
|
this.client = client;
|
|
5429
|
+
this.messageSearchChannelFilters = messageSearchChannelFilters;
|
|
5430
|
+
this.messageSearchFilters = messageSearchFilters;
|
|
5431
|
+
this.messageSearchSort = messageSearchSort;
|
|
5432
|
+
this.channelQueryFilters = channelQueryFilters;
|
|
5433
|
+
this.channelQuerySort = channelQuerySort;
|
|
5434
|
+
this.channelQueryOptions = channelQueryOptions;
|
|
5093
5435
|
this.messageSearchChannelFilterBuilder = new FilterBuilder(filterBuilderOptions?.messageSearchChannel);
|
|
5094
5436
|
this.messageSearchFilterBuilder = new FilterBuilder({
|
|
5095
5437
|
...filterBuilderOptions?.messageSearch,
|
|
@@ -5112,7 +5454,7 @@ var MessageSearchSource = class extends BaseSearchSource {
|
|
|
5112
5454
|
}
|
|
5113
5455
|
});
|
|
5114
5456
|
}
|
|
5115
|
-
async query(searchQuery) {
|
|
5457
|
+
async query(searchQuery, queryOptions = {}) {
|
|
5116
5458
|
if (!this.client.userID || this.next === null) return { items: [] };
|
|
5117
5459
|
const channelFilters = this.messageSearchChannelFilterBuilder.buildFilters({
|
|
5118
5460
|
baseFilters: {
|
|
@@ -5140,9 +5482,11 @@ var MessageSearchSource = class extends BaseSearchSource {
|
|
|
5140
5482
|
const { next, results } = await this.client.search(
|
|
5141
5483
|
channelFilters,
|
|
5142
5484
|
messageFilters,
|
|
5143
|
-
options
|
|
5485
|
+
options,
|
|
5486
|
+
queryOptions
|
|
5144
5487
|
);
|
|
5145
5488
|
const items = results.map(({ message }) => message);
|
|
5489
|
+
if (queryOptions.signal?.aborted) return { items, next };
|
|
5146
5490
|
const cids = Array.from(
|
|
5147
5491
|
items.reduce((acc, message) => {
|
|
5148
5492
|
if (message.cid && !this.client.activeChannels[message.cid]) acc.add(message.cid);
|
|
@@ -5160,7 +5504,8 @@ var MessageSearchSource = class extends BaseSearchSource {
|
|
|
5160
5504
|
last_message_at: -1,
|
|
5161
5505
|
...this.channelQuerySort
|
|
5162
5506
|
},
|
|
5163
|
-
this.channelQueryOptions
|
|
5507
|
+
this.channelQueryOptions,
|
|
5508
|
+
queryOptions
|
|
5164
5509
|
);
|
|
5165
5510
|
}
|
|
5166
5511
|
return { items, next };
|
|
@@ -5885,6 +6230,13 @@ var MessageComposerMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
|
5885
6230
|
createCompositionDataCleanupMiddleware(composer)
|
|
5886
6231
|
]);
|
|
5887
6232
|
}
|
|
6233
|
+
/**
|
|
6234
|
+
* Narrows the base accessor to the composition middleware type, so callers can read the
|
|
6235
|
+
* declarations it carries (`allowsPendingUploads`) without casting.
|
|
6236
|
+
*/
|
|
6237
|
+
get installedMiddleware() {
|
|
6238
|
+
return super.installedMiddleware;
|
|
6239
|
+
}
|
|
5888
6240
|
};
|
|
5889
6241
|
var MessageDraftComposerMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
5890
6242
|
constructor({ composer }) {
|
|
@@ -6454,13 +6806,18 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6454
6806
|
constructor(channel, options) {
|
|
6455
6807
|
const {
|
|
6456
6808
|
mentionAllAppUsers,
|
|
6809
|
+
memberFilters,
|
|
6810
|
+
memberSort,
|
|
6811
|
+
searchOptions,
|
|
6457
6812
|
suggestionFactoryMappers,
|
|
6458
6813
|
textComposerText,
|
|
6459
6814
|
transliterate,
|
|
6460
6815
|
trigger,
|
|
6816
|
+
userFilters,
|
|
6817
|
+
userSort,
|
|
6461
6818
|
...restOptions
|
|
6462
6819
|
} = options || {};
|
|
6463
|
-
super(restOptions);
|
|
6820
|
+
super({ ...restOptions, allowEmptySearchString: true });
|
|
6464
6821
|
this.type = "mentions";
|
|
6465
6822
|
this.normalizeSearchValue = (value) => this.transliterate(removeDiacritics(value)).toLowerCase();
|
|
6466
6823
|
this.matchesSearchQuery = (value, searchQuery) => {
|
|
@@ -6498,10 +6855,6 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6498
6855
|
this.toHereMentionSuggestion = (searchToken = this.searchQuery) => this.mapMentionSuggestion("here", "here", searchToken);
|
|
6499
6856
|
this.toRoleMentionSuggestion = (role, searchToken = this.searchQuery) => this.mapMentionSuggestion("role", role, searchToken);
|
|
6500
6857
|
this.toUserGroupMentionSuggestion = (userGroup, searchToken = this.searchQuery) => this.mapMentionSuggestion("user_group", userGroup, searchToken);
|
|
6501
|
-
this.canExecuteQuery = (newSearchString) => {
|
|
6502
|
-
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
6503
|
-
return this.isActive && !this.isLoading && (hasNewSearchQuery || this.hasNext);
|
|
6504
|
-
};
|
|
6505
6858
|
this.transliterate = (text) => text;
|
|
6506
6859
|
this.getMembersAndWatchers = () => {
|
|
6507
6860
|
const memberUsers = Object.values(this.channel.state.members ?? {}).map(
|
|
@@ -6521,10 +6874,10 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6521
6874
|
...this.isMentionTypeAllowed("channel") ? [this.toChannelMentionSuggestion(searchQuery)] : [],
|
|
6522
6875
|
...this.isMentionTypeAllowed("here") ? [this.toHereMentionSuggestion(searchQuery)] : []
|
|
6523
6876
|
].filter(({ name }) => this.matchesPrefixSearchQuery(name, searchQuery));
|
|
6524
|
-
this.getRoleMentionSuggestions = async (query) => {
|
|
6877
|
+
this.getRoleMentionSuggestions = async (query, queryOptions = {}) => {
|
|
6525
6878
|
if (!this.isMentionTypeAllowed("role")) return [];
|
|
6526
6879
|
if (!query) return [];
|
|
6527
|
-
const { roles } = await this.client.searchRoles({ query });
|
|
6880
|
+
const { roles } = await this.client.searchRoles({ query }, queryOptions);
|
|
6528
6881
|
return [...roles?.map((role) => role.name) ?? []].sort((left, right) => left.localeCompare(right)).map((role) => this.toRoleMentionSuggestion(role, query));
|
|
6529
6882
|
};
|
|
6530
6883
|
this.searchMembersLocally = (searchQuery) => {
|
|
@@ -6586,20 +6939,25 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6586
6939
|
options: { ...this.searchOptions, limit: this.pageSize, offset }
|
|
6587
6940
|
};
|
|
6588
6941
|
};
|
|
6589
|
-
this.queryUsers = async (searchQuery, offset = 0) => {
|
|
6942
|
+
this.queryUsers = async (searchQuery, offset = 0, queryOptions = {}) => {
|
|
6590
6943
|
const { filters, sort, options } = this.prepareQueryUsersParams(searchQuery, offset);
|
|
6591
|
-
const { users } = await this.client.queryUsers(filters, sort, options);
|
|
6944
|
+
const { users } = await this.client.queryUsers(filters, sort, options, queryOptions);
|
|
6592
6945
|
return users;
|
|
6593
6946
|
};
|
|
6594
|
-
this.queryMembers = async (searchQuery, offset = 0) => {
|
|
6947
|
+
this.queryMembers = async (searchQuery, offset = 0, queryOptions = {}) => {
|
|
6595
6948
|
const { filters, sort, options } = this.prepareQueryMembersParams(
|
|
6596
6949
|
searchQuery,
|
|
6597
6950
|
offset
|
|
6598
6951
|
);
|
|
6599
|
-
const response = await this.channel.queryMembers(
|
|
6952
|
+
const response = await this.channel.queryMembers(
|
|
6953
|
+
filters,
|
|
6954
|
+
sort,
|
|
6955
|
+
options,
|
|
6956
|
+
queryOptions
|
|
6957
|
+
);
|
|
6600
6958
|
return response.members.map((member) => member.user);
|
|
6601
6959
|
};
|
|
6602
|
-
this.getUserSuggestionsPage = async (searchQuery, userOffset = 0) => {
|
|
6960
|
+
this.getUserSuggestionsPage = async (searchQuery, userOffset = 0, queryOptions = {}) => {
|
|
6603
6961
|
if (!this.isMentionTypeAllowed("user")) {
|
|
6604
6962
|
return {
|
|
6605
6963
|
items: [],
|
|
@@ -6609,7 +6967,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6609
6967
|
let users;
|
|
6610
6968
|
const shouldSearchLocally = this.allMembersLoadedWithInitialChannelQuery || !searchQuery;
|
|
6611
6969
|
if (this.config.mentionAllAppUsers) {
|
|
6612
|
-
users = await this.queryUsers(searchQuery, userOffset);
|
|
6970
|
+
users = await this.queryUsers(searchQuery, userOffset, queryOptions);
|
|
6613
6971
|
} else if (shouldSearchLocally) {
|
|
6614
6972
|
const localUsers = this.searchMembersLocally(searchQuery);
|
|
6615
6973
|
const items2 = localUsers.slice(userOffset, userOffset + this.pageSize).map((user) => this.toUserSuggestion(user, searchQuery));
|
|
@@ -6618,7 +6976,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6618
6976
|
nextOffset: localUsers.length > userOffset + this.pageSize ? userOffset + items2.length : void 0
|
|
6619
6977
|
};
|
|
6620
6978
|
} else {
|
|
6621
|
-
users = await this.queryMembers(searchQuery, userOffset);
|
|
6979
|
+
users = await this.queryMembers(searchQuery, userOffset, queryOptions);
|
|
6622
6980
|
}
|
|
6623
6981
|
const items = users.map((user) => this.toUserSuggestion(user, searchQuery));
|
|
6624
6982
|
return {
|
|
@@ -6635,7 +6993,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6635
6993
|
name_gt: lastItem.name
|
|
6636
6994
|
});
|
|
6637
6995
|
};
|
|
6638
|
-
this.getUserGroupSuggestionsPage = async (searchQuery, cursor) => {
|
|
6996
|
+
this.getUserGroupSuggestionsPage = async (searchQuery, cursor, queryOptions = {}) => {
|
|
6639
6997
|
if (!this.isMentionTypeAllowed("user_group")) {
|
|
6640
6998
|
return {
|
|
6641
6999
|
items: [],
|
|
@@ -6657,7 +7015,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6657
7015
|
...userGroupCursor?.id_gt ? { id_gt: userGroupCursor.id_gt } : {},
|
|
6658
7016
|
...userGroupCursor?.name_gt ? { name_gt: userGroupCursor.name_gt } : {}
|
|
6659
7017
|
};
|
|
6660
|
-
const { user_groups } = await this.client.searchUserGroups(options);
|
|
7018
|
+
const { user_groups } = await this.client.searchUserGroups(options, queryOptions);
|
|
6661
7019
|
return {
|
|
6662
7020
|
items: user_groups.map(
|
|
6663
7021
|
(userGroup) => this.toUserGroupMentionSuggestion(userGroup, searchQuery)
|
|
@@ -6667,6 +7025,11 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6667
7025
|
};
|
|
6668
7026
|
this.client = channel.getClient();
|
|
6669
7027
|
this.channel = channel;
|
|
7028
|
+
this.userFilters = userFilters;
|
|
7029
|
+
this.userSort = userSort;
|
|
7030
|
+
this.memberFilters = memberFilters;
|
|
7031
|
+
this.memberSort = memberSort;
|
|
7032
|
+
this.searchOptions = searchOptions;
|
|
6670
7033
|
this.config = {
|
|
6671
7034
|
mentionAllAppUsers,
|
|
6672
7035
|
suggestionFactoryMappers,
|
|
@@ -6699,16 +7062,21 @@ var MentionsSearchSource = class extends BaseSearchSource {
|
|
|
6699
7062
|
offset: (this.offset ?? 0) + userPaginationState.itemCount
|
|
6700
7063
|
};
|
|
6701
7064
|
}
|
|
6702
|
-
async query(searchQuery) {
|
|
7065
|
+
async query(searchQuery, queryOptions = {}) {
|
|
6703
7066
|
const userOffset = this.offset ?? 0;
|
|
6704
7067
|
const isFirstPage = userOffset === 0 && typeof this.userGroupCursor === "undefined";
|
|
6705
7068
|
const previousUserPaginationState = this.latestUserPaginationState;
|
|
6706
7069
|
const previousUserGroupCursor = this.userGroupCursor;
|
|
6707
7070
|
const [userResultsState, userGroupResultsState, roleSuggestionsState] = await Promise.allSettled([
|
|
6708
|
-
this.getUserSuggestionsPage(searchQuery, userOffset),
|
|
6709
|
-
this.getUserGroupSuggestionsPage(
|
|
6710
|
-
|
|
7071
|
+
this.getUserSuggestionsPage(searchQuery, userOffset, queryOptions),
|
|
7072
|
+
this.getUserGroupSuggestionsPage(
|
|
7073
|
+
searchQuery,
|
|
7074
|
+
previousUserGroupCursor,
|
|
7075
|
+
queryOptions
|
|
7076
|
+
),
|
|
7077
|
+
isFirstPage ? this.getRoleMentionSuggestions(searchQuery, queryOptions) : Promise.resolve([])
|
|
6711
7078
|
]);
|
|
7079
|
+
if (queryOptions.signal?.aborted) return { items: [] };
|
|
6712
7080
|
const userResults = userResultsState.status === "fulfilled" ? userResultsState.value : {
|
|
6713
7081
|
items: [],
|
|
6714
7082
|
nextOffset: isFirstPage ? void 0 : previousUserPaginationState?.nextOffset
|
|
@@ -6983,7 +7351,7 @@ var DEFAULT_COMPOSER_CONFIG = {
|
|
|
6983
7351
|
};
|
|
6984
7352
|
|
|
6985
7353
|
// src/messageComposer/CustomDataManager.ts
|
|
6986
|
-
var
|
|
7354
|
+
var initState4 = (options) => {
|
|
6987
7355
|
if (!options)
|
|
6988
7356
|
return { message: {}, custom: {} };
|
|
6989
7357
|
return { message: {}, custom: {} };
|
|
@@ -6992,14 +7360,14 @@ var CustomDataManager = class {
|
|
|
6992
7360
|
constructor({ composer, message }) {
|
|
6993
7361
|
this.isMessageDataEqual = (nextState, previousState) => JSON.stringify(nextState.message) === JSON.stringify(previousState?.message);
|
|
6994
7362
|
this.initState = ({ message } = {}) => {
|
|
6995
|
-
this.state.next(
|
|
7363
|
+
this.state.next(initState4({ composer: this.composer, message }));
|
|
6996
7364
|
};
|
|
6997
7365
|
this.getSnapshot = () => this.state.getLatestValue();
|
|
6998
7366
|
this.restoreSnapshot = (snapshot) => {
|
|
6999
7367
|
this.state.next(snapshot);
|
|
7000
7368
|
};
|
|
7001
7369
|
this.composer = composer;
|
|
7002
|
-
this.state = new StateStore(
|
|
7370
|
+
this.state = new StateStore(initState4({ composer, message }));
|
|
7003
7371
|
}
|
|
7004
7372
|
get customMessageData() {
|
|
7005
7373
|
return this.state.getLatestValue().message;
|
|
@@ -7035,7 +7403,7 @@ var LinkPreviewStatus = /* @__PURE__ */ ((LinkPreviewStatus2) => {
|
|
|
7035
7403
|
return LinkPreviewStatus2;
|
|
7036
7404
|
})(LinkPreviewStatus || {});
|
|
7037
7405
|
var linkPreviewArrayToMap = (linkPreviews) => new Map(linkPreviews.map((linkPreview) => [linkPreview.og_scrape_url, linkPreview]));
|
|
7038
|
-
var
|
|
7406
|
+
var initState5 = ({
|
|
7039
7407
|
message
|
|
7040
7408
|
}) => message ? {
|
|
7041
7409
|
previews: message.attachments?.reduce((acc, attachment) => {
|
|
@@ -7054,7 +7422,7 @@ var _LinkPreviewsManager = class _LinkPreviewsManager {
|
|
|
7054
7422
|
this.shouldDiscardEnrichQueries = false;
|
|
7055
7423
|
this.initState = ({ message } = {}) => {
|
|
7056
7424
|
this.cancelURLEnrichment();
|
|
7057
|
-
this.state.next(
|
|
7425
|
+
this.state.next(initState5({ message: this.enabled ? message : void 0 }));
|
|
7058
7426
|
};
|
|
7059
7427
|
this.getSnapshot = () => this.state.getLatestValue();
|
|
7060
7428
|
this.restoreSnapshot = (snapshot) => {
|
|
@@ -7157,7 +7525,7 @@ var _LinkPreviewsManager = class _LinkPreviewsManager {
|
|
|
7157
7525
|
};
|
|
7158
7526
|
this.composer = composer;
|
|
7159
7527
|
this.state = new StateStore(
|
|
7160
|
-
|
|
7528
|
+
initState5({ message: this.enabled ? message : void 0 })
|
|
7161
7529
|
);
|
|
7162
7530
|
this.findAndEnrichUrls = debounce(
|
|
7163
7531
|
this._findAndEnrichUrls.bind(this),
|
|
@@ -7245,7 +7613,7 @@ var LinkPreviewsManager = _LinkPreviewsManager;
|
|
|
7245
7613
|
|
|
7246
7614
|
// src/messageComposer/LocationComposer.ts
|
|
7247
7615
|
var MIN_LIVE_LOCATION_SHARE_DURATION = 60 * 1e3;
|
|
7248
|
-
var
|
|
7616
|
+
var initState6 = ({
|
|
7249
7617
|
message
|
|
7250
7618
|
}) => ({
|
|
7251
7619
|
location: message?.shared_location ?? null
|
|
@@ -7253,7 +7621,7 @@ var initState5 = ({
|
|
|
7253
7621
|
var LocationComposer = class {
|
|
7254
7622
|
constructor({ composer, message }) {
|
|
7255
7623
|
this.initState = ({ message } = {}) => {
|
|
7256
|
-
this.state.next(
|
|
7624
|
+
this.state.next(initState6({ message }));
|
|
7257
7625
|
};
|
|
7258
7626
|
this.getSnapshot = () => this.state.getLatestValue();
|
|
7259
7627
|
this.restoreSnapshot = (snapshot) => {
|
|
@@ -7271,7 +7639,7 @@ var LocationComposer = class {
|
|
|
7271
7639
|
});
|
|
7272
7640
|
};
|
|
7273
7641
|
this.composer = composer;
|
|
7274
|
-
this.state = new StateStore(
|
|
7642
|
+
this.state = new StateStore(initState6({ message }));
|
|
7275
7643
|
this._deviceId = this.config.getDeviceId();
|
|
7276
7644
|
}
|
|
7277
7645
|
get config() {
|
|
@@ -7992,7 +8360,7 @@ var initEditingAuditState = (composition) => {
|
|
|
7992
8360
|
}
|
|
7993
8361
|
};
|
|
7994
8362
|
};
|
|
7995
|
-
var
|
|
8363
|
+
var initState7 = (composition) => {
|
|
7996
8364
|
if (!composition) {
|
|
7997
8365
|
return {
|
|
7998
8366
|
draftId: null,
|
|
@@ -8079,7 +8447,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8079
8447
|
this.textComposer.initState({ message });
|
|
8080
8448
|
this.pollComposer.initState();
|
|
8081
8449
|
this.customDataManager.initState({ message });
|
|
8082
|
-
this.state.next(
|
|
8450
|
+
this.state.next(initState7(composition));
|
|
8083
8451
|
};
|
|
8084
8452
|
this.initStateFromChannelResponse = (channelApiResponse) => {
|
|
8085
8453
|
if (this.channel.cid !== channelApiResponse.channel.cid) {
|
|
@@ -8545,7 +8913,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8545
8913
|
this.editingAuditState = new StateStore(
|
|
8546
8914
|
this.initEditingAuditState(composition)
|
|
8547
8915
|
);
|
|
8548
|
-
this.state = new StateStore(
|
|
8916
|
+
this.state = new StateStore(initState7(composition));
|
|
8549
8917
|
this.compositionMiddlewareExecutor = new MessageComposerMiddlewareExecutor({
|
|
8550
8918
|
composer: this
|
|
8551
8919
|
});
|
|
@@ -8624,8 +8992,32 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8624
8992
|
const currentCommand = this.textComposer.command;
|
|
8625
8993
|
return !currentCommand || this.validateCommandSendability(currentCommand).ready;
|
|
8626
8994
|
}
|
|
8995
|
+
/**
|
|
8996
|
+
* Whether the installed composition middleware composes messages whose uploads are still in
|
|
8997
|
+
* flight — see `MessageCompositionMiddleware.allowsPendingUploads`.
|
|
8998
|
+
*
|
|
8999
|
+
* Derived from the chain rather than from config, so there is exactly one switch: the UI SDK
|
|
9000
|
+
* that implements the rest of the flow installs the middleware, and everything that has to
|
|
9001
|
+
* follow from that (starting with {@link hasSendableData}) follows on its own.
|
|
9002
|
+
*
|
|
9003
|
+
* **Temporary API.** In v10 sending with pending uploads becomes part of the composer
|
|
9004
|
+
* configuration (`MessageComposerConfig`, set through `updateConfig`), and this getter,
|
|
9005
|
+
* together with the middleware declaration it reads, is replaced by that config field.
|
|
9006
|
+
*/
|
|
9007
|
+
get allowsPendingUploads() {
|
|
9008
|
+
return this.compositionMiddlewareExecutor.installedMiddleware.some(
|
|
9009
|
+
(middleware) => middleware.allowsPendingUploads
|
|
9010
|
+
);
|
|
9011
|
+
}
|
|
8627
9012
|
get hasSendableData() {
|
|
8628
|
-
|
|
9013
|
+
if (!this.isCommandSendable) return false;
|
|
9014
|
+
if (this.allowsPendingUploads) {
|
|
9015
|
+
const hasSendableAttachment = this.attachmentManager.attachments.some(
|
|
9016
|
+
(attachment) => isFinishedUpload(attachment) || isPendingUpload(attachment)
|
|
9017
|
+
);
|
|
9018
|
+
return !!(!this.textComposer.textIsEmpty || hasSendableAttachment || this.pollId || this.locationComposer.validLocation);
|
|
9019
|
+
}
|
|
9020
|
+
return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId || !!this.locationComposer.validLocation);
|
|
8629
9021
|
}
|
|
8630
9022
|
get compositionIsEmpty() {
|
|
8631
9023
|
return !this.quotedMessage && this.contentIsEmpty;
|
|
@@ -9252,14 +9644,16 @@ var Channel = class {
|
|
|
9252
9644
|
*
|
|
9253
9645
|
* @return {Promise<SendMessageAPIResponse>} The Server Response
|
|
9254
9646
|
*/
|
|
9255
|
-
async _sendMessage(
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9647
|
+
async _sendMessage(rawMessage, options) {
|
|
9648
|
+
const client = this.getClient();
|
|
9649
|
+
const message = sanitizeOutgoingAttachments({
|
|
9650
|
+
client,
|
|
9651
|
+
message: rawMessage
|
|
9652
|
+
});
|
|
9653
|
+
return await client.post(this._channelURL() + "/message", {
|
|
9654
|
+
message,
|
|
9655
|
+
...options
|
|
9656
|
+
});
|
|
9263
9657
|
}
|
|
9264
9658
|
async sendMessage(message, options) {
|
|
9265
9659
|
try {
|
|
@@ -9384,10 +9778,11 @@ var Channel = class {
|
|
|
9384
9778
|
* @param {MemberSort} [sort] Sort options, for instance [{created_at: -1}].
|
|
9385
9779
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{name: -1}, {created_at: 1}]
|
|
9386
9780
|
* @param {{ limit?: number; offset?: number }} [options] Option object, {limit: 10, offset:10}
|
|
9781
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
9387
9782
|
*
|
|
9388
9783
|
* @return {Promise<ChannelMemberAPIResponse>} Query Members response
|
|
9389
9784
|
*/
|
|
9390
|
-
async queryMembers(filterConditions, sort = [], options = {}) {
|
|
9785
|
+
async queryMembers(filterConditions, sort = [], options = {}, requestOptions = {}) {
|
|
9391
9786
|
let id;
|
|
9392
9787
|
const type = this.type;
|
|
9393
9788
|
let members;
|
|
@@ -9407,7 +9802,8 @@ var Channel = class {
|
|
|
9407
9802
|
filter_conditions: filterConditions,
|
|
9408
9803
|
...options
|
|
9409
9804
|
}
|
|
9410
|
-
}
|
|
9805
|
+
},
|
|
9806
|
+
requestOptions
|
|
9411
9807
|
);
|
|
9412
9808
|
}
|
|
9413
9809
|
/**
|
|
@@ -10708,6 +11104,7 @@ var Channel = class {
|
|
|
10708
11104
|
// delivery-report network sync below is skipped for it.
|
|
10709
11105
|
case "message.read_locally":
|
|
10710
11106
|
case "message.read":
|
|
11107
|
+
if (event.thread) break;
|
|
10711
11108
|
if (event.user?.id && event.created_at) {
|
|
10712
11109
|
const previousReadState = channelState.read[event.user.id];
|
|
10713
11110
|
channelState.read[event.user.id] = {
|
|
@@ -11157,7 +11554,7 @@ var ClientState = class {
|
|
|
11157
11554
|
var import_isomorphic_ws = __toESM(require("isomorphic-ws"));
|
|
11158
11555
|
|
|
11159
11556
|
// src/insights.ts
|
|
11160
|
-
var
|
|
11557
|
+
var import_axios2 = __toESM(require("axios"));
|
|
11161
11558
|
var InsightMetrics = class {
|
|
11162
11559
|
constructor() {
|
|
11163
11560
|
this.connectionStartTimestamp = null;
|
|
@@ -11170,7 +11567,7 @@ var postInsights = async (insightType, insights) => {
|
|
|
11170
11567
|
const maxAttempts = 3;
|
|
11171
11568
|
for (let i = 0; i < maxAttempts; i++) {
|
|
11172
11569
|
try {
|
|
11173
|
-
await
|
|
11570
|
+
await import_axios2.default.post(
|
|
11174
11571
|
`https://chat-insights.getstream.io/insights/${insightType}`,
|
|
11175
11572
|
insights
|
|
11176
11573
|
);
|
|
@@ -11678,131 +12075,6 @@ var StableWSConnection = class {
|
|
|
11678
12075
|
}
|
|
11679
12076
|
};
|
|
11680
12077
|
|
|
11681
|
-
// src/uploadManager.ts
|
|
11682
|
-
var initState7 = () => ({ uploads: {} });
|
|
11683
|
-
var upsertById = (uploads, record) => ({
|
|
11684
|
-
...uploads,
|
|
11685
|
-
[record.id]: { ...uploads[record.id], ...record }
|
|
11686
|
-
});
|
|
11687
|
-
var updateById = (uploads, record) => {
|
|
11688
|
-
if (!(record.id in uploads)) return null;
|
|
11689
|
-
const current = uploads[record.id];
|
|
11690
|
-
return { ...uploads, [record.id]: { ...current, ...record } };
|
|
11691
|
-
};
|
|
11692
|
-
var UploadManager = class {
|
|
11693
|
-
constructor(client) {
|
|
11694
|
-
this.client = client;
|
|
11695
|
-
this.inFlightUploads = /* @__PURE__ */ new Map();
|
|
11696
|
-
this.getUpload = (id) => this.uploads[id];
|
|
11697
|
-
/**
|
|
11698
|
-
* Clears all upload records.
|
|
11699
|
-
* Invoked when the user disconnects so a later session does not inherit stale upload state.
|
|
11700
|
-
* Aborts every in-flight upload request via its `UploadRequestOptions.abortSignal`.
|
|
11701
|
-
*/
|
|
11702
|
-
this.reset = () => {
|
|
11703
|
-
for (const { abortController } of this.inFlightUploads.values()) {
|
|
11704
|
-
abortController.abort();
|
|
11705
|
-
}
|
|
11706
|
-
this.inFlightUploads.clear();
|
|
11707
|
-
this.state.next(initState7());
|
|
11708
|
-
};
|
|
11709
|
-
/**
|
|
11710
|
-
* Removes the upload record for `id` if present.
|
|
11711
|
-
* If an upload is still in progress, aborts its `UploadRequestOptions.abortSignal`.
|
|
11712
|
-
*/
|
|
11713
|
-
this.deleteUploadRecord = (id) => {
|
|
11714
|
-
const flight = this.inFlightUploads.get(id);
|
|
11715
|
-
if (flight) {
|
|
11716
|
-
this.inFlightUploads.delete(id);
|
|
11717
|
-
flight.abortController.abort();
|
|
11718
|
-
}
|
|
11719
|
-
this.state.next((current) => {
|
|
11720
|
-
if (!(id in current.uploads)) return current;
|
|
11721
|
-
const uploads = { ...current.uploads };
|
|
11722
|
-
delete uploads[id];
|
|
11723
|
-
return { ...current, uploads };
|
|
11724
|
-
});
|
|
11725
|
-
};
|
|
11726
|
-
/**
|
|
11727
|
-
* Starts an upload for `id`, or returns the existing in-flight promise if one is already running.
|
|
11728
|
-
* Uses {@link StreamChat.channel}(`channelCid`) → `messageComposer.attachmentManager.doUploadRequest`.
|
|
11729
|
-
* Resolves with that result; rejects if the upload rejects (the record is removed from state either way).
|
|
11730
|
-
*/
|
|
11731
|
-
this.upload = ({
|
|
11732
|
-
id,
|
|
11733
|
-
channelCid,
|
|
11734
|
-
file
|
|
11735
|
-
}) => {
|
|
11736
|
-
const existing = this.inFlightUploads.get(id);
|
|
11737
|
-
if (existing) return existing.promise;
|
|
11738
|
-
let resolvePromise;
|
|
11739
|
-
let rejectPromise;
|
|
11740
|
-
const promise = new Promise((resolve, reject) => {
|
|
11741
|
-
resolvePromise = resolve;
|
|
11742
|
-
rejectPromise = reject;
|
|
11743
|
-
});
|
|
11744
|
-
const abortController = new AbortController();
|
|
11745
|
-
this.inFlightUploads.set(id, { promise, abortController });
|
|
11746
|
-
void (async () => {
|
|
11747
|
-
const attachmentManager = this.resolveAttachmentManager(channelCid);
|
|
11748
|
-
const trackProgress = attachmentManager.config.trackUploadProgress;
|
|
11749
|
-
try {
|
|
11750
|
-
this.upsertUpload({
|
|
11751
|
-
id,
|
|
11752
|
-
uploadProgress: trackProgress ? 0 : void 0
|
|
11753
|
-
});
|
|
11754
|
-
const onProgress = trackProgress ? (progress) => {
|
|
11755
|
-
this.updateUpload({
|
|
11756
|
-
id,
|
|
11757
|
-
uploadProgress: progress
|
|
11758
|
-
});
|
|
11759
|
-
} : void 0;
|
|
11760
|
-
const uploadRequestOptions = {
|
|
11761
|
-
abortSignal: abortController.signal,
|
|
11762
|
-
...onProgress ? { onProgress } : {}
|
|
11763
|
-
};
|
|
11764
|
-
const response = await attachmentManager.doUploadRequest(
|
|
11765
|
-
file,
|
|
11766
|
-
uploadRequestOptions
|
|
11767
|
-
);
|
|
11768
|
-
resolvePromise(response);
|
|
11769
|
-
} catch (error) {
|
|
11770
|
-
rejectPromise(error);
|
|
11771
|
-
} finally {
|
|
11772
|
-
this.inFlightUploads.delete(id);
|
|
11773
|
-
this.deleteUploadRecord(id);
|
|
11774
|
-
}
|
|
11775
|
-
})();
|
|
11776
|
-
return promise;
|
|
11777
|
-
};
|
|
11778
|
-
this.upsertUpload = (record) => {
|
|
11779
|
-
this.state.partialNext({
|
|
11780
|
-
uploads: upsertById(this.uploads, record)
|
|
11781
|
-
});
|
|
11782
|
-
};
|
|
11783
|
-
this.updateUpload = (record) => {
|
|
11784
|
-
this.state.next((current) => {
|
|
11785
|
-
const nextUploads = updateById(current.uploads, record);
|
|
11786
|
-
if (!nextUploads) return current;
|
|
11787
|
-
return { ...current, uploads: nextUploads };
|
|
11788
|
-
});
|
|
11789
|
-
};
|
|
11790
|
-
this.state = new StateStore(initState7());
|
|
11791
|
-
}
|
|
11792
|
-
resolveAttachmentManager(channelCid) {
|
|
11793
|
-
const colon = channelCid.indexOf(":");
|
|
11794
|
-
if (colon <= 0 || colon === channelCid.length - 1) {
|
|
11795
|
-
throw new Error(`Invalid channelCid: ${channelCid}`);
|
|
11796
|
-
}
|
|
11797
|
-
const channelType = channelCid.slice(0, colon);
|
|
11798
|
-
const channelId = channelCid.slice(colon + 1);
|
|
11799
|
-
return this.client.channel(channelType, channelId).messageComposer.attachmentManager;
|
|
11800
|
-
}
|
|
11801
|
-
get uploads() {
|
|
11802
|
-
return this.state.getLatestValue().uploads;
|
|
11803
|
-
}
|
|
11804
|
-
};
|
|
11805
|
-
|
|
11806
12078
|
// src/signing.ts
|
|
11807
12079
|
var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
|
|
11808
12080
|
var import_crypto = __toESM(require("crypto"));
|
|
@@ -12061,7 +12333,7 @@ var TokenManager = class {
|
|
|
12061
12333
|
};
|
|
12062
12334
|
|
|
12063
12335
|
// src/connection_fallback.ts
|
|
12064
|
-
var
|
|
12336
|
+
var import_axios3 = __toESM(require("axios"));
|
|
12065
12337
|
var WSConnectionFallback = class {
|
|
12066
12338
|
constructor({ client }) {
|
|
12067
12339
|
/** @private */
|
|
@@ -12080,7 +12352,7 @@ var WSConnectionFallback = class {
|
|
|
12080
12352
|
/** @private */
|
|
12081
12353
|
this._req = async (params, config, retry) => {
|
|
12082
12354
|
if (!this.cancelToken && !params.close) {
|
|
12083
|
-
this.cancelToken =
|
|
12355
|
+
this.cancelToken = import_axios3.default.CancelToken.source();
|
|
12084
12356
|
}
|
|
12085
12357
|
try {
|
|
12086
12358
|
const res = await this.client.doAxiosRequest(
|
|
@@ -12116,7 +12388,7 @@ var WSConnectionFallback = class {
|
|
|
12116
12388
|
}
|
|
12117
12389
|
}
|
|
12118
12390
|
} catch (error) {
|
|
12119
|
-
if (
|
|
12391
|
+
if (import_axios3.default.isCancel(error)) {
|
|
12120
12392
|
this._log(`_poll() - axios canceled request`);
|
|
12121
12393
|
return;
|
|
12122
12394
|
}
|
|
@@ -14539,6 +14811,7 @@ var StreamChat = class _StreamChat {
|
|
|
14539
14811
|
return this.handleResponse(response);
|
|
14540
14812
|
} catch (e) {
|
|
14541
14813
|
e.client_request_id = requestConfig.headers?.["x-client-request-id"];
|
|
14814
|
+
if (import_axios4.default.isCancel(e)) throw e;
|
|
14542
14815
|
this._logApiError(type, url, e);
|
|
14543
14816
|
this.consecutiveFailures += 1;
|
|
14544
14817
|
if (e.response) {
|
|
@@ -14850,7 +15123,7 @@ var StreamChat = class _StreamChat {
|
|
|
14850
15123
|
return this.userAgent;
|
|
14851
15124
|
}
|
|
14852
15125
|
if (!this.cachedUserAgent) {
|
|
14853
|
-
const version = "9.
|
|
15126
|
+
const version = "9.52.0";
|
|
14854
15127
|
const { name: sdkName, version: sdkVersion } = this.sdkIdentifier ?? {};
|
|
14855
15128
|
const { name: appName, version: appVersion } = this.appIdentifier ?? {};
|
|
14856
15129
|
const { os, model: deviceModel } = this.deviceIdentifier ?? {};
|
|
@@ -14918,7 +15191,7 @@ var StreamChat = class _StreamChat {
|
|
|
14918
15191
|
keepAliveMsecs: 3e3
|
|
14919
15192
|
});
|
|
14920
15193
|
}
|
|
14921
|
-
this.axiosInstance =
|
|
15194
|
+
this.axiosInstance = import_axios4.default.create(this.options);
|
|
14922
15195
|
this.setBaseURL(this.options.baseURL || "https://chat.stream-io-api.com");
|
|
14923
15196
|
if (typeof process !== "undefined" && "env" in process && process.env.STREAM_LOCAL_TEST_RUN) {
|
|
14924
15197
|
this.setBaseURL("http://localhost:3030");
|
|
@@ -15226,14 +15499,14 @@ var StreamChat = class _StreamChat {
|
|
|
15226
15499
|
error
|
|
15227
15500
|
});
|
|
15228
15501
|
}
|
|
15229
|
-
get(url, params) {
|
|
15230
|
-
return this.doAxiosRequest("get", url, null, { params });
|
|
15502
|
+
get(url, params, config) {
|
|
15503
|
+
return this.doAxiosRequest("get", url, null, { params, config });
|
|
15231
15504
|
}
|
|
15232
15505
|
put(url, data) {
|
|
15233
15506
|
return this.doAxiosRequest("put", url, data);
|
|
15234
15507
|
}
|
|
15235
|
-
post(url, data) {
|
|
15236
|
-
return this.doAxiosRequest("post", url, data);
|
|
15508
|
+
post(url, data, config) {
|
|
15509
|
+
return this.doAxiosRequest("post", url, data, { config });
|
|
15237
15510
|
}
|
|
15238
15511
|
patch(url, data) {
|
|
15239
15512
|
return this.doAxiosRequest("patch", url, data);
|
|
@@ -15428,10 +15701,11 @@ var StreamChat = class _StreamChat {
|
|
|
15428
15701
|
* @param {UserSort} sort Sort options, for instance [{last_active: -1}].
|
|
15429
15702
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_active: -1}, {created_at: 1}]
|
|
15430
15703
|
* @param {UserOptions} options Option object, {presence: true}
|
|
15704
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15431
15705
|
*
|
|
15432
15706
|
* @return {Promise<{ users: Array<UserResponse> }>} User Query Response
|
|
15433
15707
|
*/
|
|
15434
|
-
async queryUsers(filterConditions, sort = [], options = {}) {
|
|
15708
|
+
async queryUsers(filterConditions, sort = [], options = {}, requestOptions = {}) {
|
|
15435
15709
|
const defaultOptions = {
|
|
15436
15710
|
presence: false
|
|
15437
15711
|
};
|
|
@@ -15448,7 +15722,8 @@ var StreamChat = class _StreamChat {
|
|
|
15448
15722
|
...defaultOptions,
|
|
15449
15723
|
...options
|
|
15450
15724
|
}
|
|
15451
|
-
}
|
|
15725
|
+
},
|
|
15726
|
+
requestOptions
|
|
15452
15727
|
);
|
|
15453
15728
|
this.state.updateUsers(data.users);
|
|
15454
15729
|
return data;
|
|
@@ -15494,13 +15769,14 @@ var StreamChat = class _StreamChat {
|
|
|
15494
15769
|
* searchUserGroups - Search user groups by prefix for autocomplete
|
|
15495
15770
|
*
|
|
15496
15771
|
* @param {SearchUserGroupsOptions} options The search options
|
|
15497
|
-
*
|
|
15772
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15498
15773
|
* @return {Promise<SearchUserGroupsResponse>} User Group Search Response
|
|
15499
15774
|
*/
|
|
15500
|
-
async searchUserGroups(options) {
|
|
15775
|
+
async searchUserGroups(options, requestOptions = {}) {
|
|
15501
15776
|
return await this.get(
|
|
15502
15777
|
this.baseURL + "/usergroups/search",
|
|
15503
|
-
options
|
|
15778
|
+
options,
|
|
15779
|
+
requestOptions
|
|
15504
15780
|
);
|
|
15505
15781
|
}
|
|
15506
15782
|
/**
|
|
@@ -15620,10 +15896,11 @@ var StreamChat = class _StreamChat {
|
|
|
15620
15896
|
* @param {ChannelSort} [sort] Sort options, for instance {created_at: -1}.
|
|
15621
15897
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_updated: -1}, {created_at: 1}]
|
|
15622
15898
|
* @param {ChannelOptions} [options] Options object. Can include predefined_filter, filter_values, and sort_values for using predefined filters.
|
|
15899
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15623
15900
|
*
|
|
15624
15901
|
* @return {Promise<QueryChannelsAPIResponse>} full search channels response
|
|
15625
15902
|
*/
|
|
15626
|
-
async queryChannelsRequestWithResponse(filterConditions, sort = [], options = {}) {
|
|
15903
|
+
async queryChannelsRequestWithResponse(filterConditions, sort = [], options = {}, requestOptions = {}) {
|
|
15627
15904
|
const defaultOptions = {
|
|
15628
15905
|
state: true,
|
|
15629
15906
|
watch: true,
|
|
@@ -15648,7 +15925,11 @@ var StreamChat = class _StreamChat {
|
|
|
15648
15925
|
...defaultOptions,
|
|
15649
15926
|
...restOptions
|
|
15650
15927
|
};
|
|
15651
|
-
return await this.post(
|
|
15928
|
+
return await this.post(
|
|
15929
|
+
this.baseURL + "/channels",
|
|
15930
|
+
payload,
|
|
15931
|
+
requestOptions
|
|
15932
|
+
);
|
|
15652
15933
|
}
|
|
15653
15934
|
/**
|
|
15654
15935
|
* queryChannelsRequest - Queries channels and returns the raw channel response list.
|
|
@@ -15677,7 +15958,9 @@ var StreamChat = class _StreamChat {
|
|
|
15677
15958
|
const queryChannelsResponse = await this.queryChannelsRequestWithResponse(
|
|
15678
15959
|
filterConditions,
|
|
15679
15960
|
sort,
|
|
15680
|
-
options
|
|
15961
|
+
options,
|
|
15962
|
+
// stateOptions is never serialized, so it carries the abort signal
|
|
15963
|
+
{ signal: stateOptions.signal }
|
|
15681
15964
|
);
|
|
15682
15965
|
const channels = queryChannelsResponse.channels;
|
|
15683
15966
|
this.dispatchEvent({
|
|
@@ -15794,10 +16077,11 @@ var StreamChat = class _StreamChat {
|
|
|
15794
16077
|
* @param {ChannelFilters} filterConditions MongoDB style filter conditions
|
|
15795
16078
|
* @param {MessageFilters | string} query search query or object MongoDB style filters
|
|
15796
16079
|
* @param {SearchOptions} [options] Option object, {user_id: 'tommaso'}
|
|
16080
|
+
* @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
|
|
15797
16081
|
*
|
|
15798
16082
|
* @return {Promise<SearchAPIResponse>} search messages response
|
|
15799
16083
|
*/
|
|
15800
|
-
async search(filterConditions, query, options = {}) {
|
|
16084
|
+
async search(filterConditions, query, options = {}, requestOptions = {}) {
|
|
15801
16085
|
if (options.offset && options.next) {
|
|
15802
16086
|
throw Error(`Cannot specify offset with next`);
|
|
15803
16087
|
}
|
|
@@ -15814,7 +16098,11 @@ var StreamChat = class _StreamChat {
|
|
|
15814
16098
|
throw Error(`Invalid type ${typeof query} for query parameter`);
|
|
15815
16099
|
}
|
|
15816
16100
|
await this.wsPromise;
|
|
15817
|
-
return await this.get(
|
|
16101
|
+
return await this.get(
|
|
16102
|
+
this.baseURL + "/search",
|
|
16103
|
+
{ payload },
|
|
16104
|
+
requestOptions
|
|
16105
|
+
);
|
|
15818
16106
|
}
|
|
15819
16107
|
/**
|
|
15820
16108
|
* setLocalDevice - Set the device info for the current client(device) that will be sent via WS connection automatically
|
|
@@ -16255,6 +16543,11 @@ var StreamChat = class _StreamChat {
|
|
|
16255
16543
|
}
|
|
16256
16544
|
/**
|
|
16257
16545
|
* unflagMessage - unflag a message
|
|
16546
|
+
*
|
|
16547
|
+
* @deprecated The `/moderation/unflag` endpoint is deprecated and is a no-op on
|
|
16548
|
+
* the backend - calling this resolves successfully but does not remove the flag.
|
|
16549
|
+
* Use `client.moderation.submitAction()` against the review queue item instead.
|
|
16550
|
+
*
|
|
16258
16551
|
* @param {string} targetMessageID
|
|
16259
16552
|
* @param {string} [options.user_id] currentUserID, only used with serverside auth
|
|
16260
16553
|
* @returns {Promise<APIResponse>}
|
|
@@ -16267,6 +16560,11 @@ var StreamChat = class _StreamChat {
|
|
|
16267
16560
|
}
|
|
16268
16561
|
/**
|
|
16269
16562
|
* unflagUser - unflag a user
|
|
16563
|
+
*
|
|
16564
|
+
* @deprecated The `/moderation/unflag` endpoint is deprecated and is a no-op on
|
|
16565
|
+
* the backend - calling this resolves successfully but does not remove the flag.
|
|
16566
|
+
* Use `client.moderation.submitAction()` against the review queue item instead.
|
|
16567
|
+
*
|
|
16270
16568
|
* @param {string} targetID
|
|
16271
16569
|
* @param {string} [options.user_id] currentUserID, only used with serverside auth
|
|
16272
16570
|
* @returns {Promise<APIResponse>}
|
|
@@ -16551,7 +16849,10 @@ var StreamChat = class _StreamChat {
|
|
|
16551
16849
|
if (!message.id) {
|
|
16552
16850
|
throw Error("Please specify the message.id when calling updateMessage");
|
|
16553
16851
|
}
|
|
16554
|
-
const payload =
|
|
16852
|
+
const payload = sanitizeOutgoingAttachments({
|
|
16853
|
+
client: this,
|
|
16854
|
+
message: toUpdatedMessagePayload(message)
|
|
16855
|
+
});
|
|
16555
16856
|
if (typeof partialUserOrUserId === "string") {
|
|
16556
16857
|
payload.user_id = partialUserOrUserId;
|
|
16557
16858
|
} else if (typeof partialUserOrUserId?.id === "string") {
|
|
@@ -16851,6 +17152,7 @@ var StreamChat = class _StreamChat {
|
|
|
16851
17152
|
headers: axiosRequestConfigHeaders,
|
|
16852
17153
|
...axiosRequestConfigRest
|
|
16853
17154
|
} = this.options.axiosRequestConfig || {};
|
|
17155
|
+
const resolvedSignal = options.config?.signal ?? axiosRequestConfigRest.signal ?? signal;
|
|
16854
17156
|
return {
|
|
16855
17157
|
params: {
|
|
16856
17158
|
user_id: this.userID,
|
|
@@ -16866,9 +17168,9 @@ var StreamChat = class _StreamChat {
|
|
|
16866
17168
|
...options.headers,
|
|
16867
17169
|
...axiosRequestConfigHeaders || {}
|
|
16868
17170
|
},
|
|
16869
|
-
...signal ? { signal } : {},
|
|
16870
17171
|
...options.config,
|
|
16871
|
-
...axiosRequestConfigRest
|
|
17172
|
+
...axiosRequestConfigRest,
|
|
17173
|
+
...resolvedSignal ? { signal: resolvedSignal } : {}
|
|
16872
17174
|
};
|
|
16873
17175
|
}
|
|
16874
17176
|
_getToken() {
|
|
@@ -17008,8 +17310,12 @@ var StreamChat = class _StreamChat {
|
|
|
17008
17310
|
*
|
|
17009
17311
|
* @returns {Promise<APIResponse>}
|
|
17010
17312
|
*/
|
|
17011
|
-
searchRoles(options) {
|
|
17012
|
-
return this.get(
|
|
17313
|
+
searchRoles(options, requestOptions = {}) {
|
|
17314
|
+
return this.get(
|
|
17315
|
+
`${this.baseURL}/roles/search`,
|
|
17316
|
+
options,
|
|
17317
|
+
requestOptions
|
|
17318
|
+
);
|
|
17013
17319
|
}
|
|
17014
17320
|
/** deleteRole - deletes a custom role
|
|
17015
17321
|
*
|
|
@@ -18362,11 +18668,12 @@ var OfflineError = class extends Error {
|
|
|
18362
18668
|
};
|
|
18363
18669
|
|
|
18364
18670
|
// src/offline-support/offline_sync_manager.ts
|
|
18365
|
-
var
|
|
18671
|
+
var import_axios5 = require("axios");
|
|
18366
18672
|
var OfflineDBSyncManager = class {
|
|
18367
18673
|
constructor({
|
|
18368
18674
|
client,
|
|
18369
|
-
offlineDb
|
|
18675
|
+
offlineDb,
|
|
18676
|
+
syncMaxEventCount
|
|
18370
18677
|
}) {
|
|
18371
18678
|
this.syncStatus = false;
|
|
18372
18679
|
this.connectionChangedListener = null;
|
|
@@ -18483,13 +18790,23 @@ var OfflineDBSyncManager = class {
|
|
|
18483
18790
|
await this.offlineDb.resetDB();
|
|
18484
18791
|
} else {
|
|
18485
18792
|
const result = await this.client.sync(cids, lastSyncedAtDate.toISOString());
|
|
18486
|
-
const
|
|
18487
|
-
|
|
18488
|
-
)
|
|
18489
|
-
|
|
18490
|
-
|
|
18491
|
-
|
|
18492
|
-
|
|
18793
|
+
const { syncMaxEventCount } = this;
|
|
18794
|
+
const exceedsLimit = typeof syncMaxEventCount === "number" && syncMaxEventCount > 0 && result.events.length > syncMaxEventCount;
|
|
18795
|
+
if (exceedsLimit) {
|
|
18796
|
+
this.client.logger(
|
|
18797
|
+
"warn",
|
|
18798
|
+
`Skipping sync event replay: received ${result.events.length} events, which exceeds the configured limit of ${syncMaxEventCount}. Visible channels are refreshed on reconnect instead.`,
|
|
18799
|
+
{ tags: ["sync", "offline"] }
|
|
18800
|
+
);
|
|
18801
|
+
} else {
|
|
18802
|
+
const queryPromises = result.events.map(
|
|
18803
|
+
(event) => this.offlineDb.handleEvent({ event, execute: false })
|
|
18804
|
+
);
|
|
18805
|
+
const queriesArray = await Promise.all(queryPromises);
|
|
18806
|
+
const queries = queriesArray.flat();
|
|
18807
|
+
if (queries.length) {
|
|
18808
|
+
await this.offlineDb.executeSqlBatch(queries);
|
|
18809
|
+
}
|
|
18493
18810
|
}
|
|
18494
18811
|
}
|
|
18495
18812
|
}
|
|
@@ -18499,7 +18816,7 @@ var OfflineDBSyncManager = class {
|
|
|
18499
18816
|
});
|
|
18500
18817
|
} catch (e) {
|
|
18501
18818
|
console.log("An error has occurred while syncing the DB.", e);
|
|
18502
|
-
if ((0,
|
|
18819
|
+
if ((0, import_axios5.isAxiosError)(e) && e.code === "ECONNABORTED") {
|
|
18503
18820
|
return;
|
|
18504
18821
|
}
|
|
18505
18822
|
const error = e;
|
|
@@ -18533,12 +18850,16 @@ var OfflineDBSyncManager = class {
|
|
|
18533
18850
|
};
|
|
18534
18851
|
this.client = client;
|
|
18535
18852
|
this.offlineDb = offlineDb;
|
|
18853
|
+
this.syncMaxEventCount = syncMaxEventCount;
|
|
18536
18854
|
}
|
|
18537
18855
|
};
|
|
18538
18856
|
|
|
18539
18857
|
// src/offline-support/offline_support_api.ts
|
|
18540
18858
|
var AbstractOfflineDB = class {
|
|
18541
|
-
constructor({
|
|
18859
|
+
constructor({
|
|
18860
|
+
client,
|
|
18861
|
+
syncMaxEventCount
|
|
18862
|
+
}) {
|
|
18542
18863
|
/**
|
|
18543
18864
|
* Initializes the DB as well as its syncManager for a given userId.
|
|
18544
18865
|
* It will update the DBs reactive state with initialization values.
|
|
@@ -19004,6 +19325,7 @@ var AbstractOfflineDB = class {
|
|
|
19004
19325
|
return this.handleMessageUpdatedEvent({ event, execute });
|
|
19005
19326
|
}
|
|
19006
19327
|
if (type === "message.read" || type === "notification.mark_read") {
|
|
19328
|
+
if (event.thread) return [];
|
|
19007
19329
|
return this.handleRead({ event, unreadMessages: 0, execute });
|
|
19008
19330
|
}
|
|
19009
19331
|
if (type === "message.read_locally") {
|
|
@@ -19228,7 +19550,11 @@ var AbstractOfflineDB = class {
|
|
|
19228
19550
|
}
|
|
19229
19551
|
};
|
|
19230
19552
|
this.client = client;
|
|
19231
|
-
this.syncManager = new OfflineDBSyncManager({
|
|
19553
|
+
this.syncManager = new OfflineDBSyncManager({
|
|
19554
|
+
client,
|
|
19555
|
+
offlineDb: this,
|
|
19556
|
+
syncMaxEventCount
|
|
19557
|
+
});
|
|
19232
19558
|
this.state = new StateStore({
|
|
19233
19559
|
initialized: false,
|
|
19234
19560
|
userId: this.client.userID
|
|
@@ -19567,6 +19893,7 @@ var LiveLocationManager = _LiveLocationManager;
|
|
|
19567
19893
|
createMessageComposerStateCompositionMiddleware,
|
|
19568
19894
|
createPollComposerStateMiddleware,
|
|
19569
19895
|
createPostUploadAttachmentEnrichmentMiddleware,
|
|
19896
|
+
createSendWithPendingUploadsAttachmentsMiddleware,
|
|
19570
19897
|
createSharedLocationCompositionMiddleware,
|
|
19571
19898
|
createTextComposerCompositionMiddleware,
|
|
19572
19899
|
createTextComposerPreValidationMiddleware,
|
|
@@ -19595,6 +19922,7 @@ var LiveLocationManager = _LiveLocationManager;
|
|
|
19595
19922
|
getTokenizedSuggestionDisplayName,
|
|
19596
19923
|
getTriggerCharWithToken,
|
|
19597
19924
|
gunzipPayload,
|
|
19925
|
+
hasPending,
|
|
19598
19926
|
insertItemWithTrigger,
|
|
19599
19927
|
isAudioAttachment,
|
|
19600
19928
|
isBlobButNotFile,
|
|
@@ -19602,6 +19930,7 @@ var LiveLocationManager = _LiveLocationManager;
|
|
|
19602
19930
|
isFileAttachment,
|
|
19603
19931
|
isFileList,
|
|
19604
19932
|
isFileReference,
|
|
19933
|
+
isFinishedUpload,
|
|
19605
19934
|
isGiphyAttachment,
|
|
19606
19935
|
isImageAttachment,
|
|
19607
19936
|
isImageFile,
|
|
@@ -19614,9 +19943,11 @@ var LiveLocationManager = _LiveLocationManager;
|
|
|
19614
19943
|
isLocalVoiceRecordingAttachment,
|
|
19615
19944
|
isOwnUser,
|
|
19616
19945
|
isPatch,
|
|
19946
|
+
isPendingUpload,
|
|
19617
19947
|
isScrapedContent,
|
|
19618
19948
|
isSharedLocationResponse,
|
|
19619
19949
|
isTargetedOptionTextUpdate,
|
|
19950
|
+
isUploadCancellation,
|
|
19620
19951
|
isUploadedAttachment,
|
|
19621
19952
|
isVideoAttachment,
|
|
19622
19953
|
isVoiceRecordingAttachment,
|
|
@@ -19636,11 +19967,14 @@ var LiveLocationManager = _LiveLocationManager;
|
|
|
19636
19967
|
readFileAsArrayBuffer,
|
|
19637
19968
|
removeDiacritics,
|
|
19638
19969
|
replaceWordWithEntity,
|
|
19970
|
+
settled,
|
|
19639
19971
|
stripCommandFromText,
|
|
19640
19972
|
stripMentionTokens,
|
|
19641
19973
|
textIsEmpty,
|
|
19642
19974
|
timeLeftMs,
|
|
19643
19975
|
verifyAndParseWebhook,
|
|
19644
|
-
verifySignature
|
|
19976
|
+
verifySignature,
|
|
19977
|
+
withCancellation,
|
|
19978
|
+
withoutConcurrency
|
|
19645
19979
|
});
|
|
19646
19980
|
//# sourceMappingURL=index.node.js.map
|