Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an indicator in the title bar if Streamer Mode is active #4410

Merged
merged 17 commits into from
May 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unversioned

- Minor: Add an icon showing when streamer mode is enabled (#4410)
- Minor: Added `/shoutout <username>` commands to shoutout specified user. (#4638)
- Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637)
- Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570)
Expand Down
Binary file added resources/buttons/streamerModeEnabledDark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions resources/buttons/streamerModeEnabledDark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/buttons/streamerModeEnabledLight.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions resources/buttons/streamerModeEnabledLight.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "common/Singleton.hpp"
#include "singletons/NativeMessaging.hpp"

#include <pajlada/signals.hpp>
#include <pajlada/signals/signal.hpp>
#include <QApplication>

#include <memory>
Expand Down Expand Up @@ -153,6 +155,8 @@ class Application : public IApplication
}
IUserDataController *getUserData() override;

pajlada::Signals::NoArgSignal streamerModeChanged;

private:
void addSingleton(Singleton *singleton);
void initPubSub();
Expand Down
6 changes: 6 additions & 0 deletions src/singletons/Settings.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "singletons/Settings.hpp"

#include "Application.hpp"
#include "controllers/filters/FilterRecord.hpp"
#include "controllers/highlights/HighlightBadge.hpp"
#include "controllers/highlights/HighlightBlacklistUser.hpp"
Expand Down Expand Up @@ -136,6 +137,11 @@ Settings::Settings(const QString &settingsDirectory)
},
false);
#endif
this->enableStreamerMode.connect(
[]() {
getApp()->streamerModeChanged.invoke();
},
false);
}

Settings &Settings::instance()
Expand Down
4 changes: 4 additions & 0 deletions src/util/StreamerMode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ bool isInStreamerMode()
p.exitStatus() == QProcess::NormalExit)
{
cache = (p.exitCode() == 0);
getApp()->streamerModeChanged.invoke();
return (p.exitCode() == 0);
}

Expand All @@ -89,6 +90,7 @@ bool isInStreamerMode()
qCWarning(chatterinoStreamerMode) << "pgrep execution timed out!";

cache = false;
getApp()->streamerModeChanged.invoke();
return false;
#endif

Expand Down Expand Up @@ -122,6 +124,7 @@ bool isInStreamerMode()
if (broadcastingBinaries().contains(processName))
{
cache = true;
getApp()->streamerModeChanged.invoke();
return true;
}
}
Expand All @@ -133,6 +136,7 @@ bool isInStreamerMode()
}

cache = false;
getApp()->streamerModeChanged.invoke();
#endif
return false;
}
Expand Down
41 changes: 41 additions & 0 deletions src/widgets/Notebook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
#include "common/QLogging.hpp"
#include "controllers/hotkeys/HotkeyCategory.hpp"
#include "controllers/hotkeys/HotkeyController.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.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"
Expand Down Expand Up @@ -1155,6 +1157,45 @@ void SplitNotebook::addCustomButtons()
auto updateBtn = this->addCustomButton();

initUpdateButton(*updateBtn, this->signalHolder_);

// streamer mode
this->streamerModeIcon_ = this->addCustomButton();
QObject::connect(this->streamerModeIcon_, &NotebookButton::leftClicked,
[this] {
getApp()->windows->showSettingsDialog(
this, SettingsDialogPreference::StreamerMode);
});
this->signalHolder_.managedConnect(getApp()->streamerModeChanged, [this]() {
this->updateStreamerModeIcon();
});
this->updateStreamerModeIcon();
}

void SplitNotebook::updateStreamerModeIcon()
{
if (this->streamerModeIcon_ == nullptr)
{
return;
}
// A duplicate of this code is in Window class
Mm2PL marked this conversation as resolved.
Show resolved Hide resolved
// That copy handles the TitleBar icon in Window (main window on Windows)
// This one is the one near splits (on linux and mac or non-main windows on Windows)
if (getTheme()->isLightTheme())
Mm2PL marked this conversation as resolved.
Show resolved Hide resolved
pajlada marked this conversation as resolved.
Show resolved Hide resolved
{
this->streamerModeIcon_->setPixmap(
getResources().buttons.streamerModeEnabledLight);
}
else
{
this->streamerModeIcon_->setPixmap(
getResources().buttons.streamerModeEnabledDark);
}
this->streamerModeIcon_->setVisible(isInStreamerMode());
}

void SplitNotebook::themeChangedEvent()
{
this->updateStreamerModeIcon();
}

SplitContainer *SplitNotebook::addPage(bool select)
Expand Down
6 changes: 6 additions & 0 deletions src/widgets/Notebook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class SplitNotebook : public Notebook
SplitContainer *addPage(bool select = false);
SplitContainer *getOrAddSelectedPage();
void select(QWidget *page, bool focusPage = true) override;
void themeChangedEvent() override;

protected:
void showEvent(QShowEvent *event) override;
Expand All @@ -131,6 +132,11 @@ class SplitNotebook : public Notebook
void addCustomButtons();

pajlada::Signals::SignalHolder signalHolder_;

// Main window on Windows has basically a duplicate of this in Window
NotebookButton *streamerModeIcon_{};

void updateStreamerModeIcon();
};

} // namespace chatterino
46 changes: 46 additions & 0 deletions src/widgets/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "controllers/hotkeys/HotkeyController.hpp"
#include "providers/twitch/TwitchAccount.hpp"
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"
#include "singletons/Theme.hpp"
#include "singletons/Updates.hpp"
Expand Down Expand Up @@ -186,6 +187,51 @@ void Window::addCustomTitlebarButtons()
this->userLabel_->rect().bottomLeft()));
});
this->userLabel_->setMinimumWidth(20 * scale());

