stream-chat 9.6.1 → 9.7.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.cjs +357 -50
- package/dist/cjs/index.browser.cjs.map +3 -3
- package/dist/cjs/index.node.cjs +358 -50
- package/dist/cjs/index.node.cjs.map +3 -3
- package/dist/esm/index.js +357 -50
- package/dist/esm/index.js.map +3 -3
- package/dist/types/channel.d.ts +36 -4
- package/dist/types/client.d.ts +38 -0
- package/dist/types/messageComposer/messageComposer.d.ts +4 -1
- package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +5 -5
- package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +1 -2
- package/dist/types/messageComposer/middleware/textComposer/types.d.ts +2 -2
- package/dist/types/offline-support/offline_support_api.d.ts +39 -0
- package/dist/types/offline-support/types.d.ts +36 -2
- package/dist/types/search/BaseSearchSource.d.ts +37 -31
- package/dist/types/search/ChannelSearchSource.d.ts +1 -1
- package/dist/types/search/MessageSearchSource.d.ts +1 -1
- package/dist/types/search/UserSearchSource.d.ts +1 -1
- package/dist/types/search/index.d.ts +1 -0
- package/dist/types/search/types.d.ts +20 -0
- package/dist/types/types.d.ts +5 -1
- package/dist/types/utils.d.ts +11 -2
- package/package.json +1 -1
- package/src/channel.ts +85 -10
- package/src/client.ts +61 -3
- package/src/messageComposer/messageComposer.ts +120 -14
- package/src/messageComposer/middleware/textComposer/commands.ts +6 -7
- package/src/messageComposer/middleware/textComposer/mentions.ts +1 -2
- package/src/messageComposer/middleware/textComposer/types.ts +2 -2
- package/src/offline-support/offline_support_api.ts +79 -0
- package/src/offline-support/types.ts +41 -1
- package/src/search/BaseSearchSource.ts +123 -52
- package/src/search/ChannelSearchSource.ts +1 -1
- package/src/search/MessageSearchSource.ts +1 -1
- package/src/search/UserSearchSource.ts +1 -1
- package/src/search/index.ts +1 -0
- package/src/search/types.ts +20 -0
- package/src/types.ts +8 -1
- package/src/utils.ts +31 -2
|
@@ -161,6 +161,7 @@ __export(index_exports, {
|
|
|
161
161
|
AttachmentManager: () => AttachmentManager,
|
|
162
162
|
BasePaginator: () => BasePaginator,
|
|
163
163
|
BaseSearchSource: () => BaseSearchSource,
|
|
164
|
+
BaseSearchSourceSync: () => BaseSearchSourceSync,
|
|
164
165
|
BuiltinPermissions: () => BuiltinPermissions,
|
|
165
166
|
BuiltinRoles: () => BuiltinRoles,
|
|
166
167
|
Campaign: () => Campaign,
|
|
@@ -2757,6 +2758,23 @@ function formatMessage(message) {
|
|
|
2757
2758
|
quoted_message: toLocalMessageBase(message.quoted_message)
|
|
2758
2759
|
};
|
|
2759
2760
|
}
|
|
2761
|
+
function unformatMessage(message) {
|
|
2762
|
+
const toMessageResponseBase = (msg) => {
|
|
2763
|
+
if (!msg) return null;
|
|
2764
|
+
const newDateString = (/* @__PURE__ */ new Date()).toISOString();
|
|
2765
|
+
return {
|
|
2766
|
+
...msg,
|
|
2767
|
+
created_at: message.created_at ? message.created_at.toISOString() : newDateString,
|
|
2768
|
+
deleted_at: message.deleted_at ? message.deleted_at.toISOString() : void 0,
|
|
2769
|
+
pinned_at: message.pinned_at ? message.pinned_at.toISOString() : void 0,
|
|
2770
|
+
updated_at: message.updated_at ? message.updated_at.toISOString() : newDateString
|
|
2771
|
+
};
|
|
2772
|
+
};
|
|
2773
|
+
return {
|
|
2774
|
+
...toMessageResponseBase(message),
|
|
2775
|
+
quoted_message: toMessageResponseBase(message.quoted_message)
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2760
2778
|
var localMessageToNewMessagePayload = (localMessage) => {
|
|
2761
2779
|
const {
|
|
2762
2780
|
// Remove all timestamp fields and client-specific fields.
|
|
@@ -6296,11 +6314,8 @@ var DEFAULT_SEARCH_SOURCE_OPTIONS = {
|
|
|
6296
6314
|
debounceMs: 300,
|
|
6297
6315
|
pageSize: 10
|
|
6298
6316
|
};
|
|
6299
|
-
var
|
|
6317
|
+
var BaseSearchSourceBase = class {
|
|
6300
6318
|
constructor(options) {
|
|
6301
|
-
this.setDebounceOptions = ({ debounceMs }) => {
|
|
6302
|
-
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
6303
|
-
};
|
|
6304
6319
|
this.activate = () => {
|
|
6305
6320
|
if (this.isActive) return;
|
|
6306
6321
|
this.state.partialNext({ isActive: true });
|
|
@@ -6314,11 +6329,9 @@ var BaseSearchSource = class {
|
|
|
6314
6329
|
const searchString = newSearchString ?? this.searchQuery;
|
|
6315
6330
|
return !!(this.isActive && !this.isLoading && (this.hasNext || hasNewSearchQuery) && searchString);
|
|
6316
6331
|
};
|
|
6317
|
-
|
|
6318
|
-
const { debounceMs, pageSize } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
6332
|
+
const { pageSize } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
6319
6333
|
this.pageSize = pageSize;
|
|
6320
6334
|
this.state = new StateStore(this.initialState);
|
|
6321
|
-
this.setDebounceOptions({ debounceMs });
|
|
6322
6335
|
}
|
|
6323
6336
|
get lastQueryError() {
|
|
6324
6337
|
return this.state.getLatestValue().lastQueryError;
|
|
@@ -6378,8 +6391,7 @@ var BaseSearchSource = class {
|
|
|
6378
6391
|
items: isFirstPage ? stateUpdate.items : [...this.items ?? [], ...stateUpdate.items || []]
|
|
6379
6392
|
};
|
|
6380
6393
|
}
|
|
6381
|
-
|
|
6382
|
-
if (!this.canExecuteQuery(newSearchString)) return;
|
|
6394
|
+
prepareStateForQuery(newSearchString) {
|
|
6383
6395
|
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
6384
6396
|
const searchString = newSearchString ?? this.searchQuery;
|
|
6385
6397
|
if (hasNewSearchQuery) {
|
|
@@ -6387,18 +6399,47 @@ var BaseSearchSource = class {
|
|
|
6387
6399
|
} else {
|
|
6388
6400
|
this.state.partialNext({ isLoading: true });
|
|
6389
6401
|
}
|
|
6402
|
+
return { searchString, hasNewSearchQuery };
|
|
6403
|
+
}
|
|
6404
|
+
updatePaginationStateFromQuery(result) {
|
|
6405
|
+
const { items, next } = result;
|
|
6390
6406
|
const stateUpdate = {};
|
|
6407
|
+
if (next || next === null) {
|
|
6408
|
+
stateUpdate.next = next;
|
|
6409
|
+
stateUpdate.hasNext = !!next;
|
|
6410
|
+
} else {
|
|
6411
|
+
stateUpdate.offset = (this.offset ?? 0) + items.length;
|
|
6412
|
+
stateUpdate.hasNext = items.length === this.pageSize;
|
|
6413
|
+
}
|
|
6414
|
+
return stateUpdate;
|
|
6415
|
+
}
|
|
6416
|
+
resetState() {
|
|
6417
|
+
this.state.next(this.initialState);
|
|
6418
|
+
}
|
|
6419
|
+
resetStateAndActivate() {
|
|
6420
|
+
this.resetState();
|
|
6421
|
+
this.activate();
|
|
6422
|
+
}
|
|
6423
|
+
};
|
|
6424
|
+
var BaseSearchSource = class extends BaseSearchSourceBase {
|
|
6425
|
+
constructor(options) {
|
|
6426
|
+
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
6427
|
+
super(options);
|
|
6428
|
+
this.setDebounceOptions = ({ debounceMs }) => {
|
|
6429
|
+
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
6430
|
+
};
|
|
6431
|
+
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
6432
|
+
this.setDebounceOptions({ debounceMs });
|
|
6433
|
+
}
|
|
6434
|
+
async executeQuery(newSearchString) {
|
|
6435
|
+
if (!this.canExecuteQuery(newSearchString)) return;
|
|
6436
|
+
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
6437
|
+
let stateUpdate = {};
|
|
6391
6438
|
try {
|
|
6392
6439
|
const results = await this.query(searchString);
|
|
6393
6440
|
if (!results) return;
|
|
6394
|
-
const { items
|
|
6395
|
-
|
|
6396
|
-
stateUpdate.next = next;
|
|
6397
|
-
stateUpdate.hasNext = !!next;
|
|
6398
|
-
} else {
|
|
6399
|
-
stateUpdate.offset = (this.offset ?? 0) + items.length;
|
|
6400
|
-
stateUpdate.hasNext = items.length === this.pageSize;
|
|
6401
|
-
}
|
|
6441
|
+
const { items } = results;
|
|
6442
|
+
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
6402
6443
|
stateUpdate.items = await this.filterQueryResults(items);
|
|
6403
6444
|
} catch (e) {
|
|
6404
6445
|
stateUpdate.lastQueryError = e;
|
|
@@ -6409,12 +6450,35 @@ var BaseSearchSource = class {
|
|
|
6409
6450
|
cancelScheduledQuery() {
|
|
6410
6451
|
this.searchDebounced.cancel();
|
|
6411
6452
|
}
|
|
6412
|
-
|
|
6413
|
-
|
|
6453
|
+
};
|
|
6454
|
+
var BaseSearchSourceSync = class extends BaseSearchSourceBase {
|
|
6455
|
+
constructor(options) {
|
|
6456
|
+
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
6457
|
+
super(options);
|
|
6458
|
+
this.setDebounceOptions = ({ debounceMs }) => {
|
|
6459
|
+
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
6460
|
+
};
|
|
6461
|
+
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
6462
|
+
this.setDebounceOptions({ debounceMs });
|
|
6414
6463
|
}
|
|
6415
|
-
|
|
6416
|
-
this.
|
|
6417
|
-
this.
|
|
6464
|
+
executeQuery(newSearchString) {
|
|
6465
|
+
if (!this.canExecuteQuery(newSearchString)) return;
|
|
6466
|
+
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
6467
|
+
let stateUpdate = {};
|
|
6468
|
+
try {
|
|
6469
|
+
const results = this.query(searchString);
|
|
6470
|
+
if (!results) return;
|
|
6471
|
+
const { items } = results;
|
|
6472
|
+
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
6473
|
+
stateUpdate.items = this.filterQueryResults(items);
|
|
6474
|
+
} catch (e) {
|
|
6475
|
+
stateUpdate.lastQueryError = e;
|
|
6476
|
+
} finally {
|
|
6477
|
+
this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
cancelScheduledQuery() {
|
|
6481
|
+
this.searchDebounced.cancel();
|
|
6418
6482
|
}
|
|
6419
6483
|
};
|
|
6420
6484
|
|
|
@@ -6697,7 +6761,7 @@ var getTokenizedSuggestionDisplayName = ({
|
|
|
6697
6761
|
});
|
|
6698
6762
|
|
|
6699
6763
|
// src/messageComposer/middleware/textComposer/commands.ts
|
|
6700
|
-
var CommandSearchSource = class extends
|
|
6764
|
+
var CommandSearchSource = class extends BaseSearchSourceSync {
|
|
6701
6765
|
constructor(channel, options) {
|
|
6702
6766
|
super(options);
|
|
6703
6767
|
this.type = "commands";
|
|
@@ -6741,10 +6805,10 @@ var CommandSearchSource = class extends BaseSearchSource {
|
|
|
6741
6805
|
}
|
|
6742
6806
|
return 0;
|
|
6743
6807
|
});
|
|
6744
|
-
return
|
|
6808
|
+
return {
|
|
6745
6809
|
items: selectedCommands.map((c) => ({ ...c, id: c.name })),
|
|
6746
6810
|
next: null
|
|
6747
|
-
}
|
|
6811
|
+
};
|
|
6748
6812
|
}
|
|
6749
6813
|
filterQueryResults(items) {
|
|
6750
6814
|
return items;
|
|
@@ -7902,7 +7966,33 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7902
7966
|
this.editedMessage = message;
|
|
7903
7967
|
}
|
|
7904
7968
|
};
|
|
7969
|
+
this.initStateFromChannelResponse = (channelApiResponse) => {
|
|
7970
|
+
if (this.channel.cid !== channelApiResponse.channel.cid) {
|
|
7971
|
+
return;
|
|
7972
|
+
}
|
|
7973
|
+
if (channelApiResponse.draft) {
|
|
7974
|
+
this.initState({ composition: channelApiResponse.draft });
|
|
7975
|
+
} else if (this.state.getLatestValue().draftId) {
|
|
7976
|
+
this.clear();
|
|
7977
|
+
this.client.offlineDb?.executeQuerySafely(
|
|
7978
|
+
(db) => db.deleteDraft({
|
|
7979
|
+
cid: this.channel.cid,
|
|
7980
|
+
parent_id: void 0
|
|
7981
|
+
// makes sure that we don't delete thread drafts while upserting channels
|
|
7982
|
+
}),
|
|
7983
|
+
{ method: "deleteDraft" }
|
|
7984
|
+
);
|
|
7985
|
+
}
|
|
7986
|
+
};
|
|
7905
7987
|
this.initEditingAuditState = (composition) => initEditingAuditState(composition);
|
|
7988
|
+
this.registerDraftEventSubscriptions = () => {
|
|
7989
|
+
const unsubscribeDraftUpdated = this.subscribeDraftUpdated();
|
|
7990
|
+
const unsubscribeDraftDeleted = this.subscribeDraftDeleted();
|
|
7991
|
+
return () => {
|
|
7992
|
+
unsubscribeDraftUpdated();
|
|
7993
|
+
unsubscribeDraftDeleted();
|
|
7994
|
+
};
|
|
7995
|
+
};
|
|
7906
7996
|
this.registerSubscriptions = () => {
|
|
7907
7997
|
if (!this.hasSubscriptions) {
|
|
7908
7998
|
this.addUnsubscribeFunction(this.subscribeMessageComposerSetupStateChange());
|
|
@@ -7967,13 +8057,13 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7967
8057
|
}).unsubscribe;
|
|
7968
8058
|
this.subscribeDraftUpdated = () => this.client.on("draft.updated", (event) => {
|
|
7969
8059
|
const draft = event.draft;
|
|
7970
|
-
if (!draft ||
|
|
8060
|
+
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid)
|
|
7971
8061
|
return;
|
|
7972
8062
|
this.initState({ composition: draft });
|
|
7973
8063
|
}).unsubscribe;
|
|
7974
8064
|
this.subscribeDraftDeleted = () => this.client.on("draft.deleted", (event) => {
|
|
7975
8065
|
const draft = event.draft;
|
|
7976
|
-
if (!draft ||
|
|
8066
|
+
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid) {
|
|
7977
8067
|
return;
|
|
7978
8068
|
}
|
|
7979
8069
|
this.logDraftUpdateTimestamp();
|
|
@@ -8037,7 +8127,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8037
8127
|
}
|
|
8038
8128
|
});
|
|
8039
8129
|
this.subscribeMessageComposerConfigStateChanged = () => {
|
|
8040
|
-
let
|
|
8130
|
+
let draftUnsubscribeFunction;
|
|
8041
8131
|
const unsubscribe = this.configState.subscribeWithSelector(
|
|
8042
8132
|
(currentValue) => ({
|
|
8043
8133
|
textDefaultValue: currentValue.text.defaultValue,
|
|
@@ -8050,19 +8140,16 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8050
8140
|
selection: { start: 0, end: 0 }
|
|
8051
8141
|
});
|
|
8052
8142
|
}
|
|
8053
|
-
if (draftsEnabled && !
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
} else if (!draftsEnabled && draftUnsubscribeFunctions) {
|
|
8059
|
-
draftUnsubscribeFunctions.forEach((fn) => fn());
|
|
8060
|
-
draftUnsubscribeFunctions = null;
|
|
8143
|
+
if (draftsEnabled && !draftUnsubscribeFunction) {
|
|
8144
|
+
draftUnsubscribeFunction = this.registerDraftEventSubscriptions();
|
|
8145
|
+
} else if (!draftsEnabled && draftUnsubscribeFunction) {
|
|
8146
|
+
draftUnsubscribeFunction();
|
|
8147
|
+
draftUnsubscribeFunction = null;
|
|
8061
8148
|
}
|
|
8062
8149
|
}
|
|
8063
8150
|
);
|
|
8064
8151
|
return () => {
|
|
8065
|
-
|
|
8152
|
+
draftUnsubscribeFunction?.();
|
|
8066
8153
|
unsubscribe();
|
|
8067
8154
|
};
|
|
8068
8155
|
};
|
|
@@ -8132,14 +8219,78 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8132
8219
|
if (!composition) return;
|
|
8133
8220
|
const { draft } = composition;
|
|
8134
8221
|
this.state.partialNext({ draftId: draft.id });
|
|
8222
|
+
if (this.client.offlineDb) {
|
|
8223
|
+
try {
|
|
8224
|
+
const optimisticDraftResponse = {
|
|
8225
|
+
channel_cid: this.channel.cid,
|
|
8226
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8227
|
+
message: draft,
|
|
8228
|
+
parent_id: draft.parent_id,
|
|
8229
|
+
quoted_message: this.quotedMessage ? unformatMessage(this.quotedMessage) : void 0
|
|
8230
|
+
};
|
|
8231
|
+
await this.client.offlineDb.upsertDraft({ draft: optimisticDraftResponse });
|
|
8232
|
+
} catch (error) {
|
|
8233
|
+
this.client.logger("error", `offlineDb:upsertDraft`, {
|
|
8234
|
+
tags: ["channel", "offlineDb"],
|
|
8235
|
+
error
|
|
8236
|
+
});
|
|
8237
|
+
}
|
|
8238
|
+
}
|
|
8135
8239
|
this.logDraftUpdateTimestamp();
|
|
8136
8240
|
await this.channel.createDraft(draft);
|
|
8137
8241
|
};
|
|
8138
8242
|
this.deleteDraft = async () => {
|
|
8139
8243
|
if (this.editedMessage || !this.config.drafts.enabled || !this.draftId) return;
|
|
8140
8244
|
this.state.partialNext({ draftId: null });
|
|
8245
|
+
const parentId = this.threadId ?? void 0;
|
|
8246
|
+
if (this.client.offlineDb) {
|
|
8247
|
+
try {
|
|
8248
|
+
await this.client.offlineDb.deleteDraft({
|
|
8249
|
+
cid: this.channel.cid,
|
|
8250
|
+
parent_id: parentId
|
|
8251
|
+
});
|
|
8252
|
+
} catch (error) {
|
|
8253
|
+
this.client.logger("error", `offlineDb:deleteDraft`, {
|
|
8254
|
+
tags: ["channel", "offlineDb"],
|
|
8255
|
+
error
|
|
8256
|
+
});
|
|
8257
|
+
}
|
|
8258
|
+
}
|
|
8141
8259
|
this.logDraftUpdateTimestamp();
|
|
8142
|
-
await this.channel.deleteDraft({ parent_id:
|
|
8260
|
+
await this.channel.deleteDraft({ parent_id: parentId });
|
|
8261
|
+
};
|
|
8262
|
+
this.getDraft = async () => {
|
|
8263
|
+
if (this.editedMessage || !this.config.drafts.enabled || !this.client.userID) return;
|
|
8264
|
+
const draftFromOfflineDB = await this.client.offlineDb?.getDraft({
|
|
8265
|
+
cid: this.channel.cid,
|
|
8266
|
+
userId: this.client.userID,
|
|
8267
|
+
parent_id: this.threadId ?? void 0
|
|
8268
|
+
});
|
|
8269
|
+
if (draftFromOfflineDB) {
|
|
8270
|
+
this.initState({ composition: draftFromOfflineDB });
|
|
8271
|
+
}
|
|
8272
|
+
try {
|
|
8273
|
+
const response = await this.channel.getDraft({
|
|
8274
|
+
parent_id: this.threadId ?? void 0
|
|
8275
|
+
});
|
|
8276
|
+
const { draft } = response;
|
|
8277
|
+
if (!draft) return;
|
|
8278
|
+
this.client.offlineDb?.executeQuerySafely(
|
|
8279
|
+
(db) => db.upsertDraft({
|
|
8280
|
+
draft
|
|
8281
|
+
}),
|
|
8282
|
+
{ method: "upsertDraft" }
|
|
8283
|
+
);
|
|
8284
|
+
this.initState({ composition: draft });
|
|
8285
|
+
} catch (error) {
|
|
8286
|
+
this.client.notifications.add({
|
|
8287
|
+
message: "Failed to get the draft",
|
|
8288
|
+
origin: {
|
|
8289
|
+
emitter: "MessageComposer",
|
|
8290
|
+
context: { composer: this }
|
|
8291
|
+
}
|
|
8292
|
+
});
|
|
8293
|
+
}
|
|
8143
8294
|
};
|
|
8144
8295
|
this.createPoll = async () => {
|
|
8145
8296
|
const composition = await this.pollComposer.compose();
|
|
@@ -8268,6 +8419,9 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
8268
8419
|
return this.state.getLatestValue().showReplyInChannel;
|
|
8269
8420
|
}
|
|
8270
8421
|
get hasSendableData() {
|
|
8422
|
+
if (this.client.offlineDb) {
|
|
8423
|
+
return !this.compositionIsEmpty;
|
|
8424
|
+
}
|
|
8271
8425
|
return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId);
|
|
8272
8426
|
}
|
|
8273
8427
|
get compositionIsEmpty() {
|
|
@@ -8583,6 +8737,17 @@ var Channel = class {
|
|
|
8583
8737
|
updates
|
|
8584
8738
|
);
|
|
8585
8739
|
}
|
|
8740
|
+
/**
|
|
8741
|
+
* sendReaction - Sends a reaction to a message. If offline support is enabled, it will make sure
|
|
8742
|
+
* that sending the reaction is queued up if it fails due to bad internet conditions and executed
|
|
8743
|
+
* later.
|
|
8744
|
+
*
|
|
8745
|
+
* @param {string} messageID the message id
|
|
8746
|
+
* @param {Reaction} reaction the reaction object for instance {type: 'love'}
|
|
8747
|
+
* @param {{ enforce_unique?: boolean, skip_push?: boolean }} [options] Option object, {enforce_unique: true, skip_push: true} to override any existing reaction or skip sending push notifications
|
|
8748
|
+
*
|
|
8749
|
+
* @return {Promise<ReactionAPIResponse>} The Server Response
|
|
8750
|
+
*/
|
|
8586
8751
|
async sendReaction(messageID, reaction, options) {
|
|
8587
8752
|
if (!messageID) {
|
|
8588
8753
|
throw Error(`Message id is missing`);
|
|
@@ -9435,9 +9600,7 @@ var Channel = class {
|
|
|
9435
9600
|
};
|
|
9436
9601
|
this.getClient().polls.hydratePollCache(state.messages, true);
|
|
9437
9602
|
this.getClient().reminders.hydrateState(state.messages);
|
|
9438
|
-
|
|
9439
|
-
this.messageComposer.initState({ composition: state.draft });
|
|
9440
|
-
}
|
|
9603
|
+
this.messageComposer.initStateFromChannelResponse(state);
|
|
9441
9604
|
const areCapabilitiesChanged = [...state.channel.own_capabilities || []].sort().join() !== [
|
|
9442
9605
|
...this.data && Array.isArray(this.data?.own_capabilities) ? this.data.own_capabilities : []
|
|
9443
9606
|
].sort().join();
|
|
@@ -9564,13 +9727,11 @@ var Channel = class {
|
|
|
9564
9727
|
/**
|
|
9565
9728
|
* createDraft - Creates or updates a draft message in a channel
|
|
9566
9729
|
*
|
|
9567
|
-
* @param {string} channelType The channel type
|
|
9568
|
-
* @param {string} channelID The channel ID
|
|
9569
9730
|
* @param {DraftMessagePayload} message The draft message to create or update
|
|
9570
9731
|
*
|
|
9571
9732
|
* @return {Promise<CreateDraftResponse>} Response containing the created draft
|
|
9572
9733
|
*/
|
|
9573
|
-
async
|
|
9734
|
+
async _createDraft(message) {
|
|
9574
9735
|
return await this.getClient().post(
|
|
9575
9736
|
this._channelURL() + "/draft",
|
|
9576
9737
|
{
|
|
@@ -9579,18 +9740,82 @@ var Channel = class {
|
|
|
9579
9740
|
);
|
|
9580
9741
|
}
|
|
9581
9742
|
/**
|
|
9582
|
-
*
|
|
9743
|
+
* createDraft - Creates or updates a draft message in a channel. If offline support is
|
|
9744
|
+
* enabled, it will make sure that creating the draft is queued up if it fails due to
|
|
9745
|
+
* bad internet conditions and executed later.
|
|
9746
|
+
*
|
|
9747
|
+
* @param {DraftMessagePayload} message The draft message to create or update
|
|
9748
|
+
*
|
|
9749
|
+
* @return {Promise<CreateDraftResponse>} Response containing the created draft
|
|
9750
|
+
*/
|
|
9751
|
+
async createDraft(message) {
|
|
9752
|
+
try {
|
|
9753
|
+
const offlineDb = this.getClient().offlineDb;
|
|
9754
|
+
if (offlineDb) {
|
|
9755
|
+
return await offlineDb.queueTask({
|
|
9756
|
+
task: {
|
|
9757
|
+
channelId: this.id,
|
|
9758
|
+
channelType: this.type,
|
|
9759
|
+
threadId: message.parent_id,
|
|
9760
|
+
payload: [message],
|
|
9761
|
+
type: "create-draft"
|
|
9762
|
+
}
|
|
9763
|
+
});
|
|
9764
|
+
}
|
|
9765
|
+
} catch (error) {
|
|
9766
|
+
this._client.logger("error", `offlineDb:create-draft`, {
|
|
9767
|
+
tags: ["channel", "offlineDb"],
|
|
9768
|
+
error
|
|
9769
|
+
});
|
|
9770
|
+
}
|
|
9771
|
+
return this._createDraft(message);
|
|
9772
|
+
}
|
|
9773
|
+
/**
|
|
9774
|
+
* deleteDraft - Deletes a draft message from a channel or a thread.
|
|
9583
9775
|
*
|
|
9584
9776
|
* @param {Object} options
|
|
9585
9777
|
* @param {string} options.parent_id Optional parent message ID for drafts in threads
|
|
9586
9778
|
*
|
|
9587
9779
|
* @return {Promise<APIResponse>} API response
|
|
9588
9780
|
*/
|
|
9589
|
-
async
|
|
9781
|
+
async _deleteDraft({ parent_id } = {}) {
|
|
9590
9782
|
return await this.getClient().delete(this._channelURL() + "/draft", {
|
|
9591
9783
|
parent_id
|
|
9592
9784
|
});
|
|
9593
9785
|
}
|
|
9786
|
+
/**
|
|
9787
|
+
* deleteDraft - Deletes a draft message from a channel or a thread. If offline support is
|
|
9788
|
+
* enabled, it will make sure that deleting the draft is queued up if it fails due to
|
|
9789
|
+
* bad internet conditions and executed later.
|
|
9790
|
+
*
|
|
9791
|
+
* @param {Object} options
|
|
9792
|
+
* @param {string} options.parent_id Optional parent message ID for drafts in threads
|
|
9793
|
+
*
|
|
9794
|
+
* @return {Promise<APIResponse>} API response
|
|
9795
|
+
*/
|
|
9796
|
+
async deleteDraft(options = {}) {
|
|
9797
|
+
const { parent_id } = options;
|
|
9798
|
+
try {
|
|
9799
|
+
const offlineDb = this.getClient().offlineDb;
|
|
9800
|
+
if (offlineDb) {
|
|
9801
|
+
return await offlineDb.queueTask({
|
|
9802
|
+
task: {
|
|
9803
|
+
channelId: this.id,
|
|
9804
|
+
channelType: this.type,
|
|
9805
|
+
threadId: parent_id,
|
|
9806
|
+
payload: [options],
|
|
9807
|
+
type: "delete-draft"
|
|
9808
|
+
}
|
|
9809
|
+
});
|
|
9810
|
+
}
|
|
9811
|
+
} catch (error) {
|
|
9812
|
+
this._client.logger("error", `offlineDb:delete-draft`, {
|
|
9813
|
+
tags: ["channel", "offlineDb"],
|
|
9814
|
+
error
|
|
9815
|
+
});
|
|
9816
|
+
}
|
|
9817
|
+
return this._deleteDraft(options);
|
|
9818
|
+
}
|
|
9594
9819
|
/**
|
|
9595
9820
|
* getDraft - Retrieves a draft message from a channel
|
|
9596
9821
|
*
|
|
@@ -14240,9 +14465,7 @@ var StreamChat = class _StreamChat {
|
|
|
14240
14465
|
this.polls.hydratePollCache(channelState.messages, true);
|
|
14241
14466
|
this.reminders.hydrateState(channelState.messages);
|
|
14242
14467
|
}
|
|
14243
|
-
|
|
14244
|
-
c.messageComposer.initState({ composition: channelState.draft });
|
|
14245
|
-
}
|
|
14468
|
+
c.messageComposer.initStateFromChannelResponse(channelState);
|
|
14246
14469
|
channels.push(c);
|
|
14247
14470
|
}
|
|
14248
14471
|
return channels;
|
|
@@ -15159,7 +15382,7 @@ var StreamChat = class _StreamChat {
|
|
|
15159
15382
|
if (this.userAgent) {
|
|
15160
15383
|
return this.userAgent;
|
|
15161
15384
|
}
|
|
15162
|
-
const version = "9.
|
|
15385
|
+
const version = "9.7.0";
|
|
15163
15386
|
const clientBundle = "browser-cjs";
|
|
15164
15387
|
let userAgentString = "";
|
|
15165
15388
|
if (this.sdkIdentifier) {
|
|
@@ -16248,6 +16471,52 @@ var StreamChat = class _StreamChat {
|
|
|
16248
16471
|
...rest
|
|
16249
16472
|
});
|
|
16250
16473
|
}
|
|
16474
|
+
/**
|
|
16475
|
+
* uploadFile - Uploads a file to the configured storage (defaults to Stream CDN)
|
|
16476
|
+
*
|
|
16477
|
+
* @param {string|NodeJS.ReadableStream|Buffer|File} uri The file to upload
|
|
16478
|
+
* @param {string} [name] The name of the file
|
|
16479
|
+
* @param {string} [contentType] The content type of the file
|
|
16480
|
+
* @param {UserResponse} [user] Optional user information
|
|
16481
|
+
*
|
|
16482
|
+
* @return {Promise<SendFileAPIResponse>} Response containing the file URL
|
|
16483
|
+
*/
|
|
16484
|
+
uploadFile(uri, name, contentType, user) {
|
|
16485
|
+
return this.sendFile(`${this.baseURL}/uploads/file`, uri, name, contentType, user);
|
|
16486
|
+
}
|
|
16487
|
+
/**
|
|
16488
|
+
* uploadImage - Uploads an image to the configured storage (defaults to Stream CDN)
|
|
16489
|
+
*
|
|
16490
|
+
* @param {string|NodeJS.ReadableStream|File} uri The image to upload
|
|
16491
|
+
* @param {string} [name] The name of the image
|
|
16492
|
+
* @param {string} [contentType] The content type of the image
|
|
16493
|
+
* @param {UserResponse} [user] Optional user information
|
|
16494
|
+
*
|
|
16495
|
+
* @return {Promise<SendFileAPIResponse>} Response containing the image URL
|
|
16496
|
+
*/
|
|
16497
|
+
uploadImage(uri, name, contentType, user) {
|
|
16498
|
+
return this.sendFile(`${this.baseURL}/uploads/image`, uri, name, contentType, user);
|
|
16499
|
+
}
|
|
16500
|
+
/**
|
|
16501
|
+
* deleteFile - Deletes a file from the configured storage
|
|
16502
|
+
*
|
|
16503
|
+
* @param {string} url The URL of the file to delete
|
|
16504
|
+
*
|
|
16505
|
+
* @return {Promise<APIResponse>} The server response
|
|
16506
|
+
*/
|
|
16507
|
+
deleteFile(url) {
|
|
16508
|
+
return this.delete(`${this.baseURL}/uploads/file`, { url });
|
|
16509
|
+
}
|
|
16510
|
+
/**
|
|
16511
|
+
* deleteImage - Deletes an image from the configured storage
|
|
16512
|
+
*
|
|
16513
|
+
* @param {string} url The URL of the image to delete
|
|
16514
|
+
*
|
|
16515
|
+
* @return {Promise<APIResponse>} The server response
|
|
16516
|
+
*/
|
|
16517
|
+
deleteImage(url) {
|
|
16518
|
+
return this.delete(`${this.baseURL}/uploads/image`, { url });
|
|
16519
|
+
}
|
|
16251
16520
|
};
|
|
16252
16521
|
|
|
16253
16522
|
// src/events.ts
|
|
@@ -16956,6 +17225,35 @@ var AbstractOfflineDB = class {
|
|
|
16956
17225
|
(executeOverride) => reactionMethod({ message, reaction, execute: executeOverride })
|
|
16957
17226
|
);
|
|
16958
17227
|
};
|
|
17228
|
+
/**
|
|
17229
|
+
* A utility handler for all draft events:
|
|
17230
|
+
* - draft.updated -> updateDraft
|
|
17231
|
+
* - draft.deleted -> deleteDraft
|
|
17232
|
+
* @param event - the WS event we are trying to process
|
|
17233
|
+
* @param execute - whether to immediately execute the operation.
|
|
17234
|
+
*/
|
|
17235
|
+
this.handleDraftEvent = async ({
|
|
17236
|
+
event,
|
|
17237
|
+
execute = true
|
|
17238
|
+
}) => {
|
|
17239
|
+
const { cid, draft, type } = event;
|
|
17240
|
+
if (!draft) return [];
|
|
17241
|
+
if (type === "draft.updated") {
|
|
17242
|
+
return await this.upsertDraft({
|
|
17243
|
+
draft,
|
|
17244
|
+
execute
|
|
17245
|
+
});
|
|
17246
|
+
}
|
|
17247
|
+
if (type === "draft.deleted") {
|
|
17248
|
+
if (!cid) return [];
|
|
17249
|
+
return await this.deleteDraft({
|
|
17250
|
+
cid,
|
|
17251
|
+
parent_id: draft.parent_id,
|
|
17252
|
+
execute
|
|
17253
|
+
});
|
|
17254
|
+
}
|
|
17255
|
+
return [];
|
|
17256
|
+
};
|
|
16959
17257
|
/**
|
|
16960
17258
|
* A generic event handler that decides which DB API to invoke based on
|
|
16961
17259
|
* event.type for all events we are currently handling. It is used to both
|
|
@@ -16992,6 +17290,9 @@ var AbstractOfflineDB = class {
|
|
|
16992
17290
|
if (type === "channel.hidden" || type === "channel.visible") {
|
|
16993
17291
|
return await this.handleChannelVisibilityEvent({ event, execute });
|
|
16994
17292
|
}
|
|
17293
|
+
if (type === "draft.updated" || type === "draft.deleted") {
|
|
17294
|
+
return await this.handleDraftEvent({ event, execute });
|
|
17295
|
+
}
|
|
16995
17296
|
if ((type === "channel.updated" || type === "notification.message_new" || type === "notification.added_to_channel") && channel) {
|
|
16996
17297
|
return await this.upsertChannelData({ channel, execute });
|
|
16997
17298
|
}
|
|
@@ -17066,6 +17367,12 @@ var AbstractOfflineDB = class {
|
|
|
17066
17367
|
if (task.type === "delete-reaction") {
|
|
17067
17368
|
return await channel._deleteReaction(...task.payload);
|
|
17068
17369
|
}
|
|
17370
|
+
if (task.type === "create-draft") {
|
|
17371
|
+
return await channel._createDraft(...task.payload);
|
|
17372
|
+
}
|
|
17373
|
+
if (task.type === "delete-draft") {
|
|
17374
|
+
return await channel._deleteDraft(...task.payload);
|
|
17375
|
+
}
|
|
17069
17376
|
if (task.type === "send-message") {
|
|
17070
17377
|
const newMessageResponse = await channel._sendMessage(...task.payload);
|
|
17071
17378
|
const newMessage = newMessageResponse?.message;
|