diff --git a/autotests/texthandlertest.cpp b/autotests/texthandlertest.cpp index a9ea8592f..523a6f248 100644 --- a/autotests/texthandlertest.cpp +++ b/autotests/texthandlertest.cpp @@ -10,6 +10,8 @@ #include #include +#include "models/customemojimodel.h" +#include "neochatconnection.h" #include "utils.h" using namespace Quotient; @@ -48,6 +50,9 @@ private Q_SLOTS: void sendBadLinks(); void sendEscapeCode(); void sendCodeClass(); + void sendCustomEmoji(); + void sendCustomEmojiCode_data(); + void sendCustomEmojiCode(); void receiveStripReply(); void receivePlainTextIn(); @@ -80,6 +85,14 @@ void TextHandlerTest::initTestCase() connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org")); room = new TestRoom(connection, QStringLiteral("#myroom:kde.org"), JoinState::Join); + connection->setAccountData("im.ponies.user_emotes"_ls, + QJsonObject{{"images"_ls, + QJsonObject{{"test"_ls, + QJsonObject{{"body"_ls, "Test custom emoji"_ls}, + {"url"_ls, "mxc://example.org/test"_ls}, + {"usage"_ls, QJsonArray{"emoticon"_ls}}}}}}}); + CustomEmojiModel::instance().setConnection(static_cast(connection)); + QFile testTextHandlerSyncFile; testTextHandlerSyncFile.setFileName(QLatin1String(DATA_DIR) + u'/' + QLatin1String("test-texthandler-sync.json")); testTextHandlerSyncFile.open(QIODevice::ReadOnly); @@ -234,6 +247,39 @@ void TextHandlerTest::sendCodeClass() QCOMPARE(testTextHandler.handleSendText(), testOutputString); } +void TextHandlerTest::sendCustomEmoji() +{ + const QString testInputString = QStringLiteral(":test:"); + const QString testOutputString = QStringLiteral( + "

\":test:\"

"); + + TextHandler testTextHandler; + testTextHandler.setData(testInputString); + + QCOMPARE(testTextHandler.handleSendText(), testOutputString); +} + +void TextHandlerTest::sendCustomEmojiCode_data() +{ + QTest::addColumn("testInputString"); + QTest::addColumn("testOutputString"); + + QTest::newRow("inline") << QStringLiteral("`:test:`") << QStringLiteral("

:test:

"); + QTest::newRow("block") << QStringLiteral("```\n:test:\n```") << QStringLiteral("
:test:\n
"); +} + +// Custom emojis in code blocks should be left alone. +void TextHandlerTest::sendCustomEmojiCode() +{ + QFETCH(QString, testInputString); + QFETCH(QString, testOutputString); + + TextHandler testTextHandler; + testTextHandler.setData(testInputString); + + QCOMPARE(testTextHandler.handleSendText(), testOutputString); +} + void TextHandlerTest::receiveStripReply() { const QString testInputString = QStringLiteral( diff --git a/src/actionshandler.cpp b/src/actionshandler.cpp index a562e93f7..6967473e9 100644 --- a/src/actionshandler.cpp +++ b/src/actionshandler.cpp @@ -12,7 +12,6 @@ #include #include "models/actionsmodel.h" -#include "models/customemojimodel.h" #include "neochatconfig.h" #include "texthandler.h" @@ -135,7 +134,6 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, Cha } } - handledText = CustomEmojiModel::instance().preprocessText(handledText); TextHandler textHandler; textHandler.setData(handledText); handledText = textHandler.handleSendText(); diff --git a/src/models/customemojimodel.cpp b/src/models/customemojimodel.cpp index 88956bfe5..aafcb4cf3 100644 --- a/src/models/customemojimodel.cpp +++ b/src/models/customemojimodel.cpp @@ -188,22 +188,14 @@ QHash CustomEmojiModel::roleNames() const }; } -QString CustomEmojiModel::preprocessText(const QString &text) +QString CustomEmojiModel::preprocessText(QString text) { - auto parts = text.split("```"_ls); - bool skip = true; - for (auto &part : parts) { - skip = !skip; - if (skip) { - continue; - } - for (const auto &emoji : std::as_const(m_emojis)) { - part.replace( - emoji.regexp, - QStringLiteral(R"(%2)").arg(emoji.url, emoji.name)); - } + for (const auto &emoji : std::as_const(m_emojis)) { + text.replace( + emoji.regexp, + QStringLiteral(R"(%2)").arg(emoji.url, emoji.name)); } - return parts.join("```"_ls); + return text; } QVariantList CustomEmojiModel::filterModel(const QString &filter) diff --git a/src/models/customemojimodel.h b/src/models/customemojimodel.h index 1b374a301..c4b1e474e 100644 --- a/src/models/customemojimodel.h +++ b/src/models/customemojimodel.h @@ -85,7 +85,7 @@ public: /** * @brief Substitute any custom emojis for an image in the input text. */ - Q_INVOKABLE QString preprocessText(const QString &it); + Q_INVOKABLE QString preprocessText(QString text); /** * @brief Return a list of custom emojis where the name contains the filter text. diff --git a/src/texthandler.cpp b/src/texthandler.cpp index c228f43bf..ac3aa643d 100644 --- a/src/texthandler.cpp +++ b/src/texthandler.cpp @@ -16,6 +16,7 @@ #include +#include "models/customemojimodel.h" #include "utils.h" static const QStringList allowedTags = { @@ -63,13 +64,21 @@ QString TextHandler::handleSendText() next(); QString nextTokenBuffer = m_nextToken; - if (m_nextTokenType == Type::Text || m_nextTokenType == Type::TextCode) { + switch (m_nextTokenType) { + case Text: nextTokenBuffer = escapeHtml(nextTokenBuffer); - } else if (m_nextTokenType == Type::Tag) { + nextTokenBuffer = CustomEmojiModel::instance().preprocessText(nextTokenBuffer); + break; + case TextCode: + nextTokenBuffer = escapeHtml(nextTokenBuffer); + break; + case Tag: if (!isAllowedTag(getTagType())) { nextTokenBuffer = QString(); } nextTokenBuffer = cleanAttributes(getTagType(), nextTokenBuffer); + default: + break; } outputString.append(nextTokenBuffer);