mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-24 13:25:52 +03:00
WinUpdater: More useful options on update failure #7217
Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
This commit is contained in:
parent
9596eb7f20
commit
0b3512f49c
2 changed files with 97 additions and 53 deletions
|
@ -32,7 +32,6 @@ namespace OCC {
|
||||||
static const char updateAvailableC[] = "Updater/updateAvailable";
|
static const char updateAvailableC[] = "Updater/updateAvailable";
|
||||||
static const char updateTargetVersionC[] = "Updater/updateTargetVersion";
|
static const char updateTargetVersionC[] = "Updater/updateTargetVersion";
|
||||||
static const char seenVersionC[] = "Updater/seenVersion";
|
static const char seenVersionC[] = "Updater/seenVersion";
|
||||||
static const char autoUpdateFailedVersionC[] = "Updater/autoUpdateFailedVersion";
|
|
||||||
static const char autoUpdateAttemptedC[] = "Updater/autoUpdateAttempted";
|
static const char autoUpdateAttemptedC[] = "Updater/autoUpdateAttempted";
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,7 +274,6 @@ void OCUpdater::slotTimedOut()
|
||||||
|
|
||||||
NSISUpdater::NSISUpdater(const QUrl &url)
|
NSISUpdater::NSISUpdater(const QUrl &url)
|
||||||
: OCUpdater(url)
|
: OCUpdater(url)
|
||||||
, _showFallbackMessage(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,6 +285,18 @@ void NSISUpdater::slotWriteFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NSISUpdater::wipeUpdateData()
|
||||||
|
{
|
||||||
|
ConfigFile cfg;
|
||||||
|
QSettings settings(cfg.configFile(), QSettings::IniFormat);
|
||||||
|
QString updateFileName = settings.value(updateAvailableC).toString();
|
||||||
|
if (!updateFileName.isEmpty())
|
||||||
|
QFile::remove(updateFileName);
|
||||||
|
settings.remove(updateAvailableC);
|
||||||
|
settings.remove(updateTargetVersionC);
|
||||||
|
settings.remove(autoUpdateAttemptedC);
|
||||||
|
}
|
||||||
|
|
||||||
void NSISUpdater::slotDownloadFinished()
|
void NSISUpdater::slotDownloadFinished()
|
||||||
{
|
{
|
||||||
auto *reply = qobject_cast<QNetworkReply *>(sender());
|
auto *reply = qobject_cast<QNetworkReply *>(sender());
|
||||||
|
@ -329,12 +339,9 @@ void NSISUpdater::versionInfoArrived(const UpdateInfo &info)
|
||||||
setDownloadState(UpToDate);
|
setDownloadState(UpToDate);
|
||||||
} else {
|
} else {
|
||||||
QString url = info.downloadUrl();
|
QString url = info.downloadUrl();
|
||||||
qint64 autoUpdateFailedVersion =
|
if (url.isEmpty()) {
|
||||||
Helper::stringVersionToInt(settings.value(autoUpdateFailedVersionC).toString());
|
showNoUrlDialog(info);
|
||||||
if (url.isEmpty() || _showFallbackMessage || infoVersion == autoUpdateFailedVersion) {
|
} else {
|
||||||
showDialog(info);
|
|
||||||
}
|
|
||||||
if (!url.isEmpty()) {
|
|
||||||
_targetFile = cfg.configPath() + url.mid(url.lastIndexOf('/')+1);
|
_targetFile = cfg.configPath() + url.mid(url.lastIndexOf('/')+1);
|
||||||
if (QFile(_targetFile).exists()) {
|
if (QFile(_targetFile).exists()) {
|
||||||
setDownloadState(DownloadComplete);
|
setDownloadState(DownloadComplete);
|
||||||
|
@ -353,14 +360,15 @@ void NSISUpdater::versionInfoArrived(const UpdateInfo &info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSISUpdater::showDialog(const UpdateInfo &info)
|
void NSISUpdater::showNoUrlDialog(const UpdateInfo &info)
|
||||||
{
|
{
|
||||||
// if the version tag is set, there is a newer version.
|
// if the version tag is set, there is a newer version.
|
||||||
auto *msgBox = new QDialog;
|
auto *msgBox = new QDialog;
|
||||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->setWindowFlags(msgBox->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
QIcon infoIcon = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, nullptr);
|
QIcon infoIcon = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation);
|
||||||
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, nullptr);
|
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
|
||||||
|
|
||||||
msgBox->setWindowIcon(infoIcon);
|
msgBox->setWindowIcon(infoIcon);
|
||||||
|
|
||||||
|
@ -387,7 +395,6 @@ void NSISUpdater::showDialog(const UpdateInfo &info)
|
||||||
hlayout->addWidget(lbl);
|
hlayout->addWidget(lbl);
|
||||||
|
|
||||||
auto *bb = new QDialogButtonBox;
|
auto *bb = new QDialogButtonBox;
|
||||||
bb->setWindowFlags(bb->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
||||||
QPushButton *skip = bb->addButton(tr("Skip this version"), QDialogButtonBox::ResetRole);
|
QPushButton *skip = bb->addButton(tr("Skip this version"), QDialogButtonBox::ResetRole);
|
||||||
QPushButton *reject = bb->addButton(tr("Skip this time"), QDialogButtonBox::AcceptRole);
|
QPushButton *reject = bb->addButton(tr("Skip this time"), QDialogButtonBox::AcceptRole);
|
||||||
QPushButton *getupdate = bb->addButton(tr("Get update"), QDialogButtonBox::AcceptRole);
|
QPushButton *getupdate = bb->addButton(tr("Get update"), QDialogButtonBox::AcceptRole);
|
||||||
|
@ -397,14 +404,78 @@ void NSISUpdater::showDialog(const UpdateInfo &info)
|
||||||
connect(getupdate, &QAbstractButton::clicked, msgBox, &QDialog::accept);
|
connect(getupdate, &QAbstractButton::clicked, msgBox, &QDialog::accept);
|
||||||
|
|
||||||
connect(skip, &QAbstractButton::clicked, this, &NSISUpdater::slotSetSeenVersion);
|
connect(skip, &QAbstractButton::clicked, this, &NSISUpdater::slotSetSeenVersion);
|
||||||
connect(getupdate, SIGNAL(clicked()), SLOT(slotOpenUpdateUrl()));
|
connect(getupdate, &QAbstractButton::clicked, this, &NSISUpdater::slotOpenUpdateUrl);
|
||||||
|
|
||||||
layout->addWidget(bb);
|
layout->addWidget(bb);
|
||||||
|
|
||||||
msgBox->open();
|
msgBox->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
NSISUpdater::UpdateState NSISUpdater::updateStateOnStart()
|
void NSISUpdater::showUpdateErrorDialog()
|
||||||
|
{
|
||||||
|
QDialog *msgBox = new QDialog;
|
||||||
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->setWindowFlags(msgBox->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
|
QIcon infoIcon = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation);
|
||||||
|
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
|
||||||
|
|
||||||
|
msgBox->setWindowIcon(infoIcon);
|
||||||
|
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(msgBox);
|
||||||
|
QHBoxLayout *hlayout = new QHBoxLayout;
|
||||||
|
layout->addLayout(hlayout);
|
||||||
|
|
||||||
|
msgBox->setWindowTitle(tr("Update Failed"));
|
||||||
|
|
||||||
|
QLabel *ico = new QLabel;
|
||||||
|
ico->setFixedSize(iconSize, iconSize);
|
||||||
|
ico->setPixmap(infoIcon.pixmap(iconSize));
|
||||||
|
QLabel *lbl = new QLabel;
|
||||||
|
QString txt = tr("<p>A new version of the %1 Client is available but the updating process failed.</p>"
|
||||||
|
"<p><b>%2</b> has been downloaded. The installed version is %3.</p>")
|
||||||
|
.arg(Utility::escape(Theme::instance()->appNameGUI()),
|
||||||
|
Utility::escape(updateInfo().versionString()), Utility::escape(clientVersion()));
|
||||||
|
|
||||||
|
lbl->setText(txt);
|
||||||
|
lbl->setTextFormat(Qt::RichText);
|
||||||
|
lbl->setWordWrap(true);
|
||||||
|
|
||||||
|
hlayout->addWidget(ico);
|
||||||
|
hlayout->addWidget(lbl);
|
||||||
|
|
||||||
|
QDialogButtonBox *bb = new QDialogButtonBox;
|
||||||
|
QPushButton *skip = bb->addButton(tr("Skip this version"), QDialogButtonBox::ResetRole);
|
||||||
|
QPushButton *askagain = bb->addButton(tr("Ask again later"), QDialogButtonBox::ResetRole);
|
||||||
|
QPushButton *retry = bb->addButton(tr("Restart and update"), QDialogButtonBox::AcceptRole);
|
||||||
|
QPushButton *getupdate = bb->addButton(tr("Update manually"), QDialogButtonBox::AcceptRole);
|
||||||
|
|
||||||
|
connect(skip, &QAbstractButton::clicked, msgBox, &QDialog::reject);
|
||||||
|
connect(askagain, &QAbstractButton::clicked, msgBox, &QDialog::reject);
|
||||||
|
connect(retry, &QAbstractButton::clicked, msgBox, &QDialog::accept);
|
||||||
|
connect(getupdate, &QAbstractButton::clicked, msgBox, &QDialog::accept);
|
||||||
|
|
||||||
|
connect(skip, &QAbstractButton::clicked, this, [this]() {
|
||||||
|
wipeUpdateData();
|
||||||
|
slotSetSeenVersion();
|
||||||
|
});
|
||||||
|
// askagain: do nothing
|
||||||
|
connect(retry, &QAbstractButton::clicked, this, [this]() {
|
||||||
|
slotStartInstaller();
|
||||||
|
qApp->quit();
|
||||||
|
});
|
||||||
|
connect(getupdate, &QAbstractButton::clicked, this, [this]() {
|
||||||
|
wipeUpdateData();
|
||||||
|
slotSetSeenVersion();
|
||||||
|
slotOpenUpdateUrl();
|
||||||
|
});
|
||||||
|
|
||||||
|
layout->addWidget(bb);
|
||||||
|
|
||||||
|
msgBox->open();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NSISUpdater::handleStartup()
|
||||||
{
|
{
|
||||||
ConfigFile cfg;
|
ConfigFile cfg;
|
||||||
QSettings settings(cfg.configFile(), QSettings::IniFormat);
|
QSettings settings(cfg.configFile(), QSettings::IniFormat);
|
||||||
|
@ -413,44 +484,20 @@ NSISUpdater::UpdateState NSISUpdater::updateStateOnStart()
|
||||||
if (!updateFileName.isEmpty() && QFile(updateFileName).exists()) {
|
if (!updateFileName.isEmpty() && QFile(updateFileName).exists()) {
|
||||||
// did it try to execute the update?
|
// did it try to execute the update?
|
||||||
if (settings.value(autoUpdateAttemptedC, false).toBool()) {
|
if (settings.value(autoUpdateAttemptedC, false).toBool()) {
|
||||||
// clean up
|
|
||||||
settings.remove(autoUpdateAttemptedC);
|
|
||||||
settings.remove(updateAvailableC);
|
|
||||||
QFile::remove(updateFileName);
|
|
||||||
if (updateSucceeded()) {
|
if (updateSucceeded()) {
|
||||||
// success: clean up even more
|
// success: clean up
|
||||||
settings.remove(updateTargetVersionC);
|
wipeUpdateData();
|
||||||
settings.remove(autoUpdateFailedVersionC);
|
return false;
|
||||||
return NoUpdate;
|
|
||||||
} else {
|
} else {
|
||||||
// auto update failed. Set autoUpdateFailedVersion as a hint
|
// auto update failed. Ask user what to do
|
||||||
// for visual fallback notification
|
showUpdateErrorDialog();
|
||||||
QString targetVersion = settings.value(updateTargetVersionC).toString();
|
return false;
|
||||||
settings.setValue(autoUpdateFailedVersionC, targetVersion);
|
|
||||||
settings.remove(updateTargetVersionC);
|
|
||||||
return UpdateFailed;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!settings.contains(autoUpdateFailedVersionC)) {
|
return performUpdate();
|
||||||
return UpdateAvailable;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NoUpdate;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
bool NSISUpdater::handleStartup()
|
|
||||||
{
|
|
||||||
switch (updateStateOnStart()) {
|
|
||||||
case NSISUpdater::UpdateAvailable:
|
|
||||||
return performUpdate();
|
|
||||||
case NSISUpdater::UpdateFailed:
|
|
||||||
_showFallbackMessage = true;
|
|
||||||
return false;
|
|
||||||
case NSISUpdater::NoUpdate:
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSISUpdater::slotSetSeenVersion()
|
void NSISUpdater::slotSetSeenVersion()
|
||||||
|
|
|
@ -120,9 +120,9 @@ public slots:
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void backgroundCheckForUpdate() override;
|
void backgroundCheckForUpdate() override;
|
||||||
|
void slotOpenUpdateUrl();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotOpenUpdateUrl();
|
|
||||||
void slotVersionInfoArrived();
|
void slotVersionInfoArrived();
|
||||||
void slotTimedOut();
|
void slotTimedOut();
|
||||||
|
|
||||||
|
@ -148,9 +148,6 @@ class NSISUpdater : public OCUpdater
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum UpdateState { NoUpdate = 0,
|
|
||||||
UpdateAvailable,
|
|
||||||
UpdateFailed };
|
|
||||||
explicit NSISUpdater(const QUrl &url);
|
explicit NSISUpdater(const QUrl &url);
|
||||||
bool handleStartup() override;
|
bool handleStartup() override;
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -159,12 +156,12 @@ private slots:
|
||||||
void slotWriteFile();
|
void slotWriteFile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NSISUpdater::UpdateState updateStateOnStart();
|
void wipeUpdateData();
|
||||||
void showDialog(const UpdateInfo &info);
|
void showNoUrlDialog(const UpdateInfo &info);
|
||||||
|
void showUpdateErrorDialog();
|
||||||
void versionInfoArrived(const UpdateInfo &info) override;
|
void versionInfoArrived(const UpdateInfo &info) override;
|
||||||
QScopedPointer<QTemporaryFile> _file;
|
QScopedPointer<QTemporaryFile> _file;
|
||||||
QString _targetFile;
|
QString _targetFile;
|
||||||
bool _showFallbackMessage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue