diff --git a/docusaurus/docs/React/custom-code-examples/override-submit-handler.mdx b/docusaurus/docs/React/custom-code-examples/override-submit-handler.mdx index a430d1e645..14dbc8a779 100644 --- a/docusaurus/docs/React/custom-code-examples/override-submit-handler.mdx +++ b/docusaurus/docs/React/custom-code-examples/override-submit-handler.mdx @@ -15,6 +15,10 @@ The `MessageInput` component accepts an `overrideSubmitHandler` prop, which allo conclusion of the underlying `textarea` element's [`handleSubmit`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/hooks/useSubmitHandler.ts) function. +:::note +You do not have to implement your custom submit handler, if the only thing you need is to pass custom message data to the underlying API call. In that case you can use the [`handleSubmit`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/hooks/useSubmitHandler.ts) function from the [`MessageInputContext`](../contexts/message-input-context.mdx). The `handleSubmit` function allows you to pass custom message data through its second parameter `customMessageData`. This applies to sending a new message as well as updating an existing one. In order for this to work, you will have to implement custom message input components and pass them to [`Channel`](../core-components/channel.mdx) props `EditMessageInput` or `Input` respectively. +::: + The `overrideSubmitHandler` function receives two arguments, the message to be sent and the `cid` (channel type prepended to channel id) for the currently active channel. The message object is of the following type: diff --git a/package.json b/package.json index bfdbacfdea..d654419108 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "lodash.isequal": "^4.5.0", "lodash.throttle": "^4.1.1", "lodash.uniqby": "^4.7.0", - "mdast-util-find-and-replace": "1.1.1", + "mdast-util-find-and-replace": "^2.2.1", "nanoid": "^3.3.4", "pretty-bytes": "^5.4.1", "prop-types": "^15.7.2", @@ -103,6 +103,7 @@ "@types/lodash.isequal": "^4.5.5", "@types/lodash.throttle": "^4.1.6", "@types/lodash.uniqby": "^4.7.6", + "@types/mdast": "^3.0.10", "@types/moment": "^2.13.0", "@types/react": "^18.0.8", "@types/react-dom": "^18.0.3", @@ -208,7 +209,8 @@ "e2e-container": "./e2e/scripts/run_in_container.sh" }, "resolutions": { - "ast-types": "^0.14.0" + "ast-types": "^0.14.0", + "@types/unist": "^2.0.6" }, "browserslist": [ ">0.2%", diff --git a/src/__tests__/__snapshots__/utils.test.js.snap b/src/__tests__/__snapshots__/utils.test.js.snap new file mode 100644 index 0000000000..8a80dc0894 --- /dev/null +++ b/src/__tests__/__snapshots__/utils.test.js.snap @@ -0,0 +1,142 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renderText handles the special case where user name matches to an e-mail pattern - 1 1`] = ` +
+ Hello + + @username@email.com + + , is + + username@email.com + + your @primary e-mail? +
+`; + +exports[`renderText handles the special case where user name matches to an e-mail pattern - 2 1`] = ` ++ + username@email.com + + + + @username@email.com + + is this the right address? +
+`; + +exports[`renderText handles the special case where user name matches to an e-mail pattern - 3 1`] = ` ++ + @username@email.com + + + + @username@email.com + + + + @username@email.com + + + + @username@email.com + +
+`; + +exports[`renderText handles the special case where user name matches to an e-mail pattern - 4 1`] = ` ++ + @username@email.com + + + + @username@email.com + + + + username@email.com + + + + @username@email.com + +
+`; + +exports[`renderText renders custom mention 1`] = ` ++ + @username@email.com + + + + @username@email.com + + + + username@email.com + + + + @username@email.com + +
+`; + +exports[`renderText renders standard markdown text 1`] = ` ++ Hi, shall we meet on + + Tuesday + + ? +
+`; diff --git a/src/__tests__/utils.test.js b/src/__tests__/utils.test.js new file mode 100644 index 0000000000..2ecf2d43e3 --- /dev/null +++ b/src/__tests__/utils.test.js @@ -0,0 +1,63 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { renderText } from '../utils'; + +describe(`renderText`, () => { + it('handles the special case where user name matches to an e-mail pattern - 1', () => { + const Markdown = renderText( + 'Hello @username@email.com, is username@email.com your @primary e-mail?', + [{ id: 'id-username@email.com', name: 'username@email.com' }], + ); + const tree = renderer.create(Markdown).toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('handles the special case where user name matches to an e-mail pattern - 2', () => { + const Markdown = renderText( + 'username@email.com @username@email.com is this the right address?', + [{ id: 'id-username@email.com', name: 'username@email.com' }], + ); + const tree = renderer.create(Markdown).toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('handles the special case where user name matches to an e-mail pattern - 3', () => { + const Markdown = renderText( + '@username@email.com @username@email.com @username@email.com @username@email.com', + [{ id: 'id-username@email.com', name: 'username@email.com' }], + ); + const tree = renderer.create(Markdown).toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('handles the special case where user name matches to an e-mail pattern - 4', () => { + const Markdown = renderText( + '@username@email.com @username@email.com username@email.com @username@email.com', + [{ id: 'id-username@email.com', name: 'username@email.com' }], + ); + const tree = renderer.create(Markdown).toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('renders custom mention', () => { + const Markdown = renderText( + '@username@email.com @username@email.com username@email.com @username@email.com', + [{ id: 'id-username@email.com', name: 'username@email.com' }], + { + customMarkDownRenderers: { + mention: function MyMention(props) { + return {props.children}; + }, + }, + }, + ); + const tree = renderer.create(Markdown).toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('renders standard markdown text', () => { + const Markdown = renderText('Hi, shall we meet on **Tuesday**?', []); + const tree = renderer.create(Markdown).toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/MessageInput/__tests__/MessageInput.test.js b/src/components/MessageInput/__tests__/MessageInput.test.js index ea448f5de0..4b79245d8e 100644 --- a/src/components/MessageInput/__tests__/MessageInput.test.js +++ b/src/components/MessageInput/__tests__/MessageInput.test.js @@ -15,6 +15,7 @@ import { Channel } from '../../Channel/Channel'; import { MessageActionsBox } from '../../MessageActions'; import { MessageProvider } from '../../../context/MessageContext'; +import { useMessageInputContext } from '../../../context/MessageInputContext'; import { useChatContext } from '../../../context/ChatContext'; import { dispatchMessageDeletedEvent, @@ -664,6 +665,57 @@ function axeNoViolations(container) { await axeNoViolations(container); }); + it('should allow to send custom message data', async () => { + const customMessageData = { customX: 'customX' }; + const CustomInputForm = () => { + const { handleChange, handleSubmit, value } = useMessageInputContext(); + return ( + + ); + }; + + const messageInputProps = + componentName === 'EditMessageForm' + ? { + messageInputProps: { + message: { + text: `abc`, + }, + }, + } + : {}; + + const renderComponent = makeRenderFn(CustomInputForm); + const { container, submit } = await renderComponent(messageInputProps); + + fireEvent.change(await screen.findByPlaceholderText(inputPlaceholder), { + target: { + value: 'Some text', + }, + }); + + await act(() => submit()); + + await waitFor(() => { + const calledMock = componentName === 'EditMessageForm' ? editMock : submitMock; + expect(calledMock).toHaveBeenCalledWith( + expect.stringMatching(/.+:.+/), + expect.objectContaining(customMessageData), + ); + }); + await axeNoViolations(container); + }); + it('Should use overrideSubmitHandler prop if it is defined', async () => { const overrideMock = jest.fn().mockImplementation(() => Promise.resolve()); const customMessageData = undefined; diff --git a/src/components/MessageInput/hooks/useSubmitHandler.ts b/src/components/MessageInput/hooks/useSubmitHandler.ts index f58a2a1754..71913332ba 100644 --- a/src/components/MessageInput/hooks/useSubmitHandler.ts +++ b/src/components/MessageInput/hooks/useSubmitHandler.ts @@ -152,6 +152,7 @@ export const useSubmitHandler = < await editMessage(({ ...message, ...updatedMessage, + ...customMessageData, } as unknown) as UpdatedMessage