diff --git a/src/core/autotests/emojimanagertest.cpp b/src/core/autotests/emojimanagertest.cpp index 9feaa5cc..74f47878 100644 --- a/src/core/autotests/emojimanagertest.cpp +++ b/src/core/autotests/emojimanagertest.cpp @@ -1,112 +1,115 @@ /* Copyright (c) 2018-2020 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "emojimanagertest.h" #include "emoticons/emojimanager.h" #include "emoticons/emoji.h" #include #include #include QTEST_GUILESS_MAIN(EmojiManagerTest) EmojiManagerTest::EmojiManagerTest(QObject *parent) : QObject(parent) { } void EmojiManagerTest::shouldHaveDefaultValue() { EmojiManager manager(nullptr, false); QVERIFY(manager.serverUrl().isEmpty()); QCOMPARE(manager.count(), 0); } void EmojiManagerTest::shouldParseEmoji_data() { QTest::addColumn("name"); QTest::addColumn("number"); QTest::addRow("emojiparent") << QStringLiteral("emojiparent") << 7; } void EmojiManagerTest::shouldParseEmoji() { QFETCH(QString, name); QFETCH(int, number); const QString originalJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QLatin1String("/json/restapi/") + name + QLatin1String(".json"); QFile f(originalJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject obj = doc.object(); EmojiManager manager(nullptr, false); manager.loadCustomEmoji(obj); QCOMPARE(manager.count(), number); } void EmojiManagerTest::shouldGenerateHtml() { const QString originalJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QLatin1String("/json/restapi/emojiparent.json"); QFile f(originalJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject obj = doc.object(); EmojiManager manager; manager.loadCustomEmoji(obj); //No serverUrl set. QCOMPARE(manager.replaceEmojiIdentifier(QStringLiteral(":foo:")), QStringLiteral(":foo:")); const QString serverUrl = QStringLiteral("www.kde.org"); manager.setServerUrl(serverUrl); // :foo: doesn't exist QCOMPARE(manager.replaceEmojiIdentifier(QStringLiteral(":foo:")), QStringLiteral(":foo:")); + QCOMPARE(manager.customEmojiFileName(QStringLiteral(":foo:")), QString()); // Existing emoji QCOMPARE(manager.replaceEmojiIdentifier(QStringLiteral(":vader:")), QStringLiteral("")); + QCOMPARE(manager.customEmojiFileName(QStringLiteral(":vader:")), QStringLiteral("/emoji-custom/vader.png")); // Alias QCOMPARE(manager.replaceEmojiIdentifier(QStringLiteral(":darth:")), QStringLiteral("")); + QCOMPARE(manager.customEmojiFileName(QStringLiteral(":darth:")), QStringLiteral("/emoji-custom/vader.png")); } void EmojiManagerTest::shouldChangeServerUrl() { const QString originalJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QLatin1String("/json/restapi/emojiparent.json"); QFile f(originalJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject obj = doc.object(); EmojiManager manager(nullptr, false); manager.loadCustomEmoji(obj); QString serverUrl = QStringLiteral("www.kde.org"); manager.setServerUrl(serverUrl); //It exists QCOMPARE(manager.replaceEmojiIdentifier(QStringLiteral(":vader:")), QStringLiteral("").arg(serverUrl)); //Change server url => clear cache serverUrl = QStringLiteral("www.bla.org"); manager.setServerUrl(serverUrl); QCOMPARE(manager.replaceEmojiIdentifier(QStringLiteral(":vader:")), QStringLiteral("").arg(serverUrl)); } diff --git a/src/core/emoticons/emojimanager.cpp b/src/core/emoticons/emojimanager.cpp index d8951f2d..862a75f1 100644 --- a/src/core/emoticons/emojimanager.cpp +++ b/src/core/emoticons/emojimanager.cpp @@ -1,161 +1,171 @@ /* Copyright (c) 2018-2020 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "emoticons/emojimanager.h" #include "emoticons/unicodeemoticonparser.h" #include #include #include #include #include "ruqola_debug.h" //TODO cache emoji ? EmojiManager::EmojiManager(QObject *parent, bool loadUnicode) : QObject(parent) { if (loadUnicode) { loadUnicodeEmoji(); } } EmojiManager::~EmojiManager() { } void EmojiManager::loadUnicodeEmoji() { UnicodeEmoticonParser unicodeParser; QFile file(QStringLiteral(":/emoji.json")); if (!file.open(QFile::ReadOnly)) { qCWarning(RUQOLA_LOG) << "Impossible to open file: " << file.errorString(); return; } const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); const QJsonObject obj = doc.object(); mUnicodeEmojiList = unicodeParser.parse(obj); } QMap > EmojiManager::unicodeEmojiList() const { return mUnicodeEmojiList; } void EmojiManager::loadCustomEmoji(const QJsonObject &obj) { mCustomEmojiList.clear(); const QJsonObject result = obj.value(QLatin1String("emojis")).toObject(); const QJsonArray array = result.value(QLatin1String("update")).toArray(); //TODO add support for remove when we store it in local for (int i = 0; i < array.size(); i++) { const QJsonObject emojiJson = array.at(i).toObject(); Emoji emoji; emoji.parseEmoji(emojiJson); if (emoji.isValid()) { mCustomEmojiList.append(emoji); } } } int EmojiManager::count() const { return mCustomEmojiList.count() + mUnicodeEmojiList.count(); } bool EmojiManager::isAnimatedImage(const QString &emojiIdentifier) const { if (emojiIdentifier.startsWith(QLatin1Char(':')) && emojiIdentifier.endsWith(QLatin1Char(':'))) { for (int i = 0, total = mCustomEmojiList.size(); i < total; ++i) { const Emoji emoji = mCustomEmojiList.at(i); if (emoji.hasEmoji(emojiIdentifier)) { return emoji.isAnimatedImage(); } } } return false; } UnicodeEmoticon EmojiManager::unicodeEmoticonForEmoji(const QString &emojiIdentifier) const { // ## why isn't the key in the QMap, the identifier? for (auto emojiId = mUnicodeEmojiList.constBegin(); emojiId != mUnicodeEmojiList.constEnd(); ++emojiId) { const QVector lst = emojiId.value(); for (const UnicodeEmoticon &emo : lst) { if (emo.hasEmoji(emojiIdentifier)) { return emo; } } } return {}; } +QString EmojiManager::customEmojiFileName(const QString &emojiIdentifier) const +{ + for (const Emoji &customEmoji : mCustomEmojiList) { + if (customEmoji.hasEmoji(emojiIdentifier)) { + return customEmoji.emojiFileName(); + } + } + return {}; +} + QString EmojiManager::replaceEmojiIdentifier(const QString &emojiIdentifier, bool isReaction) { if (mServerUrl.isEmpty()) { qCWarning(RUQOLA_LOG) << "Server Url not defined"; return emojiIdentifier; } if (emojiIdentifier.startsWith(QLatin1Char(':')) && emojiIdentifier.endsWith(QLatin1Char(':'))) { for (int i = 0, total = mCustomEmojiList.size(); i < total; ++i) { if (mCustomEmojiList.at(i).hasEmoji(emojiIdentifier)) { QString cachedHtml = mCustomEmojiList.at(i).cachedHtml(); if (cachedHtml.isEmpty()) { Emoji &emoji = mCustomEmojiList[i]; //For the moment we can't support animated image as emoticon in text. Only as Reaction. if (emoji.isAnimatedImage() && isReaction) { cachedHtml = emoji.generateAnimatedUrlFromCustomEmoji(mServerUrl); } else { cachedHtml = emoji.generateHtmlFromCustomEmoji(mServerUrl); } } return cachedHtml; } } const UnicodeEmoticon unicodeEmoticon = unicodeEmoticonForEmoji(emojiIdentifier); if (unicodeEmoticon.isValid()) { return unicodeEmoticon.unicodeDisplay(); } } else { qCWarning(RUQOLA_LOG) << "Emoji identifier is not correct :" << emojiIdentifier; } return emojiIdentifier; } QString EmojiManager::serverUrl() const { return mServerUrl; } void EmojiManager::setServerUrl(const QString &serverUrl) { if (mServerUrl != serverUrl) { mServerUrl = serverUrl; clearCustomEmojiCachedHtml(); } } void EmojiManager::clearCustomEmojiCachedHtml() { for (int i = 0, total = mCustomEmojiList.size(); i < total; ++i) { mCustomEmojiList[i].clearCachedHtml(); } } diff --git a/src/core/emoticons/emojimanager.h b/src/core/emoticons/emojimanager.h index 017e6d65..537e63ba 100644 --- a/src/core/emoticons/emojimanager.h +++ b/src/core/emoticons/emojimanager.h @@ -1,60 +1,62 @@ /* Copyright (c) 2018-2020 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef EMOJIMANAGER_H #define EMOJIMANAGER_H #include #include "emoji.h" #include "unicodeemoticon.h" #include "libruqolacore_export.h" class LIBRUQOLACORE_EXPORT EmojiManager : public QObject { Q_OBJECT public: explicit EmojiManager(QObject *parent = nullptr, bool loadUnicode = true); ~EmojiManager() override; void loadCustomEmoji(const QJsonObject &obj); Q_REQUIRED_RESULT int count() const; Q_REQUIRED_RESULT QString replaceEmojiIdentifier(const QString &emojiIdentifier, bool isReaction = false); Q_REQUIRED_RESULT QString serverUrl() const; void setServerUrl(const QString &serverUrl); Q_REQUIRED_RESULT QMap > unicodeEmojiList() const; Q_REQUIRED_RESULT bool isAnimatedImage(const QString &emojiIdentifier) const; Q_REQUIRED_RESULT UnicodeEmoticon unicodeEmoticonForEmoji(const QString &emojiIdentifier) const; + QString customEmojiFileName(const QString &emojiIdentifier) const; + private: Q_DISABLE_COPY(EmojiManager) void clearCustomEmojiCachedHtml(); void loadUnicodeEmoji(); //Use identifier in a QMap ??? QVector mCustomEmojiList; QMap > mUnicodeEmojiList; QString mServerUrl; }; #endif // EMOJIMANAGER_H