stream-chat 9.28.0 → 9.30.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 +576 -341
- package/dist/cjs/index.browser.js.map +3 -3
- package/dist/cjs/index.node.js +576 -341
- package/dist/cjs/index.node.js.map +3 -3
- package/dist/esm/index.mjs +576 -341
- package/dist/esm/index.mjs.map +3 -3
- package/dist/types/CooldownTimer.d.ts +45 -0
- package/dist/types/channel.d.ts +5 -2
- package/dist/types/channel_state.d.ts +1 -1
- package/dist/types/client.d.ts +51 -3
- package/dist/types/index.d.ts +1 -0
- package/dist/types/insights.d.ts +2 -2
- package/dist/types/messageComposer/fileUtils.d.ts +1 -1
- package/dist/types/messageComposer/messageComposer.d.ts +3 -3
- package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +2 -2
- package/dist/types/messageComposer/types.d.ts +8 -0
- package/dist/types/types.d.ts +73 -0
- package/dist/types/utils.d.ts +5 -5
- package/package.json +1 -1
- package/src/CooldownTimer.ts +196 -0
- package/src/channel.ts +14 -1
- package/src/client.ts +121 -11
- package/src/index.ts +1 -0
- package/src/messageComposer/attachmentManager.ts +18 -13
- package/src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts +5 -4
- package/src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts +5 -4
- package/src/messageComposer/types.ts +8 -0
- package/src/types.ts +86 -0
|
@@ -2132,6 +2132,399 @@ var ChannelState = class {
|
|
|
2132
2132
|
}
|
|
2133
2133
|
};
|
|
2134
2134
|
|
|
2135
|
+
// src/store.ts
|
|
2136
|
+
var isPatch = (value) => typeof value === "function";
|
|
2137
|
+
var noop = () => {
|
|
2138
|
+
};
|
|
2139
|
+
var StateStore = class {
|
|
2140
|
+
constructor(value) {
|
|
2141
|
+
this.value = value;
|
|
2142
|
+
this.handlers = /* @__PURE__ */ new Set();
|
|
2143
|
+
this.preprocessors = /* @__PURE__ */ new Set();
|
|
2144
|
+
this.partialNext = (partial) => this.next((current) => ({ ...current, ...partial }));
|
|
2145
|
+
this.subscribeWithSelector = (selector, handler) => {
|
|
2146
|
+
let previouslySelectedValues;
|
|
2147
|
+
const wrappedHandler = (nextValue) => {
|
|
2148
|
+
const newlySelectedValues = selector(nextValue);
|
|
2149
|
+
let hasUpdatedValues = typeof previouslySelectedValues === "undefined";
|
|
2150
|
+
for (const key in previouslySelectedValues) {
|
|
2151
|
+
if (previouslySelectedValues[key] === newlySelectedValues[key]) continue;
|
|
2152
|
+
hasUpdatedValues = true;
|
|
2153
|
+
break;
|
|
2154
|
+
}
|
|
2155
|
+
if (!hasUpdatedValues) return;
|
|
2156
|
+
const previouslySelectedValuesCopy = previouslySelectedValues;
|
|
2157
|
+
previouslySelectedValues = newlySelectedValues;
|
|
2158
|
+
handler(newlySelectedValues, previouslySelectedValuesCopy);
|
|
2159
|
+
};
|
|
2160
|
+
return this.subscribe(wrappedHandler);
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Allows merging two stores only if their keys differ otherwise there's no way to ensure the data type stability.
|
|
2165
|
+
* @experimental
|
|
2166
|
+
* This method is experimental and may change in future versions.
|
|
2167
|
+
*/
|
|
2168
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2169
|
+
merge(stateStore) {
|
|
2170
|
+
return new MergedStateStore({
|
|
2171
|
+
original: this,
|
|
2172
|
+
merged: stateStore
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
next(newValueOrPatch) {
|
|
2176
|
+
const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
|
|
2177
|
+
if (newValue === this.value) return;
|
|
2178
|
+
this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
|
|
2179
|
+
const oldValue = this.value;
|
|
2180
|
+
this.value = newValue;
|
|
2181
|
+
this.handlers.forEach((handler) => handler(this.value, oldValue));
|
|
2182
|
+
}
|
|
2183
|
+
getLatestValue() {
|
|
2184
|
+
return this.value;
|
|
2185
|
+
}
|
|
2186
|
+
subscribe(handler) {
|
|
2187
|
+
handler(this.value, void 0);
|
|
2188
|
+
this.handlers.add(handler);
|
|
2189
|
+
return () => {
|
|
2190
|
+
this.handlers.delete(handler);
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
/**
|
|
2194
|
+
* Registers a preprocessor function that will be called before the state is updated.
|
|
2195
|
+
*
|
|
2196
|
+
* Preprocessors are invoked with the new and previous values whenever `next` or `partialNext` methods
|
|
2197
|
+
* are called, allowing you to mutate or react to the new value before it is set. Preprocessors run in the
|
|
2198
|
+
* order they were registered.
|
|
2199
|
+
*
|
|
2200
|
+
* @example
|
|
2201
|
+
* ```ts
|
|
2202
|
+
* const store = new StateStore<{ count: number; isMaxValue: bool; }>({ count: 0, isMaxValue: false });
|
|
2203
|
+
*
|
|
2204
|
+
* store.addPreprocessor((nextValue, prevValue) => {
|
|
2205
|
+
* if (nextValue.count > 10) {
|
|
2206
|
+
* nextValue.count = 10; // Clamp the value to a maximum of 10
|
|
2207
|
+
* }
|
|
2208
|
+
*
|
|
2209
|
+
* if (nextValue.count === 10) {
|
|
2210
|
+
* nextValue.isMaxValue = true; // Set isMaxValue to true if count is 10
|
|
2211
|
+
* } else {
|
|
2212
|
+
* nextValue.isMaxValue = false; // Reset isMaxValue otherwise
|
|
2213
|
+
* }
|
|
2214
|
+
* });
|
|
2215
|
+
*
|
|
2216
|
+
* store.partialNext({ count: 15 });
|
|
2217
|
+
*
|
|
2218
|
+
* store.getLatestValue(); // { count: 10, isMaxValue: true }
|
|
2219
|
+
*
|
|
2220
|
+
* store.partialNext({ count: 5 });
|
|
2221
|
+
*
|
|
2222
|
+
* store.getLatestValue(); // { count: 5, isMaxValue: false }
|
|
2223
|
+
* ```
|
|
2224
|
+
*
|
|
2225
|
+
* @param preprocessor - The function to be called with the next and previous values before the state is updated.
|
|
2226
|
+
* @returns A `RemovePreprocessor` function that removes the preprocessor when called.
|
|
2227
|
+
*/
|
|
2228
|
+
addPreprocessor(preprocessor) {
|
|
2229
|
+
this.preprocessors.add(preprocessor);
|
|
2230
|
+
return () => {
|
|
2231
|
+
this.preprocessors.delete(preprocessor);
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
};
|
|
2235
|
+
var MergedStateStore = class _MergedStateStore extends StateStore {
|
|
2236
|
+
constructor({ original, merged }) {
|
|
2237
|
+
const originalValue = original.getLatestValue();
|
|
2238
|
+
const mergedValue = merged.getLatestValue();
|
|
2239
|
+
super({
|
|
2240
|
+
...originalValue,
|
|
2241
|
+
...mergedValue
|
|
2242
|
+
});
|
|
2243
|
+
// override original methods and "disable" them
|
|
2244
|
+
this.next = () => {
|
|
2245
|
+
console.warn(
|
|
2246
|
+
`${_MergedStateStore.name}.next is disabled, call original.next or merged.next instead`
|
|
2247
|
+
);
|
|
2248
|
+
};
|
|
2249
|
+
this.partialNext = () => {
|
|
2250
|
+
console.warn(
|
|
2251
|
+
`${_MergedStateStore.name}.partialNext is disabled, call original.partialNext or merged.partialNext instead`
|
|
2252
|
+
);
|
|
2253
|
+
};
|
|
2254
|
+
this.cachedOriginalValue = originalValue;
|
|
2255
|
+
this.cachedMergedValue = mergedValue;
|
|
2256
|
+
this.original = original;
|
|
2257
|
+
this.merged = merged;
|
|
2258
|
+
}
|
|
2259
|
+
/**
|
|
2260
|
+
* Subscribes to changes in the merged state store.
|
|
2261
|
+
*
|
|
2262
|
+
* This method extends the base subscribe functionality to handle the merged nature of this store:
|
|
2263
|
+
* 1. The first subscriber triggers registration of helper subscribers that listen to both source stores
|
|
2264
|
+
* 2. Changes from either source store are propagated to this merged store
|
|
2265
|
+
* 3. Source store values are cached to prevent unnecessary updates
|
|
2266
|
+
*
|
|
2267
|
+
* When the first subscriber is added, the method sets up listeners on both original and merged stores.
|
|
2268
|
+
* These listeners update the combined store value whenever either source store changes.
|
|
2269
|
+
* All subscriptions (helpers and the actual handler) are tracked so they can be properly cleaned up.
|
|
2270
|
+
*
|
|
2271
|
+
* @param handler - The callback function that will be executed when the state changes
|
|
2272
|
+
* @returns An unsubscribe function that, when called, removes the subscription and any helper subscriptions
|
|
2273
|
+
*/
|
|
2274
|
+
subscribe(handler) {
|
|
2275
|
+
const unsubscribeFunctions = [];
|
|
2276
|
+
if (!this.handlers.size) {
|
|
2277
|
+
const base = (nextValue) => {
|
|
2278
|
+
super.next((currentValue) => ({
|
|
2279
|
+
...currentValue,
|
|
2280
|
+
...nextValue
|
|
2281
|
+
}));
|
|
2282
|
+
};
|
|
2283
|
+
unsubscribeFunctions.push(
|
|
2284
|
+
this.original.subscribe((nextValue) => {
|
|
2285
|
+
if (nextValue === this.cachedOriginalValue) return;
|
|
2286
|
+
this.cachedOriginalValue = nextValue;
|
|
2287
|
+
base(nextValue);
|
|
2288
|
+
}),
|
|
2289
|
+
this.merged.subscribe((nextValue) => {
|
|
2290
|
+
if (nextValue === this.cachedMergedValue) return;
|
|
2291
|
+
this.cachedMergedValue = nextValue;
|
|
2292
|
+
base(nextValue);
|
|
2293
|
+
})
|
|
2294
|
+
);
|
|
2295
|
+
}
|
|
2296
|
+
unsubscribeFunctions.push(super.subscribe(handler));
|
|
2297
|
+
return () => {
|
|
2298
|
+
unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2301
|
+
/**
|
|
2302
|
+
* Retrieves the latest combined state from both original and merged stores.
|
|
2303
|
+
*
|
|
2304
|
+
* This method extends the base getLatestValue functionality to ensure the merged store
|
|
2305
|
+
* remains in sync with its source stores even when there are no active subscribers.
|
|
2306
|
+
*
|
|
2307
|
+
* When there are no handlers registered, the method:
|
|
2308
|
+
* 1. Fetches the latest values from both source stores
|
|
2309
|
+
* 2. Compares them with the cached values to detect changes
|
|
2310
|
+
* 3. If changes are detected, updates the internal value and caches
|
|
2311
|
+
* the new source values to maintain consistency
|
|
2312
|
+
*
|
|
2313
|
+
* This approach ensures that calling getLatestValue() always returns the most
|
|
2314
|
+
* up-to-date combined state, even if the merged store hasn't been actively
|
|
2315
|
+
* receiving updates through subscriptions.
|
|
2316
|
+
*
|
|
2317
|
+
* @returns The latest combined state from both original and merged stores
|
|
2318
|
+
*/
|
|
2319
|
+
getLatestValue() {
|
|
2320
|
+
if (!this.handlers.size) {
|
|
2321
|
+
const originalValue = this.original.getLatestValue();
|
|
2322
|
+
const mergedValue = this.merged.getLatestValue();
|
|
2323
|
+
if (originalValue !== this.cachedOriginalValue || mergedValue !== this.cachedMergedValue) {
|
|
2324
|
+
this.value = {
|
|
2325
|
+
...originalValue,
|
|
2326
|
+
...mergedValue
|
|
2327
|
+
};
|
|
2328
|
+
this.cachedMergedValue = mergedValue;
|
|
2329
|
+
this.cachedOriginalValue = originalValue;
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
return super.getLatestValue();
|
|
2333
|
+
}
|
|
2334
|
+
addPreprocessor() {
|
|
2335
|
+
console.warn(
|
|
2336
|
+
`${_MergedStateStore.name}.addPreprocessor is disabled, call original.addPreprocessor or merged.addPreprocessor instead`
|
|
2337
|
+
);
|
|
2338
|
+
return noop;
|
|
2339
|
+
}
|
|
2340
|
+
};
|
|
2341
|
+
|
|
2342
|
+
// src/utils/WithSubscriptions.ts
|
|
2343
|
+
var _WithSubscriptions = class _WithSubscriptions {
|
|
2344
|
+
constructor() {
|
|
2345
|
+
this.unsubscribeFunctions = /* @__PURE__ */ new Set();
|
|
2346
|
+
this.refCount = 0;
|
|
2347
|
+
}
|
|
2348
|
+
/**
|
|
2349
|
+
* Returns a boolean, provides information of whether `registerSubscriptions`
|
|
2350
|
+
* method has already been called for this instance.
|
|
2351
|
+
*/
|
|
2352
|
+
get hasSubscriptions() {
|
|
2353
|
+
return this.unsubscribeFunctions.size > 0;
|
|
2354
|
+
}
|
|
2355
|
+
addUnsubscribeFunction(unsubscribeFunction) {
|
|
2356
|
+
this.unsubscribeFunctions.add(unsubscribeFunction);
|
|
2357
|
+
}
|
|
2358
|
+
/**
|
|
2359
|
+
* Increments `refCount` by one and returns new value.
|
|
2360
|
+
*/
|
|
2361
|
+
incrementRefCount() {
|
|
2362
|
+
return ++this.refCount;
|
|
2363
|
+
}
|
|
2364
|
+
/**
|
|
2365
|
+
* If you re-declare `unregisterSubscriptions` method within your class
|
|
2366
|
+
* make sure to run the original too.
|
|
2367
|
+
*
|
|
2368
|
+
* @example
|
|
2369
|
+
* ```ts
|
|
2370
|
+
* class T extends WithSubscriptions {
|
|
2371
|
+
* ...
|
|
2372
|
+
* public unregisterSubscriptions = () => {
|
|
2373
|
+
* this.customThing();
|
|
2374
|
+
* return super.unregisterSubscriptions();
|
|
2375
|
+
* }
|
|
2376
|
+
* }
|
|
2377
|
+
* ```
|
|
2378
|
+
*/
|
|
2379
|
+
unregisterSubscriptions() {
|
|
2380
|
+
if (this.refCount > 1) {
|
|
2381
|
+
this.refCount--;
|
|
2382
|
+
return _WithSubscriptions.symbol;
|
|
2383
|
+
}
|
|
2384
|
+
this.unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
|
|
2385
|
+
this.unsubscribeFunctions.clear();
|
|
2386
|
+
this.refCount = 0;
|
|
2387
|
+
return _WithSubscriptions.symbol;
|
|
2388
|
+
}
|
|
2389
|
+
};
|
|
2390
|
+
/**
|
|
2391
|
+
* Workaround for the missing TS keyword - ensures that inheritants
|
|
2392
|
+
* overriding `unregisterSubscriptions` call the base method and return
|
|
2393
|
+
* its unique symbol value.
|
|
2394
|
+
*/
|
|
2395
|
+
_WithSubscriptions.symbol = Symbol(_WithSubscriptions.name);
|
|
2396
|
+
var WithSubscriptions = _WithSubscriptions;
|
|
2397
|
+
|
|
2398
|
+
// src/CooldownTimer.ts
|
|
2399
|
+
var toDateOrUndefined = (value) => {
|
|
2400
|
+
if (value instanceof Date) return value;
|
|
2401
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
2402
|
+
const parsed = new Date(value);
|
|
2403
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
2404
|
+
}
|
|
2405
|
+
return void 0;
|
|
2406
|
+
};
|
|
2407
|
+
var CooldownTimer = class extends WithSubscriptions {
|
|
2408
|
+
constructor({ channel }) {
|
|
2409
|
+
super();
|
|
2410
|
+
this.timeout = null;
|
|
2411
|
+
this.registerSubscriptions = () => {
|
|
2412
|
+
this.incrementRefCount();
|
|
2413
|
+
if (this.hasSubscriptions) return;
|
|
2414
|
+
this.addUnsubscribeFunction(
|
|
2415
|
+
this.channel.on("message.new", (event) => {
|
|
2416
|
+
const isOwnMessage = event.message?.user?.id && event.message.user.id === this.getOwnUserId();
|
|
2417
|
+
if (!isOwnMessage) return;
|
|
2418
|
+
this.setOwnLatestMessageDate(toDateOrUndefined(event.message?.created_at));
|
|
2419
|
+
}).unsubscribe
|
|
2420
|
+
);
|
|
2421
|
+
this.addUnsubscribeFunction(
|
|
2422
|
+
this.channel.on("channel.updated", (event) => {
|
|
2423
|
+
const cooldownChanged = event.channel?.cooldown !== this.cooldownConfigSeconds;
|
|
2424
|
+
if (!cooldownChanged) return;
|
|
2425
|
+
this.refresh();
|
|
2426
|
+
}).unsubscribe
|
|
2427
|
+
);
|
|
2428
|
+
};
|
|
2429
|
+
this.setCooldownRemaining = (cooldownRemaining) => {
|
|
2430
|
+
this.state.partialNext({ cooldownRemaining });
|
|
2431
|
+
};
|
|
2432
|
+
this.clearTimeout = () => {
|
|
2433
|
+
if (!this.timeout) return;
|
|
2434
|
+
clearTimeout(this.timeout);
|
|
2435
|
+
this.timeout = null;
|
|
2436
|
+
};
|
|
2437
|
+
this.refresh = () => {
|
|
2438
|
+
const { cooldown: cooldownConfigSeconds = 0, own_capabilities } = this.channel.data ?? {};
|
|
2439
|
+
const canSkipCooldown = (own_capabilities ?? []).includes("skip-slow-mode");
|
|
2440
|
+
const ownLatestMessageDate = this.findOwnLatestMessageDate({
|
|
2441
|
+
messages: this.channel.state.latestMessages
|
|
2442
|
+
});
|
|
2443
|
+
if (cooldownConfigSeconds !== this.cooldownConfigSeconds || ownLatestMessageDate?.getTime() !== this.ownLatestMessageDate?.getTime() || canSkipCooldown !== this.canSkipCooldown) {
|
|
2444
|
+
this.state.partialNext({
|
|
2445
|
+
cooldownConfigSeconds,
|
|
2446
|
+
ownLatestMessageDate,
|
|
2447
|
+
canSkipCooldown
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2450
|
+
if (this.canSkipCooldown || this.cooldownConfigSeconds === 0) {
|
|
2451
|
+
this.clearTimeout();
|
|
2452
|
+
if (this.cooldownRemaining !== 0) {
|
|
2453
|
+
this.setCooldownRemaining(0);
|
|
2454
|
+
}
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
this.recalculate();
|
|
2458
|
+
};
|
|
2459
|
+
/**
|
|
2460
|
+
* Updates the known latest own message date and recomputes remaining time.
|
|
2461
|
+
* Prefer calling this when you already know the message date (e.g. from an event).
|
|
2462
|
+
*/
|
|
2463
|
+
this.setOwnLatestMessageDate = (date) => {
|
|
2464
|
+
this.state.partialNext({ ownLatestMessageDate: date });
|
|
2465
|
+
this.recalculate();
|
|
2466
|
+
};
|
|
2467
|
+
this.recalculate = () => {
|
|
2468
|
+
this.clearTimeout();
|
|
2469
|
+
const { cooldownConfigSeconds, ownLatestMessageDate, canSkipCooldown } = this.state.getLatestValue();
|
|
2470
|
+
const timeSinceOwnLastMessage = ownLatestMessageDate != null ? (
|
|
2471
|
+
// prevent negative values
|
|
2472
|
+
Math.max(0, (Date.now() - ownLatestMessageDate.getTime()) / 1e3)
|
|
2473
|
+
) : void 0;
|
|
2474
|
+
const remaining = !canSkipCooldown && typeof timeSinceOwnLastMessage !== "undefined" && cooldownConfigSeconds > timeSinceOwnLastMessage ? Math.round(cooldownConfigSeconds - timeSinceOwnLastMessage) : 0;
|
|
2475
|
+
if (remaining !== this.cooldownRemaining) {
|
|
2476
|
+
this.setCooldownRemaining(remaining);
|
|
2477
|
+
}
|
|
2478
|
+
if (remaining <= 0) return;
|
|
2479
|
+
this.timeout = setTimeout(() => {
|
|
2480
|
+
this.recalculate();
|
|
2481
|
+
}, 1e3);
|
|
2482
|
+
};
|
|
2483
|
+
this.channel = channel;
|
|
2484
|
+
this.state = new StateStore({
|
|
2485
|
+
cooldownConfigSeconds: 0,
|
|
2486
|
+
cooldownRemaining: 0,
|
|
2487
|
+
ownLatestMessageDate: void 0,
|
|
2488
|
+
canSkipCooldown: false
|
|
2489
|
+
});
|
|
2490
|
+
this.refresh();
|
|
2491
|
+
}
|
|
2492
|
+
get cooldownConfigSeconds() {
|
|
2493
|
+
return this.state.getLatestValue().cooldownConfigSeconds;
|
|
2494
|
+
}
|
|
2495
|
+
get cooldownRemaining() {
|
|
2496
|
+
return this.state.getLatestValue().cooldownRemaining;
|
|
2497
|
+
}
|
|
2498
|
+
get canSkipCooldown() {
|
|
2499
|
+
return this.state.getLatestValue().canSkipCooldown;
|
|
2500
|
+
}
|
|
2501
|
+
get ownLatestMessageDate() {
|
|
2502
|
+
return this.state.getLatestValue().ownLatestMessageDate;
|
|
2503
|
+
}
|
|
2504
|
+
getOwnUserId() {
|
|
2505
|
+
const client = this.channel.getClient();
|
|
2506
|
+
return client.userID ?? client.user?.id;
|
|
2507
|
+
}
|
|
2508
|
+
findOwnLatestMessageDate({
|
|
2509
|
+
messages
|
|
2510
|
+
}) {
|
|
2511
|
+
const ownUserId = this.getOwnUserId();
|
|
2512
|
+
if (!ownUserId) return void 0;
|
|
2513
|
+
let latest;
|
|
2514
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
2515
|
+
const message = messages[i];
|
|
2516
|
+
if (message.user?.id !== ownUserId) continue;
|
|
2517
|
+
const createdAt = toDateOrUndefined(message.created_at);
|
|
2518
|
+
if (!createdAt) continue;
|
|
2519
|
+
if (!latest || createdAt.getTime() > latest.getTime()) {
|
|
2520
|
+
latest = createdAt;
|
|
2521
|
+
}
|
|
2522
|
+
if (latest.getTime() > createdAt.getTime()) break;
|
|
2523
|
+
}
|
|
2524
|
+
return latest;
|
|
2525
|
+
}
|
|
2526
|
+
};
|
|
2527
|
+
|
|
2135
2528
|
// src/messageComposer/attachmentIdentity.ts
|
|
2136
2529
|
var isScrapedContent = (attachment) => !!attachment?.og_scrape_url || !!attachment?.title_link;
|
|
2137
2530
|
var isLocalAttachment = (attachment) => !!attachment?.localMetadata?.id;
|
|
@@ -2223,11 +2616,12 @@ var createPostUploadAttachmentEnrichmentMiddleware = () => ({
|
|
|
2223
2616
|
if (error) return forward();
|
|
2224
2617
|
if (!attachment || !response) return discard();
|
|
2225
2618
|
const enrichedAttachment = { ...attachment };
|
|
2619
|
+
const previewUri = attachment.localMetadata.previewUri;
|
|
2620
|
+
if (previewUri) {
|
|
2621
|
+
if (previewUri.startsWith("blob:")) URL.revokeObjectURL(previewUri);
|
|
2622
|
+
delete enrichedAttachment.localMetadata.previewUri;
|
|
2623
|
+
}
|
|
2226
2624
|
if (isLocalImageAttachment(attachment)) {
|
|
2227
|
-
if (attachment.localMetadata.previewUri) {
|
|
2228
|
-
URL.revokeObjectURL(attachment.localMetadata.previewUri);
|
|
2229
|
-
delete enrichedAttachment.localMetadata.previewUri;
|
|
2230
|
-
}
|
|
2231
2625
|
enrichedAttachment.image_url = response.file;
|
|
2232
2626
|
} else {
|
|
2233
2627
|
enrichedAttachment.asset_url = response.file;
|
|
@@ -2438,275 +2832,68 @@ var createUploadConfigCheckMiddleware = (composer) => ({
|
|
|
2438
2832
|
id: "stream-io/attachment-manager-middleware/file-upload-config-check",
|
|
2439
2833
|
handlers: {
|
|
2440
2834
|
prepare: async ({
|
|
2441
|
-
state,
|
|
2442
|
-
next,
|
|
2443
|
-
discard
|
|
2444
|
-
}) => {
|
|
2445
|
-
const { attachmentManager } = composer;
|
|
2446
|
-
if (!attachmentManager || !state.attachment) return discard();
|
|
2447
|
-
const uploadPermissionCheck = await attachmentManager.getUploadConfigCheck(
|
|
2448
|
-
state.attachment.localMetadata.file
|
|
2449
|
-
);
|
|
2450
|
-
const attachment = {
|
|
2451
|
-
...state.attachment,
|
|
2452
|
-
localMetadata: {
|
|
2453
|
-
...state.attachment.localMetadata,
|
|
2454
|
-
uploadPermissionCheck,
|
|
2455
|
-
uploadState: uploadPermissionCheck.uploadBlocked ? "blocked" : "pending"
|
|
2456
|
-
}
|
|
2457
|
-
};
|
|
2458
|
-
return next({
|
|
2459
|
-
...state,
|
|
2460
|
-
attachment
|
|
2461
|
-
});
|
|
2462
|
-
}
|
|
2463
|
-
}
|
|
2464
|
-
});
|
|
2465
|
-
|
|
2466
|
-
// src/messageComposer/middleware/attachmentManager/preUpload/blockedUploadNotification.ts
|
|
2467
|
-
var createBlockedAttachmentUploadNotificationMiddleware = (composer) => ({
|
|
2468
|
-
id: "stream-io/attachment-manager-middleware/blocked-upload-notification",
|
|
2469
|
-
handlers: {
|
|
2470
|
-
prepare: ({
|
|
2471
|
-
state: { attachment },
|
|
2472
|
-
forward
|
|
2473
|
-
}) => {
|
|
2474
|
-
if (!attachment) return forward();
|
|
2475
|
-
if (attachment.localMetadata.uploadPermissionCheck?.uploadBlocked) {
|
|
2476
|
-
composer.client.notifications.addError({
|
|
2477
|
-
message: `The attachment upload was blocked`,
|
|
2478
|
-
origin: {
|
|
2479
|
-
emitter: "AttachmentManager",
|
|
2480
|
-
context: { blockedAttachment: attachment }
|
|
2481
|
-
},
|
|
2482
|
-
options: {
|
|
2483
|
-
type: "validation:attachment:upload:blocked",
|
|
2484
|
-
metadata: {
|
|
2485
|
-
reason: attachment.localMetadata.uploadPermissionCheck?.reason
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
|
-
});
|
|
2489
|
-
}
|
|
2490
|
-
return forward();
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
});
|
|
2494
|
-
|
|
2495
|
-
// src/messageComposer/middleware/attachmentManager/preUpload/AttachmentPreUploadMiddlewareExecutor.ts
|
|
2496
|
-
var AttachmentPreUploadMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
2497
|
-
constructor({ composer }) {
|
|
2498
|
-
super();
|
|
2499
|
-
this.use([
|
|
2500
|
-
createUploadConfigCheckMiddleware(composer),
|
|
2501
|
-
createBlockedAttachmentUploadNotificationMiddleware(composer)
|
|
2502
|
-
]);
|
|
2503
|
-
}
|
|
2504
|
-
};
|
|
2505
|
-
|
|
2506
|
-
// src/store.ts
|
|
2507
|
-
var isPatch = (value) => typeof value === "function";
|
|
2508
|
-
var noop = () => {
|
|
2509
|
-
};
|
|
2510
|
-
var StateStore = class {
|
|
2511
|
-
constructor(value) {
|
|
2512
|
-
this.value = value;
|
|
2513
|
-
this.handlers = /* @__PURE__ */ new Set();
|
|
2514
|
-
this.preprocessors = /* @__PURE__ */ new Set();
|
|
2515
|
-
this.partialNext = (partial) => this.next((current) => ({ ...current, ...partial }));
|
|
2516
|
-
this.subscribeWithSelector = (selector, handler) => {
|
|
2517
|
-
let previouslySelectedValues;
|
|
2518
|
-
const wrappedHandler = (nextValue) => {
|
|
2519
|
-
const newlySelectedValues = selector(nextValue);
|
|
2520
|
-
let hasUpdatedValues = typeof previouslySelectedValues === "undefined";
|
|
2521
|
-
for (const key in previouslySelectedValues) {
|
|
2522
|
-
if (previouslySelectedValues[key] === newlySelectedValues[key]) continue;
|
|
2523
|
-
hasUpdatedValues = true;
|
|
2524
|
-
break;
|
|
2525
|
-
}
|
|
2526
|
-
if (!hasUpdatedValues) return;
|
|
2527
|
-
const previouslySelectedValuesCopy = previouslySelectedValues;
|
|
2528
|
-
previouslySelectedValues = newlySelectedValues;
|
|
2529
|
-
handler(newlySelectedValues, previouslySelectedValuesCopy);
|
|
2530
|
-
};
|
|
2531
|
-
return this.subscribe(wrappedHandler);
|
|
2532
|
-
};
|
|
2533
|
-
}
|
|
2534
|
-
/**
|
|
2535
|
-
* Allows merging two stores only if their keys differ otherwise there's no way to ensure the data type stability.
|
|
2536
|
-
* @experimental
|
|
2537
|
-
* This method is experimental and may change in future versions.
|
|
2538
|
-
*/
|
|
2539
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2540
|
-
merge(stateStore) {
|
|
2541
|
-
return new MergedStateStore({
|
|
2542
|
-
original: this,
|
|
2543
|
-
merged: stateStore
|
|
2544
|
-
});
|
|
2545
|
-
}
|
|
2546
|
-
next(newValueOrPatch) {
|
|
2547
|
-
const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
|
|
2548
|
-
if (newValue === this.value) return;
|
|
2549
|
-
this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
|
|
2550
|
-
const oldValue = this.value;
|
|
2551
|
-
this.value = newValue;
|
|
2552
|
-
this.handlers.forEach((handler) => handler(this.value, oldValue));
|
|
2553
|
-
}
|
|
2554
|
-
getLatestValue() {
|
|
2555
|
-
return this.value;
|
|
2556
|
-
}
|
|
2557
|
-
subscribe(handler) {
|
|
2558
|
-
handler(this.value, void 0);
|
|
2559
|
-
this.handlers.add(handler);
|
|
2560
|
-
return () => {
|
|
2561
|
-
this.handlers.delete(handler);
|
|
2562
|
-
};
|
|
2563
|
-
}
|
|
2564
|
-
/**
|
|
2565
|
-
* Registers a preprocessor function that will be called before the state is updated.
|
|
2566
|
-
*
|
|
2567
|
-
* Preprocessors are invoked with the new and previous values whenever `next` or `partialNext` methods
|
|
2568
|
-
* are called, allowing you to mutate or react to the new value before it is set. Preprocessors run in the
|
|
2569
|
-
* order they were registered.
|
|
2570
|
-
*
|
|
2571
|
-
* @example
|
|
2572
|
-
* ```ts
|
|
2573
|
-
* const store = new StateStore<{ count: number; isMaxValue: bool; }>({ count: 0, isMaxValue: false });
|
|
2574
|
-
*
|
|
2575
|
-
* store.addPreprocessor((nextValue, prevValue) => {
|
|
2576
|
-
* if (nextValue.count > 10) {
|
|
2577
|
-
* nextValue.count = 10; // Clamp the value to a maximum of 10
|
|
2578
|
-
* }
|
|
2579
|
-
*
|
|
2580
|
-
* if (nextValue.count === 10) {
|
|
2581
|
-
* nextValue.isMaxValue = true; // Set isMaxValue to true if count is 10
|
|
2582
|
-
* } else {
|
|
2583
|
-
* nextValue.isMaxValue = false; // Reset isMaxValue otherwise
|
|
2584
|
-
* }
|
|
2585
|
-
* });
|
|
2586
|
-
*
|
|
2587
|
-
* store.partialNext({ count: 15 });
|
|
2588
|
-
*
|
|
2589
|
-
* store.getLatestValue(); // { count: 10, isMaxValue: true }
|
|
2590
|
-
*
|
|
2591
|
-
* store.partialNext({ count: 5 });
|
|
2592
|
-
*
|
|
2593
|
-
* store.getLatestValue(); // { count: 5, isMaxValue: false }
|
|
2594
|
-
* ```
|
|
2595
|
-
*
|
|
2596
|
-
* @param preprocessor - The function to be called with the next and previous values before the state is updated.
|
|
2597
|
-
* @returns A `RemovePreprocessor` function that removes the preprocessor when called.
|
|
2598
|
-
*/
|
|
2599
|
-
addPreprocessor(preprocessor) {
|
|
2600
|
-
this.preprocessors.add(preprocessor);
|
|
2601
|
-
return () => {
|
|
2602
|
-
this.preprocessors.delete(preprocessor);
|
|
2603
|
-
};
|
|
2604
|
-
}
|
|
2605
|
-
};
|
|
2606
|
-
var MergedStateStore = class _MergedStateStore extends StateStore {
|
|
2607
|
-
constructor({ original, merged }) {
|
|
2608
|
-
const originalValue = original.getLatestValue();
|
|
2609
|
-
const mergedValue = merged.getLatestValue();
|
|
2610
|
-
super({
|
|
2611
|
-
...originalValue,
|
|
2612
|
-
...mergedValue
|
|
2613
|
-
});
|
|
2614
|
-
// override original methods and "disable" them
|
|
2615
|
-
this.next = () => {
|
|
2616
|
-
console.warn(
|
|
2617
|
-
`${_MergedStateStore.name}.next is disabled, call original.next or merged.next instead`
|
|
2618
|
-
);
|
|
2619
|
-
};
|
|
2620
|
-
this.partialNext = () => {
|
|
2621
|
-
console.warn(
|
|
2622
|
-
`${_MergedStateStore.name}.partialNext is disabled, call original.partialNext or merged.partialNext instead`
|
|
2835
|
+
state,
|
|
2836
|
+
next,
|
|
2837
|
+
discard
|
|
2838
|
+
}) => {
|
|
2839
|
+
const { attachmentManager } = composer;
|
|
2840
|
+
if (!attachmentManager || !state.attachment) return discard();
|
|
2841
|
+
const uploadPermissionCheck = await attachmentManager.getUploadConfigCheck(
|
|
2842
|
+
state.attachment.localMetadata.file
|
|
2623
2843
|
);
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
* Subscribes to changes in the merged state store.
|
|
2632
|
-
*
|
|
2633
|
-
* This method extends the base subscribe functionality to handle the merged nature of this store:
|
|
2634
|
-
* 1. The first subscriber triggers registration of helper subscribers that listen to both source stores
|
|
2635
|
-
* 2. Changes from either source store are propagated to this merged store
|
|
2636
|
-
* 3. Source store values are cached to prevent unnecessary updates
|
|
2637
|
-
*
|
|
2638
|
-
* When the first subscriber is added, the method sets up listeners on both original and merged stores.
|
|
2639
|
-
* These listeners update the combined store value whenever either source store changes.
|
|
2640
|
-
* All subscriptions (helpers and the actual handler) are tracked so they can be properly cleaned up.
|
|
2641
|
-
*
|
|
2642
|
-
* @param handler - The callback function that will be executed when the state changes
|
|
2643
|
-
* @returns An unsubscribe function that, when called, removes the subscription and any helper subscriptions
|
|
2644
|
-
*/
|
|
2645
|
-
subscribe(handler) {
|
|
2646
|
-
const unsubscribeFunctions = [];
|
|
2647
|
-
if (!this.handlers.size) {
|
|
2648
|
-
const base = (nextValue) => {
|
|
2649
|
-
super.next((currentValue) => ({
|
|
2650
|
-
...currentValue,
|
|
2651
|
-
...nextValue
|
|
2652
|
-
}));
|
|
2844
|
+
const attachment = {
|
|
2845
|
+
...state.attachment,
|
|
2846
|
+
localMetadata: {
|
|
2847
|
+
...state.attachment.localMetadata,
|
|
2848
|
+
uploadPermissionCheck,
|
|
2849
|
+
uploadState: uploadPermissionCheck.uploadBlocked ? "blocked" : "pending"
|
|
2850
|
+
}
|
|
2653
2851
|
};
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
base(nextValue);
|
|
2659
|
-
}),
|
|
2660
|
-
this.merged.subscribe((nextValue) => {
|
|
2661
|
-
if (nextValue === this.cachedMergedValue) return;
|
|
2662
|
-
this.cachedMergedValue = nextValue;
|
|
2663
|
-
base(nextValue);
|
|
2664
|
-
})
|
|
2665
|
-
);
|
|
2852
|
+
return next({
|
|
2853
|
+
...state,
|
|
2854
|
+
attachment
|
|
2855
|
+
});
|
|
2666
2856
|
}
|
|
2667
|
-
unsubscribeFunctions.push(super.subscribe(handler));
|
|
2668
|
-
return () => {
|
|
2669
|
-
unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
|
|
2670
|
-
};
|
|
2671
2857
|
}
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
...mergedValue
|
|
2698
|
-
};
|
|
2699
|
-
this.cachedMergedValue = mergedValue;
|
|
2700
|
-
this.cachedOriginalValue = originalValue;
|
|
2858
|
+
});
|
|
2859
|
+
|
|
2860
|
+
// src/messageComposer/middleware/attachmentManager/preUpload/blockedUploadNotification.ts
|
|
2861
|
+
var createBlockedAttachmentUploadNotificationMiddleware = (composer) => ({
|
|
2862
|
+
id: "stream-io/attachment-manager-middleware/blocked-upload-notification",
|
|
2863
|
+
handlers: {
|
|
2864
|
+
prepare: ({
|
|
2865
|
+
state: { attachment },
|
|
2866
|
+
forward
|
|
2867
|
+
}) => {
|
|
2868
|
+
if (!attachment) return forward();
|
|
2869
|
+
if (attachment.localMetadata.uploadPermissionCheck?.uploadBlocked) {
|
|
2870
|
+
composer.client.notifications.addError({
|
|
2871
|
+
message: `The attachment upload was blocked`,
|
|
2872
|
+
origin: {
|
|
2873
|
+
emitter: "AttachmentManager",
|
|
2874
|
+
context: { blockedAttachment: attachment }
|
|
2875
|
+
},
|
|
2876
|
+
options: {
|
|
2877
|
+
type: "validation:attachment:upload:blocked",
|
|
2878
|
+
metadata: {
|
|
2879
|
+
reason: attachment.localMetadata.uploadPermissionCheck?.reason
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
});
|
|
2701
2883
|
}
|
|
2884
|
+
return forward();
|
|
2702
2885
|
}
|
|
2703
|
-
return super.getLatestValue();
|
|
2704
2886
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2887
|
+
});
|
|
2888
|
+
|
|
2889
|
+
// src/messageComposer/middleware/attachmentManager/preUpload/AttachmentPreUploadMiddlewareExecutor.ts
|
|
2890
|
+
var AttachmentPreUploadMiddlewareExecutor = class extends MiddlewareExecutor {
|
|
2891
|
+
constructor({ composer }) {
|
|
2892
|
+
super();
|
|
2893
|
+
this.use([
|
|
2894
|
+
createUploadConfigCheckMiddleware(composer),
|
|
2895
|
+
createBlockedAttachmentUploadNotificationMiddleware(composer)
|
|
2896
|
+
]);
|
|
2710
2897
|
}
|
|
2711
2898
|
};
|
|
2712
2899
|
|
|
@@ -3336,11 +3523,12 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
3336
3523
|
uploadState: "finished"
|
|
3337
3524
|
}
|
|
3338
3525
|
};
|
|
3526
|
+
const previewUri = uploadedAttachment.localMetadata.previewUri;
|
|
3527
|
+
if (previewUri) {
|
|
3528
|
+
if (previewUri.startsWith("blob:")) URL.revokeObjectURL(previewUri);
|
|
3529
|
+
delete uploadedAttachment.localMetadata.previewUri;
|
|
3530
|
+
}
|
|
3339
3531
|
if (isLocalImageAttachment(uploadedAttachment)) {
|
|
3340
|
-
if (uploadedAttachment.localMetadata.previewUri) {
|
|
3341
|
-
URL.revokeObjectURL(uploadedAttachment.localMetadata.previewUri);
|
|
3342
|
-
delete uploadedAttachment.localMetadata.previewUri;
|
|
3343
|
-
}
|
|
3344
3532
|
uploadedAttachment.image_url = response.file;
|
|
3345
3533
|
} else {
|
|
3346
3534
|
uploadedAttachment.asset_url = response.file;
|
|
@@ -3521,12 +3709,10 @@ _AttachmentManager.toLocalUploadAttachment = (fileLike) => {
|
|
|
3521
3709
|
type: getAttachmentTypeFromMimeType(file.type)
|
|
3522
3710
|
};
|
|
3523
3711
|
localAttachment[isImageFile(file) ? "fallback" : "title"] = file.name;
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
localAttachment.original_width = fileLike.width;
|
|
3529
|
-
}
|
|
3712
|
+
localAttachment.localMetadata.previewUri = isFileReference(fileLike) ? fileLike.uri : URL.createObjectURL?.(fileLike);
|
|
3713
|
+
if (isFileReference(fileLike) && fileLike.height && fileLike.width && isImageFile(file)) {
|
|
3714
|
+
localAttachment.original_height = fileLike.height;
|
|
3715
|
+
localAttachment.original_width = fileLike.width;
|
|
3530
3716
|
}
|
|
3531
3717
|
if (isFileReference(fileLike) && fileLike.thumb_url) {
|
|
3532
3718
|
localAttachment.thumb_url = fileLike.thumb_url;
|
|
@@ -5560,10 +5746,11 @@ var getTriggerCharWithToken = ({
|
|
|
5560
5746
|
isCommand = false,
|
|
5561
5747
|
acceptTrailingSpaces = true
|
|
5562
5748
|
}) => {
|
|
5563
|
-
const
|
|
5749
|
+
const escapedTrigger = escapeRegExp(trigger);
|
|
5750
|
+
const triggerNorWhitespace = `[^\\s${escapedTrigger}]*`;
|
|
5564
5751
|
const match = text.match(
|
|
5565
5752
|
new RegExp(
|
|
5566
|
-
isCommand ? `^[${
|
|
5753
|
+
isCommand ? `^[${escapedTrigger}]${triggerNorWhitespace}$` : acceptTrailingSpaces ? `(?!^|\\W)?[${escapedTrigger}]${triggerNorWhitespace}\\s?${triggerNorWhitespace}$` : `(?!^|\\W)?[${escapedTrigger}]${triggerNorWhitespace}$`,
|
|
5567
5754
|
"g"
|
|
5568
5755
|
)
|
|
5569
5756
|
);
|
|
@@ -6341,62 +6528,6 @@ var TextComposer = class {
|
|
|
6341
6528
|
// --- END TEXT PROCESSING ----
|
|
6342
6529
|
};
|
|
6343
6530
|
|
|
6344
|
-
// src/utils/WithSubscriptions.ts
|
|
6345
|
-
var _WithSubscriptions = class _WithSubscriptions {
|
|
6346
|
-
constructor() {
|
|
6347
|
-
this.unsubscribeFunctions = /* @__PURE__ */ new Set();
|
|
6348
|
-
this.refCount = 0;
|
|
6349
|
-
}
|
|
6350
|
-
/**
|
|
6351
|
-
* Returns a boolean, provides information of whether `registerSubscriptions`
|
|
6352
|
-
* method has already been called for this instance.
|
|
6353
|
-
*/
|
|
6354
|
-
get hasSubscriptions() {
|
|
6355
|
-
return this.unsubscribeFunctions.size > 0;
|
|
6356
|
-
}
|
|
6357
|
-
addUnsubscribeFunction(unsubscribeFunction) {
|
|
6358
|
-
this.unsubscribeFunctions.add(unsubscribeFunction);
|
|
6359
|
-
}
|
|
6360
|
-
/**
|
|
6361
|
-
* Increments `refCount` by one and returns new value.
|
|
6362
|
-
*/
|
|
6363
|
-
incrementRefCount() {
|
|
6364
|
-
return ++this.refCount;
|
|
6365
|
-
}
|
|
6366
|
-
/**
|
|
6367
|
-
* If you re-declare `unregisterSubscriptions` method within your class
|
|
6368
|
-
* make sure to run the original too.
|
|
6369
|
-
*
|
|
6370
|
-
* @example
|
|
6371
|
-
* ```ts
|
|
6372
|
-
* class T extends WithSubscriptions {
|
|
6373
|
-
* ...
|
|
6374
|
-
* public unregisterSubscriptions = () => {
|
|
6375
|
-
* this.customThing();
|
|
6376
|
-
* return super.unregisterSubscriptions();
|
|
6377
|
-
* }
|
|
6378
|
-
* }
|
|
6379
|
-
* ```
|
|
6380
|
-
*/
|
|
6381
|
-
unregisterSubscriptions() {
|
|
6382
|
-
if (this.refCount > 1) {
|
|
6383
|
-
this.refCount--;
|
|
6384
|
-
return _WithSubscriptions.symbol;
|
|
6385
|
-
}
|
|
6386
|
-
this.unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
|
|
6387
|
-
this.unsubscribeFunctions.clear();
|
|
6388
|
-
this.refCount = 0;
|
|
6389
|
-
return _WithSubscriptions.symbol;
|
|
6390
|
-
}
|
|
6391
|
-
};
|
|
6392
|
-
/**
|
|
6393
|
-
* Workaround for the missing TS keyword - ensures that inheritants
|
|
6394
|
-
* overriding `unregisterSubscriptions` call the base method and return
|
|
6395
|
-
* its unique symbol value.
|
|
6396
|
-
*/
|
|
6397
|
-
_WithSubscriptions.symbol = Symbol(_WithSubscriptions.name);
|
|
6398
|
-
var WithSubscriptions = _WithSubscriptions;
|
|
6399
|
-
|
|
6400
6531
|
// src/thread.ts
|
|
6401
6532
|
var DEFAULT_PAGE_LIMIT = 50;
|
|
6402
6533
|
var DEFAULT_SORT = [{ created_at: -1 }];
|
|
@@ -7983,6 +8114,7 @@ var Channel = class {
|
|
|
7983
8114
|
return msg && { timestampMs, msgId: msg.id };
|
|
7984
8115
|
}
|
|
7985
8116
|
});
|
|
8117
|
+
this.cooldownTimer = new CooldownTimer({ channel: this });
|
|
7986
8118
|
}
|
|
7987
8119
|
/**
|
|
7988
8120
|
* getClient - Get the chat client for this channel. If client.disconnect() was called, this function will error
|
|
@@ -9118,6 +9250,7 @@ var Channel = class {
|
|
|
9118
9250
|
].sort().join();
|
|
9119
9251
|
this.data = state.channel;
|
|
9120
9252
|
this.offlineMode = false;
|
|
9253
|
+
this.cooldownTimer.refresh();
|
|
9121
9254
|
if (areCapabilitiesChanged) {
|
|
9122
9255
|
this.getClient().dispatchEvent({
|
|
9123
9256
|
type: "capabilities.changed",
|
|
@@ -9188,11 +9321,13 @@ var Channel = class {
|
|
|
9188
9321
|
* unbanUser - Removes the bans for a user on a channel
|
|
9189
9322
|
*
|
|
9190
9323
|
* @param {string} targetUserID
|
|
9324
|
+
* @param {UnBanUserOptions} options
|
|
9191
9325
|
* @returns {Promise<APIResponse>}
|
|
9192
9326
|
*/
|
|
9193
|
-
async unbanUser(targetUserID) {
|
|
9327
|
+
async unbanUser(targetUserID, options) {
|
|
9194
9328
|
this._checkInitialized();
|
|
9195
9329
|
return await this.getClient().unbanUser(targetUserID, {
|
|
9330
|
+
...options,
|
|
9196
9331
|
type: this.type,
|
|
9197
9332
|
id: this.id
|
|
9198
9333
|
});
|
|
@@ -9497,6 +9632,9 @@ var Channel = class {
|
|
|
9497
9632
|
channelState.addPinnedMessage(event.message);
|
|
9498
9633
|
}
|
|
9499
9634
|
const preventUnreadCountUpdate = ownMessage || isThreadMessage;
|
|
9635
|
+
if (ownMessage) {
|
|
9636
|
+
this.cooldownTimer.refresh();
|
|
9637
|
+
}
|
|
9500
9638
|
if (preventUnreadCountUpdate) break;
|
|
9501
9639
|
if (event.user?.id) {
|
|
9502
9640
|
for (const userId in channelState.read) {
|
|
@@ -9631,6 +9769,7 @@ var Channel = class {
|
|
|
9631
9769
|
own_capabilities: event.channel?.own_capabilities ?? channel.data?.own_capabilities
|
|
9632
9770
|
};
|
|
9633
9771
|
channel.data = newChannelData;
|
|
9772
|
+
this.cooldownTimer.refresh();
|
|
9634
9773
|
}
|
|
9635
9774
|
break;
|
|
9636
9775
|
case "reaction.new":
|
|
@@ -9815,6 +9954,7 @@ var Channel = class {
|
|
|
9815
9954
|
}
|
|
9816
9955
|
);
|
|
9817
9956
|
this.disconnected = true;
|
|
9957
|
+
this.cooldownTimer.clearTimeout();
|
|
9818
9958
|
this.state.setIsUpToDate(false);
|
|
9819
9959
|
}
|
|
9820
9960
|
};
|
|
@@ -13778,6 +13918,20 @@ var StreamChat = class _StreamChat {
|
|
|
13778
13918
|
}
|
|
13779
13919
|
});
|
|
13780
13920
|
}
|
|
13921
|
+
/**
|
|
13922
|
+
* queryFutureChannelBans - Query future channel bans created by a user
|
|
13923
|
+
*
|
|
13924
|
+
* @param {QueryFutureChannelBansOptions} options Option object with user_id, exclude_expired_bans, limit, offset
|
|
13925
|
+
* @returns {Promise<FutureChannelBansResponse>} Future Channel Bans Response
|
|
13926
|
+
*/
|
|
13927
|
+
async queryFutureChannelBans(options = {}) {
|
|
13928
|
+
return await this.get(
|
|
13929
|
+
this.baseURL + "/query_future_channel_bans",
|
|
13930
|
+
{
|
|
13931
|
+
payload: options
|
|
13932
|
+
}
|
|
13933
|
+
);
|
|
13934
|
+
}
|
|
13781
13935
|
/**
|
|
13782
13936
|
* queryMessageFlags - Query message flags
|
|
13783
13937
|
*
|
|
@@ -13797,10 +13951,10 @@ var StreamChat = class _StreamChat {
|
|
|
13797
13951
|
/**
|
|
13798
13952
|
* queryChannelsRequest - Queries channels and returns the raw response
|
|
13799
13953
|
*
|
|
13800
|
-
* @param {ChannelFilters} filterConditions object MongoDB style filters
|
|
13954
|
+
* @param {ChannelFilters} filterConditions object MongoDB style filters. Can be empty object when using predefined_filter in options.
|
|
13801
13955
|
* @param {ChannelSort} [sort] Sort options, for instance {created_at: -1}.
|
|
13802
13956
|
* When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_updated: -1}, {created_at: 1}]
|
|
13803
|
-
* @param {ChannelOptions} [options] Options object
|
|
13957
|
+
* @param {ChannelOptions} [options] Options object. Can include predefined_filter, filter_values, and sort_values for using predefined filters.
|
|
13804
13958
|
*
|
|
13805
13959
|
* @return {Promise<Array<ChannelAPIResponse>>} search channels response
|
|
13806
13960
|
*/
|
|
@@ -13814,11 +13968,18 @@ var StreamChat = class _StreamChat {
|
|
|
13814
13968
|
if (!this._hasConnectionID()) {
|
|
13815
13969
|
defaultOptions.watch = false;
|
|
13816
13970
|
}
|
|
13817
|
-
const
|
|
13971
|
+
const { predefined_filter, filter_values, sort_values, ...restOptions } = options;
|
|
13972
|
+
const payload = predefined_filter ? {
|
|
13973
|
+
predefined_filter,
|
|
13974
|
+
filter_values,
|
|
13975
|
+
sort_values,
|
|
13976
|
+
...defaultOptions,
|
|
13977
|
+
...restOptions
|
|
13978
|
+
} : {
|
|
13818
13979
|
filter_conditions: filterConditions,
|
|
13819
13980
|
sort: normalizeQuerySort(sort),
|
|
13820
13981
|
...defaultOptions,
|
|
13821
|
-
...
|
|
13982
|
+
...restOptions
|
|
13822
13983
|
};
|
|
13823
13984
|
const data = await this.post(
|
|
13824
13985
|
this.baseURL + "/channels",
|
|
@@ -13930,6 +14091,7 @@ var StreamChat = class _StreamChat {
|
|
|
13930
14091
|
this.reminders.hydrateState(channelState.messages);
|
|
13931
14092
|
}
|
|
13932
14093
|
c.messageComposer.initStateFromChannelResponse(channelState);
|
|
14094
|
+
c.cooldownTimer.refresh();
|
|
13933
14095
|
channels.push(c);
|
|
13934
14096
|
}
|
|
13935
14097
|
this.syncDeliveredCandidates(channels);
|
|
@@ -14925,7 +15087,7 @@ var StreamChat = class _StreamChat {
|
|
|
14925
15087
|
if (this.userAgent) {
|
|
14926
15088
|
return this.userAgent;
|
|
14927
15089
|
}
|
|
14928
|
-
const version = "9.
|
|
15090
|
+
const version = "9.30.0";
|
|
14929
15091
|
const clientBundle = "browser-cjs";
|
|
14930
15092
|
let userAgentString = "";
|
|
14931
15093
|
if (this.sdkIdentifier) {
|
|
@@ -15241,7 +15403,7 @@ var StreamChat = class _StreamChat {
|
|
|
15241
15403
|
validateServerSideAuth() {
|
|
15242
15404
|
if (!this.secret) {
|
|
15243
15405
|
throw new Error(
|
|
15244
|
-
"
|
|
15406
|
+
"This feature can be used server-side only. Please initialize the client with a secret to use this feature."
|
|
15245
15407
|
);
|
|
15246
15408
|
}
|
|
15247
15409
|
}
|
|
@@ -16106,6 +16268,79 @@ var StreamChat = class _StreamChat {
|
|
|
16106
16268
|
payload
|
|
16107
16269
|
);
|
|
16108
16270
|
}
|
|
16271
|
+
/**
|
|
16272
|
+
* createPredefinedFilter - Creates a new predefined filter (server-side only)
|
|
16273
|
+
*
|
|
16274
|
+
* @param {CreatePredefinedFilterOptions} options Predefined filter options
|
|
16275
|
+
*
|
|
16276
|
+
* @return {Promise<PredefinedFilterResponse>} The created predefined filter
|
|
16277
|
+
*/
|
|
16278
|
+
async createPredefinedFilter(options) {
|
|
16279
|
+
this.validateServerSideAuth();
|
|
16280
|
+
return await this.post(
|
|
16281
|
+
`${this.baseURL}/predefined_filters`,
|
|
16282
|
+
options
|
|
16283
|
+
);
|
|
16284
|
+
}
|
|
16285
|
+
/**
|
|
16286
|
+
* getPredefinedFilter - Gets a predefined filter by name (server-side only)
|
|
16287
|
+
*
|
|
16288
|
+
* @param {string} name Predefined filter name
|
|
16289
|
+
*
|
|
16290
|
+
* @return {Promise<PredefinedFilterResponse>} The predefined filter
|
|
16291
|
+
*/
|
|
16292
|
+
async getPredefinedFilter(name) {
|
|
16293
|
+
this.validateServerSideAuth();
|
|
16294
|
+
return await this.get(
|
|
16295
|
+
`${this.baseURL}/predefined_filters/${encodeURIComponent(name)}`
|
|
16296
|
+
);
|
|
16297
|
+
}
|
|
16298
|
+
/**
|
|
16299
|
+
* updatePredefinedFilter - Updates a predefined filter (server-side only)
|
|
16300
|
+
*
|
|
16301
|
+
* @param {string} name Predefined filter name
|
|
16302
|
+
* @param {UpdatePredefinedFilterOptions} options Predefined filter options
|
|
16303
|
+
*
|
|
16304
|
+
* @return {Promise<PredefinedFilterResponse>} The updated predefined filter
|
|
16305
|
+
*/
|
|
16306
|
+
async updatePredefinedFilter(name, options) {
|
|
16307
|
+
this.validateServerSideAuth();
|
|
16308
|
+
return await this.put(
|
|
16309
|
+
`${this.baseURL}/predefined_filters/${encodeURIComponent(name)}`,
|
|
16310
|
+
options
|
|
16311
|
+
);
|
|
16312
|
+
}
|
|
16313
|
+
/**
|
|
16314
|
+
* deletePredefinedFilter - Deletes a predefined filter (server-side only)
|
|
16315
|
+
*
|
|
16316
|
+
* @param {string} name Predefined filter name
|
|
16317
|
+
*
|
|
16318
|
+
* @return {Promise<APIResponse>} The server response
|
|
16319
|
+
*/
|
|
16320
|
+
async deletePredefinedFilter(name) {
|
|
16321
|
+
this.validateServerSideAuth();
|
|
16322
|
+
return await this.delete(
|
|
16323
|
+
`${this.baseURL}/predefined_filters/${encodeURIComponent(name)}`
|
|
16324
|
+
);
|
|
16325
|
+
}
|
|
16326
|
+
/**
|
|
16327
|
+
* listPredefinedFilters - Lists all predefined filters (server-side only)
|
|
16328
|
+
*
|
|
16329
|
+
* @param {ListPredefinedFiltersOptions} options Query options
|
|
16330
|
+
*
|
|
16331
|
+
* @return {Promise<ListPredefinedFiltersResponse>} The list of predefined filters
|
|
16332
|
+
*/
|
|
16333
|
+
async listPredefinedFilters(options = {}) {
|
|
16334
|
+
this.validateServerSideAuth();
|
|
16335
|
+
const { sort, ...paginationOptions } = options;
|
|
16336
|
+
return await this.get(
|
|
16337
|
+
`${this.baseURL}/predefined_filters`,
|
|
16338
|
+
{
|
|
16339
|
+
...paginationOptions,
|
|
16340
|
+
...sort ? { sort: JSON.stringify(sort) } : {}
|
|
16341
|
+
}
|
|
16342
|
+
);
|
|
16343
|
+
}
|
|
16109
16344
|
};
|
|
16110
16345
|
|
|
16111
16346
|
// src/events.ts
|