From b836be653070cbfddef1cf376a2c2bd0d6be6ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20J=C3=BCrgens?= Date: Fri, 13 Jan 2023 23:33:47 +0100 Subject: [PATCH] Implement Tray Icon --- assets/userscript.js | 104 +++++++++++++++++++++++++++++++++++++++---- src/discordpage.cpp | 15 +++++-- src/mainwindow.cpp | 69 +++++++++++++++++++++++++++- src/mainwindow.h | 13 ++++++ 4 files changed, 189 insertions(+), 12 deletions(-) diff --git a/assets/userscript.js b/assets/userscript.js index 55e5e84..de7affb 100644 --- a/assets/userscript.js +++ b/assets/userscript.js @@ -75,6 +75,52 @@ const clonedElements = []; const hiddenElements = []; let wasStreamActive = false; +function createButton(text, onClick) { + const button = document.createElement("button"); + button.style.marginBottom = "20px"; + button.classList = + "button-f2h6uQ lookFilled-yCfaCM colorBrand-I6CyqQ sizeSmall-wU2dO- grow-2sR_-F"; + button.innerText = text; + button.addEventListener("click", onClick); + return button; +} + +function createSwitch(text, enabled, onClick) { + const container = document.createElement("div"); + container.style.marginBottom = "20px"; + container.className = "labelRow-2jl9gK"; + + const label = document.createElement("label"); + label.innerText = text; + label.className = "title-2dsDLn"; + container.appendChild(label); + + const svg = document.createElement("div"); + container.appendChild(svg); + + function setSvgDisabled() { + svg.innerHTML = `
`; + } + + function setSvgEnabled() { + svg.innerHTML = `
`; + } + + function updateSvg() { + if (enabled) setSvgEnabled(); + else setSvgDisabled(); + } + + container.addEventListener("click", () => { + enabled = !enabled; + updateSvg(); + onClick(enabled); + }); + updateSvg(); + + return container; +} + setInterval(() => { const streamActive = document.getElementsByClassName("panel-2ZFCRb activityPanel-9icbyU") @@ -179,14 +225,11 @@ setInterval(() => { .getElementsByClassName("children-1xdcWE")[0]; const div = document.createElement("div"); div.style.marginBottom = "50px"; - const button = document.createElement("button"); - button.classList = - "button-f2h6uQ lookFilled-yCfaCM colorBrand-I6CyqQ sizeSmall-wU2dO- grow-2sR_-F"; - button.innerText = "Edit Global Keybinds"; - button.addEventListener("click", () => { - console.log("!discord-screenaudio-keybinds"); - }); - div.appendChild(button); + div.appendChild( + createButton("Edit Global Keybinds", () => { + console.log("!discord-screenaudio-keybinds"); + }) + ); el.innerHTML = ""; el.appendChild(div); } @@ -221,6 +264,51 @@ setInterval(() => { el.innerHTML = window.discordScreenaudioResolutionString; } } + + const accountTab = document.getElementById("my-account-tab"); + if (accountTab) { + const discordScreenaudioSettings = document.getElementById( + "discord-screenaudio-settings" + ); + if (!discordScreenaudioSettings) { + const firstDivider = accountTab.getElementsByClassName( + "divider-_0um2u marginTop40-Q4o1tS" + )[0]; + if (firstDivider) { + const section = document.createElement("div"); + section.className = "marginTop40-Q4o1tS"; + section.id = "discord-screenaudio-settings"; + + const title = document.createElement("h2"); + title.className = + "h1-34Txb0 title-3hptVQ defaultColor-2cKwKo defaultMarginh1-EURXsm"; + title.innerText = "discord-screenaudio"; + section.appendChild(title); + + section.appendChild( + createButton("Edit Global Keybinds", () => { + console.log("!discord-screenaudio-keybinds"); + }) + ); + + section.appendChild( + createSwitch( + "Move discord-screenaudio to the system tray instead of closing", + window.discordScreenaudioTrayEnabled, + (enabled) => { + console.log(`!discord-screenaudio-tray-${enabled}`); + } + ) + ); + + const divider = document.createElement("div"); + divider.className = "divider-_0um2u marginTop40-Q4o1tS"; + + firstDivider.after(section); + section.after(divider); + } + } + } }, 500); // Fix for broken discord notifications after restart diff --git a/src/discordpage.cpp b/src/discordpage.cpp index 8f42f01..3b63111 100644 --- a/src/discordpage.cpp +++ b/src/discordpage.cpp @@ -55,9 +55,14 @@ DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) { injectScriptFile("userscript.js", ":/assets/userscript.js"); - injectScriptText("version.js", - QString("window.discordScreenaudioVersion = '%1';") - .arg(QApplication::applicationVersion())); + injectScriptText("vars.js", + QString("window.discordScreenaudioVersion = '%1'; " + "window.discordScreenaudioTrayEnabled = %2;") + .arg(QApplication::applicationVersion()) + .arg(MainWindow::instance() + ->settings() + ->value("trayIcon", false) + .toBool())); #ifdef KXMLGUI injectScriptText("xmlgui.js", "window.discordScreenaudioKXMLGUI = true;"); @@ -221,6 +226,10 @@ void DiscordPage::javaScriptConsoleMessage( "(KXmlGui and KGlobalAccel are not available).", QMessageBox::Ok); #endif + } else if (message == "!discord-screenaudio-tray-true") { + MainWindow::instance()->setTrayIcon(true); + } else if (message == "!discord-screenaudio-tray-false") { + MainWindow::instance()->setTrayIcon(false); } else if (message.startsWith("dsa: ")) { qDebug(userscriptLog) << message.mid(5).toUtf8().constData(); } else { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9072bcf..fa9a47f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -29,7 +29,9 @@ MainWindow::MainWindow(bool useNotifySend, QWidget *parent) assert(MainWindow::m_instance == nullptr); MainWindow::m_instance = this; m_useNotifySend = useNotifySend; + setupSettings(); setupWebView(); + setupTrayIcon(); resize(1000, 700); showMaximized(); } @@ -66,6 +68,7 @@ void MainWindow::setupWebView() { connect(notification, &KNotification::defaultActivated, [&, notificationInfo = std::move(notificationInfo)]() { notificationInfo->click(); + show(); activateWindow(); }); notification->sendEvent(); @@ -87,6 +90,70 @@ void MainWindow::fullScreenRequested( } } -void MainWindow::closeEvent(QCloseEvent *event) { QApplication::quit(); } +void MainWindow::setupTrayIcon() { + if (m_settings->value("trayIcon", false).toBool() == false || + m_trayIcon != nullptr) + return; + + auto aboutAction = new QAction( + "discord-screenaudio v" + QString(DISCORD_SCEENAUDIO_VERSION_FULL), this); + aboutAction->setIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png")); + aboutAction->setEnabled(false); + + auto exitAction = new QAction("Exit", this); + connect(exitAction, &QAction::triggered, []() { QApplication::quit(); }); + + m_trayIconMenu = new QMenu(this); + m_trayIconMenu->addAction(aboutAction); + m_trayIconMenu->addAction(exitAction); + + m_trayIcon = new QSystemTrayIcon(this); + m_trayIcon->setContextMenu(m_trayIconMenu); + m_trayIcon->setIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png")); + m_trayIcon->show(); + + connect(m_trayIcon, &QSystemTrayIcon::activated, [this](auto reason) { + if (reason == QSystemTrayIcon::Trigger) { + if (isVisible()) { + hide(); + } else { + show(); + activateWindow(); + } + } + }); +} + +void MainWindow::cleanTrayIcon() { + m_trayIcon->hide(); + m_trayIconMenu->deleteLater(); + m_trayIcon->deleteLater(); + m_trayIconMenu = nullptr; + m_trayIcon = nullptr; +} + +void MainWindow::setupSettings() { + m_settings = new QSettings("maltejur", "discord-screenaudio", this); + m_settings->beginGroup("settings"); + m_settings->endGroup(); +} + +QSettings *MainWindow::settings() const { return m_settings; } + +void MainWindow::setTrayIcon(bool enabled) { + m_settings->setValue("trayIcon", enabled); + if (enabled) { + setupTrayIcon(); + } else { + cleanTrayIcon(); + } +} + +void MainWindow::closeEvent(QCloseEvent *event) { + if (m_settings->value("trayIcon", false).toBool()) { + hide(); + } else + QApplication::quit(); +} MainWindow *MainWindow::instance() { return m_instance; } diff --git a/src/mainwindow.h b/src/mainwindow.h index e1b991a..3b5ed4a 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -3,8 +3,11 @@ #include "discordpage.h" #include +#include #include +#include #include +#include #include #include #include @@ -16,13 +19,20 @@ class MainWindow : public QMainWindow { public: explicit MainWindow(bool useNotifySend = false, QWidget *parent = nullptr); static MainWindow *instance(); + QSettings *settings() const; private: void setupWebView(); + void setupTrayIcon(); + void cleanTrayIcon(); + void setupSettings(); QWebEngineView *m_webView; QWebEngineProfile *prepareProfile(); DiscordPage *m_discordPage; void closeEvent(QCloseEvent *event) override; + QSystemTrayIcon *m_trayIcon; + QMenu *m_trayIconMenu; + QSettings *m_settings; bool m_wasMaximized; static MainWindow *m_instance; bool m_useNotifySend; @@ -32,6 +42,9 @@ private: bool m_useKF5Notifications = false; #endif +public Q_SLOTS: + void setTrayIcon(bool enabled); + private Q_SLOTS: void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); };