From f7533a454c383dd8921286924688907ec56d5134 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). --- 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 6b938ce47..c8832a0bb 100644 --- a/src/models/reactionmodel.cpp +++ b/src/models/reactionmodel.cpp @@ -2,15 +2,10 @@ // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL #include "reactionmodel.h" +#include "utils.h" #include #include -#ifdef HAVE_ICU -#include -#include -#include -#include -#endif #include @@ -154,30 +149,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(); @@ -191,7 +162,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 7e284e2a9..d07007e71 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