diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 9d9e3a1ba0..f19b5903df 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -51,6 +51,7 @@ import {replaceableComponent} from "../../../utils/replaceableComponent"; // matches emoticons which follow the start of a line or whitespace const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$'); +export const REGEX_EMOTICON = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')$'); const IS_MAC = navigator.platform.indexOf("Mac") !== -1; @@ -150,7 +151,7 @@ export default class BasicMessageEditor extends React.Component } } - private replaceEmoticon = (caretPosition: DocumentPosition) => { + public replaceEmoticon(caretPosition: DocumentPosition, regex: RegExp) { const {model} = this.props; const range = model.startRange(caretPosition); // expand range max 8 characters backwards from caretPosition, @@ -161,7 +162,7 @@ export default class BasicMessageEditor extends React.Component n -= 1; return n >= 0 && (part.type === "plain" || part.type === "pill-candidate"); }); - const emoticonMatch = REGEX_EMOTICON_WHITESPACE.exec(range.text); + const emoticonMatch = regex.exec(range.text); if (emoticonMatch) { const query = emoticonMatch[1].replace("-", ""); // try both exact match and lower-case, this means that xd won't match xD but :P will match :p @@ -180,7 +181,7 @@ export default class BasicMessageEditor extends React.Component return range.replace([partCreator.plain(data.unicode + " ")]); } } - }; + } private updateEditorState = (selection: Caret, inputType?: string, diff?: IDiff) => { renderModel(this.editorRef.current, this.props.model); @@ -567,8 +568,7 @@ export default class BasicMessageEditor extends React.Component }; private configureEmoticonAutoReplace = () => { - const shouldReplace = SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji'); - this.props.model.setTransformCallback(shouldReplace ? this.replaceEmoticon : null); + this.props.model.setTransformCallback(this.transform); }; private configureShouldShowPillAvatar = () => { @@ -576,6 +576,11 @@ export default class BasicMessageEditor extends React.Component this.setState({ showPillAvatar }); }; + private transform = (documentPosition: DocumentPosition) => { + const shouldReplace = SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji'); + if (shouldReplace) this.replaceEmoticon(documentPosition, REGEX_EMOTICON_WHITESPACE); + } + componentWillUnmount() { document.removeEventListener("selectionchange", this.onSelectionChange); this.editorRef.current.removeEventListener("input", this.onInput, true); diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index a3e841a0e2..703d409b00 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -28,7 +28,7 @@ import { stripPrefix, } from '../../../editor/serialize'; import {CommandPartCreator} from '../../../editor/parts'; -import BasicMessageComposer from "./BasicMessageComposer"; +import BasicMessageComposer, {REGEX_EMOTICON} from "./BasicMessageComposer"; import ReplyThread from "../elements/ReplyThread"; import {parseEvent} from '../../../editor/deserialize'; import {findEditableEvent} from '../../../utils/EventUtils'; @@ -334,6 +334,11 @@ export default class SendMessageComposer extends React.Component { return; } + // Replace emoticon at the end of the message + const caret = this._editorRef.getCaret(); + const position = model.positionForOffset(caret.offset, caret.atNodeEnd); + this._editorRef.replaceEmoticon(position, REGEX_EMOTICON); + const replyToEvent = this.props.replyToEvent; let shouldSend = true; let content;