From 78d8d22457fd481e4b961e7c65cd5646c1b15557 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 24 Oct 2018 16:46:06 +0100 Subject: [PATCH] Fix emoji replacement in composer * Re-scan the slate document tree on each emoji replacement since doing a replacement will invalidate all the offsets we have. * Reset the emoji regex each time we use it. Fixes https://github.com/vector-im/riot-web/issues/7550 --- .../views/rooms/MessageComposerInput.js | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 04f9299825..604c797fe4 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -573,29 +573,43 @@ export default class MessageComposerInput extends React.Component { } // emojioneify any emoji - editorState.document.getTexts().forEach(node => { - if (node.text !== '' && HtmlUtils.containsEmoji(node.text)) { - let match; - while ((match = EMOJI_REGEX.exec(node.text)) !== null) { - const range = Range.create({ - anchor: { - key: node.key, - offset: match.index, - }, - focus: { - key: node.key, - offset: match.index + match[0].length, - }, - }); - const inline = Inline.create({ - type: 'emoji', - data: { emojiUnicode: match[0] }, - }); - change = change.insertInlineAtRange(range, inline); - editorState = change.value; + while (true) { + let foundEmoji = false; + + for (const node of editorState.document.getTexts()) { + if (node.text !== '' && HtmlUtils.containsEmoji(node.text)) { + let match; + EMOJI_REGEX.lastIndex = 0; + while ((match = EMOJI_REGEX.exec(node.text)) !== null) { + const range = Range.create({ + anchor: { + key: node.key, + offset: match.index, + }, + focus: { + key: node.key, + offset: match.index + match[0].length, + }, + }); + const inline = Inline.create({ + type: 'emoji', + data: { emojiUnicode: match[0] }, + }); + change = change.insertInlineAtRange(range, inline); + editorState = change.value; + + // if we replaced an emoji, start again looking for more + // emoji in the new editor state since doing the replacement + // will change the node structure & offsets so we can't compute + // insertion ranges from node.key / match.index anymore. + foundEmoji = true; + break; + } } } - }); + + if (!foundEmoji) break; + } // work around weird bug where inserting emoji via the macOS // emoji picker can leave the selection stuck in the emoji's