diff --git a/docusaurus/docs/React/components/contexts/component-context.mdx b/docusaurus/docs/React/components/contexts/component-context.mdx
index dcb67cf42..963a48625 100644
--- a/docusaurus/docs/React/components/contexts/component-context.mdx
+++ b/docusaurus/docs/React/components/contexts/component-context.mdx
@@ -74,8 +74,10 @@ Custom UI component to display a user's avatar.
Custom UI component to display image resp. a fallback in case of load error, in `` element. The default resp. custom (from `ComponentContext`) `BaseImage` component is rendered by:
- - single image attachment in message list
-- - group of image attachments in message list
-- - image uploads preview in message input (composer)
+- - group of image attachments in message
+ list
+- - image
+ uploads preview in message input (composer)
The `BaseImage` component accepts the same props as `` element.
@@ -261,6 +263,14 @@ Custom UI component to display a timestamp on a message.
| --------- | ------------------------------------------------------------------------------- |
| component | |
+### MessageBouncePrompt
+
+Custom UI component for the content of the modal dialog for messages that got bounced by the moderation rules.
+
+| Type | Default |
+| --------- | ------------------------------------------------------------------------------------------- |
+| component | |
+
### ModalGallery
Custom UI component for viewing message's image attachments.
@@ -369,16 +379,16 @@ Custom UI component for the typing indicator.
Custom UI component that indicates a user is viewing unread messages. It disappears once the user scrolls to `UnreadMessagesSeparator`.
-| Type | Default |
-| --------- | ------------------------------------------------------------------------------------- |
+| Type | Default |
+| --------- | ------------------------------------------------------------------------------------------------------- |
| component | |
### UnreadMessagesSeparator
Custom UI component inserted before the first message marked unread.
-| Type | Default |
-| --------- | ------------------------------------------------------------------------------------- |
+| Type | Default |
+| --------- | ------------------------------------------------------------------------------------------------- |
| component | |
### VirtualMessage
diff --git a/docusaurus/docs/React/components/contexts/message-bounce-context.mdx b/docusaurus/docs/React/components/contexts/message-bounce-context.mdx
new file mode 100644
index 000000000..32ced6dcc
--- /dev/null
+++ b/docusaurus/docs/React/components/contexts/message-bounce-context.mdx
@@ -0,0 +1,152 @@
+---
+id: message_bounce_context
+sidebar_position: 11
+title: MessageBounceContext
+---
+
+The `MessageBounceContext` is available inside the modal rendered by the default message component for messages that got bounced by the moderation rules. This context provides callbacks that can be used to deal with the bounced message.
+
+## Basic Usage
+
+In most cases when using the default Message UI component implementation you are not going to deal with the `MessageBounceContext` directly. However if you are customizing the Message UI component, or providing a custom `MessageBouncePrompt`, the callbacks provided by this context come in handy.
+
+Get values from context with our custom hook:
+
+```jsx
+const { message, handleEdit, handleSend, handleDelete } = useMessageBounceContext();
+```
+
+Use these callbacks to implement your custom `MessageBouncePrompt`. Normally this component displays three options: edit the message before sending it again, send the message again without changes (this can be useful if you are using the "Bounce then flag" moderation flow), and delete the message.
+
+```jsx
+import { useMessageBounceContext } from 'stream-chat-react';
+
+function MyCustomMessageBouncePrompt({ onClose }) {
+ const { message, handleEdit, handleSend, handleDelete } = useMessageBounceContext();
+ return (
+ <>
+
Your message is in violation of our community rules.
+
Message id: "{message.id}"
+
+ {/* ... */}
+ >
+ );
+}
+```
+
+Then override the default `MessageBouncePrompt` component with your custom one:
+
+```jsx
+
+
+
+
+
+
+
+
+```
+
+## Usage in a Custom Message UI component
+
+When implementing your own Message component from scratch, you should consider implementing UI for bounced messages, especially if you are using one of the moderation flows with message bouncing ("Bounce", "Bounce then flag", or "Bounce then block").
+
+To do that, first check if the message is bounced:
+
+```jsx
+import { useMessageContext, isMessageBounced } from 'stream-chat-react';
+
+function CustomMessage() {
+ const { message } = useMessageContext();
+ const isBounced = isMessageBounced(message);
+ // ...
+}
+```
+
+Then, display custom UI in case the message is bounced. Don't forget to wrap the UI with the `MessageBounceProvider`, so that it has access to the callbacks used to deal with the bounced message:
+
+```jsx
+import { useMessageContext, isMessageBounced, MessageBounceProvider } from 'stream-chat-react';
+
+function MyCustomMessage() {
+ const { message } = useMessageContext();
+ const isBounced = isMessageBounced(message);
+
+ return (
+
+ {/* ... */}
+
+
+ {isBounced && (
+
+
+
+ )}
+
+ );
+}
+
+function MyCustomMessageBouncePrompt({ onClose }) {
+ const { message, handleEdit, handleSend, handleDelete } = useMessageBounceContext();
+ return (
+ <>
+
+ {/* ... */}
+ >
+ );
+}
+```
+
+It only makes sense to render `MessageBounceProvider` in the context of a bounced message, so you'll see a warning in the browser console if you try to render it for any other type of message.
+
+Implementing a custom Message UI component from scratch is a larger topic, covered by the [Message UI Customization](../../guides/theming/message-ui.mdx) guide.
+
+## Values
+
+### message
+
+The object representing the message that got bounced.
+
+| Type |
+| ------------- |
+| StreamMessage |
+
+### handleEdit
+
+Call this function to switch the bounced message into editing mode.
+
+| Type |
+| ----------------- |
+| ReactEventHandler |
+
+### handleSend
+
+Call this function to try sending the bounced message again without changes.
+
+| Type |
+| ----------------- |
+| ReactEventHandler |
+
+### handleDelete
+
+Call this function to remove the bounced message from the message list.
+
+| Type |
+| ----------------- |
+| ReactEventHandler |
diff --git a/docusaurus/docs/React/components/core-components/channel.mdx b/docusaurus/docs/React/components/core-components/channel.mdx
index e81dea59c..7ad965e09 100644
--- a/docusaurus/docs/React/components/core-components/channel.mdx
+++ b/docusaurus/docs/React/components/core-components/channel.mdx
@@ -474,7 +474,7 @@ export const MessageInput = (props: MessageInputProps) => {
Configuration parameter to mark the active channel as read when mounted (opened). By default, the channel is not marked read on mount.
| Type | Default |
-|---------|---------|
+| ------- | ------- |
| boolean | false |
### Input
@@ -589,6 +589,14 @@ Custom UI component to display a timestamp on a message.
| --------- | ------------------------------------------------------------------------------- |
| component | |
+### MessageBouncePrompt
+
+Custom UI component for the content of the modal dialog for messages that got bounced by the moderation rules.
+
+| Type | Default |
+| --------- | ------------------------------------------------------------------------------------------- |
+| component | |
+
### ModalGallery
Custom UI component for viewing message's image attachments.
@@ -745,17 +753,16 @@ Custom UI component for the typing indicator.
Custom UI component that indicates a user is viewing unread messages. It disappears once the user scrolls to `UnreadMessagesSeparator`.
-| Type | Default |
-| --------- | ------------------------------------------------------------------------------------- |
+| Type | Default |
+| --------- | ------------------------------------------------------------------------------------------------------- |
| component | |
-
### UnreadMessagesSeparator
Custom UI component inserted before the first message marked unread.
-| Type | Default |
-| --------- | ------------------------------------------------------------------------------------- |
+| Type | Default |
+| --------- | ------------------------------------------------------------------------------------------------- |
| component | |
### videoAttachmentSizeHandler
diff --git a/docusaurus/docs/React/components/message-components/ui-components.mdx b/docusaurus/docs/React/components/message-components/ui-components.mdx
index fdff420d0..bc83d5071 100644
--- a/docusaurus/docs/React/components/message-components/ui-components.mdx
+++ b/docusaurus/docs/React/components/message-components/ui-components.mdx
@@ -37,6 +37,9 @@ The following UI components are available for use:
- [`QuotedMessage`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/QuotedMessage.tsx) - shows a quoted
message UI wrapper when the sent message quotes a previous message
+- [`MessageBouncePrompt`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageBounce/MessageBouncePrompt.tsx) -
+ presents options to deal with a message that got bounced by the moderation rules.
+
Besides the above there are also components that render reaction list and reaction selector. You can find more about them in [dedicated chapter](./reactions.mdx).
## MessageActions Props
@@ -415,3 +418,46 @@ The side of the message list to render MML components.
:::note
`QuotedMessage` only consumes context and does not accept any optional props.
:::
+
+## MessageBouncePrompt
+
+This component is rendered in a modal dialog for messages that got bounced by the moderation rules.
+
+### MessageBouncePrompt children
+
+| Type | Default |
+| --------- | ----------------------------------------------------------------------- |
+| ReactNode | Localized string for "This message did not meet our content guidelines" |
+
+Use this prop to easily override the text displayed in the modal dialog for the bounced messages, without fully implementing a custom `MessageBouncePrompt` component:
+
+```jsx
+import { MessageBouncePrompt } from 'stream-react-chat';
+
+function MyCustomMessageBouncePrompt(props) {
+ return My custom text;
+}
+```
+
+Then override the default `MessageBouncePrompt` component with your custom one:
+
+```jsx
+
+
+
+
+
+
+
+
+```
+
+If you need deeper customization, refer to the [`MessageBounceContext`](../contexts/message-bounce-context.mdx) documentation.
+
+### onClose
+
+The Message UI component will pass this callback to close the modal dialog `MessageBouncePrompt` are rendered in.
+
+| Type |
+| ----------------- |
+| ReactEventHandler |
diff --git a/package.json b/package.json
index b13a9ab57..a89ebb129 100644
--- a/package.json
+++ b/package.json
@@ -100,7 +100,7 @@
"emoji-mart": "^5.4.0",
"react": "^18.0.0 || ^17.0.0 || ^16.8.0",
"react-dom": "^18.0.0 || ^17.0.0 || ^16.8.0",
- "stream-chat": "^8.0.0"
+ "stream-chat": "^8.15.0"
},
"peerDependenciesMeta": {
"emoji-mart": {
@@ -144,7 +144,7 @@
"@semantic-release/changelog": "^6.0.2",
"@semantic-release/git": "^10.0.1",
"@stream-io/rollup-plugin-node-builtins": "^2.1.5",
- "@stream-io/stream-chat-css": "^4.6.3",
+ "@stream-io/stream-chat-css": "^4.7.0",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^13.1.1",
"@testing-library/react-hooks": "^8.0.0",
diff --git a/src/components/Channel/Channel.tsx b/src/components/Channel/Channel.tsx
index 7e8cb60b2..58343b661 100644
--- a/src/components/Channel/Channel.tsx
+++ b/src/components/Channel/Channel.tsx
@@ -140,6 +140,8 @@ type ChannelPropsForwardedToComponentContext<
LoadingIndicator?: ComponentContextValue['LoadingIndicator'];
/** Custom UI component to display a message in the standard `MessageList`, defaults to and accepts the same props as: [MessageSimple](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageSimple.tsx) */
Message?: ComponentContextValue['Message'];
+ /** Custom UI component to display the contents of a bounced message modal. Usually it allows to retry, edit, or delete the message. Defaults to and accepts the same props as: [MessageBouncePrompt](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageBounce/MessageBouncePrompt.tsx) */
+ MessageBouncePrompt?: ComponentContextValue['MessageBouncePrompt'];
/** Custom UI component for a deleted message, defaults to and accepts same props as: [MessageDeleted](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageDeleted.tsx) */
MessageDeleted?: ComponentContextValue['MessageDeleted'];
/** Custom UI component that displays message and connection status notifications in the `MessageList`, defaults to and accepts same props as [DefaultMessageListNotifications](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageList/MessageListNotifications.tsx) */
@@ -1112,6 +1114,7 @@ const ChannelInner = <
LinkPreviewList: props.LinkPreviewList,
LoadingIndicator: props.LoadingIndicator,
Message: props.Message || MessageSimple,
+ MessageBouncePrompt: props.MessageBouncePrompt,
MessageDeleted: props.MessageDeleted,
MessageListNotifications: props.MessageListNotifications,
MessageNotification: props.MessageNotification,
diff --git a/src/components/Message/MessageErrorText.tsx b/src/components/Message/MessageErrorText.tsx
new file mode 100644
index 000000000..fd4f7a137
--- /dev/null
+++ b/src/components/Message/MessageErrorText.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+
+import { StreamMessage, useTranslationContext } from '../../context';
+import { DefaultStreamChatGenerics } from '../../types/types';
+import { isMessageBounced } from './utils';
+
+export interface MessageErrorTextProps<
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
+> {
+ message: StreamMessage;
+ theme: string;
+}
+
+export function MessageErrorText<
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
+>({ message, theme }: MessageErrorTextProps) {
+ const { t } = useTranslationContext('MessageText');
+
+ if (message.type === 'error' && !isMessageBounced(message)) {
+ return (
+