stream-chat-react 12.8.2 → 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,
@@ -18085,16 +18086,16 @@ var import_react7 = require("react");
18085
18086
 
18086
18087
  // src/store/hooks/useStateStore.ts
18087
18088
  var import_react6 = require("react");
18088
- function useStateStore(store, selector6) {
18089
+ function useStateStore(store, selector7) {
18089
18090
  const [state, setState] = (0, import_react6.useState)(() => {
18090
18091
  if (!store) return void 0;
18091
- return selector6(store.getLatestValue());
18092
+ return selector7(store.getLatestValue());
18092
18093
  });
18093
18094
  (0, import_react6.useEffect)(() => {
18094
18095
  if (!store) return;
18095
- const unsubscribe = store.subscribeWithSelector(selector6, setState);
18096
+ const unsubscribe = store.subscribeWithSelector(selector7, setState);
18096
18097
  return unsubscribe;
18097
- }, [store, selector6]);
18098
+ }, [store, selector7]);
18098
18099
  return state;
18099
18100
  }
18100
18101
 
@@ -39961,7 +39962,10 @@ var moveChannelUpwards = ({
39961
39962
  const targetChannelExistsWithinList = targetChannelIndex >= 0;
39962
39963
  const targetChannelAlreadyAtTheTop = targetChannelIndex === 0;
39963
39964
  const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
39964
- if (targetChannelAlreadyAtTheTop) return channels;
39965
+ const isTargetChannelPinned = isChannelPinned(channelToMove);
39966
+ if (targetChannelAlreadyAtTheTop || considerPinnedChannels && isTargetChannelPinned) {
39967
+ return channels;
39968
+ }
39965
39969
  const newChannels = [...channels];
39966
39970
  if (targetChannelExistsWithinList) {
39967
39971
  newChannels.splice(targetChannelIndex, 1);
@@ -39978,25 +39982,48 @@ var moveChannelUpwards = ({
39978
39982
  return newChannels;
39979
39983
  };
39980
39984
  var shouldConsiderPinnedChannels = (sort) => {
39981
- if (!sort) return false;
39982
- if (!Array.isArray(sort)) return false;
39983
- const [option] = sort;
39984
- if (!option?.pinned_at) return false;
39985
- 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;
39986
40013
  };
39987
40014
  var shouldConsiderArchivedChannels = (filters) => {
39988
40015
  if (!filters) return false;
39989
- return !filters.archived;
40016
+ return typeof filters.archived === "boolean";
39990
40017
  };
39991
40018
  var isChannelPinned = (channel) => {
39992
40019
  if (!channel) return false;
39993
- const member = channel.state.membership;
39994
- return !!member?.pinned_at;
40020
+ const membership = channel.state.membership;
40021
+ return typeof membership.pinned_at === "string";
39995
40022
  };
39996
40023
  var isChannelArchived = (channel) => {
39997
40024
  if (!channel) return false;
39998
- const member = channel.state.membership;
39999
- return !!member?.archived_at;
40025
+ const membership = channel.state.membership;
40026
+ return typeof membership.archived_at === "string";
40000
40027
  };
40001
40028
 
40002
40029
  // src/components/ChannelList/hooks/usePaginatedChannels.ts
@@ -40859,33 +40886,33 @@ var useChannelListShapeDefaults = () => {
40859
40886
  if (typeof customHandler === "function") {
40860
40887
  return customHandler(setChannels, event);
40861
40888
  }
40862
- setChannels((channels) => {
40863
- 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);
40864
40895
  const targetChannelExistsWithinList = targetChannelIndex >= 0;
40865
- const targetChannel = channels[targetChannelIndex];
40866
40896
  const isTargetChannelPinned = isChannelPinned(targetChannel);
40867
40897
  const isTargetChannelArchived = isChannelArchived(targetChannel);
40868
40898
  const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
40869
40899
  const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
40870
40900
  if (
40871
- // target channel is archived
40872
- isTargetChannelArchived && considerArchivedChannels || // target channel is pinned
40873
- 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
40874
40905
  lockChannelOrder || // target channel is not within the loaded list and loading from cache is disallowed
40875
40906
  !targetChannelExistsWithinList && !allowNewMessagesFromUnfilteredChannels
40876
40907
  ) {
40877
- return channels;
40878
- }
40879
- const channelToMove = channels[targetChannelIndex] ?? (allowNewMessagesFromUnfilteredChannels && event.channel_type ? client.channel(event.channel_type, event.channel_id) : null);
40880
- if (channelToMove) {
40881
- return moveChannelUpwards({
40882
- channels,
40883
- channelToMove,
40884
- channelToMoveIndexWithinChannels: targetChannelIndex,
40885
- sort
40886
- });
40908
+ return currentChannels;
40887
40909
  }
40888
- return channels;
40910
+ return moveChannelUpwards({
40911
+ channels: currentChannels,
40912
+ channelToMove: targetChannel,
40913
+ channelToMoveIndexWithinChannels: targetChannelIndex,
40914
+ sort
40915
+ });
40889
40916
  });
40890
40917
  },
40891
40918
  [client]
@@ -40911,7 +40938,7 @@ var useChannelListShapeDefaults = () => {
40911
40938
  type: event.channel.type
40912
40939
  });
40913
40940
  const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
40914
- if (isChannelArchived(channel) && considerArchivedChannels) {
40941
+ if (isChannelArchived(channel) && considerArchivedChannels && !filters.archived) {
40915
40942
  return;
40916
40943
  }
40917
40944
  if (!allowNewMessagesFromUnfilteredChannels) {
@@ -40933,26 +40960,33 @@ var useChannelListShapeDefaults = () => {
40933
40960
  allowNewMessagesFromUnfilteredChannels,
40934
40961
  customHandler,
40935
40962
  event,
40936
- setChannels
40963
+ setChannels,
40964
+ sort
40937
40965
  }) => {
40938
40966
  if (typeof customHandler === "function") {
40939
40967
  return customHandler(setChannels, event);
40940
40968
  }
40941
- if (allowNewMessagesFromUnfilteredChannels && event.channel?.type) {
40942
- const channel = await getChannel({
40943
- client,
40944
- id: event.channel.id,
40945
- members: event.channel.members?.reduce((acc, { user, user_id }) => {
40946
- const userId = user_id || user?.id;
40947
- if (userId) {
40948
- acc.push(userId);
40949
- }
40950
- return acc;
40951
- }, []),
40952
- type: event.channel.type
40953
- });
40954
- setChannels((channels) => (0, import_lodash11.default)([channel, ...channels], "cid"));
40969
+ if (!event.channel || !allowNewMessagesFromUnfilteredChannels) {
40970
+ return;
40955
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
+ );
40956
40990
  },
40957
40991
  [client]
40958
40992
  );
@@ -40970,29 +41004,37 @@ var useChannelListShapeDefaults = () => {
40970
41004
  []
40971
41005
  );
40972
41006
  const handleMemberUpdated = (0, import_react101.useCallback)(
40973
- ({ event, lockChannelOrder, setChannels, sort }) => {
41007
+ ({
41008
+ event,
41009
+ filters,
41010
+ lockChannelOrder,
41011
+ setChannels,
41012
+ sort
41013
+ }) => {
40974
41014
  if (!event.member?.user || event.member.user.id !== client.userID || !event.channel_type) {
40975
41015
  return;
40976
41016
  }
40977
- const member = event.member;
40978
41017
  const channelType = event.channel_type;
40979
41018
  const channelId = event.channel_id;
40980
41019
  const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
40981
- 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" });
40982
41022
  setChannels((currentChannels) => {
40983
41023
  const targetChannel = client.channel(channelType, channelId);
40984
41024
  const targetChannelIndex = currentChannels.indexOf(targetChannel);
40985
41025
  const targetChannelExistsWithinList = targetChannelIndex >= 0;
41026
+ const isTargetChannelArchived = isChannelArchived(targetChannel);
41027
+ const isTargetChannelPinned = isChannelPinned(targetChannel);
40986
41028
  if (!considerPinnedChannels || lockChannelOrder) return currentChannels;
40987
41029
  const newChannels = [...currentChannels];
40988
41030
  if (targetChannelExistsWithinList) {
40989
41031
  newChannels.splice(targetChannelIndex, 1);
40990
41032
  }
40991
- if (typeof member.archived_at === "string") {
41033
+ if (considerArchivedChannels && isTargetChannelArchived && !filters.archived || considerArchivedChannels && !isTargetChannelArchived && filters.archived) {
40992
41034
  return newChannels;
40993
41035
  }
40994
41036
  let lastPinnedChannelIndex = null;
40995
- if (pinnedAtSort === 1 || pinnedAtSort === -1 && !member.pinned_at) {
41037
+ if (pinnedAtSort === 1 || pinnedAtSort === -1 && !isTargetChannelPinned) {
40996
41038
  lastPinnedChannelIndex = findLastPinnedChannelIndex({ channels: newChannels });
40997
41039
  }
40998
41040
  const newTargetChannelIndex = typeof lastPinnedChannelIndex === "number" ? lastPinnedChannelIndex + 1 : 0;
@@ -41193,6 +41235,7 @@ var usePrepareShapeHandlers = ({
41193
41235
  case "member.updated":
41194
41236
  defaults.handleMemberUpdated({
41195
41237
  event,
41238
+ filters,
41196
41239
  lockChannelOrder,
41197
41240
  setChannels,
41198
41241
  sort
@@ -41676,24 +41719,41 @@ var useUserPresenceChangedListener = (setChannels) => {
41676
41719
  }, [client, setChannels]);
41677
41720
  };
41678
41721
 
41679
- // src/components/ChannelList/hooks/useChannelMembershipState.ts
41722
+ // src/components/ChannelList/hooks/useSelectedChannelState.ts
41680
41723
  var import_react113 = require("react");
41681
- var useChannelMembershipState = (channel) => {
41682
- const [membership, setMembership] = (0, import_react113.useState)(
41683
- channel?.state.membership || {}
41684
- );
41685
- const { client } = useChatContext();
41686
- (0, import_react113.useEffect)(() => {
41687
- if (!channel) return;
41688
- const subscriptions = ["member.updated"].map(
41689
- (v) => client.on(v, () => {
41690
- setMembership(channel.state.membership);
41691
- })
41692
- );
41693
- return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
41694
- }, [client, channel]);
41695
- return membership;
41724
+ var import_shim = require("use-sync-external-store/shim");
41725
+ var noop = () => {
41696
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
+ }
41697
41757
 
41698
41758
  // src/components/ChannelPreview/icons.tsx
41699
41759
  var import_react114 = __toESM(require("react"));
@@ -42178,12 +42238,12 @@ var ThreadAdapter = ({ children }) => {
42178
42238
  useActiveThread({ activeThread });
42179
42239
  return /* @__PURE__ */ import_react122.default.createElement(ThreadProvider, { thread: activeThread }, children);
42180
42240
  };
42181
- var selector = ({ unreadThreadCount }) => ({
42241
+ var selector2 = ({ unreadThreadCount }) => ({
42182
42242
  unreadThreadCount
42183
42243
  });
42184
42244
  var ChatViewSelector = () => {
42185
42245
  const { client } = useChatContext();
42186
- const { unreadThreadCount } = useStateStore(client.threads.state, selector);
42246
+ const { unreadThreadCount } = useStateStore(client.threads.state, selector2);
42187
42247
  const { activeChatView, setActiveChatView } = (0, import_react122.useContext)(ChatViewContext);
42188
42248
  return /* @__PURE__ */ import_react122.default.createElement("div", { className: "str-chat__chat-view__selector" }, /* @__PURE__ */ import_react122.default.createElement(
42189
42249
  "button",
@@ -42245,7 +42305,7 @@ var getTitleFromMessage = ({
42245
42305
  var ThreadListItemUI = (props) => {
42246
42306
  const { client } = useChatContext();
42247
42307
  const thread = useThreadListItemContext();
42248
- const selector6 = (0, import_react123.useCallback)(
42308
+ const selector7 = (0, import_react123.useCallback)(
42249
42309
  (nextValue) => ({
42250
42310
  channel: nextValue.channel,
42251
42311
  deletedAt: nextValue.deletedAt,
@@ -42257,7 +42317,7 @@ var ThreadListItemUI = (props) => {
42257
42317
  );
42258
42318
  const { channel, deletedAt, latestReply, ownUnreadMessageCount, parentMessage } = useStateStore(
42259
42319
  thread.state,
42260
- selector6
42320
+ selector7
42261
42321
  );
42262
42322
  const { displayTitle: channelDisplayTitle } = useChannelPreviewInfo({ channel });
42263
42323
  const { activeThread, setActiveThread } = useThreadsViewContext();
@@ -42294,12 +42354,12 @@ var ThreadListEmptyPlaceholder = () => /* @__PURE__ */ import_react125.default.c
42294
42354
 
42295
42355
  // src/components/Threads/ThreadList/ThreadListUnseenThreadsBanner.tsx
42296
42356
  var import_react126 = __toESM(require("react"));
42297
- var selector2 = (nextValue) => ({
42357
+ var selector3 = (nextValue) => ({
42298
42358
  unseenThreadIds: nextValue.unseenThreadIds
42299
42359
  });
42300
42360
  var ThreadListUnseenThreadsBanner = () => {
42301
42361
  const { client } = useChatContext();
42302
- const { unseenThreadIds } = useStateStore(client.threads.state, selector2);
42362
+ const { unseenThreadIds } = useStateStore(client.threads.state, selector3);
42303
42363
  if (!unseenThreadIds.length) return null;
42304
42364
  return /* @__PURE__ */ import_react126.default.createElement("div", { className: "str-chat__unseen-threads-banner" }, unseenThreadIds.length, " unread threads", /* @__PURE__ */ import_react126.default.createElement(
42305
42365
  "button",
@@ -42313,19 +42373,19 @@ var ThreadListUnseenThreadsBanner = () => {
42313
42373
 
42314
42374
  // src/components/Threads/ThreadList/ThreadListLoadingIndicator.tsx
42315
42375
  var import_react127 = __toESM(require("react"));
42316
- var selector3 = (nextValue) => ({
42376
+ var selector4 = (nextValue) => ({
42317
42377
  isLoadingNext: nextValue.pagination.isLoadingNext
42318
42378
  });
42319
42379
  var ThreadListLoadingIndicator = () => {
42320
42380
  const { LoadingIndicator: LoadingIndicator2 = LoadingIndicator } = useComponentContext();
42321
42381
  const { client } = useChatContext();
42322
- const { isLoadingNext } = useStateStore(client.threads.state, selector3);
42382
+ const { isLoadingNext } = useStateStore(client.threads.state, selector4);
42323
42383
  if (!isLoadingNext) return null;
42324
42384
  return /* @__PURE__ */ import_react127.default.createElement("div", { className: "str-chat__thread-list-loading-indicator" }, /* @__PURE__ */ import_react127.default.createElement(LoadingIndicator2, null));
42325
42385
  };
42326
42386
 
42327
42387
  // src/components/Threads/ThreadList/ThreadList.tsx
42328
- var selector4 = (nextValue) => ({ threads: nextValue.threads });
42388
+ var selector5 = (nextValue) => ({ threads: nextValue.threads });
42329
42389
  var computeItemKey = (_, item2) => item2.id;
42330
42390
  var useThreadList = () => {
42331
42391
  const { client } = useChatContext();
@@ -42354,7 +42414,7 @@ var ThreadList = ({ virtuosoProps }) => {
42354
42414
  ThreadListLoadingIndicator: ThreadListLoadingIndicator2 = ThreadListLoadingIndicator,
42355
42415
  ThreadListUnseenThreadsBanner: ThreadListUnseenThreadsBanner2 = ThreadListUnseenThreadsBanner
42356
42416
  } = useComponentContext();
42357
- const { threads } = useStateStore(client.threads.state, selector4);
42417
+ const { threads } = useStateStore(client.threads.state, selector5);
42358
42418
  useThreadList();
42359
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(
42360
42420
  import_react_virtuoso.Virtuoso,
@@ -46572,7 +46632,7 @@ var UnMemoizedChatAutoComplete = (props) => {
46572
46632
  closeCommandsList: messageInput.closeCommandsList,
46573
46633
  closeMentionsList: messageInput.closeMentionsList,
46574
46634
  containerClassName: "str-chat__textarea str-chat__message-textarea-react-host",
46575
- disabled: disabled || !!cooldownRemaining,
46635
+ disabled: (props.disabled ?? disabled) || !!cooldownRemaining,
46576
46636
  disableMentions: messageInput.disableMentions,
46577
46637
  grow: messageInput.grow,
46578
46638
  handleSubmit: props.handleSubmit || messageInput.handleSubmit,
@@ -50811,7 +50871,7 @@ var useChat = ({
50811
50871
  if (!client) return;
50812
50872
  const userAgent = client.getUserAgent();
50813
50873
  if (!userAgent.includes("stream-chat-react")) {
50814
- client.setUserAgent(`stream-chat-react-12.8.2-${userAgent}`);
50874
+ client.setUserAgent(`stream-chat-react-12.9.0-${userAgent}`);
50815
50875
  }
50816
50876
  client.threads.registerSubscriptions();
50817
50877
  client.polls.registerSubscriptions();
@@ -51101,7 +51161,7 @@ var Thread = (props) => {
51101
51161
  /* @__PURE__ */ import_react270.default.createElement(ThreadInner, { ...props, key: `thread-${(thread ?? threadInstance)?.id}-${channel?.cid}` })
51102
51162
  );
51103
51163
  };
51104
- var selector5 = (nextValue) => ({
51164
+ var selector6 = (nextValue) => ({
51105
51165
  isLoadingNext: nextValue.pagination.isLoadingNext,
51106
51166
  isLoadingPrev: nextValue.pagination.isLoadingPrev,
51107
51167
  parentMessage: nextValue.parentMessage,
@@ -51121,7 +51181,7 @@ var ThreadInner = (props) => {
51121
51181
  virtualized
51122
51182
  } = props;
51123
51183
  const threadInstance = useThreadContext();
51124
- const { isLoadingNext, isLoadingPrev, parentMessage, replies } = useStateStore(threadInstance?.state, selector5) ?? {};
51184
+ const { isLoadingNext, isLoadingPrev, parentMessage, replies } = useStateStore(threadInstance?.state, selector6) ?? {};
51125
51185
  const {
51126
51186
  thread,
51127
51187
  threadHasMore,