feat(updater): tie in part 2, let there be UI!

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers 2023-06-26 01:22:33 -07:00
parent b7dd32274c
commit 1f70589deb
No known key found for this signature in database
GPG Key ID: E10E321EB160949B
10 changed files with 512 additions and 36 deletions

View File

@ -122,6 +122,7 @@
#include <FileSystem.h>
#include <LocalPeer.h>
#include <stdlib.h>
#include <sys.h>
#ifdef Q_OS_LINUX
@ -397,6 +398,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
.arg(dataPath));
return;
}
m_dataPath = dataPath;
/*
* Establish the mechanism for communication with an already running PrismLauncher that uses the same data path.
@ -829,7 +831,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
#ifdef Q_OS_MAC
m_updater.reset(new MacSparkleUpdater());
#else
m_updater.reset(new PrismExternalUpdater(m_rootPath, dataPath));
m_updater.reset(new PrismExternalUpdater(m_rootPath, m_dataPath));
#endif
qDebug() << "<> Updater started.";
}
@ -1024,9 +1026,120 @@ void Application::setupWizardFinished(int status)
performMainStartupAction();
}
std::tuple<QDateTime, QString, QString, QString, QString> read_lock_File(const QString& path)
{
auto contents = QString(FS::read(path));
auto lines = contents.split('\n');
QDateTime timestamp;
QString from, to, target, data_path;
for (auto line : lines) {
auto index = line.indexOf("=");
if (index < 0)
continue;
auto left = line.left(index);
auto right = line.mid(index + 1);
if (left.toLower() == "timestamp") {
timestamp = QDateTime::fromString(right, Qt::ISODate);
} else if (left.toLower() == "from") {
from = right;
} else if (left.toLower() == "to") {
to = right;
} else if (left.toLower() == "target") {
target = right;
} else if (left.toLower() == "data_path") {
data_path = right;
}
}
return std::make_tuple(timestamp, from, to, target, data_path);
}
void Application::performMainStartupAction()
{
m_status = Application::Initialized;
auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log");
auto update_lock = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"));
if (update_lock.exists()) {
auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock.absoluteFilePath());
auto infoMsg = tr("This installation has a update lock file present at: %1\n"
"\n"
"Timestamp: %2\n"
"Updating from version %3 to %4\n"
"Target install path: %5\n"
"Data Path: %6"
"\n"
"This likely means that a update attempt failed. Please ensure your installation is in working order before "
"proceeding.\n"
"Check the Prism Launcher updater log at: \n"
"%7\n"
"for details on the last update attempt.\n"
"\n"
"To delete this lock and proceed select \"Ignore\" below.")
.arg(update_lock.absoluteFilePath())
.arg(timestamp.toString(Qt::ISODate), from, to, target, data_path)
.arg(update_log_path);
auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update In Progress"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort);
msgBox.setDefaultButton(QMessageBox::Abort);
msgBox.setModal(true);
switch (msgBox.exec()) {
case QMessageBox::AcceptRole: {
FS::deletePath(update_lock.absoluteFilePath());
break;
}
case QMessageBox::RejectRole:
[[fallthrough]];
default: {
qDebug() << "Exiting because update lockfile is present";
exit(1);
}
}
}
auto update_fail_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.fail"));
if (update_fail_marker.exists()) {
auto infoMsg = tr("An update attempt failed\n"
"\n"
"Please ensure your installation is in working order before "
"proceeding.\n"
"Check the Prism Launcher updater log at: \n"
"%1\n"
"for details on the last update attempt.")
.arg(update_log_path);
auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Failed"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort);
msgBox.setDefaultButton(QMessageBox::Abort);
msgBox.setModal(true);
switch (msgBox.exec()) {
case QMessageBox::AcceptRole: {
FS::deletePath(update_fail_marker.absoluteFilePath());
break;
}
case QMessageBox::RejectRole:
[[fallthrough]];
default: {
qDebug() << "Exiting because update lockfile is present";
exit(1);
}
}
}
auto update_success_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.success"));
if (update_success_marker.exists()) {
auto infoMsg = tr("Update succeeded\n"
"\n"
"You are now running %1 .\n"
"Check the Prism Launcher updater log at: \n"
"%1\n"
"for details.")
.arg(BuildConfig.printableVersionString())
.arg(update_log_path);
auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.open();
FS::deletePath(update_success_marker.absoluteFilePath());
}
if (!m_instanceIdToLaunch.isEmpty()) {
auto inst = instances()->getInstanceById(m_instanceIdToLaunch);
if (inst) {

View File

@ -187,6 +187,11 @@ public:
return m_rootPath;
}
/// the data path the application is using
const QString& dataRoot() {
return m_dataPath;
}
bool isPortable() {
return m_portable;
}
@ -277,6 +282,7 @@ private:
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
QString m_rootPath;
QString m_dataPath;
Status m_status = Application::StartingUp;
Capabilities m_capabilities;
bool m_portable = false;

View File

@ -1078,6 +1078,15 @@ SET(LAUNCHER_SOURCES
ui/instanceview/VisualGroup.h
)
if (NOT Apple)
set(LAUNCHER_SOURCES
${LAUNCHER_SOURCES}
ui/dialogs/UpdateAvailableDialog.h
ui/dialogs/UpdateAvailableDialog.cpp
)
endif()
qt_wrap_ui(LAUNCHER_UI
ui/MainWindow.ui
ui/setupwizard/PasteWizardPage.ui
@ -1138,6 +1147,14 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/ChooseProviderDialog.ui
)
qt_wrap_ui(PRISM_UPDATE_UI
ui/dialogs/UpdateAvailableDialog.ui
)
if (NOT Apple)
set (LAUNCHER_UI ${LAUNCHER_UI} ${PRISM_UPDATE_UI})
endif()
qt_add_resources(LAUNCHER_RESOURCES
resources/backgrounds/backgrounds.qrc
resources/multimc/multimc.qrc

View File

@ -199,7 +199,7 @@ void appendSafe(const QString& filename, const QByteArray& data)
QByteArray buffer;
try {
buffer = read(filename);
} catch (FileSystemException) {
} catch (FileSystemException&) {
buffer = QByteArray();
}
buffer.append(data);

View File

@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
//
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "UpdateAvailableDialog.h"
#include <QPushButton>
#include "Application.h"
#include "BuildConfig.h"
#include "Markdown.h"
#include "ui_UpdateAvailableDialog.h"
UpdateAvailableDialog::UpdateAvailableDialog(const QString& currentVersion,
const QString& availableVersion,
const QString& releaseNotes,
QWidget* parent)
: QDialog(parent), ui(new Ui::UpdateAvailableDialog)
{
ui->setupUi(this);
QString launcherName = BuildConfig.LAUNCHER_DISPLAYNAME;
ui->headerLabel->setText(tr("A new version of %1 is available!").arg(launcherName));
ui->versionAvailableLabel->setText(
tr("Version %1 is now available - you have %2 . Would you like to download it now?").arg(availableVersion).arg(currentVersion));
ui->icon->setPixmap(APPLICATION->getThemedIcon("checkupdate").pixmap(64));
auto releaseNotesHtml = markdownToHTML(releaseNotes);
ui->releaseNotes->setHtml(releaseNotesHtml);
ui->releaseNotes->setOpenExternalLinks(true);
connect(ui->skipButton, &QPushButton::clicked, this, [this](){
this->setResult(DialogCode::Skip);
this->close();
});
connect(ui->delayButton, &QPushButton::clicked, this, [this](){
this->setResult(DialogCode::DontInstall);
this->close();
});
connect(ui->installButton, &QPushButton::clicked, this, [this](){
this->setResult(DialogCode::Install);
this->close();
});
}

View File

@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
//
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <QDialog>
namespace Ui {
class UpdateAvailableDialog;
}
class UpdateAvailableDialog : public QDialog {
Q_OBJECT
public:
enum DialogCode {
Install,
DontInstall,
Skip,
};
explicit UpdateAvailableDialog(const QString& currentVersion,
const QString& availableVersion,
const QString& releaseNotes,
QWidget* parent = 0);
~UpdateAvailableDialog();
private:
Ui::UpdateAvailableDialog* ui;
};

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UpdateAvailableDialog</class>
<widget class="QDialog" name="UpdateAvailableDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>636</width>
<height>352</height>
</rect>
</property>
<property name="windowTitle">
<string>Update Available</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
<item>
<layout class="QVBoxLayout" name="leftsideLayout">
<item>
<widget class="QLabel" name="icon">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="mainLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QLabel" name="headerLabel">
<property name="font">
<font>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>A new version is available!</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionAvailableLabel">
<property name="text">
<string>Version %1 is now available - you have %2 . Would you like to download it now?</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="releaseNotesLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Release Notes:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="releaseNotes"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="skipButton">
<property name="text">
<string>Skip This Version</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="delayButton">
<property name="text">
<string>Remind Me Later</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="installButton">
<property name="text">
<string>Install Update</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -21,19 +21,22 @@
*/
#include "PrismExternalUpdater.h"
#include <memory>
#include <QCoreApplication>
#include <QDateTime>
#include <QProgressDialog>
#include <QDir>
#include <QProcess>
#include <QTimer>
#include <QProgressDialog>
#include <QSettings>
#include <QCoreApplication>
#include <QTimer>
#include <memory>
#include <QDebug>
#include "StringUtils.h"
#include "BuildConfig.h"
#include "ui/dialogs/UpdateAvailableDialog.h"
class PrismExternalUpdater::Private {
public:
QDir appDir;
@ -78,12 +81,11 @@ PrismExternalUpdater::~PrismExternalUpdater()
void PrismExternalUpdater::checkForUpdates()
{
QProgressDialog progress(tr("Checking for updates..."), "", 0, -1);
QProgressDialog progress(tr("Checking for updates..."), "", 0, 0);
progress.setCancelButton(nullptr);
progress.show();
QCoreApplication::processEvents();
QProcess proc;
auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME);
#if defined Q_OS_WIN32
@ -98,14 +100,16 @@ void PrismExternalUpdater::checkForUpdates()
auto result_start = proc.waitForStarted(5000);
if (!result_start) {
auto err = proc.error();
qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString();
qDebug() << "Failed to start updater after 5 seconds."
<< "reason:" << err << proc.errorString();
}
QCoreApplication::processEvents();
auto result_finished = proc.waitForFinished(60000);
if (!result_finished) {
auto err = proc.error();
qDebug() << "Updater failed to close after 60 seconds." << "reason:" << err << proc.errorString();
qDebug() << "Updater failed to close after 60 seconds."
<< "reason:" << err << proc.errorString();
}
auto exit_code = proc.exitCode();
@ -116,6 +120,9 @@ void PrismExternalUpdater::checkForUpdates()
qDebug() << "captured output:" << std_output;
qDebug() << "captured error:" << std_error;
progress.hide();
QCoreApplication::processEvents();
switch (exit_code) {
case 0:
// no update available
@ -134,12 +141,14 @@ void PrismExternalUpdater::checkForUpdates()
{
auto [first_line, remainder1] = StringUtils::splitFirst(std_output, '\n');
auto [second_line, remainder2] = StringUtils::splitFirst(remainder1, '\n');
auto [third_line, changelog] = StringUtils::splitFirst(remainder2, '\n');
auto [third_line, release_notes] = StringUtils::splitFirst(remainder2, '\n');
auto version_name = StringUtils::splitFirst(first_line, ": ").second;
auto version_tag = StringUtils::splitFirst(second_line, ": ").second;
auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second, Qt::ISODate);
qDebug() << "Update available:" << version_name << version_tag << release_timestamp;
qDebug() << "Update changelog:" << changelog;
qDebug() << "Update release notes:" << release_notes;
offerUpdate(version_name, version_tag, release_notes);
}
break;
default:
@ -153,48 +162,55 @@ void PrismExternalUpdater::checkForUpdates()
priv->settings->sync();
}
bool PrismExternalUpdater::getAutomaticallyChecksForUpdates() {
bool PrismExternalUpdater::getAutomaticallyChecksForUpdates()
{
return priv->autoCheck;
}
double PrismExternalUpdater::getUpdateCheckInterval() {
double PrismExternalUpdater::getUpdateCheckInterval()
{
return priv->updateInterval;
}
bool PrismExternalUpdater::getBetaAllowed() {
bool PrismExternalUpdater::getBetaAllowed()
{
return priv->allowBeta;
}
void PrismExternalUpdater::setAutomaticallyChecksForUpdates(bool check) {
void PrismExternalUpdater::setAutomaticallyChecksForUpdates(bool check)
{
priv->autoCheck = check;
priv->settings->setValue("auto_check", check);
priv->settings->sync();
resetAutoCheckTimer();
}
void PrismExternalUpdater::setUpdateCheckInterval(double seconds) {
void PrismExternalUpdater::setUpdateCheckInterval(double seconds)
{
priv->updateInterval = seconds;
priv->settings->setValue("update_interval", seconds);
priv->settings->sync();
resetAutoCheckTimer();
}
void PrismExternalUpdater::setBetaAllowed(bool allowed) {
void PrismExternalUpdater::setBetaAllowed(bool allowed)
{
priv->allowBeta = allowed;
priv->settings->setValue("auto_beta", allowed);
priv->settings->sync();
}
void PrismExternalUpdater::resetAutoCheckTimer() {
void PrismExternalUpdater::resetAutoCheckTimer()
{
int timeoutDuration = 0;
auto now = QDateTime::currentDateTime();
if (priv->autoCheck) {
if (priv->lastCheck.isValid()) {
if (priv->lastCheck.isValid()) {
auto diff = priv->lastCheck.secsTo(now);
auto secs_left = priv->updateInterval - diff;
if (secs_left < 0)
secs_left = 0;
timeoutDuration = secs_left * 1000; // to msec
timeoutDuration = secs_left * 1000; // to msec
}
qDebug() << "Auto update timer starting," << timeoutDuration / 1000 << "seconds left";
priv->updateTimer.start(timeoutDuration);
@ -202,18 +218,66 @@ void PrismExternalUpdater::resetAutoCheckTimer() {
if (priv->updateTimer.isActive())
priv->updateTimer.stop();
}
}
void PrismExternalUpdater::connectTimer() {
void PrismExternalUpdater::connectTimer()
{
connect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired);
}
void PrismExternalUpdater::disconnectTimer() {
void PrismExternalUpdater::disconnectTimer()
{
disconnect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired);
}
void PrismExternalUpdater::autoCheckTimerFired() {
void PrismExternalUpdater::autoCheckTimerFired()
{
checkForUpdates();
}
void PrismExternalUpdater::offerUpdate(const QString& version_name, const QString& version_tag, const QString& release_notes)
{
priv->settings->beginGroup("skip");
auto should_skip = priv->settings->value(version_tag, false).toBool();
priv->settings->endGroup();
if (should_skip)
return;
UpdateAvailableDialog dlg(BuildConfig.printableVersionString(), version_name, release_notes);
auto result = dlg.exec();
switch (result) {
case UpdateAvailableDialog::Install: {
performUpdate(version_tag);
}
case UpdateAvailableDialog::Skip: {
priv->settings->beginGroup("skip");
priv->settings->setValue(version_tag, true);
priv->settings->endGroup();
priv->settings->sync();
return;
}
case UpdateAvailableDialog::DontInstall: {
return;
}
}
}
void PrismExternalUpdater::performUpdate(const QString& version_tag) {
QProcess proc;
auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME);
#if defined Q_OS_WIN32
exe_name.append(".exe");
#endif
QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag };
if (priv->allowBeta)
args.append("--pre-release");
auto result = proc.startDetached(priv->appDir.absoluteFilePath(exe_name), args);
if (!result) {
qDebug() << "Failed to start updater:" << proc.error() << proc.errorString();
}
QCoreApplication::exit();
}

View File

@ -34,7 +34,7 @@ class PrismExternalUpdater : public ExternalUpdater {
Q_OBJECT
public:
PrismExternalUpdater(const QString& appDir, const QString& dataDir);
PrismExternalUpdater(const QString& appDir, const QString& dataDir);
~PrismExternalUpdater() override;
/*!
@ -82,7 +82,8 @@ class PrismExternalUpdater : public ExternalUpdater {
void disconnectTimer();
void connectTimer();
void performUpdate();
void offerUpdate(const QString& version_name, const QString& version_tag, const QString& release_notes);
void performUpdate(const QString& version_tag);
public slots:
void autoCheckTimerFired();

View File

@ -630,7 +630,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target)
for (auto file : files) {
file_list.append(file.trimmed());
}
} catch (FS::FileSystemException) {
} catch (FS::FileSystemException&) {
}
}
@ -675,15 +675,23 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target)
if (error) {
logUpdate(tr("There were errors installing the update."));
auto fail_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.fail");
FS::move(m_updateLogPath, fail_marker);
FS::copy(m_updateLogPath, fail_marker)();
} else {
logUpdate(tr("Update succeed."));
auto success_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.success");
FS::move(m_updateLogPath, success_marker);
FS::copy(m_updateLogPath, success_marker)();
}
auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock");
FS::deletePath(update_lock_path);
QProcess proc;
auto app_exe_name = BuildConfig.LAUNCHER_APP_BINARY_NAME;
#if defined Q_OS_WIN32
app_exe_name.append(".exe");
#endif
auto app_exe_path = target.absoluteFilePath(app_exe_name);
proc.startDetached(app_exe_path);
exit(error ? 1 : 0);
}
@ -897,7 +905,7 @@ bool write_lock_file(const QString& path, QDateTime timestamp, QString from, QSt
.arg(target)
.arg(data_path)
.toUtf8());
} catch (FS::FileSystemException err) {
} catch (FS::FileSystemException& err) {
qWarning() << "Error writing lockfile:" << err.what() << "\n" << err.cause();
return false;
}
@ -922,7 +930,7 @@ void PrismUpdaterApp::performInstall(QFileInfo file)
"\n"
"This likely means that a previous update attempt failed. Please ensure your installation is in working order before "
"proceeding.\n"
"Check the Prism Launcher updater log at \n"
"Check the Prism Launcher updater log at: \n"
"%7\n"
"for details on the last update attempt.\n"
"\n"
@ -936,9 +944,9 @@ void PrismUpdaterApp::performInstall(QFileInfo file)
msgBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
switch (msgBox.exec()) {
case QMessageBox::Ignore:
case QMessageBox::AcceptRole:
break;
case QMessageBox::Cancel:
case QMessageBox::RejectRole:
[[fallthrough]];
default:
return showFatalErrorMessage(tr("Update Aborted"), tr("The update attempt was aborted"));
@ -1005,7 +1013,7 @@ void PrismUpdaterApp::backupAppDir()
for (auto file : files) {
file_list.append(file.trimmed());
}
} catch (FS::FileSystemException) {
} catch (FS::FileSystemException&) {
}
}