mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
dev: Add RecentMessages benchmark (#5071)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
78a7ebb9f9
commit
f42ae07408
|
@ -65,5 +65,11 @@ CheckOptions:
|
|||
- key: readability-identifier-naming.LocalPointerIgnoredRegexp
|
||||
value: ^L$
|
||||
|
||||
# Benchmarks
|
||||
- key: readability-identifier-naming.FunctionIgnoredRegexp
|
||||
value: ^BM_[^_]+$
|
||||
- key: readability-identifier-naming.ClassIgnoredRegexp
|
||||
value: ^BM_[^_]+$
|
||||
|
||||
- key: misc-const-correctness.AnalyzeValues
|
||||
value: false
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# JSON resources should not be prettified...
|
||||
resources/*.json
|
||||
benchmarks/resources/*.json
|
||||
tests/resources/*.json
|
||||
# ...themes should be prettified for readability.
|
||||
!resources/themes/*.json
|
||||
|
||||
|
@ -7,6 +9,7 @@ resources/*.json
|
|||
lib/*/
|
||||
conan-pkgs/*/
|
||||
cmake/sanitizers-cmake/
|
||||
tools/crash-handler
|
||||
|
||||
# Build folders
|
||||
*build-*/
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
- Dev: Autogenerate docs/plugin-meta.lua. (#5055)
|
||||
- Dev: Removed duplicate scale in settings dialog. (#5069)
|
||||
- Dev: Fix `NotebookTab` emitting updates for every message. (#5068)
|
||||
- Dev: Added benchmark for parsing and building recent messages. (#5071)
|
||||
|
||||
## 2.4.6
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
project(chatterino-benchmark)
|
||||
|
||||
set(benchmark_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/Highlights.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/FormatTime.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/Helpers.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/LimitedQueue.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/LinkParser.cpp
|
||||
src/main.cpp
|
||||
resources/bench.qrc
|
||||
|
||||
src/Emojis.cpp
|
||||
src/Highlights.cpp
|
||||
src/FormatTime.cpp
|
||||
src/Helpers.cpp
|
||||
src/LimitedQueue.cpp
|
||||
src/LinkParser.cpp
|
||||
src/RecentMessages.cpp
|
||||
# Add your new file above this line!
|
||||
)
|
||||
|
||||
|
@ -27,4 +30,5 @@ set_target_properties(${PROJECT_NAME}
|
|||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin"
|
||||
AUTORCC ON
|
||||
)
|
||||
|
|
6
benchmarks/resources/bench.qrc
Normal file
6
benchmarks/resources/bench.qrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/bench">
|
||||
<file>recentmessages-nymn.json</file>
|
||||
<file>seventvemotes-nymn.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
1
benchmarks/resources/recentmessages-nymn.json
Normal file
1
benchmarks/resources/recentmessages-nymn.json
Normal file
File diff suppressed because one or more lines are too long
1
benchmarks/resources/seventvemotes-nymn.json
Normal file
1
benchmarks/resources/seventvemotes-nymn.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -145,16 +145,13 @@ static void BM_EmojiParsing(benchmark::State &state)
|
|||
|
||||
BENCHMARK(BM_EmojiParsing);
|
||||
|
||||
template <class... Args>
|
||||
static void BM_EmojiParsing2(benchmark::State &state, Args &&...args)
|
||||
static void BM_EmojiParsing2(benchmark::State &state, const QString &input,
|
||||
int expectedNumEmojis)
|
||||
{
|
||||
Emojis emojis;
|
||||
|
||||
emojis.load();
|
||||
|
||||
auto argsTuple = std::make_tuple(std::move(args)...);
|
||||
auto input = std::get<0>(argsTuple);
|
||||
auto expectedNumEmojis = std::get<1>(argsTuple);
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto output = emojis.parse(input);
|
||||
|
|
|
@ -4,35 +4,41 @@
|
|||
|
||||
using namespace chatterino;
|
||||
|
||||
template <class... Args>
|
||||
void BM_TimeFormatting(benchmark::State &state, Args &&...args)
|
||||
void BM_TimeFormattingQString(benchmark::State &state, const QString &v)
|
||||
{
|
||||
auto args_tuple = std::make_tuple(std::move(args)...);
|
||||
for (auto _ : state)
|
||||
{
|
||||
formatTime(std::get<0>(args_tuple));
|
||||
formatTime(v);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 0, 0);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs0, "0");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 1337, 1337);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs1337, "1337");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 623452, 623452);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs623452, "623452");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 8345, 8345);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs8345, "8345");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 314034, 314034);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs314034, "314034");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 27, 27);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs27, "27");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 34589, 34589);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs34589, "34589");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 3659, 3659);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs3659, "3659");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 1045345, 1045345);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs1045345, "1045345");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 86432, 86432);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs86432, "86432");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qsempty, "");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qsinvalid, "asd");
|
||||
void BM_TimeFormattingInt(benchmark::State &state, int v)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
formatTime(v);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 0, 0);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 1045345, 1045345);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 1337, 1337);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 27, 27);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 314034, 314034);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 34589, 34589);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 3659, 3659);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 623452, 623452);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 8345, 8345);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 86432, 86432);
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs0, "0");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs1045345, "1045345");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs1337, "1337");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs27, "27");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs314034, "314034");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs34589, "34589");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs3659, "3659");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs623452, "623452");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs8345, "8345");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs86432, "86432");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qsempty, "");
|
||||
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qsinvalid, "asd");
|
||||
|
|
223
benchmarks/src/RecentMessages.cpp
Normal file
223
benchmarks/src/RecentMessages.cpp
Normal file
|
@ -0,0 +1,223 @@
|
|||
#include "common/Literals.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/highlights/HighlightController.hpp"
|
||||
#include "messages/Emote.hpp"
|
||||
#include "mocks/EmptyApplication.hpp"
|
||||
#include "mocks/TwitchIrcServer.hpp"
|
||||
#include "mocks/UserData.hpp"
|
||||
#include "providers/bttv/BttvEmotes.hpp"
|
||||
#include "providers/chatterino/ChatterinoBadges.hpp"
|
||||
#include "providers/ffz/FfzBadges.hpp"
|
||||
#include "providers/ffz/FfzEmotes.hpp"
|
||||
#include "providers/recentmessages/Impl.hpp"
|
||||
#include "providers/seventv/SeventvBadges.hpp"
|
||||
#include "providers/seventv/SeventvEmotes.hpp"
|
||||
#include "providers/twitch/TwitchChannel.hpp"
|
||||
#include "singletons/Emotes.hpp"
|
||||
#include "singletons/Resources.hpp"
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QString>
|
||||
|
||||
#include <optional>
|
||||
|
||||
using namespace chatterino;
|
||||
using namespace literals;
|
||||
|
||||
namespace {
|
||||
|
||||
class MockApplication : mock::EmptyApplication
|
||||
{
|
||||
public:
|
||||
IEmotes *getEmotes() override
|
||||
{
|
||||
return &this->emotes;
|
||||
}
|
||||
|
||||
IUserDataController *getUserData() override
|
||||
{
|
||||
return &this->userData;
|
||||
}
|
||||
|
||||
AccountController *getAccounts() override
|
||||
{
|
||||
return &this->accounts;
|
||||
}
|
||||
|
||||
ITwitchIrcServer *getTwitch() override
|
||||
{
|
||||
return &this->twitch;
|
||||
}
|
||||
|
||||
ChatterinoBadges *getChatterinoBadges() override
|
||||
{
|
||||
return &this->chatterinoBadges;
|
||||
}
|
||||
|
||||
FfzBadges *getFfzBadges() override
|
||||
{
|
||||
return &this->ffzBadges;
|
||||
}
|
||||
|
||||
SeventvBadges *getSeventvBadges() override
|
||||
{
|
||||
return &this->seventvBadges;
|
||||
}
|
||||
|
||||
HighlightController *getHighlights() override
|
||||
{
|
||||
return &this->highlights;
|
||||
}
|
||||
|
||||
AccountController accounts;
|
||||
Emotes emotes;
|
||||
mock::UserDataController userData;
|
||||
mock::MockTwitchIrcServer twitch;
|
||||
ChatterinoBadges chatterinoBadges;
|
||||
FfzBadges ffzBadges;
|
||||
SeventvBadges seventvBadges;
|
||||
HighlightController highlights;
|
||||
};
|
||||
|
||||
std::optional<QJsonDocument> tryReadJsonFile(const QString &path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QJsonParseError e;
|
||||
auto doc = QJsonDocument::fromJson(file.readAll(), &e);
|
||||
if (e.error != QJsonParseError::NoError)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
QJsonDocument readJsonFile(const QString &path)
|
||||
{
|
||||
auto opt = tryReadJsonFile(path);
|
||||
if (!opt)
|
||||
{
|
||||
_exit(1);
|
||||
}
|
||||
return *opt;
|
||||
}
|
||||
|
||||
class RecentMessages
|
||||
{
|
||||
public:
|
||||
explicit RecentMessages(const QString &name_)
|
||||
: name(name_)
|
||||
, chan(this->name)
|
||||
{
|
||||
const auto seventvEmotes =
|
||||
tryReadJsonFile(u":/bench/seventvemotes-%1.json"_s.arg(this->name));
|
||||
const auto bttvEmotes =
|
||||
tryReadJsonFile(u":/bench/bttvemotes-%1.json"_s.arg(this->name));
|
||||
const auto ffzEmotes =
|
||||
tryReadJsonFile(u":/bench/ffzemotes-%1.json"_s.arg(this->name));
|
||||
|
||||
if (seventvEmotes)
|
||||
{
|
||||
this->chan.setSeventvEmotes(
|
||||
std::make_shared<const EmoteMap>(seventv::detail::parseEmotes(
|
||||
seventvEmotes->object()["emote_set"_L1]
|
||||
.toObject()["emotes"_L1]
|
||||
.toArray(),
|
||||
false)));
|
||||
}
|
||||
|
||||
if (bttvEmotes)
|
||||
{
|
||||
this->chan.setBttvEmotes(std::make_shared<const EmoteMap>(
|
||||
bttv::detail::parseChannelEmotes(bttvEmotes->object(),
|
||||
this->name)));
|
||||
}
|
||||
|
||||
if (ffzEmotes)
|
||||
{
|
||||
this->chan.setFfzEmotes(std::make_shared<const EmoteMap>(
|
||||
ffz::detail::parseChannelEmotes(ffzEmotes->object())));
|
||||
}
|
||||
|
||||
this->messages =
|
||||
readJsonFile(u":/bench/recentmessages-%1.json"_s.arg(this->name));
|
||||
}
|
||||
|
||||
~RecentMessages()
|
||||
{
|
||||
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
|
||||
}
|
||||
|
||||
virtual void run(benchmark::State &state) = 0;
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
MockApplication app;
|
||||
TwitchChannel chan;
|
||||
QJsonDocument messages;
|
||||
};
|
||||
|
||||
class ParseRecentMessages : public RecentMessages
|
||||
{
|
||||
public:
|
||||
explicit ParseRecentMessages(const QString &name_)
|
||||
: RecentMessages(name_)
|
||||
{
|
||||
}
|
||||
|
||||
void run(benchmark::State &state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto parsed = recentmessages::detail::parseRecentMessages(
|
||||
this->messages.object());
|
||||
benchmark::DoNotOptimize(parsed);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class BuildRecentMessages : public RecentMessages
|
||||
{
|
||||
public:
|
||||
explicit BuildRecentMessages(const QString &name_)
|
||||
: RecentMessages(name_)
|
||||
{
|
||||
}
|
||||
|
||||
void run(benchmark::State &state)
|
||||
{
|
||||
auto parsed = recentmessages::detail::parseRecentMessages(
|
||||
this->messages.object());
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto built = recentmessages::detail::buildRecentMessages(
|
||||
parsed, &this->chan);
|
||||
benchmark::DoNotOptimize(built);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BM_ParseRecentMessages(benchmark::State &state, const QString &name)
|
||||
{
|
||||
ParseRecentMessages bench(name);
|
||||
bench.run(state);
|
||||
}
|
||||
|
||||
void BM_BuildRecentMessages(benchmark::State &state, const QString &name)
|
||||
{
|
||||
BuildRecentMessages bench(name);
|
||||
bench.run(state);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ParseRecentMessages, nymn, u"nymn"_s);
|
||||
BENCHMARK_CAPTURE(BM_BuildRecentMessages, nymn, u"nymn"_s);
|
|
@ -1,3 +1,4 @@
|
|||
#include "singletons/Resources.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
|
@ -11,6 +12,8 @@ int main(int argc, char **argv)
|
|||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
initResources();
|
||||
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
|
||||
// Ensure settings are initialized before any benchmarks are run
|
||||
|
|
|
@ -32,9 +32,11 @@ bool isIgnoredMessage(IgnoredMessageParameters &¶ms)
|
|||
{
|
||||
auto sourceUserID = params.twitchUserID;
|
||||
|
||||
bool isBlocked =
|
||||
getApp()->accounts->twitch.getCurrent()->blockedUserIds().contains(
|
||||
sourceUserID);
|
||||
bool isBlocked = getIApp()
|
||||
->getAccounts()
|
||||
->twitch.getCurrent()
|
||||
->blockedUserIds()
|
||||
.contains(sourceUserID);
|
||||
if (isBlocked)
|
||||
{
|
||||
switch (static_cast<ShowIgnoredUsersMessages>(
|
||||
|
|
|
@ -142,9 +142,13 @@ namespace {
|
|||
return anyModifications;
|
||||
}
|
||||
|
||||
std::pair<Outcome, EmoteMap> parseChannelEmotes(
|
||||
const QJsonObject &jsonRoot, const QString &channelDisplayName)
|
||||
{
|
||||
} // namespace
|
||||
|
||||
using namespace bttv::detail;
|
||||
|
||||
EmoteMap bttv::detail::parseChannelEmotes(const QJsonObject &jsonRoot,
|
||||
const QString &channelDisplayName)
|
||||
{
|
||||
auto emotes = EmoteMap();
|
||||
|
||||
auto innerParse = [&jsonRoot, &emotes,
|
||||
|
@ -152,20 +156,18 @@ namespace {
|
|||
auto jsonEmotes = jsonRoot.value(key).toArray();
|
||||
for (auto jsonEmote_ : jsonEmotes)
|
||||
{
|
||||
auto emote = createChannelEmote(channelDisplayName,
|
||||
jsonEmote_.toObject());
|
||||
auto emote =
|
||||
createChannelEmote(channelDisplayName, jsonEmote_.toObject());
|
||||
|
||||
emotes[emote.name] =
|
||||
cachedOrMake(std::move(emote.emote), emote.id);
|
||||
emotes[emote.name] = cachedOrMake(std::move(emote.emote), emote.id);
|
||||
}
|
||||
};
|
||||
|
||||
innerParse("channelEmotes");
|
||||
innerParse("sharedEmotes");
|
||||
|
||||
return {Success, std::move(emotes)};
|
||||
}
|
||||
} // namespace
|
||||
return emotes;
|
||||
}
|
||||
|
||||
//
|
||||
// BttvEmotes
|
||||
|
@ -230,14 +232,11 @@ void BttvEmotes::loadChannel(std::weak_ptr<Channel> channel,
|
|||
.timeout(20000)
|
||||
.onSuccess([callback = std::move(callback), channel, channelDisplayName,
|
||||
manualRefresh](auto result) {
|
||||
auto pair =
|
||||
auto emotes =
|
||||
parseChannelEmotes(result.parseJson(), channelDisplayName);
|
||||
bool hasEmotes = false;
|
||||
if (pair.first)
|
||||
{
|
||||
hasEmotes = !pair.second.empty();
|
||||
callback(std::move(pair.second));
|
||||
}
|
||||
bool hasEmotes = !emotes.empty();
|
||||
callback(std::move(emotes));
|
||||
|
||||
if (auto shared = channel.lock(); manualRefresh)
|
||||
{
|
||||
if (hasEmotes)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "common/Aliases.hpp"
|
||||
#include "common/Atomic.hpp"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
|
@ -15,6 +17,13 @@ class Channel;
|
|||
struct BttvLiveUpdateEmoteUpdateAddMessage;
|
||||
struct BttvLiveUpdateEmoteRemoveMessage;
|
||||
|
||||
namespace bttv::detail {
|
||||
|
||||
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot,
|
||||
const QString &channelDisplayName);
|
||||
|
||||
} // namespace bttv::detail
|
||||
|
||||
class BttvEmotes final
|
||||
{
|
||||
static constexpr const char *globalEmoteApiUrl =
|
||||
|
|
|
@ -149,8 +149,12 @@ namespace {
|
|||
return authorityBadge;
|
||||
}
|
||||
|
||||
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot)
|
||||
{
|
||||
} // namespace
|
||||
|
||||
using namespace ffz::detail;
|
||||
|
||||
EmoteMap ffz::detail::parseChannelEmotes(const QJsonObject &jsonRoot)
|
||||
{
|
||||
auto emotes = EmoteMap();
|
||||
|
||||
for (const auto emoteSetRef : jsonRoot["sets"].toObject())
|
||||
|
@ -159,8 +163,7 @@ namespace {
|
|||
}
|
||||
|
||||
return emotes;
|
||||
}
|
||||
} // namespace
|
||||
}
|
||||
|
||||
FfzEmotes::FfzEmotes()
|
||||
: global_(std::make_shared<EmoteMap>())
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "common/Aliases.hpp"
|
||||
#include "common/Atomic.hpp"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
|
@ -13,6 +15,12 @@ using EmotePtr = std::shared_ptr<const Emote>;
|
|||
class EmoteMap;
|
||||
class Channel;
|
||||
|
||||
namespace ffz::detail {
|
||||
|
||||
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot);
|
||||
|
||||
} // namespace ffz::detail
|
||||
|
||||
class FfzEmotes final
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -128,7 +128,34 @@ bool checkEmoteVisibility(const QJsonObject &emoteData)
|
|||
return !flags.has(SeventvEmoteFlag::ContentTwitchDisallowed);
|
||||
}
|
||||
|
||||
EmoteMap parseEmotes(const QJsonArray &emoteSetEmotes, bool isGlobal)
|
||||
EmotePtr createUpdatedEmote(const EmotePtr &oldEmote,
|
||||
const EmoteUpdateDispatch &dispatch)
|
||||
{
|
||||
bool toNonAliased = oldEmote->baseName.has_value() &&
|
||||
dispatch.emoteName == oldEmote->baseName->string;
|
||||
|
||||
auto baseName = oldEmote->baseName.value_or(oldEmote->name);
|
||||
auto emote = std::make_shared<const Emote>(Emote(
|
||||
{EmoteName{dispatch.emoteName}, oldEmote->images,
|
||||
toNonAliased
|
||||
? createTooltip(dispatch.emoteName, oldEmote->author.string, false)
|
||||
: createAliasedTooltip(dispatch.emoteName, baseName.string,
|
||||
oldEmote->author.string, false),
|
||||
oldEmote->homePage, oldEmote->zeroWidth, oldEmote->id,
|
||||
oldEmote->author, makeConditionedOptional(!toNonAliased, baseName)}));
|
||||
return emote;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
using namespace seventv::eventapi;
|
||||
using namespace seventv::detail;
|
||||
using namespace literals;
|
||||
|
||||
EmoteMap seventv::detail::parseEmotes(const QJsonArray &emoteSetEmotes,
|
||||
bool isGlobal)
|
||||
{
|
||||
auto emotes = EmoteMap();
|
||||
|
||||
|
@ -158,31 +185,6 @@ EmoteMap parseEmotes(const QJsonArray &emoteSetEmotes, bool isGlobal)
|
|||
return emotes;
|
||||
}
|
||||
|
||||
EmotePtr createUpdatedEmote(const EmotePtr &oldEmote,
|
||||
const EmoteUpdateDispatch &dispatch)
|
||||
{
|
||||
bool toNonAliased = oldEmote->baseName.has_value() &&
|
||||
dispatch.emoteName == oldEmote->baseName->string;
|
||||
|
||||
auto baseName = oldEmote->baseName.value_or(oldEmote->name);
|
||||
auto emote = std::make_shared<const Emote>(Emote(
|
||||
{EmoteName{dispatch.emoteName}, oldEmote->images,
|
||||
toNonAliased
|
||||
? createTooltip(dispatch.emoteName, oldEmote->author.string, false)
|
||||
: createAliasedTooltip(dispatch.emoteName, baseName.string,
|
||||
oldEmote->author.string, false),
|
||||
oldEmote->homePage, oldEmote->zeroWidth, oldEmote->id,
|
||||
oldEmote->author, makeConditionedOptional(!toNonAliased, baseName)}));
|
||||
return emote;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
using namespace seventv::eventapi;
|
||||
using namespace literals;
|
||||
|
||||
SeventvEmotes::SeventvEmotes()
|
||||
: global_(std::make_shared<EmoteMap>())
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "common/Atomic.hpp"
|
||||
#include "common/FlagsEnum.hpp"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <memory>
|
||||
|
@ -77,6 +78,12 @@ enum class SeventvEmoteSetFlag : uint32_t {
|
|||
};
|
||||
using SeventvEmoteSetFlags = FlagsEnum<SeventvEmoteSetFlag>;
|
||||
|
||||
namespace seventv::detail {
|
||||
|
||||
EmoteMap parseEmotes(const QJsonArray &emoteSetEmotes, bool isGlobal);
|
||||
|
||||
} // namespace seventv::detail
|
||||
|
||||
class SeventvEmotes final
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -128,7 +128,7 @@ void updateReplyParticipatedStatus(const QVariantMap &tags,
|
|||
bool isNew)
|
||||
{
|
||||
const auto ¤tLogin =
|
||||
getApp()->accounts->twitch.getCurrent()->getUserName();
|
||||
getIApp()->getAccounts()->twitch.getCurrent()->getUserName();
|
||||
|
||||
if (thread->subscribed())
|
||||
{
|
||||
|
|
|
@ -29,6 +29,12 @@ void TwitchBadges::loadTwitchBadges()
|
|||
{
|
||||
assert(this->loaded_ == false);
|
||||
|
||||
if (!getHelix())
|
||||
{
|
||||
// This is intended for tests and benchmarks.
|
||||
return;
|
||||
}
|
||||
|
||||
getHelix()->getGlobalBadges(
|
||||
[this](auto globalBadges) {
|
||||
auto badgeSets = this->badgeSets_.access();
|
||||
|
|
|
@ -87,6 +87,13 @@ TwitchChannel::TwitchChannel(const QString &name)
|
|||
{
|
||||
qCDebug(chatterinoTwitch) << "[TwitchChannel" << name << "] Opened";
|
||||
|
||||
if (!getApp())
|
||||
{
|
||||
// This is intended for tests and benchmarks.
|
||||
// Irc, Pubsub, live-updates, and live-notifications aren't mocked there.
|
||||
return;
|
||||
}
|
||||
|
||||
this->bSignals_.emplace_back(
|
||||
getApp()->accounts->twitch.currentUserChanged.connect([this] {
|
||||
this->setMod(false);
|
||||
|
@ -219,6 +226,13 @@ TwitchChannel::TwitchChannel(const QString &name)
|
|||
|
||||
TwitchChannel::~TwitchChannel()
|
||||
{
|
||||
if (!getApp())
|
||||
{
|
||||
// This is for tests and benchmarks, where live-updates aren't mocked
|
||||
// see comment in constructor.
|
||||
return;
|
||||
}
|
||||
|
||||
getApp()->twitch->dropSeventvChannel(this->seventvUserID_,
|
||||
this->seventvEmoteSetID_);
|
||||
|
||||
|
@ -282,8 +296,9 @@ void TwitchChannel::refreshBTTVChannelEmotes(bool manualRefresh)
|
|||
weakOf<Channel>(this), this->roomId(), this->getLocalizedName(),
|
||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
||||
if (auto shared = weak.lock())
|
||||
this->bttvEmotes_.set(
|
||||
std::make_shared<EmoteMap>(std::move(emoteMap)));
|
||||
{
|
||||
this->setBttvEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||
}
|
||||
},
|
||||
manualRefresh);
|
||||
}
|
||||
|
@ -300,8 +315,9 @@ void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
|||
weakOf<Channel>(this), this->roomId(),
|
||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
||||
if (auto shared = weak.lock())
|
||||
this->ffzEmotes_.set(
|
||||
std::make_shared<EmoteMap>(std::move(emoteMap)));
|
||||
{
|
||||
this->setFfzEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||
}
|
||||
},
|
||||
[this, weak = weakOf<Channel>(this)](auto &&modBadge) {
|
||||
if (auto shared = weak.lock())
|
||||
|
@ -332,8 +348,8 @@ void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
|||
auto channelInfo) {
|
||||
if (auto shared = weak.lock())
|
||||
{
|
||||
this->seventvEmotes_.set(std::make_shared<EmoteMap>(
|
||||
std::forward<decltype(emoteMap)>(emoteMap)));
|
||||
this->setSeventvEmotes(
|
||||
std::make_shared<const EmoteMap>(emoteMap));
|
||||
this->updateSeventvData(channelInfo.userID,
|
||||
channelInfo.emoteSetID);
|
||||
this->seventvUserTwitchConnectionIndex_ =
|
||||
|
@ -343,6 +359,21 @@ void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
|||
manualRefresh);
|
||||
}
|
||||
|
||||
void TwitchChannel::setBttvEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||
{
|
||||
this->bttvEmotes_.set(std::move(map));
|
||||
}
|
||||
|
||||
void TwitchChannel::setFfzEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||
{
|
||||
this->ffzEmotes_.set(std::move(map));
|
||||
}
|
||||
|
||||
void TwitchChannel::setSeventvEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||
{
|
||||
this->seventvEmotes_.set(std::move(map));
|
||||
}
|
||||
|
||||
void TwitchChannel::addQueuedRedemption(const QString &rewardId,
|
||||
const QString &originalContent,
|
||||
Communi::IrcMessage *message)
|
||||
|
@ -700,9 +731,10 @@ void TwitchChannel::setStaff(bool value)
|
|||
|
||||
bool TwitchChannel::isBroadcaster() const
|
||||
{
|
||||
auto app = getApp();
|
||||
auto *app = getIApp();
|
||||
|
||||
return this->getName() == app->accounts->twitch.getCurrent()->getUserName();
|
||||
return this->getName() ==
|
||||
app->getAccounts()->twitch.getCurrent()->getUserName();
|
||||
}
|
||||
|
||||
bool TwitchChannel::hasHighRateLimit() const
|
||||
|
@ -730,8 +762,12 @@ void TwitchChannel::setRoomId(const QString &id)
|
|||
if (*this->roomID_.accessConst() != id)
|
||||
{
|
||||
*this->roomID_.access() = id;
|
||||
// This is intended for tests and benchmarks. See comment in constructor.
|
||||
if (getApp())
|
||||
{
|
||||
this->roomIdChanged();
|
||||
this->loadRecentMessages();
|
||||
}
|
||||
this->disconnected_ = false;
|
||||
this->lastConnectedAt_ = std::chrono::system_clock::now();
|
||||
}
|
||||
|
|
|
@ -158,6 +158,10 @@ public:
|
|||
void refreshFFZChannelEmotes(bool manualRefresh);
|
||||
void refreshSevenTVChannelEmotes(bool manualRefresh);
|
||||
|
||||
void setBttvEmotes(std::shared_ptr<const EmoteMap> &&map);
|
||||
void setFfzEmotes(std::shared_ptr<const EmoteMap> &&map);
|
||||
void setSeventvEmotes(std::shared_ptr<const EmoteMap> &&map);
|
||||
|
||||
const QString &seventvUserID() const;
|
||||
const QString &seventvEmoteSetID() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue