stream-chat-react 13.7.0 → 13.8.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.
Files changed (31) hide show
  1. package/dist/components/Channel/Channel.d.ts +1 -1
  2. package/dist/components/Channel/Channel.js +2 -0
  3. package/dist/components/ChannelPreview/ChannelPreview.js +13 -2
  4. package/dist/components/Chat/hooks/useChat.js +1 -1
  5. package/dist/components/Message/MessageSimple.js +2 -2
  6. package/dist/components/Message/QuotedMessage.js +3 -1
  7. package/dist/components/Message/hooks/useActionHandler.js +6 -5
  8. package/dist/components/MessageInput/EditMessageForm.d.ts +2 -1
  9. package/dist/components/MessageInput/hooks/useMessageComposer.js +3 -1
  10. package/dist/components/Poll/PollActions/PollActions.js +2 -1
  11. package/dist/components/TextareaComposer/TextareaComposer.js +4 -1
  12. package/dist/context/ComponentContext.d.ts +3 -1
  13. package/dist/experimental/index.browser.cjs +20 -5
  14. package/dist/experimental/index.browser.cjs.map +2 -2
  15. package/dist/experimental/index.node.cjs +20 -5
  16. package/dist/experimental/index.node.cjs.map +2 -2
  17. package/dist/i18n/TranslationBuilder/notifications/NotificationTranslationTopic.js +2 -1
  18. package/dist/i18n/TranslationBuilder/notifications/attachmentUpload.d.ts +1 -0
  19. package/dist/i18n/TranslationBuilder/notifications/attachmentUpload.js +5 -0
  20. package/dist/index.browser.cjs +1267 -1233
  21. package/dist/index.browser.cjs.map +4 -4
  22. package/dist/index.node.cjs +1267 -1233
  23. package/dist/index.node.cjs.map +4 -4
  24. package/dist/plugins/Emojis/index.browser.cjs +4 -1
  25. package/dist/plugins/Emojis/index.browser.cjs.map +2 -2
  26. package/dist/plugins/Emojis/index.node.cjs +4 -1
  27. package/dist/plugins/Emojis/index.node.cjs.map +2 -2
  28. package/dist/types/defaultDataInterfaces.d.ts +2 -0
  29. package/dist/utils/useStableCallback.d.ts +25 -0
  30. package/dist/utils/useStableCallback.js +29 -0
  31. package/package.json +3 -4
@@ -5,7 +5,7 @@ import type { OnMentionAction } from './hooks/useMentionsHandlers';
5
5
  import type { LoadingErrorIndicatorProps } from '../Loading';
6
6
  import type { ComponentContextValue } from '../../context';
7
7
  import type { ChannelUnreadUiState, GiphyVersions, ImageAttachmentSizeHandler, VideoAttachmentSizeHandler } from '../../types/types';
