mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Move emojis to its own class
This commit is contained in:
parent
8e70f02e3b
commit
e09e0a5ab4
10 changed files with 249 additions and 250 deletions
|
@ -117,6 +117,7 @@ SOURCES += \
|
||||||
src/providers/twitch/twitchemotes.cpp \
|
src/providers/twitch/twitchemotes.cpp \
|
||||||
src/providers/bttv/bttvemotes.cpp \
|
src/providers/bttv/bttvemotes.cpp \
|
||||||
src/providers/ffz/ffzemotes.cpp \
|
src/providers/ffz/ffzemotes.cpp \
|
||||||
|
src/providers/emoji/emojis.cpp \
|
||||||
src/singletons/commandmanager.cpp \
|
src/singletons/commandmanager.cpp \
|
||||||
src/singletons/emotemanager.cpp \
|
src/singletons/emotemanager.cpp \
|
||||||
src/singletons/fontmanager.cpp \
|
src/singletons/fontmanager.cpp \
|
||||||
|
@ -223,7 +224,6 @@ HEADERS += \
|
||||||
src/channel.hpp \
|
src/channel.hpp \
|
||||||
src/const.hpp \
|
src/const.hpp \
|
||||||
src/debug/log.hpp \
|
src/debug/log.hpp \
|
||||||
src/emojis.hpp \
|
|
||||||
src/messages/image.hpp \
|
src/messages/image.hpp \
|
||||||
src/messages/layouts/messagelayout.hpp \
|
src/messages/layouts/messagelayout.hpp \
|
||||||
src/messages/layouts/messagelayoutcontainer.hpp \
|
src/messages/layouts/messagelayoutcontainer.hpp \
|
||||||
|
@ -248,6 +248,7 @@ HEADERS += \
|
||||||
src/providers/twitch/twitchemotes.hpp \
|
src/providers/twitch/twitchemotes.hpp \
|
||||||
src/providers/bttv/bttvemotes.hpp \
|
src/providers/bttv/bttvemotes.hpp \
|
||||||
src/providers/ffz/ffzemotes.hpp \
|
src/providers/ffz/ffzemotes.hpp \
|
||||||
|
src/providers/emoji/emojis.hpp \
|
||||||
src/singletons/commandmanager.hpp \
|
src/singletons/commandmanager.hpp \
|
||||||
src/singletons/emotemanager.hpp \
|
src/singletons/emotemanager.hpp \
|
||||||
src/singletons/fontmanager.hpp \
|
src/singletons/fontmanager.hpp \
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "util/emotemap.hpp"
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
struct EmojiData {
|
|
||||||
// actual byte-representation of the emoji (i.e. \154075\156150 which is :male:)
|
|
||||||
QString value;
|
|
||||||
|
|
||||||
// what's used in the emoji-one url
|
|
||||||
QString code;
|
|
||||||
|
|
||||||
// i.e. thinking
|
|
||||||
QString shortCode;
|
|
||||||
|
|
||||||
util::EmoteData emoteData;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
|
|
||||||
using EmojiMap = ConcurrentMap<QString, EmojiData>;
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
184
src/providers/emoji/emojis.cpp
Normal file
184
src/providers/emoji/emojis.cpp
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
#include "providers/emoji/emojis.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace emoji {
|
||||||
|
|
||||||
|
void Emojis::load()
|
||||||
|
{
|
||||||
|
QFile file(":/emojidata.txt");
|
||||||
|
file.open(QFile::ReadOnly);
|
||||||
|
QTextStream in(&file);
|
||||||
|
|
||||||
|
uint unicodeBytes[4];
|
||||||
|
|
||||||
|
while (!in.atEnd()) {
|
||||||
|
// Line example: sunglasses 1f60e
|
||||||
|
QString line = in.readLine();
|
||||||
|
|
||||||
|
if (line.at(0) == '#') {
|
||||||
|
// Ignore lines starting with # (comments)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList parts = line.split(' ');
|
||||||
|
if (parts.length() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString shortCode = parts[0];
|
||||||
|
QString code = parts[1];
|
||||||
|
|
||||||
|
QStringList unicodeCharacters = code.split('-');
|
||||||
|
if (unicodeCharacters.length() < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numUnicodeBytes = 0;
|
||||||
|
|
||||||
|
for (const QString &unicodeCharacter : unicodeCharacters) {
|
||||||
|
unicodeBytes[numUnicodeBytes++] = QString(unicodeCharacter).toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString unicodeString = QString::fromUcs4(unicodeBytes, numUnicodeBytes);
|
||||||
|
|
||||||
|
QString url = "https://cdnjs.cloudflare.com/ajax/libs/"
|
||||||
|
"emojione/2.2.6/assets/png/" +
|
||||||
|
code + ".png";
|
||||||
|
|
||||||
|
EmojiData emojiData{
|
||||||
|
unicodeString, //
|
||||||
|
code, //
|
||||||
|
shortCode, //
|
||||||
|
{new messages::Image(url, 0.35, unicodeString, ":" + shortCode + ":<br/>Emoji")},
|
||||||
|
};
|
||||||
|
|
||||||
|
this->emojiShortCodeToEmoji.insert(shortCode, emojiData);
|
||||||
|
this->shortCodes.push_back(shortCode.toStdString());
|
||||||
|
|
||||||
|
this->emojiFirstByte[emojiData.value.at(0)].append(emojiData);
|
||||||
|
|
||||||
|
this->emojis.insert(code, emojiData);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &p : this->emojiFirstByte) {
|
||||||
|
std::stable_sort(p.begin(), p.end(), [](const auto &lhs, const auto &rhs) {
|
||||||
|
return lhs.value.length() > rhs.value.length();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emojis::parse(std::vector<std::tuple<util::EmoteData, QString>> &parsedWords,
|
||||||
|
const QString &text)
|
||||||
|
{
|
||||||
|
int lastParsedEmojiEndIndex = 0;
|
||||||
|
|
||||||
|
for (auto i = 0; i < text.length(); ++i) {
|
||||||
|
const QChar character = text.at(i);
|
||||||
|
|
||||||
|
if (character.isLowSurrogate()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = this->emojiFirstByte.find(character);
|
||||||
|
if (it == this->emojiFirstByte.end()) {
|
||||||
|
// No emoji starts with this character
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<EmojiData> possibleEmojis = it.value();
|
||||||
|
|
||||||
|
int remainingCharacters = text.length() - i - 1;
|
||||||
|
|
||||||
|
EmojiData matchedEmoji;
|
||||||
|
|
||||||
|
int matchedEmojiLength = 0;
|
||||||
|
|
||||||
|
for (const EmojiData &emoji : possibleEmojis) {
|
||||||
|
int emojiExtraCharacters = emoji.value.length() - 1;
|
||||||
|
if (emojiExtraCharacters > remainingCharacters) {
|
||||||
|
// It cannot be this emoji, there's not enough space for it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
|
||||||
|
for (int j = 1; j < emoji.value.length(); ++j) {
|
||||||
|
if (text.at(i + j) != emoji.value.at(j)) {
|
||||||
|
match = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
matchedEmoji = emoji;
|
||||||
|
matchedEmojiLength = emoji.value.length();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchedEmojiLength == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentParsedEmojiFirstIndex = i;
|
||||||
|
int currentParsedEmojiEndIndex = i + (matchedEmojiLength);
|
||||||
|
|
||||||
|
int charactersFromLastParsedEmoji = currentParsedEmojiFirstIndex - lastParsedEmojiEndIndex;
|
||||||
|
|
||||||
|
if (charactersFromLastParsedEmoji > 0) {
|
||||||
|
// Add characters inbetween emojis
|
||||||
|
parsedWords.emplace_back(util::EmoteData(), text.mid(lastParsedEmojiEndIndex,
|
||||||
|
charactersFromLastParsedEmoji));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the emoji as a word to parsedWords
|
||||||
|
parsedWords.push_back(
|
||||||
|
std::tuple<util::EmoteData, QString>(matchedEmoji.emoteData, QString()));
|
||||||
|
|
||||||
|
lastParsedEmojiEndIndex = currentParsedEmojiEndIndex;
|
||||||
|
|
||||||
|
i += matchedEmojiLength - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastParsedEmojiEndIndex < text.length()) {
|
||||||
|
// Add remaining characters
|
||||||
|
parsedWords.emplace_back(util::EmoteData(), text.mid(lastParsedEmojiEndIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Emojis::replaceShortCodes(const QString &text)
|
||||||
|
{
|
||||||
|
QString ret(text);
|
||||||
|
auto it = this->findShortCodesRegex.globalMatch(text);
|
||||||
|
|
||||||
|
int32_t offset = 0;
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
auto match = it.next();
|
||||||
|
|
||||||
|
auto capturedString = match.captured();
|
||||||
|
|
||||||
|
QString matchString = capturedString.toLower().mid(1, capturedString.size() - 2);
|
||||||
|
|
||||||
|
auto emojiIt = this->emojiShortCodeToEmoji.constFind(matchString);
|
||||||
|
|
||||||
|
if (emojiIt == this->emojiShortCodeToEmoji.constEnd()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto emojiData = emojiIt.value();
|
||||||
|
|
||||||
|
ret.replace(offset + match.capturedStart(), match.capturedLength(), emojiData.value);
|
||||||
|
|
||||||
|
offset += emojiData.value.size() - match.capturedLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace emoji
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
56
src/providers/emoji/emojis.hpp
Normal file
56
src/providers/emoji/emojis.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "signalvector.hpp"
|
||||||
|
#include "util/concurrentmap.hpp"
|
||||||
|
#include "util/emotemap.hpp"
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace emoji {
|
||||||
|
|
||||||
|
struct EmojiData {
|
||||||
|
// actual byte-representation of the emoji (i.e. \154075\156150 which is :male:)
|
||||||
|
QString value;
|
||||||
|
|
||||||
|
// what's used in the emoji-one url
|
||||||
|
QString code;
|
||||||
|
|
||||||
|
// i.e. thinking
|
||||||
|
QString shortCode;
|
||||||
|
|
||||||
|
util::EmoteData emoteData;
|
||||||
|
};
|
||||||
|
|
||||||
|
using EmojiMap = util::ConcurrentMap<QString, EmojiData>;
|
||||||
|
|
||||||
|
class Emojis
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EmojiMap emojis;
|
||||||
|
|
||||||
|
std::vector<std::string> shortCodes;
|
||||||
|
|
||||||
|
void load();
|
||||||
|
QString replaceShortCodes(const QString &text);
|
||||||
|
|
||||||
|
void parse(std::vector<std::tuple<util::EmoteData, QString>> &parsedWords, const QString &text);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Emojis
|
||||||
|
QRegularExpression findShortCodesRegex{":([-+\\w]+):"};
|
||||||
|
|
||||||
|
// shortCodeToEmoji maps strings like "sunglasses" to its emoji
|
||||||
|
QMap<QString, EmojiData> emojiShortCodeToEmoji;
|
||||||
|
|
||||||
|
// Maps the first character of the emoji unicode string to a vector of possible emojis
|
||||||
|
QMap<QChar, QVector<EmojiData>> emojiFirstByte;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace emoji
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
|
@ -151,7 +151,7 @@ void TwitchChannel::sendMessage(const QString &message)
|
||||||
debug::Log("[TwitchChannel:{}] Send message: {}", this->name, message);
|
debug::Log("[TwitchChannel:{}] Send message: {}", this->name, message);
|
||||||
|
|
||||||
// Do last message processing
|
// Do last message processing
|
||||||
QString parsedMessage = app->emotes->replaceShortCodes(message);
|
QString parsedMessage = app->emotes->emojis.replaceShortCodes(message);
|
||||||
|
|
||||||
parsedMessage = parsedMessage.trimmed();
|
parsedMessage = parsedMessage.trimmed();
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ MessagePtr TwitchMessageBuilder::build()
|
||||||
std::vector<std::tuple<util::EmoteData, QString>> parsed;
|
std::vector<std::tuple<util::EmoteData, QString>> parsed;
|
||||||
|
|
||||||
// Parse emojis and take all non-emojis and put them in parsed as full text-words
|
// Parse emojis and take all non-emojis and put them in parsed as full text-words
|
||||||
app->emotes->parseEmojis(parsed, split);
|
app->emotes->emojis.parse(parsed, split);
|
||||||
|
|
||||||
for (const auto &tuple : parsed) {
|
for (const auto &tuple : parsed) {
|
||||||
const util::EmoteData &emoteData = std::get<0>(tuple);
|
const util::EmoteData &emoteData = std::get<0>(tuple);
|
||||||
|
|
|
@ -12,12 +12,6 @@ using namespace chatterino::messages;
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
|
||||||
EmoteManager::EmoteManager()
|
|
||||||
: findShortCodesRegex(":([-+\\w]+):")
|
|
||||||
{
|
|
||||||
qDebug() << "init EmoteManager";
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmoteManager::initialize()
|
void EmoteManager::initialize()
|
||||||
{
|
{
|
||||||
getApp()->accounts->twitch.currentUserChanged.connect([this] {
|
getApp()->accounts->twitch.currentUserChanged.connect([this] {
|
||||||
|
@ -26,7 +20,7 @@ void EmoteManager::initialize()
|
||||||
this->twitch.refresh(currentUser);
|
this->twitch.refresh(currentUser);
|
||||||
});
|
});
|
||||||
|
|
||||||
this->loadEmojis();
|
this->emojis.load();
|
||||||
this->bttv.loadGlobalEmotes();
|
this->bttv.loadGlobalEmotes();
|
||||||
this->ffz.loadGlobalEmotes();
|
this->ffz.loadGlobalEmotes();
|
||||||
|
|
||||||
|
@ -38,186 +32,6 @@ util::EmoteMap &EmoteManager::getChatterinoEmotes()
|
||||||
return _chatterinoEmotes;
|
return _chatterinoEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::EmojiMap &EmoteManager::getEmojis()
|
|
||||||
{
|
|
||||||
return this->emojis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmoteManager::loadEmojis()
|
|
||||||
{
|
|
||||||
QFile file(":/emojidata.txt");
|
|
||||||
file.open(QFile::ReadOnly);
|
|
||||||
QTextStream in(&file);
|
|
||||||
|
|
||||||
uint unicodeBytes[4];
|
|
||||||
|
|
||||||
while (!in.atEnd()) {
|
|
||||||
// Line example: sunglasses 1f60e
|
|
||||||
QString line = in.readLine();
|
|
||||||
|
|
||||||
if (line.at(0) == '#') {
|
|
||||||
// Ignore lines starting with # (comments)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList parts = line.split(' ');
|
|
||||||
if (parts.length() < 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString shortCode = parts[0];
|
|
||||||
QString code = parts[1];
|
|
||||||
|
|
||||||
QStringList unicodeCharacters = code.split('-');
|
|
||||||
if (unicodeCharacters.length() < 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numUnicodeBytes = 0;
|
|
||||||
|
|
||||||
for (const QString &unicodeCharacter : unicodeCharacters) {
|
|
||||||
unicodeBytes[numUnicodeBytes++] = QString(unicodeCharacter).toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString unicodeString = QString::fromUcs4(unicodeBytes, numUnicodeBytes);
|
|
||||||
|
|
||||||
QString url = "https://cdnjs.cloudflare.com/ajax/libs/"
|
|
||||||
"emojione/2.2.6/assets/png/" +
|
|
||||||
code + ".png";
|
|
||||||
|
|
||||||
EmojiData emojiData{
|
|
||||||
unicodeString, //
|
|
||||||
code, //
|
|
||||||
shortCode, //
|
|
||||||
{new Image(url, 0.35, unicodeString, ":" + shortCode + ":<br/>Emoji")},
|
|
||||||
};
|
|
||||||
|
|
||||||
this->emojiShortCodeToEmoji.insert(shortCode, emojiData);
|
|
||||||
this->emojiShortCodes.push_back(shortCode.toStdString());
|
|
||||||
|
|
||||||
this->emojiFirstByte[emojiData.value.at(0)].append(emojiData);
|
|
||||||
|
|
||||||
this->emojis.insert(code, emojiData);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &p : this->emojiFirstByte) {
|
|
||||||
std::stable_sort(p.begin(), p.end(), [](const auto &lhs, const auto &rhs) {
|
|
||||||
return lhs.value.length() > rhs.value.length();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmoteManager::parseEmojis(std::vector<std::tuple<util::EmoteData, QString>> &parsedWords,
|
|
||||||
const QString &text)
|
|
||||||
{
|
|
||||||
int lastParsedEmojiEndIndex = 0;
|
|
||||||
|
|
||||||
for (auto i = 0; i < text.length(); ++i) {
|
|
||||||
const QChar character = text.at(i);
|
|
||||||
|
|
||||||
if (character.isLowSurrogate()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = this->emojiFirstByte.find(character);
|
|
||||||
if (it == this->emojiFirstByte.end()) {
|
|
||||||
// No emoji starts with this character
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QVector<EmojiData> possibleEmojis = it.value();
|
|
||||||
|
|
||||||
int remainingCharacters = text.length() - i - 1;
|
|
||||||
|
|
||||||
EmojiData matchedEmoji;
|
|
||||||
|
|
||||||
int matchedEmojiLength = 0;
|
|
||||||
|
|
||||||
for (const EmojiData &emoji : possibleEmojis) {
|
|
||||||
int emojiExtraCharacters = emoji.value.length() - 1;
|
|
||||||
if (emojiExtraCharacters > remainingCharacters) {
|
|
||||||
// It cannot be this emoji, there's not enough space for it
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool match = true;
|
|
||||||
|
|
||||||
for (int j = 1; j < emoji.value.length(); ++j) {
|
|
||||||
if (text.at(i + j) != emoji.value.at(j)) {
|
|
||||||
match = false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
matchedEmoji = emoji;
|
|
||||||
matchedEmojiLength = emoji.value.length();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchedEmojiLength == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentParsedEmojiFirstIndex = i;
|
|
||||||
int currentParsedEmojiEndIndex = i + (matchedEmojiLength);
|
|
||||||
|
|
||||||
int charactersFromLastParsedEmoji = currentParsedEmojiFirstIndex - lastParsedEmojiEndIndex;
|
|
||||||
|
|
||||||
if (charactersFromLastParsedEmoji > 0) {
|
|
||||||
// Add characters inbetween emojis
|
|
||||||
parsedWords.emplace_back(util::EmoteData(), text.mid(lastParsedEmojiEndIndex,
|
|
||||||
charactersFromLastParsedEmoji));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the emoji as a word to parsedWords
|
|
||||||
parsedWords.push_back(
|
|
||||||
std::tuple<util::EmoteData, QString>(matchedEmoji.emoteData, QString()));
|
|
||||||
|
|
||||||
lastParsedEmojiEndIndex = currentParsedEmojiEndIndex;
|
|
||||||
|
|
||||||
i += matchedEmojiLength - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastParsedEmojiEndIndex < text.length()) {
|
|
||||||
// Add remaining characters
|
|
||||||
parsedWords.emplace_back(util::EmoteData(), text.mid(lastParsedEmojiEndIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EmoteManager::replaceShortCodes(const QString &text)
|
|
||||||
{
|
|
||||||
QString ret(text);
|
|
||||||
auto it = this->findShortCodesRegex.globalMatch(text);
|
|
||||||
|
|
||||||
int32_t offset = 0;
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
|
||||||
auto match = it.next();
|
|
||||||
|
|
||||||
auto capturedString = match.captured();
|
|
||||||
|
|
||||||
QString matchString = capturedString.toLower().mid(1, capturedString.size() - 2);
|
|
||||||
|
|
||||||
auto emojiIt = this->emojiShortCodeToEmoji.constFind(matchString);
|
|
||||||
|
|
||||||
if (emojiIt == this->emojiShortCodeToEmoji.constEnd()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto emojiData = emojiIt.value();
|
|
||||||
|
|
||||||
ret.replace(offset + match.capturedStart(), match.capturedLength(), emojiData.value);
|
|
||||||
|
|
||||||
offset += emojiData.value.size() - match.capturedLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
util::EmoteData EmoteManager::getCheerImage(long long amount, bool animated)
|
util::EmoteData EmoteManager::getCheerImage(long long amount, bool animated)
|
||||||
{
|
{
|
||||||
// TODO: fix this xD
|
// TODO: fix this xD
|
||||||
|
|
|
@ -2,21 +2,16 @@
|
||||||
|
|
||||||
#define GIF_FRAME_LENGTH 33
|
#define GIF_FRAME_LENGTH 33
|
||||||
|
|
||||||
#include "emojis.hpp"
|
|
||||||
#include "messages/image.hpp"
|
#include "messages/image.hpp"
|
||||||
#include "providers/bttv/bttvemotes.hpp"
|
#include "providers/bttv/bttvemotes.hpp"
|
||||||
|
#include "providers/emoji/emojis.hpp"
|
||||||
#include "providers/ffz/ffzemotes.hpp"
|
#include "providers/ffz/ffzemotes.hpp"
|
||||||
#include "providers/twitch/twitchemotes.hpp"
|
#include "providers/twitch/twitchemotes.hpp"
|
||||||
#include "signalvector.hpp"
|
|
||||||
#include "singletons/helper/giftimer.hpp"
|
#include "singletons/helper/giftimer.hpp"
|
||||||
#include "util/concurrentmap.hpp"
|
#include "util/concurrentmap.hpp"
|
||||||
#include "util/emotemap.hpp"
|
#include "util/emotemap.hpp"
|
||||||
|
|
||||||
#include <QMap>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
@ -24,20 +19,18 @@ namespace singletons {
|
||||||
class EmoteManager
|
class EmoteManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EmoteManager();
|
|
||||||
|
|
||||||
~EmoteManager() = delete;
|
~EmoteManager() = delete;
|
||||||
|
|
||||||
providers::twitch::TwitchEmotes twitch;
|
providers::twitch::TwitchEmotes twitch;
|
||||||
providers::bttv::BTTVEmotes bttv;
|
providers::bttv::BTTVEmotes bttv;
|
||||||
providers::ffz::FFZEmotes ffz;
|
providers::ffz::FFZEmotes ffz;
|
||||||
|
providers::emoji::Emojis emojis;
|
||||||
|
|
||||||
GIFTimer gifTimer;
|
GIFTimer gifTimer;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
util::EmoteMap &getChatterinoEmotes();
|
util::EmoteMap &getChatterinoEmotes();
|
||||||
util::EmojiMap &getEmojis();
|
|
||||||
|
|
||||||
util::EmoteData getCheerImage(long long int amount, bool animated);
|
util::EmoteData getCheerImage(long long int amount, bool animated);
|
||||||
|
|
||||||
|
@ -46,27 +39,6 @@ public:
|
||||||
util::ConcurrentMap<QString, messages::Image *> miscImageCache;
|
util::ConcurrentMap<QString, messages::Image *> miscImageCache;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Emojis
|
|
||||||
QRegularExpression findShortCodesRegex;
|
|
||||||
|
|
||||||
// shortCodeToEmoji maps strings like "sunglasses" to its emoji
|
|
||||||
QMap<QString, EmojiData> emojiShortCodeToEmoji;
|
|
||||||
|
|
||||||
// Maps the first character of the emoji unicode string to a vector of possible emojis
|
|
||||||
QMap<QChar, QVector<EmojiData>> emojiFirstByte;
|
|
||||||
|
|
||||||
util::EmojiMap emojis;
|
|
||||||
|
|
||||||
void loadEmojis();
|
|
||||||
|
|
||||||
public:
|
|
||||||
void parseEmojis(std::vector<std::tuple<util::EmoteData, QString>> &parsedWords,
|
|
||||||
const QString &text);
|
|
||||||
|
|
||||||
QString replaceShortCodes(const QString &text);
|
|
||||||
|
|
||||||
std::vector<std::string> emojiShortCodes;
|
|
||||||
|
|
||||||
/// Chatterino emotes
|
/// Chatterino emotes
|
||||||
util::EmoteMap _chatterinoEmotes;
|
util::EmoteMap _chatterinoEmotes;
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,7 +58,7 @@ void CompletionModel::refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global: Emojis
|
// Global: Emojis
|
||||||
const auto &emojiShortCodes = app->emotes->emojiShortCodes;
|
const auto &emojiShortCodes = app->emotes->emojis.shortCodes;
|
||||||
for (const auto &m : emojiShortCodes) {
|
for (const auto &m : emojiShortCodes) {
|
||||||
this->addString(":" + m + ":", TaggedString::Type::Emoji);
|
this->addString(":" + m + ":", TaggedString::Type::Emoji);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
|
||||||
|
|
||||||
void EmotePopup::loadEmojis()
|
void EmotePopup::loadEmojis()
|
||||||
{
|
{
|
||||||
auto &emojis = getApp()->emotes->getEmojis();
|
auto &emojis = getApp()->emotes->emojis.emojis;
|
||||||
|
|
||||||
ChannelPtr emojiChannel(new Channel("", Channel::None));
|
ChannelPtr emojiChannel(new Channel("", Channel::None));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue