dev: Add RecentMessages benchmark (#5071)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
nerix 2024-01-07 13:15:36 +01:00 committed by GitHub
parent 78a7ebb9f9
commit f42ae07408
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 446 additions and 119 deletions

View file

@ -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

View file

@ -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-*/

View file

@ -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

View file

@ -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
)

View file

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/bench">
<file>recentmessages-nymn.json</file>
<file>seventvemotes-nymn.json</file>
</qresource>
</RCC>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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);

View file

@ -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");

View 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);

View file

@ -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

View file

@ -32,9 +32,11 @@ bool isIgnoredMessage(IgnoredMessageParameters &&params)
{
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>(

View file

@ -142,8 +142,12 @@ 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();
@ -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)};
return emotes;
}
} // namespace
//
// 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)

View file

@ -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 =

View file

@ -149,7 +149,11 @@ namespace {
return authorityBadge;
}
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot)
} // namespace
using namespace ffz::detail;
EmoteMap ffz::detail::parseChannelEmotes(const QJsonObject &jsonRoot)
{
auto emotes = EmoteMap();
@ -160,7 +164,6 @@ namespace {
return emotes;
}
} // namespace
FfzEmotes::FfzEmotes()
: global_(std::make_shared<EmoteMap>())

View file

@ -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:

View file

@ -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>())
{

View file

@ -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:

View file

@ -128,7 +128,7 @@ void updateReplyParticipatedStatus(const QVariantMap &tags,
bool isNew)
{
const auto &currentLogin =
getApp()->accounts->twitch.getCurrent()->getUserName();
getIApp()->getAccounts()->twitch.getCurrent()->getUserName();
if (thread->subscribed())
{

View file

@ -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();

View file

@ -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();
}

View file

@ -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;