Fix edit a reply in rich text editor (#9615)

Fix edit a reply in rich text editor
This commit is contained in:
Florian Duros 2022-11-28 16:01:49 +01:00 committed by GitHub
parent b302275289
commit 033c26ab53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 15 deletions

View file

@ -44,9 +44,9 @@ interface EditWysiwygComposerProps {
export function EditWysiwygComposer({ editorStateTransfer, className, ...props }: EditWysiwygComposerProps) { export function EditWysiwygComposer({ editorStateTransfer, className, ...props }: EditWysiwygComposerProps) {
const initialContent = useInitialContent(editorStateTransfer); 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 && <WysiwygComposer return isReady && <WysiwygComposer
className={classNames("mx_EditWysiwygComposer", className)} className={classNames("mx_EditWysiwygComposer", className)}

View file

@ -22,7 +22,7 @@ import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
import { endEditing } from "../utils/editing"; import { endEditing } from "../utils/editing";
import { editMessage } from "../utils/message"; import { editMessage } from "../utils/message";
export function useEditing(initialContent: string, editorStateTransfer: EditorStateTransfer) { export function useEditing(editorStateTransfer: EditorStateTransfer, initialContent?: string) {
const roomContext = useRoomContext(); const roomContext = useRoomContext();
const mxClient = useMatrixClientContext(); const mxClient = useMatrixClientContext();
@ -34,7 +34,7 @@ export function useEditing(initialContent: string, editorStateTransfer: EditorSt
}, [initialContent]); }, [initialContent]);
const editMessageMemoized = useCallback(() => const editMessageMemoized = useCallback(() =>
editMessage(content, { roomContext, mxClient, editorStateTransfer }), content !== undefined && editMessage(content, { roomContext, mxClient, editorStateTransfer }),
[content, roomContext, mxClient, editorStateTransfer], [content, roomContext, mxClient, editorStateTransfer],
); );

View file

@ -24,6 +24,10 @@ import { CommandPartCreator, Part } from "../../../../../editor/parts";
import SettingsStore from "../../../../../settings/SettingsStore"; import SettingsStore from "../../../../../settings/SettingsStore";
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer"; import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
function getFormattedContent(editorStateTransfer: EditorStateTransfer): string {
return editorStateTransfer.getEvent().getContent().formatted_body?.replace(/<mx-reply>.*<\/mx-reply>/, '') || '';
}
function parseEditorStateTransfer( function parseEditorStateTransfer(
editorStateTransfer: EditorStateTransfer, editorStateTransfer: EditorStateTransfer,
room: Room, room: Room,
@ -42,7 +46,7 @@ function parseEditorStateTransfer(
// const restoredParts = this.restoreStoredEditorState(partCreator); // const restoredParts = this.restoreStoredEditorState(partCreator);
if (editorStateTransfer.getEvent().getContent().format === 'org.matrix.custom.html') { if (editorStateTransfer.getEvent().getContent().format === 'org.matrix.custom.html') {
return editorStateTransfer.getEvent().getContent().formatted_body || ""; return getFormattedContent(editorStateTransfer);
} }
parts = parseEvent(editorStateTransfer.getEvent(), partCreator, { parts = parseEvent(editorStateTransfer.getEvent(), partCreator, {
@ -59,7 +63,7 @@ export function useInitialContent(editorStateTransfer: EditorStateTransfer) {
const roomContext = useRoomContext(); const roomContext = useRoomContext();
const mxClient = useMatrixClientContext(); const mxClient = useMatrixClientContext();
return useMemo<string>(() => { return useMemo<string | undefined>(() => {
if (editorStateTransfer && roomContext.room) { if (editorStateTransfer && roomContext.room) {
return parseEditorStateTransfer(editorStateTransfer, roomContext.room, mxClient); return parseEditorStateTransfer(editorStateTransfer, roomContext.room, mxClient);
} }

View file

@ -16,7 +16,7 @@ limitations under the License.
import "@testing-library/jest-dom"; import "@testing-library/jest-dom";
import React from "react"; 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 MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
import RoomContext from "../../../../../src/contexts/RoomContext"; import RoomContext from "../../../../../src/contexts/RoomContext";
@ -96,6 +96,53 @@ describe('EditWysiwygComposer', () => {
await waitFor(() => await waitFor(() =>
expect(screen.getByRole('textbox')).toContainHTML(mockEvent.getContent()['body'])); 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 <mx-reply> 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": '<mx-reply>Reply</mx-reply>My 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("<mx-reply>Reply</mx-reply>");
expect(screen.getByRole('textbox')).toContainHTML("My content");
});
});
}); });
describe('Edit and save actions', () => { describe('Edit and save actions', () => {
@ -180,14 +227,16 @@ describe('EditWysiwygComposer', () => {
expect(screen.getByRole('textbox')).not.toHaveFocus(); expect(screen.getByRole('textbox')).not.toHaveFocus();
// When we send an action that would cause us to get focus // When we send an action that would cause us to get focus
defaultDispatcher.dispatch({ act(() => {
action: Action.FocusEditMessageComposer, defaultDispatcher.dispatch({
context: null, action: Action.FocusEditMessageComposer,
}); context: null,
// (Send a second event to exercise the clearTimeout logic) });
defaultDispatcher.dispatch({ // (Send a second event to exercise the clearTimeout logic)
action: Action.FocusEditMessageComposer, defaultDispatcher.dispatch({
context: null, action: Action.FocusEditMessageComposer,
context: null,
});
}); });
// Wait for event dispatch to happen // Wait for event dispatch to happen