diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index dbbe9e85d..62f6f3f34 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1065,6 +1065,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/ImportResourceDialog.h ui/dialogs/MSALoginDialog.cpp ui/dialogs/MSALoginDialog.h + ui/dialogs/NetworkJobFailedDialog.cpp + ui/dialogs/NetworkJobFailedDialog.h ui/dialogs/NewComponentDialog.cpp ui/dialogs/NewComponentDialog.h ui/dialogs/NewInstanceDialog.cpp @@ -1247,6 +1249,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ProfileSetupDialog.ui ui/dialogs/ProgressDialog.ui ui/dialogs/NewInstanceDialog.ui + ui/dialogs/NetworkJobFailedDialog.ui ui/dialogs/NewComponentDialog.ui ui/dialogs/NewsDialog.ui ui/dialogs/ProfileSelectDialog.ui diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index a40219962..05bbdfa23 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -42,7 +42,7 @@ #if defined(LAUNCHER_APPLICATION) #include "Application.h" #include "settings/SettingsObject.h" -#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/NetworkJobFailedDialog.h" #endif NetJob::NetJob(QString job_name, QNetworkAccessManager* network, int max_concurrent) : ConcurrentTask(job_name), m_network(network) @@ -164,23 +164,23 @@ void NetJob::emitFailed(QString reason) if (APPLICATION_DYN && m_ask_retry && m_manual_try < APPLICATION->settings()->get("NumberOfManualRetries").toInt() && isOnline()) { m_manual_try++; - auto response = CustomMessageBox::selectable(nullptr, "Confirm retry", - "The tasks failed.\n" - "Failed urls\n" + - getFailedFiles().join("\n\t") + - ".\n" - "If this continues to happen please check the logs of the application.\n" - "Do you want to retry?", - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) - ->exec(); + auto failed = getFailedActions(); + auto dialog = NetworkJobFailedDialog(objectName(), m_try, m_done.size(), failed.size(), nullptr); - if (response == QMessageBox::Yes) { + int i = 0; + for (const auto& request : failed) { + dialog.addFailedRequest(i, request->url(), request->errorString()); + ++i; + } + + if (dialog.exec() == QDialog::Accepted) { m_try = 0; executeNextSubTask(); return; } } #endif + ConcurrentTask::emitFailed(reason); } diff --git a/launcher/ui/dialogs/NetworkJobFailedDialog.cpp b/launcher/ui/dialogs/NetworkJobFailedDialog.cpp new file mode 100644 index 000000000..314c984d3 --- /dev/null +++ b/launcher/ui/dialogs/NetworkJobFailedDialog.cpp @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2025 Octol1ttle + * + * 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 . + */ + +#include "NetworkJobFailedDialog.h" + +#include "ui_NetworkJobFailedDialog.h" + +NetworkJobFailedDialog::NetworkJobFailedDialog(QString jobName, int attempts, int requests, int failed, QWidget* parent) : QDialog(parent), ui(new Ui::NetworkJobFailedDialog) +{ + ui->setupUi(this); + ui->failLabel->setText(ui->failLabel->text().arg(jobName)); + if (failed == requests) { + ui->requestCountLabel->setText(tr("All %1 requests have failed after %2 attempts").arg(failed).arg(attempts)); + } else if (failed < requests / 2) { + ui->requestCountLabel->setText(tr("Out of %1 requests, %2 have failed after %3 attempts").arg(requests).arg(failed).arg(attempts)); + } else { + ui->requestCountLabel->setText(tr("Out of %1 requests, only %2 succeeded after %3 attempts").arg(requests).arg(requests - failed).arg(attempts)); + } + ui->detailsTable->setRowCount(failed); + + setShowDetails(failed < 5); + + connect(ui->dialogButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(ui->dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); +} + +NetworkJobFailedDialog::~NetworkJobFailedDialog() +{ + delete ui; +} + +void NetworkJobFailedDialog::addFailedRequest(int row, QUrl url, QString error) const +{ + const auto urlItem = new QTableWidgetItem(url.toString()); + const auto errorItem = new QTableWidgetItem(error); + ui->detailsTable->setItem(row, 0, urlItem); + ui->detailsTable->setItem(row, 1, errorItem); +} + +void NetworkJobFailedDialog::setShowDetails(bool showDetails) +{ + m_showDetails = showDetails; + ui->detailsTable->setVisible(m_showDetails); + ui->detailsButton->setText(!m_showDetails ? tr("Show details") : tr("Hide details")); +} + +void NetworkJobFailedDialog::on_detailsButton_clicked() +{ + setShowDetails(!m_showDetails); +} diff --git a/launcher/ui/dialogs/NetworkJobFailedDialog.h b/launcher/ui/dialogs/NetworkJobFailedDialog.h new file mode 100644 index 000000000..e0bd01b00 --- /dev/null +++ b/launcher/ui/dialogs/NetworkJobFailedDialog.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2025 Octol1ttle + * + * 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 . + */ + +#pragma once + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { +class NetworkJobFailedDialog; +} +QT_END_NAMESPACE + +class NetworkJobFailedDialog : public QDialog { + Q_OBJECT + + public: + explicit NetworkJobFailedDialog(QString jobName, int attempts, int requests, int failed, QWidget* parent = nullptr); + ~NetworkJobFailedDialog() override; + + void addFailedRequest(int row, QUrl url, QString error) const; + + private: + void setShowDetails(bool showDetails); + + private slots: + void on_detailsButton_clicked(); + + private: + Ui::NetworkJobFailedDialog* ui; + + bool m_showDetails = false; +}; diff --git a/launcher/ui/dialogs/NetworkJobFailedDialog.ui b/launcher/ui/dialogs/NetworkJobFailedDialog.ui new file mode 100644 index 000000000..50deb5fb7 --- /dev/null +++ b/launcher/ui/dialogs/NetworkJobFailedDialog.ui @@ -0,0 +1,94 @@ + + + NetworkJobFailedDialog + + + + 0 + 0 + 450 + 350 + + + + Network error + + + + + + + + + + 0 + 0 + + + + A network operation has failed: %1 + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + PushButton + + + + + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + + URL + + + + + Error + + + + + + + + + 0 + 0 + + + + What would you like to do? + + + + + + + QDialogButtonBox::StandardButton::Abort|QDialogButtonBox::StandardButton::Retry + + + + + + + +