From 59d383c161da8b8869aff0b7e9b3452a82973d2b Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 13 Jun 2017 21:13:58 +0200 Subject: [PATCH] Huge refactor - Remove some underscore-prefixes - Start using this-> more - Remove a few of the singletons (We pass references to managers to things that need it now. Might not be much better, but for now it works. It also shows what places might be slightly wrong designed) --- chatterino.pro | 1 + src/application.cpp | 42 ++++++ src/application.hpp | 28 ++++ src/channel.cpp | 84 ++---------- src/channel.hpp | 15 ++- src/channelmanager.cpp | 23 ++-- src/channelmanager.hpp | 16 ++- src/colorscheme.cpp | 19 ++- src/colorscheme.hpp | 4 +- src/emojis.cpp | 10 +- src/emotemanager.cpp | 166 +++++++++++++++++------ src/emotemanager.hpp | 65 ++++----- src/ircmanager.cpp | 23 ++-- src/ircmanager.hpp | 17 ++- src/main.cpp | 29 ++-- src/messages/lazyloadedimage.cpp | 29 ++-- src/messages/lazyloadedimage.hpp | 22 ++- src/messages/message.cpp | 8 +- src/messages/message.hpp | 4 +- src/messages/messageref.cpp | 6 +- src/resources.cpp | 71 ++++------ src/resources.hpp | 115 +++------------- src/settingsmanager.hpp | 1 + src/twitch/twitchmessagebuilder.cpp | 201 ++++++++++++++++------------ src/twitch/twitchmessagebuilder.hpp | 21 ++- src/widgets/chatwidget.cpp | 11 +- src/widgets/chatwidget.hpp | 7 +- src/widgets/mainwindow.cpp | 22 +-- src/widgets/mainwindow.hpp | 9 +- src/widgets/notebook.cpp | 5 +- src/widgets/notebook.hpp | 7 +- src/widgets/notebookpage.cpp | 13 +- src/widgets/notebookpage.hpp | 9 +- src/widgets/settingsdialog.cpp | 4 +- src/widgets/settingsdialog.hpp | 1 + src/windowmanager.cpp | 30 ++--- src/windowmanager.hpp | 15 +-- 37 files changed, 630 insertions(+), 523 deletions(-) create mode 100644 src/application.cpp create mode 100644 src/application.hpp diff --git a/chatterino.pro b/chatterino.pro index 2c041f12..ff4a6dad 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -47,6 +47,7 @@ win32 { SOURCES += \ src/main.cpp \ + src/application.cpp \ src/channel.cpp \ src/colorscheme.cpp \ src/emojis.cpp \ diff --git a/src/application.cpp b/src/application.cpp new file mode 100644 index 00000000..575f9bdd --- /dev/null +++ b/src/application.cpp @@ -0,0 +1,42 @@ +#include "application.hpp" +#include "colorscheme.hpp" +#include "settingsmanager.hpp" + +namespace chatterino { + +Application::Application() + : windowManager(this->channelManager) + , emoteManager(this->windowManager, this->resources) + , resources(this->emoteManager, this->windowManager) + , channelManager(this->windowManager, this->emoteManager, this->ircManager) + , ircManager(this->channelManager, this->resources, this->emoteManager, this->windowManager) +{ + // TODO(pajlada): Get rid of all singletons + ColorScheme::getInstance().init(this->windowManager); + + // Initialize everything we need + this->emoteManager.loadGlobalEmotes(); + + // XXX + SettingsManager::getInstance().updateWordTypeMask(); + + this->windowManager.load(); +} + +Application::~Application() +{ + this->windowManager.save(); +} + +int Application::run(QApplication &qtApp) +{ + // Start connecting to the IRC Servers (Twitch only for now) + this->ircManager.connect(); + + // Show main window + this->windowManager.getMainWindow().show(); + + return qtApp.exec(); +} + +} // namespace chatterino diff --git a/src/application.hpp b/src/application.hpp new file mode 100644 index 00000000..93e92960 --- /dev/null +++ b/src/application.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "channelmanager.hpp" +#include "emotemanager.hpp" +#include "ircmanager.hpp" +#include "resources.hpp" +#include "windowmanager.hpp" + +#include + +namespace chatterino { + +class Application +{ +public: + Application(); + ~Application(); + + int run(QApplication &qtApp); + + WindowManager windowManager; + EmoteManager emoteManager; + Resources resources; + ChannelManager channelManager; + IrcManager ircManager; +}; + +} // namespace chatterino diff --git a/src/channel.cpp b/src/channel.cpp index 3e81974e..4bf0e2af 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -3,7 +3,6 @@ #include "ircmanager.hpp" #include "logging/loggingmanager.hpp" #include "messages/message.hpp" -#include "util/urlfetch.hpp" #include "windowmanager.hpp" #include @@ -21,8 +20,12 @@ using namespace chatterino::messages; namespace chatterino { -Channel::Channel(const QString &channel) - : _messages() +Channel::Channel(WindowManager &_windowManager, EmoteManager &_emoteManager, + IrcManager &_ircManager, const QString &channel, bool isSpecial) + : windowManager(_windowManager) + , emoteManager(_emoteManager) + , ircManager(_ircManager) + , _messages() , _name((channel.length() > 0 && channel[0] == '#') ? channel.mid(1) : channel) , _bttvChannelEmotes() , _ffzChannelEmotes() @@ -33,7 +36,9 @@ Channel::Channel(const QString &channel) { qDebug() << "Open channel:" << channel << ". Name: " << _name; printf("Channel pointer: %p\n", this); - reloadChannelEmotes(); + if (!isSpecial) { + this->reloadChannelEmotes(); + } } // @@ -121,82 +126,21 @@ void Channel::addMessage(std::shared_ptr message) this->messageAppended(message); - WindowManager::getInstance().repaintVisibleChatWidgets(this); + this->windowManager.repaintVisibleChatWidgets(this); } // private methods void Channel::reloadChannelEmotes() { - reloadBttvEmotes(); - reloadFfzEmotes(); + printf("[Channel:%s] Reloading channel emotes\n", qPrintable(this->_name)); + this->emoteManager.reloadBTTVChannelEmotes(this->_name, this->_bttvChannelEmotes); + this->emoteManager.reloadFFZChannelEmotes(this->_name, this->_ffzChannelEmotes); } void Channel::sendMessage(const QString &message) { qDebug() << "Channel send message: " << message; - IrcManager &instance = IrcManager::getInstance(); - instance.sendMessage(_name, message); -} - -void Channel::reloadBttvEmotes() -{ - util::urlJsonFetch( - "https://api.betterttv.net/2/channels/" + _name, [this](QJsonObject &rootNode) { - auto emotesNode = rootNode.value("emotes").toArray(); - - QString linkTemplate = "https:" + rootNode.value("urlTemplate").toString(); - - for (const QJsonValue &emoteNode : emotesNode) { - QJsonObject emoteObject = emoteNode.toObject(); - - QString id = emoteObject.value("id").toString(); - QString code = emoteObject.value("code").toString(); - // emoteObject.value("imageType").toString(); - - QString link = linkTemplate; - link.detach(); - - link = link.replace("{{id}}", id).replace("{{image}}", "1x"); - - auto emote = EmoteManager::getInstance().getBttvChannelEmoteFromCaches().getOrAdd( - id, [&code, &link] { - return new LazyLoadedImage(link, 1, code, code + "\nChannel Bttv Emote"); - }); - - this->getBttvChannelEmotes().insert(code, emote); - } - }); -} - -void Channel::reloadFfzEmotes() -{ - util::urlJsonFetch("http://api.frankerfacez.com/v1/room/" + _name, [this]( - QJsonObject &rootNode) { - auto setsNode = rootNode.value("sets").toObject(); - - for (const QJsonValue &setNode : setsNode) { - auto emotesNode = setNode.toObject().value("emoticons").toArray(); - - for (const QJsonValue &emoteNode : emotesNode) { - QJsonObject emoteObject = emoteNode.toObject(); - - // margins - - int id = emoteObject.value("id").toInt(); - QString code = emoteObject.value("name").toString(); - - QJsonObject urls = emoteObject.value("urls").toObject(); - QString url1 = "http:" + urls.value("1").toString(); - - auto emote = EmoteManager::getInstance().getFfzChannelEmoteFromCaches().getOrAdd( - id, [&code, &url1] { - return new LazyLoadedImage(url1, 1, code, code + "\nGlobal Ffz Emote"); - }); - - getFfzChannelEmotes().insert(code, emote); - } - } - }); + this->ircManager.sendMessage(_name, message); } } // namespace chatterino diff --git a/src/channel.hpp b/src/channel.hpp index d07aaef2..3f1f28b4 100644 --- a/src/channel.hpp +++ b/src/channel.hpp @@ -18,12 +18,15 @@ namespace messages { class Message; } -class ChannelManager; +class WindowManager; +class EmoteManager; +class IrcManager; class Channel { public: - Channel(const QString &channel); + explicit Channel(WindowManager &_windowManager, EmoteManager &_emoteManager, + IrcManager &_ircManager, const QString &channel, bool isSpecial = false); boost::signals2::signal messageRemovedFromStart; boost::signals2::signal messageAppended; @@ -51,6 +54,10 @@ public: void sendMessage(const QString &message); private: + WindowManager &windowManager; + EmoteManager &emoteManager; + IrcManager &ircManager; + // variabeles messages::LimitedQueue _messages; @@ -69,10 +76,6 @@ private: QString _streamStatus; QString _streamGame; // std::shared_ptr _loggingChannel; - - // methods - void reloadBttvEmotes(); - void reloadFfzEmotes(); }; } // namespace chatterino diff --git a/src/channelmanager.cpp b/src/channelmanager.cpp index 35c0d08d..5dfe42de 100644 --- a/src/channelmanager.cpp +++ b/src/channelmanager.cpp @@ -3,14 +3,14 @@ namespace chatterino { -ChannelManager ChannelManager::instance; - -ChannelManager::ChannelManager() - : _channels() - , _channelsMutex() - , _whispers(new Channel(QString("/whispers"))) - , _mentions(new Channel(QString("/mentions"))) - , _empty(new Channel(QString(""))) +ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager, + IrcManager &_ircManager) + : windowManager(_windowManager) + , emoteManager(_emoteManager) + , ircManager(_ircManager) + , _whispers(new Channel(_windowManager, _emoteManager, _ircManager, "/whispers", true)) + , _mentions(new Channel(_windowManager, _emoteManager, _ircManager, "/mentions", true)) + , _empty(new Channel(_windowManager, _emoteManager, _ircManager, QString(), true)) { } @@ -55,10 +55,11 @@ std::shared_ptr ChannelManager::addChannel(const QString &channel) auto it = _channels.find(channelName); if (it == _channels.end()) { - auto channel = std::shared_ptr(new Channel(channelName)); + auto channel = std::shared_ptr( + new Channel(this->windowManager, this->emoteManager, this->ircManager, channelName)); _channels.insert(channelName, std::make_tuple(channel, 1)); - IrcManager::getInstance().joinChannel(channelName); + this->ircManager.joinChannel(channelName); return channel; } @@ -114,7 +115,7 @@ void ChannelManager::removeChannel(const QString &channel) std::get<1>(a.value())--; if (std::get<1>(a.value()) == 0) { - IrcManager::getInstance().partChannel(c); + this->ircManager.partChannel(c); _channels.remove(c); } } diff --git a/src/channelmanager.hpp b/src/channelmanager.hpp index 289a2b98..2b0e261b 100644 --- a/src/channelmanager.hpp +++ b/src/channelmanager.hpp @@ -4,13 +4,15 @@ namespace chatterino { +class WindowManager; +class EmoteManager; +class IrcManager; + class ChannelManager { public: - static ChannelManager &getInstance() - { - return instance; - } + explicit ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager, + IrcManager &_ircManager); std::shared_ptr getWhispers(); std::shared_ptr getMentions(); @@ -23,9 +25,9 @@ public: void removeChannel(const QString &channel); private: - static ChannelManager instance; - - ChannelManager(); + WindowManager &windowManager; + EmoteManager &emoteManager; + IrcManager &ircManager; QMap, int>> _channels; QMutex _channelsMutex; diff --git a/src/colorscheme.cpp b/src/colorscheme.cpp index 4bb4c13d..2ae4f505 100644 --- a/src/colorscheme.cpp +++ b/src/colorscheme.cpp @@ -8,20 +8,25 @@ namespace chatterino { -void ColorScheme::init() +void ColorScheme::init(WindowManager &windowManager) { static bool initiated = false; if (!initiated) { initiated = true; ColorScheme::getInstance().update(); - SettingsManager::getInstance().theme.valueChanged.connect( - [](const QString &) { ColorScheme::getInstance().update(); }); - SettingsManager::getInstance().themeHue.valueChanged.connect( - [](const float &) { ColorScheme::getInstance().update(); }); - ColorScheme::getInstance().updated.connect( - [] { WindowManager::getInstance().repaintVisibleChatWidgets(); }); + SettingsManager::getInstance().theme.valueChanged.connect([](const QString &) { + ColorScheme::getInstance().update(); // + }); + + SettingsManager::getInstance().themeHue.valueChanged.connect([](const float &) { + ColorScheme::getInstance().update(); // + }); + + ColorScheme::getInstance().updated.connect([&windowManager] { + windowManager.repaintVisibleChatWidgets(); // + }); } } diff --git a/src/colorscheme.hpp b/src/colorscheme.hpp index 7b95d437..91d7d3c0 100644 --- a/src/colorscheme.hpp +++ b/src/colorscheme.hpp @@ -6,6 +6,8 @@ namespace chatterino { +class WindowManager; + class ColorScheme { public: @@ -67,7 +69,7 @@ public: return instance; } - void init(); + void init(WindowManager &windowManager); void normalizeColor(QColor &color); void update(); diff --git a/src/emojis.cpp b/src/emojis.cpp index 3aad860a..0673b7e1 100644 --- a/src/emojis.cpp +++ b/src/emojis.cpp @@ -46,8 +46,14 @@ void Emojis::parseEmojis(std::vector( - imageCache.getOrAdd( - url, [&url] { return new messages::LazyLoadedImage(url, 0.35); }), + imageCache.getOrAdd(url, + [/*&url*/] { + /* TODO: re-implement + return new messages::LazyLoadedImage(url, + 0.35); // + */ + return nullptr; + }), QString())); i += j - 1; diff --git a/src/emotemanager.cpp b/src/emotemanager.cpp index 3672a6cf..4b8bbc3b 100644 --- a/src/emotemanager.cpp +++ b/src/emotemanager.cpp @@ -1,5 +1,7 @@ #include "emotemanager.hpp" #include "resources.hpp" +#include "util/urlfetch.hpp" +#include "windowmanager.hpp" #include #include @@ -18,22 +20,92 @@ using namespace chatterino::messages; namespace chatterino { -EmoteManager EmoteManager::instance; - -EmoteManager::EmoteManager() - : _twitchEmotes() - , _bttvEmotes() - , _ffzEmotes() - , _chatterinoEmotes() - , _bttvChannelEmoteFromCaches() - , _ffzChannelEmoteFromCaches() - , _twitchEmoteFromCache() - , _miscImageFromCache() - , _gifUpdateTimerSignal() - , _gifUpdateTimer() - , _gifUpdateTimerInitiated(false) - , _generation(0) +EmoteManager::EmoteManager(WindowManager &_windowManager, Resources &_resources) + : windowManager(_windowManager) + , resources(_resources) { + // Note: Do not use this->resources in ctor +} + +void EmoteManager::loadGlobalEmotes() +{ + this->loadBTTVEmotes(); + this->loadFFZEmotes(); +} + +void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName, + BTTVEmoteMap &channelEmoteMap) +{ + printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName)); + + QString url("https://api.betterttv.net/2/channels/" + channelName); + util::urlJsonFetch(url, [this, &channelEmoteMap](QJsonObject &rootNode) { + channelEmoteMap.clear(); + + auto emotesNode = rootNode.value("emotes").toArray(); + + QString linkTemplate = "https:" + rootNode.value("urlTemplate").toString(); + + for (const QJsonValue &emoteNode : emotesNode) { + QJsonObject emoteObject = emoteNode.toObject(); + + QString id = emoteObject.value("id").toString(); + QString code = emoteObject.value("code").toString(); + // emoteObject.value("imageType").toString(); + + QString link = linkTemplate; + link.detach(); + + link = link.replace("{{id}}", id).replace("{{image}}", "1x"); + + auto emote = this->getBTTVChannelEmoteFromCaches().getOrAdd(id, [this, &code, &link] { + return new LazyLoadedImage(*this, this->windowManager, link, 1, code, + code + "\nChannel BTTV Emote"); + }); + + this->bttvChannelEmotes.insert(code, emote); + channelEmoteMap.insert(code, emote); + } + }); +} + +void EmoteManager::reloadFFZChannelEmotes( + const QString &channelName, + ConcurrentMap &channelEmoteMap) +{ + printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName)); + + QString url("http://api.frankerfacez.com/v1/room/" + channelName); + + util::urlJsonFetch(url, [this, &channelEmoteMap](QJsonObject &rootNode) { + channelEmoteMap.clear(); + + auto setsNode = rootNode.value("sets").toObject(); + + for (const QJsonValue &setNode : setsNode) { + auto emotesNode = setNode.toObject().value("emoticons").toArray(); + + for (const QJsonValue &emoteNode : emotesNode) { + QJsonObject emoteObject = emoteNode.toObject(); + + // margins + int id = emoteObject.value("id").toInt(); + QString code = emoteObject.value("name").toString(); + + QJsonObject urls = emoteObject.value("urls").toObject(); + QString url1 = "http:" + urls.value("1").toString(); + + auto emote = + this->getFFZChannelEmoteFromCaches().getOrAdd(id, [this, &code, &url1] { + return new LazyLoadedImage(*this, this->windowManager, url1, 1, code, + code + "\nGlobal FFZ Emote"); + }); + + this->ffzChannelEmotes.insert(code, emote); + channelEmoteMap.insert(code, emote); + } + } + }); } ConcurrentMap &EmoteManager::getTwitchEmotes() @@ -41,12 +113,12 @@ ConcurrentMap &EmoteManager::getTwitchEmotes() return _twitchEmotes; } -ConcurrentMap &EmoteManager::getBttvEmotes() +ConcurrentMap &EmoteManager::getBTTVEmotes() { return _bttvEmotes; } -ConcurrentMap &EmoteManager::getFfzEmotes() +ConcurrentMap &EmoteManager::getFFZEmotes() { return _ffzEmotes; } @@ -56,12 +128,12 @@ ConcurrentMap &EmoteManager::getChatterino return _chatterinoEmotes; } -ConcurrentMap &EmoteManager::getBttvChannelEmoteFromCaches() +ConcurrentMap &EmoteManager::getBTTVChannelEmoteFromCaches() { return _bttvChannelEmoteFromCaches; } -ConcurrentMap &EmoteManager::getFfzChannelEmoteFromCaches() +ConcurrentMap &EmoteManager::getFFZChannelEmoteFromCaches() { return _ffzChannelEmoteFromCaches; } @@ -76,13 +148,7 @@ ConcurrentMap &EmoteManager::getMiscImageF return _miscImageFromCache; } -void EmoteManager::loadGlobalEmotes() -{ - loadBttvEmotes(); - loadFfzEmotes(); -} - -void EmoteManager::loadBttvEmotes() +void EmoteManager::loadBTTVEmotes() { // bttv QNetworkAccessManager *manager = new QNetworkAccessManager(); @@ -111,8 +177,9 @@ void EmoteManager::loadBttvEmotes() tmp.detach(); QString url = tmp.replace("{{id}}", id).replace("{{image}}", "1x"); - EmoteManager::getBttvEmotes().insert( - code, new LazyLoadedImage(url, 1, code, code + "\nGlobal Bttv Emote")); + EmoteManager::getBTTVEmotes().insert( + code, new LazyLoadedImage(*this, this->windowManager, url, 1, code, + code + "\nGlobal BTTV Emote")); } } @@ -121,7 +188,7 @@ void EmoteManager::loadBttvEmotes() }); } -void EmoteManager::loadFfzEmotes() +void EmoteManager::loadFFZEmotes() { // ffz QNetworkAccessManager *manager = new QNetworkAccessManager(); @@ -153,8 +220,9 @@ void EmoteManager::loadFfzEmotes() QJsonObject urls = object.value("urls").toObject(); QString url1 = "http:" + urls.value("1").toString(); - EmoteManager::getBttvEmotes().insert( - code, new LazyLoadedImage(url1, 1, code, code + "\nGlobal Ffz Emote")); + EmoteManager::getBTTVEmotes().insert( + code, new LazyLoadedImage(*this, this->windowManager, url1, 1, code, + code + "\nGlobal FFZ Emote")); } } } @@ -166,11 +234,12 @@ void EmoteManager::loadFfzEmotes() LazyLoadedImage *EmoteManager::getTwitchEmoteById(const QString &name, long id) { - return EmoteManager::_twitchEmoteFromCache.getOrAdd(id, [&name, &id] { + return EmoteManager::_twitchEmoteFromCache.getOrAdd(id, [this, &name, &id] { qDebug() << "added twitch emote: " << id; qreal scale; QString url = getTwitchEmoteLink(id, scale); - return new LazyLoadedImage(url, scale, name, name + "\nTwitch Emote"); + return new LazyLoadedImage(*this, this->windowManager, url, scale, name, + name + "\nTwitch Emote"); }); } @@ -188,24 +257,41 @@ QString EmoteManager::getTwitchEmoteLink(long id, qreal &scale) LazyLoadedImage *EmoteManager::getCheerImage(long long amount, bool animated) { // TODO: fix this xD - return getCheerBadge(amount); + return this->getCheerBadge(amount); } LazyLoadedImage *EmoteManager::getCheerBadge(long long amount) { if (amount >= 100000) { - return Resources::getCheerBadge100000(); + return this->resources.cheerBadge100000; } else if (amount >= 10000) { - return Resources::getCheerBadge10000(); + return this->resources.cheerBadge10000; } else if (amount >= 5000) { - return Resources::getCheerBadge5000(); + return this->resources.cheerBadge5000; } else if (amount >= 1000) { - return Resources::getCheerBadge1000(); + return this->resources.cheerBadge1000; } else if (amount >= 100) { - return Resources::getCheerBadge100(); + return this->resources.cheerBadge100; } else { - return Resources::getCheerBadge1(); + return this->resources.cheerBadge1; } } +boost::signals2::signal &EmoteManager::getGifUpdateSignal() +{ + if (!_gifUpdateTimerInitiated) { + _gifUpdateTimerInitiated = true; + + _gifUpdateTimer.setInterval(30); + _gifUpdateTimer.start(); + + QObject::connect(&_gifUpdateTimer, &QTimer::timeout, [this] { + _gifUpdateTimerSignal(); + this->windowManager.repaintGifEmotes(); + }); + } + + return _gifUpdateTimerSignal; +} + } // namespace chatterino diff --git a/src/emotemanager.hpp b/src/emotemanager.hpp index d9da5cc9..cc68a70c 100644 --- a/src/emotemanager.hpp +++ b/src/emotemanager.hpp @@ -5,7 +5,6 @@ #include "concurrentmap.hpp" #include "messages/lazyloadedimage.hpp" #include "twitch/emotevalue.hpp" -#include "windowmanager.hpp" #include #include @@ -13,25 +12,33 @@ #include namespace chatterino { + +class WindowManager; +class Resources; + class EmoteManager { public: - static EmoteManager &getInstance() - { - return instance; - } + using FFZEmoteMap = ConcurrentMap; + using BTTVEmoteMap = ConcurrentMap; + using ChatterinoEmoteMap = ConcurrentMap; - ConcurrentMap &getTwitchEmotes(); - ConcurrentMap &getBttvEmotes(); - ConcurrentMap &getFfzEmotes(); - ConcurrentMap &getChatterinoEmotes(); - ConcurrentMap &getBttvChannelEmoteFromCaches(); - ConcurrentMap &getFfzChannelEmoteFromCaches(); - ConcurrentMap &getTwitchEmoteFromCache(); - ConcurrentMap &getMiscImageFromCache(); + EmoteManager(WindowManager &_windowManager, Resources &_resources); void loadGlobalEmotes(); + void reloadBTTVChannelEmotes(const QString &channelName, BTTVEmoteMap &channelEmoteMap); + void reloadFFZChannelEmotes(const QString &channelName, FFZEmoteMap &channelEmoteMap); + + ConcurrentMap &getTwitchEmotes(); + ConcurrentMap &getBTTVEmotes(); + ConcurrentMap &getFFZEmotes(); + ConcurrentMap &getChatterinoEmotes(); + ConcurrentMap &getBTTVChannelEmoteFromCaches(); + ConcurrentMap &getFFZChannelEmoteFromCaches(); + ConcurrentMap &getTwitchEmoteFromCache(); + ConcurrentMap &getMiscImageFromCache(); + messages::LazyLoadedImage *getCheerImage(long long int amount, bool animated); messages::LazyLoadedImage *getCheerBadge(long long int amount); @@ -47,29 +54,15 @@ public: _generation++; } - boost::signals2::signal &getGifUpdateSignal() - { - if (!_gifUpdateTimerInitiated) { - _gifUpdateTimerInitiated = true; - - _gifUpdateTimer.setInterval(30); - _gifUpdateTimer.start(); - - QObject::connect(&_gifUpdateTimer, &QTimer::timeout, [this] { - _gifUpdateTimerSignal(); - WindowManager::getInstance().repaintGifEmotes(); - }); - } - - return _gifUpdateTimerSignal; - } + boost::signals2::signal &getGifUpdateSignal(); private: - static EmoteManager instance; + WindowManager &windowManager; + Resources &resources; - EmoteManager(); + ConcurrentMap bttvChannelEmotes; + ConcurrentMap ffzChannelEmotes; - // variables ConcurrentMap _twitchEmotes; ConcurrentMap _bttvEmotes; ConcurrentMap _ffzEmotes; @@ -81,15 +74,15 @@ private: boost::signals2::signal _gifUpdateTimerSignal; QTimer _gifUpdateTimer; - bool _gifUpdateTimerInitiated; + bool _gifUpdateTimerInitiated = false; - int _generation; + int _generation = 0; // methods static QString getTwitchEmoteLink(long id, qreal &scale); - void loadFfzEmotes(); - void loadBttvEmotes(); + void loadFFZEmotes(); + void loadBTTVEmotes(); }; } // namespace chatterino diff --git a/src/ircmanager.cpp b/src/ircmanager.cpp index b2a3eea0..a702faed 100644 --- a/src/ircmanager.cpp +++ b/src/ircmanager.cpp @@ -3,14 +3,15 @@ #include "asyncexec.hpp" #include "channel.hpp" #include "channelmanager.hpp" +#include "emotemanager.hpp" #include "messages/messageparseargs.hpp" #include "twitch/twitchmessagebuilder.hpp" #include "twitch/twitchparsemessage.hpp" #include "twitch/twitchuser.hpp" +#include "windowmanager.hpp" #include #include - #include #include #include @@ -23,12 +24,15 @@ using namespace chatterino::messages; namespace chatterino { -IrcManager IrcManager::instance; - const QString IrcManager::defaultClientId("7ue61iz46fz11y3cugd0l3tawb4taal"); -IrcManager::IrcManager() - : _account(AccountManager::getInstance().getTwitchUser()) +IrcManager::IrcManager(ChannelManager &_channelManager, Resources &_resources, + EmoteManager &_emoteManager, WindowManager &_windowManager) + : channelManager(_channelManager) + , resources(_resources) + , emoteManager(_emoteManager) + , windowManager(_windowManager) + , _account(AccountManager::getInstance().getTwitchUser()) { } @@ -168,7 +172,7 @@ void IrcManager::beginConnecting() this->writeConnection->moveToThread(QCoreApplication::instance()->thread()); this->readConnection->moveToThread(QCoreApplication::instance()->thread()); - for (auto &channel : ChannelManager::getInstance().getItems()) { + for (auto &channel : this->channelManager.getItems()) { this->writeConnection->sendRaw("JOIN #" + channel->getName()); this->readConnection->sendRaw("JOIN #" + channel->getName()); } @@ -231,12 +235,14 @@ void IrcManager::partChannel(const QString &channelName) void IrcManager::messageReceived(Communi::IrcMessage *message) { + /* qDebug() << "Message received: " << message->command(); // qInfo(message->command().toStdString().c_str()); // for (const auto ¶m : message->parameters()) { qDebug() << "Param: " << param; } + */ /* const QString &command = message->command(); @@ -252,12 +258,13 @@ void IrcManager::messageReceived(Communi::IrcMessage *message) void IrcManager::privateMessageReceived(Communi::IrcPrivateMessage *message) { - auto c = ChannelManager::getInstance().getChannel(message->target().mid(1)); + auto c = this->channelManager.getChannel(message->target().mid(1)); if (c != nullptr) { messages::MessageParseArgs args; - c->addMessage(twitch::TwitchMessageBuilder::parse(message, c.get(), args)); + c->addMessage(twitch::TwitchMessageBuilder::parse(message, c.get(), args, this->resources, + this->emoteManager, this->windowManager)); } } diff --git a/src/ircmanager.hpp b/src/ircmanager.hpp index d701b8ec..3eaadc34 100644 --- a/src/ircmanager.hpp +++ b/src/ircmanager.hpp @@ -16,15 +16,18 @@ namespace chatterino { +class ChannelManager; +class Resources; +class EmoteManager; +class WindowManager; + class IrcManager : public QObject { Q_OBJECT public: - static IrcManager &getInstance() - { - return instance; - } + IrcManager(ChannelManager &_channelManager, Resources &_resources, EmoteManager &_emoteManager, + WindowManager &_windowManager); static const QString defaultClientId; @@ -48,8 +51,10 @@ public: void setUser(const twitch::TwitchUser &account); private: - static IrcManager instance; - IrcManager(); + ChannelManager &channelManager; + Resources &resources; + EmoteManager &emoteManager; + WindowManager &windowManager; // variables twitch::TwitchUser _account; diff --git a/src/main.cpp b/src/main.cpp index bf6af7c5..635aef48 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,4 @@ +#include "application.hpp" #include "channelmanager.hpp" #include "colorscheme.hpp" #include "emojis.hpp" @@ -16,9 +17,6 @@ #include #include -using namespace chatterino; -using namespace chatterino::widgets; - namespace { inline bool initSettings(bool portable) @@ -68,28 +66,25 @@ int main(int argc, char *argv[]) } chatterino::logging::init(); - SettingsManager::getInstance().load(); - Resources::load(); - Emojis::loadEmojis(); - EmoteManager::getInstance().loadGlobalEmotes(); + chatterino::SettingsManager::getInstance().load(); + chatterino::Emojis::loadEmojis(); - ColorScheme::getInstance().init(); + int ret = 0; - WindowManager::getInstance().load(); + { + // Initialize application + chatterino::Application app; - MainWindow &w = WindowManager::getInstance().getMainWindow(); - w.show(); + // Start the application + ret = app.run(a); - IrcManager::getInstance().connect(); + // Application will go out of scope here and deinitialize itself + } - int ret = a.exec(); - - SettingsManager::getInstance().save(); + chatterino::SettingsManager::getInstance().save(); // Save settings pajlada::Settings::SettingManager::save(); - WindowManager::getInstance().save(); - return ret; } diff --git a/src/messages/lazyloadedimage.cpp b/src/messages/lazyloadedimage.cpp index 1502be22..734940a1 100644 --- a/src/messages/lazyloadedimage.cpp +++ b/src/messages/lazyloadedimage.cpp @@ -1,5 +1,4 @@ #include "messages/lazyloadedimage.hpp" - #include "asyncexec.hpp" #include "emotemanager.hpp" #include "ircmanager.hpp" @@ -18,15 +17,15 @@ namespace chatterino { namespace messages { -LazyLoadedImage::LazyLoadedImage(const QString &url, qreal scale, const QString &name, +LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager, + const QString &url, qreal scale, const QString &name, const QString &tooltip, const QMargins &margin, bool isHat) - : _currentPixmap(nullptr) - , _currentFrame(0) - , _currentFrameOffset(0) + : emoteManager(_emoteManager) + , windowManager(_windowManager) + , _currentPixmap(nullptr) , _url(url) , _name(name) , _tooltip(tooltip) - , _animated(false) , _margin(margin) , _ishat(isHat) , _scale(scale) @@ -34,14 +33,14 @@ LazyLoadedImage::LazyLoadedImage(const QString &url, qreal scale, const QString { } -LazyLoadedImage::LazyLoadedImage(QPixmap *image, qreal scale, const QString &name, +LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager, + QPixmap *image, qreal scale, const QString &name, const QString &tooltip, const QMargins &margin, bool isHat) - : _currentPixmap(image) - , _currentFrame(0) - , _currentFrameOffset(0) + : emoteManager(_emoteManager) + , windowManager(_windowManager) + , _currentPixmap(image) , _name(name) , _tooltip(tooltip) - , _animated(false) , _margin(margin) , _ishat(isHat) , _scale(scale) @@ -81,11 +80,13 @@ void LazyLoadedImage::loadImage() if (_allFrames.size() > 1) { _animated = true; - EmoteManager::getInstance().getGifUpdateSignal().connect([this] { gifUpdateTimout(); }); + this->emoteManager.getGifUpdateSignal().connect([this] { + gifUpdateTimout(); // + }); } - EmoteManager::getInstance().incGeneration(); - WindowManager::getInstance().layoutVisibleChatWidgets(); + this->emoteManager.incGeneration(); + this->windowManager.layoutVisibleChatWidgets(); }); } diff --git a/src/messages/lazyloadedimage.hpp b/src/messages/lazyloadedimage.hpp index 5397e14a..6c922c8d 100644 --- a/src/messages/lazyloadedimage.hpp +++ b/src/messages/lazyloadedimage.hpp @@ -4,15 +4,24 @@ #include namespace chatterino { + +class EmoteManager; +class WindowManager; + namespace messages { class LazyLoadedImage : QObject { public: - explicit LazyLoadedImage(const QString &_url, qreal _scale = 1, const QString &_name = "", + LazyLoadedImage() = delete; + + explicit LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager, + const QString &_url, qreal _scale = 1, const QString &_name = "", const QString &_tooltip = "", const QMargins &_margin = QMargins(), bool isHat = false); - explicit LazyLoadedImage(QPixmap *_currentPixmap, qreal _scale = 1, const QString &_name = "", + + explicit LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager, + QPixmap *_currentPixmap, qreal _scale = 1, const QString &_name = "", const QString &_tooltip = "", const QMargins &_margin = QMargins(), bool isHat = false); @@ -78,6 +87,9 @@ public: } private: + EmoteManager &emoteManager; + WindowManager &windowManager; + struct FrameData { QPixmap *image; int duration; @@ -85,13 +97,13 @@ private: QPixmap *_currentPixmap; std::vector _allFrames; - int _currentFrame; - int _currentFrameOffset; + int _currentFrame = 0; + int _currentFrameOffset = 0; QString _url; QString _name; QString _tooltip; - bool _animated; + bool _animated = false; QMargins _margin; bool _ishat; qreal _scale; diff --git a/src/messages/message.cpp b/src/messages/message.cpp index 90d46a8d..a016e51c 100644 --- a/src/messages/message.cpp +++ b/src/messages/message.cpp @@ -21,16 +21,16 @@ namespace chatterino { namespace messages { Message::Message(const QString &text) - : _words() - , _text(text) + : _text(text) + , _words() { _words.push_back( Word(text, Word::Text, ColorScheme::getInstance().SystemMessageColor, text, QString())); } Message::Message(const QString &text, const std::vector &words) - : _words(words) - , _text(text) + : _text(text) + , _words(words) { } diff --git a/src/messages/message.hpp b/src/messages/message.hpp index 7caca9d8..1ca09786 100644 --- a/src/messages/message.hpp +++ b/src/messages/message.hpp @@ -23,8 +23,8 @@ typedef std::shared_ptr SharedMessage; class Message { public: - Message(const QString &text); - Message(const QString &text, const std::vector &words); + explicit Message(const QString &text); + explicit Message(const QString &text, const std::vector &words); bool getCanHighlightTab() const; const QString &getTimeoutUser() const; diff --git a/src/messages/messageref.cpp b/src/messages/messageref.cpp index 402f82be..28e5efad 100644 --- a/src/messages/messageref.cpp +++ b/src/messages/messageref.cpp @@ -41,7 +41,11 @@ bool MessageRef::layout(int width, bool enableEmoteMargins) int mediumTextLineHeight = FontManager::getInstance().getFontMetrics(FontManager::Medium).height(); + /* TODO(pajlada): Re-implement bool recalculateImages = _emoteGeneration != EmoteManager::getInstance().getGeneration(); + */ + bool recalculateImages = true; + bool recalculateText = _fontGeneration != FontManager::getInstance().getGeneration(); bool newWordTypes = _currentWordTypes != SettingsManager::getInstance().getWordTypeMask(); @@ -53,7 +57,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins) return false; } - _emoteGeneration = EmoteManager::getInstance().getGeneration(); + // _emoteGeneration = EmoteManager::getInstance().getGeneration(); _fontGeneration = FontManager::getInstance().getGeneration(); for (auto &word : _message->getWords()) { diff --git a/src/resources.cpp b/src/resources.cpp index fc31b563..4c87917f 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -1,60 +1,39 @@ #include "resources.hpp" +#include "emotemanager.hpp" +#include "windowmanager.hpp" #include namespace chatterino { -messages::LazyLoadedImage *Resources::badgeStaff(nullptr); -messages::LazyLoadedImage *Resources::badgeAdmin(nullptr); -messages::LazyLoadedImage *Resources::badgeModerator(nullptr); -messages::LazyLoadedImage *Resources::badgeGlobalmod(nullptr); -messages::LazyLoadedImage *Resources::badgeTurbo(nullptr); -messages::LazyLoadedImage *Resources::badgeBroadcaster(nullptr); -messages::LazyLoadedImage *Resources::badgePremium(nullptr); +namespace { -messages::LazyLoadedImage *Resources::cheerBadge100000(nullptr); -messages::LazyLoadedImage *Resources::cheerBadge10000(nullptr); -messages::LazyLoadedImage *Resources::cheerBadge5000(nullptr); -messages::LazyLoadedImage *Resources::cheerBadge1000(nullptr); -messages::LazyLoadedImage *Resources::cheerBadge100(nullptr); -messages::LazyLoadedImage *Resources::cheerBadge1(nullptr); - -messages::LazyLoadedImage *Resources::buttonBan(nullptr); -messages::LazyLoadedImage *Resources::buttonTimeout(nullptr); - -Resources::Resources() +inline messages::LazyLoadedImage *lli(EmoteManager &emoteManager, WindowManager &windowManager, + const char *pixmapPath, qreal scale = 1) { + return new messages::LazyLoadedImage(emoteManager, windowManager, new QPixmap(pixmapPath), + scale); } -void Resources::load() +} // namespace + +Resources::Resources(EmoteManager &emoteManager, WindowManager &windowManager) + : badgeStaff(lli(emoteManager, windowManager, ":/images/staff_bg.png")) + , badgeAdmin(lli(emoteManager, windowManager, ":/images/admin_bg.png")) + , badgeGlobalModerator(lli(emoteManager, windowManager, ":/images/globalmod_bg.png")) + , badgeModerator(lli(emoteManager, windowManager, ":/images/moderator_bg.png")) + , badgeTurbo(lli(emoteManager, windowManager, ":/images/turbo_bg.png")) + , badgeBroadcaster(lli(emoteManager, windowManager, ":/images/broadcaster_bg.png")) + , badgePremium(lli(emoteManager, windowManager, ":/images/twitchprime_bg.png")) + , cheerBadge100000(lli(emoteManager, windowManager, ":/images/cheer100000")) + , cheerBadge10000(lli(emoteManager, windowManager, ":/images/cheer10000")) + , cheerBadge5000(lli(emoteManager, windowManager, ":/images/cheer5000")) + , cheerBadge1000(lli(emoteManager, windowManager, ":/images/cheer1000")) + , cheerBadge100(lli(emoteManager, windowManager, ":/images/cheer100")) + , cheerBadge1(lli(emoteManager, windowManager, ":/images/cheer1")) + , buttonBan(lli(emoteManager, windowManager, ":/images/button_ban.png", 0.25)) + , buttonTimeout(lli(emoteManager, windowManager, ":/images/button_timeout.png", 0.25)) { - // badges - Resources::badgeStaff = new messages::LazyLoadedImage(new QPixmap(":/images/staff_bg.png")); - Resources::badgeAdmin = new messages::LazyLoadedImage(new QPixmap(":/images/admin_bg.png")); - Resources::badgeModerator = - new messages::LazyLoadedImage(new QPixmap(":/images/moderator_bg.png")); - Resources::badgeGlobalmod = - new messages::LazyLoadedImage(new QPixmap(":/images/globalmod_bg.png")); - Resources::badgeTurbo = new messages::LazyLoadedImage(new QPixmap(":/images/turbo_bg.png")); - Resources::badgeBroadcaster = - new messages::LazyLoadedImage(new QPixmap(":/images/broadcaster_bg.png")); - Resources::badgePremium = - new messages::LazyLoadedImage(new QPixmap(":/images/twitchprime_bg.png")); - - // cheer badges - Resources::cheerBadge100000 = - new messages::LazyLoadedImage(new QPixmap(":/images/cheer100000")); - Resources::cheerBadge10000 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer10000")); - Resources::cheerBadge5000 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer5000")); - Resources::cheerBadge1000 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer1000")); - Resources::cheerBadge100 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer100")); - Resources::cheerBadge1 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer1")); - - // button - Resources::buttonBan = - new messages::LazyLoadedImage(new QPixmap(":/images/button_ban.png"), 0.25); - Resources::buttonTimeout = - new messages::LazyLoadedImage(new QPixmap(":/images/button_timeout.png"), 0.25); } } // namespace chatterino diff --git a/src/resources.hpp b/src/resources.hpp index 2bbee465..06f93c66 100644 --- a/src/resources.hpp +++ b/src/resources.hpp @@ -4,108 +4,31 @@ namespace chatterino { +class EmoteManager; +class WindowManager; + class Resources { public: - static void load(); + explicit Resources(EmoteManager &emoteManager, WindowManager &windowManager); - // badges - static messages::LazyLoadedImage *getBadgeStaff() - { - return badgeStaff; - } + messages::LazyLoadedImage *badgeStaff; + messages::LazyLoadedImage *badgeAdmin; + messages::LazyLoadedImage *badgeGlobalModerator; + messages::LazyLoadedImage *badgeModerator; + messages::LazyLoadedImage *badgeTurbo; + messages::LazyLoadedImage *badgeBroadcaster; + messages::LazyLoadedImage *badgePremium; - static messages::LazyLoadedImage *getBadgeAdmin() - { - return badgeAdmin; - } + messages::LazyLoadedImage *cheerBadge100000; + messages::LazyLoadedImage *cheerBadge10000; + messages::LazyLoadedImage *cheerBadge5000; + messages::LazyLoadedImage *cheerBadge1000; + messages::LazyLoadedImage *cheerBadge100; + messages::LazyLoadedImage *cheerBadge1; - static messages::LazyLoadedImage *getBadgeGlobalmod() - { - return badgeGlobalmod; - } - - static messages::LazyLoadedImage *getBadgeModerator() - { - return badgeModerator; - } - - static messages::LazyLoadedImage *getBadgeTurbo() - { - return badgeTurbo; - } - - static messages::LazyLoadedImage *getBadgeBroadcaster() - { - return badgeBroadcaster; - } - - static messages::LazyLoadedImage *getBadgePremium() - { - return badgePremium; - } - - // cheer badges - static messages::LazyLoadedImage *getCheerBadge100000() - { - return cheerBadge100000; - } - - static messages::LazyLoadedImage *getCheerBadge10000() - { - return cheerBadge10000; - } - - static messages::LazyLoadedImage *getCheerBadge5000() - { - return cheerBadge5000; - } - - static messages::LazyLoadedImage *getCheerBadge1000() - { - return cheerBadge1000; - } - - static messages::LazyLoadedImage *getCheerBadge100() - { - return cheerBadge100; - } - - static messages::LazyLoadedImage *getCheerBadge1() - { - return cheerBadge1; - } - - static messages::LazyLoadedImage *getButtonBan() - { - return buttonBan; - } - - static messages::LazyLoadedImage *getButtonTimeout() - { - return buttonTimeout; - } - -private: - Resources(); - - static messages::LazyLoadedImage *badgeStaff; - static messages::LazyLoadedImage *badgeAdmin; - static messages::LazyLoadedImage *badgeGlobalmod; - static messages::LazyLoadedImage *badgeModerator; - static messages::LazyLoadedImage *badgeTurbo; - static messages::LazyLoadedImage *badgeBroadcaster; - static messages::LazyLoadedImage *badgePremium; - - static messages::LazyLoadedImage *cheerBadge100000; - static messages::LazyLoadedImage *cheerBadge10000; - static messages::LazyLoadedImage *cheerBadge5000; - static messages::LazyLoadedImage *cheerBadge1000; - static messages::LazyLoadedImage *cheerBadge100; - static messages::LazyLoadedImage *cheerBadge1; - - static messages::LazyLoadedImage *buttonBan; - static messages::LazyLoadedImage *buttonTimeout; + messages::LazyLoadedImage *buttonBan; + messages::LazyLoadedImage *buttonTimeout; }; } // namespace chatterino diff --git a/src/settingsmanager.hpp b/src/settingsmanager.hpp index 509f636e..a300ef87 100644 --- a/src/settingsmanager.hpp +++ b/src/settingsmanager.hpp @@ -34,6 +34,7 @@ private: messages::Word::Type _wordTypeMask = messages::Word::Default; // methods +public: // temporary void updateWordTypeMask(); public: diff --git a/src/twitch/twitchmessagebuilder.cpp b/src/twitch/twitchmessagebuilder.cpp index dfff760a..96ac5a1b 100644 --- a/src/twitch/twitchmessagebuilder.cpp +++ b/src/twitch/twitchmessagebuilder.cpp @@ -4,6 +4,7 @@ #include "emotemanager.hpp" #include "ircmanager.hpp" #include "resources.hpp" +#include "windowmanager.hpp" using namespace chatterino::messages; @@ -17,45 +18,15 @@ TwitchMessageBuilder::TwitchMessageBuilder() { } -void TwitchMessageBuilder::appendTwitchBadges(const QStringList &badges) -{ - for (QString badge : badges) { - if (badge.startsWith("bits/")) { - long long int cheer = std::strtoll(badge.mid(5).toStdString().c_str(), nullptr, 10); - appendWord(Word(EmoteManager::getInstance().getCheerBadge(cheer), Word::BadgeCheer, - QString(), QString("Twitch Cheer" + QString::number(cheer)))); - } else if (badge == "staff/1") { - appendWord(Word(Resources::getBadgeStaff(), Word::BadgeStaff, QString(), - QString("Twitch Staff"))); - } else if (badge == "admin/1") { - appendWord(Word(Resources::getBadgeAdmin(), Word::BadgeAdmin, QString(), - QString("Twitch Admin"))); - } else if (badge == "global_mod/1") { - appendWord(Word(Resources::getBadgeGlobalmod(), Word::BadgeGlobalMod, QString(), - QString("Global Moderator"))); - } else if (badge == "moderator/1") { - // TODO: implement this xD - appendWord(Word(Resources::getBadgeTurbo(), Word::BadgeModerator, QString(), - QString("Channel Moderator"))); // custom badge - } else if (badge == "turbo/1") { - appendWord(Word(Resources::getBadgeStaff(), Word::BadgeTurbo, QString(), - QString("Turbo Subscriber"))); - } else if (badge == "broadcaster/1") { - appendWord(Word(Resources::getBadgeBroadcaster(), Word::BadgeBroadcaster, QString(), - QString("Channel Broadcaster"))); - } else if (badge == "premium/1") { - appendWord(Word(Resources::getBadgePremium(), Word::BadgePremium, QString(), - QString("Twitch Prime"))); - } - } -} - SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircMessage, - Channel *channel, const MessageParseArgs &args) + Channel *channel, const MessageParseArgs &args, + const Resources &resources, EmoteManager &emoteManager, + WindowManager &windowManager) { TwitchMessageBuilder b; - // timestamp + // The timestamp is always appended to the builder + // Whether or not will be rendered is decided/checked later b.appendTimestamp(); auto tags = ircMessage->tags(); @@ -69,14 +40,7 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM // timestamps iterator = tags.find("tmi-sent-ts"); - // mod buttons - static QString buttonBanTooltip("Ban user"); - static QString buttonTimeoutTooltip("Timeout user"); - - b.appendWord(Word(Resources::getButtonBan(), Word::ButtonBan, QString(), buttonBanTooltip, - Link(Link::UserBan, ircMessage->account()))); - b.appendWord(Word(Resources::getButtonTimeout(), Word::ButtonTimeout, QString(), - buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account()))); + b.appendModerationWords(ircMessage, resources); // badges iterator = tags.find("badges"); @@ -84,7 +48,7 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM if (iterator != tags.end()) { auto badges = iterator.value().toString().split(','); - b.appendTwitchBadges(badges); + b.appendTwitchBadges(badges, resources, emoteManager); } // color @@ -124,11 +88,13 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM displayName + (hasLocalizedName ? (" (" + ircMessage->account() + ")") : QString()); if (args.isSentWhisper) { - userDisplayString += IrcManager::getInstance().getUser().getUserName(); + // TODO(pajlada): Re-implement + // userDisplayString += IrcManager::getInstance().getUser().getUserName(); } if (args.isReceivedWhisper) { - userDisplayString += " -> " + IrcManager::getInstance().getUser().getUserName(); + // TODO(pajlada): Re-implement + // userDisplayString += " -> " + IrcManager::getInstance().getUser().getUserName(); } if (!ircMessage->isAction()) { @@ -153,40 +119,11 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM std::vector> twitchEmotes; iterator = tags.find("emotes"); - if (iterator != tags.end()) { - auto emotes = iterator.value().toString().split('/'); + QStringList emoteString = iterator.value().toString().split('/'); - for (QString emote : emotes) { - if (!emote.contains(':')) - continue; - - QStringList parameters = emote.split(':'); - - if (parameters.length() < 2) - continue; - - long int id = std::stol(parameters.at(0).toStdString(), nullptr, 10); - - QStringList occurences = parameters.at(1).split(','); - - for (QString occurence : occurences) { - QStringList coords = occurence.split('-'); - - if (coords.length() < 2) - continue; - - long int start = std::stol(coords.at(0).toStdString(), nullptr, 10); - long int end = std::stol(coords.at(1).toStdString(), nullptr, 10); - - if (start >= end || start < 0 || end > ircMessage->content().length()) - continue; - - QString name = ircMessage->content().mid(start, end - start + 1); - - twitchEmotes.push_back(std::pair( - start, EmoteManager::getInstance().getTwitchEmoteById(name, id))); - } + for (QString emote : emoteString) { + b.appendTwitchEmote(ircMessage, emote, twitchEmotes, emoteManager); } struct { @@ -270,13 +207,15 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM QString bitsLink = QString("http://static-cdn.jtvnw.net/bits/dark/static/" + color + "/1"); - LazyLoadedImage *imageAnimated = - EmoteManager::getInstance().getMiscImageFromCache().getOrAdd( - bitsLinkAnimated, - [&bitsLinkAnimated] { return new LazyLoadedImage(bitsLinkAnimated); }); - LazyLoadedImage *image = - EmoteManager::getInstance().getMiscImageFromCache().getOrAdd( - bitsLink, [&bitsLink] { return new LazyLoadedImage(bitsLink); }); + LazyLoadedImage *imageAnimated = emoteManager.getMiscImageFromCache().getOrAdd( + bitsLinkAnimated, [&emoteManager, &windowManager, &bitsLinkAnimated] { + return new LazyLoadedImage(emoteManager, windowManager, + bitsLinkAnimated); + }); + LazyLoadedImage *image = emoteManager.getMiscImageFromCache().getOrAdd( + bitsLink, [&emoteManager, &windowManager, &bitsLink] { + return new LazyLoadedImage(emoteManager, windowManager, bitsLink); + }); b.appendWord(Word(imageAnimated, Word::BitsAnimated, QString("cheer"), QString("Twitch Cheer"), @@ -302,11 +241,11 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM LazyLoadedImage *bttvEmote; // TODO: Implement this (ignored emotes) - if (EmoteManager::getInstance().getBttvEmotes().tryGet(string, bttvEmote) || + if (emoteManager.getBTTVEmotes().tryGet(string, bttvEmote) || channel->getBttvChannelEmotes().tryGet(string, bttvEmote) || - EmoteManager::getInstance().getFfzEmotes().tryGet(string, bttvEmote) || + emoteManager.getFFZEmotes().tryGet(string, bttvEmote) || channel->getFfzChannelEmotes().tryGet(string, bttvEmote) || - EmoteManager::getInstance().getChatterinoEmotes().tryGet(string, bttvEmote)) { + emoteManager.getChatterinoEmotes().tryGet(string, bttvEmote)) { b.appendWord(Word(bttvEmote, Word::BttvEmoteImage, bttvEmote->getName(), bttvEmote->getTooltip(), Link(Link::Url, bttvEmote->getUrl()))); @@ -340,6 +279,92 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM return b.build(); } +void TwitchMessageBuilder::appendModerationWords(const Communi::IrcPrivateMessage *ircMessage, + const Resources &resources) +{ + // mod buttons + static QString buttonBanTooltip("Ban user"); + static QString buttonTimeoutTooltip("Timeout user"); + + this->appendWord(Word(resources.buttonBan, Word::ButtonBan, QString(), buttonBanTooltip, + Link(Link::UserBan, ircMessage->account()))); + this->appendWord(Word(resources.buttonTimeout, Word::ButtonTimeout, QString(), + buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account()))); +} + +void TwitchMessageBuilder::appendTwitchEmote( + const Communi::IrcPrivateMessage *ircMessage, const QString &emote, + std::vector> &vec, EmoteManager &emoteManager) +{ + if (!emote.contains(':')) { + return; + } + + QStringList parameters = emote.split(':'); + + if (parameters.length() < 2) { + return; + } + + long int id = std::stol(parameters.at(0).toStdString(), nullptr, 10); + + QStringList occurences = parameters.at(1).split(','); + + for (QString occurence : occurences) { + QStringList coords = occurence.split('-'); + + if (coords.length() < 2) { + return; + } + + long int start = std::stol(coords.at(0).toStdString(), nullptr, 10); + long int end = std::stol(coords.at(1).toStdString(), nullptr, 10); + + if (start >= end || start < 0 || end > ircMessage->content().length()) { + return; + } + + QString name = ircMessage->content().mid(start, end - start + 1); + + vec.push_back(std::pair( + start, emoteManager.getTwitchEmoteById(name, id))); + } +} + +void TwitchMessageBuilder::appendTwitchBadges(const QStringList &badges, const Resources &resources, + EmoteManager &emoteManager) +{ + for (QString badge : badges) { + if (badge.startsWith("bits/")) { + long long int cheer = std::strtoll(badge.mid(5).toStdString().c_str(), nullptr, 10); + appendWord(Word(emoteManager.getCheerBadge(cheer), Word::BadgeCheer, QString(), + QString("Twitch Cheer" + QString::number(cheer)))); + } else if (badge == "staff/1") { + appendWord( + Word(resources.badgeStaff, Word::BadgeStaff, QString(), QString("Twitch Staff"))); + } else if (badge == "admin/1") { + appendWord( + Word(resources.badgeAdmin, Word::BadgeAdmin, QString(), QString("Twitch Admin"))); + } else if (badge == "global_mod/1") { + appendWord(Word(resources.badgeGlobalModerator, Word::BadgeGlobalMod, QString(), + QString("Global Moderator"))); + } else if (badge == "moderator/1") { + // TODO: implement this xD + appendWord(Word(resources.badgeTurbo, Word::BadgeModerator, QString(), + QString("Channel Moderator"))); // custom badge + } else if (badge == "turbo/1") { + appendWord(Word(resources.badgeStaff, Word::BadgeTurbo, QString(), + QString("Turbo Subscriber"))); + } else if (badge == "broadcaster/1") { + appendWord(Word(resources.badgeBroadcaster, Word::BadgeBroadcaster, QString(), + QString("Channel Broadcaster"))); + } else if (badge == "premium/1") { + appendWord(Word(resources.badgePremium, Word::BadgePremium, QString(), + QString("Twitch Prime"))); + } + } +} + // bool // sortTwitchEmotes(const std::pair &a, // const std::pair &b) diff --git a/src/twitch/twitchmessagebuilder.hpp b/src/twitch/twitchmessagebuilder.hpp index 9fd4af56..53938d48 100644 --- a/src/twitch/twitchmessagebuilder.hpp +++ b/src/twitch/twitchmessagebuilder.hpp @@ -4,8 +4,14 @@ #include "messages/messagebuilder.hpp" #include +#include namespace chatterino { + +class Resources; +class EmoteManager; +class WindowManager; + namespace twitch { class TwitchMessageBuilder : public messages::MessageBuilder @@ -13,17 +19,26 @@ class TwitchMessageBuilder : public messages::MessageBuilder public: TwitchMessageBuilder(); - void appendTwitchBadges(const QStringList &badges); - QString messageId; QString userName; static messages::SharedMessage parse(const Communi::IrcPrivateMessage *ircMessage, - Channel *channel, const messages::MessageParseArgs &args); + Channel *channel, const messages::MessageParseArgs &args, + const Resources &resources, EmoteManager &emoteManager, + WindowManager &windowManager); // static bool sortTwitchEmotes( // const std::pair &a, // const std::pair &b); + +private: + void appendModerationWords(const Communi::IrcPrivateMessage *ircMessage, + const Resources &resources); + void appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage, const QString &emote, + std::vector> &vec, + EmoteManager &emoteManager); + void appendTwitchBadges(const QStringList &badges, const Resources &resources, + EmoteManager &emoteManager); }; } // namespace twitch diff --git a/src/widgets/chatwidget.cpp b/src/widgets/chatwidget.cpp index 3a01c0d3..afe51b67 100644 --- a/src/widgets/chatwidget.cpp +++ b/src/widgets/chatwidget.cpp @@ -30,9 +30,10 @@ inline void ezShortcut(ChatWidget *w, const char *key, T t) } // namespace -ChatWidget::ChatWidget(QWidget *parent) +ChatWidget::ChatWidget(ChannelManager &_channelManager, QWidget *parent) : QWidget(parent) - , channel(ChannelManager::getInstance().getEmpty()) + , channelManager(_channelManager) + , channel(_channelManager.getEmpty()) , vbox(this) , header(this) , view(this) @@ -90,7 +91,7 @@ void ChatWidget::setChannelName(const QString &_newChannelName) // remove current channel if (!this->channelName.isEmpty()) { - ChannelManager::getInstance().removeChannel(this->channelName); + this->channelManager.removeChannel(this->channelName); this->detachChannel(); } @@ -104,7 +105,7 @@ void ChatWidget::setChannelName(const QString &_newChannelName) if (newChannelName.isEmpty()) { this->channel = nullptr; } else { - this->setChannel(ChannelManager::getInstance().addChannel(newChannelName)); + this->setChannel(this->channelManager.addChannel(newChannelName)); } // update header @@ -240,7 +241,7 @@ void ChatWidget::doChangeChannel() void ChatWidget::doPopup() { // TODO: Copy signals and stuff too - auto widget = new ChatWidget(); + auto widget = new ChatWidget(this->channelManager); widget->setChannelName(this->getChannelName()); widget->show(); } diff --git a/src/widgets/chatwidget.hpp b/src/widgets/chatwidget.hpp index 9104ea68..2cc359ae 100644 --- a/src/widgets/chatwidget.hpp +++ b/src/widgets/chatwidget.hpp @@ -17,6 +17,9 @@ #include namespace chatterino { + +class ChannelManager; + namespace widgets { // Each ChatWidget consists of three sub-elements that handle their own part of the chat widget: @@ -34,7 +37,7 @@ class ChatWidget : public QWidget Q_OBJECT public: - ChatWidget(QWidget *parent = nullptr); + ChatWidget(ChannelManager &_channelManager, QWidget *parent = nullptr); ~ChatWidget(); std::shared_ptr getChannel() const; @@ -53,6 +56,8 @@ protected: void paintEvent(QPaintEvent *) override; private: + ChannelManager &channelManager; + void setChannel(std::shared_ptr newChannel); void detachChannel(); diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp index aaa819f1..f4a423dd 100644 --- a/src/widgets/mainwindow.cpp +++ b/src/widgets/mainwindow.cpp @@ -1,4 +1,5 @@ #include "widgets/mainwindow.hpp" +#include "channelmanager.hpp" #include "colorscheme.hpp" #include "settingsmanager.hpp" #include "widgets/chatwidget.hpp" @@ -18,9 +19,10 @@ namespace chatterino { namespace widgets { -MainWindow::MainWindow(QWidget *parent) +MainWindow::MainWindow(ChannelManager &_channelManager, QWidget *parent) : QWidget(parent) - , _notebook(this) + , channelManager(_channelManager) + , notebook(this->channelManager, this) , _loaded(false) , _titleBar() { @@ -31,7 +33,7 @@ MainWindow::MainWindow(QWidget *parent) // layout->addWidget(&_titleBar); // } - layout->addWidget(&_notebook); + layout->addWidget(&this->notebook); setLayout(layout); // set margin @@ -63,7 +65,7 @@ MainWindow::~MainWindow() void MainWindow::layoutVisibleChatWidgets(Channel *channel) { - auto *page = _notebook.getSelectedPage(); + auto *page = this->notebook.getSelectedPage(); if (page == nullptr) { return; @@ -82,7 +84,7 @@ void MainWindow::layoutVisibleChatWidgets(Channel *channel) void MainWindow::repaintVisibleChatWidgets(Channel *channel) { - auto *page = _notebook.getSelectedPage(); + auto *page = this->notebook.getSelectedPage(); if (page == nullptr) { return; @@ -101,7 +103,7 @@ void MainWindow::repaintVisibleChatWidgets(Channel *channel) void MainWindow::repaintGifEmotes() { - auto *page = _notebook.getSelectedPage(); + auto *page = this->notebook.getSelectedPage(); if (page == nullptr) { return; @@ -118,7 +120,7 @@ void MainWindow::repaintGifEmotes() void MainWindow::load(const boost::property_tree::ptree &tree) { - this->_notebook.load(tree); + this->notebook.load(tree); _loaded = true; } @@ -129,14 +131,14 @@ boost::property_tree::ptree MainWindow::save() child.put("type", "main"); - _notebook.save(child); + this->notebook.save(child); return child; } void MainWindow::loadDefaults() { - _notebook.loadDefaults(); + this->notebook.loadDefaults(); _loaded = true; } @@ -148,7 +150,7 @@ bool MainWindow::isLoaded() const Notebook &MainWindow::getNotebook() { - return _notebook; + return this->notebook; } } // namespace widgets diff --git a/src/widgets/mainwindow.hpp b/src/widgets/mainwindow.hpp index 3e41a8f8..d8c50c1b 100644 --- a/src/widgets/mainwindow.hpp +++ b/src/widgets/mainwindow.hpp @@ -11,6 +11,9 @@ #include namespace chatterino { + +class ChannelManager; + namespace widgets { class MainWindow : public QWidget @@ -18,7 +21,7 @@ class MainWindow : public QWidget Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(ChannelManager &_channelManager, QWidget *parent = nullptr); ~MainWindow(); void layoutVisibleChatWidgets(Channel *channel = nullptr); @@ -34,7 +37,9 @@ public: Notebook &getNotebook(); private: - Notebook _notebook; + ChannelManager &channelManager; + + Notebook notebook; bool _loaded; TitleBar _titleBar; }; diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index c849b093..2f56ec4a 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -18,8 +18,9 @@ namespace chatterino { namespace widgets { -Notebook::Notebook(QWidget *parent) +Notebook::Notebook(ChannelManager &_channelManager, QWidget *parent) : QWidget(parent) + , channelManager(_channelManager) , _addButton(this) , _settingsButton(this) , _userButton(this) @@ -47,7 +48,7 @@ Notebook::Notebook(QWidget *parent) NotebookPage *Notebook::addPage(bool select) { auto tab = new NotebookTab(this); - auto page = new NotebookPage(this, tab); + auto page = new NotebookPage(this->channelManager, this, tab); tab->show(); diff --git a/src/widgets/notebook.hpp b/src/widgets/notebook.hpp index c9259df5..08491ba1 100644 --- a/src/widgets/notebook.hpp +++ b/src/widgets/notebook.hpp @@ -9,6 +9,9 @@ #include namespace chatterino { + +class ChannelManager; + namespace widgets { class Notebook : public QWidget @@ -18,7 +21,7 @@ class Notebook : public QWidget public: enum HighlightType { none, highlighted, newMessage }; - Notebook(QWidget *parent); + Notebook(ChannelManager &_channelManager, QWidget *parent); NotebookPage *addPage(bool select = false); @@ -46,6 +49,8 @@ public slots: void addPageButtonClicked(); private: + ChannelManager &channelManager; + QList _pages; NotebookButton _addButton; diff --git a/src/widgets/notebookpage.cpp b/src/widgets/notebookpage.cpp index 3e8423c2..9fae9a3c 100644 --- a/src/widgets/notebookpage.cpp +++ b/src/widgets/notebookpage.cpp @@ -19,9 +19,10 @@ bool NotebookPage::isDraggingSplit = false; ChatWidget *NotebookPage::draggingSplit = nullptr; std::pair NotebookPage::dropPosition = std::pair(-1, -1); -NotebookPage::NotebookPage(QWidget *parent, NotebookTab *tab) +NotebookPage::NotebookPage(ChannelManager &_channelManager, QWidget *parent, NotebookTab *_tab) : QWidget(parent) - , _tab(tab) + , channelManager(_channelManager) + , tab(_tab) , _parentbox(this) , _chatWidgets() , _preview(this) @@ -46,12 +47,12 @@ const std::vector &NotebookPage::getChatWidgets() const NotebookTab *NotebookPage::getTab() const { - return _tab; + return this->tab; } void NotebookPage::addChat(bool openChannelNameDialog) { - ChatWidget *w = new ChatWidget(); + ChatWidget *w = new ChatWidget(this->channelManager); if (openChannelNameDialog) { w->showChangeChannelPopup(); @@ -143,7 +144,7 @@ void NotebookPage::mouseReleaseEvent(QMouseEvent *event) { if (_hbox.count() == 0 && event->button() == Qt::LeftButton) { // "Add Chat" was clicked - addToLayout(new ChatWidget(), std::pair(-1, -1)); + addToLayout(new ChatWidget(this->channelManager), std::pair(-1, -1)); setCursor(QCursor(Qt::ArrowCursor)); } @@ -275,7 +276,7 @@ void NotebookPage::load(const boost::property_tree::ptree &tree) for (const auto &v : tree.get_child("columns.")) { int row = 0; for (const auto &innerV : v.second.get_child("")) { - auto widget = new ChatWidget(); + auto widget = new ChatWidget(this->channelManager); widget->load(innerV.second); addToLayout(widget, std::pair(column, row)); ++row; diff --git a/src/widgets/notebookpage.hpp b/src/widgets/notebookpage.hpp index 9f71a432..6ca554b6 100644 --- a/src/widgets/notebookpage.hpp +++ b/src/widgets/notebookpage.hpp @@ -15,6 +15,9 @@ #include namespace chatterino { + +class ChannelManager; + namespace widgets { class NotebookPage : public QWidget @@ -22,7 +25,7 @@ class NotebookPage : public QWidget Q_OBJECT public: - NotebookPage(QWidget *parent, NotebookTab *_tab); + NotebookPage(ChannelManager &_channelManager, QWidget *parent, NotebookTab *_tab); std::pair removeFromLayout(ChatWidget *widget); void addToLayout(ChatWidget *widget, std::pair position); @@ -49,6 +52,8 @@ protected: void dropEvent(QDropEvent *event) override; private: + ChannelManager &channelManager; + struct DropRegion { QRect rect; std::pair position; @@ -60,7 +65,7 @@ private: } }; - NotebookTab *_tab; + NotebookTab *tab; QVBoxLayout _parentbox; QHBoxLayout _hbox; diff --git a/src/widgets/settingsdialog.cpp b/src/widgets/settingsdialog.cpp index 30123ef7..4d1e1117 100644 --- a/src/widgets/settingsdialog.cpp +++ b/src/widgets/settingsdialog.cpp @@ -153,7 +153,9 @@ void SettingsDialog::addTabs() QObject::connect(slider, &QSlider::valueChanged, this, [&settings](int value) { settings.themeHue.set(value / 1000.0); - WindowManager::getInstance().updateAll(); + + // TODO(pajlada): re-implement + // this->windowManager.updateAll(); }); group->setLayout(form); diff --git a/src/widgets/settingsdialog.hpp b/src/widgets/settingsdialog.hpp index 40aac2a5..1e4c5c04 100644 --- a/src/widgets/settingsdialog.hpp +++ b/src/widgets/settingsdialog.hpp @@ -17,6 +17,7 @@ #include namespace chatterino { + namespace widgets { class SettingsDialog : public QWidget diff --git a/src/windowmanager.cpp b/src/windowmanager.cpp index d97c4292..8bfee675 100644 --- a/src/windowmanager.cpp +++ b/src/windowmanager.cpp @@ -1,5 +1,6 @@ #include "windowmanager.hpp" #include "appdatapath.hpp" +#include "channelmanager.hpp" #include #include @@ -7,10 +8,9 @@ #include namespace chatterino { -WindowManager WindowManager::instance; -WindowManager::WindowManager() - : _mainWindow(nullptr) +WindowManager::WindowManager(ChannelManager &_channelManager) + : channelManager(_channelManager) { } @@ -23,41 +23,41 @@ static const std::string &getSettingsPath() void WindowManager::layoutVisibleChatWidgets(Channel *channel) { - if (_mainWindow != nullptr) { - _mainWindow->layoutVisibleChatWidgets(channel); + if (this->mainWindow != nullptr) { + this->mainWindow->layoutVisibleChatWidgets(channel); } } void WindowManager::repaintVisibleChatWidgets(Channel *channel) { - if (_mainWindow != nullptr) { - _mainWindow->repaintVisibleChatWidgets(channel); + if (this->mainWindow != nullptr) { + this->mainWindow->repaintVisibleChatWidgets(channel); } } void WindowManager::repaintGifEmotes() { - if (_mainWindow != nullptr) { - _mainWindow->repaintGifEmotes(); + if (this->mainWindow != nullptr) { + this->mainWindow->repaintGifEmotes(); } } void WindowManager::updateAll() { - if (_mainWindow != nullptr) { - _mainWindow->update(); + if (this->mainWindow != nullptr) { + this->mainWindow->update(); } } widgets::MainWindow &WindowManager::getMainWindow() { - std::lock_guard lock(_windowMutex); + std::lock_guard lock(this->windowMutex); - if (_mainWindow == nullptr) { - _mainWindow = new widgets::MainWindow(); + if (this->mainWindow == nullptr) { + this->mainWindow = new widgets::MainWindow(this->channelManager); } - return *_mainWindow; + return *this->mainWindow; } void WindowManager::load() diff --git a/src/windowmanager.hpp b/src/windowmanager.hpp index 88b8e78c..cf81433a 100644 --- a/src/windowmanager.hpp +++ b/src/windowmanager.hpp @@ -6,13 +6,12 @@ namespace chatterino { +class ChannelManager; + class WindowManager { public: - static WindowManager &getInstance() - { - return instance; - } + explicit WindowManager(ChannelManager &_channelManager); void layoutVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr); @@ -25,12 +24,12 @@ public: void save(); private: - static WindowManager instance; + ChannelManager &channelManager; - WindowManager(); + std::mutex windowMutex; - std::mutex _windowMutex; - widgets::MainWindow *_mainWindow; + // TODO(pajlada): Store as a value instead of a pointer + widgets::MainWindow *mainWindow = nullptr; }; } // namespace chatterino