stream-chat-react 12.2.0 → 12.2.1

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.
@@ -7,6 +7,7 @@ import { ChannelSearchProps } from '../ChannelSearch/ChannelSearch';
7
7
  import { EmptyStateIndicatorProps } from '../EmptyStateIndicator';
8
8
  import { LoadMorePaginatorProps } from '../LoadMore/LoadMorePaginator';
9
9
  import type { Channel, ChannelFilters, ChannelOptions, ChannelSort, Event } from 'stream-chat';
10
+ import type { TranslationContextValue } from '../../context/TranslationContext';
10
11
  import type { DefaultStreamChatGenerics, PaginatorProps } from '../../types/types';
11
12
  export type ChannelListProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = {
12
13
  /** Additional props for underlying ChannelSearch component and channel search controller, [available props](https://getstream.io/chat/docs/sdk/react/utility-components/channel_search/#props) */
@@ -32,6 +33,8 @@ export type ChannelListProps<StreamChatGenerics extends DefaultStreamChatGeneric
32
33
  EmptyStateIndicator?: React.ComponentType<EmptyStateIndicatorProps>;
33
34
  /** An object containing channel query filters */
34
35
  filters?: ChannelFilters<StreamChatGenerics>;
36
+ /** Custom function that generates the message preview in ChannelPreview component */
37
+ getLatestMessagePreview?: (channel: Channel<StreamChatGenerics>, t: TranslationContextValue['t'], userLanguage: TranslationContextValue['userLanguage']) => string | JSX.Element;
35
38
  /** Custom UI component to display the container for the queried channels, defaults to and accepts same props as: [ChannelListMessenger](https://github.com/GetStream/stream-chat-react/blob/master/src/components/ChannelList/ChannelListMessenger.tsx) */
36
39
  List?: React.ComponentType<ChannelListMessengerProps<StreamChatGenerics>>;
37
40
  /** Custom UI component to display the loading error indicator, defaults to component that renders null */
@@ -28,7 +28,7 @@ const DEFAULT_FILTERS = {};
28
28
  const DEFAULT_OPTIONS = {};
29
29
  const DEFAULT_SORT = {};
30
30
  const UnMemoizedChannelList = (props) => {
31
- const { additionalChannelSearchProps, Avatar = DefaultAvatar, allowNewMessagesFromUnfilteredChannels, channelRenderFilterFn, ChannelSearch = DefaultChannelSearch, customActiveChannel, customQueryChannels, EmptyStateIndicator = DefaultEmptyStateIndicator, filters, LoadingErrorIndicator = NullComponent, LoadingIndicator = LoadingChannels, List = ChannelListMessenger, lockChannelOrder, onAddedToChannel, onChannelDeleted, onChannelHidden, onChannelTruncated, onChannelUpdated, onChannelVisible, onMessageNew, onMessageNewHandler, onRemovedFromChannel, options, Paginator = LoadMorePaginator, Preview, recoveryThrottleIntervalMs, renderChannels, sendChannelsToList = false, setActiveChannelOnMount = true, showChannelSearch = false, sort = DEFAULT_SORT, watchers = {}, } = props;
31
+ const { additionalChannelSearchProps, Avatar = DefaultAvatar, allowNewMessagesFromUnfilteredChannels, channelRenderFilterFn, ChannelSearch = DefaultChannelSearch, customActiveChannel, customQueryChannels, EmptyStateIndicator = DefaultEmptyStateIndicator, filters, getLatestMessagePreview, LoadingErrorIndicator = NullComponent, LoadingIndicator = LoadingChannels, List = ChannelListMessenger, lockChannelOrder, onAddedToChannel, onChannelDeleted, onChannelHidden, onChannelTruncated, onChannelUpdated, onChannelVisible, onMessageNew, onMessageNewHandler, onRemovedFromChannel, options, Paginator = LoadMorePaginator, Preview, recoveryThrottleIntervalMs, renderChannels, sendChannelsToList = false, setActiveChannelOnMount = true, showChannelSearch = false, sort = DEFAULT_SORT, watchers = {}, } = props;
32
32
  const { channel, channelsQueryState, client, closeMobileNav, customClasses, navOpen = false, setActiveChannel, theme, useImageFlagEmojisOnWindows, } = useChatContext('ChannelList');
33
33
  const channelListRef = useRef(null);
34
34
  const [channelUpdateCount, setChannelUpdateCount] = useState(0);
@@ -119,6 +119,7 @@ const UnMemoizedChannelList = (props) => {
119
119
  channel: item,
120
120
  // forces the update of preview component on channel update
121
121
  channelUpdateCount,
122
+ getLatestMessagePreview,
122
123
  key: item.cid,
123
124
  Preview,
124
125
  setActiveChannel,
@@ -4,6 +4,7 @@ import { MessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
4
4
  import type { Channel } from 'stream-chat';
5
5
  import type { AvatarProps } from '../Avatar/Avatar';
6
6
  import type { StreamMessage } from '../../context/ChannelStateContext';
7
+ import type { TranslationContextValue } from '../../context/TranslationContext';
7
8
  import type { DefaultStreamChatGenerics } from '../../types/types';
8
9
  export type ChannelPreviewUIComponentProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = ChannelPreviewProps<StreamChatGenerics> & {
9
10
  /** If the component's channel is the active (selected) Channel */
@@ -14,8 +15,10 @@ export type ChannelPreviewUIComponentProps<StreamChatGenerics extends DefaultStr
14
15
  displayTitle?: string;
15
16
  /** The last message received in a channel */
16
17
  lastMessage?: StreamMessage<StreamChatGenerics>;
17
- /** Latest message preview to display, will be a string or JSX element supporting markdown. */
18
+ /** @deprecated Use latestMessagePreview prop instead. */
18
19
  latestMessage?: string | JSX.Element;
20
+ /** Latest message preview to display, will be a string or JSX element supporting markdown. */
21
+ latestMessagePreview?: string | JSX.Element;
19
22
  /** Status describing whether own message has been delivered or read by another. If the last message is not an own message, then the status is undefined. */
20
23
  messageDeliveryStatus?: MessageDeliveryStatus;
21
24
  /** Number of unread Messages */
@@ -32,6 +35,8 @@ export type ChannelPreviewProps<StreamChatGenerics extends DefaultStreamChatGene
32
35
  channelUpdateCount?: number;
33
36
  /** Custom class for the channel preview root */
34
37
  className?: string;
38
+ /** Custom function that generates the message preview in ChannelPreview component */
39
+ getLatestMessagePreview?: (channel: Channel<StreamChatGenerics>, t: TranslationContextValue['t'], userLanguage: TranslationContextValue['userLanguage']) => string | JSX.Element;
35
40
  key?: string;
36
41
  /** Custom ChannelPreview click handler function */
37
42
  onSelect?: (event: React.MouseEvent) => void;
@@ -3,12 +3,12 @@ import React, { useEffect, useMemo, useState } from 'react';
3
3
  import { ChannelPreviewMessenger } from './ChannelPreviewMessenger';
4
4
  import { useIsChannelMuted } from './hooks/useIsChannelMuted';
5
5
  import { useChannelPreviewInfo } from './hooks/useChannelPreviewInfo';
6
- import { getLatestMessagePreview } from './utils';
6
+ import { getLatestMessagePreview as defaultGetLatestMessagePreview } from './utils';
7
7
  import { useChatContext } from '../../context/ChatContext';
8
8
  import { useTranslationContext } from '../../context/TranslationContext';
9
9
  import { useMessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
10
10
  export const ChannelPreview = (props) => {
11
- const { channel, Preview = ChannelPreviewMessenger, channelUpdateCount } = props;
11
+ const { channel, Preview = ChannelPreviewMessenger, channelUpdateCount, getLatestMessagePreview = defaultGetLatestMessagePreview, } = props;
12
12
  const { channel: activeChannel, client, setActiveChannel } = useChatContext('ChannelPreview');
13
13
  const { t, userLanguage } = useTranslationContext('ChannelPreview');
14
14
  const { displayImage, displayTitle } = useChannelPreviewInfo({ channel });
@@ -54,23 +54,25 @@ export const ChannelPreview = (props) => {
54
54
  }, 400), [channel, muted]);
55
55
  useEffect(() => {
56
56
  refreshUnreadCount();
57
- const handleEvent = (event) => {
58
- if (event.message)
59
- setLastMessage(event.message);
57
+ const handleEvent = () => {
58
+ setLastMessage(channel.state.latestMessages[channel.state.latestMessages.length - 1]);
60
59
  refreshUnreadCount();
61
60
  };
62
61
  channel.on('message.new', handleEvent);
63
62
  channel.on('message.updated', handleEvent);
64
63
  channel.on('message.deleted', handleEvent);
64
+ channel.on('message.undeleted', handleEvent);
65
+ channel.on('channel.truncated', handleEvent);
65
66
  return () => {
66
67
  channel.off('message.new', handleEvent);
67
68
  channel.off('message.updated', handleEvent);
68
69
  channel.off('message.deleted', handleEvent);
70
+ channel.off('message.undeleted', handleEvent);
71
+ channel.off('channel.truncated', handleEvent);
69
72
  };
70
- // eslint-disable-next-line react-hooks/exhaustive-deps
71
- }, [refreshUnreadCount, channelUpdateCount]);
73
+ }, [channel, refreshUnreadCount, channelUpdateCount]);
72
74
  if (!Preview)
73
75
  return null;
74
- const latestMessage = getLatestMessagePreview(channel, t, userLanguage);
75
- return (React.createElement(Preview, { ...props, active: isActive, displayImage: displayImage, displayTitle: displayTitle, lastMessage: lastMessage, latestMessage: latestMessage, messageDeliveryStatus: messageDeliveryStatus, setActiveChannel: setActiveChannel, unread: unread }));
76
+ const latestMessagePreview = getLatestMessagePreview(channel, t, userLanguage);
77
+ return (React.createElement(Preview, { ...props, active: isActive, displayImage: displayImage, displayTitle: displayTitle, lastMessage: lastMessage, latestMessage: latestMessagePreview, latestMessagePreview: latestMessagePreview, messageDeliveryStatus: messageDeliveryStatus, setActiveChannel: setActiveChannel, unread: unread }));
76
78
  };
@@ -2,7 +2,7 @@ import React, { useRef } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import { Avatar as DefaultAvatar } from '../Avatar';
4
4
  const UnMemoizedChannelPreviewMessenger = (props) => {
5
- const { active, Avatar = DefaultAvatar, channel, className: customClassName = '', displayImage, displayTitle, latestMessage, onSelect: customOnSelectChannel, setActiveChannel, unread, watchers, } = props;
5
+ const { active, Avatar = DefaultAvatar, channel, className: customClassName = '', displayImage, displayTitle, latestMessagePreview, onSelect: customOnSelectChannel, setActiveChannel, unread, watchers, } = props;
6
6
  const channelPreviewButton = useRef(null);
7
7
  const avatarName = displayTitle || channel.state.messages[channel.state.messages.length - 1]?.user?.id;
8
8
  const onSelectChannel = (e) => {
@@ -24,7 +24,7 @@ const UnMemoizedChannelPreviewMessenger = (props) => {
24
24
  React.createElement("div", { className: 'str-chat__channel-preview-messenger--name' },
25
25
  React.createElement("span", null, displayTitle)),
26
26
  !!unread && (React.createElement("div", { className: 'str-chat__channel-preview-unread-badge', "data-testid": 'unread-badge' }, unread))),
27
- React.createElement("div", { className: 'str-chat__channel-preview-messenger--last-message' }, latestMessage))));
27
+ React.createElement("div", { className: 'str-chat__channel-preview-messenger--last-message' }, latestMessagePreview))));
28
28
  };
