diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js
index a8bbce10dc..69a0abd90e 100644
--- a/src/HtmlUtils.js
+++ b/src/HtmlUtils.js
@@ -51,6 +51,7 @@ const ZWJ_REGEX = new RegExp("\u200D|\u2003", "g");
const WHITESPACE_REGEX = new RegExp("\\s", "g");
const BIGEMOJI_REGEX = new RegExp(`^(${EMOJIBASE_REGEX.source})+$`, 'i');
+const SINGLE_EMOJI_REGEX = new RegExp(`^(${EMOJIBASE_REGEX.source})$`, 'i');
const COLOR_REGEX = /^#[0-9a-fA-F]{6}$/;
@@ -63,10 +64,19 @@ const PERMITTED_URL_SCHEMES = ['http', 'https', 'ftp', 'mailto', 'magnet'];
* need emojification.
* unicodeToImage uses this function.
*/
-export function containsEmoji(str) {
+export function mayContainEmoji(str) {
return SURROGATE_PAIR_PATTERN.test(str) || SYMBOL_PATTERN.test(str);
}
+/**
+ * Returns true if the string definitely contains a single emoji.
+ * @param {String} str String to test
+ * @return {Boolean}
+ */
+export function isSingleEmoji(str) {
+ return mayContainEmoji(str) && SINGLE_EMOJI_REGEX.test(str);
+}
+
/**
* Returns the shortcode for an emoji character.
*
@@ -428,7 +438,7 @@ export function bodyToHtml(content, highlights, opts={}) {
if (opts.stripReplyFallback && formattedBody) formattedBody = ReplyThread.stripHTMLReply(formattedBody);
strippedBody = opts.stripReplyFallback ? ReplyThread.stripPlainReply(content.body) : content.body;
- bodyHasEmoji = containsEmoji(isHtmlMessage ? formattedBody : content.body);
+ bodyHasEmoji = mayContainEmoji(isHtmlMessage ? formattedBody : content.body);
// Only generate safeBody if the message was sent as org.matrix.custom.html
if (isHtmlMessage) {
diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js
index b14eed88da..51f62807a5 100644
--- a/src/components/views/messages/ReactionsRow.js
+++ b/src/components/views/messages/ReactionsRow.js
@@ -19,6 +19,7 @@ import PropTypes from 'prop-types';
import sdk from '../../../index';
import { isContentActionable } from '../../../utils/EventUtils';
+import { isSingleEmoji } from '../../../HtmlUtils';
import MatrixClientPeg from '../../../MatrixClientPeg';
export default class ReactionsRow extends React.PureComponent {
@@ -103,6 +104,9 @@ export default class ReactionsRow extends React.PureComponent {
const ReactionsRowButton = sdk.getComponent('messages.ReactionsRowButton');
const items = reactions.getSortedAnnotationsByKey().map(([content, events]) => {
+ if (!isSingleEmoji(content)) {
+ return null;
+ }
const count = events.size;
if (!count) {
return null;