stream-chat 10.0.0-rc.10 → 10.0.0-rc.11
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 +127 -78
- package/dist/cjs/index.browser.js.map +2 -2
- package/dist/cjs/index.node.js +127 -78
- package/dist/cjs/index.node.js.map +2 -2
- package/dist/esm/index.mjs +127 -78
- package/dist/esm/index.mjs.map +2 -2
- package/dist/types/ConnectionRecoveryManager.d.ts +1 -1
- package/dist/types/messageOperations/MessageOperations.d.ts +7 -0
- package/dist/types/notifications/NotificationManager.d.ts +10 -0
- package/dist/types/offline-support/offline_support_api.d.ts +20 -4
- package/dist/types/offline-support/offline_sync_manager.d.ts +2 -2
- package/dist/types/offline-support/types.d.ts +19 -2
- package/dist/types/pagination/paginators/ChannelPaginator.d.ts +12 -0
- package/dist/types/search/SearchController.d.ts +0 -9
- package/package.json +1 -1
- package/src/ConnectionRecoveryManager.ts +1 -1
- package/src/messageComposer/attachmentManager.ts +14 -4
- package/src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts +1 -1
- package/src/messageComposer/middleware/attachmentManager/preUpload/blockedUploadNotification.ts +1 -1
- package/src/messageOperations/MessageOperationStatePolicy.ts +9 -5
- package/src/messageOperations/MessageOperations.ts +21 -0
- package/src/notifications/NotificationManager.ts +15 -0
- package/src/offline-support/offline_support_api.ts +39 -73
- package/src/offline-support/offline_sync_manager.ts +3 -3
- package/src/offline-support/types.ts +20 -1
- package/src/pagination/paginators/ChannelPaginator.ts +46 -18
- package/src/search/SearchController.ts +0 -13
|
@@ -4125,6 +4125,19 @@ var NotificationManager = class {
|
|
|
4125
4125
|
}, duration);
|
|
4126
4126
|
this.timeouts.set(id, timeout);
|
|
4127
4127
|
}
|
|
4128
|
+
/**
|
|
4129
|
+
* Starts the notification's auto-dismiss countdown unless one is already running.
|
|
4130
|
+
*
|
|
4131
|
+
* The counterpart to {@link startTimeout}, which always restarts. Use this wherever the caller
|
|
4132
|
+
* cannot know whether the countdown has been started already -- a UI component that remounts and
|
|
4133
|
+
* has lost the record, or a second view displaying the same notification. Restarting there is
|
|
4134
|
+
* invisible and open-ended: each call hands the notification another full lifetime, so it can
|
|
4135
|
+
* outlive its duration indefinitely while looking like it is counting down.
|
|
4136
|
+
*/
|
|
4137
|
+
ensureTimeout(id, durationOverride) {
|
|
4138
|
+
if (this.timeouts.has(id)) return;
|
|
4139
|
+
this.startTimeout(id, durationOverride);
|
|
4140
|
+
}
|
|
4128
4141
|
remove(id) {
|
|
4129
4142
|
this.clearTimeout(id);
|
|
4130
4143
|
this.store.partialNext({
|
|
@@ -5921,7 +5934,7 @@ var createUploadErrorHandlerMiddleware = (composer) => ({
|
|
|
5921
5934
|
message: "Error uploading attachment",
|
|
5922
5935
|
origin: {
|
|
5923
5936
|
emitter: "AttachmentManager",
|
|
5924
|
-
context: { attachment }
|
|
5937
|
+
context: { attachment, composer }
|
|
5925
5938
|
},
|
|
5926
5939
|
options: {
|
|
5927
5940
|
type: CORE_NOTIFICATION_TYPE.attachmentUploadFailed,
|
|
@@ -5989,7 +6002,7 @@ var createBlockedAttachmentUploadNotificationMiddleware = (composer) => ({
|
|
|
5989
6002
|
message: `The attachment upload was blocked`,
|
|
5990
6003
|
origin: {
|
|
5991
6004
|
emitter: "AttachmentManager",
|
|
5992
|
-
context: { blockedAttachment: attachment }
|
|
6005
|
+
context: { blockedAttachment: attachment, composer }
|
|
5993
6006
|
},
|
|
5994
6007
|
options: {
|
|
5995
6008
|
type: CORE_NOTIFICATION_TYPE.attachmentUploadBlocked,
|
|
@@ -6195,7 +6208,10 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
6195
6208
|
if (!attachment.localMetadata?.file) {
|
|
6196
6209
|
this.client.notifications.addError({
|
|
6197
6210
|
message: "File is required for upload attachment",
|
|
6198
|
-
origin: {
|
|
6211
|
+
origin: {
|
|
6212
|
+
emitter: "AttachmentManager",
|
|
6213
|
+
context: { attachment, composer: this.composer }
|
|
6214
|
+
},
|
|
6199
6215
|
options: { type: CORE_NOTIFICATION_TYPE.attachmentFileMissing }
|
|
6200
6216
|
});
|
|
6201
6217
|
return;
|
|
@@ -6203,7 +6219,10 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
6203
6219
|
if (!attachment.localMetadata.id) {
|
|
6204
6220
|
this.client.notifications.addError({
|
|
6205
6221
|
message: "Local upload attachment missing local id",
|
|
6206
|
-
origin: {
|
|
6222
|
+
origin: {
|
|
6223
|
+
emitter: "AttachmentManager",
|
|
6224
|
+
context: { attachment, composer: this.composer }
|
|
6225
|
+
},
|
|
6207
6226
|
options: { type: CORE_NOTIFICATION_TYPE.attachmentIdMissing }
|
|
6208
6227
|
});
|
|
6209
6228
|
return;
|
|
@@ -6270,7 +6289,11 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
6270
6289
|
message: `The attachment upload was blocked`,
|
|
6271
6290
|
origin: {
|
|
6272
6291
|
emitter: "AttachmentManager",
|
|
6273
|
-
context: {
|
|
6292
|
+
context: {
|
|
6293
|
+
attachment,
|
|
6294
|
+
blockedAttachment: localAttachment,
|
|
6295
|
+
composer: this.composer
|
|
6296
|
+
}
|
|
6274
6297
|
},
|
|
6275
6298
|
options: {
|
|
6276
6299
|
type: CORE_NOTIFICATION_TYPE.attachmentUploadBlocked,
|
|
@@ -6298,7 +6321,7 @@ var _AttachmentManager = class _AttachmentManager {
|
|
|
6298
6321
|
message: "Error uploading attachment",
|
|
6299
6322
|
origin: {
|
|
6300
6323
|
emitter: "AttachmentManager",
|
|
6301
|
-
context: { attachment, failedAttachment }
|
|
6324
|
+
context: { attachment, failedAttachment, composer: this.composer }
|
|
6302
6325
|
},
|
|
6303
6326
|
options: {
|
|
6304
6327
|
type: CORE_NOTIFICATION_TYPE.attachmentUploadFailed,
|
|
@@ -7605,6 +7628,13 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7605
7628
|
retryCount: DEFAULT_QUERY_CHANNELS_RETRY_COUNT,
|
|
7606
7629
|
...paginatorOptions
|
|
7607
7630
|
});
|
|
7631
|
+
/**
|
|
7632
|
+
* True while the loaded items came ONLY from the offline cache - seeded by `setItems`, never
|
|
7633
|
+
* confirmed by a query. Such a state has no pagination position worth continuing from, so the seed
|
|
7634
|
+
* records `offset = <cache size>` and a query shape, which is what makes the next query look like a
|
|
7635
|
+
* continuation rather than a first page. See `executeQuery`.
|
|
7636
|
+
*/
|
|
7637
|
+
this._itemsLoadedFromOfflineDB = false;
|
|
7608
7638
|
/**
|
|
7609
7639
|
* Filters sent to the server with the next query (and used as the offline-db query key). Deliberately
|
|
7610
7640
|
* built from the locally configured filters only — feeding the backend-resolved filter back in would
|
|
@@ -7629,12 +7659,15 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7629
7659
|
return void 0;
|
|
7630
7660
|
const { stateOptions: _, ...request } = queryShape;
|
|
7631
7661
|
try {
|
|
7632
|
-
const
|
|
7662
|
+
const cachedQuery = await this.client.offlineDb.getChannelsForQuery({
|
|
7633
7663
|
userId: this.client.user.id,
|
|
7634
7664
|
options: request
|
|
7635
7665
|
});
|
|
7636
|
-
if (
|
|
7637
|
-
|
|
7666
|
+
if (cachedQuery) {
|
|
7667
|
+
if (cachedQuery.predefinedFilter) {
|
|
7668
|
+
this.applyPredefinedFilterResponse(cachedQuery.predefinedFilter);
|
|
7669
|
+
}
|
|
7670
|
+
return this.client.hydrateActiveChannels(cachedQuery.channels, {
|
|
7638
7671
|
offlineMode: true,
|
|
7639
7672
|
skipInitialization: []
|
|
7640
7673
|
// passing empty array will clear out the existing messages from channel state, this removes the possibility of duplicate messages
|
|
@@ -7658,6 +7691,7 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7658
7691
|
});
|
|
7659
7692
|
};
|
|
7660
7693
|
this.query = async () => {
|
|
7694
|
+
this._itemsLoadedFromOfflineDB = false;
|
|
7661
7695
|
if (!this._nextQueryShape) {
|
|
7662
7696
|
this._nextQueryShape = this.getNextQueryShape();
|
|
7663
7697
|
}
|
|
@@ -7676,7 +7710,7 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7676
7710
|
return { items };
|
|
7677
7711
|
};
|
|
7678
7712
|
this.filterQueryResults = (items) => items;
|
|
7679
|
-
const definedSort = sort
|
|
7713
|
+
const definedSort = sort?.length ? sort : DEFAULT_BACKEND_SORT2;
|
|
7680
7714
|
this.client = client;
|
|
7681
7715
|
this._id = id ?? `channel-paginator-${generateUUIDv4()}`;
|
|
7682
7716
|
this._sort = definedSort;
|
|
@@ -7732,7 +7766,7 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7732
7766
|
return this._staticFilters;
|
|
7733
7767
|
}
|
|
7734
7768
|
get sort() {
|
|
7735
|
-
return this._sort
|
|
7769
|
+
return this._sort?.length ? this._sort : DEFAULT_BACKEND_SORT2;
|
|
7736
7770
|
}
|
|
7737
7771
|
/**
|
|
7738
7772
|
* What the backend reported it actually filtered and sorted by for the last first-page query —
|
|
@@ -7856,6 +7890,11 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7856
7890
|
* `predefined_filter` / `filter_values` / `sort_values` appear, without which two predefined-filter
|
|
7857
7891
|
* lists cannot be told apart. The duplication goes away once `convertFilterSortToQuery` derives the
|
|
7858
7892
|
* key from `options` (a change in that implementation plus a schema-version bump to flush stale rows).
|
|
7893
|
+
*
|
|
7894
|
+
* The resolved `predefinedFilter` rides along with the order it produced: a cache-seeded list has no
|
|
7895
|
+
* response to learn it from, and without it `effectiveFilters` / `effectiveSort` fall back to the
|
|
7896
|
+
* local filters and the default sort - i.e. it would match and order by a different rule than the
|
|
7897
|
+
* one the cached order came from.
|
|
7859
7898
|
*/
|
|
7860
7899
|
cacheCidsForQuery({
|
|
7861
7900
|
cids,
|
|
@@ -7866,6 +7905,7 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7866
7905
|
cids,
|
|
7867
7906
|
filters: request.filter_conditions,
|
|
7868
7907
|
options: request,
|
|
7908
|
+
predefinedFilter: this._predefinedFilter,
|
|
7869
7909
|
sort: request.sort
|
|
7870
7910
|
}),
|
|
7871
7911
|
{ method: "upsertCidsForQuery" }
|
|
@@ -7895,24 +7935,32 @@ var ChannelPaginator = class extends BasePaginator {
|
|
|
7895
7935
|
*/
|
|
7896
7936
|
async executeQuery(params = {}) {
|
|
7897
7937
|
const { offlineDb } = this.client;
|
|
7898
|
-
const
|
|
7899
|
-
const
|
|
7900
|
-
|
|
7938
|
+
const effectiveParams = this._itemsLoadedFromOfflineDB && params.reset !== "yes" ? { ...params, keepPreviousItems: true, reset: "yes" } : params;
|
|
7939
|
+
const queryShape = effectiveParams.queryShape ?? this.getNextQueryShape();
|
|
7940
|
+
const shouldDeferUntilSynced = !!offlineDb?.getChannelsForQuery && !!this.client.user?.id && !offlineDb.syncManager.isSynced && // Items seeded from the cache are not an already loaded list, so paginating them has to defer too.
|
|
7941
|
+
(this._itemsLoadedFromOfflineDB || this.isFirstPageQuery({ queryShape, reset: effectiveParams.reset }));
|
|
7942
|
+
if (!shouldDeferUntilSynced) return await super.executeQuery(effectiveParams);
|
|
7901
7943
|
if (!this.isInitialized) {
|
|
7902
7944
|
const cachedChannels = await this.preloadFirstPageFromOfflineDb({
|
|
7903
|
-
...
|
|
7945
|
+
...effectiveParams,
|
|
7904
7946
|
queryShape
|
|
7905
7947
|
});
|
|
7906
7948
|
if (cachedChannels?.length) {
|
|
7907
7949
|
this.setItems({ valueOrFactory: cachedChannels, isFirstPage: true });
|
|
7950
|
+
this._itemsLoadedFromOfflineDB = true;
|
|
7908
7951
|
}
|
|
7909
7952
|
this.state.partialNext({ isLoading: false });
|
|
7910
7953
|
}
|
|
7911
|
-
|
|
7912
|
-
|
|
7954
|
+
const refreshParams = {
|
|
7955
|
+
...effectiveParams,
|
|
7956
|
+
keepPreviousItems: true,
|
|
7957
|
+
...this._itemsLoadedFromOfflineDB ? { reset: "yes" } : {}
|
|
7958
|
+
};
|
|
7959
|
+
if (offlineDb.syncManager.isSynced) {
|
|
7960
|
+
return await super.executeQuery(refreshParams);
|
|
7913
7961
|
}
|
|
7914
7962
|
offlineDb.syncManager.scheduleSyncStatusChangeCallback(this.id, async () => {
|
|
7915
|
-
await this.executeQuery(
|
|
7963
|
+
await this.executeQuery(refreshParams);
|
|
7916
7964
|
});
|
|
7917
7965
|
}
|
|
7918
7966
|
setItems(params) {
|
|
@@ -8671,7 +8719,6 @@ var SearchController = class {
|
|
|
8671
8719
|
searchQuery: "",
|
|
8672
8720
|
sources: sources ?? []
|
|
8673
8721
|
});
|
|
8674
|
-
this._internalState = new import_state_store12.StateStore({});
|
|
8675
8722
|
this.configController = new ConfigController({
|
|
8676
8723
|
defaults: DEFAULT_SEARCH_CONTROLLER_CONFIG,
|
|
8677
8724
|
constructorOptions: config
|
|
@@ -11500,9 +11547,10 @@ var MessageOperationStatePolicy = class {
|
|
|
11500
11547
|
}
|
|
11501
11548
|
return;
|
|
11502
11549
|
}
|
|
11503
|
-
const queued = kind !== "send" && kind !== "retry" && await this.ctx.isQueued(
|
|
11504
|
-
|
|
11505
|
-
|
|
11550
|
+
const queued = kind !== "send" && kind !== "retry" && await this.ctx.isQueued(
|
|
11551
|
+
messageId,
|
|
11552
|
+
kind === "delete" ? ["delete-message"] : ["update-message", "send-message"]
|
|
11553
|
+
);
|
|
11506
11554
|
if (kind === "delete") {
|
|
11507
11555
|
if (!queued) this.revertDelete({ messageId, optimistic, options });
|
|
11508
11556
|
return;
|
|
@@ -11630,6 +11678,23 @@ var MessageOperations = class {
|
|
|
11630
11678
|
clearCachedFailedSend(messageId) {
|
|
11631
11679
|
this.failedSendCache.delete(messageId);
|
|
11632
11680
|
}
|
|
11681
|
+
/**
|
|
11682
|
+
* Folds an edit into the payload cached for this message's failed send, so `retry` resends what the
|
|
11683
|
+
* message contains now rather than what it contained when the send failed.
|
|
11684
|
+
*
|
|
11685
|
+
* This exists so a retry while offline for example is also persisted, rather than just disappearing.
|
|
11686
|
+
*/
|
|
11687
|
+
rewriteCachedFailedSend(localMessage) {
|
|
11688
|
+
const cached = this.getCachedFailedSend(localMessage.id);
|
|
11689
|
+
if (!cached) return;
|
|
11690
|
+
this.failedSendCache.set(localMessage.id, {
|
|
11691
|
+
...cached,
|
|
11692
|
+
message: {
|
|
11693
|
+
...cached.message,
|
|
11694
|
+
...localMessageToNewMessagePayload(localMessage)
|
|
11695
|
+
}
|
|
11696
|
+
});
|
|
11697
|
+
}
|
|
11633
11698
|
/**
|
|
11634
11699
|
* The shared lifecycle: apply the optimistic state, fire the request, then reconcile or record the
|
|
11635
11700
|
* failure. `kind` is threaded through because the three operations want materially different state
|
|
@@ -11710,6 +11775,7 @@ var MessageOperations = class {
|
|
|
11710
11775
|
}
|
|
11711
11776
|
}
|
|
11712
11777
|
async update(params, requestFn) {
|
|
11778
|
+
this.rewriteCachedFailedSend(params.localMessage);
|
|
11713
11779
|
const handlers = this.ctx.handlers();
|
|
11714
11780
|
let updateOptions;
|
|
11715
11781
|
if (params.options) {
|
|
@@ -23200,7 +23266,7 @@ var StreamChat = class _StreamChat extends ChatApi {
|
|
|
23200
23266
|
return this.userAgent;
|
|
23201
23267
|
}
|
|
23202
23268
|
if (!this.cachedUserAgent) {
|
|
23203
|
-
const version = "10.0.0-rc.
|
|
23269
|
+
const version = "10.0.0-rc.11";
|
|
23204
23270
|
const { name: sdkName, version: sdkVersion } = this.sdkIdentifier ?? {};
|
|
23205
23271
|
const { name: appName, version: appVersion } = this.appIdentifier ?? {};
|
|
23206
23272
|
const { os, model: deviceModel } = this.deviceIdentifier ?? {};
|
|
@@ -24875,7 +24941,7 @@ var OfflineDBSyncManager = class {
|
|
|
24875
24941
|
offlineDb,
|
|
24876
24942
|
syncMaxEventCount
|
|
24877
24943
|
}) {
|
|
24878
|
-
this.
|
|
24944
|
+
this.isSynced = false;
|
|
24879
24945
|
this.connectionChangedListener = null;
|
|
24880
24946
|
this.syncStatusListeners = [];
|
|
24881
24947
|
this.scheduledSyncStatusCallbacks = /* @__PURE__ */ new Map();
|
|
@@ -24940,7 +25006,7 @@ var OfflineDBSyncManager = class {
|
|
|
24940
25006
|
* @param status - The new sync status (`true` or `false`).
|
|
24941
25007
|
*/
|
|
24942
25008
|
this.invokeSyncStatusListeners = async (status) => {
|
|
24943
|
-
this.
|
|
25009
|
+
this.isSynced = status;
|
|
24944
25010
|
this.syncStatusListeners.forEach((l) => {
|
|
24945
25011
|
try {
|
|
24946
25012
|
l(status);
|
|
@@ -25033,7 +25099,7 @@ var OfflineDBSyncManager = class {
|
|
|
25033
25099
|
* Each step is isolated so a failure in one does not prevent the other, and
|
|
25034
25100
|
* neither can escape to the callers (init + the connection.changed handler).
|
|
25035
25101
|
* This guarantees the subsequent invokeSyncStatusListeners(true) always runs,
|
|
25036
|
-
* so
|
|
25102
|
+
* so isSynced recovers to true and gated channel queries are unblocked.
|
|
25037
25103
|
* Failed syncs degrade to "possibly stale data until the next query" rather
|
|
25038
25104
|
* than freezing all future queries. See issue #1816.
|
|
25039
25105
|
*/
|
|
@@ -25786,69 +25852,52 @@ var AbstractOfflineDB = class {
|
|
|
25786
25852
|
* @param error - The error thrown while executing the failed task.
|
|
25787
25853
|
*/
|
|
25788
25854
|
this.shouldSkipQueueingTask = (error) => !isEphemeral(error);
|
|
25789
|
-
this.mergeFailedMessageUpdateIntoPendingSendMessage = ({
|
|
25790
|
-
editedMessage,
|
|
25791
|
-
pendingMessage
|
|
25792
|
-
}) => {
|
|
25793
|
-
const normalizedEditedMessage = localMessageToNewMessagePayload(
|
|
25794
|
-
editedMessage
|
|
25795
|
-
);
|
|
25796
|
-
const pendingMessageStatus = pendingMessage.status;
|
|
25797
|
-
return {
|
|
25798
|
-
...pendingMessage,
|
|
25799
|
-
...normalizedEditedMessage,
|
|
25800
|
-
...typeof pendingMessageStatus !== "undefined" ? { status: pendingMessageStatus } : {}
|
|
25801
|
-
};
|
|
25802
|
-
};
|
|
25803
25855
|
this.isPendingSendMessageTask = (task) => task.type === "send-message";
|
|
25804
|
-
|
|
25856
|
+
/**
|
|
25857
|
+
* Folds an edit of a message the server has never seen into that message's queued `send-message`
|
|
25858
|
+
* task, so a replay sends the edited text once instead of sending the original and then editing it.
|
|
25859
|
+
* The send task keeps its row, and with it its place in the queue, which is what keeps the edited
|
|
25860
|
+
* message ordered against everything queued after it.
|
|
25861
|
+
*
|
|
25862
|
+
* Keyed on a queued `send-message` task existing for this id - the only reliable statement of "the
|
|
25863
|
+
* server has never seen this message". NOT on the edited message's status: both payloads are built
|
|
25864
|
+
* by `localMessageToNewMessagePayload`, which strips `status` along with every other client-only
|
|
25865
|
+
* field, so nothing arriving here carries one.
|
|
25866
|
+
*
|
|
25867
|
+
* That same normalization is why the two merge by a plain spread: both are already `MessageRequest`s,
|
|
25868
|
+
* and normalizing again would map an already-flattened `mentioned_users` back over itself as
|
|
25869
|
+
* `[undefined]`.
|
|
25870
|
+
*
|
|
25871
|
+
* With nothing to fold into, the edit is queued on its own and replays as an ordinary update.
|
|
25872
|
+
*/
|
|
25873
|
+
this.handleUpdateMessagePendingTask = async (task) => {
|
|
25805
25874
|
const [{ id, message }] = task.payload;
|
|
25806
|
-
if (!id) {
|
|
25807
|
-
return;
|
|
25808
|
-
}
|
|
25809
25875
|
const pendingTasks = await this.getPendingTasks({ messageId: id });
|
|
25810
|
-
const
|
|
25811
|
-
if (
|
|
25876
|
+
const sendTask = pendingTasks.find(this.isPendingSendMessageTask);
|
|
25877
|
+
if (sendTask?.id === void 0) {
|
|
25878
|
+
if (!isMessageUpdateReplayable(message)) return;
|
|
25879
|
+
await this.addPendingTask(task);
|
|
25812
25880
|
return;
|
|
25813
25881
|
}
|
|
25814
|
-
const
|
|
25815
|
-
|
|
25816
|
-
|
|
25817
|
-
|
|
25818
|
-
|
|
25882
|
+
const [sendRequest, ...sendRequestOptions] = sendTask.payload;
|
|
25883
|
+
await this.updatePendingTask({
|
|
25884
|
+
id: sendTask.id,
|
|
25885
|
+
task: {
|
|
25886
|
+
...sendTask,
|
|
25887
|
+
payload: [
|
|
25888
|
+
{ ...sendRequest, message: { ...sendRequest.message, ...message } },
|
|
25889
|
+
...sendRequestOptions
|
|
25890
|
+
]
|
|
25819
25891
|
}
|
|
25820
|
-
);
|
|
25821
|
-
const updatedPendingTask = {
|
|
25822
|
-
...pendingSendMessageTask,
|
|
25823
|
-
payload: [
|
|
25824
|
-
{
|
|
25825
|
-
...pendingSendMessageTask.payload[0],
|
|
25826
|
-
message: updatedPendingSendMessage
|
|
25827
|
-
}
|
|
25828
|
-
]
|
|
25829
|
-
};
|
|
25830
|
-
if (pendingSendMessageTask.id) {
|
|
25831
|
-
await this.updatePendingTask({
|
|
25832
|
-
id: pendingSendMessageTask.id,
|
|
25833
|
-
task: updatedPendingTask
|
|
25834
|
-
});
|
|
25835
|
-
return;
|
|
25836
|
-
}
|
|
25837
|
-
await this.addPendingTask({
|
|
25838
|
-
...updatedPendingTask,
|
|
25839
|
-
id: void 0
|
|
25840
25892
|
});
|
|
25841
25893
|
};
|
|
25842
25894
|
/**
|
|
25843
|
-
* Central ingress for persisting pending tasks. It either stores the task as-is
|
|
25844
|
-
*
|
|
25895
|
+
* Central ingress for persisting pending tasks. It either stores the task as-is or folds an edit of
|
|
25896
|
+
* a message that has not been sent yet into that message's queued `send-message` task.
|
|
25845
25897
|
*/
|
|
25846
25898
|
this.handleAddPendingTask = async ({ task }) => {
|
|
25847
|
-
if (task.type === "update-message"
|
|
25848
|
-
|
|
25849
|
-
}
|
|
25850
|
-
if (task.type === "update-message" && !this.client.wsConnection?.isHealthy && task.payload[0].message?.status === "failed") {
|
|
25851
|
-
await this.handleOfflineFailedUpdateMessagePendingTask(task);
|
|
25899
|
+
if (task.type === "update-message") {
|
|
25900
|
+
await this.handleUpdateMessagePendingTask(task);
|
|
25852
25901
|
return;
|
|
25853
25902
|
}
|
|
25854
25903
|
await this.addPendingTask(task);
|