stream-chat 9.6.0 → 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 +383 -65
- package/dist/cjs/index.browser.cjs.map +3 -3
- package/dist/cjs/index.node.cjs +387 -68
- package/dist/cjs/index.node.cjs.map +3 -3
- package/dist/esm/index.js +383 -65
- 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/WithSubscriptions.d.ts +7 -2
- 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 +136 -32
- 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/WithSubscriptions.ts +16 -2
- package/src/utils.ts +31 -2
package/dist/cjs/index.node.cjs
CHANGED
|
@@ -10233,7 +10233,7 @@ var require_follow_redirects = __commonJS({
|
|
|
10233
10233
|
"ERR_STREAM_WRITE_AFTER_END",
|
|
10234
10234
|
"write after end"
|
|
10235
10235
|
);
|
|
10236
|
-
var destroy = Writable.prototype.destroy ||
|
|
10236
|
+
var destroy = Writable.prototype.destroy || noop3;
|
|
10237
10237
|
function RedirectableRequest(options, responseCallback) {
|
|
10238
10238
|
Writable.call(this);
|
|
10239
10239
|
this._sanitizeOptions(options);
|
|
@@ -10585,7 +10585,7 @@ var require_follow_redirects = __commonJS({
|
|
|
10585
10585
|
});
|
|
10586
10586
|
return exports3;
|
|
10587
10587
|
}
|
|
10588
|
-
function
|
|
10588
|
+
function noop3() {
|
|
10589
10589
|
}
|
|
10590
10590
|
function urlToOptions(urlObject) {
|
|
10591
10591
|
var options = {
|
|
@@ -10631,7 +10631,7 @@ var require_follow_redirects = __commonJS({
|
|
|
10631
10631
|
for (var event of events) {
|
|
10632
10632
|
request.removeListener(event, eventHandlers[event]);
|
|
10633
10633
|
}
|
|
10634
|
-
request.on("error",
|
|
10634
|
+
request.on("error", noop3);
|
|
10635
10635
|
request.destroy(error);
|
|
10636
10636
|
}
|
|
10637
10637
|
function isSubdomain(subdomain, domain) {
|
|
@@ -10672,6 +10672,7 @@ __export(index_exports, {
|
|
|
10672
10672
|
AttachmentManager: () => AttachmentManager,
|
|
10673
10673
|
BasePaginator: () => BasePaginator,
|
|
10674
10674
|
BaseSearchSource: () => BaseSearchSource,
|
|
10675
|
+
BaseSearchSourceSync: () => BaseSearchSourceSync,
|
|
10675
10676
|
BuiltinPermissions: () => BuiltinPermissions,
|
|
10676
10677
|
BuiltinRoles: () => BuiltinRoles,
|
|
10677
10678
|
Campaign: () => Campaign,
|
|
@@ -14100,6 +14101,23 @@ function formatMessage(message) {
|
|
|
14100
14101
|
quoted_message: toLocalMessageBase(message.quoted_message)
|
|
14101
14102
|
};
|
|
14102
14103
|
}
|
|
14104
|
+
function unformatMessage(message) {
|
|
14105
|
+
const toMessageResponseBase = (msg) => {
|
|
14106
|
+
if (!msg) return null;
|
|
14107
|
+
const newDateString = (/* @__PURE__ */ new Date()).toISOString();
|
|
14108
|
+
return {
|
|
14109
|
+
...msg,
|
|
14110
|
+
created_at: message.created_at ? message.created_at.toISOString() : newDateString,
|
|
14111
|
+
deleted_at: message.deleted_at ? message.deleted_at.toISOString() : void 0,
|
|
14112
|
+
pinned_at: message.pinned_at ? message.pinned_at.toISOString() : void 0,
|
|
14113
|
+
updated_at: message.updated_at ? message.updated_at.toISOString() : newDateString
|
|
14114
|
+
};
|
|
14115
|
+
};
|
|
14116
|
+
return {
|
|
14117
|
+
...toMessageResponseBase(message),
|
|
14118
|
+
quoted_message: toMessageResponseBase(message.quoted_message)
|
|
14119
|
+
};
|
|
14120
|
+
}
|
|
14103
14121
|
var localMessageToNewMessagePayload = (localMessage) => {
|
|
14104
14122
|
const {
|
|
14105
14123
|
// Remove all timestamp fields and client-specific fields.
|
|
@@ -17639,11 +17657,8 @@ var DEFAULT_SEARCH_SOURCE_OPTIONS = {
|
|
|
17639
17657
|
debounceMs: 300,
|
|
17640
17658
|
pageSize: 10
|
|
17641
17659
|
};
|
|
17642
|
-
var
|
|
17660
|
+
var BaseSearchSourceBase = class {
|
|
17643
17661
|
constructor(options) {
|
|
17644
|
-
this.setDebounceOptions = ({ debounceMs }) => {
|
|
17645
|
-
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
17646
|
-
};
|
|
17647
17662
|
this.activate = () => {
|
|
17648
17663
|
if (this.isActive) return;
|
|
17649
17664
|
this.state.partialNext({ isActive: true });
|
|
@@ -17657,11 +17672,9 @@ var BaseSearchSource = class {
|
|
|
17657
17672
|
const searchString = newSearchString ?? this.searchQuery;
|
|
17658
17673
|
return !!(this.isActive && !this.isLoading && (this.hasNext || hasNewSearchQuery) && searchString);
|
|
17659
17674
|
};
|
|
17660
|
-
|
|
17661
|
-
const { debounceMs, pageSize } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
17675
|
+
const { pageSize } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
17662
17676
|
this.pageSize = pageSize;
|
|
17663
17677
|
this.state = new StateStore(this.initialState);
|
|
17664
|
-
this.setDebounceOptions({ debounceMs });
|
|
17665
17678
|
}
|
|
17666
17679
|
get lastQueryError() {
|
|
17667
17680
|
return this.state.getLatestValue().lastQueryError;
|
|
@@ -17721,8 +17734,7 @@ var BaseSearchSource = class {
|
|
|
17721
17734
|
items: isFirstPage ? stateUpdate.items : [...this.items ?? [], ...stateUpdate.items || []]
|
|
17722
17735
|
};
|
|
17723
17736
|
}
|
|
17724
|
-
|
|
17725
|
-
if (!this.canExecuteQuery(newSearchString)) return;
|
|
17737
|
+
prepareStateForQuery(newSearchString) {
|
|
17726
17738
|
const hasNewSearchQuery = typeof newSearchString !== "undefined";
|
|
17727
17739
|
const searchString = newSearchString ?? this.searchQuery;
|
|
17728
17740
|
if (hasNewSearchQuery) {
|
|
@@ -17730,18 +17742,47 @@ var BaseSearchSource = class {
|
|
|
17730
17742
|
} else {
|
|
17731
17743
|
this.state.partialNext({ isLoading: true });
|
|
17732
17744
|
}
|
|
17745
|
+
return { searchString, hasNewSearchQuery };
|
|
17746
|
+
}
|
|
17747
|
+
updatePaginationStateFromQuery(result) {
|
|
17748
|
+
const { items, next } = result;
|
|
17733
17749
|
const stateUpdate = {};
|
|
17750
|
+
if (next || next === null) {
|
|
17751
|
+
stateUpdate.next = next;
|
|
17752
|
+
stateUpdate.hasNext = !!next;
|
|
17753
|
+
} else {
|
|
17754
|
+
stateUpdate.offset = (this.offset ?? 0) + items.length;
|
|
17755
|
+
stateUpdate.hasNext = items.length === this.pageSize;
|
|
17756
|
+
}
|
|
17757
|
+
return stateUpdate;
|
|
17758
|
+
}
|
|
17759
|
+
resetState() {
|
|
17760
|
+
this.state.next(this.initialState);
|
|
17761
|
+
}
|
|
17762
|
+
resetStateAndActivate() {
|
|
17763
|
+
this.resetState();
|
|
17764
|
+
this.activate();
|
|
17765
|
+
}
|
|
17766
|
+
};
|
|
17767
|
+
var BaseSearchSource = class extends BaseSearchSourceBase {
|
|
17768
|
+
constructor(options) {
|
|
17769
|
+
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
17770
|
+
super(options);
|
|
17771
|
+
this.setDebounceOptions = ({ debounceMs }) => {
|
|
17772
|
+
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
17773
|
+
};
|
|
17774
|
+
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
17775
|
+
this.setDebounceOptions({ debounceMs });
|
|
17776
|
+
}
|
|
17777
|
+
async executeQuery(newSearchString) {
|
|
17778
|
+
if (!this.canExecuteQuery(newSearchString)) return;
|
|
17779
|
+
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
17780
|
+
let stateUpdate = {};
|
|
17734
17781
|
try {
|
|
17735
17782
|
const results = await this.query(searchString);
|
|
17736
17783
|
if (!results) return;
|
|
17737
|
-
const { items
|
|
17738
|
-
|
|
17739
|
-
stateUpdate.next = next;
|
|
17740
|
-
stateUpdate.hasNext = !!next;
|
|
17741
|
-
} else {
|
|
17742
|
-
stateUpdate.offset = (this.offset ?? 0) + items.length;
|
|
17743
|
-
stateUpdate.hasNext = items.length === this.pageSize;
|
|
17744
|
-
}
|
|
17784
|
+
const { items } = results;
|
|
17785
|
+
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
17745
17786
|
stateUpdate.items = await this.filterQueryResults(items);
|
|
17746
17787
|
} catch (e) {
|
|
17747
17788
|
stateUpdate.lastQueryError = e;
|
|
@@ -17752,12 +17793,35 @@ var BaseSearchSource = class {
|
|
|
17752
17793
|
cancelScheduledQuery() {
|
|
17753
17794
|
this.searchDebounced.cancel();
|
|
17754
17795
|
}
|
|
17755
|
-
|
|
17756
|
-
|
|
17796
|
+
};
|
|
17797
|
+
var BaseSearchSourceSync = class extends BaseSearchSourceBase {
|
|
17798
|
+
constructor(options) {
|
|
17799
|
+
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
17800
|
+
super(options);
|
|
17801
|
+
this.setDebounceOptions = ({ debounceMs }) => {
|
|
17802
|
+
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
17803
|
+
};
|
|
17804
|
+
this.search = (searchQuery) => this.searchDebounced(searchQuery);
|
|
17805
|
+
this.setDebounceOptions({ debounceMs });
|
|
17757
17806
|
}
|
|
17758
|
-
|
|
17759
|
-
this.
|
|
17760
|
-
this.
|
|
17807
|
+
executeQuery(newSearchString) {
|
|
17808
|
+
if (!this.canExecuteQuery(newSearchString)) return;
|
|
17809
|
+
const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
|
|
17810
|
+
let stateUpdate = {};
|
|
17811
|
+
try {
|
|
17812
|
+
const results = this.query(searchString);
|
|
17813
|
+
if (!results) return;
|
|
17814
|
+
const { items } = results;
|
|
17815
|
+
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
17816
|
+
stateUpdate.items = this.filterQueryResults(items);
|
|
17817
|
+
} catch (e) {
|
|
17818
|
+
stateUpdate.lastQueryError = e;
|
|
17819
|
+
} finally {
|
|
17820
|
+
this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
|
|
17821
|
+
}
|
|
17822
|
+
}
|
|
17823
|
+
cancelScheduledQuery() {
|
|
17824
|
+
this.searchDebounced.cancel();
|
|
17761
17825
|
}
|
|
17762
17826
|
};
|
|
17763
17827
|
|
|
@@ -18040,7 +18104,7 @@ var getTokenizedSuggestionDisplayName = ({
|
|
|
18040
18104
|
});
|
|
18041
18105
|
|
|
18042
18106
|
// src/messageComposer/middleware/textComposer/commands.ts
|
|
18043
|
-
var CommandSearchSource = class extends
|
|
18107
|
+
var CommandSearchSource = class extends BaseSearchSourceSync {
|
|
18044
18108
|
constructor(channel, options) {
|
|
18045
18109
|
super(options);
|
|
18046
18110
|
this.type = "commands";
|
|
@@ -18084,10 +18148,10 @@ var CommandSearchSource = class extends BaseSearchSource {
|
|
|
18084
18148
|
}
|
|
18085
18149
|
return 0;
|
|
18086
18150
|
});
|
|
18087
|
-
return
|
|
18151
|
+
return {
|
|
18088
18152
|
items: selectedCommands.map((c) => ({ ...c, id: c.name })),
|
|
18089
18153
|
next: null
|
|
18090
|
-
}
|
|
18154
|
+
};
|
|
18091
18155
|
}
|
|
18092
18156
|
filterQueryResults(items) {
|
|
18093
18157
|
return items;
|
|
@@ -18695,6 +18759,7 @@ var TextComposer = class {
|
|
|
18695
18759
|
var _WithSubscriptions = class _WithSubscriptions {
|
|
18696
18760
|
constructor() {
|
|
18697
18761
|
this.unsubscribeFunctions = /* @__PURE__ */ new Set();
|
|
18762
|
+
this.refCount = 0;
|
|
18698
18763
|
}
|
|
18699
18764
|
/**
|
|
18700
18765
|
* Returns a boolean, provides information of whether `registerSubscriptions`
|
|
@@ -18706,6 +18771,12 @@ var _WithSubscriptions = class _WithSubscriptions {
|
|
|
18706
18771
|
addUnsubscribeFunction(unsubscribeFunction) {
|
|
18707
18772
|
this.unsubscribeFunctions.add(unsubscribeFunction);
|
|
18708
18773
|
}
|
|
18774
|
+
/**
|
|
18775
|
+
* Increments `refCount` by one and returns new value.
|
|
18776
|
+
*/
|
|
18777
|
+
incrementRefCount() {
|
|
18778
|
+
return ++this.refCount;
|
|
18779
|
+
}
|
|
18709
18780
|
/**
|
|
18710
18781
|
* If you re-declare `unregisterSubscriptions` method within your class
|
|
18711
18782
|
* make sure to run the original too.
|
|
@@ -18722,8 +18793,13 @@ var _WithSubscriptions = class _WithSubscriptions {
|
|
|
18722
18793
|
* ```
|
|
18723
18794
|
*/
|
|
18724
18795
|
unregisterSubscriptions() {
|
|
18796
|
+
if (this.refCount > 1) {
|
|
18797
|
+
this.refCount--;
|
|
18798
|
+
return _WithSubscriptions.symbol;
|
|
18799
|
+
}
|
|
18725
18800
|
this.unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
|
|
18726
18801
|
this.unsubscribeFunctions.clear();
|
|
18802
|
+
this.refCount = 0;
|
|
18727
18803
|
return _WithSubscriptions.symbol;
|
|
18728
18804
|
}
|
|
18729
18805
|
};
|
|
@@ -19209,7 +19285,6 @@ var initState5 = (composition) => {
|
|
|
19209
19285
|
showReplyInChannel: false
|
|
19210
19286
|
};
|
|
19211
19287
|
};
|
|
19212
|
-
var noop3 = () => void 0;
|
|
19213
19288
|
var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
19214
19289
|
// todo: mediaRecorder: MediaRecorderController;
|
|
19215
19290
|
constructor({
|
|
@@ -19234,22 +19309,48 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
19234
19309
|
this.editedMessage = message;
|
|
19235
19310
|
}
|
|
19236
19311
|
};
|
|
19312
|
+
this.initStateFromChannelResponse = (channelApiResponse) => {
|
|
19313
|
+
if (this.channel.cid !== channelApiResponse.channel.cid) {
|
|
19314
|
+
return;
|
|
19315
|
+
}
|
|
19316
|
+
if (channelApiResponse.draft) {
|
|
19317
|
+
this.initState({ composition: channelApiResponse.draft });
|
|
19318
|
+
} else if (this.state.getLatestValue().draftId) {
|
|
19319
|
+
this.clear();
|
|
19320
|
+
this.client.offlineDb?.executeQuerySafely(
|
|
19321
|
+
(db) => db.deleteDraft({
|
|
19322
|
+
cid: this.channel.cid,
|
|
19323
|
+
parent_id: void 0
|
|
19324
|
+
// makes sure that we don't delete thread drafts while upserting channels
|
|
19325
|
+
}),
|
|
19326
|
+
{ method: "deleteDraft" }
|
|
19327
|
+
);
|
|
19328
|
+
}
|
|
19329
|
+
};
|
|
19237
19330
|
this.initEditingAuditState = (composition) => initEditingAuditState(composition);
|
|
19331
|
+
this.registerDraftEventSubscriptions = () => {
|
|
19332
|
+
const unsubscribeDraftUpdated = this.subscribeDraftUpdated();
|
|
19333
|
+
const unsubscribeDraftDeleted = this.subscribeDraftDeleted();
|
|
19334
|
+
return () => {
|
|
19335
|
+
unsubscribeDraftUpdated();
|
|
19336
|
+
unsubscribeDraftDeleted();
|
|
19337
|
+
};
|
|
19338
|
+
};
|
|
19238
19339
|
this.registerSubscriptions = () => {
|
|
19239
|
-
if (this.hasSubscriptions) {
|
|
19240
|
-
|
|
19241
|
-
|
|
19242
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
this.
|
|
19252
|
-
return this.unregisterSubscriptions
|
|
19340
|
+
if (!this.hasSubscriptions) {
|
|
19341
|
+
this.addUnsubscribeFunction(this.subscribeMessageComposerSetupStateChange());
|
|
19342
|
+
this.addUnsubscribeFunction(this.subscribeMessageUpdated());
|
|
19343
|
+
this.addUnsubscribeFunction(this.subscribeMessageDeleted());
|
|
19344
|
+
this.addUnsubscribeFunction(this.subscribeTextComposerStateChanged());
|
|
19345
|
+
this.addUnsubscribeFunction(this.subscribeAttachmentManagerStateChanged());
|
|
19346
|
+
this.addUnsubscribeFunction(this.subscribeLinkPreviewsManagerStateChanged());
|
|
19347
|
+
this.addUnsubscribeFunction(this.subscribePollComposerStateChanged());
|
|
19348
|
+
this.addUnsubscribeFunction(this.subscribeCustomDataManagerStateChanged());
|
|
19349
|
+
this.addUnsubscribeFunction(this.subscribeMessageComposerStateChanged());
|
|
19350
|
+
this.addUnsubscribeFunction(this.subscribeMessageComposerConfigStateChanged());
|
|
19351
|
+
}
|
|
19352
|
+
this.incrementRefCount();
|
|
19353
|
+
return () => this.unregisterSubscriptions();
|
|
19253
19354
|
};
|
|
19254
19355
|
this.subscribeMessageUpdated = () => {
|
|
19255
19356
|
const eventTypes = [
|
|
@@ -19299,13 +19400,13 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
19299
19400
|
}).unsubscribe;
|
|
19300
19401
|
this.subscribeDraftUpdated = () => this.client.on("draft.updated", (event) => {
|
|
19301
19402
|
const draft = event.draft;
|
|
19302
|
-
if (!draft ||
|
|
19403
|
+
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid)
|
|
19303
19404
|
return;
|
|
19304
19405
|
this.initState({ composition: draft });
|
|
19305
19406
|
}).unsubscribe;
|
|
19306
19407
|
this.subscribeDraftDeleted = () => this.client.on("draft.deleted", (event) => {
|
|
19307
19408
|
const draft = event.draft;
|
|
19308
|
-
if (!draft ||
|
|
19409
|
+
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid) {
|
|
19309
19410
|
return;
|
|
19310
19411
|
}
|
|
19311
19412
|
this.logDraftUpdateTimestamp();
|
|
@@ -19369,7 +19470,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
19369
19470
|
}
|
|
19370
19471
|
});
|
|
19371
19472
|
this.subscribeMessageComposerConfigStateChanged = () => {
|
|
19372
|
-
let
|
|
19473
|
+
let draftUnsubscribeFunction;
|
|
19373
19474
|
const unsubscribe = this.configState.subscribeWithSelector(
|
|
19374
19475
|
(currentValue) => ({
|
|
19375
19476
|
textDefaultValue: currentValue.text.defaultValue,
|
|
@@ -19382,19 +19483,16 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
19382
19483
|
selection: { start: 0, end: 0 }
|
|
19383
19484
|
});
|
|
19384
19485
|
}
|
|
19385
|
-
if (draftsEnabled && !
|
|
19386
|
-
|
|
19387
|
-
|
|
19388
|
-
|
|
19389
|
-
|
|
19390
|
-
} else if (!draftsEnabled && draftUnsubscribeFunctions) {
|
|
19391
|
-
draftUnsubscribeFunctions.forEach((fn) => fn());
|
|
19392
|
-
draftUnsubscribeFunctions = null;
|
|
19486
|
+
if (draftsEnabled && !draftUnsubscribeFunction) {
|
|
19487
|
+
draftUnsubscribeFunction = this.registerDraftEventSubscriptions();
|
|
19488
|
+
} else if (!draftsEnabled && draftUnsubscribeFunction) {
|
|
19489
|
+
draftUnsubscribeFunction();
|
|
19490
|
+
draftUnsubscribeFunction = null;
|
|
19393
19491
|
}
|
|
19394
19492
|
}
|
|
19395
19493
|
);
|
|
19396
19494
|
return () => {
|
|
19397
|
-
|
|
19495
|
+
draftUnsubscribeFunction?.();
|
|
19398
19496
|
unsubscribe();
|
|
19399
19497
|
};
|
|
19400
19498
|
};
|
|
@@ -19464,14 +19562,78 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
19464
19562
|
if (!composition) return;
|
|
19465
19563
|
const { draft } = composition;
|
|
19466
19564
|
this.state.partialNext({ draftId: draft.id });
|
|
19565
|
+
if (this.client.offlineDb) {
|
|
19566
|
+
try {
|
|
19567
|
+
const optimisticDraftResponse = {
|
|
19568
|
+
channel_cid: this.channel.cid,
|
|
19569
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19570
|
+
message: draft,
|
|
19571
|
+
parent_id: draft.parent_id,
|
|
19572
|
+
quoted_message: this.quotedMessage ? unformatMessage(this.quotedMessage) : void 0
|
|
19573
|
+
};
|
|
19574
|
+
await this.client.offlineDb.upsertDraft({ draft: optimisticDraftResponse });
|
|
19575
|
+
} catch (error) {
|
|
19576
|
+
this.client.logger("error", `offlineDb:upsertDraft`, {
|
|
19577
|
+
tags: ["channel", "offlineDb"],
|
|
19578
|
+
error
|
|
19579
|
+
});
|
|
19580
|
+
}
|
|
19581
|
+
}
|
|
19467
19582
|
this.logDraftUpdateTimestamp();
|
|
19468
19583
|
await this.channel.createDraft(draft);
|
|
19469
19584
|
};
|
|
19470
19585
|
this.deleteDraft = async () => {
|
|
19471
19586
|
if (this.editedMessage || !this.config.drafts.enabled || !this.draftId) return;
|
|
19472
19587
|
this.state.partialNext({ draftId: null });
|
|
19588
|
+
const parentId = this.threadId ?? void 0;
|
|
19589
|
+
if (this.client.offlineDb) {
|
|
19590
|
+
try {
|
|
19591
|
+
await this.client.offlineDb.deleteDraft({
|
|
19592
|
+
cid: this.channel.cid,
|
|
19593
|
+
parent_id: parentId
|
|
19594
|
+
});
|
|
19595
|
+
} catch (error) {
|
|
19596
|
+
this.client.logger("error", `offlineDb:deleteDraft`, {
|
|
19597
|
+
tags: ["channel", "offlineDb"],
|
|
19598
|
+
error
|
|
19599
|
+
});
|
|
19600
|
+
}
|
|
19601
|
+
}
|
|
19473
19602
|
this.logDraftUpdateTimestamp();
|
|
19474
|
-
await this.channel.deleteDraft({ parent_id:
|
|
19603
|
+
await this.channel.deleteDraft({ parent_id: parentId });
|
|
19604
|
+
};
|
|
19605
|
+
this.getDraft = async () => {
|
|
19606
|
+
if (this.editedMessage || !this.config.drafts.enabled || !this.client.userID) return;
|
|
19607
|
+
const draftFromOfflineDB = await this.client.offlineDb?.getDraft({
|
|
19608
|
+
cid: this.channel.cid,
|
|
19609
|
+
userId: this.client.userID,
|
|
19610
|
+
parent_id: this.threadId ?? void 0
|
|
19611
|
+
});
|
|
19612
|
+
if (draftFromOfflineDB) {
|
|
19613
|
+
this.initState({ composition: draftFromOfflineDB });
|
|
19614
|
+
}
|
|
19615
|
+
try {
|
|
19616
|
+
const response = await this.channel.getDraft({
|
|
19617
|
+
parent_id: this.threadId ?? void 0
|
|
19618
|
+
});
|
|
19619
|
+
const { draft } = response;
|
|
19620
|
+
if (!draft) return;
|
|
19621
|
+
this.client.offlineDb?.executeQuerySafely(
|
|
19622
|
+
(db) => db.upsertDraft({
|
|
19623
|
+
draft
|
|
19624
|
+
}),
|
|
19625
|
+
{ method: "upsertDraft" }
|
|
19626
|
+
);
|
|
19627
|
+
this.initState({ composition: draft });
|
|
19628
|
+
} catch (error) {
|
|
19629
|
+
this.client.notifications.add({
|
|
19630
|
+
message: "Failed to get the draft",
|
|
19631
|
+
origin: {
|
|
19632
|
+
emitter: "MessageComposer",
|
|
19633
|
+
context: { composer: this }
|
|
19634
|
+
}
|
|
19635
|
+
});
|
|
19636
|
+
}
|
|
19475
19637
|
};
|
|
19476
19638
|
this.createPoll = async () => {
|
|
19477
19639
|
const composition = await this.pollComposer.compose();
|
|
@@ -19600,6 +19762,9 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
19600
19762
|
return this.state.getLatestValue().showReplyInChannel;
|
|
19601
19763
|
}
|
|
19602
19764
|
get hasSendableData() {
|
|
19765
|
+
if (this.client.offlineDb) {
|
|
19766
|
+
return !this.compositionIsEmpty;
|
|
19767
|
+
}
|
|
19603
19768
|
return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId);
|
|
19604
19769
|
}
|
|
19605
19770
|
get compositionIsEmpty() {
|
|
@@ -19915,6 +20080,17 @@ var Channel = class {
|
|
|
19915
20080
|
updates
|
|
19916
20081
|
);
|
|
19917
20082
|
}
|
|
20083
|
+
/**
|
|
20084
|
+
* sendReaction - Sends a reaction to a message. If offline support is enabled, it will make sure
|
|
20085
|
+
* that sending the reaction is queued up if it fails due to bad internet conditions and executed
|
|
20086
|
+
* later.
|
|
20087
|
+
*
|
|
20088
|
+
* @param {string} messageID the message id
|
|
20089
|
+
* @param {Reaction} reaction the reaction object for instance {type: 'love'}
|
|
20090
|
+
* @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
|
|
20091
|
+
*
|
|
20092
|
+
* @return {Promise<ReactionAPIResponse>} The Server Response
|
|
20093
|
+
*/
|
|
19918
20094
|
async sendReaction(messageID, reaction, options) {
|
|
19919
20095
|
if (!messageID) {
|
|
19920
20096
|
throw Error(`Message id is missing`);
|
|
@@ -20767,9 +20943,7 @@ var Channel = class {
|
|
|
20767
20943
|
};
|
|
20768
20944
|
this.getClient().polls.hydratePollCache(state.messages, true);
|
|
20769
20945
|
this.getClient().reminders.hydrateState(state.messages);
|
|
20770
|
-
|
|
20771
|
-
this.messageComposer.initState({ composition: state.draft });
|
|
20772
|
-
}
|
|
20946
|
+
this.messageComposer.initStateFromChannelResponse(state);
|
|
20773
20947
|
const areCapabilitiesChanged = [...state.channel.own_capabilities || []].sort().join() !== [
|
|
20774
20948
|
...this.data && Array.isArray(this.data?.own_capabilities) ? this.data.own_capabilities : []
|
|
20775
20949
|
].sort().join();
|
|
@@ -20896,13 +21070,11 @@ var Channel = class {
|
|
|
20896
21070
|
/**
|
|
20897
21071
|
* createDraft - Creates or updates a draft message in a channel
|
|
20898
21072
|
*
|
|
20899
|
-
* @param {string} channelType The channel type
|
|
20900
|
-
* @param {string} channelID The channel ID
|
|
20901
21073
|
* @param {DraftMessagePayload} message The draft message to create or update
|
|
20902
21074
|
*
|
|
20903
21075
|
* @return {Promise<CreateDraftResponse>} Response containing the created draft
|
|
20904
21076
|
*/
|
|
20905
|
-
async
|
|
21077
|
+
async _createDraft(message) {
|
|
20906
21078
|
return await this.getClient().post(
|
|
20907
21079
|
this._channelURL() + "/draft",
|
|
20908
21080
|
{
|
|
@@ -20911,18 +21083,82 @@ var Channel = class {
|
|
|
20911
21083
|
);
|
|
20912
21084
|
}
|
|
20913
21085
|
/**
|
|
20914
|
-
*
|
|
21086
|
+
* createDraft - Creates or updates a draft message in a channel. If offline support is
|
|
21087
|
+
* enabled, it will make sure that creating the draft is queued up if it fails due to
|
|
21088
|
+
* bad internet conditions and executed later.
|
|
21089
|
+
*
|
|
21090
|
+
* @param {DraftMessagePayload} message The draft message to create or update
|
|
21091
|
+
*
|
|
21092
|
+
* @return {Promise<CreateDraftResponse>} Response containing the created draft
|
|
21093
|
+
*/
|
|
21094
|
+
async createDraft(message) {
|
|
21095
|
+
try {
|
|
21096
|
+
const offlineDb = this.getClient().offlineDb;
|
|
21097
|
+
if (offlineDb) {
|
|
21098
|
+
return await offlineDb.queueTask({
|
|
21099
|
+
task: {
|
|
21100
|
+
channelId: this.id,
|
|
21101
|
+
channelType: this.type,
|
|
21102
|
+
threadId: message.parent_id,
|
|
21103
|
+
payload: [message],
|
|
21104
|
+
type: "create-draft"
|
|
21105
|
+
}
|
|
21106
|
+
});
|
|
21107
|
+
}
|
|
21108
|
+
} catch (error) {
|
|
21109
|
+
this._client.logger("error", `offlineDb:create-draft`, {
|
|
21110
|
+
tags: ["channel", "offlineDb"],
|
|
21111
|
+
error
|
|
21112
|
+
});
|
|
21113
|
+
}
|
|
21114
|
+
return this._createDraft(message);
|
|
21115
|
+
}
|
|
21116
|
+
/**
|
|
21117
|
+
* deleteDraft - Deletes a draft message from a channel or a thread.
|
|
20915
21118
|
*
|
|
20916
21119
|
* @param {Object} options
|
|
20917
21120
|
* @param {string} options.parent_id Optional parent message ID for drafts in threads
|
|
20918
21121
|
*
|
|
20919
21122
|
* @return {Promise<APIResponse>} API response
|
|
20920
21123
|
*/
|
|
20921
|
-
async
|
|
21124
|
+
async _deleteDraft({ parent_id } = {}) {
|
|
20922
21125
|
return await this.getClient().delete(this._channelURL() + "/draft", {
|
|
20923
21126
|
parent_id
|
|
20924
21127
|
});
|
|
20925
21128
|
}
|
|
21129
|
+
/**
|
|
21130
|
+
* deleteDraft - Deletes a draft message from a channel or a thread. If offline support is
|
|
21131
|
+
* enabled, it will make sure that deleting the draft is queued up if it fails due to
|
|
21132
|
+
* bad internet conditions and executed later.
|
|
21133
|
+
*
|
|
21134
|
+
* @param {Object} options
|
|
21135
|
+
* @param {string} options.parent_id Optional parent message ID for drafts in threads
|
|
21136
|
+
*
|
|
21137
|
+
* @return {Promise<APIResponse>} API response
|
|
21138
|
+
*/
|
|
21139
|
+
async deleteDraft(options = {}) {
|
|
21140
|
+
const { parent_id } = options;
|
|
21141
|
+
try {
|
|
21142
|
+
const offlineDb = this.getClient().offlineDb;
|
|
21143
|
+
if (offlineDb) {
|
|
21144
|
+
return await offlineDb.queueTask({
|
|
21145
|
+
task: {
|
|
21146
|
+
channelId: this.id,
|
|
21147
|
+
channelType: this.type,
|
|
21148
|
+
threadId: parent_id,
|
|
21149
|
+
payload: [options],
|
|
21150
|
+
type: "delete-draft"
|
|
21151
|
+
}
|
|
21152
|
+
});
|
|
21153
|
+
}
|
|
21154
|
+
} catch (error) {
|
|
21155
|
+
this._client.logger("error", `offlineDb:delete-draft`, {
|
|
21156
|
+
tags: ["channel", "offlineDb"],
|
|
21157
|
+
error
|
|
21158
|
+
});
|
|
21159
|
+
}
|
|
21160
|
+
return this._deleteDraft(options);
|
|
21161
|
+
}
|
|
20926
21162
|
/**
|
|
20927
21163
|
* getDraft - Retrieves a draft message from a channel
|
|
20928
21164
|
*
|
|
@@ -25560,9 +25796,7 @@ var StreamChat = class _StreamChat {
|
|
|
25560
25796
|
this.polls.hydratePollCache(channelState.messages, true);
|
|
25561
25797
|
this.reminders.hydrateState(channelState.messages);
|
|
25562
25798
|
}
|
|
25563
|
-
|
|
25564
|
-
c.messageComposer.initState({ composition: channelState.draft });
|
|
25565
|
-
}
|
|
25799
|
+
c.messageComposer.initStateFromChannelResponse(channelState);
|
|
25566
25800
|
channels.push(c);
|
|
25567
25801
|
}
|
|
25568
25802
|
return channels;
|
|
@@ -26479,7 +26713,7 @@ var StreamChat = class _StreamChat {
|
|
|
26479
26713
|
if (this.userAgent) {
|
|
26480
26714
|
return this.userAgent;
|
|
26481
26715
|
}
|
|
26482
|
-
const version = "9.
|
|
26716
|
+
const version = "9.7.0";
|
|
26483
26717
|
const clientBundle = "node-cjs";
|
|
26484
26718
|
let userAgentString = "";
|
|
26485
26719
|
if (this.sdkIdentifier) {
|
|
@@ -27568,6 +27802,52 @@ var StreamChat = class _StreamChat {
|
|
|
27568
27802
|
...rest
|
|
27569
27803
|
});
|
|
27570
27804
|
}
|
|
27805
|
+
/**
|
|
27806
|
+
* uploadFile - Uploads a file to the configured storage (defaults to Stream CDN)
|
|
27807
|
+
*
|
|
27808
|
+
* @param {string|NodeJS.ReadableStream|Buffer|File} uri The file to upload
|
|
27809
|
+
* @param {string} [name] The name of the file
|
|
27810
|
+
* @param {string} [contentType] The content type of the file
|
|
27811
|
+
* @param {UserResponse} [user] Optional user information
|
|
27812
|
+
*
|
|
27813
|
+
* @return {Promise<SendFileAPIResponse>} Response containing the file URL
|
|
27814
|
+
*/
|
|
27815
|
+
uploadFile(uri, name, contentType, user) {
|
|
27816
|
+
return this.sendFile(`${this.baseURL}/uploads/file`, uri, name, contentType, user);
|
|
27817
|
+
}
|
|
27818
|
+
/**
|
|
27819
|
+
* uploadImage - Uploads an image to the configured storage (defaults to Stream CDN)
|
|
27820
|
+
*
|
|
27821
|
+
* @param {string|NodeJS.ReadableStream|File} uri The image to upload
|
|
27822
|
+
* @param {string} [name] The name of the image
|
|
27823
|
+
* @param {string} [contentType] The content type of the image
|
|
27824
|
+
* @param {UserResponse} [user] Optional user information
|
|
27825
|
+
*
|
|
27826
|
+
* @return {Promise<SendFileAPIResponse>} Response containing the image URL
|
|
27827
|
+
*/
|
|
27828
|
+
uploadImage(uri, name, contentType, user) {
|
|
27829
|
+
return this.sendFile(`${this.baseURL}/uploads/image`, uri, name, contentType, user);
|
|
27830
|
+
}
|
|
27831
|
+
/**
|
|
27832
|
+
* deleteFile - Deletes a file from the configured storage
|
|
27833
|
+
*
|
|
27834
|
+
* @param {string} url The URL of the file to delete
|
|
27835
|
+
*
|
|
27836
|
+
* @return {Promise<APIResponse>} The server response
|
|
27837
|
+
*/
|
|
27838
|
+
deleteFile(url2) {
|
|
27839
|
+
return this.delete(`${this.baseURL}/uploads/file`, { url: url2 });
|
|
27840
|
+
}
|
|
27841
|
+
/**
|
|
27842
|
+
* deleteImage - Deletes an image from the configured storage
|
|
27843
|
+
*
|
|
27844
|
+
* @param {string} url The URL of the image to delete
|
|
27845
|
+
*
|
|
27846
|
+
* @return {Promise<APIResponse>} The server response
|
|
27847
|
+
*/
|
|
27848
|
+
deleteImage(url2) {
|
|
27849
|
+
return this.delete(`${this.baseURL}/uploads/image`, { url: url2 });
|
|
27850
|
+
}
|
|
27571
27851
|
};
|
|
27572
27852
|
|
|
27573
27853
|
// src/events.ts
|
|
@@ -28276,6 +28556,35 @@ var AbstractOfflineDB = class {
|
|
|
28276
28556
|
(executeOverride) => reactionMethod({ message, reaction, execute: executeOverride })
|
|
28277
28557
|
);
|
|
28278
28558
|
};
|
|
28559
|
+
/**
|
|
28560
|
+
* A utility handler for all draft events:
|
|
28561
|
+
* - draft.updated -> updateDraft
|
|
28562
|
+
* - draft.deleted -> deleteDraft
|
|
28563
|
+
* @param event - the WS event we are trying to process
|
|
28564
|
+
* @param execute - whether to immediately execute the operation.
|
|
28565
|
+
*/
|
|
28566
|
+
this.handleDraftEvent = async ({
|
|
28567
|
+
event,
|
|
28568
|
+
execute = true
|
|
28569
|
+
}) => {
|
|
28570
|
+
const { cid, draft, type } = event;
|
|
28571
|
+
if (!draft) return [];
|
|
28572
|
+
if (type === "draft.updated") {
|
|
28573
|
+
return await this.upsertDraft({
|
|
28574
|
+
draft,
|
|
28575
|
+
execute
|
|
28576
|
+
});
|
|
28577
|
+
}
|
|
28578
|
+
if (type === "draft.deleted") {
|
|
28579
|
+
if (!cid) return [];
|
|
28580
|
+
return await this.deleteDraft({
|
|
28581
|
+
cid,
|
|
28582
|
+
parent_id: draft.parent_id,
|
|
28583
|
+
execute
|
|
28584
|
+
});
|
|
28585
|
+
}
|
|
28586
|
+
return [];
|
|
28587
|
+
};
|
|
28279
28588
|
/**
|
|
28280
28589
|
* A generic event handler that decides which DB API to invoke based on
|
|
28281
28590
|
* event.type for all events we are currently handling. It is used to both
|
|
@@ -28312,6 +28621,9 @@ var AbstractOfflineDB = class {
|
|
|
28312
28621
|
if (type === "channel.hidden" || type === "channel.visible") {
|
|
28313
28622
|
return await this.handleChannelVisibilityEvent({ event, execute });
|
|
28314
28623
|
}
|
|
28624
|
+
if (type === "draft.updated" || type === "draft.deleted") {
|
|
28625
|
+
return await this.handleDraftEvent({ event, execute });
|
|
28626
|
+
}
|
|
28315
28627
|
if ((type === "channel.updated" || type === "notification.message_new" || type === "notification.added_to_channel") && channel) {
|
|
28316
28628
|
return await this.upsertChannelData({ channel, execute });
|
|
28317
28629
|
}
|
|
@@ -28386,6 +28698,12 @@ var AbstractOfflineDB = class {
|
|
|
28386
28698
|
if (task.type === "delete-reaction") {
|
|
28387
28699
|
return await channel._deleteReaction(...task.payload);
|
|
28388
28700
|
}
|
|
28701
|
+
if (task.type === "create-draft") {
|
|
28702
|
+
return await channel._createDraft(...task.payload);
|
|
28703
|
+
}
|
|
28704
|
+
if (task.type === "delete-draft") {
|
|
28705
|
+
return await channel._deleteDraft(...task.payload);
|
|
28706
|
+
}
|
|
28389
28707
|
if (task.type === "send-message") {
|
|
28390
28708
|
const newMessageResponse = await channel._sendMessage(...task.payload);
|
|
28391
28709
|
const newMessage = newMessageResponse?.message;
|
|
@@ -28514,6 +28832,7 @@ var FixedSizeQueueCache = class {
|
|
|
28514
28832
|
AttachmentManager,
|
|
28515
28833
|
BasePaginator,
|
|
28516
28834
|
BaseSearchSource,
|
|
28835
|
+
BaseSearchSourceSync,
|
|
28517
28836
|
BuiltinPermissions,
|
|
28518
28837
|
BuiltinRoles,
|
|
28519
28838
|
Campaign,
|