refactor: Move TwitchBadges to Application (#5096)

* refactor: Move TwitchBadges to Application

* refactor: Use named initializers

* refactor: Use `empty()` instead of `size() > 0`

* refactor: use emplace instead of push into the callback queue
This commit is contained in:
pajlada 2024-01-17 23:53:10 +01:00 committed by GitHub
parent 7d5967c248
commit 11838c8e16
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 52 additions and 44 deletions

View file

@ -106,6 +106,7 @@
- Dev: Move `clang-tidy` checker to its own CI job. (#4996) - Dev: Move `clang-tidy` checker to its own CI job. (#4996)
- Dev: Refactored the Image Uploader feature. (#4971) - Dev: Refactored the Image Uploader feature. (#4971)
- Dev: Refactored the SplitOverlay code. (#5082) - Dev: Refactored the SplitOverlay code. (#5082)
- Dev: Refactored the TwitchBadges structure, making it less of a singleton. (#5096)
- Dev: Moved the Network files to their own folder. (#5089) - Dev: Moved the Network files to their own folder. (#5089)
- Dev: Fixed deadlock and use-after-free in tests. (#4981) - Dev: Fixed deadlock and use-after-free in tests. (#4981)
- Dev: Moved all `.clang-format` files to the root directory. (#5037) - Dev: Moved all `.clang-format` files to the root directory. (#5037)

View file

@ -122,6 +122,12 @@ public:
return nullptr; return nullptr;
} }
TwitchBadges *getTwitchBadges() override
{
assert(false && "getTwitchBadges was called without being initialized");
return nullptr;
}
Logging *getChatLogger() override Logging *getChatLogger() override
{ {
assert(!"getChatLogger was called without being initialized"); assert(!"getChatLogger was called without being initialized");

View file

@ -12,6 +12,7 @@
#include "controllers/notifications/NotificationController.hpp" #include "controllers/notifications/NotificationController.hpp"
#include "controllers/sound/ISoundController.hpp" #include "controllers/sound/ISoundController.hpp"
#include "providers/seventv/SeventvAPI.hpp" #include "providers/seventv/SeventvAPI.hpp"
#include "providers/twitch/TwitchBadges.hpp"
#include "singletons/ImageUploader.hpp" #include "singletons/ImageUploader.hpp"
#ifdef CHATTERINO_HAVE_PLUGINS #ifdef CHATTERINO_HAVE_PLUGINS
# include "controllers/plugins/PluginController.hpp" # include "controllers/plugins/PluginController.hpp"
@ -133,6 +134,7 @@ Application::Application(Settings &_settings, const Paths &paths,
, sound(&this->emplace<ISoundController>(makeSoundController(_settings))) , sound(&this->emplace<ISoundController>(makeSoundController(_settings)))
, twitchLiveController(&this->emplace<TwitchLiveController>()) , twitchLiveController(&this->emplace<TwitchLiveController>())
, twitchPubSub(new PubSub(TWITCH_PUBSUB_URL)) , twitchPubSub(new PubSub(TWITCH_PUBSUB_URL))
, twitchBadges(new TwitchBadges)
, logging(new Logging(_settings)) , logging(new Logging(_settings))
#ifdef CHATTERINO_HAVE_PLUGINS #ifdef CHATTERINO_HAVE_PLUGINS
, plugins(&this->emplace(new PluginController(paths))) , plugins(&this->emplace(new PluginController(paths)))
@ -153,6 +155,7 @@ Application::~Application() = default;
void Application::fakeDtor() void Application::fakeDtor()
{ {
this->twitchPubSub.reset(); this->twitchPubSub.reset();
this->twitchBadges.reset();
} }
void Application::initialize(Settings &settings, const Paths &paths) void Application::initialize(Settings &settings, const Paths &paths)
@ -320,6 +323,13 @@ ITwitchLiveController *Application::getTwitchLiveController()
return this->twitchLiveController; return this->twitchLiveController;
} }
TwitchBadges *Application::getTwitchBadges()
{
assert(this->twitchBadges);
return this->twitchBadges.get();
}
ITwitchIrcServer *Application::getTwitch() ITwitchIrcServer *Application::getTwitch()
{ {
return this->twitch; return this->twitch;

View file

@ -28,6 +28,7 @@ class ISoundController;
class SoundController; class SoundController;
class ITwitchLiveController; class ITwitchLiveController;
class TwitchLiveController; class TwitchLiveController;
class TwitchBadges;
#ifdef CHATTERINO_HAVE_PLUGINS #ifdef CHATTERINO_HAVE_PLUGINS
class PluginController; class PluginController;
#endif #endif
@ -78,6 +79,7 @@ public:
virtual IUserDataController *getUserData() = 0; virtual IUserDataController *getUserData() = 0;
virtual ISoundController *getSound() = 0; virtual ISoundController *getSound() = 0;
virtual ITwitchLiveController *getTwitchLiveController() = 0; virtual ITwitchLiveController *getTwitchLiveController() = 0;
virtual TwitchBadges *getTwitchBadges() = 0;
virtual ImageUploader *getImageUploader() = 0; virtual ImageUploader *getImageUploader() = 0;
virtual SeventvAPI *getSeventvAPI() = 0; virtual SeventvAPI *getSeventvAPI() = 0;
virtual Updates &getUpdates() = 0; virtual Updates &getUpdates() = 0;
@ -141,6 +143,7 @@ public:
private: private:
TwitchLiveController *const twitchLiveController{}; TwitchLiveController *const twitchLiveController{};
std::unique_ptr<PubSub> twitchPubSub; std::unique_ptr<PubSub> twitchPubSub;
std::unique_ptr<TwitchBadges> twitchBadges;
const std::unique_ptr<Logging> logging; const std::unique_ptr<Logging> logging;
public: public:
@ -215,6 +218,7 @@ public:
IUserDataController *getUserData() override; IUserDataController *getUserData() override;
ISoundController *getSound() override; ISoundController *getSound() override;
ITwitchLiveController *getTwitchLiveController() override; ITwitchLiveController *getTwitchLiveController() override;
TwitchBadges *getTwitchBadges() override;
ImageUploader *getImageUploader() override ImageUploader *getImageUploader() override
{ {
return this->imageUploader; return this->imageUploader;

View file

@ -53,7 +53,7 @@ void BadgeHighlightModel::getRowFromItem(const HighlightBadge &item,
setFilePathItem(row[Column::SoundPath], item.getSoundUrl()); setFilePathItem(row[Column::SoundPath], item.getSoundUrl());
setColorItem(row[Column::Color], *item.getColor()); setColorItem(row[Column::Color], *item.getColor());
TwitchBadges::instance()->getBadgeIcon( getIApp()->getTwitchBadges()->getBadgeIcon(
item.badgeName(), [item, row](QString /*name*/, const QIconPtr pixmap) { item.badgeName(), [item, row](QString /*name*/, const QIconPtr pixmap) {
row[Column::Badge]->setData(QVariant(*pixmap), Qt::DecorationRole); row[Column::Badge]->setData(QVariant(*pixmap), Qt::DecorationRole);
}); });

View file

@ -1,4 +1,4 @@
#include "TwitchBadges.hpp" #include "providers/twitch/TwitchBadges.hpp"
#include "common/network/NetworkRequest.hpp" #include "common/network/NetworkRequest.hpp"
#include "common/network/NetworkResult.hpp" #include "common/network/NetworkResult.hpp"
@ -45,14 +45,15 @@ void TwitchBadges::loadTwitchBadges()
for (const auto &version : badgeSet.versions) for (const auto &version : badgeSet.versions)
{ {
const auto &emote = Emote{ const auto &emote = Emote{
EmoteName{}, .name = EmoteName{},
ImageSet{ .images =
Image::fromUrl(version.imageURL1x, 1), ImageSet{
Image::fromUrl(version.imageURL2x, .5), Image::fromUrl(version.imageURL1x, 1),
Image::fromUrl(version.imageURL4x, .25), Image::fromUrl(version.imageURL2x, .5),
}, Image::fromUrl(version.imageURL4x, .25),
Tooltip{version.title}, },
version.clickURL, .tooltip = Tooltip{version.title},
.homePage = version.clickURL,
}; };
(*badgeSets)[setID][version.id] = (*badgeSets)[setID][version.id] =
std::make_shared<Emote>(emote); std::make_shared<Emote>(emote);
@ -112,20 +113,19 @@ void TwitchBadges::parseTwitchBadges(QJsonObject root)
auto versionObj = vIt.value().toObject(); auto versionObj = vIt.value().toObject();
auto emote = Emote{ auto emote = Emote{
{""}, .name = {""},
ImageSet{ .images =
Image::fromUrl( ImageSet{
{versionObj.value("image_url_1x").toString()}, 1), Image::fromUrl(
Image::fromUrl( {versionObj.value("image_url_1x").toString()}, 1),
{versionObj.value("image_url_2x").toString()}, .5), Image::fromUrl(
Image::fromUrl( {versionObj.value("image_url_2x").toString()}, .5),
{versionObj.value("image_url_4x").toString()}, .25), Image::fromUrl(
}, {versionObj.value("image_url_4x").toString()}, .25),
Tooltip{versionObj.value("title").toString()}, },
Url{versionObj.value("click_url").toString()}, .tooltip = Tooltip{versionObj.value("title").toString()},
.homePage = Url{versionObj.value("click_url").toString()},
}; };
// "title"
// "clickAction"
(*badgeSets)[key][vIt.key()] = std::make_shared<Emote>(emote); (*badgeSets)[key][vIt.key()] = std::make_shared<Emote>(emote);
} }
@ -176,9 +176,10 @@ std::optional<EmotePtr> TwitchBadges::badge(const QString &set) const
auto it = badgeSets->find(set); auto it = badgeSets->find(set);
if (it != badgeSets->end()) if (it != badgeSets->end())
{ {
if (it->second.size() > 0) const auto &badges = it->second;
if (!badges.empty())
{ {
return it->second.begin()->second; return badges.begin()->second;
} }
} }
return std::nullopt; return std::nullopt;
@ -193,7 +194,7 @@ void TwitchBadges::getBadgeIcon(const QString &name, BadgeIconCallback callback)
{ {
// Badges have not been loaded yet, store callback in a queue // Badges have not been loaded yet, store callback in a queue
std::unique_lock queueLock(this->queueMutex_); std::unique_lock queueLock(this->queueMutex_);
this->callbackQueue_.push({name, std::move(callback)}); this->callbackQueue_.emplace(name, std::move(callback));
return; return;
} }
} }
@ -279,16 +280,4 @@ void TwitchBadges::loadEmoteImage(const QString &name, ImagePtr image,
.execute(); .execute();
} }
TwitchBadges *TwitchBadges::instance_;
TwitchBadges *TwitchBadges::instance()
{
if (TwitchBadges::instance_ == nullptr)
{
TwitchBadges::instance_ = new TwitchBadges();
}
return TwitchBadges::instance_;
}
} // namespace chatterino } // namespace chatterino

View file

@ -32,7 +32,7 @@ class TwitchBadges
using BadgeIconCallback = std::function<void(QString, const QIconPtr)>; using BadgeIconCallback = std::function<void(QString, const QIconPtr)>;
public: public:
static TwitchBadges *instance(); TwitchBadges();
// Get badge from name and version // Get badge from name and version
std::optional<EmotePtr> badge(const QString &set, std::optional<EmotePtr> badge(const QString &set,
@ -46,9 +46,6 @@ public:
BadgeIconCallback callback); BadgeIconCallback callback);
private: private:
static TwitchBadges *instance_;
TwitchBadges();
void loadTwitchBadges(); void loadTwitchBadges();
void parseTwitchBadges(QJsonObject root); void parseTwitchBadges(QJsonObject root);
void loaded(); void loaded();

View file

@ -163,7 +163,7 @@ namespace {
} }
if (auto globalBadge = if (auto globalBadge =
TwitchBadges::instance()->badge(badge.key_, badge.value_)) getIApp()->getTwitchBadges()->badge(badge.key_, badge.value_))
{ {
return globalBadge; return globalBadge;
} }

View file

@ -1,5 +1,6 @@
#include "BadgePickerDialog.hpp" #include "BadgePickerDialog.hpp"
#include "Application.hpp"
#include "providers/twitch/TwitchBadges.hpp" #include "providers/twitch/TwitchBadges.hpp"
#include "singletons/Resources.hpp" #include "singletons/Resources.hpp"
@ -57,7 +58,7 @@ BadgePickerDialog::BadgePickerDialog(QList<DisplayBadge> badges,
updateBadge(0); updateBadge(0);
// Set icons. // Set icons.
TwitchBadges::instance()->getBadgeIcons( getIApp()->getTwitchBadges()->getBadgeIcons(
badges, badges,
[&dropdown = this->dropdown_](QString identifier, const QIconPtr icon) { [&dropdown = this->dropdown_](QString identifier, const QIconPtr icon) {
if (!dropdown) if (!dropdown)