Show all global FFZ badges of a user (#3818)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
- Bugfix: Fixed automod queue pubsub topic persisting after user change. (#3718)
|
- Bugfix: Fixed automod queue pubsub topic persisting after user change. (#3718)
|
||||||
- Bugfix: Fixed viewer list not closing after pressing escape key. (#3734)
|
- 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 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: Add icon in the CMake macOS bundle. (#3832)
|
||||||
- Bugfix: Adopt popup windows in order to force floating behavior on some window managers. (#3836)
|
- 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)
|
- Bugfix: Fix split focusing being broken in certain circumstances when the "Show input when it's empty" setting was disabled. (#3838)
|
||||||
|
|||||||
@@ -263,10 +263,10 @@ MessageLayoutElement *VipBadgeElement::makeImageLayoutElement(
|
|||||||
|
|
||||||
// FFZ Badge
|
// FFZ Badge
|
||||||
FfzBadgeElement::FfzBadgeElement(const EmotePtr &data,
|
FfzBadgeElement::FfzBadgeElement(const EmotePtr &data,
|
||||||
MessageElementFlags flags_, QColor &color)
|
MessageElementFlags flags_, QColor color_)
|
||||||
: BadgeElement(data, flags_)
|
: BadgeElement(data, flags_)
|
||||||
|
, color(std::move(color_))
|
||||||
{
|
{
|
||||||
this->color = color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageLayoutElement *FfzBadgeElement::makeImageLayoutElement(
|
MessageLayoutElement *FfzBadgeElement::makeImageLayoutElement(
|
||||||
|
|||||||
@@ -296,12 +296,12 @@ class FfzBadgeElement : public BadgeElement
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FfzBadgeElement(const EmotePtr &data, MessageElementFlags flags_,
|
FfzBadgeElement(const EmotePtr &data, MessageElementFlags flags_,
|
||||||
QColor &color);
|
QColor color_);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
|
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
|
||||||
const QSize &size) override;
|
const QSize &size) override;
|
||||||
QColor color;
|
const QColor color;
|
||||||
};
|
};
|
||||||
|
|
||||||
// contains a text, formated depending on the preferences
|
// contains a text, formated depending on the preferences
|
||||||
|
|||||||
@@ -15,38 +15,42 @@ namespace chatterino {
|
|||||||
|
|
||||||
void FfzBadges::initialize(Settings &settings, Paths &paths)
|
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_);
|
std::shared_lock lock(this->mutex_);
|
||||||
|
|
||||||
auto it = this->badgeMap.find(id.string);
|
auto it = this->userBadges.find(id.string);
|
||||||
if (it != this->badgeMap.end())
|
if (it != this->userBadges.end())
|
||||||
{
|
{
|
||||||
return this->badges[it->second];
|
for (const auto &badgeID : 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())
|
|
||||||
{
|
{
|
||||||
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;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FfzBadges::loadFfzBadges()
|
void FfzBadges::load()
|
||||||
{
|
{
|
||||||
static QUrl url("https://api.frankerfacez.com/v1/badges/ids");
|
static QUrl url("https://api.frankerfacez.com/v1/badges/ids");
|
||||||
|
|
||||||
@@ -55,7 +59,6 @@ void FfzBadges::loadFfzBadges()
|
|||||||
std::unique_lock lock(this->mutex_);
|
std::unique_lock lock(this->mutex_);
|
||||||
|
|
||||||
auto jsonRoot = result.parseJson();
|
auto jsonRoot = result.parseJson();
|
||||||
int index = 0;
|
|
||||||
for (const auto &jsonBadge_ : jsonRoot.value("badges").toArray())
|
for (const auto &jsonBadge_ : jsonRoot.value("badges").toArray())
|
||||||
{
|
{
|
||||||
auto jsonBadge = jsonBadge_.toObject();
|
auto jsonBadge = jsonBadge_.toObject();
|
||||||
@@ -70,20 +73,33 @@ void FfzBadges::loadFfzBadges()
|
|||||||
jsonUrls.value("4").toString()}},
|
jsonUrls.value("4").toString()}},
|
||||||
Tooltip{jsonBadge.value("title").toString()}, Url{}};
|
Tooltip{jsonBadge.value("title").toString()}, Url{}};
|
||||||
|
|
||||||
this->badges.push_back(
|
Badge badge;
|
||||||
std::make_shared<const Emote>(std::move(emote)));
|
|
||||||
this->colorMap[index] =
|
|
||||||
QColor(jsonBadge.value("color").toString());
|
|
||||||
|
|
||||||
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")
|
for (const auto &user : jsonRoot.value("users")
|
||||||
.toObject()
|
.toObject()
|
||||||
.value(badgeId)
|
.value(badgeIDString)
|
||||||
.toArray())
|
.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;
|
return Success;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <common/Singleton.hpp>
|
#include <common/Singleton.hpp>
|
||||||
|
|
||||||
#include "common/Aliases.hpp"
|
#include "common/Aliases.hpp"
|
||||||
|
#include "common/UniqueAccess.hpp"
|
||||||
#include "util/QStringHash.hpp"
|
#include "util/QStringHash.hpp"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -25,17 +26,25 @@ public:
|
|||||||
virtual void initialize(Settings &settings, Paths &paths) override;
|
virtual void initialize(Settings &settings, Paths &paths) override;
|
||||||
FfzBadges() = default;
|
FfzBadges() = default;
|
||||||
|
|
||||||
boost::optional<EmotePtr> getBadge(const UserId &id);
|
struct Badge {
|
||||||
boost::optional<QColor> getBadgeColor(const UserId &id);
|
EmotePtr emote;
|
||||||
|
QColor color;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Badge> getUserBadges(const UserId &id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadFfzBadges();
|
boost::optional<Badge> getBadge(int badgeID);
|
||||||
|
|
||||||
|
void load();
|
||||||
|
|
||||||
std::shared_mutex mutex_;
|
std::shared_mutex mutex_;
|
||||||
|
|
||||||
std::unordered_map<QString, int> badgeMap;
|
// userBadges points a user ID to the list of badges they have
|
||||||
std::vector<EmotePtr> badges;
|
std::unordered_map<QString, std::vector<int>> userBadges;
|
||||||
std::unordered_map<int, QColor> colorMap;
|
|
||||||
|
// badges points a badge ID to the information about the badge
|
||||||
|
std::unordered_map<int, Badge> badges;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1107,13 +1107,11 @@ void TwitchMessageBuilder::appendChatterinoBadges()
|
|||||||
|
|
||||||
void TwitchMessageBuilder::appendFfzBadges()
|
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.emote, MessageElementFlag::BadgeFfz, badge.color);
|
||||||
this->emplace<FfzBadgeElement>(*badge, MessageElementFlag::BadgeFfz,
|
|
||||||
color.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user