Show all global FFZ badges of a user (#3818)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
Jaxkey 2022-06-27 14:36:58 -04:00 committed by GitHub
parent 2bf58fba17
commit f49e8b4bc8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 45 deletions

View file

@ -36,6 +36,7 @@
- Bugfix: Fixed automod queue pubsub topic persisting after user change. (#3718)
- Bugfix: Fixed viewer list not closing after pressing escape key. (#3734)
- Bugfix: Fixed links with no thumbnail having previous link's thumbnail. (#3720)
- Bugfix: Fixed message only showing a maximum of one global FrankerFaceZ badge even if the user has multiple. (#3818)
- Bugfix: Add icon in the CMake macOS bundle. (#3832)
- Bugfix: Adopt popup windows in order to force floating behavior on some window managers. (#3836)
- Bugfix: Fix split focusing being broken in certain circumstances when the "Show input when it's empty" setting was disabled. (#3838)

View file

@ -263,10 +263,10 @@ MessageLayoutElement *VipBadgeElement::makeImageLayoutElement(
// FFZ Badge
FfzBadgeElement::FfzBadgeElement(const EmotePtr &data,
MessageElementFlags flags_, QColor &color)
MessageElementFlags flags_, QColor color_)
: BadgeElement(data, flags_)
, color(std::move(color_))
{
this->color = color;
}
MessageLayoutElement *FfzBadgeElement::makeImageLayoutElement(

View file

@ -296,12 +296,12 @@ class FfzBadgeElement : public BadgeElement
{
public:
FfzBadgeElement(const EmotePtr &data, MessageElementFlags flags_,
QColor &color);
QColor color_);
protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size) override;
QColor color;
const QColor color;
};
// contains a text, formated depending on the preferences

View file

@ -15,38 +15,42 @@ namespace chatterino {
void FfzBadges::initialize(Settings &settings, Paths &paths)
{
this->loadFfzBadges();
this->load();
}
boost::optional<EmotePtr> FfzBadges::getBadge(const UserId &id)
std::vector<FfzBadges::Badge> FfzBadges::getUserBadges(const UserId &id)
{
std::vector<Badge> badges;
std::shared_lock lock(this->mutex_);
auto it = this->badgeMap.find(id.string);
if (it != this->badgeMap.end())
auto it = this->userBadges.find(id.string);
if (it != this->userBadges.end())
{
return this->badges[it->second];
}
return boost::none;
}
boost::optional<QColor> FfzBadges::getBadgeColor(const UserId &id)
{
std::shared_lock lock(this->mutex_);
auto badgeIt = this->badgeMap.find(id.string);
if (badgeIt != this->badgeMap.end())
{
auto colorIt = this->colorMap.find(badgeIt->second);
if (colorIt != this->colorMap.end())
for (const auto &badgeID : it->second)
{
return colorIt->second;
if (auto badge = this->getBadge(badgeID); badge)
{
badges.emplace_back(*badge);
}
}
return boost::none;
}
return badges;
}
boost::optional<FfzBadges::Badge> FfzBadges::getBadge(const int badgeID)
{
auto it = this->badges.find(badgeID);
if (it != this->badges.end())
{
return it->second;
}
return boost::none;
}
void FfzBadges::loadFfzBadges()
void FfzBadges::load()
{
static QUrl url("https://api.frankerfacez.com/v1/badges/ids");
@ -55,7 +59,6 @@ void FfzBadges::loadFfzBadges()
std::unique_lock lock(this->mutex_);
auto jsonRoot = result.parseJson();
int index = 0;
for (const auto &jsonBadge_ : jsonRoot.value("badges").toArray())
{
auto jsonBadge = jsonBadge_.toObject();
@ -70,20 +73,33 @@ void FfzBadges::loadFfzBadges()
jsonUrls.value("4").toString()}},
Tooltip{jsonBadge.value("title").toString()}, Url{}};
this->badges.push_back(
std::make_shared<const Emote>(std::move(emote)));
this->colorMap[index] =
QColor(jsonBadge.value("color").toString());
Badge badge;
auto badgeId = QString::number(jsonBadge.value("id").toInt());
int badgeID = jsonBadge.value("id").toInt();
this->badges[badgeID] = Badge{
std::make_shared<const Emote>(std::move(emote)),
QColor(jsonBadge.value("color").toString()),
};
// Find users with this badge
auto badgeIDString = QString::number(badgeID);
for (const auto &user : jsonRoot.value("users")
.toObject()
.value(badgeId)
.value(badgeIDString)
.toArray())
{
this->badgeMap[QString::number(user.toInt())] = index;
auto userIDString = QString::number(user.toInt());
auto [userBadges, created] = this->userBadges.emplace(
std::make_pair<QString, std::vector<int>>(
std::move(userIDString), {badgeID}));
if (!created)
{
// User already had a badge assigned
userBadges->second.push_back(badgeID);
}
}
++index;
}
return Success;

View file

@ -4,6 +4,7 @@
#include <common/Singleton.hpp>
#include "common/Aliases.hpp"
#include "common/UniqueAccess.hpp"
#include "util/QStringHash.hpp"
#include <map>
@ -25,17 +26,25 @@ public:
virtual void initialize(Settings &settings, Paths &paths) override;
FfzBadges() = default;
boost::optional<EmotePtr> getBadge(const UserId &id);
boost::optional<QColor> getBadgeColor(const UserId &id);
struct Badge {
EmotePtr emote;
QColor color;
};
std::vector<Badge> getUserBadges(const UserId &id);
private:
void loadFfzBadges();
boost::optional<Badge> getBadge(int badgeID);
void load();
std::shared_mutex mutex_;
std::unordered_map<QString, int> badgeMap;
std::vector<EmotePtr> badges;
std::unordered_map<int, QColor> colorMap;
// userBadges points a user ID to the list of badges they have
std::unordered_map<QString, std::vector<int>> userBadges;
// badges points a badge ID to the information about the badge
std::unordered_map<int, Badge> badges;
};
} // namespace chatterino

View file

@ -1107,13 +1107,11 @@ void TwitchMessageBuilder::appendChatterinoBadges()
void TwitchMessageBuilder::appendFfzBadges()
{
if (auto badge = getApp()->ffzBadges->getBadge({this->userId_}))
for (const auto &badge :
getApp()->ffzBadges->getUserBadges({this->userId_}))
{
if (auto color = getApp()->ffzBadges->getBadgeColor({this->userId_}))
{
this->emplace<FfzBadgeElement>(*badge, MessageElementFlag::BadgeFfz,
color.get());
}
this->emplace<FfzBadgeElement>(
badge.emote, MessageElementFlag::BadgeFfz, badge.color);
}
}