stream-chat-react 12.8.1 → 12.9.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.
@@ -2757,9 +2757,9 @@ var require_unified = __commonJS({
2757
2757
  return typeof value === "function" && value.prototype && // A function with keys in its prototype is probably a constructor.
2758
2758
  // Classes’ prototype methods are not enumerable, so we check if some value
2759
2759
  // exists in the prototype.
2760
- (keys2(value.prototype) || name in value.prototype);
2760
+ (keys3(value.prototype) || name in value.prototype);
2761
2761
  }
2762
- function keys2(value) {
2762
+ function keys3(value) {
2763
2763
  var key;
2764
2764
  for (key in value) {
2765
2765
  return true;
@@ -16321,14 +16321,14 @@ var init_mml_react_esm = __esm({
16321
16321
  this.reset(true);
16322
16322
  }
16323
16323
  exports.keys = function(object) {
16324
- var keys2 = [];
16324
+ var keys3 = [];
16325
16325
  for (var key in object) {
16326
- keys2.push(key);
16326
+ keys3.push(key);
16327
16327
  }
16328
- keys2.reverse();
16328
+ keys3.reverse();
16329
16329
  return function next() {
16330
- while (keys2.length) {
16331
- var key2 = keys2.pop();
16330
+ while (keys3.length) {
16331
+ var key2 = keys3.pop();
16332
16332
  if (key2 in object) {
16333
16333
  next.value = key2;
16334
16334
  next.done = false;
@@ -17622,6 +17622,7 @@ __export(src_exports, {
17622
17622
  enTranslations: () => en_default,
17623
17623
  esTranslations: () => es_default,
17624
17624
  escapeRegExp: () => escapeRegExp,
17625
+ extractSortValue: () => extractSortValue,
17625
17626
  findLastPinnedChannelIndex: () => findLastPinnedChannelIndex,
17626
17627
  frTranslations: () => fr_default,
17627
17628
  getChannel: () => getChannel,
@@ -17630,6 +17631,7 @@ __export(src_exports, {
17630
17631
  getGroupChannelDisplayInfo: () => getGroupChannelDisplayInfo,
17631
17632
  getGroupStyles: () => getGroupStyles,
17632
17633
  getImages: () => getImages,
17634
+ getIsFirstUnreadMessage: () => getIsFirstUnreadMessage,
17633
17635
  getLastReceived: () => getLastReceived,
17634
17636
  getLatestMessagePreview: () => getLatestMessagePreview,
17635
17637
  getMessageActions: () => getMessageActions,
@@ -18084,16 +18086,16 @@ var import_react7 = require("react");
18084
18086
 
18085
18087
  // src/store/hooks/useStateStore.ts
18086
18088
  var import_react6 = require("react");
18087
- function useStateStore(store, selector6) {
18089
+ function useStateStore(store, selector7) {
18088
18090
  const [state, setState] = (0, import_react6.useState)(() => {
18089
18091
  if (!store) return void 0;
18090
- return selector6(store.getLatestValue());
18092
+ return selector7(store.getLatestValue());
18091
18093
  });
18092
18094
  (0, import_react6.useEffect)(() => {
18093
18095
  if (!store) return;
18094
- const unsubscribe = store.subscribeWithSelector(selector6, setState);
18096
+ const unsubscribe = store.subscribeWithSelector(selector7, setState);
18095
18097
  return unsubscribe;
18096
- }, [store, selector6]);
18098
+ }, [store, selector7]);
18097
18099
  return state;
18098
18100
  }
18099
18101
 
@@ -39960,7 +39962,10 @@ var moveChannelUpwards = ({
39960
39962
  const targetChannelExistsWithinList = targetChannelIndex >= 0;
39961
39963
  const targetChannelAlreadyAtTheTop = targetChannelIndex === 0;
39962
39964
  const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
39963
- if (targetChannelAlreadyAtTheTop) return channels;
39965
+ const isTargetChannelPinned = isChannelPinned(channelToMove);
39966
+ if (targetChannelAlreadyAtTheTop || considerPinnedChannels && isTargetChannelPinned) {
39967
+ return channels;
39968
+ }
39964
39969
  const newChannels = [...channels];
39965
39970
  if (targetChannelExistsWithinList) {
39966
39971
  newChannels.splice(targetChannelIndex, 1);
@@ -39977,25 +39982,48 @@ var moveChannelUpwards = ({
39977
39982
  return newChannels;
39978
39983
  };
39979
39984
  var shouldConsiderPinnedChannels = (sort) => {
39980
- if (!sort) return false;
39981
- if (!Array.isArray(sort)) return false;
39982
- const [option] = sort;
39983
- if (!option?.pinned_at) return false;
39984
- return Math.abs(option.pinned_at) === 1;
39985
+ const value = extractSortValue({ atIndex: 0, sort, targetKey: "pinned_at" });
39986
+ if (typeof value !== "number") return false;
39987
+ return Math.abs(value) === 1;
39988
+ };
39989
+ var extractSortValue = ({
39990
+ atIndex,
39991
+ sort,
39992
+ targetKey
39993
+ }) => {
39994
+ if (!sort) return null;
39995
+ let option = null;
39996
+ if (Array.isArray(sort)) {
39997
+ option = sort[atIndex] ?? null;
39998
+ } else {
39999
+ let index3 = 0;
40000
+ for (const key in sort) {
40001
+ if (index3 !== atIndex) {
40002
+ index3++;
40003
+ continue;
40004
+ }
40005
+ if (key !== targetKey) {
40006
+ return null;
40007
+ }
40008
+ option = sort;
40009
+ break;
40010
+ }
40011
+ }
40012
+ return option?.[targetKey] ?? null;
39985
40013
  };
39986
40014
  var shouldConsiderArchivedChannels = (filters) => {
39987
40015
  if (!filters) return false;
39988
- return !filters.archived;
40016
+ return typeof filters.archived === "boolean";
39989
40017
  };
39990
40018
  var isChannelPinned = (channel) => {
39991
40019
  if (!channel) return false;
39992
- const member = channel.state.membership;
39993
- return !!member?.pinned_at;
40020
+ const membership = channel.state.membership;
40021
+ return typeof membership.pinned_at === "string";
39994
40022
  };
39995
40023
  var isChannelArchived = (channel) => {
39996
40024
  if (!channel) return false;
39997
- const member = channel.state.membership;
39998
- return !!member?.archived_at;
40025
+ const membership = channel.state.membership;
40026
+ return typeof membership.archived_at === "string";
39999
40027
  };
40000
40028
 
40001
40029
  // src/components/ChannelList/hooks/usePaginatedChannels.ts
@@ -40858,33 +40886,33 @@ var useChannelListShapeDefaults = () => {
40858
40886
  if (typeof customHandler === "function") {
40859
40887
  return customHandler(setChannels, event);
40860
40888
  }
40861
- setChannels((channels) => {
40862
- const targetChannelIndex = channels.findIndex((channel) => channel.cid === event.cid);
40889
+ const channelType = event.channel_type;
40890
+ const channelId = event.channel_id;
40891
+ if (!channelType || !channelId) return;
40892
+ setChannels((currentChannels) => {
40893
+ const targetChannel = client.channel(channelType, channelId);
40894
+ const targetChannelIndex = currentChannels.indexOf(targetChannel);
40863
40895
  const targetChannelExistsWithinList = targetChannelIndex >= 0;
40864
- const targetChannel = channels[targetChannelIndex];
40865
40896
  const isTargetChannelPinned = isChannelPinned(targetChannel);
40866
40897
  const isTargetChannelArchived = isChannelArchived(targetChannel);
40867
40898
  const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
40868
40899
  const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
40869
40900
  if (
40870
- // target channel is archived
40871
- isTargetChannelArchived && considerArchivedChannels || // target channel is pinned
40872
- isTargetChannelPinned && considerPinnedChannels || // list order is locked
40901
+ // filter is defined, target channel is archived and filter option is set to false
40902
+ considerArchivedChannels && isTargetChannelArchived && !filters.archived || // filter is defined, target channel isn't archived and filter option is set to true
40903
+ considerArchivedChannels && !isTargetChannelArchived && filters.archived || // sort option is defined, target channel is pinned
40904
+ considerPinnedChannels && isTargetChannelPinned || // list order is locked
40873
40905
  lockChannelOrder || // target channel is not within the loaded list and loading from cache is disallowed
40874
40906
  !targetChannelExistsWithinList && !allowNewMessagesFromUnfilteredChannels
40875
40907
  ) {
40876
- return channels;
40877
- }
40878
- const channelToMove = channels[targetChannelIndex] ?? (allowNewMessagesFromUnfilteredChannels && event.channel_type ? client.channel(event.channel_type, event.channel_id) : null);
40879
- if (channelToMove) {
40880
- return moveChannelUpwards({
40881
- channels,
40882
- channelToMove,
40883
- channelToMoveIndexWithinChannels: targetChannelIndex,
40884
- sort
40885
- });
40908
+ return currentChannels;
40886
40909
  }
40887
- return channels;
40910
+ return moveChannelUpwards({
40911
+ channels: currentChannels,
40912
+ channelToMove: targetChannel,
40913
+ channelToMoveIndexWithinChannels: targetChannelIndex,
40914
+ sort
40915
+ });
40888
40916
  });
40889
40917
  },
40890
40918
  [client]
@@ -40910,7 +40938,7 @@ var useChannelListShapeDefaults = () => {
40910
40938
  type: event.channel.type
40911
40939
  });
40912
40940
  const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
40913
- if (isChannelArchived(channel) && considerArchivedChannels) {
40941
+ if (isChannelArchived(channel) && considerArchivedChannels && !filters.archived) {
40914
40942
  return;
40915
40943
  }
40916
40944
  if (!allowNewMessagesFromUnfilteredChannels) {
@@ -40932,26 +40960,33 @@ var useChannelListShapeDefaults = () => {
40932
40960
  allowNewMessagesFromUnfilteredChannels,
40933
40961
  customHandler,
40934
40962
  event,
40935
- setChannels
40963
+ setChannels,
40964
+ sort
40936
40965
  }) => {
40937
40966
  if (typeof customHandler === "function") {
40938
40967
  return customHandler(setChannels, event);
40939
40968
  }
40940
- if (allowNewMessagesFromUnfilteredChannels && event.channel?.type) {
40941
- const channel = await getChannel({
40942
- client,
40943
- id: event.channel.id,
40944
- members: event.channel.members?.reduce((acc, { user, user_id }) => {
40945
- const userId = user_id || user?.id;
40946
- if (userId) {
40947
- acc.push(userId);
40948
- }
40949
- return acc;
40950
- }, []),
40951
- type: event.channel.type
40952
- });
40953
- setChannels((channels) => (0, import_lodash11.default)([channel, ...channels], "cid"));
40969
+ if (!event.channel || !allowNewMessagesFromUnfilteredChannels) {
40970
+ return;
40954
40971
  }
40972
+ const channel = await getChannel({
40973
+ client,
40974
+ id: event.channel.id,
40975
+ members: event.channel.members?.reduce((newMembers, { user, user_id }) => {
40976
+ const userId = user_id || user?.id;
40977
+ if (userId) newMembers.push(userId);
40978
+ return newMembers;
40979
+ }, []),
40980
+ type: event.channel.type
40981
+ });
40982
+ setChannels(
40983
+ (channels) => moveChannelUpwards({
40984
+ channels,
40985
+ channelToMove: channel,
40986
+ channelToMoveIndexWithinChannels: -1,
40987
+ sort
40988
+ })
40989
+ );
40955
40990
  },
40956
40991
  [client]
40957
40992
  );
@@ -40969,29 +41004,37 @@ var useChannelListShapeDefaults = () => {
40969
41004
  []
40970
41005
  );
40971
41006
  const handleMemberUpdated = (0, import_react101.useCallback)(
40972
- ({ event, lockChannelOrder, setChannels, sort }) => {
41007
+ ({
41008
+ event,
41009
+ filters,
41010
+ lockChannelOrder,
41011
+ setChannels,
41012
+ sort
41013
+ }) => {
40973
41014
  if (!event.member?.user || event.member.user.id !== client.userID || !event.channel_type) {
40974
41015
  return;
40975
41016
  }
40976
- const member = event.member;
40977
41017
  const channelType = event.channel_type;
40978
41018
  const channelId = event.channel_id;
40979
41019
  const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
40980
- const pinnedAtSort = Array.isArray(sort) ? sort[0]?.pinned_at ?? null : null;
41020
+ const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
41021
+ const pinnedAtSort = extractSortValue({ atIndex: 0, sort, targetKey: "pinned_at" });
40981
41022
  setChannels((currentChannels) => {
40982
41023
  const targetChannel = client.channel(channelType, channelId);
40983
41024
  const targetChannelIndex = currentChannels.indexOf(targetChannel);
40984
41025
  const targetChannelExistsWithinList = targetChannelIndex >= 0;
41026
+ const isTargetChannelArchived = isChannelArchived(targetChannel);
41027
+ const isTargetChannelPinned = isChannelPinned(targetChannel);
40985
41028
  if (!considerPinnedChannels || lockChannelOrder) return currentChannels;
40986
41029
  const newChannels = [...currentChannels];
40987
41030
  if (targetChannelExistsWithinList) {
40988
41031
  newChannels.splice(targetChannelIndex, 1);
40989
41032
  }
40990
- if (typeof member.archived_at === "string") {
41033
+ if (considerArchivedChannels && isTargetChannelArchived && !filters.archived || considerArchivedChannels && !isTargetChannelArchived && filters.archived) {
40991
41034
  return newChannels;
40992
41035
  }
40993
41036
  let lastPinnedChannelIndex = null;
40994
- if (pinnedAtSort === 1 || pinnedAtSort === -1 && !member.pinned_at) {
41037
+ if (pinnedAtSort === 1 || pinnedAtSort === -1 && !isTargetChannelPinned) {
40995
41038
  lastPinnedChannelIndex = findLastPinnedChannelIndex({ channels: newChannels });
40996
41039
  }
40997
41040
  const newTargetChannelIndex = typeof lastPinnedChannelIndex === "number" ? lastPinnedChannelIndex + 1 : 0;
@@ -41192,6 +41235,7 @@ var usePrepareShapeHandlers = ({
41192
41235
  case "member.updated":
41193
41236
  defaults.handleMemberUpdated({
41194
41237
  event,
41238
+ filters,
41195
41239
  lockChannelOrder,
41196
41240
  setChannels,
41197
41241
  sort
@@ -41675,24 +41719,41 @@ var useUserPresenceChangedListener = (setChannels) => {
41675
41719
  }, [client, setChannels]);
41676
41720
  };
41677
41721
 
41678
- // src/components/ChannelList/hooks/useChannelMembershipState.ts
41722
+ // src/components/ChannelList/hooks/useSelectedChannelState.ts
41679
41723
  var import_react113 = require("react");
41680
- var useChannelMembershipState = (channel) => {
41681
- const [membership, setMembership] = (0, import_react113.useState)(
41682
- channel?.state.membership || {}
41683
- );
41684
- const { client } = useChatContext();
41685
- (0, import_react113.useEffect)(() => {
41686
- if (!channel) return;
41687
- const subscriptions = ["member.updated"].map(
41688
- (v) => client.on(v, () => {
41689
- setMembership(channel.state.membership);
41690
- })
41691
- );
41692
- return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
41693
- }, [client, channel]);
41694
- return membership;
41724
+ var import_shim = require("use-sync-external-store/shim");
41725
+ var noop = () => {
41695
41726
  };
41727
+ function useSelectedChannelState({
41728
+ channel,
41729
+ stateChangeEventKeys = ["all"],
41730
+ selector: selector7
41731
+ }) {
41732
+ const subscribe = (0, import_react113.useCallback)(
41733
+ (onStoreChange) => {
41734
+ if (!channel) return noop;
41735
+ const subscriptions = stateChangeEventKeys.map(
41736
+ (et) => channel.on(et, () => {
41737
+ onStoreChange(selector7(channel));
41738
+ })
41739
+ );
41740
+ return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
41741
+ },
41742
+ [channel, selector7, stateChangeEventKeys]
41743
+ );
41744
+ const getSnapshot = (0, import_react113.useCallback)(() => {
41745
+ if (!channel) return void 0;
41746
+ return selector7(channel);
41747
+ }, [channel, selector7]);
41748
+ return (0, import_shim.useSyncExternalStore)(subscribe, getSnapshot);
41749
+ }
41750
+
41751
+ // src/components/ChannelList/hooks/useChannelMembershipState.ts
41752
+ var selector = (c) => c.state.membership;
41753
+ var keys2 = ["member.updated"];
41754
+ function useChannelMembershipState(channel) {
41755
+ return useSelectedChannelState({ channel, selector, stateChangeEventKeys: keys2 });
41756
+ }
41696
41757
 
41697
41758
  // src/components/ChannelPreview/icons.tsx
41698
41759
  var import_react114 = __toESM(require("react"));
@@ -42177,12 +42238,12 @@ var ThreadAdapter = ({ children }) => {
42177
42238
  useActiveThread({ activeThread });
42178
42239
  return /* @__PURE__ */ import_react122.default.createElement(ThreadProvider, { thread: activeThread }, children);
42179
42240
  };
42180
- var selector = ({ unreadThreadCount }) => ({
42241
+ var selector2 = ({ unreadThreadCount }) => ({
42181
42242
  unreadThreadCount
42182
42243
  });
42183
42244
  var ChatViewSelector = () => {
42184
42245
  const { client } = useChatContext();
42185
- const { unreadThreadCount } = useStateStore(client.threads.state, selector);
42246
+ const { unreadThreadCount } = useStateStore(client.threads.state, selector2);
42186
42247
  const { activeChatView, setActiveChatView } = (0, import_react122.useContext)(ChatViewContext);
42187
42248
  return /* @__PURE__ */ import_react122.default.createElement("div", { className: "str-chat__chat-view__selector" }, /* @__PURE__ */ import_react122.default.createElement(
42188
42249
  "button",
@@ -42244,7 +42305,7 @@ var getTitleFromMessage = ({
42244
42305
  var ThreadListItemUI = (props) => {
42245
42306
  const { client } = useChatContext();
42246
42307
  const thread = useThreadListItemContext();
42247
- const selector6 = (0, import_react123.useCallback)(
42308
+ const selector7 = (0, import_react123.useCallback)(
42248
42309
  (nextValue) => ({
42249
42310
  channel: nextValue.channel,
42250
42311
  deletedAt: nextValue.deletedAt,
@@ -42256,7 +42317,7 @@ var ThreadListItemUI = (props) => {
42256
42317
  );
42257
42318
  const { channel, deletedAt, latestReply, ownUnreadMessageCount, parentMessage } = useStateStore(
42258
42319
  thread.state,
42259
- selector6
42320
+ selector7
42260
42321
  );
42261
42322
  const { displayTitle: channelDisplayTitle } = useChannelPreviewInfo({ channel });
42262
42323
  const { activeThread, setActiveThread } = useThreadsViewContext();
@@ -42293,12 +42354,12 @@ var ThreadListEmptyPlaceholder = () => /* @__PURE__ */ import_react125.default.c
42293
42354
 
42294
42355
  // src/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.tsx
42295
42356
  var import_react126 = __toESM(require("react"));
42296
- var selector2 = (nextValue) => ({
42357
+ var selector3 = (nextValue) => ({
42297
42358
  unseenThreadIds: nextValue.unseenThreadIds
42298
42359
  });
42299
42360
  var ThreadListUnseenThreadsBanner = () => {
42300
42361
  const { client } = useChatContext();
42301
- const { unseenThreadIds } = useStateStore(client.threads.state, selector2);
42362
+ const { unseenThreadIds } = useStateStore(client.threads.state, selector3);
42302
42363
  if (!unseenThreadIds.length) return null;
42303
42364
  return /* @__PURE__ */ import_react126.default.createElement("div", { className: "str-chat__unseen-threads-banner" }, unseenThreadIds.length, " unread threads", /* @__PURE__ */ import_react126.default.createElement(
42304
42365
  "button",
@@ -42312,19 +42373,19 @@ var ThreadListUnseenThreadsBanner = () => {
42312
42373
 
42313
42374
  // src/components/Threads/ThreadList/ThreadListLoadingIndicator.tsx
42314
42375
  var import_react127 = __toESM(require("react"));
42315
- var selector3 = (nextValue) => ({
42376
+ var selector4 = (nextValue) => ({
42316
42377
  isLoadingNext: nextValue.pagination.isLoadingNext
42317
42378
  });
42318
42379
  var ThreadListLoadingIndicator = () => {
42319
42380
  const { LoadingIndicator: LoadingIndicator2 = LoadingIndicator } = useComponentContext();
42320
42381
  const { client } = useChatContext();
42321
- const { isLoadingNext } = useStateStore(client.threads.state, selector3);
42382
+ const { isLoadingNext } = useStateStore(client.threads.state, selector4);
42322
42383
  if (!isLoadingNext) return null;
42323
42384
  return /* @__PURE__ */ import_react127.default.createElement("div", { className: "str-chat__thread-list-loading-indicator" }, /* @__PURE__ */ import_react127.default.createElement(LoadingIndicator2, null));
42324
42385
  };
42325
42386
 
42326
42387
  // src/components/Threads/ThreadList/ThreadList.tsx
42327
- var selector4 = (nextValue) => ({ threads: nextValue.threads });
42388
+ var selector5 = (nextValue) => ({ threads: nextValue.threads });
42328
42389
  var computeItemKey = (_, item2) => item2.id;
42329
42390
  var useThreadList = () => {
42330
42391
  const { client } = useChatContext();
@@ -42353,7 +42414,7 @@ var ThreadList = ({ virtuosoProps }) => {
42353
42414
  ThreadListLoadingIndicator: ThreadListLoadingIndicator2 = ThreadListLoadingIndicator,
42354
42415
  ThreadListUnseenThreadsBanner: ThreadListUnseenThreadsBanner2 = ThreadListUnseenThreadsBanner
42355
42416
  } = useComponentContext();
42356
- const { threads } = useStateStore(client.threads.state, selector4);
42417
+ const { threads } = useStateStore(client.threads.state, selector5);
42357
42418
  useThreadList();
42358
42419
  return /* @__PURE__ */ import_react128.default.createElement("div", { className: "str-chat__thread-list-container" }, /* @__PURE__ */ import_react128.default.createElement(ThreadListUnseenThreadsBanner2, null), /* @__PURE__ */ import_react128.default.createElement(
42359
42420
  import_react_virtuoso.Virtuoso,
@@ -46571,7 +46632,7 @@ var UnMemoizedChatAutoComplete = (props) => {
46571
46632
  closeCommandsList: messageInput.closeCommandsList,
46572
46633
  closeMentionsList: messageInput.closeMentionsList,
46573
46634
  containerClassName: "str-chat__textarea str-chat__message-textarea-react-host",
46574
- disabled: disabled || !!cooldownRemaining,
46635
+ disabled: (props.disabled ?? disabled) || !!cooldownRemaining,
46575
46636
  disableMentions: messageInput.disableMentions,
46576
46637
  grow: messageInput.grow,
46577
46638
  handleSubmit: props.handleSubmit || messageInput.handleSubmit,
@@ -47819,6 +47880,21 @@ var hasNotMoreMessages = (returnedCountMessages, limit) => returnedCountMessages
47819
47880
  function isDateSeparatorMessage(message) {
47820
47881
  return message.customType === CUSTOM_MESSAGE_TYPE.date && !!message.date && isDate(message.date);
47821
47882
  }
47883
+ var getIsFirstUnreadMessage = ({
47884
+ firstUnreadMessageId,
47885
+ isFirstMessage,
47886
+ lastReadDate,
47887
+ lastReadMessageId,
47888
+ message,
47889
+ previousMessage,
47890
+ unreadMessageCount = 0
47891
+ }) => {
47892
+ const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
47893
+ const lastReadTimestamp = lastReadDate?.getTime();
47894
+ const messageIsUnread = !!createdAtTimestamp && !!lastReadTimestamp && createdAtTimestamp > lastReadTimestamp;
47895
+ const previousMessageIsLastRead = !!lastReadMessageId && lastReadMessageId === previousMessage?.id;
47896
+ return firstUnreadMessageId === message.id || !!unreadMessageCount && messageIsUnread && (isFirstMessage || previousMessageIsLastRead);
47897
+ };
47822
47898
 
47823
47899
  // src/components/MessageList/hooks/MessageList/useEnrichedMessages.ts
47824
47900
  var useEnrichedMessages = (args) => {
@@ -48175,7 +48251,6 @@ var useMarkRead = ({
48175
48251
  if (shouldMarkRead(channel.countUnread())) markRead();
48176
48252
  };
48177
48253
  const handleMessageNew = (event) => {
48178
- const newMessageToCurrentChannel = event.cid === channel.cid;
48179
48254
  const isOwnMessage = event.user?.id && event.user.id === client.user?.id;
48180
48255
  const mainChannelUpdated = !event.message?.parent_id || event.message?.show_in_channel;
48181
48256
  if (isOwnMessage) return;
@@ -48193,17 +48268,17 @@ var useMarkRead = ({
48193
48268
  unread_messages: previousUnreadCount + 1
48194
48269
  };
48195
48270
  });
48196
- } else if (newMessageToCurrentChannel && mainChannelUpdated && shouldMarkRead(channel.countUnread())) {
48271
+ } else if (mainChannelUpdated && shouldMarkRead(channel.countUnread())) {
48197
48272
  markRead();
48198
48273
  }
48199
48274
  };
48200
- client.on("message.new", handleMessageNew);
48275
+ channel.on("message.new", handleMessageNew);
48201
48276
  document.addEventListener("visibilitychange", onVisibilityChange);
48202
48277
  const hasScrolledToBottom = previousRenderMessageListScrolledToBottom.current !== isMessageListScrolledToBottom && isMessageListScrolledToBottom;
48203
48278
  if (hasScrolledToBottom && shouldMarkRead(channel.countUnread())) markRead();
48204
48279
  previousRenderMessageListScrolledToBottom.current = isMessageListScrolledToBottom;
48205
48280
  return () => {
48206
- client.off("message.new", handleMessageNew);
48281
+ channel.off("message.new", handleMessageNew);
48207
48282
  document.removeEventListener("visibilitychange", onVisibilityChange);
48208
48283
  };
48209
48284
  }, [
@@ -48638,6 +48713,7 @@ function defaultRenderMessages({
48638
48713
  } = components;
48639
48714
  const renderedMessages = [];
48640
48715
  let firstMessage;
48716
+ let previousMessage = void 0;
48641
48717
  for (let index3 = 0; index3 < messages.length; index3++) {
48642
48718
  const message = messages[index3];
48643
48719
  if (isDateSeparatorMessage(message)) {
@@ -48665,16 +48741,17 @@ function defaultRenderMessages({
48665
48741
  }
48666
48742
  const groupStyles = messageGroupStyles[message.id] || "";
48667
48743
  const messageClass = customClasses?.message || `str-chat__li str-chat__li--${groupStyles}`;
48668
- const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
48669
- const lastReadTimestamp = channelUnreadUiState?.last_read.getTime();
48670
- const isFirstMessage = firstMessage?.id && firstMessage.id === message.id;
48671
- const isNewestMessage = index3 === messages.length - 1;
48672
- const isLastReadMessage = channelUnreadUiState?.last_read_message_id === message.id || !channelUnreadUiState?.unread_messages && createdAtTimestamp === lastReadTimestamp;
48673
- const isFirstUnreadMessage = channelUnreadUiState?.first_unread_message_id === message.id || !!channelUnreadUiState?.unread_messages && !!createdAtTimestamp && !!lastReadTimestamp && createdAtTimestamp > lastReadTimestamp && isFirstMessage;
48674
- const showUnreadSeparatorAbove = !channelUnreadUiState?.last_read_message_id && isFirstUnreadMessage;
48675
- const showUnreadSeparatorBelow = isLastReadMessage && !isNewestMessage && (channelUnreadUiState?.first_unread_message_id || !!channelUnreadUiState?.unread_messages);
48744
+ const isFirstUnreadMessage = getIsFirstUnreadMessage({
48745
+ firstUnreadMessageId: channelUnreadUiState?.first_unread_message_id,
48746
+ isFirstMessage: !!firstMessage?.id && firstMessage.id === message.id,
48747
+ lastReadDate: channelUnreadUiState?.last_read,
48748
+ lastReadMessageId: channelUnreadUiState?.last_read_message_id,
48749
+ message,
48750
+ previousMessage,
48751
+ unreadMessageCount: channelUnreadUiState?.unread_messages
48752
+ });
48676
48753
  renderedMessages.push(
48677
- /* @__PURE__ */ import_react246.default.createElement(import_react246.Fragment, { key: message.id || message.created_at }, showUnreadSeparatorAbove && UnreadMessagesSeparator2 && /* @__PURE__ */ import_react246.default.createElement("li", { className: "str-chat__li str-chat__unread-messages-separator-wrapper" }, /* @__PURE__ */ import_react246.default.createElement(UnreadMessagesSeparator2, { unreadCount: channelUnreadUiState?.unread_messages })), /* @__PURE__ */ import_react246.default.createElement("li", { className: messageClass, "data-message-id": message.id, "data-testid": messageClass }, /* @__PURE__ */ import_react246.default.createElement(
48754
+ /* @__PURE__ */ import_react246.default.createElement(import_react246.Fragment, { key: message.id || message.created_at }, isFirstUnreadMessage && UnreadMessagesSeparator2 && /* @__PURE__ */ import_react246.default.createElement("li", { className: "str-chat__li str-chat__unread-messages-separator-wrapper" }, /* @__PURE__ */ import_react246.default.createElement(UnreadMessagesSeparator2, { unreadCount: channelUnreadUiState?.unread_messages })), /* @__PURE__ */ import_react246.default.createElement("li", { className: messageClass, "data-message-id": message.id, "data-testid": messageClass }, /* @__PURE__ */ import_react246.default.createElement(
48678
48755
  Message,
48679
48756
  {
48680
48757
  groupStyles: [groupStyles],
@@ -48683,8 +48760,9 @@ function defaultRenderMessages({
48683
48760
  readBy: readData[message.id] || [],
48684
48761
  ...messageProps
48685
48762
  }
48686
- )), showUnreadSeparatorBelow && UnreadMessagesSeparator2 && /* @__PURE__ */ import_react246.default.createElement("li", { className: "str-chat__li str-chat__unread-messages-separator-wrapper" }, /* @__PURE__ */ import_react246.default.createElement(UnreadMessagesSeparator2, { unreadCount: channelUnreadUiState?.unread_messages })))
48763
+ )))
48687
48764
  );
48765
+ previousMessage = message;
48688
48766
  }
48689
48767
  }
48690
48768
  return renderedMessages;
@@ -49284,15 +49362,16 @@ var messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
49284
49362
  const maybeNextMessage = messageList[streamMessageIndex + 1];
49285
49363
  const firstOfGroup = shouldGroupByUser && (message.user?.id !== maybePrevMessage?.user?.id || maybePrevMessage && isMessageEdited(maybePrevMessage));
49286
49364
  const endOfGroup = shouldGroupByUser && (message.user?.id !== maybeNextMessage?.user?.id || isMessageEdited(message));
49287
- const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
49288
- const lastReadTimestamp = lastReadDate?.getTime();
49289
- const isFirstMessage = streamMessageIndex === 0;
49290
- const isNewestMessage = lastReadMessageId === lastReceivedMessageId;
49291
- const isLastReadMessage = message.id === lastReadMessageId || !unreadMessageCount && createdAtTimestamp === lastReadTimestamp;
49292
- const isFirstUnreadMessage = firstUnreadMessageId === message.id || !!unreadMessageCount && createdAtTimestamp && lastReadTimestamp && createdAtTimestamp > lastReadTimestamp && isFirstMessage;
49293
- const showUnreadSeparatorAbove = !lastReadMessageId && isFirstUnreadMessage;
49294
- const showUnreadSeparatorBelow = isLastReadMessage && !isNewestMessage && (firstUnreadMessageId || !!unreadMessageCount);
49295
- return /* @__PURE__ */ import_react256.default.createElement(import_react256.default.Fragment, null, showUnreadSeparatorAbove && /* @__PURE__ */ import_react256.default.createElement("div", { className: "str-chat__unread-messages-separator-wrapper" }, /* @__PURE__ */ import_react256.default.createElement(UnreadMessagesSeparator2, { unreadCount: unreadMessageCount })), /* @__PURE__ */ import_react256.default.createElement(
49365
+ const isFirstUnreadMessage = getIsFirstUnreadMessage({
49366
+ firstUnreadMessageId,
49367
+ isFirstMessage: streamMessageIndex === 0,
49368
+ lastReadDate,
49369
+ lastReadMessageId,
49370
+ message,
49371
+ previousMessage: streamMessageIndex ? messageList[streamMessageIndex - 1] : void 0,
49372
+ unreadMessageCount
49373
+ });
49374
+ return /* @__PURE__ */ import_react256.default.createElement(import_react256.default.Fragment, null, isFirstUnreadMessage && /* @__PURE__ */ import_react256.default.createElement("div", { className: "str-chat__unread-messages-separator-wrapper" }, /* @__PURE__ */ import_react256.default.createElement(UnreadMessagesSeparator2, { unreadCount: unreadMessageCount })), /* @__PURE__ */ import_react256.default.createElement(
49296
49375
  Message,
49297
49376
  {
49298
49377
  additionalMessageInputProps,
@@ -49315,7 +49394,7 @@ var messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
49315
49394
  sortReactions,
49316
49395
  threadList
49317
49396
  }
49318
- ), showUnreadSeparatorBelow && /* @__PURE__ */ import_react256.default.createElement("div", { className: "str-chat__unread-messages-separator-wrapper" }, /* @__PURE__ */ import_react256.default.createElement(UnreadMessagesSeparator2, { unreadCount: unreadMessageCount })));
49397
+ ));
49319
49398
  };
49320
49399
 
49321
49400
  // src/components/MessageList/VirtualizedMessageList.tsx
@@ -50792,7 +50871,7 @@ var useChat = ({
50792
50871
  if (!client) return;
50793
50872
  const userAgent = client.getUserAgent();
50794
50873
  if (!userAgent.includes("stream-chat-react")) {
50795
- client.setUserAgent(`stream-chat-react-12.8.1-${userAgent}`);
50874
+ client.setUserAgent(`stream-chat-react-12.9.0-${userAgent}`);
50796
50875
  }
50797
50876
  client.threads.registerSubscriptions();
50798
50877
  client.polls.registerSubscriptions();
@@ -51082,7 +51161,7 @@ var Thread = (props) => {
51082
51161
  /* @__PURE__ */ import_react270.default.createElement(ThreadInner, { ...props, key: `thread-${(thread ?? threadInstance)?.id}-${channel?.cid}` })
51083
51162
  );
51084
51163
  };
51085
- var selector5 = (nextValue) => ({
51164
+ var selector6 = (nextValue) => ({
51086
51165
  isLoadingNext: nextValue.pagination.isLoadingNext,
51087
51166
  isLoadingPrev: nextValue.pagination.isLoadingPrev,
51088
51167
  parentMessage: nextValue.parentMessage,
@@ -51102,7 +51181,7 @@ var ThreadInner = (props) => {
51102
51181
  virtualized
51103
51182
  } = props;
51104
51183
  const threadInstance = useThreadContext();
51105
- const { isLoadingNext, isLoadingPrev, parentMessage, replies } = useStateStore(threadInstance?.state, selector5) ?? {};
51184
+ const { isLoadingNext, isLoadingPrev, parentMessage, replies } = useStateStore(threadInstance?.state, selector6) ?? {};
51106
51185
  const {
51107
51186
  thread,
51108
51187
  threadHasMore,