From 78d8d22457fd481e4b961e7c65cd5646c1b15557 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 24 Oct 2018 16:46:06 +0100 Subject: [PATCH 1/3] 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 From 401f6333ed18e0981a0c3fff2936e303d9e1fef3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 25 Oct 2018 14:54:32 +0100 Subject: [PATCH 2/3] Do...while loops are a thing --- src/components/views/rooms/MessageComposerInput.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 604c797fe4..792dcede8a 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -573,7 +573,7 @@ export default class MessageComposerInput extends React.Component { } // emojioneify any emoji - while (true) { + do { let foundEmoji = false; for (const node of editorState.document.getTexts()) { @@ -607,9 +607,7 @@ export default class MessageComposerInput extends React.Component { } } } - - if (!foundEmoji) break; - } + } while (foundEmoji); // work around weird bug where inserting emoji via the macOS // emoji picker can leave the selection stuck in the emoji's From 5e81e5b8b84ff3954bb9b19cffeb80b679cabc44 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 25 Oct 2018 15:07:19 +0100 Subject: [PATCH 3/3] Fix variable scope --- src/components/views/rooms/MessageComposerInput.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 792dcede8a..570cb8a59b 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -573,8 +573,9 @@ export default class MessageComposerInput extends React.Component { } // emojioneify any emoji + let foundEmoji; do { - let foundEmoji = false; + foundEmoji = false; for (const node of editorState.document.getTexts()) { if (node.text !== '' && HtmlUtils.containsEmoji(node.text)) {