diff --git a/resources/images/download_update_error.png b/resources/images/download_update_error.png
new file mode 100644
index 00000000..5c1fec10
Binary files /dev/null and b/resources/images/download_update_error.png differ
diff --git a/resources/resources.qrc b/resources/resources.qrc
index 146c2c66..cf41c346 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -73,6 +73,7 @@
avatars/fourtf.png
avatars/pajlada.png
images/download_update.png
+ images/download_update_error.png
qt.conf
diff --git a/src/singletons/Updates.cpp b/src/singletons/Updates.cpp
index 4cadf2b1..c9580939 100644
--- a/src/singletons/Updates.cpp
+++ b/src/singletons/Updates.cpp
@@ -141,12 +141,40 @@ void Updates::checkForUpdates()
#endif
}
-Updates::UpdateStatus Updates::getStatus() const
+Updates::Status Updates::getStatus() const
{
return this->status_;
}
-void Updates::setStatus_(UpdateStatus status)
+bool Updates::shouldShowUpdateButton() const
+{
+ switch (this->getStatus()) {
+ case UpdateAvailable:
+ case SearchFailed:
+ case Downloading:
+ case DownloadFailed:
+ case WriteFileFailed:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool Updates::isError() const
+{
+ switch (this->getStatus()) {
+ case SearchFailed:
+ case DownloadFailed:
+ case WriteFileFailed:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void Updates::setStatus_(Status status)
{
if (this->status_ != status) {
this->status_ = status;
diff --git a/src/singletons/Updates.hpp b/src/singletons/Updates.hpp
index f760631a..ff3df8bb 100644
--- a/src/singletons/Updates.hpp
+++ b/src/singletons/Updates.hpp
@@ -10,7 +10,7 @@ class Updates
Updates();
public:
- enum UpdateStatus {
+ enum Status {
None,
Searching,
UpdateAvailable,
@@ -28,18 +28,21 @@ public:
const QString &getCurrentVersion() const;
const QString &getOnlineVersion() const;
void installUpdates();
- UpdateStatus getStatus() const;
+ Status getStatus() const;
- pajlada::Signals::Signal statusUpdated;
+ bool shouldShowUpdateButton() const;
+ bool isError() const;
+
+ pajlada::Signals::Signal statusUpdated;
private:
QString currentVersion_;
QString onlineVersion_;
- UpdateStatus status_ = None;
+ Status status_ = None;
QString updateUrl_;
- void setStatus_(UpdateStatus status);
+ void setStatus_(Status status);
};
} // namespace chatterino
diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp
index c78096c5..dfcd8b8b 100644
--- a/src/widgets/BaseWindow.cpp
+++ b/src/widgets/BaseWindow.cpp
@@ -409,6 +409,11 @@ void BaseWindow::resizeEvent(QResizeEvent *)
this->calcButtonsSizes();
}
+void BaseWindow::closeEvent(QCloseEvent *)
+{
+ this->closing.invoke();
+}
+
void BaseWindow::moveIntoDesktopRect(QWidget *parent)
{
if (!this->stayInScreenRect_)
diff --git a/src/widgets/BaseWindow.hpp b/src/widgets/BaseWindow.hpp
index 8e6c591e..5baf88b6 100644
--- a/src/widgets/BaseWindow.hpp
+++ b/src/widgets/BaseWindow.hpp
@@ -52,6 +52,8 @@ public:
Flags getFlags();
+ pajlada::Signals::NoArgSignal closing;
+
protected:
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
virtual void scaleChangedEvent(float) override;
@@ -61,6 +63,7 @@ protected:
virtual void changeEvent(QEvent *) override;
virtual void leaveEvent(QEvent *) override;
virtual void resizeEvent(QResizeEvent *) override;
+ virtual void closeEvent(QCloseEvent *) override;
virtual void themeRefreshEvent() override;
virtual bool event(QEvent *event) override;
diff --git a/src/widgets/Window.cpp b/src/widgets/Window.cpp
index 23475e9d..5e733abb 100644
--- a/src/widgets/Window.cpp
+++ b/src/widgets/Window.cpp
@@ -6,6 +6,7 @@
#include "providers/twitch/TwitchServer.hpp"
#include "singletons/Settings.hpp"
#include "singletons/Theme.hpp"
+#include "singletons/Updates.hpp"
#include "singletons/WindowManager.hpp"
#include "widgets/AccountSwitchPopupWidget.hpp"
#include "widgets/Notebook.hpp"
@@ -53,27 +54,7 @@ Window::Window(WindowType _type)
});
if (this->hasCustomWindowFrame() && _type == Window::Main) {
- // settings
- this->addTitleBarButton(TitleBarButton::Settings, [app] {
- app->windows->showSettingsDialog(); //
- });
-
- // updates
- auto update = this->addTitleBarButton(TitleBarButton::None, [] {});
- update->setPixmap(QPixmap(":/images/download_update.png"));
- QObject::connect(update, &TitleBarButton::clicked, this, [this, update] {
- auto dialog = new UpdatePromptDialog();
- dialog->setActionOnFocusLoss(BaseWindow::Delete);
- dialog->move(update->mapToGlobal(QPoint(-100 * this->getScale(), update->height())));
- dialog->show();
- dialog->raise();
- });
-
- // account
- this->userLabel = this->addTitleBarLabel([this, app] {
- app->windows->showAccountSelectPopup(
- this->userLabel->mapToGlobal(this->userLabel->rect().bottomLeft())); //
- });
+ this->addCustomTitlebarButtons();
}
if (_type == Window::Main) {
@@ -194,6 +175,54 @@ Window::Window(WindowType _type)
this->notebook.setShowAddButton(true);
}
+void Window::addCustomTitlebarButtons()
+{
+ // settings
+ this->addTitleBarButton(TitleBarButton::Settings, [] {
+ getApp()->windows->showSettingsDialog(); //
+ });
+
+ // updates
+ auto update = this->addTitleBarButton(TitleBarButton::None, [] {});
+ update->hide();
+ QObject::connect(update, &TitleBarButton::clicked, this, [this, update] {
+ auto dialog = new UpdatePromptDialog();
+ dialog->setActionOnFocusLoss(BaseWindow::Delete);
+ dialog->move(update->mapToGlobal(QPoint(int(-100 * this->getScale()), update->height())));
+ dialog->show();
+ dialog->raise();
+
+ dialog->buttonClicked.connect([update](auto button) {
+ switch (button) {
+ case UpdatePromptDialog::Dismiss: {
+ update->hide();
+ } break;
+ }
+ });
+
+ this->updateDialogHandle_.reset(dialog);
+ dialog->closing.connect([this] { this->updateDialogHandle_.release(); });
+ });
+
+ auto updateChange = [update](auto) {
+ update->setVisible(Updates::getInstance().shouldShowUpdateButton());
+
+ auto imageUrl = Updates::getInstance().isError() ? ":/images/download_update_error.png"
+ : ":/images/download_update.png";
+ update->setPixmap(QPixmap(imageUrl));
+ };
+
+ updateChange(Updates::getInstance().getStatus());
+ this->signalHolder.managedConnect(Updates::getInstance().statusUpdated,
+ [updateChange](auto status) { updateChange(status); });
+
+ // account
+ this->userLabel = this->addTitleBarLabel([this] {
+ getApp()->windows->showAccountSelectPopup(
+ this->userLabel->mapToGlobal(this->userLabel->rect().bottomLeft())); //
+ });
+}
+
Window::WindowType Window::getType()
{
return this->type;
diff --git a/src/widgets/Window.hpp b/src/widgets/Window.hpp
index 60bf8be8..60ce046c 100644
--- a/src/widgets/Window.hpp
+++ b/src/widgets/Window.hpp
@@ -10,10 +10,12 @@
#include
#include
+#include
namespace chatterino {
class Theme;
+class UpdatePromptDialog;
class Window : public BaseWindow
{
@@ -40,15 +42,19 @@ protected:
bool event(QEvent *event) override;
private:
+ void addCustomTitlebarButtons();
+ void loadGeometry();
+
RippleEffectLabel *userLabel = nullptr;
+ std::unique_ptr updateDialogHandle_;
WindowType type;
float dpi;
- void loadGeometry();
-
SplitNotebook notebook;
+ pajlada::Signals::SignalHolder signalHolder;
+
friend class Notebook;
public:
diff --git a/src/widgets/dialogs/UpdatePromptDialog.cpp b/src/widgets/dialogs/UpdatePromptDialog.cpp
index 2cc4df2a..a8b36c38 100644
--- a/src/widgets/dialogs/UpdatePromptDialog.cpp
+++ b/src/widgets/dialogs/UpdatePromptDialog.cpp
@@ -1,5 +1,6 @@
#include "UpdatePromptDialog.hpp"
+#include "singletons/Updates.hpp"
#include "util/LayoutCreator.hpp"
#include "widgets/Label.hpp"
@@ -15,16 +16,53 @@ UpdatePromptDialog::UpdatePromptDialog()
{
auto layout = LayoutCreator(this).setLayoutType();
- layout.emplace