From 63dc8a5857a1cdc74367669910027990fed51a43 Mon Sep 17 00:00:00 2001 From: Claire Elford Date: Sat, 7 Sep 2024 18:16:09 +1000 Subject: [PATCH] Fix increasing font size of certain emojis Before this commit, NeoChat has two methods of detecting whether or not a piece of text was an emoji. One is through a regex, and the other is by using the ICU library. The two methods are used in different parts of the code. This commit removes the regex detector and instead uses ICU for all the places where NeoChat needs to figure out whether or not a string is an emoji. This fixes increasing the font size for messages that only consist of emoji when certain emoji are used that the regex did not handle (such as the transgender symbol and transgender flag emojis). (cherry picked from commit f7533a454c383dd8921286924688907ec56d5134) --- src/models/reactionmodel.cpp | 33 ++----------------------------- src/timeline/TextComponent.qml | 14 ++----------- src/utils.cpp | 36 ++++++++++++++++++++++++++++++++++ src/utils.h | 3 +++ 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/models/reactionmodel.cpp b/src/models/reactionmodel.cpp index 6a4260ede..9de34d99d 100644 --- a/src/models/reactionmodel.cpp +++ b/src/models/reactionmodel.cpp @@ -3,15 +3,10 @@ #include "reactionmodel.h" #include "neochatroom.h" +#include "utils.h" #include #include -#ifdef HAVE_ICU -#include -#include -#include -#include -#endif #include @@ -157,30 +152,6 @@ QHash ReactionModel::roleNames() const }; } -bool isEmoji(const QString &text) -{ -#ifdef HAVE_ICU - QTextBoundaryFinder finder(QTextBoundaryFinder::Grapheme, text); - int from = 0; - while (finder.toNextBoundary() != -1) { - auto to = finder.position(); - if (text[from].isSpace()) { - from = to; - continue; - } - - auto first = text.mid(from, to - from).toUcs4()[0]; - if (!u_hasBinaryProperty(first, UCHAR_EMOJI)) { - return false; - } - from = to; - } - return true; -#else - return false; -#endif -} - QString ReactionModel::reactionText(QString text) const { text = text.toHtmlEscaped(); @@ -194,7 +165,7 @@ QString ReactionModel::reactionText(QString text) const .arg(m_room->connection()->makeMediaUrl(QUrl(text)).toString(), QString::number(size)); } - return isEmoji(text) ? QStringLiteral("") + text + QStringLiteral("") : text; + return Utils::isEmoji(text) ? QStringLiteral("") + text + QStringLiteral("") : text; } #include "moc_reactionmodel.cpp" diff --git a/src/timeline/TextComponent.qml b/src/timeline/TextComponent.qml index bcf05f6da..3cb9c7a49 100644 --- a/src/timeline/TextComponent.qml +++ b/src/timeline/TextComponent.qml @@ -25,16 +25,6 @@ TextEdit { */ property bool isReply: false - /** - * @brief Regex for detecting a message with a single emoji. - */ - readonly property var isEmojiRegex: /^()?(\u00a9|\u00ae|[\u20D0-\u2fff]|[\u3190-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])+(<\/span>)?$/ - - /** - * @brief Whether the message is an emoji - */ - readonly property var isEmoji: isEmojiRegex.test(display) - /** * @brief Regex for detecting a message with a spoiler. */ @@ -113,8 +103,8 @@ a{ selectedTextColor: Kirigami.Theme.highlightedTextColor selectionColor: Kirigami.Theme.highlightColor font { - pointSize: !root.isReply && root.isEmoji ? Kirigami.Theme.defaultFont.pointSize * 4 : Kirigami.Theme.defaultFont.pointSize - family: root.isEmoji ? 'emoji' : Kirigami.Theme.defaultFont.family + pointSize: !root.isReply && QmlUtils.isEmoji(display) ? Kirigami.Theme.defaultFont.pointSize * 4 : Kirigami.Theme.defaultFont.pointSize + family: QmlUtils.isEmoji(display) ? 'emoji' : Kirigami.Theme.defaultFont.family } selectByMouse: !Kirigami.Settings.isMobile readOnly: true diff --git a/src/utils.cpp b/src/utils.cpp index 04d775e8e..b35307aed 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -3,12 +3,24 @@ #include "utils.h" +#ifdef HAVE_ICU +#include +#include +#include +#include +#endif + #include #include using namespace Quotient; +bool QmlUtils::isEmoji(const QString &text) +{ + return Utils::isEmoji(text); +} + bool QmlUtils::isValidJson(const QByteArray &json) { return !QJsonDocument::fromJson(json).isNull(); @@ -26,4 +38,28 @@ QColor QmlUtils::getUserColor(qreal hueF) return QColor::fromHslF(hueF, 1, -0.7 * lightness + 0.9, 1); } +bool Utils::isEmoji(const QString &text) +{ +#ifdef HAVE_ICU + QTextBoundaryFinder finder(QTextBoundaryFinder::Grapheme, text); + int from = 0; + while (finder.toNextBoundary() != -1) { + auto to = finder.position(); + if (text[from].isSpace()) { + from = to; + continue; + } + + auto first = text.mid(from, to - from).toUcs4()[0]; + if (!u_hasBinaryProperty(first, UCHAR_EMOJI)) { + return false; + } + from = to; + } + return true; +#else + return false; +#endif +} + #include "moc_utils.cpp" diff --git a/src/utils.h b/src/utils.h index a0d688c26..b3765114f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -30,6 +30,7 @@ public: return _instance; } + Q_INVOKABLE bool isEmoji(const QString &text); Q_INVOKABLE bool isValidJson(const QByteArray &json); Q_INVOKABLE QString escapeString(const QString &string); Q_INVOKABLE QColor getUserColor(qreal hueF); @@ -53,6 +54,8 @@ inline QColor getUserColor(qreal hueF) // https://github.com/quotient-im/libQuotient/wiki/User-color-coding-standard-draft-proposal return QColor::fromHslF(hueF, 1, -0.7 * lightness + 0.9, 1); } + +bool isEmoji(const QString &text); } namespace TextRegex