refactor: turn StreamerMode into a singleton(-like thing) (#5216)

This commit is contained in:
nerix 2024-03-01 21:12:02 +01:00 committed by GitHub
parent ea19c5c989
commit c1fa51242f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 386 additions and 210 deletions

View file

@ -166,6 +166,7 @@
- Dev: Twitch messages can be sent using Twitch's Helix API instead of IRC (disabled by default). (#5200)
- Dev: Added estimation for image sizes to avoid layout shifts. (#5192)
- Dev: Added the `launachable` entry to Linux AppData. (#5210)
- Dev: Refactor `StreamerMode`. (#5216)
## 2.4.6

View file

@ -2,6 +2,7 @@
#include "controllers/accounts/AccountController.hpp"
#include "controllers/highlights/HighlightController.hpp"
#include "messages/Emote.hpp"
#include "mocks/DisabledStreamerMode.hpp"
#include "mocks/EmptyApplication.hpp"
#include "mocks/TwitchIrcServer.hpp"
#include "mocks/UserData.hpp"
@ -93,6 +94,11 @@ public:
return &this->seventvEmotes;
}
IStreamerMode *getStreamerMode() override
{
return &this->streamerMode;
}
AccountController accounts;
Emotes emotes;
mock::UserDataController userData;
@ -105,6 +111,7 @@ public:
BttvEmotes bttvEmotes;
FfzEmotes ffzEmotes;
SeventvEmotes seventvEmotes;
DisabledStreamerMode streamerMode;
};
std::optional<QJsonDocument> tryReadJsonFile(const QString &path)

View file

@ -0,0 +1,12 @@
#pragma once
#include "singletons/StreamerMode.hpp"
class DisabledStreamerMode : public chatterino::IStreamerMode
{
public:
bool isEnabled() const override
{
return false;
}
};

View file

@ -228,6 +228,13 @@ public:
return nullptr;
}
IStreamerMode *getStreamerMode() override
{
assert(false && "EmptyApplication::getStreamerMode was called without "
"being initialized");
return nullptr;
}
private:
Paths paths_;
Args args_;

View file

@ -51,6 +51,7 @@
#include "singletons/Logging.hpp"
#include "singletons/Paths.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/Toasts.hpp"
#include "singletons/Updates.hpp"
@ -144,6 +145,7 @@ Application::Application(Settings &_settings, const Paths &paths,
, seventvEmotes(new SeventvEmotes)
, logging(new Logging(_settings))
, linkResolver(new LinkResolver)
, streamerMode(new StreamerMode)
#ifdef CHATTERINO_HAVE_PLUGINS
, plugins(&this->emplace(new PluginController(paths)))
#endif
@ -503,6 +505,11 @@ ILinkResolver *Application::getLinkResolver()
return this->linkResolver.get();
}
IStreamerMode *Application::getStreamerMode()
{
return this->streamerMode.get();
}
BttvEmotes *Application::getBttvEmotes()
{
assertInGuiThread();
@ -707,7 +714,7 @@ void Application::initPubSub()
}
if (getSettings()->streamerModeHideModActions &&
isInStreamerMode())
this->getStreamerMode()->isEnabled())
{
return;
}
@ -756,7 +763,7 @@ void Application::initPubSub()
}
if (getSettings()->streamerModeHideModActions &&
isInStreamerMode())
this->getStreamerMode()->isEnabled())
{
return;
}
@ -892,9 +899,8 @@ void Application::initPubSub()
std::ignore = this->twitchPubSub->moderation.automodUserMessage.connect(
[&](const auto &action) {
// This condition has been set up to execute isInStreamerMode() as the last thing
// as it could end up being expensive.
if (getSettings()->streamerModeHideModActions && isInStreamerMode())
if (getSettings()->streamerModeHideModActions &&
this->getStreamerMode()->isEnabled())
{
return;
}

View file

@ -4,8 +4,6 @@
#include "debug/AssertInGuiThread.hpp"
#include "singletons/NativeMessaging.hpp"
#include <pajlada/signals.hpp>
#include <pajlada/signals/signal.hpp>
#include <QApplication>
#include <cassert>
@ -55,6 +53,7 @@ class BttvEmotes;
class FfzEmotes;
class SeventvEmotes;
class ILinkResolver;
class IStreamerMode;
class IApplication
{
@ -97,6 +96,7 @@ public:
virtual FfzEmotes *getFfzEmotes() = 0;
virtual SeventvEmotes *getSeventvEmotes() = 0;
virtual ILinkResolver *getLinkResolver() = 0;
virtual IStreamerMode *getStreamerMode() = 0;
};
class Application : public IApplication
@ -165,6 +165,7 @@ private:
std::unique_ptr<SeventvEmotes> seventvEmotes;
const std::unique_ptr<Logging> logging;
std::unique_ptr<ILinkResolver> linkResolver;
std::unique_ptr<IStreamerMode> streamerMode;
#ifdef CHATTERINO_HAVE_PLUGINS
PluginController *const plugins{};
#endif
@ -216,8 +217,7 @@ public:
SeventvEmotes *getSeventvEmotes() override;
ILinkResolver *getLinkResolver() override;
pajlada::Signals::NoArgSignal streamerModeChanged;
IStreamerMode *getStreamerMode() override;
private:
void addSingleton(Singleton *singleton);

View file

@ -452,6 +452,8 @@ set(SOURCE_FILES
singletons/Resources.hpp
singletons/Settings.cpp
singletons/Settings.hpp
singletons/StreamerMode.cpp
singletons/StreamerMode.hpp
singletons/Theme.cpp
singletons/Theme.hpp
singletons/Toasts.cpp
@ -505,8 +507,6 @@ set(SOURCE_FILES
util/SplitCommand.hpp
util/StreamLink.cpp
util/StreamLink.hpp
util/StreamerMode.cpp
util/StreamerMode.hpp
util/ThreadGuard.hpp
util/Twitch.cpp
util/Twitch.hpp
@ -770,6 +770,7 @@ target_link_libraries(${LIBRARY_PROJECT}
RapidJSON::RapidJSON
LRUCache
MagicEnum
$<$<BOOL:${WIN32}>:Wtsapi32>
)
if (CHATTERINO_PLUGINS)
target_link_libraries(${LIBRARY_PROJECT} PUBLIC lua)

View file

@ -16,6 +16,7 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Emotes.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "util/Twitch.hpp"
@ -183,7 +184,7 @@ bool appendWhisperMessageWordsLocally(const QStringList &words)
if (getSettings()->inlineWhispers &&
!(getSettings()->streamerModeSuppressInlineWhispers &&
isInStreamerMode()))
getIApp()->getStreamerMode()->isEnabled()))
{
app->twitch->forEachChannel(
[&messagexD, overrideFlags](ChannelPtr _channel) {

View file

@ -9,6 +9,7 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "providers/twitch/TwitchMessageBuilder.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Toasts.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Helpers.hpp"
@ -186,14 +187,15 @@ void NotificationController::checkStream(bool live, QString channelName)
getIApp()->getToasts()->sendChannelNotification(channelName, QString(),
Platform::Twitch);
}
bool inStreamerMode = getIApp()->getStreamerMode()->isEnabled();
if (getSettings()->notificationPlaySound &&
!(isInStreamerMode() &&
!(inStreamerMode &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getIApp()->getNotifications()->playSound();
}
if (getSettings()->notificationFlashTaskbar &&
!(isInStreamerMode() &&
!(inStreamerMode &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getIApp()->getWindows()->sendAlert();

View file

@ -11,10 +11,10 @@
#include "messages/MessageElement.hpp"
#include "providers/twitch/TwitchBadge.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Helpers.hpp"
#include "util/Qt.hpp"
#include "util/StreamerMode.hpp"
#include <QFileInfo>
@ -204,7 +204,8 @@ void SharedMessageBuilder::triggerHighlights(
const QString &channelName, bool playSound,
const std::optional<QUrl> &customSoundUrl, bool windowAlert)
{
if (isInStreamerMode() && getSettings()->streamerModeMuteMentions)
if (getIApp()->getStreamerMode()->isEnabled() &&
getSettings()->streamerModeMuteMentions)
{
// We are in streamer mode with muting mention sounds enabled. Do nothing.
return;

View file

@ -9,9 +9,9 @@
#include "messages/Selection.hpp"
#include "providers/colors/ColorProvider.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/WindowManager.hpp"
#include "util/DebugCount.hpp"
#include "util/StreamerMode.hpp"
#include <QApplication>
#include <QDebug>
@ -160,11 +160,9 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
if (this->message_->flags.has(MessageFlag::Timeout) ||
this->message_->flags.has(MessageFlag::Untimeout))
{
// This condition has been set up to execute isInStreamerMode() as the last thing
// as it could end up being expensive.
if (hideModerationActions ||
(getSettings()->streamerModeHideModActions &&
isInStreamerMode()))
getIApp()->getStreamerMode()->isEnabled()))
{
continue;
}

View file

@ -22,12 +22,12 @@
#include "providers/twitch/TwitchMessageBuilder.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/WindowManager.hpp"
#include "util/ChannelHelpers.hpp"
#include "util/FormatTime.hpp"
#include "util/Helpers.hpp"
#include "util/IrcHelpers.hpp"
#include "util/StreamerMode.hpp"
#include <IrcMessage>
#include <QLocale>
@ -931,7 +931,7 @@ void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *ircMessage)
if (getSettings()->inlineWhispers &&
!(getSettings()->streamerModeSuppressInlineWhispers &&
isInStreamerMode()))
getIApp()->getStreamerMode()->isEnabled()))
{
getApp()->twitch->forEachChannel(
[&message, overrideFlags](ChannelPtr channel) {

View file

@ -11,7 +11,6 @@
#include "util/DebugCount.hpp"
#include "util/Helpers.hpp"
#include "util/RapidjsonHelpers.hpp"
#include "util/StreamerMode.hpp"
#include <QJsonArray>

View file

@ -35,6 +35,7 @@
#include "providers/twitch/TwitchMessageBuilder.hpp"
#include "singletons/Emotes.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Toasts.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Helpers.hpp"
@ -180,7 +181,7 @@ TwitchChannel::TwitchChannel(const QString &name)
// Notify on all channels with a ping sound
if (getSettings()->notificationOnAnyChannel &&
!(isInStreamerMode() &&
!(getIApp()->getStreamerMode()->isEnabled() &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getIApp()->getNotifications()->playSound();

View file

@ -186,11 +186,6 @@ Settings::Settings(const QString &settingsDirectory)
},
false);
#endif
this->enableStreamerMode.connect(
[]() {
getApp()->streamerModeChanged.invoke();
},
false);
}
Settings::~Settings()

View file

@ -15,7 +15,6 @@
#include "controllers/sound/ISoundController.hpp"
#include "singletons/Toasts.hpp"
#include "util/RapidJsonSerializeQString.hpp"
#include "util/StreamerMode.hpp"
#include "widgets/Notebook.hpp"
#include <pajlada/settings/setting.hpp>
@ -68,6 +67,12 @@ enum class ChatSendProtocol : int {
Helix = 2,
};
enum StreamerModeSetting {
Disabled = 0,
Enabled = 1,
DetectStreamingSoftware = 2,
};
/// Settings which are availlable for reading and writing on the gui thread.
// These settings are still accessed concurrently in the code but it is bad practice.
class Settings

View file

@ -0,0 +1,245 @@
#include "singletons/StreamerMode.hpp"
#include "Application.hpp"
#include "common/Literals.hpp"
#include "common/QLogging.hpp"
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Settings.hpp"
#include "util/PostToThread.hpp"
#include <QAbstractEventDispatcher>
#include <QDebug>
#include <QProcess>
#include <QThread>
#include <QTimer>
#ifdef Q_OS_WIN
// clang-format off
# include <Windows.h>
# include <VersionHelpers.h>
# include <WtsApi32.h>
// clang-format on
#endif
#include <atomic>
namespace {
using namespace chatterino;
using namespace literals;
/// Number of timeouts to skip if nothing called `isEnabled` in the meantime.
constexpr uint8_t SKIPPED_TIMEOUTS = 5;
const QStringList &broadcastingBinaries()
{
#ifdef USEWINSDK
static QStringList bins = {
u"obs.exe"_s, u"obs64.exe"_s, u"PRISMLiveStudio.exe"_s,
u"XSplit.Core.exe"_s, u"TwitchStudio.exe"_s, u"vMix64.exe"_s,
};
#else
static QStringList bins = {
u"obs"_s,
u"Twitch Studio"_s,
u"Streamlabs Desktop"_s,
};
#endif
return bins;
}
bool isBroadcasterSoftwareActive()
{
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
QProcess p;
p.start("pgrep", {"-x", broadcastingBinaries().join("|")},
QIODevice::NotOpen);
if (p.waitForFinished(1000) && p.exitStatus() == QProcess::NormalExit)
{
return (p.exitCode() == 0);
}
// Fallback to false and showing a warning
static bool shouldShowWarning = true;
if (shouldShowWarning)
{
shouldShowWarning = false;
postToThread([] {
getApp()->twitch->addGlobalSystemMessage(
"Streamer Mode is set to Automatic, but pgrep is missing. "
"Install it to fix the issue or set Streamer Mode to "
"Enabled or Disabled in the Settings.");
});
}
qCWarning(chatterinoStreamerMode) << "pgrep execution timed out!";
return false;
#elif defined(Q_OS_WIN)
if (!IsWindowsVistaOrGreater())
{
return false;
}
WTS_PROCESS_INFO *pProcessInfo = nullptr;
DWORD dwProcCount = 0;
if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pProcessInfo,
&dwProcCount))
{
//Go through all processes retrieved
for (DWORD i = 0; i < dwProcCount; i++)
{
QStringView processName(pProcessInfo[i].pProcessName);
if (broadcastingBinaries().contains(processName))
{
WTSFreeMemory(pProcessInfo);
return true;
}
}
}
if (pProcessInfo)
{
WTSFreeMemory(pProcessInfo);
}
#else
# warning Unsupported OS: Broadcasting software can't be detected
#endif
return false;
}
} // namespace
namespace chatterino {
using namespace std::chrono_literals;
class StreamerModePrivate
{
public:
StreamerModePrivate(StreamerMode *parent_);
[[nodiscard]] bool isEnabled() const;
private:
void settingChanged(StreamerModeSetting value);
void setEnabled(bool enabled);
void check();
StreamerMode *parent_;
pajlada::Signals::SignalHolder settingConnections_;
QTimer timer_;
QThread thread_;
std::atomic<bool> enabled_ = false;
mutable std::atomic<uint8_t> timeouts_ = 0;
StreamerModeSetting currentSetting_ = StreamerModeSetting::Disabled;
};
StreamerMode::StreamerMode()
: private_(new StreamerModePrivate(this))
{
}
StreamerMode::~StreamerMode() = default;
void StreamerMode::updated(bool enabled)
{
this->changed(enabled);
}
bool StreamerMode::isEnabled() const
{
return this->private_->isEnabled();
}
StreamerModePrivate::StreamerModePrivate(StreamerMode *parent)
: parent_(parent)
{
this->thread_.start();
this->timer_.moveToThread(&this->thread_);
QObject::connect(&this->timer_, &QTimer::timeout, [this] {
auto timeouts =
this->timeouts_.fetch_add(1, std::memory_order::relaxed);
if (timeouts < SKIPPED_TIMEOUTS)
{
return;
}
this->timeouts_.store(0, std::memory_order::relaxed);
this->check();
});
getSettings()->enableStreamerMode.connect(
[this](auto value) {
QMetaObject::invokeMethod(this->thread_.eventDispatcher(), [this,
value] {
this->settingChanged(static_cast<StreamerModeSetting>(value));
});
},
this->settingConnections_);
}
bool StreamerModePrivate::isEnabled() const
{
this->timeouts_.store(SKIPPED_TIMEOUTS, std::memory_order::relaxed);
return this->enabled_.load(std::memory_order::relaxed);
}
void StreamerModePrivate::setEnabled(bool enabled)
{
if (enabled == this->enabled_.load(std::memory_order::relaxed))
{
return;
}
this->enabled_.store(enabled, std::memory_order::relaxed);
this->parent_->updated(enabled);
}
void StreamerModePrivate::settingChanged(StreamerModeSetting value)
{
if (value == this->currentSetting_)
{
return;
}
this->currentSetting_ = value;
switch (this->currentSetting_)
{
case StreamerModeSetting::Disabled: {
this->setEnabled(false);
this->timer_.stop();
}
break;
case StreamerModeSetting::Enabled: {
this->setEnabled(true);
this->timer_.stop();
}
break;
case StreamerModeSetting::DetectStreamingSoftware: {
if (!this->timer_.isActive())
{
this->timer_.start(20s);
this->check();
}
}
break;
default:
assert(false && "Unexpected setting");
break;
}
}
void StreamerModePrivate::check()
{
this->setEnabled(isBroadcasterSoftwareActive());
}
} // namespace chatterino

View file

@ -0,0 +1,48 @@
#pragma once
#include <QObject>
#include <memory>
namespace chatterino {
class IStreamerMode : public QObject
{
Q_OBJECT
public:
IStreamerMode() = default;
~IStreamerMode() override = default;
IStreamerMode(const IStreamerMode &) = delete;
IStreamerMode(IStreamerMode &&) = delete;
IStreamerMode &operator=(const IStreamerMode &) = delete;
IStreamerMode &operator=(IStreamerMode &&) = delete;
[[nodiscard]] virtual bool isEnabled() const = 0;
signals:
void changed(bool enabled);
};
class StreamerModePrivate;
class StreamerMode : public IStreamerMode
{
public:
StreamerMode();
~StreamerMode() override;
StreamerMode(const StreamerMode &) = delete;
StreamerMode(StreamerMode &&) = delete;
StreamerMode &operator=(const StreamerMode &) = delete;
StreamerMode &operator=(StreamerMode &&) = delete;
bool isEnabled() const override;
private:
void updated(bool enabled);
std::unique_ptr<StreamerModePrivate> private_;
friend class StreamerModePrivate;
};
} // namespace chatterino

View file

@ -9,6 +9,7 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Paths.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "util/StreamLink.hpp"
#include "widgets/helper/CommonTexts.hpp"
@ -72,7 +73,7 @@ bool Toasts::isEnabled()
{
#ifdef Q_OS_WIN
return WinToast::isCompatible() && getSettings()->notificationToast &&
!(isInStreamerMode() &&
!(getIApp()->getStreamerMode()->isEnabled() &&
getSettings()->streamerModeSuppressLiveNotifications);
#else
return false;

View file

@ -1,146 +0,0 @@
#include "util/StreamerMode.hpp"
#include "Application.hpp"
#include "common/QLogging.hpp"
#include "messages/MessageBuilder.hpp"
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Settings.hpp"
#include "singletons/WindowManager.hpp"
#include "widgets/helper/NotebookTab.hpp"
#include "widgets/Notebook.hpp"
#include "widgets/splits/Split.hpp"
#include "widgets/Window.hpp"
#include <QProcess>
#ifdef USEWINSDK
// clang-format off
// These imports cannot be ordered alphabetically.
# include <Windows.h>
# include <VersionHelpers.h>
# include <WtsApi32.h>
// clang-format on
# pragma comment(lib, "Wtsapi32.lib")
#endif
namespace chatterino {
constexpr int cooldownInS = 10;
bool shouldShowWarning = true;
const QStringList &broadcastingBinaries()
{
#ifdef USEWINSDK
static QStringList bins = {
"obs.exe", "obs64.exe", "PRISMLiveStudio.exe",
"XSplit.Core.exe", "TwitchStudio.exe", "vMix64.exe"};
#else
static QStringList bins = {"obs", "Twitch Studio", "Streamlabs Desktop"};
#endif
return bins;
}
bool isInStreamerMode()
{
switch (getSettings()->enableStreamerMode.getEnum())
{
case StreamerModeSetting::Enabled:
return true;
case StreamerModeSetting::Disabled:
return false;
case StreamerModeSetting::DetectStreamingSoftware:
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
static bool cache = false;
static QDateTime time = QDateTime();
if (time.isValid() &&
time.addSecs(cooldownInS) > QDateTime::currentDateTime())
{
return cache;
}
time = QDateTime::currentDateTime();
QProcess p;
p.start("pgrep", {"-x", broadcastingBinaries().join("|")},
QIODevice::NotOpen);
if (p.waitForFinished(1000) &&
p.exitStatus() == QProcess::NormalExit)
{
cache = (p.exitCode() == 0);
getApp()->streamerModeChanged.invoke();
return (p.exitCode() == 0);
}
// Fallback to false and showing a warning
if (shouldShowWarning)
{
shouldShowWarning = false;
getApp()->twitch->addGlobalSystemMessage(
"Streamer Mode is set to Automatic, but pgrep is missing. "
"Install it to fix the issue or set Streamer Mode to "
"Enabled or Disabled in the Settings.");
}
qCWarning(chatterinoStreamerMode) << "pgrep execution timed out!";
cache = false;
getApp()->streamerModeChanged.invoke();
return false;
#endif
#ifdef USEWINSDK
if (!IsWindowsVistaOrGreater())
{
return false;
}
static bool cache = false;
static QDateTime time = QDateTime();
if (time.isValid() &&
time.addSecs(cooldownInS) > QDateTime::currentDateTime())
{
return cache;
}
time = QDateTime::currentDateTime();
WTS_PROCESS_INFO *pWPIs = nullptr;
DWORD dwProcCount = 0;
if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1,
&pWPIs, &dwProcCount))
{
//Go through all processes retrieved
for (DWORD i = 0; i < dwProcCount; i++)
{
QString processName = QString::fromUtf16(
reinterpret_cast<char16_t *>(pWPIs[i].pProcessName));
if (broadcastingBinaries().contains(processName))
{
cache = true;
getApp()->streamerModeChanged.invoke();
return true;
}
}
}
if (pWPIs)
{
WTSFreeMemory(pWPIs);
}
cache = false;
getApp()->streamerModeChanged.invoke();
#endif
return false;
}
return false;
}
} // namespace chatterino

View file

@ -1,16 +0,0 @@
#pragma once
#include <QStringList>
namespace chatterino {
enum StreamerModeSetting {
Disabled = 0,
Enabled = 1,
DetectStreamingSoftware = 2,
};
const QStringList &broadcastingBinaries();
bool isInStreamerMode();
} // namespace chatterino

View file

@ -7,10 +7,10 @@
#include "controllers/hotkeys/HotkeyController.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/InitUpdateButton.hpp"
#include "util/StreamerMode.hpp"
#include "widgets/dialogs/SettingsDialog.hpp"
#include "widgets/helper/ChannelView.hpp"
#include "widgets/helper/NotebookButton.hpp"
@ -1437,9 +1437,8 @@ void SplitNotebook::addCustomButtons()
getIApp()->getWindows()->showSettingsDialog(
this, SettingsDialogPreference::StreamerMode);
});
this->signalHolder_.managedConnect(getApp()->streamerModeChanged, [this]() {
this->updateStreamerModeIcon();
});
QObject::connect(getIApp()->getStreamerMode(), &IStreamerMode::changed,
this, &SplitNotebook::updateStreamerModeIcon);
this->updateStreamerModeIcon();
}
@ -1462,7 +1461,8 @@ void SplitNotebook::updateStreamerModeIcon()
this->streamerModeIcon_->setPixmap(
getResources().buttons.streamerModeEnabledDark);
}
this->streamerModeIcon_->setVisible(isInStreamerMode());
this->streamerModeIcon_->setVisible(
getIApp()->getStreamerMode()->isEnabled());
}
void SplitNotebook::themeChangedEvent()

View file

@ -12,6 +12,7 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/Updates.hpp"
#include "singletons/WindowManager.hpp"
@ -202,9 +203,8 @@ void Window::addCustomTitlebarButtons()
getIApp()->getWindows()->showSettingsDialog(
this, SettingsDialogPreference::StreamerMode);
});
this->signalHolder_.managedConnect(getApp()->streamerModeChanged, [this]() {
this->updateStreamerModeIcon();
});
QObject::connect(getIApp()->getStreamerMode(), &IStreamerMode::changed,
this, &Window::updateStreamerModeIcon);
// Update initial state
this->updateStreamerModeIcon();
@ -231,7 +231,8 @@ void Window::updateStreamerModeIcon()
this->streamerModeTitlebarIcon_->setPixmap(
getResources().buttons.streamerModeEnabledDark);
}
this->streamerModeTitlebarIcon_->setVisible(isInStreamerMode());
this->streamerModeTitlebarIcon_->setVisible(
getIApp()->getStreamerMode()->isEnabled());
#else
// clang-format off
assert(false && "Streamer mode TitleBar icon should not exist on non-Windows OSes");
@ -609,7 +610,7 @@ void Window::addShortcuts()
}
else if (mode == 2)
{
if (isInStreamerMode())
if (getIApp()->getStreamerMode()->isEnabled())
{
getSettings()->enableStreamerMode.setValue(
StreamerModeSetting::Disabled);

View file

@ -18,12 +18,12 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Clipboard.hpp"
#include "util/Helpers.hpp"
#include "util/LayoutCreator.hpp"
#include "util/StreamerMode.hpp"
#include "widgets/helper/ChannelView.hpp"
#include "widgets/helper/EffectLabel.hpp"
#include "widgets/helper/InvisibleSizeGrip.hpp"
@ -858,7 +858,7 @@ void UserInfoPopup::updateUserData()
this->ui_.userIDLabel->setText(TEXT_USER_ID + user.id);
this->ui_.userIDLabel->setProperty("copy-text", user.id);
if (isInStreamerMode() &&
if (getIApp()->getStreamerMode()->isEnabled() &&
getSettings()->streamerModeHideUsercardAvatars)
{
this->ui_.avatarButton->setPixmap(getResources().streamerMode);

View file

@ -26,13 +26,13 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Clipboard.hpp"
#include "util/DistanceBetweenPoints.hpp"
#include "util/Helpers.hpp"
#include "util/IncognitoBrowser.hpp"
#include "util/StreamerMode.hpp"
#include "util/Twitch.hpp"
#include "widgets/dialogs/ReplyThreadPopup.hpp"
#include "widgets/dialogs/SettingsDialog.hpp"
@ -3079,7 +3079,8 @@ void ChannelView::setLinkInfoTooltip(LinkInfo *info)
ImagePtr thumbnail;
if (info->hasThumbnail() && thumbnailSize > 0)
{
if (isInStreamerMode() && getSettings()->streamerModeHideLinkThumbnails)
if (getIApp()->getStreamerMode()->isEnabled() &&
getSettings()->streamerModeHideLinkThumbnails)
{
thumbnail = Image::fromResourcePixmap(getResources().streamerMode);
}

View file

@ -17,7 +17,6 @@
#include "util/FuzzyConvert.hpp"
#include "util/Helpers.hpp"
#include "util/IncognitoBrowser.hpp"
#include "util/StreamerMode.hpp"
#include "widgets/BaseWindow.hpp"
#include "widgets/settingspages/GeneralPageView.hpp"
#include "widgets/splits/SplitInput.hpp"

View file

@ -15,11 +15,11 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Helpers.hpp"
#include "util/LayoutHelper.hpp"
#include "util/StreamerMode.hpp"
#include "widgets/dialogs/SettingsDialog.hpp"
#include "widgets/helper/CommonTexts.hpp"
#include "widgets/helper/EffectLabel.hpp"
@ -140,7 +140,7 @@ auto formatTooltip(const TwitchChannel::StreamStatus &s, QString thumbnail)
}();
auto extraStreamData = [&s]() -> QString {
if (isInStreamerMode() &&
if (getIApp()->getStreamerMode()->isEnabled() &&
getSettings()->streamerModeHideViewerCountAndDuration)
{
return QStringLiteral(

View file

@ -7,6 +7,7 @@
#include "messages/MessageBuilder.hpp"
#include "mocks/Channel.hpp"
#include "mocks/ChatterinoBadges.hpp"
#include "mocks/DisabledStreamerMode.hpp"
#include "mocks/EmptyApplication.hpp"
#include "mocks/TwitchIrcServer.hpp"
#include "mocks/UserData.hpp"
@ -86,6 +87,11 @@ public:
return &this->seventvEmotes;
}
IStreamerMode *getStreamerMode() override
{
return &this->streamerMode;
}
AccountController accounts;
Emotes emotes;
mock::UserDataController userData;
@ -97,6 +103,7 @@ public:
BttvEmotes bttvEmotes;
FfzEmotes ffzEmotes;
SeventvEmotes seventvEmotes;
DisabledStreamerMode streamerMode;
};
} // namespace