refactor: some Application & style things (#5561)

This commit is contained in:
pajlada
2024-08-25 15:33:07 +02:00
committed by GitHub
parent ac88730563
commit 627c735524
41 changed files with 733 additions and 678 deletions
+117 -124
View File
@@ -15,82 +15,57 @@
#include <QJsonArray>
#include <QThread>
namespace chatterino {
namespace {
const QString CHANNEL_HAS_NO_EMOTES(
"This channel has no BetterTTV channel emotes.");
using namespace chatterino;
QString emoteLinkFormat("https://betterttv.com/emotes/%1");
// BTTV doesn't provide any data on the size, so we assume an emote is 28x28
constexpr QSize EMOTE_BASE_SIZE(28, 28);
const QString CHANNEL_HAS_NO_EMOTES(
"This channel has no BetterTTV channel emotes.");
struct CreateEmoteResult {
EmoteId id;
EmoteName name;
Emote emote;
};
/// The emote page template.
///
/// %1 being the emote ID (e.g. 566ca04265dbbdab32ec054a)
constexpr QStringView EMOTE_LINK_FORMAT = u"https://betterttv.com/emotes/%1";
Url getEmoteLink(QString urlTemplate, const EmoteId &id,
const QString &emoteScale)
/// The emote CDN link template.
///
/// %1 being the emote ID (e.g. 566ca04265dbbdab32ec054a)
///
/// %2 being the emote size (e.g. 3x)
constexpr QStringView EMOTE_CDN_FORMAT =
u"https://cdn.betterttv.net/emote/%1/%2";
// BTTV doesn't provide any data on the size, so we assume an emote is 28x28
constexpr QSize EMOTE_BASE_SIZE(28, 28);
struct CreateEmoteResult {
EmoteId id;
EmoteName name;
Emote emote;
};
Url getEmoteLinkV3(const EmoteId &id, const QString &emoteScale)
{
return {EMOTE_CDN_FORMAT.arg(id.string, emoteScale)};
}
EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id)
{
static std::unordered_map<EmoteId, std::weak_ptr<const Emote>> cache;
static std::mutex mutex;
return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id);
}
std::pair<Outcome, EmoteMap> parseGlobalEmotes(const QJsonArray &jsonEmotes,
const EmoteMap &currentEmotes)
{
auto emotes = EmoteMap();
for (auto jsonEmote : jsonEmotes)
{
urlTemplate.detach();
return {urlTemplate.replace("{{id}}", id.string)
.replace("{{image}}", emoteScale)};
}
Url getEmoteLinkV3(const EmoteId &id, const QString &emoteScale)
{
static const QString urlTemplate(
"https://cdn.betterttv.net/emote/%1/%2");
return {urlTemplate.arg(id.string, emoteScale)};
}
EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id)
{
static std::unordered_map<EmoteId, std::weak_ptr<const Emote>> cache;
static std::mutex mutex;
return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id);
}
std::pair<Outcome, EmoteMap> parseGlobalEmotes(
const QJsonArray &jsonEmotes, const EmoteMap &currentEmotes)
{
auto emotes = EmoteMap();
for (auto jsonEmote : jsonEmotes)
{
auto id = EmoteId{jsonEmote.toObject().value("id").toString()};
auto name =
EmoteName{jsonEmote.toObject().value("code").toString()};
auto emote = Emote({
name,
ImageSet{Image::fromUrl(getEmoteLinkV3(id, "1x"), 1,
EMOTE_BASE_SIZE),
Image::fromUrl(getEmoteLinkV3(id, "2x"), 0.5,
EMOTE_BASE_SIZE * 2),
Image::fromUrl(getEmoteLinkV3(id, "3x"), 0.25,
EMOTE_BASE_SIZE * 4)},
Tooltip{name.string + "<br>Global BetterTTV Emote"},
Url{emoteLinkFormat.arg(id.string)},
});
emotes[name] =
cachedOrMakeEmotePtr(std::move(emote), currentEmotes);
}
return {Success, std::move(emotes)};
}
CreateEmoteResult createChannelEmote(const QString &channelDisplayName,
const QJsonObject &jsonEmote)
{
auto id = EmoteId{jsonEmote.value("id").toString()};
auto name = EmoteName{jsonEmote.value("code").toString()};
auto author = EmoteAuthor{
jsonEmote.value("user").toObject().value("displayName").toString()};
auto id = EmoteId{jsonEmote.toObject().value("id").toString()};
auto name = EmoteName{jsonEmote.toObject().value("code").toString()};
auto emote = Emote({
name,
@@ -99,58 +74,82 @@ namespace {
Image::fromUrl(getEmoteLinkV3(id, "2x"), 0.5,
EMOTE_BASE_SIZE * 2),
Image::fromUrl(getEmoteLinkV3(id, "3x"), 0.25,
EMOTE_BASE_SIZE * 4),
},
Tooltip{
QString("%1<br>%2 BetterTTV Emote<br>By: %3")
.arg(name.string)
// when author is empty, it is a channel emote created by the broadcaster
.arg(author.string.isEmpty() ? "Channel" : "Shared")
.arg(author.string.isEmpty() ? channelDisplayName
: author.string)},
Url{emoteLinkFormat.arg(id.string)},
false,
id,
EMOTE_BASE_SIZE * 4)},
Tooltip{name.string + "<br>Global BetterTTV Emote"},
Url{EMOTE_LINK_FORMAT.arg(id.string)},
});
return {id, name, emote};
emotes[name] = cachedOrMakeEmotePtr(std::move(emote), currentEmotes);
}
bool updateChannelEmote(Emote &emote, const QString &channelDisplayName,
const QJsonObject &jsonEmote)
return {Success, std::move(emotes)};
}
CreateEmoteResult createChannelEmote(const QString &channelDisplayName,
const QJsonObject &jsonEmote)
{
auto id = EmoteId{jsonEmote.value("id").toString()};
auto name = EmoteName{jsonEmote.value("code").toString()};
auto author = EmoteAuthor{
jsonEmote.value("user").toObject().value("displayName").toString()};
auto emote = Emote({
name,
ImageSet{
Image::fromUrl(getEmoteLinkV3(id, "1x"), 1, EMOTE_BASE_SIZE),
Image::fromUrl(getEmoteLinkV3(id, "2x"), 0.5, EMOTE_BASE_SIZE * 2),
Image::fromUrl(getEmoteLinkV3(id, "3x"), 0.25, EMOTE_BASE_SIZE * 4),
},
Tooltip{
QString("%1<br>%2 BetterTTV Emote<br>By: %3")
.arg(name.string)
// when author is empty, it is a channel emote created by the broadcaster
.arg(author.string.isEmpty() ? "Channel" : "Shared")
.arg(author.string.isEmpty() ? channelDisplayName
: author.string)},
Url{EMOTE_LINK_FORMAT.arg(id.string)},
false,
id,
});
return {id, name, emote};
}
bool updateChannelEmote(Emote &emote, const QString &channelDisplayName,
const QJsonObject &jsonEmote)
{
bool anyModifications = false;
if (jsonEmote.contains("code"))
{
bool anyModifications = false;
if (jsonEmote.contains("code"))
{
emote.name = EmoteName{jsonEmote.value("code").toString()};
anyModifications = true;
}
if (jsonEmote.contains("user"))
{
emote.author = EmoteAuthor{jsonEmote.value("user")
.toObject()
.value("displayName")
.toString()};
anyModifications = true;
}
if (anyModifications)
{
emote.tooltip = Tooltip{
QString("%1<br>%2 BetterTTV Emote<br>By: %3")
.arg(emote.name.string)
// when author is empty, it is a channel emote created by the broadcaster
.arg(emote.author.string.isEmpty() ? "Channel" : "Shared")
.arg(emote.author.string.isEmpty() ? channelDisplayName
: emote.author.string)};
}
return anyModifications;
emote.name = EmoteName{jsonEmote.value("code").toString()};
anyModifications = true;
}
if (jsonEmote.contains("user"))
{
emote.author = EmoteAuthor{
jsonEmote.value("user").toObject().value("displayName").toString()};
anyModifications = true;
}
if (anyModifications)
{
emote.tooltip = Tooltip{
QString("%1<br>%2 BetterTTV Emote<br>By: %3")
.arg(emote.name.string)
// when author is empty, it is a channel emote created by the broadcaster
.arg(emote.author.string.isEmpty() ? "Channel" : "Shared")
.arg(emote.author.string.isEmpty() ? channelDisplayName
: emote.author.string)};
}
return anyModifications;
}
} // namespace
namespace chatterino {
using namespace bttv::detail;
EmoteMap bttv::detail::parseChannelEmotes(const QJsonObject &jsonRoot,
@@ -182,6 +181,11 @@ EmoteMap bttv::detail::parseChannelEmotes(const QJsonObject &jsonRoot,
BttvEmotes::BttvEmotes()
: global_(std::make_shared<EmoteMap>())
{
getSettings()->enableBTTVGlobalEmotes.connect(
[this] {
this->loadEmotes();
},
this->managedConnections, false);
}
std::shared_ptr<const EmoteMap> BttvEmotes::emotes() const
@@ -360,15 +364,4 @@ std::optional<EmotePtr> BttvEmotes::removeEmote(
return emote;
}
/*
static Url getEmoteLink(QString urlTemplate, const EmoteId &id,
const QString &emoteScale)
{
urlTemplate.detach();
return {urlTemplate.replace("{{id}}", id.string)
.replace("{{image}}", emoteScale)};
}
*/
} // namespace chatterino