// streamer mode
this->streamerModeTitlebarIcon_ =
this->addTitleBarButton(TitleBarButtonStyle::StreamerMode, [this] {
getApp()->windows->showSettingsDialog(
this, SettingsDialogPreference::StreamerMode);
});
this->signalHolder_.managedConnect(getApp()->streamerModeChanged, [this]() {
this->updateStreamerModeIcon();
});
}

void Window::updateStreamerModeIcon()
{
// A duplicate of this code is in SplitNotebook class (in Notebook.{c,h}pp)
// That one is the one near splits (on linux and mac or non-main windows on Windows)
// This copy handles the TitleBar icon in Window (main window on Windows)
if (this->streamerModeTitlebarIcon_ == nullptr)
{
return;
}
#ifdef Q_OS_WIN
assert(this->getType() == WindowType::Main);
if (getTheme()->isLightTheme())
pajlada marked this conversation as resolved.
Show resolved Hide resolved
{
this->streamerModeTitlebarIcon_->setPixmap(
getResources().buttons.streamerModeEnabledLight);
}
else
{
this->streamerModeTitlebarIcon_->setPixmap(
getResources().buttons.streamerModeEnabledDark);
}
this->streamerModeTitlebarIcon_->setVisible(isInStreamerMode());
#else
// clang-format off
assert(false && "Streamer mode TitleBar icon should not exist on non-Windows OSes");
// clang-format on
#endif
}

void Window::themeChangedEvent()
{
this->updateStreamerModeIcon();
BaseWindow::themeChangedEvent();
}

void Window::addDebugStuff(HotkeyController::HotkeyMap &actions)
Expand Down
5 changes: 5 additions & 0 deletions src/widgets/Window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Window : public BaseWindow
protected:
void closeEvent(QCloseEvent *event) override;
bool event(QEvent *event) override;
void themeChangedEvent() override;

private:
void addCustomTitlebarButtons();
Expand All @@ -51,6 +52,10 @@ class Window : public BaseWindow
pajlada::Signals::SignalHolder signalHolder_;
std::vector<boost::signals2::scoped_connection> bSignals_;

// this is only used on Windows and only on the main window, for the one used otherwise, see SplitNotebook in Notebook.hpp
TitleBarButton *streamerModeTitlebarIcon_ = nullptr;
void updateStreamerModeIcon();

friend class Notebook;
};

Expand Down
17 changes: 16 additions & 1 deletion src/widgets/dialogs/SettingsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ void SettingsDialog::filterElements(const QString &text)
}
}

void SettingsDialog::setElementFilter(const QString &query)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: method 'setElementFilter' can be made const [readability-make-member-function-const]

Suggested change
void SettingsDialog::setElementFilter(const QString &query)
void SettingsDialog::setElementFilter(const QString &query) const

src/widgets/dialogs/SettingsDialog.hpp:60:

-     void setElementFilter(const QString &query);
+     void setElementFilter(const QString &query) const;

{
this->ui_.search->setText(query);
}

void SettingsDialog::addTabs()
{
this->ui_.tabContainer->setSpacing(0);
Expand All @@ -203,7 +208,7 @@ void SettingsDialog::addTabs()
// Constructors are wrapped in std::function to remove some strain from first time loading.

// clang-format off
this->addTab([]{return new GeneralPage;}, "General", ":/settings/about.svg");
this->addTab([]{return new GeneralPage;}, "General", ":/settings/about.svg", SettingsTabId::General);
this->ui_.tabContainer->addSpacing(16);
this->addTab([]{return new AccountsPage;}, "Accounts", ":/settings/accounts.svg", SettingsTabId::Accounts);
this->addTab([]{return new NicknamesPage;}, "Nicknames", ":/settings/accounts.svg");
Expand Down Expand Up @@ -316,10 +321,20 @@ void SettingsDialog::showDialog(QWidget *parent,
}
break;

case SettingsDialogPreference::StreamerMode: {
instance->selectTab(SettingsTabId::General);
}
break;

default:;
}

instance->show();
if (preferredTab == SettingsDialogPreference::StreamerMode)
{
// this is needed because each time the settings are opened, the query is reset
instance->setElementFilter("Streamer Mode");
}
instance->activateWindow();
instance->raise();
instance->setFocus();
Expand Down
2 changes: 2 additions & 0 deletions src/widgets/dialogs/SettingsDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PageHeader : public QFrame

enum class SettingsDialogPreference {
NoPreference,
StreamerMode,
Accounts,
ModerationActions,
};
Expand Down Expand Up @@ -57,6 +58,7 @@ class SettingsDialog : public BaseWindow
void selectTab(SettingsDialogTab *tab, const bool byUser = true);
void selectTab(SettingsTabId id);
void filterElements(const QString &query);
void setElementFilter(const QString &query);

void onOkClicked();
void onCancelClicked();
Expand Down
1 change: 1 addition & 0 deletions src/widgets/helper/SettingsDialogTab.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SettingsDialog;

enum class SettingsTabId {
None,
General,
Accounts,
Moderation,
};
Expand Down
3 changes: 2 additions & 1 deletion src/widgets/helper/TitlebarButton.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ enum class TitleBarButtonStyle {
Unmaximize = 4,
Close = 8,
User = 16,
Settings = 32
Settings = 32,
StreamerMode = 64,
};

class TitleBarButton : public Button
Expand Down
3 changes: 3 additions & 0 deletions src/widgets/settingspages/AboutPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ AboutPage::AboutPage()
"https://github.com/getsentry/crashpad",
":/licenses/crashpad.txt");
#endif
addLicense(form.getElement(), "Fluent icons",
"https://github.com/microsoft/fluentui-system-icons",
":/licenses/fluenticons.txt");
}

// Attributions
Expand Down