29
29
  /**
30
30
  * Used as preview component for channel item in [ChannelList](#channellist) component.
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import ReactMarkdown from 'react-markdown';
3
3
  export const renderPreviewText = (text) => React.createElement(ReactMarkdown, { skipHtml: true }, text);
4
4
  export const getLatestMessagePreview = (channel, t, userLanguage = 'en') => {
5
- const latestMessage = channel.state.messages[channel.state.messages.length - 1];
5
+ const latestMessage = channel.state.latestMessages[channel.state.latestMessages.length - 1];
6
6
  const previewTextToRender = latestMessage?.i18n?.[`${userLanguage}_text`] ||
7
7
  latestMessage?.text;
8
8
  if (!latestMessage) {
@@ -12,8 +12,7 @@ export const getLatestMessagePreview = (channel, t, userLanguage = 'en') => {
12
12
  return t('Message deleted');
13
13
  }
14
14
  if (previewTextToRender) {
15
- const renderedText = renderPreviewText(previewTextToRender);
16
- return renderedText;
15
+ return renderPreviewText(previewTextToRender);
17
16
  }
18
17
  if (latestMessage.command) {
19
18
  return `/${latestMessage.command}`;
@@ -39019,7 +39019,7 @@ var UnMemoizedChannelPreviewMessenger = (props) => {
39019
39019
  className: customClassName = "",
39020
39020
  displayImage,
39021
39021
  displayTitle,
39022
- latestMessage,
39022
+ latestMessagePreview,
39023
39023
  onSelect: customOnSelectChannel,
39024
39024
  setActiveChannel,
39025
39025
  unread,
@@ -39061,7 +39061,7 @@ var UnMemoizedChannelPreviewMessenger = (props) => {
39061
39061
  name: avatarName
39062
39062
  }
39063
39063
  )),
39064
- /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-end" }, /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-end-first-row" }, /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-messenger--name" }, /* @__PURE__ */ import_react83.default.createElement("span", null, displayTitle)), !!unread && /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-unread-badge", "data-testid": "unread-badge" }, unread)), /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-messenger--last-message" }, latestMessage))
39064
+ /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-end" }, /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-end-first-row" }, /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-messenger--name" }, /* @__PURE__ */ import_react83.default.createElement("span", null, displayTitle)), !!unread && /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-unread-badge", "data-testid": "unread-badge" }, unread)), /* @__PURE__ */ import_react83.default.createElement("div", { className: "str-chat__channel-preview-messenger--last-message" }, latestMessagePreview))
39065
39065
  );