8
- type ChannelPropsForwardedToComponentContext = Pick<ComponentContextValue, 'Attachment' | 'AttachmentPreviewList' | 'AttachmentSelector' | 'AttachmentSelectorInitiationButtonContents' | 'AudioRecorder' | 'AutocompleteSuggestionItem' | 'AutocompleteSuggestionList' | 'Avatar' | 'BaseImage' | 'CooldownTimer' | 'CustomMessageActionsList' | 'DateSeparator' | 'EditMessageInput' | 'EmojiPicker' | 'emojiSearchIndex' | 'EmptyStateIndicator' | 'FileUploadIcon' | 'GiphyPreviewMessage' | 'HeaderComponent' | 'Input' | 'LinkPreviewList' | 'LoadingIndicator' | 'ShareLocationDialog' | 'Message' | 'MessageActions' | 'MessageBouncePrompt' | 'MessageBlocked' | 'MessageDeleted' | 'MessageIsThreadReplyInChannelButtonIndicator' | 'MessageListNotifications' | 'MessageListMainPanel' | 'MessageNotification' | 'MessageOptions' | 'MessageRepliesCountButton' | 'MessageStatus' | 'MessageSystem' | 'MessageTimestamp' | 'Modal' | 'ModalGallery' | 'PinIndicator' | 'PollActions' | 'PollContent' | 'PollCreationDialog' | 'PollHeader' | 'PollOptionSelector' | 'QuotedMessage' | 'QuotedMessagePreview' | 'QuotedPoll' | 'reactionOptions' | 'ReactionSelector' | 'ReactionsList' | 'ReactionsListModal' | 'ReminderNotification' | 'SendButton' | 'SendToChannelCheckbox' | 'StartRecordingAudioButton' | 'TextareaComposer' | 'ThreadHead' | 'ThreadHeader' | 'ThreadStart' | 'Timestamp' | 'TypingIndicator' | 'UnreadMessagesNotification' | 'UnreadMessagesSeparator' | 'VirtualMessage' | 'StopAIGenerationButton' | 'StreamedMessageText'>;
8
+ type ChannelPropsForwardedToComponentContext = Pick<ComponentContextValue, 'Attachment' | 'AttachmentPreviewList' | 'AttachmentSelector' | 'AttachmentSelectorInitiationButtonContents' | 'AudioRecorder' | 'AutocompleteSuggestionItem' | 'AutocompleteSuggestionList' | 'Avatar' | 'BaseImage' | 'CooldownTimer' | 'CustomMessageActionsList' | 'DateSeparator' | 'EditMessageInput' | 'EditMessageModal' | 'EmojiPicker' | 'emojiSearchIndex' | 'EmptyStateIndicator' | 'FileUploadIcon' | 'GiphyPreviewMessage' | 'HeaderComponent' | 'Input' | 'LinkPreviewList' | 'LoadingIndicator' | 'ShareLocationDialog' | 'Message' | 'MessageActions' | 'MessageBouncePrompt' | 'MessageBlocked' | 'MessageDeleted' | 'MessageIsThreadReplyInChannelButtonIndicator' | 'MessageListNotifications' | 'MessageListMainPanel' | 'MessageNotification' | 'MessageOptions' | 'MessageRepliesCountButton' | 'MessageStatus' | 'MessageSystem' | 'MessageTimestamp' | 'Modal' | 'ModalGallery' | 'PinIndicator' | 'PollActions' | 'PollContent' | 'PollCreationDialog' | 'PollHeader' | 'PollOptionSelector' | 'QuotedMessage' | 'QuotedMessagePreview' | 'QuotedPoll' | 'reactionOptions' | 'ReactionSelector' | 'ReactionsList' | 'ReactionsListModal' | 'ReminderNotification' | 'SendButton' | 'SendToChannelCheckbox' | 'StartRecordingAudioButton' | 'TextareaComposer' | 'ThreadHead' | 'ThreadHeader' | 'ThreadStart' | 'Timestamp' | 'TypingIndicator' | 'UnreadMessagesNotification' | 'UnreadMessagesSeparator' | 'VirtualMessage' | 'StopAIGenerationButton' | 'StreamedMessageText'>;
9
9
  export type ChannelProps = ChannelPropsForwardedToComponentContext & {
10
10
  /** Custom handler function that runs when the active channel has unread messages and the app is running on a separate browser tab */
11
11
  activeUnreadHandler?: (unread: number, documentTitle: string) => void;
@@ -724,6 +724,7 @@ const ChannelInner = (props) => {
724
724
  CustomMessageActionsList: props.CustomMessageActionsList,
725
725
  DateSeparator: props.DateSeparator,
726
726
  EditMessageInput: props.EditMessageInput,
727
+ EditMessageModal: props.EditMessageModal,
727
728
  EmojiPicker: props.EmojiPicker,
728
729
  emojiSearchIndex: props.emojiSearchIndex,
729
730
  EmptyStateIndicator: props.EmptyStateIndicator,
@@ -791,6 +792,7 @@ const ChannelInner = (props) => {
791
792
  props.CustomMessageActionsList,
792
793
  props.DateSeparator,
793
794
  props.EditMessageInput,
795
+ props.EditMessageModal,
794
796
  props.EmojiPicker,
795
797
  props.emojiSearchIndex,
796
798
  props.EmptyStateIndicator,
@@ -15,6 +15,7 @@ export const ChannelPreview = (props) => {
15
15
  channel,
16
16
  });
17
17
  const [lastMessage, setLastMessage] = useState(channel.state.messages[channel.state.messages.length - 1]);
18
+ const [latestMessagePreview, setLatestMessagePreview] = useState(() => getLatestMessagePreview(channel, t, userLanguage, isMessageAIGenerated));
18
19
  const [unread, setUnread] = useState(0);
19
20
  const { messageDeliveryStatus } = useMessageDeliveryStatus({
20
21
  channel,
@@ -55,11 +56,13 @@ export const ChannelPreview = (props) => {
55
56
  }, 400), [channel, muted]);
56
57
  useEffect(() => {
57
58
  refreshUnreadCount();
59
+ setLatestMessagePreview(getLatestMessagePreview(channel, t, userLanguage, isMessageAIGenerated));
58
60
  const handleEvent = (event) => {
59
61
  const deletedMessagesInAnotherChannel = event.type === 'user.messages.deleted' && event.cid && event.cid !== channel.cid;
60
62
  if (deletedMessagesInAnotherChannel)
61
63
  return;
62
64
  setLastMessage(channel.state.latestMessages[channel.state.latestMessages.length - 1]);
65
+ setLatestMessagePreview(getLatestMessagePreview(channel, t, userLanguage, isMessageAIGenerated));
63
66
  refreshUnreadCount();
64
67
  };
65
68
  channel.on('message.new', handleEvent);
@@ -76,9 +79,17 @@ export const ChannelPreview = (props) => {
76
79
  channel.off('message.undeleted', handleEvent);
77
80
  channel.off('channel.truncated', handleEvent);
78
81
  };
79
- }, [channel, client, refreshUnreadCount, channelUpdateCount]);
82
+ }, [
83
+ channel,
84
+ client,
85
+ refreshUnreadCount,
86
+ channelUpdateCount,
87
+ getLatestMessagePreview,
88
+ t,
89
+ userLanguage,
90
+ isMessageAIGenerated,
91
+ ]);
80
92
  if (!Preview)
