mirror-chatterino2/src/singletons/Updates.cpp

239 lines
6.5 KiB
C++
Raw Normal View History

2018-06-28 19:46:45 +02:00
#include "Updates.hpp"
2018-04-19 22:16:55 +02:00
2018-06-26 15:33:51 +02:00
#include "common/NetworkRequest.hpp"
#include "common/Outcome.hpp"
2018-06-26 15:33:51 +02:00
#include "common/Version.hpp"
2018-07-07 12:03:37 +02:00
#include "singletons/Paths.hpp"
2018-06-26 14:09:39 +02:00
#include "util/CombinePath.hpp"
#include "util/PostToThread.hpp"
2018-04-19 22:16:55 +02:00
#include <QDebug>
2019-08-18 20:14:00 +02:00
#include <QDesktopServices>
2018-06-21 22:02:35 +02:00
#include <QMessageBox>
#include <QProcess>
2018-04-19 22:16:55 +02:00
namespace chatterino {
2018-06-28 19:51:07 +02:00
Updates::Updates()
2018-06-01 14:20:46 +02:00
: currentVersion_(CHATTERINO_VERSION)
2019-08-18 20:14:00 +02:00
, updateGuideLink_("https://chatterino.com")
2018-04-19 22:16:55 +02:00
{
qDebug() << "init UpdateManager";
2018-04-19 22:16:55 +02:00
}
2018-06-28 19:51:07 +02:00
Updates &Updates::getInstance()
2018-04-19 22:16:55 +02:00
{
2018-06-01 14:20:46 +02:00
// fourtf: don't add this class to the application class
2018-06-28 19:51:07 +02:00
static Updates instance;
2018-06-01 14:20:46 +02:00
2018-04-19 22:16:55 +02:00
return instance;
}
2018-06-28 19:51:07 +02:00
const QString &Updates::getCurrentVersion() const
2018-04-19 22:16:55 +02:00
{
2018-06-01 14:20:46 +02:00
return currentVersion_;
2018-04-19 22:16:55 +02:00
}
2018-06-28 19:51:07 +02:00
const QString &Updates::getOnlineVersion() const
2018-04-19 22:16:55 +02:00
{
2018-06-01 14:20:46 +02:00
return onlineVersion_;
}
2018-06-28 19:51:07 +02:00
void Updates::installUpdates()
2018-06-01 14:20:46 +02:00
{
2018-10-21 13:43:02 +02:00
if (this->status_ != UpdateAvailable)
{
2018-06-21 22:02:35 +02:00
assert(false);
return;
}
2019-08-18 20:14:00 +02:00
#ifdef Q_OS_MACOS
QMessageBox *box = new QMessageBox(
QMessageBox::Information, "Chatterino Update",
"A link will open in your browser. Download and install to update.");
box->setAttribute(Qt::WA_DeleteOnClose);
box->exec();
QDesktopServices::openUrl(this->updateExe_);
#elif defined Q_OS_LINUX
QMessageBox *box =
new QMessageBox(QMessageBox::Information, "Chatterino Update",
"Automatic updates are currently not available on "
"linux. Please redownload the app to update.");
box->setAttribute(Qt::WA_DeleteOnClose);
box->exec();
QDesktopServices::openUrl(this->updateGuideLink_);
#elif defined Q_OS_WIN
2018-08-06 21:17:03 +02:00
QMessageBox *box =
new QMessageBox(QMessageBox::Information, "Chatterino Update",
"Chatterino is downloading the update "
"in the background and will run the "
"updater once it is finished.");
2018-06-21 22:02:35 +02:00
box->setAttribute(Qt::WA_DeleteOnClose);
box->show();
2019-08-18 20:14:00 +02:00
NetworkRequest req(this->updateExe_);
2018-06-21 22:02:35 +02:00
req.setTimeout(600000);
req.onError([this](int) -> bool {
this->setStatus_(DownloadFailed);
2018-06-21 22:39:17 +02:00
2019-08-18 20:14:00 +02:00
QMessageBox *box =
new QMessageBox(QMessageBox::Information, "Chatterino Update",
"Failed to download the update. \n\nTry manually "
"downloading the update.");
box->setAttribute(Qt::WA_DeleteOnClose);
box->exec();
2018-06-21 22:02:35 +02:00
return true;
});
2018-07-07 12:03:37 +02:00
2018-08-06 18:25:47 +02:00
req.onSuccess([this](auto result) -> Outcome {
2018-07-07 12:03:37 +02:00
QByteArray object = result.getData();
2019-08-18 20:14:00 +02:00
auto filename = combinePath(getPaths()->miscDirectory, "Update.exe");
2018-06-21 22:02:35 +02:00
QFile file(filename);
2018-06-21 23:02:42 +02:00
file.open(QIODevice::Truncate | QIODevice::WriteOnly);
2018-10-21 13:43:02 +02:00
if (file.write(object) == -1)
{
2018-06-21 22:02:35 +02:00
this->setStatus_(WriteFileFailed);
2019-08-18 20:14:00 +02:00
QMessageBox *box = new QMessageBox(
QMessageBox::Information, "Chatterino Update",
"Failed to save the update file. This could be due to "
"window settings or antivirus software.\n\nTry manually "
"downloading the update.");
box->setAttribute(Qt::WA_DeleteOnClose);
box->exec();
QDesktopServices::openUrl(this->updateExe_);
2018-08-06 18:25:47 +02:00
return Failure;
2018-06-21 22:02:35 +02:00
}
2019-08-18 20:14:00 +02:00
file.close();
if (QProcess::startDetached(filename))
{
QApplication::exit(0);
}
else
{
QMessageBox *box = new QMessageBox(
QMessageBox::Information, "Chatterino Update",
"Failed to execute update binary. This could be due to window "
"settings or antivirus software.\n\nTry manually downloading "
"the update.");
box->setAttribute(Qt::WA_DeleteOnClose);
box->exec();
2018-06-21 22:02:35 +02:00
2019-08-18 20:14:00 +02:00
QDesktopServices::openUrl(this->updateExe_);
}
2018-06-21 22:02:35 +02:00
2018-08-06 18:25:47 +02:00
return Success;
2018-06-21 22:02:35 +02:00
});
this->setStatus_(Downloading);
req.execute();
#endif
2018-04-19 22:16:55 +02:00
}
2018-06-28 19:51:07 +02:00
void Updates::checkForUpdates()
2018-04-19 22:16:55 +02:00
{
2018-08-06 21:17:03 +02:00
QString url =
"https://notitia.chatterino.com/version/chatterino/" CHATTERINO_OS
"/stable";
2018-04-19 22:16:55 +02:00
2018-06-26 17:06:17 +02:00
NetworkRequest req(url);
2019-08-18 20:14:00 +02:00
req.setTimeout(60000);
2018-08-06 18:25:47 +02:00
req.onSuccess([this](auto result) -> Outcome {
auto object = result.parseJson();
2019-08-18 20:14:00 +02:00
/// Version available on every platform
2018-04-20 00:15:57 +02:00
QJsonValue version_val = object.value("version");
2018-06-21 22:02:35 +02:00
2019-08-18 20:14:00 +02:00
if (!version_val.isString())
2018-10-21 13:43:02 +02:00
{
2018-06-21 22:02:35 +02:00
this->setStatus_(SearchFailed);
2018-04-19 22:16:55 +02:00
qDebug() << "error updating";
2019-08-18 20:14:00 +02:00
return Failure;
}
2018-06-21 22:02:35 +02:00
2019-08-18 20:14:00 +02:00
#if defined Q_OS_WIN || defined Q_OS_MACOS
/// Windows downloads an installer for the new version
QJsonValue updateExe_val = object.value("updateexe");
if (!updateExe_val.isString())
{
this->setStatus_(SearchFailed);
qDebug() << "error updating";
2018-08-06 18:25:47 +02:00
return Failure;
2018-04-19 22:16:55 +02:00
}
2019-08-18 20:14:00 +02:00
this->updateExe_ = updateExe_val.toString();
2018-04-19 22:16:55 +02:00
2019-08-18 20:14:00 +02:00
#elif defined Q_OS_LINUX
QJsonValue updateGuide_val = object.value("updateguide");
if (updateGuide_val.isString())
{
this->updateGuideLink_ = updateGuide_val.toString();
}
#else
return Failure;
#endif
/// Current version
2018-06-01 14:20:46 +02:00
this->onlineVersion_ = version_val.toString();
2019-08-18 20:14:00 +02:00
/// Update available :)
2018-10-21 13:43:02 +02:00
if (this->currentVersion_ != this->onlineVersion_)
{
2018-06-01 14:20:46 +02:00
this->setStatus_(UpdateAvailable);
2018-10-21 13:43:02 +02:00
}
else
{
2018-06-01 14:20:46 +02:00
this->setStatus_(NoUpdateAvailable);
}
2018-08-06 18:25:47 +02:00
return Failure;
2018-04-19 22:16:55 +02:00
});
2018-06-01 14:20:46 +02:00
this->setStatus_(Searching);
req.execute();
}
2018-07-05 11:42:40 +02:00
Updates::Status Updates::getStatus() const
2018-06-01 14:20:46 +02:00
{
return this->status_;
}
2018-07-05 11:42:40 +02:00
bool Updates::shouldShowUpdateButton() const
{
2018-10-21 13:43:02 +02:00
switch (this->getStatus())
{
2018-07-05 11:42:40 +02:00
case UpdateAvailable:
case SearchFailed:
case Downloading:
case DownloadFailed:
case WriteFileFailed:
return true;
default:
return false;
}
}
bool Updates::isError() const
{
2018-10-21 13:43:02 +02:00
switch (this->getStatus())
{
2018-07-05 11:42:40 +02:00
case SearchFailed:
case DownloadFailed:
case WriteFileFailed:
return true;
default:
return false;
}
}
void Updates::setStatus_(Status status)
2018-06-01 14:20:46 +02:00
{
2018-10-21 13:43:02 +02:00
if (this->status_ != status)
{
2018-06-01 14:20:46 +02:00
this->status_ = status;
2018-06-26 17:06:17 +02:00
postToThread([this, status] { this->statusUpdated.invoke(status); });
2018-06-01 14:20:46 +02:00
}
2018-04-19 22:16:55 +02:00
}
} // namespace chatterino