39066
39066
  };
39067
39067
  var ChannelPreviewMessenger = import_react83.default.memo(
@@ -39088,7 +39088,7 @@ var import_react86 = require("react");
39088
39088
  var import_react85 = __toESM(require("react"));
39089
39089
  var renderPreviewText = (text6) => /* @__PURE__ */ import_react85.default.createElement(ReactMarkdown, { skipHtml: true }, text6);
39090
39090
  var getLatestMessagePreview = (channel, t2, userLanguage = "en") => {
39091
- const latestMessage = channel.state.messages[channel.state.messages.length - 1];
39091
+ const latestMessage = channel.state.latestMessages[channel.state.latestMessages.length - 1];
39092
39092
  const previewTextToRender = latestMessage?.i18n?.[`${userLanguage}_text`] || latestMessage?.text;
39093
39093
  if (!latestMessage) {
39094
39094
  return t2("Nothing yet...");
@@ -39097,8 +39097,7 @@ var getLatestMessagePreview = (channel, t2, userLanguage = "en") => {
39097
39097
  return t2("Message deleted");
39098
39098
  }
39099
39099
  if (previewTextToRender) {
39100
- const renderedText = renderPreviewText(previewTextToRender);
39101
- return renderedText;
39100
+ return renderPreviewText(previewTextToRender);
39102
39101
  }
39103
39102
  if (latestMessage.command) {
39104
39103
  return `/${latestMessage.command}`;
@@ -39206,7 +39205,12 @@ var useMessageDeliveryStatus = ({
39206
39205
 
39207
39206
  // src/components/ChannelPreview/ChannelPreview.tsx
39208
39207
  var ChannelPreview = (props) => {
39209
- const { channel, Preview = ChannelPreviewMessenger, channelUpdateCount } = props;
39208
+ const {
39209
+ channel,
39210
+ Preview = ChannelPreviewMessenger,
39211
+ channelUpdateCount,
39212
+ getLatestMessagePreview: getLatestMessagePreview2 = getLatestMessagePreview
39213
+ } = props;
39210
39214
  const { channel: activeChannel, client, setActiveChannel } = useChatContext(
39211
39215
  "ChannelPreview"
39212
39216
  );
@@ -39253,21 +39257,25 @@ var ChannelPreview = (props) => {
39253
39257
  );
39254
39258
  (0, import_react88.useEffect)(() => {
39255
39259
  refreshUnreadCount();
39256
- const handleEvent = (event) => {
39257
- if (event.message) setLastMessage(event.message);
39260
+ const handleEvent = () => {
39261
+ setLastMessage(channel.state.latestMessages[channel.state.latestMessages.length - 1]);
39258
39262
  refreshUnreadCount();
39259
39263
  };
39260
39264
  channel.on("message.new", handleEvent);
39261
39265
  channel.on("message.updated", handleEvent);
39262
39266
  channel.on("message.deleted", handleEvent);
39267
+ channel.on("message.undeleted", handleEvent);
39268
+ channel.on("channel.truncated", handleEvent);
39263
39269
  return () => {
39264
39270
  channel.off("message.new", handleEvent);
39265
39271
  channel.off("message.updated", handleEvent);
39266
39272
  channel.off("message.deleted", handleEvent);
39273
+ channel.off("message.undeleted", handleEvent);
39274
+ channel.off("channel.truncated", handleEvent);
39267
39275
  };
39268
- }, [refreshUnreadCount, channelUpdateCount]);
39276
+ }, [channel, refreshUnreadCount, channelUpdateCount]);
39269
39277
  if (!Preview) return null;
39270
- const latestMessage = getLatestMessagePreview(channel, t2, userLanguage);
39278
+ const latestMessagePreview = getLatestMessagePreview2(channel, t2, userLanguage);
39271
39279
  return /* @__PURE__ */ import_react88.default.createElement(
39272
39280
  Preview,
39273
39281
  {
@@ -39276,7 +39284,8 @@ var ChannelPreview = (props) => {
39276
39284
  displayImage,
39277
39285
  displayTitle,
39278
39286
  lastMessage,
39279
- latestMessage,
39287
+ latestMessage: latestMessagePreview,
39288
+ latestMessagePreview,
39280
39289
  messageDeliveryStatus,
39281
39290
  setActiveChannel,
39282
39291
  unread
@@ -47272,6 +47281,7 @@ var UnMemoizedChannelList = (props) => {
47272
47281
  customQueryChannels,
47273
47282
  EmptyStateIndicator: EmptyStateIndicator2 = EmptyStateIndicator,
47274
47283
  filters,
47284
+ getLatestMessagePreview: getLatestMessagePreview2,
47275
47285
  LoadingErrorIndicator: LoadingErrorIndicator2 = NullComponent,
47276
47286
  LoadingIndicator: LoadingIndicator2 = LoadingChannels,
47277
47287
  List: List2 = ChannelListMessenger,
@@ -47404,6 +47414,7 @@ var UnMemoizedChannelList = (props) => {
47404
47414
  channel: item2,
47405
47415
  // forces the update of preview component on channel update
47406
47416
  channelUpdateCount,
47417
+ getLatestMessagePreview: getLatestMessagePreview2,
47407
47418
  key: item2.cid,
47408
47419
  Preview,
47409
47420
  setActiveChannel,