diff --git a/res/css/views/rooms/_MessageComposer.pcss b/res/css/views/rooms/_MessageComposer.pcss index 4cddf31084..4d22f60a12 100644 --- a/res/css/views/rooms/_MessageComposer.pcss +++ b/res/css/views/rooms/_MessageComposer.pcss @@ -240,7 +240,7 @@ limitations under the License. */ .mx_MessageComposer_wysiwyg { .mx_MessageComposer_e2eIcon.mx_E2EIcon,.mx_MessageComposer_button, .mx_MessageComposer_sendMessage { - margin-top: 22px; + margin-top: 28px; } } @@ -264,6 +264,14 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg'); } +.mx_MessageComposer_plain_text::before { + mask-image: url('$(res)/img/element-icons/room/composer/plain_text.svg'); +} + +.mx_MessageComposer_rich_text::before { + mask-image: url('$(res)/img/element-icons/room/composer/rich_text.svg'); +} + .mx_MessageComposer_location::before { mask-image: url('$(res)/img/element-icons/room/composer/location.svg'); } diff --git a/res/img/element-icons/room/composer/plain_text.svg b/res/img/element-icons/room/composer/plain_text.svg new file mode 100644 index 0000000000..7ff47fe085 --- /dev/null +++ b/res/img/element-icons/room/composer/plain_text.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/res/img/element-icons/room/composer/rich_text.svg b/res/img/element-icons/room/composer/rich_text.svg new file mode 100644 index 0000000000..d2da9d2551 --- /dev/null +++ b/res/img/element-icons/room/composer/rich_text.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index 674635d896..f663f57e9c 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -100,6 +100,8 @@ interface IState { showStickersButton: boolean; showPollsButton: boolean; showVoiceBroadcastButton: boolean; + isWysiwygLabEnabled: boolean; + isRichTextEnabled: boolean; } export class MessageComposer extends React.Component { @@ -117,6 +119,7 @@ export class MessageComposer extends React.Component { public static defaultProps = { compact: false, showVoiceBroadcastButton: false, + isRichTextEnabled: true, }; public constructor(props: IProps) { @@ -133,6 +136,8 @@ export class MessageComposer extends React.Component { showStickersButton: SettingsStore.getValue("MessageComposerInput.showStickersButton"), showPollsButton: SettingsStore.getValue("MessageComposerInput.showPollsButton"), showVoiceBroadcastButton: SettingsStore.getValue(Features.VoiceBroadcast), + isWysiwygLabEnabled: SettingsStore.getValue("feature_wysiwyg_composer"), + isRichTextEnabled: true, }; this.instanceId = instanceCount++; @@ -140,6 +145,7 @@ export class MessageComposer extends React.Component { SettingsStore.monitorSetting("MessageComposerInput.showStickersButton", null); SettingsStore.monitorSetting("MessageComposerInput.showPollsButton", null); SettingsStore.monitorSetting(Features.VoiceBroadcast, null); + SettingsStore.monitorSetting("feature_wysiwyg_composer", null); } private get voiceRecording(): Optional { @@ -220,6 +226,12 @@ export class MessageComposer extends React.Component { } break; } + case "feature_wysiwyg_composer": { + if (this.state.isWysiwygLabEnabled !== settingUpdatedPayload.newValue) { + this.setState({ isWysiwygLabEnabled: Boolean(settingUpdatedPayload.newValue) }); + } + break; + } } } } @@ -318,10 +330,10 @@ export class MessageComposer extends React.Component { this.messageComposerInput.current?.sendMessage(); - const isWysiwygComposerEnabled = SettingsStore.getValue("feature_wysiwyg_composer"); - if (isWysiwygComposerEnabled) { + if (this.state.isWysiwygLabEnabled) { const { permalinkCreator, relation, replyToEvent } = this.props; sendMessage(this.state.composerContent, + this.state.isRichTextEnabled, { mxClient: this.props.mxClient, roomContext: this.context, permalinkCreator, relation, replyToEvent }); dis.dispatch({ action: Action.ClearAndFocusSendMessageComposer }); } @@ -340,6 +352,12 @@ export class MessageComposer extends React.Component { }); }; + private onRichTextToggle = () => { + this.setState(state => ({ + isRichTextEnabled: !state.isRichTextEnabled, + })); + }; + private onVoiceStoreUpdate = () => { this.updateRecordingState(); }; @@ -395,7 +413,6 @@ export class MessageComposer extends React.Component { } public render() { - const isWysiwygComposerEnabled = SettingsStore.getValue("feature_wysiwyg_composer"); const controls = [ this.props.e2eStatus ? : @@ -410,12 +427,13 @@ export class MessageComposer extends React.Component { const canSendMessages = this.context.canSendMessages && !this.context.tombstone; if (canSendMessages) { - if (isWysiwygComposerEnabled) { + if (this.state.isWysiwygLabEnabled) { controls.push( , ); } else { @@ -503,7 +521,7 @@ export class MessageComposer extends React.Component { "mx_MessageComposer": true, "mx_MessageComposer--compact": this.props.compact, "mx_MessageComposer_e2eStatus": this.props.e2eStatus != undefined, - "mx_MessageComposer_wysiwyg": isWysiwygComposerEnabled, + "mx_MessageComposer_wysiwyg": this.state.isWysiwygLabEnabled && this.state.isRichTextEnabled, }); return ( @@ -532,6 +550,9 @@ export class MessageComposer extends React.Component { showLocationButton={!window.electron} showPollsButton={this.state.showPollsButton} showStickersButton={this.showStickersButton} + showComposerModeButton={this.state.isWysiwygLabEnabled} + isComposerModeToggled={this.state.isRichTextEnabled} + onComposerModeClick={this.onRichTextToggle} toggleButtonMenu={this.toggleButtonMenu} showVoiceBroadcastButton={this.state.showVoiceBroadcastButton} onStartVoiceBroadcastClick={() => { diff --git a/src/components/views/rooms/MessageComposerButtons.tsx b/src/components/views/rooms/MessageComposerButtons.tsx index b77bff66a8..8ab4c2570b 100644 --- a/src/components/views/rooms/MessageComposerButtons.tsx +++ b/src/components/views/rooms/MessageComposerButtons.tsx @@ -17,7 +17,7 @@ limitations under the License. import classNames from 'classnames'; import { IEventRelation } from "matrix-js-sdk/src/models/event"; import { M_POLL_START } from "matrix-events-sdk"; -import React, { createContext, ReactElement, useContext, useRef } from 'react'; +import React, { createContext, MouseEventHandler, ReactElement, useContext, useRef } from 'react'; import { Room } from 'matrix-js-sdk/src/models/room'; import { MatrixClient } from 'matrix-js-sdk/src/client'; import { THREAD_RELATION_TYPE } from 'matrix-js-sdk/src/models/thread'; @@ -55,6 +55,9 @@ interface IProps { toggleButtonMenu: () => void; showVoiceBroadcastButton: boolean; onStartVoiceBroadcastClick: () => void; + isComposerModeToggled: boolean; + showComposerModeButton: boolean; + onComposerModeClick: () => void; } type OverflowMenuCloser = () => void; @@ -85,6 +88,8 @@ const MessageComposerButtons: React.FC = (props: IProps) => { } else { mainButtons = [ emojiButton(props), + props.showComposerModeButton && + , uploadButton(), // props passed via UploadButtonContext ]; moreButtons = [ @@ -397,4 +402,21 @@ function showLocationButton( ); } +interface WysiwygToggleButtonProps { + isToggled: boolean; + onClick: MouseEventHandler; +} + +function ComposerModeButton({ isToggled, onClick }: WysiwygToggleButtonProps) { + return ; +} + export default MessageComposerButtons; diff --git a/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx index 2a485d9975..9208e79ac4 100644 --- a/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/SendWysiwygComposer.tsx @@ -15,32 +15,37 @@ limitations under the License. */ import React, { forwardRef, RefObject } from 'react'; -import { FormattingFunctions } from '@matrix-org/matrix-wysiwyg'; import { useWysiwygSendActionHandler } from './hooks/useWysiwygSendActionHandler'; import { WysiwygComposer } from './components/WysiwygComposer'; +import { PlainTextComposer } from './components/PlainTextComposer'; +import { ComposerFunctions } from './types'; -interface SendWysiwygComposerProps { - disabled?: boolean; - onChange: (content: string) => void; - onSend: () => void; -} interface ContentProps { disabled: boolean; - formattingFunctions: FormattingFunctions; + composerFunctions: ComposerFunctions; } const Content = forwardRef( - function Content({ disabled, formattingFunctions: wysiwyg }: ContentProps, forwardRef: RefObject) { - useWysiwygSendActionHandler(disabled, forwardRef, wysiwyg); + function Content({ disabled, composerFunctions }: ContentProps, forwardRef: RefObject) { + useWysiwygSendActionHandler(disabled, forwardRef, composerFunctions); return null; }, ); -export function SendWysiwygComposer(props: SendWysiwygComposerProps) { - return ( - { (ref, wysiwyg) => ( - - ) } - ); +interface SendWysiwygComposerProps { + isRichTextEnabled: boolean; + disabled?: boolean; + onChange: (content: string) => void; + onSend: () => void; +} + +export function SendWysiwygComposer({ isRichTextEnabled, ...props }: SendWysiwygComposerProps) { + const Composer = isRichTextEnabled ? WysiwygComposer : PlainTextComposer; + + return + { (ref, composerFunctions) => ( + + ) } + ; } diff --git a/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx b/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx new file mode 100644 index 0000000000..cf25175755 --- /dev/null +++ b/src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer.tsx @@ -0,0 +1,44 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { MutableRefObject, ReactNode } from 'react'; +import { useComposerFunctions } from '../hooks/useComposerFunctions'; +import { usePlainTextListeners } from '../hooks/usePlainTextListeners'; +import { ComposerFunctions } from '../types'; + +import { Editor } from "./Editor"; + +interface PlainTextComposerProps { + disabled?: boolean; + onChange?: (content: string) => void; + onSend: () => void; + initialContent?: string; + className?: string; + children?: ( + ref: MutableRefObject, + composerFunctions: ComposerFunctions, + ) => ReactNode; +} + +export function PlainTextComposer({ className, disabled, onSend, onChange, children }: PlainTextComposerProps) { + const {ref, onInput, onPaste, onKeyDown} = usePlainTextListeners(onChange, onSend) + const composerFunctions = useComposerFunctions(ref) + + return
+ + {children?.(ref, composerFunctions)} +
; +} diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.tsx b/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.tsx new file mode 100644 index 0000000000..99a89589ee --- /dev/null +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useComposerFunctions.tsx @@ -0,0 +1,27 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { RefObject, useMemo } from "react"; + +export function useComposerFunctions(ref: RefObject) { + return useMemo(() => ({ + clear: () => { + if (ref.current) { + ref.current.innerHTML = ''; + } + }, + }), [ref]); +} diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts index 414b6df45c..06839ab262 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useInputEventProcessor.ts @@ -20,7 +20,7 @@ import { useCallback } from "react"; import { useSettingValue } from "../../../../../hooks/useSettings"; export function useInputEventProcessor(onSend: () => void) { - const isCtrlEnter = useSettingValue("MessageComposerInput.ctrlEnterToSend") as boolean; + const isCtrlEnter = useSettingValue("MessageComposerInput.ctrlEnterToSend"); return useCallback((event: WysiwygInputEvent) => { if (event instanceof ClipboardEvent) { return event; diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.tsx b/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.tsx new file mode 100644 index 0000000000..98d09c12b0 --- /dev/null +++ b/src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners.tsx @@ -0,0 +1,50 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { KeyboardEvent, SyntheticEvent, useCallback, useRef } from "react"; + +import { useInputEventProcessor } from "./useInputEventProcessor"; + +function isDivElement(target: EventTarget): target is HTMLDivElement { + return target instanceof HTMLDivElement; +} + +export function usePlainTextListeners(onChange: (content: string) => void, onSend: () => void) { + const ref = useRef(); + const send = useCallback((() => { + if (ref.current) { + ref.current.innerText = ''; + } + onSend(); + }), [ref, onSend]); + + const inputEventProcessor = useInputEventProcessor(send); + + const onInput = useCallback((event: SyntheticEvent) => { + if (isDivElement(event.target)) { + onChange(event.target.innerText); + } + inputEventProcessor(event.nativeEvent); + }, [onChange, inputEventProcessor]); + + const onKeyDown = useCallback((event: KeyboardEvent) => { + if (event.key === 'Enter') { + send(); + } + }, [send]); + + return { ref, onInput, onPaste: onInput, onKeyDown }; +} diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygSendActionHandler.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygSendActionHandler.ts index b7c18f19c2..49c6302d5b 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygSendActionHandler.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useWysiwygSendActionHandler.ts @@ -15,7 +15,6 @@ limitations under the License. */ import { RefObject, useCallback, useRef } from "react"; -import { FormattingFunctions } from "@matrix-org/matrix-wysiwyg"; import defaultDispatcher from "../../../../../dispatcher/dispatcher"; import { Action } from "../../../../../dispatcher/actions"; @@ -23,11 +22,12 @@ import { ActionPayload } from "../../../../../dispatcher/payloads"; import { TimelineRenderingType, useRoomContext } from "../../../../../contexts/RoomContext"; import { useDispatcher } from "../../../../../hooks/useDispatcher"; import { focusComposer } from "./utils"; +import { ComposerFunctions } from "../types"; export function useWysiwygSendActionHandler( disabled: boolean, composerElement: RefObject, - wysiwyg: FormattingFunctions, + composerFunctions: ComposerFunctions, ) { const roomContext = useRoomContext(); const timeoutId = useRef(); @@ -45,12 +45,12 @@ export function useWysiwygSendActionHandler( focusComposer(composerElement, context, roomContext, timeoutId); break; case Action.ClearAndFocusSendMessageComposer: - wysiwyg.clear(); + composerFunctions.clear(); focusComposer(composerElement, context, roomContext, timeoutId); break; // TODO: case Action.ComposerInsert: - see SendMessageComposer } - }, [disabled, composerElement, wysiwyg, timeoutId, roomContext]); + }, [disabled, composerElement, composerFunctions, timeoutId, roomContext]); useDispatcher(defaultDispatcher, handler); } diff --git a/src/components/views/rooms/wysiwyg_composer/types.ts b/src/components/views/rooms/wysiwyg_composer/types.ts new file mode 100644 index 0000000000..96095abebf --- /dev/null +++ b/src/components/views/rooms/wysiwyg_composer/types.ts @@ -0,0 +1,19 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export type ComposerFunctions = { + clear: () => void; +}; diff --git a/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts b/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts index cc0d2235bf..df42b0062b 100644 --- a/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts +++ b/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts @@ -16,6 +16,8 @@ limitations under the License. import { IContent, IEventRelation, MatrixEvent, MsgType } from "matrix-js-sdk/src/matrix"; +import { htmlSerializeFromMdIfNeeded } from "../../../../../editor/serialize"; +import SettingsStore from "../../../../../settings/SettingsStore"; import { RoomPermalinkCreator } from "../../../../../utils/permalinks/Permalinks"; import { addReplyToMessageContent } from "../../../../../utils/Reply"; @@ -39,6 +41,19 @@ function getHtmlReplyFallback(mxEvent: MatrixEvent): string { return (mxReply && mxReply.outerHTML) || ""; } +function getTextReplyFallback(mxEvent: MatrixEvent): string { + const body = mxEvent.getContent().body; + const lines = body.split("\n").map(l => l.trim()); + if (lines.length > 2 && lines[0].startsWith("> ") && lines[1].length === 0) { + return `${lines[0]}\n\n`; + } + return ""; +} + +function htmlToPlainText(html: string) { + return new DOMParser().parseFromString(html, 'text/html').documentElement.textContent; +} + interface CreateMessageContentParams { relation?: IEventRelation; replyToEvent?: MatrixEvent; @@ -49,6 +64,7 @@ interface CreateMessageContentParams { export function createMessageContent( message: string, + isHTML: boolean, { relation, replyToEvent, permalinkCreator, includeReplyLegacyFallback = true, editedEvent }: CreateMessageContentParams, ): IContent { @@ -56,6 +72,7 @@ export function createMessageContent( const isEditing = Boolean(editedEvent); const isReply = isEditing ? Boolean(editedEvent?.replyEventId) : Boolean(replyToEvent); + const isReplyAndEditing = isEditing && isReply; /*const isEmote = containsEmote(model); if (isEmote) { @@ -67,37 +84,43 @@ export function createMessageContent( model = unescapeMessage(model);*/ // const body = textSerialize(model); - const body = message; + + const body = isHTML && htmlToPlainText(message) || message; + const bodyPrefix = isReplyAndEditing && getTextReplyFallback(editedEvent) || ''; + const formattedBodyPrefix = isReplyAndEditing && getHtmlReplyFallback(editedEvent) || ''; const content: IContent = { // TODO emote - // msgtype: isEmote ? "m.emote" : "m.text", msgtype: MsgType.Text, - body: body, + // TODO when available, use HTML --> Plain text conversion from wysiwyg rust model + body: isEditing ? `${bodyPrefix} * ${body}` : body, }; // TODO markdown support - /*const formattedBody = htmlSerializeIfNeeded(model, { - forceHTML: !!replyToEvent, - useMarkdown: SettingsStore.getValue("MessageComposerInput.useMarkdown"), - });*/ - const formattedBody = message; + const isMarkdownEnabled = SettingsStore.getValue("MessageComposerInput.useMarkdown"); + const formattedBody = + isHTML ? + message : + isMarkdownEnabled ? + htmlSerializeFromMdIfNeeded(message, { forceHTML: isReply }) : + null; if (formattedBody) { content.format = "org.matrix.custom.html"; - - const htmlPrefix = isReply && isEditing ? getHtmlReplyFallback(editedEvent) : ''; - content.formatted_body = isEditing ? `${htmlPrefix} * ${formattedBody}` : formattedBody; + content.formatted_body = isEditing ? `${formattedBodyPrefix} * ${formattedBody}` : formattedBody; } if (isEditing) { content['m.new_content'] = { "msgtype": content.msgtype, "body": body, - "format": "org.matrix.custom.html", - 'formatted_body': formattedBody, }; + + if (formattedBody) { + content['m.new_content'].format = "org.matrix.custom.html"; + content['m.new_content']['formatted_body'] = formattedBody; + } } const newRelation = isEditing ? diff --git a/src/components/views/rooms/wysiwyg_composer/utils/message.ts b/src/components/views/rooms/wysiwyg_composer/utils/message.ts index dbea29c848..d84392c18e 100644 --- a/src/components/views/rooms/wysiwyg_composer/utils/message.ts +++ b/src/components/views/rooms/wysiwyg_composer/utils/message.ts @@ -44,7 +44,8 @@ interface SendMessageParams { } export function sendMessage( - html: string, + message: string, + isHTML: boolean, { roomContext, mxClient, ...params }: SendMessageParams, ) { const { relation, replyToEvent } = params; @@ -76,7 +77,8 @@ export function sendMessage( if (!content) { content = createMessageContent( - html, + message, + isHTML, params, ); } @@ -167,7 +169,7 @@ export function editMessage( const position = this.model.positionForOffset(caret.offset, caret.atNodeEnd); this.editorRef.current?.replaceEmoticon(position, REGEX_EMOTICON); }*/ - const editContent = createMessageContent(html, { editedEvent }); + const editContent = createMessageContent(html, true, { editedEvent }); const newContent = editContent["m.new_content"]; const shouldSend = true; diff --git a/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx b/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx index 72fd52be57..051d25b435 100644 --- a/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx +++ b/test/components/views/rooms/wysiwyg_composer/EditWysiwygComposer-test.tsx @@ -163,7 +163,7 @@ describe('EditWysiwygComposer', () => { // Then const expectedContent = { - "body": mockContent, + "body": ` * ${mockContent}`, "format": "org.matrix.custom.html", "formatted_body": ` * ${mockContent}`, "m.new_content": { diff --git a/test/components/views/rooms/wysiwyg_composer/SendWysiwygComposer-test.tsx b/test/components/views/rooms/wysiwyg_composer/SendWysiwygComposer-test.tsx index 20148b802a..c97e5e9086 100644 --- a/test/components/views/rooms/wysiwyg_composer/SendWysiwygComposer-test.tsx +++ b/test/components/views/rooms/wysiwyg_composer/SendWysiwygComposer-test.tsx @@ -72,7 +72,7 @@ describe('SendWysiwygComposer', () => { return render( - + , ); diff --git a/test/components/views/rooms/wysiwyg_composer/utils/createMessageContent-test.ts b/test/components/views/rooms/wysiwyg_composer/utils/createMessageContent-test.ts index a4335b2bf1..4c7028749c 100644 --- a/test/components/views/rooms/wysiwyg_composer/utils/createMessageContent-test.ts +++ b/test/components/views/rooms/wysiwyg_composer/utils/createMessageContent-test.ts @@ -40,11 +40,11 @@ describe('createMessageContent', () => { it("Should create html message", () => { // When - const content = createMessageContent(message, { permalinkCreator }); + const content = createMessageContent(message, true, { permalinkCreator }); // Then expect(content).toEqual({ - "body": message, + "body": "hello world", "format": "org.matrix.custom.html", "formatted_body": message, "msgtype": "m.text", @@ -53,11 +53,11 @@ describe('createMessageContent', () => { it('Should add reply to message content', () => { // When - const content = createMessageContent(message, { permalinkCreator, replyToEvent: mockEvent }); + const content = createMessageContent(message, true, { permalinkCreator, replyToEvent: mockEvent }); // Then expect(content).toEqual({ - "body": "> Replying to this\n\nhello world", + "body": "> Replying to this\n\nhello world", "format": "org.matrix.custom.html", "formatted_body": "
In reply to" + " myfakeuser"+ @@ -77,11 +77,11 @@ describe('createMessageContent', () => { rel_type: "m.thread", event_id: "myFakeThreadId", }; - const content = createMessageContent(message, { permalinkCreator, relation }); + const content = createMessageContent(message, true, { permalinkCreator, relation }); // Then expect(content).toEqual({ - "body": message, + "body": "hello world", "format": "org.matrix.custom.html", "formatted_body": message, "msgtype": "m.text", @@ -110,16 +110,16 @@ describe('createMessageContent', () => { event: true, }); const content = - createMessageContent(message, { permalinkCreator, editedEvent }); + createMessageContent(message, true, { permalinkCreator, editedEvent }); // Then expect(content).toEqual({ - "body": message, + "body": " * hello world", "format": "org.matrix.custom.html", "formatted_body": ` * ${message}`, "msgtype": "m.text", "m.new_content": { - "body": message, + "body": "hello world", "format": "org.matrix.custom.html", "formatted_body": message, "msgtype": "m.text", diff --git a/test/components/views/rooms/wysiwyg_composer/utils/message-test.ts b/test/components/views/rooms/wysiwyg_composer/utils/message-test.ts index 9d13f28176..0829b19adb 100644 --- a/test/components/views/rooms/wysiwyg_composer/utils/message-test.ts +++ b/test/components/views/rooms/wysiwyg_composer/utils/message-test.ts @@ -65,7 +65,7 @@ describe('message', () => { describe('sendMessage', () => { it('Should not send empty html message', async () => { // When - await sendMessage('', { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }); + await sendMessage('', true, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }); // Then expect(mockClient.sendMessage).toBeCalledTimes(0); @@ -74,11 +74,15 @@ describe('message', () => { it('Should send html message', async () => { // When - await sendMessage(message, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }); + await sendMessage( + message, + true, + { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }, + ); // Then const expectedContent = { - "body": "hello world", + "body": "hello world", "format": "org.matrix.custom.html", "formatted_body": "hello world", "msgtype": "m.text", @@ -97,7 +101,7 @@ describe('message', () => { }); // When - await sendMessage(message, { + await sendMessage(message, true, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator, @@ -112,7 +116,7 @@ describe('message', () => { }); const expectedContent = { - "body": "> My reply\n\nhello world", + "body": "> My reply\n\nhello world", "format": "org.matrix.custom.html", "formatted_body": "
In reply to" + " myfakeuser2" + @@ -130,7 +134,11 @@ describe('message', () => { it('Should scroll to bottom after sending a html message', async () => { // When SettingsStore.setValue("scrollToBottomOnMessageSent", null, SettingLevel.DEVICE, true); - await sendMessage(message, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }); + await sendMessage( + message, + true, + { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }, + ); // Then expect(spyDispatcher).toBeCalledWith( @@ -140,7 +148,11 @@ describe('message', () => { it('Should handle emojis', async () => { // When - await sendMessage('🎉', { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }); + await sendMessage( + '🎉', + false, + { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator }, + ); // Then expect(spyDispatcher).toBeCalledWith( @@ -203,7 +215,7 @@ describe('message', () => { // Then const { msgtype, format } = mockEvent.getContent(); const expectedContent = { - "body": newMessage, + "body": ` * ${newMessage}`, "formatted_body": ` * ${newMessage}`, "m.new_content": { "body": "Replying to this new content",