stream-chat 9.48.0 → 9.50.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 +109 -48
- package/dist/cjs/index.browser.js.map +2 -2
- package/dist/cjs/index.node.js +109 -48
- package/dist/cjs/index.node.js.map +2 -2
- package/dist/esm/index.mjs +109 -48
- package/dist/esm/index.mjs.map +2 -2
- package/dist/types/channel.d.ts +12 -0
- package/dist/types/client.d.ts +4 -2
- package/dist/types/events.d.ts +1 -0
- package/dist/types/types.d.ts +16 -0
- package/dist/types/utils.d.ts +13 -0
- package/package.json +1 -1
- package/src/channel.ts +45 -4
- package/src/client.ts +47 -28
- package/src/events.ts +1 -0
- package/src/messageDelivery/MessageDeliveryReporter.ts +3 -1
- package/src/offline-support/offline_support_api.ts +53 -24
- package/src/types.ts +14 -0
- package/src/utils.ts +22 -0
package/dist/cjs/index.node.js
CHANGED
|
@@ -590,6 +590,12 @@ function isOwnUserBaseProperty(property) {
|
|
|
590
590
|
};
|
|
591
591
|
return ownUserBaseProperties[property];
|
|
592
592
|
}
|
|
593
|
+
var channelHasReadEvents = (channel) => {
|
|
594
|
+
const ownCapabilities = channel?.data?.own_capabilities;
|
|
595
|
+
return !(Array.isArray(ownCapabilities) && !ownCapabilities.includes("read-events"));
|
|
596
|
+
};
|
|
597
|
+
var channelTracksReadLocally = (channel) => !channelHasReadEvents(channel) && !!channel?.getClient().options.isLocalUnreadCountEnabled;
|
|
598
|
+
var userHasReadReceipts = (client) => client.user?.privacy_settings?.read_receipts?.enabled ?? true;
|
|
593
599
|
function addFileToFormData(uri, name, contentType) {
|
|
594
600
|
const data = new import_form_data.default();
|
|
595
601
|
if (isReadableStream(uri) || isBuffer(uri) || isFileWebAPI(uri) || isBlobWebAPI(uri)) {
|
|
@@ -8751,6 +8757,7 @@ var MessageDeliveryReporter = class _MessageDeliveryReporter {
|
|
|
8751
8757
|
* @param options
|
|
8752
8758
|
*/
|
|
8753
8759
|
this.markRead = async (collection, options) => {
|
|
8760
|
+
if (!userHasReadReceipts(this.client)) return null;
|
|
8754
8761
|
let result = null;
|
|
8755
8762
|
if (isChannel(collection)) {
|
|
8756
8763
|
result = await collection.markAsReadRequest(options);
|
|
@@ -10095,6 +10102,33 @@ var Channel = class {
|
|
|
10095
10102
|
...data
|
|
10096
10103
|
});
|
|
10097
10104
|
}
|
|
10105
|
+
/**
|
|
10106
|
+
* markReadLocally - Resets this user's unread count locally, without any backend call. Intended for
|
|
10107
|
+
* channels that have read events disabled (e.g. livestreams) when the client is created with the
|
|
10108
|
+
* `isLocalUnreadCountEnabled` option. Dispatches a dedicated, client-only `message.read_locally` event
|
|
10109
|
+
* that runs through the same `_handleChannelEvent` read logic as a real `message.read` (minus the
|
|
10110
|
+
* delivery-report network sync), so the read-state update lives in one place. When offline support
|
|
10111
|
+
* is enabled, the offline DB persists the reset for read-events-disabled channels, so the local
|
|
10112
|
+
* count stays consistent across app restarts.
|
|
10113
|
+
*
|
|
10114
|
+
* @return {Event | undefined} The dispatched `message.read_locally` event, or `undefined` if there is no connected user.
|
|
10115
|
+
*/
|
|
10116
|
+
markReadLocally() {
|
|
10117
|
+
const client = this.getClient();
|
|
10118
|
+
if (!client.userID) return;
|
|
10119
|
+
const event = {
|
|
10120
|
+
channel_id: this.id,
|
|
10121
|
+
channel_type: this.type,
|
|
10122
|
+
cid: this.cid,
|
|
10123
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10124
|
+
last_read_message_id: this.lastMessage()?.id,
|
|
10125
|
+
team: this.data?.team,
|
|
10126
|
+
type: "message.read_locally",
|
|
10127
|
+
user: client.user
|
|
10128
|
+
};
|
|
10129
|
+
client.dispatchEvent(event);
|
|
10130
|
+
return event;
|
|
10131
|
+
}
|
|
10098
10132
|
/**
|
|
10099
10133
|
* clean - Cleans the channel state and fires stop typing if needed
|
|
10100
10134
|
*/
|
|
@@ -10250,7 +10284,7 @@ var Channel = class {
|
|
|
10250
10284
|
if (message.user?.id === this.getClient().userID) return false;
|
|
10251
10285
|
if (message.user?.id && this.getClient().userMuteStatus(message.user.id))
|
|
10252
10286
|
return false;
|
|
10253
|
-
if (
|
|
10287
|
+
if (!this.getClient().options.isLocalUnreadCountEnabled && !channelHasReadEvents(this)) {
|
|
10254
10288
|
return false;
|
|
10255
10289
|
}
|
|
10256
10290
|
if (this.getClient()._muteStatus(this.cid).muted) return false;
|
|
@@ -10661,6 +10695,11 @@ var Channel = class {
|
|
|
10661
10695
|
delete channelState.typing[event.user.id];
|
|
10662
10696
|
}
|
|
10663
10697
|
break;
|
|
10698
|
+
// `message.read_locally` is the client-only event dispatched by `markReadLocally()` when read
|
|
10699
|
+
// events are disabled (e.g. livestreams with `isLocalUnreadCountEnabled`). It reuses the exact
|
|
10700
|
+
// `message.read` state logic so the read-state update lives in one place — only the
|
|
10701
|
+
// delivery-report network sync below is skipped for it.
|
|
10702
|
+
case "message.read_locally":
|
|
10664
10703
|
case "message.read":
|
|
10665
10704
|
if (event.user?.id && event.created_at) {
|
|
10666
10705
|
const previousReadState = channelState.read[event.user.id];
|
|
@@ -10681,7 +10720,9 @@ var Channel = class {
|
|
|
10681
10720
|
const isOwnEvent = event.user?.id === client.user?.id;
|
|
10682
10721
|
if (isOwnEvent) {
|
|
10683
10722
|
channelState.unreadCount = 0;
|
|
10684
|
-
|
|
10723
|
+
if (event.type === "message.read") {
|
|
10724
|
+
client.syncDeliveredCandidates([this]);
|
|
10725
|
+
}
|
|
10685
10726
|
}
|
|
10686
10727
|
}
|
|
10687
10728
|
break;
|
|
@@ -14796,6 +14837,31 @@ var StreamChat = class _StreamChat {
|
|
|
14796
14837
|
* @return {Promise<APIResponse>}
|
|
14797
14838
|
*/
|
|
14798
14839
|
this.markAllRead = this.markChannelsRead;
|
|
14840
|
+
this.getUserAgent = () => {
|
|
14841
|
+
if (this.userAgent) {
|
|
14842
|
+
return this.userAgent;
|
|
14843
|
+
}
|
|
14844
|
+
if (!this.cachedUserAgent) {
|
|
14845
|
+
const version = "9.50.0";
|
|
14846
|
+
const { name: sdkName, version: sdkVersion } = this.sdkIdentifier ?? {};
|
|
14847
|
+
const { name: appName, version: appVersion } = this.appIdentifier ?? {};
|
|
14848
|
+
const { os, model: deviceModel } = this.deviceIdentifier ?? {};
|
|
14849
|
+
const head = sdkName ? `stream-chat-${sdkName}-v${sdkVersion}-llc-v${version}` : `stream-chat-js-v${version}-${this.node ? "node" : "browser"}`;
|
|
14850
|
+
this.cachedUserAgent = [
|
|
14851
|
+
head,
|
|
14852
|
+
// reports the host app, the device OS, the device model, and the picked
|
|
14853
|
+
// exports bundle, each only when a value is present
|
|
14854
|
+
...Object.entries({
|
|
14855
|
+
app: appName,
|
|
14856
|
+
app_version: appVersion,
|
|
14857
|
+
os,
|
|
14858
|
+
device_model: deviceModel,
|
|
14859
|
+
client_bundle: "node-cjs"
|
|
14860
|
+
}).filter(([, value]) => value && value.length > 0).map(([key, value]) => `${key}=${value}`)
|
|
14861
|
+
].join("|");
|
|
14862
|
+
}
|
|
14863
|
+
return this.cachedUserAgent;
|
|
14864
|
+
};
|
|
14799
14865
|
/**
|
|
14800
14866
|
* _isUsingServerAuth - Returns true if we're using server side auth
|
|
14801
14867
|
*/
|
|
@@ -14834,6 +14900,7 @@ var StreamChat = class _StreamChat {
|
|
|
14834
14900
|
warmUp: false,
|
|
14835
14901
|
recoverStateOnReconnect: true,
|
|
14836
14902
|
disableCache: false,
|
|
14903
|
+
isLocalUnreadCountEnabled: false,
|
|
14837
14904
|
wsUrlParams: new URLSearchParams({}),
|
|
14838
14905
|
...inputOptions
|
|
14839
14906
|
};
|
|
@@ -15248,6 +15315,13 @@ var StreamChat = class _StreamChat {
|
|
|
15248
15315
|
delete this.activeChannels[cid];
|
|
15249
15316
|
});
|
|
15250
15317
|
}
|
|
15318
|
+
if (event.type === "notification.removed_from_channel" && event.cid) {
|
|
15319
|
+
const { cid } = event;
|
|
15320
|
+
this.activeChannels[cid]?._disconnect();
|
|
15321
|
+
postListenerCallbacks.push(() => {
|
|
15322
|
+
delete this.activeChannels[cid];
|
|
15323
|
+
});
|
|
15324
|
+
}
|
|
15251
15325
|
return postListenerCallbacks;
|
|
15252
15326
|
}
|
|
15253
15327
|
_muteStatus(cid) {
|
|
@@ -16739,31 +16813,6 @@ var StreamChat = class _StreamChat {
|
|
|
16739
16813
|
partialThreadObject
|
|
16740
16814
|
);
|
|
16741
16815
|
}
|
|
16742
|
-
getUserAgent() {
|
|
16743
|
-
if (this.userAgent) {
|
|
16744
|
-
return this.userAgent;
|
|
16745
|
-
}
|
|
16746
|
-
const version = "9.48.0";
|
|
16747
|
-
const clientBundle = "node-cjs";
|
|
16748
|
-
let userAgentString = "";
|
|
16749
|
-
if (this.sdkIdentifier) {
|
|
16750
|
-
userAgentString = `stream-chat-${this.sdkIdentifier.name}-v${this.sdkIdentifier.version}-llc-v${version}`;
|
|
16751
|
-
} else {
|
|
16752
|
-
userAgentString = `stream-chat-js-v${version}-${this.node ? "node" : "browser"}`;
|
|
16753
|
-
}
|
|
16754
|
-
const { os, model } = this.deviceIdentifier ?? {};
|
|
16755
|
-
return [
|
|
16756
|
-
// reports the device OS, if provided
|
|
16757
|
-
["os", os],
|
|
16758
|
-
// reports the device model, if provided
|
|
16759
|
-
["device_model", model],
|
|
16760
|
-
// reports which bundle is being picked from the exports
|
|
16761
|
-
["client_bundle", clientBundle]
|
|
16762
|
-
].reduce(
|
|
16763
|
-
(withArguments, [key, value]) => value && value.length > 0 ? withArguments.concat(`|${key}=${value}`) : withArguments,
|
|
16764
|
-
userAgentString
|
|
16765
|
-
);
|
|
16766
|
-
}
|
|
16767
16816
|
/**
|
|
16768
16817
|
* @deprecated use sdkIdentifier instead
|
|
16769
16818
|
* @param userAgent
|
|
@@ -18205,6 +18254,7 @@ var EVENT_MAP = {
|
|
|
18205
18254
|
"ai_indicator.stop": true,
|
|
18206
18255
|
"ai_indicator.clear": true,
|
|
18207
18256
|
// local events
|
|
18257
|
+
"message.read_locally": true,
|
|
18208
18258
|
"channels.queried": true,
|
|
18209
18259
|
"offline_reactions.queried": true,
|
|
18210
18260
|
"connection.changed": true,
|
|
@@ -18588,7 +18638,8 @@ var AbstractOfflineDB = class {
|
|
|
18588
18638
|
if (cid && client.user && client.user.id !== user?.id) {
|
|
18589
18639
|
const userId = client.user.id;
|
|
18590
18640
|
const channel = client.activeChannels[cid];
|
|
18591
|
-
|
|
18641
|
+
const tracksReadLocally = channelTracksReadLocally(channel);
|
|
18642
|
+
if (channel && (channelHasReadEvents(channel) || tracksReadLocally)) {
|
|
18592
18643
|
const ownReads = channel.state.read[userId];
|
|
18593
18644
|
const unreadCount = channel.countUnread();
|
|
18594
18645
|
const upsertReadsQueries = await this.upsertReads({
|
|
@@ -18596,8 +18647,8 @@ var AbstractOfflineDB = class {
|
|
|
18596
18647
|
execute: false,
|
|
18597
18648
|
reads: [
|
|
18598
18649
|
{
|
|
18599
|
-
last_read: ownReads
|
|
18600
|
-
last_read_message_id: ownReads
|
|
18650
|
+
last_read: (ownReads?.last_read ?? /* @__PURE__ */ new Date(0)).toISOString(),
|
|
18651
|
+
last_read_message_id: ownReads?.last_read_message_id,
|
|
18601
18652
|
unread_messages: unreadCount,
|
|
18602
18653
|
user: client.user
|
|
18603
18654
|
}
|
|
@@ -18796,27 +18847,30 @@ var AbstractOfflineDB = class {
|
|
|
18796
18847
|
truncated_at,
|
|
18797
18848
|
execute: false
|
|
18798
18849
|
});
|
|
18850
|
+
let finalQueries = [...truncateQueries];
|
|
18799
18851
|
const userId = ownUser.id;
|
|
18800
18852
|
const activeChannel = this.client.activeChannels[cid];
|
|
18801
|
-
const
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
|
|
18853
|
+
const tracksReadLocally = channelTracksReadLocally(activeChannel);
|
|
18854
|
+
if (activeChannel && (channelHasReadEvents(activeChannel) || tracksReadLocally)) {
|
|
18855
|
+
const ownReads = activeChannel.state.read[userId];
|
|
18856
|
+
let unreadCount = 0;
|
|
18857
|
+
if (truncated_at) {
|
|
18858
|
+
unreadCount = activeChannel.countUnread(new Date(truncated_at));
|
|
18859
|
+
}
|
|
18860
|
+
const upsertReadQueries = await this.upsertReads({
|
|
18861
|
+
cid,
|
|
18862
|
+
execute: false,
|
|
18863
|
+
reads: [
|
|
18864
|
+
{
|
|
18865
|
+
last_read: (ownReads?.last_read ?? /* @__PURE__ */ new Date(0)).toString(),
|
|
18866
|
+
last_read_message_id: ownReads?.last_read_message_id,
|
|
18867
|
+
unread_messages: unreadCount,
|
|
18868
|
+
user: ownUser
|
|
18869
|
+
}
|
|
18870
|
+
]
|
|
18871
|
+
});
|
|
18872
|
+
finalQueries = [...finalQueries, ...upsertReadQueries];
|
|
18806
18873
|
}
|
|
18807
|
-
const upsertReadQueries = await this.upsertReads({
|
|
18808
|
-
cid,
|
|
18809
|
-
execute: false,
|
|
18810
|
-
reads: [
|
|
18811
|
-
{
|
|
18812
|
-
last_read: ownReads.last_read.toString(),
|
|
18813
|
-
last_read_message_id: ownReads.last_read_message_id,
|
|
18814
|
-
unread_messages: unreadCount,
|
|
18815
|
-
user: ownUser
|
|
18816
|
-
}
|
|
18817
|
-
]
|
|
18818
|
-
});
|
|
18819
|
-
const finalQueries = [...truncateQueries, ...upsertReadQueries];
|
|
18820
18874
|
if (execute) {
|
|
18821
18875
|
await this.executeSqlBatch(finalQueries);
|
|
18822
18876
|
}
|
|
@@ -18917,6 +18971,13 @@ var AbstractOfflineDB = class {
|
|
|
18917
18971
|
if (type === "message.read" || type === "notification.mark_read") {
|
|
18918
18972
|
return this.handleRead({ event, unreadMessages: 0, execute });
|
|
18919
18973
|
}
|
|
18974
|
+
if (type === "message.read_locally") {
|
|
18975
|
+
const localChannel = event.cid ? this.client.activeChannels[event.cid] : void 0;
|
|
18976
|
+
if (channelTracksReadLocally(localChannel)) {
|
|
18977
|
+
return this.handleRead({ event, unreadMessages: 0, execute });
|
|
18978
|
+
}
|
|
18979
|
+
return [];
|
|
18980
|
+
}
|
|
18920
18981
|
if (type === "notification.mark_unread") {
|
|
18921
18982
|
return this.handleRead({ event, execute });
|
|
18922
18983
|
}
|