From 033c26ab538691da38f4ff65445d356f03d38459 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Mon, 28 Nov 2022 16:01:49 +0100 Subject: [PATCH] Fix edit a reply in rich text editor (#9615) Fix edit a reply in rich text editor --- .../wysiwyg_composer/EditWysiwygComposer.tsx | 4 +- .../wysiwyg_composer/hooks/useEditing.ts | 4 +- .../hooks/useInitialContent.ts | 8 ++- .../EditWysiwygComposer-test.tsx | 67 ++++++++++++++++--- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx index c03e87c526..0ea4ed3204 100644 --- a/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx @@ -44,9 +44,9 @@ interface EditWysiwygComposerProps { export function EditWysiwygComposer({ editorStateTransfer, className, ...props }: EditWysiwygComposerProps) { const initialContent = useInitialContent(editorStateTransfer); - const isReady = !editorStateTransfer || Boolean(initialContent); + const isReady = !editorStateTransfer || initialContent !== undefined; - const { editMessage, endEditing, onChange, isSaveDisabled } = useEditing(initialContent, editorStateTransfer); + const { editMessage, endEditing, onChange, isSaveDisabled } = useEditing(editorStateTransfer, initialContent); return isReady && - editMessage(content, { roomContext, mxClient, editorStateTransfer }), + content !== undefined && editMessage(content, { roomContext, mxClient, editorStateTransfer }), [content, roomContext, mxClient, editorStateTransfer], ); diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useInitialContent.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useInitialContent.ts index 331ea1b6c3..6372703ed5 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useInitialContent.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useInitialContent.ts @@ -24,6 +24,10 @@ import { CommandPartCreator, Part } from "../../../../../editor/parts"; import SettingsStore from "../../../../../settings/SettingsStore"; import EditorStateTransfer from "../../../../../utils/EditorStateTransfer"; +function getFormattedContent(editorStateTransfer: EditorStateTransfer): string { + return editorStateTransfer.getEvent().getContent().formatted_body?.replace(/.*<\/mx-reply>/, '') || ''; +} + function parseEditorStateTransfer( editorStateTransfer: EditorStateTransfer, room: Room, @@ -42,7 +46,7 @@ function parseEditorStateTransfer( // const restoredParts = this.restoreStoredEditorState(partCreator); if (editorStateTransfer.getEvent().getContent().format === 'org.matrix.custom.html') { - return editorStateTransfer.getEvent().getContent().formatted_body || ""; + return getFormattedContent(editorStateTransfer); } parts = parseEvent(editorStateTransfer.getEvent(), partCreator, { @@ -59,7 +63,7 @@ export function useInitialContent(editorStateTransfer: EditorStateTransfer) { const roomContext = useRoomContext(); const mxClient = useMatrixClientContext(); - return useMemo(() => { + return useMemo(() => { if (editorStateTransfer && roomContext.room) { return parseEditorStateTransfer(editorStateTransfer, roomContext.room, mxClient); } diff --git a/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx b/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx index ddb691460b..d177561f05 100644 --- a/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx +++ b/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx @@ -16,7 +16,7 @@ limitations under the License. import "@testing-library/jest-dom"; import React from "react"; -import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { act, fireEvent, render, screen, waitFor } from "@testing-library/react"; import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext"; import RoomContext from "../../../../../src/contexts/RoomContext"; @@ -96,6 +96,53 @@ describe('EditWysiwygComposer', () => { await waitFor(() => expect(screen.getByRole('textbox')).toContainHTML(mockEvent.getContent()['body'])); }); + + it('Should ignore when formatted_body is not filled', async () => { + // When + const mockEvent = mkEvent({ + type: "m.room.message", + room: 'myfakeroom', + user: 'myfakeuser', + content: { + "msgtype": "m.text", + "body": "Replying to this", + "format": "org.matrix.custom.html", + }, + event: true, + }); + + const editorStateTransfer = new EditorStateTransfer(mockEvent); + customRender(false, editorStateTransfer); + + // Then + await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true")); + }); + + it('Should strip tag from initial content', async () => { + // When + const mockEvent = mkEvent({ + type: "m.room.message", + room: 'myfakeroom', + user: 'myfakeuser', + content: { + "msgtype": "m.text", + "body": "Replying to this", + "format": "org.matrix.custom.html", + "formatted_body": 'ReplyMy content', + }, + event: true, + }); + + const editorStateTransfer = new EditorStateTransfer(mockEvent); + customRender(false, editorStateTransfer); + await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true")); + + // Then + await waitFor(() => { + expect(screen.getByRole('textbox')).not.toContainHTML("Reply"); + expect(screen.getByRole('textbox')).toContainHTML("My content"); + }); + }); }); describe('Edit and save actions', () => { @@ -180,14 +227,16 @@ describe('EditWysiwygComposer', () => { expect(screen.getByRole('textbox')).not.toHaveFocus(); // When we send an action that would cause us to get focus - defaultDispatcher.dispatch({ - action: Action.FocusEditMessageComposer, - context: null, - }); - // (Send a second event to exercise the clearTimeout logic) - defaultDispatcher.dispatch({ - action: Action.FocusEditMessageComposer, - context: null, + act(() => { + defaultDispatcher.dispatch({ + action: Action.FocusEditMessageComposer, + context: null, + }); + // (Send a second event to exercise the clearTimeout logic) + defaultDispatcher.dispatch({ + action: Action.FocusEditMessageComposer, + context: null, + }); }); // Wait for event dispatch to happen