mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Refactor ConcurrentMap
* Add operator[] to ConcurrentMap which returns a TValue reference * BTTV/FFZ channel emotes are now stored in the Emote Manager, and each Channel object has a reference to their own BTTV/FFZ channel emote map. * Restructure EmoteManager a bit (simplify the ConcurrentMap havoc). * Add EmoteData struct which can store emote data (for now only messages::LazyLoadedImage*) * Add CompletionManager that does nothing
This commit is contained in:
parent
1f1b0d7f03
commit
5aa892e834
11 changed files with 239 additions and 139 deletions
|
@ -95,7 +95,8 @@ SOURCES += \
|
||||||
src/widgets/accountpopup.cpp \
|
src/widgets/accountpopup.cpp \
|
||||||
src/messagefactory.cpp \
|
src/messagefactory.cpp \
|
||||||
src/widgets/basewidget.cpp \
|
src/widgets/basewidget.cpp \
|
||||||
src/widgets/resizingtextedit.cpp
|
src/widgets/resizingtextedit.cpp \
|
||||||
|
src/completionmanager.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/asyncexec.hpp \
|
src/asyncexec.hpp \
|
||||||
|
@ -155,7 +156,8 @@ HEADERS += \
|
||||||
src/widgets/accountpopup.hpp \
|
src/widgets/accountpopup.hpp \
|
||||||
src/util/distancebetweenpoints.hpp \
|
src/util/distancebetweenpoints.hpp \
|
||||||
src/messagefactory.hpp \
|
src/messagefactory.hpp \
|
||||||
src/widgets/basewidget.hpp
|
src/widgets/basewidget.hpp \
|
||||||
|
src/completionmanager.hpp
|
||||||
|
|
||||||
PRECOMPILED_HEADER =
|
PRECOMPILED_HEADER =
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "messagefactory.hpp"
|
#include "messagefactory.hpp"
|
||||||
#include "resources.hpp"
|
#include "resources.hpp"
|
||||||
#include "windowmanager.hpp"
|
#include "windowmanager.hpp"
|
||||||
|
#include "completionmanager.hpp"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ public:
|
||||||
|
|
||||||
int run(QApplication &qtApp);
|
int run(QApplication &qtApp);
|
||||||
|
|
||||||
|
CompletionManager completionManager;
|
||||||
WindowManager windowManager;
|
WindowManager windowManager;
|
||||||
ColorScheme colorScheme;
|
ColorScheme colorScheme;
|
||||||
EmoteManager emoteManager;
|
EmoteManager emoteManager;
|
||||||
|
|
|
@ -26,6 +26,8 @@ Channel::Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
|
||||||
, emoteManager(_emoteManager)
|
, emoteManager(_emoteManager)
|
||||||
, ircManager(_ircManager)
|
, ircManager(_ircManager)
|
||||||
, _name((channel.length() > 0 && channel[0] == '#') ? channel.mid(1) : channel)
|
, _name((channel.length() > 0 && channel[0] == '#') ? channel.mid(1) : channel)
|
||||||
|
, bttvChannelEmotes(this->emoteManager.bttvChannels[channel])
|
||||||
|
, ffzChannelEmotes(this->emoteManager.ffzChannels[channel])
|
||||||
, _subLink("https://www.twitch.tv/" + _name + "/subscribe?ref=in_chat_subscriber_link")
|
, _subLink("https://www.twitch.tv/" + _name + "/subscribe?ref=in_chat_subscriber_link")
|
||||||
, _channelLink("https://twitch.tv/" + _name)
|
, _channelLink("https://twitch.tv/" + _name)
|
||||||
, _popoutPlayerLink("https://player.twitch.tv/?channel=" + _name)
|
, _popoutPlayerLink("https://player.twitch.tv/?channel=" + _name)
|
||||||
|
@ -41,14 +43,14 @@ Channel::Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
|
||||||
//
|
//
|
||||||
// properties
|
// properties
|
||||||
//
|
//
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &Channel::getBttvChannelEmotes()
|
EmoteManager::EmoteMap &Channel::getBTTVChannelEmotes()
|
||||||
{
|
{
|
||||||
return _bttvChannelEmotes;
|
return this->bttvChannelEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &Channel::getFfzChannelEmotes()
|
EmoteManager::EmoteMap &Channel::getFFZChannelEmotes()
|
||||||
{
|
{
|
||||||
return _ffzChannelEmotes;
|
return this->ffzChannelEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Channel::isEmpty() const
|
bool Channel::isEmpty() const
|
||||||
|
@ -125,8 +127,8 @@ void Channel::addMessage(std::shared_ptr<Message> message)
|
||||||
void Channel::reloadChannelEmotes()
|
void Channel::reloadChannelEmotes()
|
||||||
{
|
{
|
||||||
printf("[Channel:%s] Reloading channel emotes\n", qPrintable(this->_name));
|
printf("[Channel:%s] Reloading channel emotes\n", qPrintable(this->_name));
|
||||||
this->emoteManager.reloadBTTVChannelEmotes(this->_name, this->_bttvChannelEmotes);
|
this->emoteManager.reloadBTTVChannelEmotes(this->_name);
|
||||||
this->emoteManager.reloadFFZChannelEmotes(this->_name, this->_ffzChannelEmotes);
|
this->emoteManager.reloadFFZChannelEmotes(this->_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::sendMessage(const QString &message)
|
void Channel::sendMessage(const QString &message)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "concurrentmap.hpp"
|
#include "concurrentmap.hpp"
|
||||||
|
#include "emotemanager.hpp"
|
||||||
#include "logging/loggingchannel.hpp"
|
#include "logging/loggingchannel.hpp"
|
||||||
#include "messages/lazyloadedimage.hpp"
|
#include "messages/lazyloadedimage.hpp"
|
||||||
#include "messages/limitedqueue.hpp"
|
#include "messages/limitedqueue.hpp"
|
||||||
|
@ -19,7 +20,6 @@ class Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
class EmoteManager;
|
|
||||||
class IrcManager;
|
class IrcManager;
|
||||||
|
|
||||||
class Channel
|
class Channel
|
||||||
|
@ -32,8 +32,8 @@ public:
|
||||||
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
|
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBttvChannelEmotes();
|
EmoteManager::EmoteMap &getBTTVChannelEmotes();
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getFfzChannelEmotes();
|
EmoteManager::EmoteMap &getFFZChannelEmotes();
|
||||||
|
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
const QString &getName() const;
|
const QString &getName() const;
|
||||||
|
@ -64,8 +64,8 @@ private:
|
||||||
|
|
||||||
QString _name;
|
QString _name;
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _bttvChannelEmotes;
|
EmoteManager::EmoteMap &bttvChannelEmotes;
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _ffzChannelEmotes;
|
EmoteManager::EmoteMap &ffzChannelEmotes;
|
||||||
|
|
||||||
QString _subLink;
|
QString _subLink;
|
||||||
QString _channelLink;
|
QString _channelLink;
|
||||||
|
|
20
src/completionmanager.cpp
Normal file
20
src/completionmanager.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "completionmanager.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
CompletionManager::CompletionManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletionModel *CompletionManager::createModel(const std::string &channelName)
|
||||||
|
{
|
||||||
|
CompletionModel *ret = new CompletionModel();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompletionManager::updateModel(CompletionModel *model, const std::string &channelName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
51
src/completionmanager.hpp
Normal file
51
src/completionmanager.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
class CompletionModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int columnCount(const QModelIndex & /*parent*/) const override
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role) const override
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const override
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QModelIndex parent(const QModelIndex &child) const override
|
||||||
|
{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int rowCount(const QModelIndex &parent) const override
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompletionManager
|
||||||
|
{
|
||||||
|
CompletionManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CompletionModel *createModel(const std::string &channelName);
|
||||||
|
void updateModel(CompletionModel *model, const std::string &channelName);
|
||||||
|
|
||||||
|
friend class Application;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
|
@ -14,16 +14,15 @@ class ConcurrentMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcurrentMap()
|
ConcurrentMap()
|
||||||
: _map()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tryGet(const TKey &name, TValue &value) const
|
bool tryGet(const TKey &name, TValue &value) const
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
auto a = _map.find(name);
|
auto a = this->data.find(name);
|
||||||
if (a == _map.end()) {
|
if (a == this->data.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,35 +33,51 @@ public:
|
||||||
|
|
||||||
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
|
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
auto a = _map.find(name);
|
auto a = this->data.find(name);
|
||||||
if (a == _map.end()) {
|
if (a == this->data.end()) {
|
||||||
TValue value = addLambda();
|
TValue value = addLambda();
|
||||||
_map.insert(name, value);
|
this->data.insert(name, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.value();
|
return a.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TValue &operator[](const TKey &name)
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
|
return this->data[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
ConcurrentMap(const ConcurrentMap &o)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ConcurrentMap &operator=(const ConcurrentMap &rhs)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
_map.clear();
|
this->data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(const TKey &name, const TValue &value)
|
void insert(const TKey &name, const TValue &value)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
_map.insert(name, value);
|
this->data.insert(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable QMutex _mutex;
|
mutable QMutex mutex;
|
||||||
QMap<TKey, TValue> _map;
|
QMap<TKey, TValue> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TKey, typename TValue>
|
template <typename TKey, typename TValue>
|
||||||
|
@ -97,6 +112,13 @@ public:
|
||||||
return a.value();
|
return a.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TValue &operator[](const TKey &name)
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&_mutex);
|
||||||
|
|
||||||
|
return this->_map[name];
|
||||||
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
|
|
|
@ -34,13 +34,14 @@ void EmoteManager::loadGlobalEmotes()
|
||||||
this->loadFFZEmotes();
|
this->loadFFZEmotes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName,
|
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
|
||||||
BTTVEmoteMap &channelEmoteMap)
|
|
||||||
{
|
{
|
||||||
printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName));
|
printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName));
|
||||||
|
|
||||||
QString url("https://api.betterttv.net/2/channels/" + channelName);
|
QString url("https://api.betterttv.net/2/channels/" + channelName);
|
||||||
util::urlFetchJSON(url, [this, &channelEmoteMap](QJsonObject &rootNode) {
|
util::urlFetchJSON(url, [this, channelName](QJsonObject &rootNode) {
|
||||||
|
EmoteMap &channelEmoteMap = this->bttvChannels[channelName];
|
||||||
|
|
||||||
channelEmoteMap.clear();
|
channelEmoteMap.clear();
|
||||||
|
|
||||||
auto emotesNode = rootNode.value("emotes").toArray();
|
auto emotesNode = rootNode.value("emotes").toArray();
|
||||||
|
@ -60,8 +61,8 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName,
|
||||||
link = link.replace("{{id}}", id).replace("{{image}}", "1x");
|
link = link.replace("{{id}}", id).replace("{{image}}", "1x");
|
||||||
|
|
||||||
auto emote = this->getBTTVChannelEmoteFromCaches().getOrAdd(id, [this, &code, &link] {
|
auto emote = this->getBTTVChannelEmoteFromCaches().getOrAdd(id, [this, &code, &link] {
|
||||||
return new LazyLoadedImage(*this, this->windowManager, link, 1, code,
|
return EmoteData(new LazyLoadedImage(*this, this->windowManager, link, 1, code,
|
||||||
code + "\nChannel BTTV Emote");
|
code + "\nChannel BTTV Emote"));
|
||||||
});
|
});
|
||||||
|
|
||||||
this->bttvChannelEmotes.insert(code, emote);
|
this->bttvChannelEmotes.insert(code, emote);
|
||||||
|
@ -70,15 +71,15 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::reloadFFZChannelEmotes(
|
void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
|
||||||
const QString &channelName,
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &channelEmoteMap)
|
|
||||||
{
|
{
|
||||||
printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName));
|
printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName));
|
||||||
|
|
||||||
QString url("http://api.frankerfacez.com/v1/room/" + channelName);
|
QString url("http://api.frankerfacez.com/v1/room/" + channelName);
|
||||||
|
|
||||||
util::urlFetchJSON(url, [this, &channelEmoteMap](QJsonObject &rootNode) {
|
util::urlFetchJSON(url, [this, channelName](QJsonObject &rootNode) {
|
||||||
|
EmoteMap &channelEmoteMap = this->ffzChannels[channelName];
|
||||||
|
|
||||||
channelEmoteMap.clear();
|
channelEmoteMap.clear();
|
||||||
|
|
||||||
auto setsNode = rootNode.value("sets").toObject();
|
auto setsNode = rootNode.value("sets").toObject();
|
||||||
|
@ -98,8 +99,8 @@ void EmoteManager::reloadFFZChannelEmotes(
|
||||||
|
|
||||||
auto emote =
|
auto emote =
|
||||||
this->getFFZChannelEmoteFromCaches().getOrAdd(id, [this, &code, &url1] {
|
this->getFFZChannelEmoteFromCaches().getOrAdd(id, [this, &code, &url1] {
|
||||||
return new LazyLoadedImage(*this, this->windowManager, url1, 1, code,
|
return EmoteData(new LazyLoadedImage(*this, this->windowManager, url1, 1,
|
||||||
code + "\nGlobal FFZ Emote");
|
code, code + "\nGlobal FFZ Emote"));
|
||||||
});
|
});
|
||||||
|
|
||||||
this->ffzChannelEmotes.insert(code, emote);
|
this->ffzChannelEmotes.insert(code, emote);
|
||||||
|
@ -114,41 +115,36 @@ ConcurrentMap<QString, twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
|
||||||
return _twitchEmotes;
|
return _twitchEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getBTTVEmotes()
|
EmoteManager::EmoteMap &EmoteManager::getBTTVEmotes()
|
||||||
{
|
{
|
||||||
return _bttvEmotes;
|
return _bttvEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getFFZEmotes()
|
EmoteManager::EmoteMap &EmoteManager::getFFZEmotes()
|
||||||
{
|
{
|
||||||
return _ffzEmotes;
|
return _ffzEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getChatterinoEmotes()
|
EmoteManager::EmoteMap &EmoteManager::getChatterinoEmotes()
|
||||||
{
|
{
|
||||||
return _chatterinoEmotes;
|
return _chatterinoEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getBTTVChannelEmoteFromCaches()
|
EmoteManager::EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches()
|
||||||
{
|
{
|
||||||
return _bttvChannelEmoteFromCaches;
|
return _bttvChannelEmoteFromCaches;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<int, messages::LazyLoadedImage *> &EmoteManager::getFFZChannelEmoteFromCaches()
|
ConcurrentMap<int, EmoteData> &EmoteManager::getFFZChannelEmoteFromCaches()
|
||||||
{
|
{
|
||||||
return _ffzChannelEmoteFromCaches;
|
return _ffzChannelEmoteFromCaches;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<long, messages::LazyLoadedImage *> &EmoteManager::getTwitchEmoteFromCache()
|
ConcurrentMap<long, EmoteData> &EmoteManager::getTwitchEmoteFromCache()
|
||||||
{
|
{
|
||||||
return _twitchEmoteFromCache;
|
return _twitchEmoteFromCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getMiscImageFromCache()
|
|
||||||
{
|
|
||||||
return _miscImageFromCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmoteManager::loadEmojis()
|
void EmoteManager::loadEmojis()
|
||||||
{
|
{
|
||||||
QFile file(":/emojidata.txt");
|
QFile file(":/emojidata.txt");
|
||||||
|
@ -199,8 +195,8 @@ void EmoteManager::loadEmojis()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::parseEmojis(
|
void EmoteManager::parseEmojis(std::vector<std::tuple<EmoteData, QString>> &parsedWords,
|
||||||
std::vector<std::tuple<messages::LazyLoadedImage *, QString>> &parsedWords, const QString &text)
|
const QString &text)
|
||||||
{
|
{
|
||||||
int lastParsedEmojiEndIndex = 0;
|
int lastParsedEmojiEndIndex = 0;
|
||||||
|
|
||||||
|
@ -270,12 +266,11 @@ void EmoteManager::parseEmojis(
|
||||||
|
|
||||||
// Create or fetch cached emoji image
|
// Create or fetch cached emoji image
|
||||||
auto emojiImage = this->emojiCache.getOrAdd(url, [this, &url] {
|
auto emojiImage = this->emojiCache.getOrAdd(url, [this, &url] {
|
||||||
return new LazyLoadedImage(*this, this->windowManager, url, 0.35); //
|
return EmoteData(new LazyLoadedImage(*this, this->windowManager, url, 0.35)); //
|
||||||
});
|
});
|
||||||
|
|
||||||
// Push the emoji as a word to parsedWords
|
// Push the emoji as a word to parsedWords
|
||||||
parsedWords.push_back(
|
parsedWords.push_back(std::tuple<EmoteData, QString>(emojiImage, QString()));
|
||||||
std::tuple<messages::LazyLoadedImage *, QString>(emojiImage, QString()));
|
|
||||||
|
|
||||||
lastParsedEmojiEndIndex = currentParsedEmojiEndIndex;
|
lastParsedEmojiEndIndex = currentParsedEmojiEndIndex;
|
||||||
|
|
||||||
|
@ -373,14 +368,16 @@ void EmoteManager::loadFFZEmotes()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoadedImage *EmoteManager::getTwitchEmoteById(const QString &name, long id)
|
// id is used for lookup
|
||||||
|
// emoteName is used for giving a name to the emote in case it doesn't exist
|
||||||
|
EmoteData EmoteManager::getTwitchEmoteById(long id, const QString &emoteName)
|
||||||
{
|
{
|
||||||
return EmoteManager::_twitchEmoteFromCache.getOrAdd(id, [this, &name, &id] {
|
return _twitchEmoteFromCache.getOrAdd(id, [this, &emoteName, &id] {
|
||||||
qDebug() << "added twitch emote: " << id;
|
qDebug() << "added twitch emote: " << id;
|
||||||
qreal scale;
|
qreal scale;
|
||||||
QString url = getTwitchEmoteLink(id, scale);
|
QString url = getTwitchEmoteLink(id, scale);
|
||||||
return new LazyLoadedImage(*this, this->windowManager, url, scale, name,
|
return new LazyLoadedImage(*this, this->windowManager, url, scale, emoteName,
|
||||||
name + "\nTwitch Emote");
|
emoteName + "\nTwitch Emote");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,27 +392,10 @@ QString EmoteManager::getTwitchEmoteLink(long id, qreal &scale)
|
||||||
return value.replace("{id}", QString::number(id)).replace("{scale}", "2");
|
return value.replace("{id}", QString::number(id)).replace("{scale}", "2");
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoadedImage *EmoteManager::getCheerImage(long long amount, bool animated)
|
EmoteData EmoteManager::getCheerImage(long long amount, bool animated)
|
||||||
{
|
{
|
||||||
// TODO: fix this xD
|
// TODO: fix this xD
|
||||||
return this->getCheerBadge(amount);
|
return EmoteData();
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoadedImage *EmoteManager::getCheerBadge(long long amount)
|
|
||||||
{
|
|
||||||
if (amount >= 100000) {
|
|
||||||
return this->resources.cheerBadge100000;
|
|
||||||
} else if (amount >= 10000) {
|
|
||||||
return this->resources.cheerBadge10000;
|
|
||||||
} else if (amount >= 5000) {
|
|
||||||
return this->resources.cheerBadge5000;
|
|
||||||
} else if (amount >= 1000) {
|
|
||||||
return this->resources.cheerBadge1000;
|
|
||||||
} else if (amount >= 100) {
|
|
||||||
return this->resources.cheerBadge100;
|
|
||||||
} else {
|
|
||||||
return this->resources.cheerBadge1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::signals2::signal<void()> &EmoteManager::getGifUpdateSignal()
|
boost::signals2::signal<void()> &EmoteManager::getGifUpdateSignal()
|
||||||
|
|
|
@ -18,33 +18,42 @@ namespace chatterino {
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
class Resources;
|
class Resources;
|
||||||
|
|
||||||
|
struct EmoteData {
|
||||||
|
EmoteData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EmoteData(messages::LazyLoadedImage *_image)
|
||||||
|
: image(_image)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
messages::LazyLoadedImage *image = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class EmoteManager
|
class EmoteManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using FFZEmoteMap = ConcurrentMap<QString, messages::LazyLoadedImage *>;
|
using EmoteMap = ConcurrentMap<QString, EmoteData>;
|
||||||
using BTTVEmoteMap = ConcurrentMap<QString, messages::LazyLoadedImage *>;
|
|
||||||
using ChatterinoEmoteMap = ConcurrentMap<QString, messages::LazyLoadedImage *>;
|
|
||||||
|
|
||||||
EmoteManager(WindowManager &_windowManager, Resources &_resources);
|
EmoteManager(WindowManager &_windowManager, Resources &_resources);
|
||||||
|
|
||||||
void loadGlobalEmotes();
|
void loadGlobalEmotes();
|
||||||
|
|
||||||
void reloadBTTVChannelEmotes(const QString &channelName, BTTVEmoteMap &channelEmoteMap);
|
void reloadBTTVChannelEmotes(const QString &channelName);
|
||||||
void reloadFFZChannelEmotes(const QString &channelName, FFZEmoteMap &channelEmoteMap);
|
void reloadFFZChannelEmotes(const QString &channelName);
|
||||||
|
|
||||||
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBTTVEmotes();
|
EmoteMap &getBTTVEmotes();
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getFFZEmotes();
|
EmoteMap &getFFZEmotes();
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getChatterinoEmotes();
|
EmoteMap &getChatterinoEmotes();
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBTTVChannelEmoteFromCaches();
|
EmoteMap &getBTTVChannelEmoteFromCaches();
|
||||||
ConcurrentMap<int, messages::LazyLoadedImage *> &getFFZChannelEmoteFromCaches();
|
ConcurrentMap<int, EmoteData> &getFFZChannelEmoteFromCaches();
|
||||||
ConcurrentMap<long, messages::LazyLoadedImage *> &getTwitchEmoteFromCache();
|
ConcurrentMap<long, EmoteData> &getTwitchEmoteFromCache();
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> &getMiscImageFromCache();
|
|
||||||
|
|
||||||
messages::LazyLoadedImage *getCheerImage(long long int amount, bool animated);
|
EmoteData getCheerImage(long long int amount, bool animated);
|
||||||
messages::LazyLoadedImage *getCheerBadge(long long int amount);
|
|
||||||
|
|
||||||
messages::LazyLoadedImage *getTwitchEmoteById(const QString &name, long int id);
|
EmoteData getTwitchEmoteById(long int id, const QString &emoteName);
|
||||||
|
|
||||||
int getGeneration()
|
int getGeneration()
|
||||||
{
|
{
|
||||||
|
@ -58,6 +67,9 @@ public:
|
||||||
|
|
||||||
boost::signals2::signal<void()> &getGifUpdateSignal();
|
boost::signals2::signal<void()> &getGifUpdateSignal();
|
||||||
|
|
||||||
|
// Bit badge/emotes?
|
||||||
|
ConcurrentMap<QString, messages::LazyLoadedImage *> miscImageCache;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowManager &windowManager;
|
WindowManager &windowManager;
|
||||||
Resources &resources;
|
Resources &resources;
|
||||||
|
@ -70,38 +82,44 @@ private:
|
||||||
QMap<QChar, QVector<EmojiData>> emojiFirstByte;
|
QMap<QChar, QVector<EmojiData>> emojiFirstByte;
|
||||||
|
|
||||||
// url Emoji-one image
|
// url Emoji-one image
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> emojiCache;
|
EmoteMap emojiCache;
|
||||||
|
|
||||||
void loadEmojis();
|
void loadEmojis();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void parseEmojis(std::vector<std::tuple<messages::LazyLoadedImage *, QString>> &parsedWords,
|
void parseEmojis(std::vector<std::tuple<EmoteData, QString>> &parsedWords, const QString &text);
|
||||||
const QString &text);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Twitch emotes
|
/// Twitch emotes
|
||||||
ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
|
ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
|
||||||
ConcurrentMap<long, messages::LazyLoadedImage *> _twitchEmoteFromCache;
|
ConcurrentMap<long, EmoteData> _twitchEmoteFromCache;
|
||||||
|
|
||||||
/// BTTV emotes
|
/// BTTV emotes
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> bttvChannelEmotes;
|
EmoteMap bttvChannelEmotes;
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _bttvEmotes;
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _bttvChannelEmoteFromCaches;
|
public:
|
||||||
|
ConcurrentMap<QString, EmoteMap> bttvChannels;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EmoteMap _bttvEmotes;
|
||||||
|
EmoteMap _bttvChannelEmoteFromCaches;
|
||||||
|
|
||||||
void loadBTTVEmotes();
|
void loadBTTVEmotes();
|
||||||
|
|
||||||
/// FFZ emotes
|
/// FFZ emotes
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> ffzChannelEmotes;
|
EmoteMap ffzChannelEmotes;
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _ffzEmotes;
|
|
||||||
ConcurrentMap<int, messages::LazyLoadedImage *> _ffzChannelEmoteFromCaches;
|
public:
|
||||||
|
ConcurrentMap<QString, EmoteMap> ffzChannels;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EmoteMap _ffzEmotes;
|
||||||
|
ConcurrentMap<int, EmoteData> _ffzChannelEmoteFromCaches;
|
||||||
|
|
||||||
void loadFFZEmotes();
|
void loadFFZEmotes();
|
||||||
|
|
||||||
/// Chatterino emotes
|
/// Chatterino emotes
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _chatterinoEmotes;
|
EmoteMap _chatterinoEmotes;
|
||||||
|
|
||||||
// ???
|
|
||||||
ConcurrentMap<QString, messages::LazyLoadedImage *> _miscImageFromCache;
|
|
||||||
|
|
||||||
boost::signals2::signal<void()> _gifUpdateTimerSignal;
|
boost::signals2::signal<void()> _gifUpdateTimerSignal;
|
||||||
QTimer _gifUpdateTimer;
|
QTimer _gifUpdateTimer;
|
||||||
|
|
|
@ -59,7 +59,7 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// twitch emotes
|
// twitch emotes
|
||||||
std::vector<std::pair<long int, LazyLoadedImage *>> twitchEmotes;
|
std::vector<std::pair<long, EmoteData>> twitchEmotes;
|
||||||
|
|
||||||
iterator = this->tags.find("emotes");
|
iterator = this->tags.find("emotes");
|
||||||
if (iterator != this->tags.end()) {
|
if (iterator != this->tags.end()) {
|
||||||
|
@ -70,8 +70,8 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool operator()(const std::pair<long int, messages::LazyLoadedImage *> &lhs,
|
bool operator()(const std::pair<long, EmoteData> &lhs,
|
||||||
const std::pair<long int, messages::LazyLoadedImage *> &rhs)
|
const std::pair<long, EmoteData> &rhs)
|
||||||
{
|
{
|
||||||
return lhs.first < rhs.first;
|
return lhs.first < rhs.first;
|
||||||
}
|
}
|
||||||
|
@ -95,13 +95,13 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
// twitch emote
|
// twitch emote
|
||||||
if (currentTwitchEmote != twitchEmotes.end() && currentTwitchEmote->first == i) {
|
if (currentTwitchEmote != twitchEmotes.end() && currentTwitchEmote->first == i) {
|
||||||
this->appendWord(
|
this->appendWord(
|
||||||
Word(currentTwitchEmote->second, Word::TwitchEmoteImage,
|
Word(currentTwitchEmote->second.image, Word::TwitchEmoteImage,
|
||||||
currentTwitchEmote->second->getName(),
|
currentTwitchEmote->second.image->getName(),
|
||||||
currentTwitchEmote->second->getName() + QString("\nTwitch Emote")));
|
currentTwitchEmote->second.image->getName() + QString("\nTwitch Emote")));
|
||||||
this->appendWord(
|
this->appendWord(
|
||||||
Word(currentTwitchEmote->second->getName(), Word::TwitchEmoteText, textColor,
|
Word(currentTwitchEmote->second.image->getName(), Word::TwitchEmoteText, textColor,
|
||||||
currentTwitchEmote->second->getName(),
|
currentTwitchEmote->second.image->getName(),
|
||||||
currentTwitchEmote->second->getName() + QString("\nTwitch Emote")));
|
currentTwitchEmote->second.image->getName() + QString("\nTwitch Emote")));
|
||||||
|
|
||||||
i += split.length() + 1;
|
i += split.length() + 1;
|
||||||
currentTwitchEmote = std::next(currentTwitchEmote);
|
currentTwitchEmote = std::next(currentTwitchEmote);
|
||||||
|
@ -110,15 +110,15 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// split words
|
// split words
|
||||||
std::vector<std::tuple<LazyLoadedImage *, QString>> parsed;
|
std::vector<std::tuple<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
|
||||||
emoteManager.parseEmojis(parsed, split);
|
emoteManager.parseEmojis(parsed, split);
|
||||||
|
|
||||||
for (const std::tuple<LazyLoadedImage *, QString> &tuple : parsed) {
|
for (const auto &tuple : parsed) {
|
||||||
LazyLoadedImage *image = std::get<0>(tuple);
|
const EmoteData &emoteData = std::get<0>(tuple);
|
||||||
|
|
||||||
if (image == nullptr) { // is text
|
if (emoteData.image == nullptr) { // is text
|
||||||
QString string = std::get<1>(tuple);
|
QString string = std::get<1>(tuple);
|
||||||
|
|
||||||
static QRegularExpression cheerRegex("cheer[1-9][0-9]*");
|
static QRegularExpression cheerRegex("cheer[1-9][0-9]*");
|
||||||
|
@ -153,13 +153,13 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
QString bitsLink =
|
QString bitsLink =
|
||||||
QString("http://static-cdn.jtvnw.net/bits/dark/static/" + color + "/1");
|
QString("http://static-cdn.jtvnw.net/bits/dark/static/" + color + "/1");
|
||||||
|
|
||||||
LazyLoadedImage *imageAnimated = emoteManager.getMiscImageFromCache().getOrAdd(
|
LazyLoadedImage *imageAnimated = emoteManager.miscImageCache.getOrAdd(
|
||||||
bitsLinkAnimated, [this, &bitsLinkAnimated] {
|
bitsLinkAnimated, [this, &bitsLinkAnimated] {
|
||||||
return new LazyLoadedImage(this->emoteManager, this->windowManager,
|
return new LazyLoadedImage(this->emoteManager, this->windowManager,
|
||||||
bitsLinkAnimated);
|
bitsLinkAnimated);
|
||||||
});
|
});
|
||||||
LazyLoadedImage *image =
|
LazyLoadedImage *image =
|
||||||
emoteManager.getMiscImageFromCache().getOrAdd(bitsLink, [this, &bitsLink] {
|
emoteManager.miscImageCache.getOrAdd(bitsLink, [this, &bitsLink] {
|
||||||
return new LazyLoadedImage(this->emoteManager, this->windowManager,
|
return new LazyLoadedImage(this->emoteManager, this->windowManager,
|
||||||
bitsLink);
|
bitsLink);
|
||||||
});
|
});
|
||||||
|
@ -185,21 +185,21 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// bttv / ffz emotes
|
// bttv / ffz emotes
|
||||||
LazyLoadedImage *bttvEmote;
|
EmoteData emoteData;
|
||||||
|
|
||||||
// TODO: Implement ignored emotes
|
// TODO: Implement ignored emotes
|
||||||
// Format of ignored emotes:
|
// Format of ignored emotes:
|
||||||
// Emote name: "forsenPuke" - if string in ignoredEmotes
|
// Emote name: "forsenPuke" - if string in ignoredEmotes
|
||||||
// Will match emote regardless of source (i.e. bttv, ffz)
|
// Will match emote regardless of source (i.e. bttv, ffz)
|
||||||
// Emote source + name: "bttv:nyanPls"
|
// Emote source + name: "bttv:nyanPls"
|
||||||
if (emoteManager.getBTTVEmotes().tryGet(string, bttvEmote) ||
|
if (emoteManager.getBTTVEmotes().tryGet(string, emoteData) ||
|
||||||
this->channel->getBttvChannelEmotes().tryGet(string, bttvEmote) ||
|
this->channel->getBTTVChannelEmotes().tryGet(string, emoteData) ||
|
||||||
emoteManager.getFFZEmotes().tryGet(string, bttvEmote) ||
|
emoteManager.getFFZEmotes().tryGet(string, emoteData) ||
|
||||||
this->channel->getFfzChannelEmotes().tryGet(string, bttvEmote) ||
|
this->channel->getFFZChannelEmotes().tryGet(string, emoteData) ||
|
||||||
emoteManager.getChatterinoEmotes().tryGet(string, bttvEmote)) {
|
emoteManager.getChatterinoEmotes().tryGet(string, emoteData)) {
|
||||||
this->appendWord(Word(bttvEmote, Word::BttvEmoteImage, bttvEmote->getName(),
|
this->appendWord(Word(emoteData.image, Word::BttvEmoteImage,
|
||||||
bttvEmote->getTooltip(),
|
emoteData.image->getName(), emoteData.image->getTooltip(),
|
||||||
Link(Link::Url, bttvEmote->getUrl())));
|
Link(Link::Url, emoteData.image->getUrl())));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -212,8 +212,10 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
} else { // is emoji
|
} else { // is emoji
|
||||||
static QString emojiTooltip("Emoji");
|
static QString emojiTooltip("Emoji");
|
||||||
|
|
||||||
this->appendWord(Word(image, Word::EmojiImage, image->getName(), emojiTooltip));
|
this->appendWord(Word(emoteData.image, Word::EmojiImage, emoteData.image->getName(),
|
||||||
Word(image->getName(), Word::EmojiText, textColor, image->getName(), emojiTooltip);
|
emojiTooltip));
|
||||||
|
Word(emoteData.image->getName(), Word::EmojiText, textColor,
|
||||||
|
emoteData.image->getName(), emojiTooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,9 +318,10 @@ void TwitchMessageBuilder::appendModerationButtons()
|
||||||
buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
|
buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::appendTwitchEmote(
|
void TwitchMessageBuilder::appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage,
|
||||||
const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
|
const QString &emote,
|
||||||
std::vector<std::pair<long int, messages::LazyLoadedImage *>> &vec, EmoteManager &emoteManager)
|
std::vector<std::pair<long int, EmoteData>> &vec,
|
||||||
|
EmoteManager &emoteManager)
|
||||||
{
|
{
|
||||||
if (!emote.contains(':')) {
|
if (!emote.contains(':')) {
|
||||||
return;
|
return;
|
||||||
|
@ -350,8 +353,8 @@ void TwitchMessageBuilder::appendTwitchEmote(
|
||||||
|
|
||||||
QString name = ircMessage->content().mid(start, end - start + 1);
|
QString name = ircMessage->content().mid(start, end - start + 1);
|
||||||
|
|
||||||
vec.push_back(std::pair<long int, LazyLoadedImage *>(
|
vec.push_back(
|
||||||
start, emoteManager.getTwitchEmoteById(name, id)));
|
std::pair<long int, EmoteData>(start, emoteManager.getTwitchEmoteById(id, name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "emotemanager.hpp"
|
||||||
#include "messages/messagebuilder.hpp"
|
#include "messages/messagebuilder.hpp"
|
||||||
#include "resources.hpp"
|
#include "resources.hpp"
|
||||||
|
|
||||||
|
@ -8,7 +9,6 @@
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class EmoteManager;
|
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
class Channel;
|
class Channel;
|
||||||
class ColorScheme;
|
class ColorScheme;
|
||||||
|
@ -55,7 +55,7 @@ private:
|
||||||
|
|
||||||
void appendModerationButtons();
|
void appendModerationButtons();
|
||||||
void appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
|
void appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
|
||||||
std::vector<std::pair<long int, messages::LazyLoadedImage *>> &vec,
|
std::vector<std::pair<long, EmoteData>> &vec,
|
||||||
EmoteManager &emoteManager);
|
EmoteManager &emoteManager);
|
||||||
|
|
||||||
void parseTwitchBadges();
|
void parseTwitchBadges();
|
||||||
|
|
Loading…
Reference in a new issue