81
93
  return null;
82
- const latestMessagePreview = getLatestMessagePreview(channel, t, userLanguage, isMessageAIGenerated);
83
94
  return (React.createElement(Preview, { ...props, active: isActive, displayImage: displayImage, displayTitle: displayTitle, groupChannelDisplayInfo: groupChannelDisplayInfo, lastMessage: lastMessage, latestMessage: latestMessagePreview, latestMessagePreview: latestMessagePreview, messageDeliveryStatus: messageDeliveryStatus, setActiveChannel: setActiveChannel, unread: unread }));
84
95
  };
@@ -24,7 +24,7 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
24
24
  useEffect(() => {
25
25
  if (!client)
26
26
  return;
27
- const version = "13.7.0";
27
+ const version = "13.8.0";
28
28
  const userAgent = client.getUserAgent();
29
29
  if (!userAgent.includes('stream-chat-react')) {
30
30
  // result looks like: 'stream-chat-react-2.3.2-stream-chat-javascript-client-browser-2.2.2'
@@ -17,7 +17,7 @@ import { useMessageReminder } from './hooks';
17
17
  import { areMessageUIPropsEqual, isMessageBlocked, isMessageBounced, isMessageEdited, messageHasAttachments, messageHasReactions, } from './utils';
18
18
  import { Avatar as DefaultAvatar } from '../Avatar';
19
19
  import { Attachment as DefaultAttachment } from '../Attachment';
20
- import { EditMessageModal } from '../MessageInput';
20
+ import { EditMessageModal as DefaultEditMessageModal } from '../MessageInput';
21
21
  import { Poll } from '../Poll';
22
22
  import { ReactionsList as DefaultReactionList } from '../Reactions';
23
23
  import { MessageBounceModal } from '../MessageBounce/MessageBounceModal';
@@ -32,7 +32,7 @@ const MessageSimpleWithContext = (props) => {
32
32
  const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false);
33
33
  const [isEditedTimestampOpen, setEditedTimestampOpen] = useState(false);
34
34
  const reminder = useMessageReminder(message.id);
35
- const { Attachment = DefaultAttachment, Avatar = DefaultAvatar, MessageOptions = DefaultMessageOptions,
35
+ const { Attachment = DefaultAttachment, Avatar = DefaultAvatar, EditMessageModal = DefaultEditMessageModal, MessageOptions = DefaultMessageOptions,
36
36
  // TODO: remove this "passthrough" in the next
37
37
  // major release and use the new default instead
38
38
  MessageActions = MessageOptions, MessageBlocked = DefaultMessageBlocked, MessageBouncePrompt = DefaultMessageBouncePrompt, MessageDeleted = DefaultMessageDeleted, MessageIsThreadReplyInChannelButtonIndicator = DefaultMessageIsThreadReplyInChannelButtonIndicator, MessageRepliesCountButton = DefaultMessageRepliesCountButton, MessageStatus = DefaultMessageStatus, MessageTimestamp = DefaultMessageTimestamp, ReactionsList = DefaultReactionList, ReminderNotification = DefaultReminderNotification, StreamedMessageText = DefaultStreamedMessageText, PinIndicator, } = useComponentContext('MessageSimple');
@@ -9,12 +9,14 @@ import { useMessageContext } from '../../context/MessageContext';
9
9
  import { useTranslationContext } from '../../context/TranslationContext';
10
10
  import { useChannelActionContext } from '../../context/ChannelActionContext';
11
11
  import { renderText as defaultRenderText } from './renderText';
12
+ import { useActionHandler } from './';
12
13
  export const QuotedMessage = ({ renderText: propsRenderText }) => {
13
14
  const { Attachment = DefaultAttachment, Avatar: ContextAvatar } = useComponentContext('QuotedMessage');
14
15
  const { client } = useChatContext();
15
16
  const { isMyMessage, message, renderText: contextRenderText, } = useMessageContext('QuotedMessage');
16
17
  const { t, userLanguage } = useTranslationContext('QuotedMessage');
17
18
  const { jumpToMessage } = useChannelActionContext('QuotedMessage');
19
+ const actionHandler = useActionHandler(message);
18
20
  const renderText = propsRenderText ?? contextRenderText ?? defaultRenderText;
19
21
  const Avatar = ContextAvatar || DefaultAvatar;
20
22
  const { quoted_message } = message;
@@ -42,5 +44,5 @@ export const QuotedMessage = ({ renderText: propsRenderText }) => {
42
44
  React.createElement("div", { className: 'str-chat__quoted-message-bubble', "data-testid": 'quoted-message-contents' }, poll ? (React.createElement(Poll, { isQuoted: true, poll: poll })) : (React.createElement(React.Fragment, null,
43
45
  quotedMessageAttachment && (React.createElement(Attachment, { attachments: [quotedMessageAttachment], isQuoted: true })),
44
46
  React.createElement("div", { className: 'str-chat__quoted-message-bubble__text', "data-testid": 'quoted-message-text' }, renderedText))))),
45
- message.attachments?.length ? (React.createElement(Attachment, { attachments: message.attachments })) : null));
47
+ message.attachments?.length ? (React.createElement(Attachment, { actionHandler: actionHandler, attachments: message.attachments })) : null));
46
48
  };
@@ -1,18 +1,19 @@
1
1
  import { useChannelActionContext } from '../../../context/ChannelActionContext';
2
2
  import { useChannelStateContext } from '../../../context/ChannelStateContext';
3
+ import { useStableCallback } from '../../../utils/useStableCallback';
3
4
  export const handleActionWarning = `Action handler was called, but it is missing one of its required arguments.
4
5
  Make sure the ChannelAction and ChannelState contexts are properly set and the hook is initialized with a valid message.`;
5
6
  export function useActionHandler(message) {
6
7
  const { removeMessage, updateMessage } = useChannelActionContext('useActionHandler');
7
8
  const { channel } = useChannelStateContext('useActionHandler');
8
- return async (dataOrName, value, event) => {
9
+ return useStableCallback(async (dataOrName, value, event) => {
9
10
  if (event)
10
11
  event.preventDefault();
11
12
  if (!message || !updateMessage || !removeMessage || !channel) {
12
13
  console.warn(handleActionWarning);
13
14
  return;
14
15
  }
15
- const messageID = message.id;
16
+ const messageId = message.id;
16
17
  let formData = {};
17
18
  // deprecated: value&name should be removed in favor of data obj
18
19
  if (typeof dataOrName === 'string') {
@@ -21,8 +22,8 @@ export function useActionHandler(message) {
21
22
  else {
22
23
  formData = { ...dataOrName };
23
24
  }
24
- if (messageID) {
25
- const data = await channel.sendAction(messageID, formData);
25
+ if (messageId) {
26
+ const data = await channel.sendAction(messageId, formData);
26
27
  if (data?.message) {
27
28
  updateMessage(data.message);
28
29
  }
@@ -30,5 +31,5 @@ export function useActionHandler(message) {
30
31
  removeMessage(message);
31
32
  }
32
33
  }
33
- };
34
+ });
34
35
  }
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
2
  import type { MessageUIComponentProps } from '../Message';
3
3
  export declare const EditMessageForm: () => React.JSX.Element;
4
- export declare const EditMessageModal: ({ additionalMessageInputProps, }: Pick<MessageUIComponentProps, 'additionalMessageInputProps'>) => React.JSX.Element;
4
+ export type EditMessageModalProps = Pick<MessageUIComponentProps, 'additionalMessageInputProps'>;
5
+ export declare const EditMessageModal: ({ additionalMessageInputProps, }: EditMessageModalProps) => React.JSX.Element;
@@ -30,8 +30,10 @@ export const useMessageComposer = () => {
30
30
  if (editing && cachedEditedMessage) {
31
31
  const tag = MessageComposer.constructTag(cachedEditedMessage);
32
32
  const cachedComposer = queueCache.get(tag);
33
- if (cachedComposer)
33
+ if (cachedComposer) {
34
+ cachedComposer.editedMessage = cachedEditedMessage;
34
35
  return cachedComposer;
36
+ }
35
37
  return new MessageComposer({
36
38
  client,
37
39
  composition: cachedEditedMessage,
@@ -28,6 +28,7 @@ export const PollActions = ({ AddCommentForm = DefaultAddCommentForm, EndPollDia
28
28
  const { poll } = usePollContext();
29
29
  const { allow_answers, allow_user_suggested_options, answers_count, created_by_id, is_closed, options, ownAnswer, } = useStateStore(poll.state, pollStateSelector);
30
30
  const [modalOpen, setModalOpen] = useState();
31
+ const canCastVote = channelCapabilities['cast-poll-vote'] && !is_closed;
31
32
  const closeModal = useCallback(() => setModalOpen(undefined), []);
32
33
  const onUpdateAnswerClick = useCallback(() => setModalOpen('add-comment'), []);
33
34
  return (React.createElement("div", { className: 'str-chat__poll-actions' },
@@ -35,7 +36,7 @@ export const PollActions = ({ AddCommentForm = DefaultAddCommentForm, EndPollDia
35
36
  count: options.length,
36
37
  }), closeModal: closeModal, modalClassName: COMMON_MODAL_CLASS, modalIsOpen: modalOpen === 'view-all-options', openModal: () => setModalOpen('view-all-options') },
37
38
  React.createElement(PollOptionsFullList, { close: closeModal }))),
38
- !is_closed &&
39
+ canCastVote &&
39
40
  allow_user_suggested_options &&
40
41
  options.length < MAX_POLL_OPTIONS && (React.createElement(PollAction, { buttonText: t('Suggest an option'), closeModal: closeModal, modalClassName: clsx(COMMON_MODAL_CLASS, 'str-chat__suggest-poll-option-modal'), modalIsOpen: modalOpen === 'suggest-option', openModal: () => setModalOpen('suggest-option') },
41
42
  React.createElement(SuggestPollOptionForm, { close: closeModal, messageId: message.id }))),
@@ -110,7 +110,9 @@ export const TextareaComposer = ({ className, closeSuggestionsOnClickOutside, co
110
110
  });
111
111
  }
112
112
  }
113
- else if (shouldSubmit(event) && textareaRef.current) {
113
+ else if (shouldSubmit(event) &&
114
+ textareaRef.current &&
115
+ messageComposer.hasSendableData) {
114
116
  if (event.key === 'Enter') {
115
117
  // prevent adding newline when submitting a message with
116
118
  event.preventDefault();
@@ -120,6 +122,7 @@ export const TextareaComposer = ({ className, closeSuggestionsOnClickOutside, co
120
122
  }, [
121
123
  focusedItemIndex,
122
124
  handleSubmit,
125
+ messageComposer,
123
126
  onKeyDown,
124
127
  shouldSubmit,
125
128
  suggestions,
@@ -1,6 +1,6 @@
1
1
  import type { PropsWithChildren } from 'react';
2
2
  import React from 'react';
3
- import type { AttachmentPreviewListProps, AttachmentProps, AvatarProps, BaseImageProps, ChannelPreviewActionButtonsProps, CooldownTimerProps, CustomMessageActionsListProps, DateSeparatorProps, EmojiSearchIndex, EmptyStateIndicatorProps, EventComponentProps, FixedHeightMessageProps, GiphyPreviewMessageProps, LoadingIndicatorProps, MessageBouncePromptProps, MessageDeletedProps, MessageInputProps, MessageListNotificationsProps, MessageNotificationProps, MessageOptionsProps, MessageProps, MessageRepliesCountButtonProps, MessageStatusProps, MessageTimestampProps, MessageUIComponentProps, ModalGalleryProps, ModalProps, PinIndicatorProps, PollCreationDialogProps, PollOptionSelectorProps, QuotedMessagePreviewProps, ReactionOptions, ReactionSelectorProps, ReactionsListModalProps, ReactionsListProps, RecordingPermissionDeniedNotificationProps, ReminderNotificationProps, SendButtonProps, StartRecordingAudioButtonProps, StreamedMessageTextProps, TextareaComposerProps, ThreadHeaderProps, ThreadListItemProps, ThreadListItemUIProps, TimestampProps, TypingIndicatorProps, UnreadMessagesNotificationProps, UnreadMessagesSeparatorProps } from '../components';
3
+ import type { AttachmentPreviewListProps, AttachmentProps, AvatarProps, BaseImageProps, ChannelPreviewActionButtonsProps, CooldownTimerProps, CustomMessageActionsListProps, DateSeparatorProps, EditMessageModalProps, EmojiSearchIndex, EmptyStateIndicatorProps, EventComponentProps, FixedHeightMessageProps, GiphyPreviewMessageProps, LoadingIndicatorProps, MessageBouncePromptProps, MessageDeletedProps, MessageInputProps, MessageListNotificationsProps, MessageNotificationProps, MessageOptionsProps, MessageProps, MessageRepliesCountButtonProps, MessageStatusProps, MessageTimestampProps, MessageUIComponentProps, ModalGalleryProps, ModalProps, PinIndicatorProps, PollCreationDialogProps, PollOptionSelectorProps, QuotedMessagePreviewProps, ReactionOptions, ReactionSelectorProps, ReactionsListModalProps, ReactionsListProps, RecordingPermissionDeniedNotificationProps, ReminderNotificationProps, SendButtonProps, StartRecordingAudioButtonProps, StreamedMessageTextProps, TextareaComposerProps, ThreadHeaderProps, ThreadListItemProps, ThreadListItemUIProps, TimestampProps, TypingIndicatorProps, UnreadMessagesNotificationProps, UnreadMessagesSeparatorProps } from '../components';
4
4
  import type { SuggestionItemProps, SuggestionListProps } from '../components/TextareaComposer';
5
5
  import type { SearchProps, SearchResultsPresearchProps, SearchSourceResultListProps } from '../experimental';
6
6
  import type { PropsWithChildrenOnly, UnknownType } from '../types/types';
@@ -35,6 +35,8 @@ export type ComponentContextValue = {
35
35
  DateSeparator?: React.ComponentType<DateSeparatorProps>;
36
36
  /** Custom UI component to override default edit message input, defaults to and accepts same props as: [EditMessageForm](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/EditMessageForm.tsx) */
37
37
  EditMessageInput?: React.ComponentType<MessageInputProps>;
38
+ /** Custom UI component to override default EditMessageModal, defaults to and accepts same props as: [EditMessageModal](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/EditMessageForm.tsx) */
39
+ EditMessageModal?: React.ComponentType<EditMessageModalProps>;
38
40
  /** Custom UI component for rendering button with emoji picker in MessageInput */
39
41
  EmojiPicker?: React.ComponentType;
40
42
  /** Mechanism to be used with autocomplete and text replace features of the `MessageInput` component, see [emoji-mart `SearchIndex`](https://github.com/missive/emoji-mart#%EF%B8%8F%EF%B8%8F-headless-search) */
@@ -14668,6 +14668,9 @@ var ChannelPreview = (props) => {
14668
14668
  const [lastMessage, setLastMessage] = (0, import_react35.useState)(
14669
14669
  channel.state.messages[channel.state.messages.length - 1]
14670
14670
  );
14671
+ const [latestMessagePreview, setLatestMessagePreview] = (0, import_react35.useState)(
14672
+ () => getLatestMessagePreview2(channel, t, userLanguage, isMessageAIGenerated)
14673
+ );
14671
14674
  const [unread, setUnread] = (0, import_react35.useState)(0);
14672
14675
  const { messageDeliveryStatus } = useMessageDeliveryStatus({
14673
14676
  channel,
@@ -14706,12 +14709,18 @@ var ChannelPreview = (props) => {
14706
14709
  );
14707
14710
  (0, import_react35.useEffect)(() => {
14708
14711
  refreshUnreadCount();
14712
+ setLatestMessagePreview(
14713
+ getLatestMessagePreview2(channel, t, userLanguage, isMessageAIGenerated)
14714
+ );
14709
14715
  const handleEvent = (event) => {
14710
14716
  const deletedMessagesInAnotherChannel = event.type === "user.messages.deleted" && event.cid && event.cid !== channel.cid;
14711
14717
  if (deletedMessagesInAnotherChannel) return;
14712
14718
  setLastMessage(
14713
14719
  channel.state.latestMessages[channel.state.latestMessages.length - 1]
14714
14720
  );
14721
+ setLatestMessagePreview(
14722
+ getLatestMessagePreview2(channel, t, userLanguage, isMessageAIGenerated)
14723
+ );
14715
14724
  refreshUnreadCount();
14716
14725
  };
14717
14726
  channel.on("message.new", handleEvent);
@@ -14728,14 +14737,17 @@ var ChannelPreview = (props) => {
14728
14737
  channel.off("message.undeleted", handleEvent);
14729
14738
  channel.off("channel.truncated", handleEvent);
14730
14739
  };
14731
- }, [channel, client, refreshUnreadCount, channelUpdateCount]);
14732
- if (!Preview) return null;
14733
- const latestMessagePreview = getLatestMessagePreview2(
14740
+ }, [
14734
14741
  channel,
14742
+ client,
14743
+ refreshUnreadCount,
14744
+ channelUpdateCount,
14745
+ getLatestMessagePreview2,
14735
14746
  t,
14736
14747
  userLanguage,
14737
14748
  isMessageAIGenerated
14738
- );
14749
+ ]);
14750
+ if (!Preview) return null;
14739
14751
  return /* @__PURE__ */ import_react35.default.createElement(
14740
14752
  Preview,
14741
14753
  {
@@ -14779,7 +14791,10 @@ var useMessageComposer = () => {
14779
14791
  if (editing && cachedEditedMessage) {
14780
14792
  const tag = import_stream_chat2.MessageComposer.constructTag(cachedEditedMessage);
14781
14793
  const cachedComposer = queueCache.get(tag);
14782
- if (cachedComposer) return cachedComposer;
14794
+ if (cachedComposer) {
14795
+ cachedComposer.editedMessage = cachedEditedMessage;
14796
+ return cachedComposer;
14797
+ }
14783
14798
  return new import_stream_chat2.MessageComposer({
14784
14799
  client,
14785
14800
  composition: cachedEditedMessage,