From 02b4468bcddcdab6c269282564a0968c6394a34f Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 19:52:47 -0300 Subject: [PATCH 01/30] feat(ui): add ManagedPackPage ui Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.ui | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 launcher/ui/pages/instance/ManagedPackPage.ui diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui new file mode 100644 index 00000000..3f019606 --- /dev/null +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -0,0 +1,173 @@ + + + ManagedPackPage + + + + 0 + 0 + 731 + 538 + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + + + 0 + 0 + + + + Pack information + + + + + + + + Pack name: + + + + + + + placeholder + + + + + + + + + + + Current version: + + + + + + + IBeamCursor + + + placeholder + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + + Provider information: + + + + + + + IBeamCursor + + + placeholder + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 0 + 0 + + + + Update to version: + + + + + + + + + + + 0 + 0 + + + + Update pack + + + + + + + + + + 0 + 0 + + + + Changelog + + + + + + + + + + + + + + + From e5c42f68c2429a924b22dbcfb0df5a497690b805 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 19:55:21 -0300 Subject: [PATCH 02/30] feat: add basic ManagedPackPage classes The idea is to have a base class that defines common behavior, and subclasses for each modpack provider, adding specific behavior. Signed-off-by: flow --- .../ui/pages/instance/ManagedPackPage.cpp | 129 ++++++++++++++++++ launcher/ui/pages/instance/ManagedPackPage.h | 98 +++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 launcher/ui/pages/instance/ManagedPackPage.cpp create mode 100644 launcher/ui/pages/instance/ManagedPackPage.h diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp new file mode 100644 index 00000000..725f8ce5 --- /dev/null +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -0,0 +1,129 @@ +#include "ManagedPackPage.h" +#include "ui_ManagedPackPage.h" + +#include +#include + +#include "Application.h" + +/** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen. + * ... thanks Qt. + */ +class NoBigComboBoxStyle : public QProxyStyle { + Q_OBJECT + + public: + NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {} + + // clang-format off + int styleHint(QStyle::StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override + { + if (hint == QStyle::SH_ComboBox_Popup) + return false; + + return QProxyStyle::styleHint(hint, option, widget, returnData); + } + // clang-format on +}; + +ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent) +{ + if (type == "modrinth") + return new ModrinthManagedPackPage(inst, parent); + if (type == "flame") + return new FlameManagedPackPage(inst, parent); + + return new GenericManagedPackPage(inst, parent); +} + +ManagedPackPage::ManagedPackPage(BaseInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::ManagedPackPage), m_inst(inst) +{ + Q_ASSERT(inst); + + ui->setupUi(this); + + ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style())); +} + +ManagedPackPage::~ManagedPackPage() +{ + delete ui; +} + +void ManagedPackPage::openedImpl() +{ + ui->packName->setText(m_inst->getManagedPackName()); + ui->packVersion->setText(m_inst->getManagedPackVersionName()); + ui->packOrigin->setText(tr("Website: %1 | Pack ID: %2 | Version ID: %3") + .arg(displayName(), m_inst->getManagedPackID(), m_inst->getManagedPackVersionID())); + + parseManagedPack(); +} + +QString ManagedPackPage::displayName() const +{ + auto type = m_inst->getManagedPackType(); + if (type.isEmpty()) + return {}; + return type.replace(0, 1, type[0].toUpper()); +} + +QIcon ManagedPackPage::icon() const +{ + return APPLICATION->getThemedIcon(m_inst->getManagedPackType()); +} + +QString ManagedPackPage::helpPage() const +{ + return {}; +} + +void ManagedPackPage::retranslate() +{ + ui->retranslateUi(this); +} + +bool ManagedPackPage::shouldDisplay() const +{ + return m_inst->isManagedPack(); +} + +ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, QWidget* parent) : ManagedPackPage(inst, parent) +{ + Q_ASSERT(inst->isManagedPack()); + connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); +} + +void ModrinthManagedPackPage::parseManagedPack() +{ +} + +QString ModrinthManagedPackPage::url() const +{ + return {}; +} + +void ModrinthManagedPackPage::suggestVersion() +{ +} + +FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, QWidget* parent) : ManagedPackPage(inst, parent) +{ + Q_ASSERT(inst->isManagedPack()); + connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); +} + +void FlameManagedPackPage::parseManagedPack() +{ +} + +QString FlameManagedPackPage::url() const +{ + return {}; +} + +void FlameManagedPackPage::suggestVersion() +{ +} + +#include "ManagedPackPage.moc" diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h new file mode 100644 index 00000000..be49383c --- /dev/null +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -0,0 +1,98 @@ +#pragma once + +#include "BaseInstance.h" + +#include "modplatform/modrinth/ModrinthAPI.h" +#include "modplatform/modrinth/ModrinthPackManifest.h" + +#include "ui/pages/BasePage.h" + +#include + +namespace Ui { +class ManagedPackPage; +} + +class ManagedPackPage : public QWidget, public BasePage { + Q_OBJECT + + public: + inline static ManagedPackPage* createPage(BaseInstance* inst, QWidget* parent = nullptr) + { + return ManagedPackPage::createPage(inst, inst->getManagedPackType(), parent); + } + + static ManagedPackPage* createPage(BaseInstance* inst, QString type, QWidget* parent = nullptr); + ~ManagedPackPage() override; + + [[nodiscard]] QString displayName() const override; + [[nodiscard]] QIcon icon() const override; + [[nodiscard]] QString helpPage() const override; + [[nodiscard]] QString id() const override { return "managed_pack"; } + [[nodiscard]] bool shouldDisplay() const override; + + void openedImpl() override; + + bool apply() override { return true; } + void retranslate() override; + + /** Gets the necessary information about the managed pack, such as + * available versions*/ + virtual void parseManagedPack() {}; + + /** URL of the managed pack. + * Not the version-specific one. + */ + [[nodiscard]] virtual QString url() const { return {}; }; + + public slots: + /** Gets the current version selection and update the changelog. + */ + virtual void suggestVersion() {}; + + protected: + ManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr); + + protected: + Ui::ManagedPackPage* ui; + BaseInstance* m_inst; + + bool m_loaded = false; +}; + +/** Simple page for when we aren't a managed pack. */ +class GenericManagedPackPage final : public ManagedPackPage { + Q_OBJECT + + public: + GenericManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr) : ManagedPackPage(inst, parent) {} + ~GenericManagedPackPage() override = default; +}; + +class ModrinthManagedPackPage final : public ManagedPackPage { + Q_OBJECT + + public: + ModrinthManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr); + ~ModrinthManagedPackPage() override = default; + + void parseManagedPack() override; + [[nodiscard]] QString url() const override; + + public slots: + void suggestVersion() override; +}; + +class FlameManagedPackPage final : public ManagedPackPage { + Q_OBJECT + + public: + FlameManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr); + ~FlameManagedPackPage() override = default; + + void parseManagedPack() override; + [[nodiscard]] QString url() const override; + + public slots: + void suggestVersion() override; +}; From cba2608c1c196c341275b32becc4a7c713e92bbf Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 19:57:23 -0300 Subject: [PATCH 03/30] feat: add logic for the modrinth instance modpack page Signed-off-by: flow --- .../modrinth/ModrinthPackManifest.cpp | 1 + .../modrinth/ModrinthPackManifest.h | 1 + .../ui/pages/instance/ManagedPackPage.cpp | 50 +++++++++++++++++++ launcher/ui/pages/instance/ManagedPackPage.h | 4 ++ 4 files changed, 56 insertions(+) diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index 96f54067..4dca786f 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -128,6 +128,7 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion file.name = Json::requireString(obj, "name"); file.version = Json::requireString(obj, "version_number"); + file.changelog = Json::ensureString(obj, "changelog"); file.id = Json::requireString(obj, "id"); file.project_id = Json::requireString(obj, "project_id"); diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h index 035dc62e..2973dfba 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.h +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.h @@ -80,6 +80,7 @@ struct ModpackExtra { struct ModpackVersion { QString name; QString version; + QString changelog; QString id; QString project_id; diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 725f8ce5..ead33136 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -5,6 +5,10 @@ #include #include "Application.h" +#include "BuildConfig.h" +#include "Json.h" + +#include "modplatform/modrinth/ModrinthPackManifest.h" /** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen. * ... thanks Qt. @@ -96,6 +100,48 @@ ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, QWidget* pa void ModrinthManagedPackPage::parseManagedPack() { + qDebug() << "Parsing Modrinth pack"; + + auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()); + auto response = new QByteArray(); + + QString id = m_inst->getManagedPackID(); + + netJob->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + + QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + + try { + Modrinth::loadIndexedVersions(m_pack, doc); + } catch (const JSONValidationError& e) { + qDebug() << *response; + qWarning() << "Error while reading modrinth modpack version: " << e.cause(); + } + + for (auto version : m_pack.versions) { + if (!version.name.contains(version.version)) + ui->versionsComboBox->addItem(QString("%1 — %2").arg(version.name, version.version), QVariant(version.id)); + else + ui->versionsComboBox->addItem(version.name, QVariant(version.id)); + } + + suggestVersion(); + + m_loaded = true; + }); + QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { + netJob->deleteLater(); + delete response; + }); + netJob->start(); } QString ModrinthManagedPackPage::url() const @@ -105,6 +151,10 @@ QString ModrinthManagedPackPage::url() const void ModrinthManagedPackPage::suggestVersion() { + auto index = ui->versionsComboBox->currentIndex(); + auto version = m_pack.versions.at(index); + + ui->changelogTextBrowser->setText(version.changelog); } FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, QWidget* parent) : ManagedPackPage(inst, parent) diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index be49383c..1a756d33 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -81,6 +81,10 @@ class ModrinthManagedPackPage final : public ManagedPackPage { public slots: void suggestVersion() override; + + private: + Modrinth::Modpack m_pack; + ModrinthAPI m_api; }; class FlameManagedPackPage final : public ManagedPackPage { From 1c567232e3a241cb7be767756c88350ec62335a1 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 20:32:40 -0300 Subject: [PATCH 04/30] feat: add (current) indicator to the currently installed version in MR Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index ead33136..7c51cf38 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -127,10 +127,19 @@ void ModrinthManagedPackPage::parseManagedPack() } for (auto version : m_pack.versions) { + QString name; + if (!version.name.contains(version.version)) - ui->versionsComboBox->addItem(QString("%1 — %2").arg(version.name, version.version), QVariant(version.id)); + name = QString("%1 — %2").arg(version.name, version.version); else - ui->versionsComboBox->addItem(version.name, QVariant(version.id)); + name = version.name; + + // NOTE: the id from version isn't the same id in the modpack format spec... + // e.g. HexMC's 4.4.0 has versionId 4.0.0 in the modpack index.............. + if (version.version == m_inst->getManagedPackVersionName()) + name.append(tr(" (Current)")); + + ui->versionsComboBox->addItem(name, QVariant(version.id)); } suggestVersion(); From 9e17ff884f84601bd6e48721b32c2af51ca8ee7d Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 14 Oct 2022 14:09:41 -0300 Subject: [PATCH 05/30] feat: add PageContainer::getPage This allows us to directly access a page from outside. This will be useful for telling the ManagedPackPage who is the window it's on, so that we can close it when updating :^) Signed-off-by: flow --- launcher/ui/pages/BasePageContainer.h | 3 +++ launcher/ui/widgets/PageContainer.cpp | 5 +++++ launcher/ui/widgets/PageContainer.h | 1 + 3 files changed, 9 insertions(+) diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h index f8c7adeb..b41fe12a 100644 --- a/launcher/ui/pages/BasePageContainer.h +++ b/launcher/ui/pages/BasePageContainer.h @@ -1,10 +1,13 @@ #pragma once +class BasePage; + class BasePageContainer { public: virtual ~BasePageContainer(){}; virtual bool selectPage(QString pageId) = 0; + virtual BasePage* getPage(QString pageId) { return nullptr; }; virtual void refreshContainer() = 0; virtual bool requestClose() = 0; }; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 8d606820..0a06a351 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -130,6 +130,11 @@ bool PageContainer::selectPage(QString pageId) return false; } +BasePage* PageContainer::getPage(QString pageId) +{ + return m_model->findPageEntryById(pageId); +} + void PageContainer::refreshContainer() { m_proxyModel->invalidate(); diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 80d87a9b..97e294dc 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -79,6 +79,7 @@ public: } virtual bool selectPage(QString pageId) override; + BasePage* getPage(QString pageId) override; void refreshContainer() override; virtual void setParentContainer(BasePageContainer * container) From 08d008a5aa7379efe76201250b2511b66665d9a7 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 14 Oct 2022 14:22:13 -0300 Subject: [PATCH 06/30] refactor: abstract away update confirmation dialog ... so that we can avoid code duplication. Signed-off-by: flow --- launcher/InstanceTask.cpp | 23 +++++++++++++++++++ launcher/InstanceTask.h | 2 ++ .../flame/FlameInstanceCreationTask.cpp | 19 +++------------ .../modrinth/ModrinthInstanceCreationTask.cpp | 19 +++------------ 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp index 55a44fd3..06682782 100644 --- a/launcher/InstanceTask.cpp +++ b/launcher/InstanceTask.cpp @@ -18,6 +18,29 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol return InstanceNameChange::ShouldKeep; } +ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name) +{ + auto info = CustomMessageBox::selectable( + parent, QObject::tr("Similar modpack was found!"), + QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a " + "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " + "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") + .arg(original_version_name), + QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort); + info->setButtonText(QMessageBox::Ok, QObject::tr("Update existing instance")); + info->setButtonText(QMessageBox::Abort, QObject::tr("Create new instance")); + info->setButtonText(QMessageBox::Reset, QObject::tr("Cancel")); + + info->exec(); + + if (info->clickedButton() == info->button(QMessageBox::Ok)) + return ShouldUpdate::Update; + if (info->clickedButton() == info->button(QMessageBox::Abort)) + return ShouldUpdate::SkipUpdating; + return ShouldUpdate::Cancel; + +} + QString InstanceName::name() const { if (!m_modified_name.isEmpty()) diff --git a/launcher/InstanceTask.h b/launcher/InstanceTask.h index e35533fc..178fbc45 100644 --- a/launcher/InstanceTask.h +++ b/launcher/InstanceTask.h @@ -6,6 +6,8 @@ /* Helpers */ enum class InstanceNameChange { ShouldChange, ShouldKeep }; [[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name); +enum class ShouldUpdate { Update, SkipUpdating, Cancel }; +[[nodiscard]] ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name); struct InstanceName { public: diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index f9258f24..d8356c75 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -102,23 +102,10 @@ bool FlameCreationTask::updateInstance() auto version_id = inst->getManagedPackVersionName(); auto version_str = !version_id.isEmpty() ? tr(" (version %1)").arg(version_id) : ""; - auto info = CustomMessageBox::selectable( - m_parent, tr("Similar modpack was found!"), - tr("One or more of your instances are from this same modpack%1. Do you want to create a " - "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " - "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") - .arg(version_str), - QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort); - info->setButtonText(QMessageBox::Ok, tr("Update existing instance")); - info->setButtonText(QMessageBox::Abort, tr("Create new instance")); - info->setButtonText(QMessageBox::Reset, tr("Cancel")); - - info->exec(); - - if (info->clickedButton() == info->button(QMessageBox::Abort)) + auto should_update = askIfShouldUpdate(m_parent, version_str); + if (should_update == ShouldUpdate::SkipUpdating) return false; - - if (info->clickedButton() == info->button(QMessageBox::Reset)) { + if (should_update == ShouldUpdate::Cancel) { m_abort = true; return false; } diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index ddeea224..762feef6 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -49,23 +49,10 @@ bool ModrinthCreationTask::updateInstance() auto version_name = inst->getManagedPackVersionName(); auto version_str = !version_name.isEmpty() ? tr(" (version %1)").arg(version_name) : ""; - auto info = CustomMessageBox::selectable( - m_parent, tr("Similar modpack was found!"), - tr("One or more of your instances are from this same modpack%1. Do you want to create a " - "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " - "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") - .arg(version_str), - QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort); - info->setButtonText(QMessageBox::Ok, tr("Create new instance")); - info->setButtonText(QMessageBox::Abort, tr("Update existing instance")); - info->setButtonText(QMessageBox::Reset, tr("Cancel")); - - info->exec(); - - if (info->clickedButton() == info->button(QMessageBox::Ok)) + auto should_update = askIfShouldUpdate(m_parent, version_str); + if (should_update == ShouldUpdate::SkipUpdating) return false; - - if (info->clickedButton() == info->button(QMessageBox::Reset)) { + if (should_update == ShouldUpdate::Cancel) { m_abort = true; return false; } From 82699cc297de64fe6e39404dae29ad812766aba0 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 14 Oct 2022 14:23:55 -0300 Subject: [PATCH 07/30] feat: allow skipping the update confirmation dialog Signed-off-by: flow --- launcher/InstanceTask.h | 4 ++++ .../flame/FlameInstanceCreationTask.cpp | 14 ++++++++------ .../modrinth/ModrinthInstanceCreationTask.cpp | 14 ++++++++------ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/launcher/InstanceTask.h b/launcher/InstanceTask.h index 178fbc45..e481354c 100644 --- a/launcher/InstanceTask.h +++ b/launcher/InstanceTask.h @@ -44,6 +44,9 @@ class InstanceTask : public Task, public InstanceName { void setGroup(const QString& group) { m_instGroup = group; } QString group() const { return m_instGroup; } + [[nodiscard]] bool shouldConfirmUpdate() const { return m_confirm_update; } + void setConfirmUpdate(bool confirm) { m_confirm_update = confirm; } + bool shouldOverride() const { return m_override_existing; } protected: @@ -56,4 +59,5 @@ class InstanceTask : public Task, public InstanceName { QString m_stagingPath; bool m_override_existing = false; + bool m_confirm_update = true; }; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index d8356c75..d466f029 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -102,12 +102,14 @@ bool FlameCreationTask::updateInstance() auto version_id = inst->getManagedPackVersionName(); auto version_str = !version_id.isEmpty() ? tr(" (version %1)").arg(version_id) : ""; - auto should_update = askIfShouldUpdate(m_parent, version_str); - if (should_update == ShouldUpdate::SkipUpdating) - return false; - if (should_update == ShouldUpdate::Cancel) { - m_abort = true; - return false; + if (shouldConfirmUpdate()) { + auto should_update = askIfShouldUpdate(m_parent, version_str); + if (should_update == ShouldUpdate::SkipUpdating) + return false; + if (should_update == ShouldUpdate::Cancel) { + m_abort = true; + return false; + } } QDir old_inst_dir(inst->instanceRoot()); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 762feef6..5eb28a85 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -49,12 +49,14 @@ bool ModrinthCreationTask::updateInstance() auto version_name = inst->getManagedPackVersionName(); auto version_str = !version_name.isEmpty() ? tr(" (version %1)").arg(version_name) : ""; - auto should_update = askIfShouldUpdate(m_parent, version_str); - if (should_update == ShouldUpdate::SkipUpdating) - return false; - if (should_update == ShouldUpdate::Cancel) { - m_abort = true; - return false; + if (shouldConfirmUpdate()) { + auto should_update = askIfShouldUpdate(m_parent, version_str); + if (should_update == ShouldUpdate::SkipUpdating) + return false; + if (should_update == ShouldUpdate::Cancel) { + m_abort = true; + return false; + } } // Remove repeated files, we don't need to download them! From 58d2c15ffa4a966b40ba2f741c90e1d32fdbe106 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 14 Oct 2022 14:36:48 -0300 Subject: [PATCH 08/30] feat: add functionality to MR modpack update in the page :D Signed-off-by: flow --- launcher/InstanceImportTask.cpp | 2 + launcher/ui/InstanceWindow.cpp | 6 ++ .../ui/pages/instance/ManagedPackPage.cpp | 73 ++++++++++++++++--- launcher/ui/pages/instance/ManagedPackPage.h | 28 +++++-- 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 5f459649..f5ef250e 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -264,6 +264,7 @@ void InstanceImportTask::processFlame() inst_creation_task->setName(*this); inst_creation_task->setIcon(m_instIcon); inst_creation_task->setGroup(m_instGroup); + inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { setOverride(inst_creation_task->shouldOverride()); @@ -328,6 +329,7 @@ void InstanceImportTask::processModrinth() inst_creation_task->setName(*this); inst_creation_task->setIcon(m_instIcon); inst_creation_task->setGroup(m_instGroup); + inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { setOverride(inst_creation_task->shouldOverride()); diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index 09ce0d67..c62b370f 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -132,6 +132,12 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) { connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged); } + + // add ourself as the modpack page's instance window + { + static_cast(m_container->getPage("managed_pack"))->setInstanceWindow(this); + } + show(); } diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 7c51cf38..348dd857 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -6,10 +6,17 @@ #include "Application.h" #include "BuildConfig.h" +#include "InstanceImportTask.h" +#include "InstanceList.h" +#include "InstanceTask.h" #include "Json.h" #include "modplatform/modrinth/ModrinthPackManifest.h" +#include "ui/InstanceWindow.h" +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" + /** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen. * ... thanks Qt. */ @@ -33,14 +40,15 @@ class NoBigComboBoxStyle : public QProxyStyle { ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent) { if (type == "modrinth") - return new ModrinthManagedPackPage(inst, parent); + return new ModrinthManagedPackPage(inst, nullptr, parent); if (type == "flame") - return new FlameManagedPackPage(inst, parent); + return new FlameManagedPackPage(inst, nullptr, parent); - return new GenericManagedPackPage(inst, parent); + return new GenericManagedPackPage(inst, nullptr, parent); } -ManagedPackPage::ManagedPackPage(BaseInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::ManagedPackPage), m_inst(inst) +ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) + : QWidget(parent), m_instance_window(instance_window), ui(new Ui::ManagedPackPage), m_inst(inst) { Q_ASSERT(inst); @@ -92,10 +100,37 @@ bool ManagedPackPage::shouldDisplay() const return m_inst->isManagedPack(); } -ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, QWidget* parent) : ManagedPackPage(inst, parent) +bool ManagedPackPage::runUpdateTask(InstanceTask* task) +{ + Q_ASSERT(task); + + unique_qobject_ptr wrapped_task(APPLICATION->instances()->wrapInstanceTask(task)); + + connect(task, &Task::failed, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + connect(task, &Task::succeeded, [this, task]() { + QStringList warnings = task->warnings(); + if (warnings.count()) + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); + }); + connect(task, &Task::aborted, [this] { + CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) + ->show(); + }); + + ProgressDialog loadDialog(this); + loadDialog.setSkipButton(true, tr("Abort")); + loadDialog.execWithTask(task); + + return task->wasSuccessful(); +} + +ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) + : ManagedPackPage(inst, instance_window, parent) { Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); + connect(ui->updateButton, &QPushButton::pressed, this, &ModrinthManagedPackPage::update); } void ModrinthManagedPackPage::parseManagedPack() @@ -166,15 +201,35 @@ void ModrinthManagedPackPage::suggestVersion() ui->changelogTextBrowser->setText(version.changelog); } -FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, QWidget* parent) : ManagedPackPage(inst, parent) +void ModrinthManagedPackPage::update() +{ + auto index = ui->versionsComboBox->currentIndex(); + auto version = m_pack.versions.at(index); + + auto extracted = new InstanceImportTask(version.download_url, this); + + InstanceName inst_name(m_inst->getManagedPackName(), version.version); + inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); + extracted->setName(inst_name); + + extracted->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id())); + extracted->setIcon(m_inst->iconKey()); + extracted->setConfirmUpdate(false); + + auto did_succeed = runUpdateTask(extracted); + + if (m_instance_window && did_succeed) + m_instance_window->close(); +} + +FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) + : ManagedPackPage(inst, instance_window, parent) { Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); } -void FlameManagedPackPage::parseManagedPack() -{ -} +void FlameManagedPackPage::parseManagedPack() {} QString FlameManagedPackPage::url() const { diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 1a756d33..dc6ae118 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -13,6 +13,9 @@ namespace Ui { class ManagedPackPage; } +class InstanceTask; +class InstanceWindow; + class ManagedPackPage : public QWidget, public BasePage { Q_OBJECT @@ -45,15 +48,28 @@ class ManagedPackPage : public QWidget, public BasePage { */ [[nodiscard]] virtual QString url() const { return {}; }; + void setInstanceWindow(InstanceWindow* window) { m_instance_window = window; } + public slots: /** Gets the current version selection and update the changelog. */ virtual void suggestVersion() {}; - protected: - ManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr); + virtual void update() {}; protected: + ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr); + + /** Run the InstanceTask, with a progress dialog and all. + * Similar to MainWindow::instanceFromInstanceTask + * + * Returns whether the task was successful. + */ + bool runUpdateTask(InstanceTask*); + + protected: + InstanceWindow* m_instance_window = nullptr; + Ui::ManagedPackPage* ui; BaseInstance* m_inst; @@ -65,7 +81,7 @@ class GenericManagedPackPage final : public ManagedPackPage { Q_OBJECT public: - GenericManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr) : ManagedPackPage(inst, parent) {} + GenericManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr) : ManagedPackPage(inst, instance_window, parent) {} ~GenericManagedPackPage() override = default; }; @@ -73,7 +89,7 @@ class ModrinthManagedPackPage final : public ManagedPackPage { Q_OBJECT public: - ModrinthManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr); + ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr); ~ModrinthManagedPackPage() override = default; void parseManagedPack() override; @@ -82,6 +98,8 @@ class ModrinthManagedPackPage final : public ManagedPackPage { public slots: void suggestVersion() override; + void update() override; + private: Modrinth::Modpack m_pack; ModrinthAPI m_api; @@ -91,7 +109,7 @@ class FlameManagedPackPage final : public ManagedPackPage { Q_OBJECT public: - FlameManagedPackPage(BaseInstance* inst, QWidget* parent = nullptr); + FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr); ~FlameManagedPackPage() override = default; void parseManagedPack() override; From 0ff8891c6669ffe851afd98edab226a9173a6633 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 14 Oct 2022 14:38:42 -0300 Subject: [PATCH 09/30] feat: add ManagedPackPage to the instance pages Signed-off-by: flow --- launcher/CMakeLists.txt | 3 +++ launcher/InstancePageProvider.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 3eb765dc..245b6995 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -680,6 +680,8 @@ SET(LAUNCHER_SOURCES ui/pages/instance/GameOptionsPage.h ui/pages/instance/VersionPage.cpp ui/pages/instance/VersionPage.h + ui/pages/instance/ManagedPackPage.cpp + ui/pages/instance/ManagedPackPage.h ui/pages/instance/TexturePackPage.h ui/pages/instance/ResourcePackPage.h ui/pages/instance/ShaderPackPage.h @@ -919,6 +921,7 @@ qt_wrap_ui(LAUNCHER_UI ui/pages/instance/OtherLogsPage.ui ui/pages/instance/InstanceSettingsPage.ui ui/pages/instance/VersionPage.ui + ui/pages/instance/ManagedPackPage.ui ui/pages/instance/WorldListPage.ui ui/pages/instance/ScreenshotsPage.ui ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h index bf29377d..5d8beca9 100644 --- a/launcher/InstancePageProvider.h +++ b/launcher/InstancePageProvider.h @@ -5,6 +5,7 @@ #include "ui/pages/BasePageProvider.h" #include "ui/pages/instance/LogPage.h" #include "ui/pages/instance/VersionPage.h" +#include "ui/pages/instance/ManagedPackPage.h" #include "ui/pages/instance/ModFolderPage.h" #include "ui/pages/instance/ResourcePackPage.h" #include "ui/pages/instance/TexturePackPage.h" @@ -33,6 +34,7 @@ public: values.append(new LogPage(inst)); std::shared_ptr onesix = std::dynamic_pointer_cast(inst); values.append(new VersionPage(onesix.get())); + values.append(ManagedPackPage::createPage(onesix.get())); auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList()); modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); values.append(modsPage); From 25cfa26e7b24242dec3b775d9b0c09c84f870a39 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 22 Oct 2022 16:02:10 -0300 Subject: [PATCH 10/30] fix: use rich text in changelog for modrinth modpacks Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 348dd857..6d051760 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "Application.h" #include "BuildConfig.h" #include "InstanceImportTask.h" @@ -198,7 +200,8 @@ void ModrinthManagedPackPage::suggestVersion() auto index = ui->versionsComboBox->currentIndex(); auto version = m_pack.versions.at(index); - ui->changelogTextBrowser->setText(version.changelog); + HoeDown md_parser; + ui->changelogTextBrowser->setHtml(md_parser.process(version.changelog.toUtf8())); } void ModrinthManagedPackPage::update() From 95392309150079d73f4ee83ea7bdba98ef9caa2f Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 11 Nov 2022 16:58:37 -0300 Subject: [PATCH 11/30] fix: do not display managed pack page for providers without an impl. yet Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index dc6ae118..7ad13533 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -83,6 +83,9 @@ class GenericManagedPackPage final : public ManagedPackPage { public: GenericManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr) : ManagedPackPage(inst, instance_window, parent) {} ~GenericManagedPackPage() override = default; + + // TODO: We may want to show this page with some useful info at some point. + [[nodiscard]] bool shouldDisplay() const override { return false; }; }; class ModrinthManagedPackPage final : public ManagedPackPage { From d4979974b4f65d6662557e0415085c90f1ad5a11 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 11 Nov 2022 17:44:16 -0300 Subject: [PATCH 12/30] fix(ManagedPackPage): better UX for when network requests fail / are pending Signed-off-by: flow --- .../ui/pages/instance/ManagedPackPage.cpp | 34 +++++++++++++++++++ launcher/ui/pages/instance/ManagedPackPage.h | 14 ++++++-- launcher/ui/pages/instance/ManagedPackPage.ui | 5 ++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 6d051760..be0b2f86 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -127,6 +127,30 @@ bool ManagedPackPage::runUpdateTask(InstanceTask* task) return task->wasSuccessful(); } +void ManagedPackPage::suggestVersion() +{ + ui->updateButton->setText(tr("Update pack")); + ui->updateButton->setDisabled(false); +} + +void ManagedPackPage::setFailState() +{ + qDebug() << "Setting fail state!"; + + // We block signals here so that suggestVersion() doesn't get called, causing an assertion fail. + ui->versionsComboBox->blockSignals(true); + ui->versionsComboBox->clear(); + ui->versionsComboBox->addItem(tr("Failed to search for available versions."), {}); + ui->versionsComboBox->blockSignals(false); + + ui->changelogTextBrowser->setText(tr("Failed to request changelog data for this modpack.")); + + ui->updateButton->setText(tr("Cannot update!")); + ui->updateButton->setDisabled(true); + + // TODO: Perhaps start a timer here when m_loaded is false to try and reload. +} + ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) : ManagedPackPage(inst, instance_window, parent) { @@ -153,6 +177,9 @@ void ModrinthManagedPackPage::parseManagedPack() qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; + + setFailState(); + return; } @@ -161,6 +188,9 @@ void ModrinthManagedPackPage::parseManagedPack() } catch (const JSONValidationError& e) { qDebug() << *response; qWarning() << "Error while reading modrinth modpack version: " << e.cause(); + + setFailState(); + return; } for (auto version : m_pack.versions) { @@ -183,6 +213,8 @@ void ModrinthManagedPackPage::parseManagedPack() m_loaded = true; }); + QObject::connect(netJob, &NetJob::failed, this, &ModrinthManagedPackPage::setFailState); + QObject::connect(netJob, &NetJob::aborted, this, &ModrinthManagedPackPage::setFailState); QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); delete response; @@ -202,6 +234,8 @@ void ModrinthManagedPackPage::suggestVersion() HoeDown md_parser; ui->changelogTextBrowser->setHtml(md_parser.process(version.changelog.toUtf8())); + + ManagedPackPage::suggestVersion(); } void ModrinthManagedPackPage::update() diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 7ad13533..a81d24f0 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -51,12 +51,22 @@ class ManagedPackPage : public QWidget, public BasePage { void setInstanceWindow(InstanceWindow* window) { m_instance_window = window; } public slots: - /** Gets the current version selection and update the changelog. + /** Gets the current version selection and update the UI, including the update button and the changelog. */ - virtual void suggestVersion() {}; + virtual void suggestVersion(); virtual void update() {}; + protected slots: + /** Does the necessary UI changes for when something failed. + * + * This includes: + * - Setting an appropriate text on the version selector to indicate a fail; + * - Setting an appropriate text on the changelog text browser to indicate a fail; + * - Disable the update button. + */ + void setFailState(); + protected: ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr); diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index 3f019606..14009b13 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -133,6 +133,9 @@ + + false + 0 @@ -140,7 +143,7 @@ - Update pack + Fetching versions... From 7f5dea28bb2d9cd6ee90c4e5498dce0b57c0cce0 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 11 Nov 2022 18:29:32 -0300 Subject: [PATCH 13/30] feat(ManagedPackPage): add link to the Modrinth's pack page Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 6 +++--- launcher/ui/pages/instance/ManagedPackPage.ui | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index be0b2f86..126757d5 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -68,8 +68,8 @@ void ManagedPackPage::openedImpl() { ui->packName->setText(m_inst->getManagedPackName()); ui->packVersion->setText(m_inst->getManagedPackVersionName()); - ui->packOrigin->setText(tr("Website: %1 | Pack ID: %2 | Version ID: %3") - .arg(displayName(), m_inst->getManagedPackID(), m_inst->getManagedPackVersionID())); + ui->packOrigin->setText(tr("Website: %2 | Pack ID: %3 | Version ID: %4") + .arg(url(), displayName(), m_inst->getManagedPackID(), m_inst->getManagedPackVersionID())); parseManagedPack(); } @@ -224,7 +224,7 @@ void ModrinthManagedPackPage::parseManagedPack() QString ModrinthManagedPackPage::url() const { - return {}; + return "https://modrinth.com/mod/" + m_inst->getManagedPackID(); } void ModrinthManagedPackPage::suggestVersion() diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index 14009b13..6d8911e0 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -96,6 +96,12 @@ placeholder + + Qt::RichText + + + true + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse From 968366c2aecb3337af281a01de56023ce5ffe2f9 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 11:42:07 -0300 Subject: [PATCH 14/30] feat+fix: allow forwarding extra info to InstanceImportTask This allows us to pass to the creation instances their actual pack ID and version ID, that in Flame's case, are only available before starting to create an instance. Signed-off-by: flow --- launcher/InstanceImportTask.cpp | 29 ++++++++++++++----- launcher/InstanceImportTask.h | 6 +++- .../flame/FlameInstanceCreationTask.cpp | 2 +- .../flame/FlameInstanceCreationTask.h | 6 ++-- .../modrinth/ModrinthInstanceCreationTask.cpp | 15 ++-------- .../modrinth/ModrinthInstanceCreationTask.h | 6 ++-- .../ui/pages/modplatform/flame/FlamePage.cpp | 17 ++++++++--- .../ui/pages/modplatform/flame/FlamePage.h | 2 +- .../modplatform/modrinth/ModrinthPage.cpp | 6 +++- 9 files changed, 56 insertions(+), 33 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index f5ef250e..7c04ec47 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -55,11 +55,9 @@ #include -InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent) -{ - m_sourceUrl = sourceUrl; - m_parent = parent; -} +InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap extra_info) + : m_sourceUrl(sourceUrl), m_extra_info(std::move(extra_info)), m_parent(parent) +{} bool InstanceImportTask::abort() { @@ -259,7 +257,15 @@ void InstanceImportTask::extractAborted() void InstanceImportTask::processFlame() { - auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent); + auto pack_id_it = m_extra_info.constFind("pack_id"); + Q_ASSERT(pack_id_it != m_extra_info.constEnd()); + auto pack_id = pack_id_it.value(); + + auto pack_version_id_it = m_extra_info.constFind("pack_version_id"); + Q_ASSERT(pack_version_id_it != m_extra_info.constEnd()); + auto pack_version_id = pack_version_id_it.value(); + + auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id); inst_creation_task->setName(*this); inst_creation_task->setIcon(m_instIcon); @@ -324,7 +330,16 @@ void InstanceImportTask::processMultiMC() void InstanceImportTask::processModrinth() { - auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, m_sourceUrl.toString()); + auto pack_id_it = m_extra_info.constFind("pack_id"); + Q_ASSERT(pack_id_it != m_extra_info.constEnd()); + auto pack_id = pack_id_it.value(); + + QString pack_version_id; + auto pack_version_id_it = m_extra_info.constFind("pack_version_id"); + if (pack_version_id_it != m_extra_info.constEnd()) + pack_version_id = pack_version_id_it.value(); + + auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id); inst_creation_task->setName(*this); inst_creation_task->setIcon(m_instIcon); diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h index ef70c819..712ef054 100644 --- a/launcher/InstanceImportTask.h +++ b/launcher/InstanceImportTask.h @@ -56,7 +56,7 @@ class InstanceImportTask : public InstanceTask { Q_OBJECT public: - explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr); + explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap extra_info = {}); bool abort() override; const QVector &getBlockedFiles() const @@ -101,6 +101,10 @@ private: /* data */ Modrinth, } m_modpackType = ModpackType::Unknown; + // Extra info we might need, that's available before, but can't be derived from + // the source URL / the resource it points to alone. + QMap m_extra_info; + //FIXME: nuke QWidget* m_parent; }; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index d466f029..ad50597e 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -355,7 +355,7 @@ bool FlameCreationTask::createInstance() FS::deletePath(jarmodsPath); } - instance.setManagedPack("flame", {}, m_pack.name, {}, m_pack.version); + instance.setManagedPack("flame", m_managed_id, m_pack.name, m_managed_version_id, m_pack.version); instance.setName(name()); m_mod_id_resolver = new Flame::FileResolvingTask(APPLICATION->network(), m_pack); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 5d227ee5..2a513602 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -51,8 +51,8 @@ class FlameCreationTask final : public InstanceCreationTask { Q_OBJECT public: - FlameCreationTask(const QString& staging_path, SettingsObjectPtr global_settings, QWidget* parent) - : InstanceCreationTask(), m_parent(parent) + FlameCreationTask(const QString& staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString id, QString version_id) + : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); @@ -78,5 +78,7 @@ class FlameCreationTask final : public InstanceCreationTask { NetJob* m_process_update_file_info_job = nullptr; NetJob::Ptr m_files_job = nullptr; + QString m_managed_id, m_managed_version_id; + std::optional m_instance; }; diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 5eb28a85..c043a2e3 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -211,7 +211,7 @@ bool ModrinthCreationTask::createInstance() instance.setIconKey("modrinth"); } - instance.setManagedPack("modrinth", getManagedPackID(), m_managed_name, m_managed_version_id, version()); + instance.setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version()); instance.setName(name()); instance.saveNow(); @@ -284,7 +284,8 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector< } if (set_managed_info) { - m_managed_version_id = Json::ensureString(obj, "versionId", {}, "Managed ID"); + if (m_managed_version_id.isEmpty()) + m_managed_version_id = Json::ensureString(obj, "versionId", {}, "Managed ID"); m_managed_name = Json::ensureString(obj, "name", {}, "Managed Name"); } @@ -384,13 +385,3 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector< return true; } - -QString ModrinthCreationTask::getManagedPackID() const -{ - if (!m_source_url.isEmpty()) { - QRegularExpression regex(R"(data\/(.*)\/versions)"); - return regex.match(m_source_url).captured(1); - } - - return {}; -} diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h index e459aadf..551674d2 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h @@ -14,8 +14,8 @@ class ModrinthCreationTask final : public InstanceCreationTask { Q_OBJECT public: - ModrinthCreationTask(QString staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString source_url = {}) - : InstanceCreationTask(), m_parent(parent), m_source_url(std::move(source_url)) + ModrinthCreationTask(QString staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString id, QString version_id = {}) + : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); @@ -28,14 +28,12 @@ class ModrinthCreationTask final : public InstanceCreationTask { private: bool parseManifest(const QString&, std::vector&, bool set_managed_info = true, bool show_optional_dialog = true); - QString getManagedPackID() const; private: QWidget* m_parent = nullptr; QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion; QString m_managed_id, m_managed_version_id, m_managed_name; - QString m_source_url; std::vector m_files; NetJob::Ptr m_files_job; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index a65b6585..d288a869 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -197,12 +197,18 @@ void FlamePage::suggestCurrent() return; } - if (selectedVersion.isEmpty() || selectedVersion == "-1") { + if (m_selected_version_index == -1) { dialog->setSuggestedPack(); return; } - dialog->setSuggestedPack(current.name, new InstanceImportTask(selectedVersion,this)); + auto version = current.versions.at(m_selected_version_index); + + QMap extra_info; + extra_info.insert("pack_id", QString::number(current.addonId)); + extra_info.insert("pack_version_id", QString::number(version.fileId)); + + dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, extra_info)); QString editedLogoName; editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0); listModel->getLogo(current.logoName, current.logoUrl, @@ -212,10 +218,13 @@ void FlamePage::suggestCurrent() void FlamePage::onVersionSelectionChanged(QString data) { if (data.isNull() || data.isEmpty()) { - selectedVersion = ""; + m_selected_version_index = -1; return; } - selectedVersion = ui->versionSelectionBox->currentData().toString(); + + m_selected_version_index = ui->versionSelectionBox->currentIndex(); + Q_ASSERT(current.versions.at(m_selected_version_index).downloadUrl == ui->versionSelectionBox->currentData().toString()); + suggestCurrent(); } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index 8130e416..8bdca38e 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -99,5 +99,5 @@ private: Flame::ListModel* listModel = nullptr; Flame::IndexedPack current; - QString selectedVersion; + int m_selected_version_index = -1; }; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 4482774c..c66395f2 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -300,7 +300,11 @@ void ModrinthPage::suggestCurrent() for (auto& ver : current.versions) { if (ver.id == selectedVersion) { - dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this)); + QMap extra_info; + extra_info.insert("pack_id", current.id); + extra_info.insert("pack_version_id", ver.id); + + dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this, extra_info)); auto iconName = current.iconName; m_model->getLogo(iconName, current.iconUrl.toString(), [this, iconName](QString logo) { dialog->setSuggestedIconFromFile(logo, iconName); }); From 04dbe287931b618c0d12617150ce426dd7359cf2 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 11:49:21 -0300 Subject: [PATCH 15/30] fix(ManagedPackPage): better changelog text when fetching / no changelog Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 3 +++ launcher/ui/pages/instance/ManagedPackPage.ui | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 126757d5..2f1e4ff0 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -219,6 +219,9 @@ void ModrinthManagedPackPage::parseManagedPack() netJob->deleteLater(); delete response; }); + + ui->changelogTextBrowser->setText(tr("Fetching changelogs...")); + netJob->start(); } diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index 6d8911e0..b7c91798 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -168,7 +168,11 @@ - + + + No changelog available for this version! + + From 527c1113f1c92b8afe59eb0df0dbac8a1d508d98 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 12:19:05 -0300 Subject: [PATCH 16/30] feat(ManagedPackPage): add Flame UI Signed-off-by: flow --- buildconfig/BuildConfig.h | 2 + .../ui/pages/instance/ManagedPackPage.cpp | 66 ++++++++++++++++++- launcher/ui/pages/instance/ManagedPackPage.h | 7 ++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 4a309073..a05d7a9e 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -161,6 +161,8 @@ class Config { QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; + QString FLAME_BASE_URL = "https://api.curseforge.com/v1"; + QString versionString() const; /** * \brief Converts the Version to a string. diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 2f1e4ff0..45be7c71 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -269,7 +269,65 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); } -void FlameManagedPackPage::parseManagedPack() {} +void FlameManagedPackPage::parseManagedPack() { + qDebug() << "Parsing Flame pack"; + + auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()); + auto response = new QByteArray(); + + QString id = m_inst->getManagedPackID(); + + netJob->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response)); + + QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Flame at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + + setFailState(); + + return; + } + + try { + auto obj = doc.object(); + auto data = Json::ensureArray(obj, "data"); + Flame::loadIndexedPackVersions(m_pack, data); + } catch (const JSONValidationError& e) { + qDebug() << *response; + qWarning() << "Error while reading modrinth modpack version: " << e.cause(); + + setFailState(); + return; + } + + for (auto version : m_pack.versions) { + QString name; + + name = version.version; + + if (version.fileId == m_inst->getManagedPackVersionID().toInt()) + name.append(tr(" (Current)")); + + ui->versionsComboBox->addItem(name, QVariant(version.fileId)); + } + + suggestVersion(); + + m_loaded = true; + }); + QObject::connect(netJob, &NetJob::failed, this, &FlameManagedPackPage::setFailState); + QObject::connect(netJob, &NetJob::aborted, this, &FlameManagedPackPage::setFailState); + QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { + netJob->deleteLater(); + delete response; + }); + + netJob->start(); +} QString FlameManagedPackPage::url() const { @@ -278,6 +336,12 @@ QString FlameManagedPackPage::url() const void FlameManagedPackPage::suggestVersion() { + auto index = ui->versionsComboBox->currentIndex(); + auto version = m_pack.versions.at(index); + + ui->changelogTextBrowser->setHtml(m_api.getModFileChangelog(m_inst->getManagedPackID().toInt(), version.fileId)); + + ManagedPackPage::suggestVersion(); } #include "ManagedPackPage.moc" diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index a81d24f0..6d487820 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -5,6 +5,9 @@ #include "modplatform/modrinth/ModrinthAPI.h" #include "modplatform/modrinth/ModrinthPackManifest.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/flame/FlamePackIndex.h" + #include "ui/pages/BasePage.h" #include @@ -130,4 +133,8 @@ class FlameManagedPackPage final : public ManagedPackPage { public slots: void suggestVersion() override; + + private: + Flame::IndexedPack m_pack; + FlameAPI m_api; }; From 38f59fdf39250af22ee8e99e8a1cbcb1f838c6d2 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 12:42:26 -0300 Subject: [PATCH 17/30] fix(ManagedPackPage): add warning about old bug with pack IDs Signed-off-by: flow --- .../ui/pages/instance/ManagedPackPage.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 45be7c71..c72b554d 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -272,6 +272,25 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i void FlameManagedPackPage::parseManagedPack() { qDebug() << "Parsing Flame pack"; + // We need to tell the user to redownload the pack, since we didn't save the required info previously + if (m_inst->getManagedPackID().isEmpty()) { + setFailState(); + QString message = tr( + "

Hey there!

" + "

" + "It seems like your Pack ID is null. This is because of a bug in older versions of the launcher.
" + "Unfortunately, we can't do the proper API requests without this information.
" + "
" + "So, in order for this feature to work, you will need to re-download the modpack from the built-in downloader.
" + "
" + "Don't worry though, it will ask you to update this instance instead, so you'll not lose this instance!" + "

" + ); + + ui->changelogTextBrowser->setHtml(message); + return; + } + auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()); auto response = new QByteArray(); From 34794cc4af5655021b43291c61ad94f7116a3c27 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 12:49:03 -0300 Subject: [PATCH 18/30] fix(ManagedPackPage): give extra_info to InstanceImportTask in MR packs Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index c72b554d..f00a2bdd 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -246,7 +246,11 @@ void ModrinthManagedPackPage::update() auto index = ui->versionsComboBox->currentIndex(); auto version = m_pack.versions.at(index); - auto extracted = new InstanceImportTask(version.download_url, this); + QMap extra_info; + extra_info.insert("pack_id", m_pack.id); + extra_info.insert("pack_version_id", version.id); + + auto extracted = new InstanceImportTask(version.download_url, this, extra_info); InstanceName inst_name(m_inst->getManagedPackName(), version.version); inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); From 57b905be2493f68ab49482a45ab63249bb6468fa Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 13:03:50 -0300 Subject: [PATCH 19/30] feat(ManagedPackPage): implement Flame modpack updating button Signed-off-by: flow --- .../ui/pages/instance/ManagedPackPage.cpp | 26 +++++++++++++++++++ launcher/ui/pages/instance/ManagedPackPage.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index f00a2bdd..5f108cf1 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -271,6 +271,7 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i { Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); + connect(ui->updateButton, &QPushButton::pressed, this, &FlameManagedPackPage::update); } void FlameManagedPackPage::parseManagedPack() { @@ -367,4 +368,29 @@ void FlameManagedPackPage::suggestVersion() ManagedPackPage::suggestVersion(); } +void FlameManagedPackPage::update() +{ + auto index = ui->versionsComboBox->currentIndex(); + auto version = m_pack.versions.at(index); + + QMap extra_info; + extra_info.insert("pack_id", m_inst->getManagedPackID()); + extra_info.insert("pack_version_id", QString::number(version.fileId)); + + auto extracted = new InstanceImportTask(version.downloadUrl, this, extra_info); + + InstanceName inst_name(m_inst->getManagedPackName(), version.version); + inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); + extracted->setName(inst_name); + + extracted->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id())); + extracted->setIcon(m_inst->iconKey()); + extracted->setConfirmUpdate(false); + + auto did_succeed = runUpdateTask(extracted); + + if (m_instance_window && did_succeed) + m_instance_window->close(); +} + #include "ManagedPackPage.moc" diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 6d487820..9ad5e34a 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -134,6 +134,8 @@ class FlameManagedPackPage final : public ManagedPackPage { public slots: void suggestVersion() override; + void update() override; + private: Flame::IndexedPack m_pack; FlameAPI m_api; From 74f7039abfad08c79e860a1922efa29912e04e1c Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 13:06:20 -0300 Subject: [PATCH 20/30] fix(ManagedPackPage): clear combo boxes when adding new versions Prevents versions to undergo mitosis. Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 5f108cf1..0b141a1f 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -193,6 +193,11 @@ void ModrinthManagedPackPage::parseManagedPack() return; } + // We block signals here so that suggestVersion() doesn't get called, causing an assertion fail. + ui->versionsComboBox->blockSignals(true); + ui->versionsComboBox->clear(); + ui->versionsComboBox->blockSignals(false); + for (auto version : m_pack.versions) { QString name; @@ -328,6 +333,11 @@ void FlameManagedPackPage::parseManagedPack() { return; } + // We block signals here so that suggestVersion() doesn't get called, causing an assertion fail. + ui->versionsComboBox->blockSignals(true); + ui->versionsComboBox->clear(); + ui->versionsComboBox->blockSignals(false); + for (auto version : m_pack.versions) { QString name; From c5c426ecbc5811fb2a5c0ea8d22e65c43d7b9ff2 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 13:27:09 -0300 Subject: [PATCH 21/30] chore(ManagedPackPage): format and add headers Signed-off-by: flow --- .../ui/pages/instance/ManagedPackPage.cpp | 37 ++++++++++++------- launcher/ui/pages/instance/ManagedPackPage.h | 12 ++++-- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 0b141a1f..cf782606 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 flow +// +// SPDX-License-Identifier: GPL-3.0-only + #include "ManagedPackPage.h" #include "ui_ManagedPackPage.h" @@ -79,6 +83,8 @@ QString ManagedPackPage::displayName() const auto type = m_inst->getManagedPackType(); if (type.isEmpty()) return {}; + if (type == "flame") + type = "CurseForge"; return type.replace(0, 1, type[0].toUpper()); } @@ -159,6 +165,8 @@ ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWin connect(ui->updateButton, &QPushButton::pressed, this, &ModrinthManagedPackPage::update); } +// MODRINTH + void ModrinthManagedPackPage::parseManagedPack() { qDebug() << "Parsing Modrinth pack"; @@ -271,6 +279,8 @@ void ModrinthManagedPackPage::update() m_instance_window->close(); } +// FLAME + FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) : ManagedPackPage(inst, instance_window, parent) { @@ -279,23 +289,23 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i connect(ui->updateButton, &QPushButton::pressed, this, &FlameManagedPackPage::update); } -void FlameManagedPackPage::parseManagedPack() { +void FlameManagedPackPage::parseManagedPack() +{ qDebug() << "Parsing Flame pack"; // We need to tell the user to redownload the pack, since we didn't save the required info previously if (m_inst->getManagedPackID().isEmpty()) { setFailState(); - QString message = tr( - "

Hey there!

" - "

" - "It seems like your Pack ID is null. This is because of a bug in older versions of the launcher.
" - "Unfortunately, we can't do the proper API requests without this information.
" - "
" - "So, in order for this feature to work, you will need to re-download the modpack from the built-in downloader.
" - "
" - "Don't worry though, it will ask you to update this instance instead, so you'll not lose this instance!" - "

" - ); + QString message = + tr("

Hey there!

" + "

" + "It seems like your Pack ID is null. This is because of a bug in older versions of the launcher.
" + "Unfortunately, we can't do the proper API requests without this information.
" + "
" + "So, in order for this feature to work, you will need to re-download the modpack from the built-in downloader.
" + "
" + "Don't worry though, it will ask you to update this instance instead, so you'll not lose this instance!" + "

"); ui->changelogTextBrowser->setHtml(message); return; @@ -327,7 +337,7 @@ void FlameManagedPackPage::parseManagedPack() { Flame::loadIndexedPackVersions(m_pack, data); } catch (const JSONValidationError& e) { qDebug() << *response; - qWarning() << "Error while reading modrinth modpack version: " << e.cause(); + qWarning() << "Error while reading flame modpack version: " << e.cause(); setFailState(); return; @@ -365,6 +375,7 @@ void FlameManagedPackPage::parseManagedPack() { QString FlameManagedPackPage::url() const { + // FIXME: We should display the websiteUrl field, but this requires doing the API request first :( return {}; } diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 9ad5e34a..282a8111 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 flow +// +// SPDX-License-Identifier: GPL-3.0-only + #pragma once #include "BaseInstance.h" @@ -44,7 +48,7 @@ class ManagedPackPage : public QWidget, public BasePage { /** Gets the necessary information about the managed pack, such as * available versions*/ - virtual void parseManagedPack() {}; + virtual void parseManagedPack(){}; /** URL of the managed pack. * Not the version-specific one. @@ -58,7 +62,7 @@ class ManagedPackPage : public QWidget, public BasePage { */ virtual void suggestVersion(); - virtual void update() {}; + virtual void update(){}; protected slots: /** Does the necessary UI changes for when something failed. @@ -94,7 +98,9 @@ class GenericManagedPackPage final : public ManagedPackPage { Q_OBJECT public: - GenericManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr) : ManagedPackPage(inst, instance_window, parent) {} + GenericManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr) + : ManagedPackPage(inst, instance_window, parent) + {} ~GenericManagedPackPage() override = default; // TODO: We may want to show this page with some useful info at some point. From cb12c51afc97ea2c7ad51c218db5cbc7bfbc39d2 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 12 Nov 2022 13:41:48 -0300 Subject: [PATCH 22/30] fix(ManagedPackPage): check app capabilities for creating the CF page Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index cf782606..8b0f715d 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -47,7 +47,7 @@ ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, Q { if (type == "modrinth") return new ModrinthManagedPackPage(inst, nullptr, parent); - if (type == "flame") + if (type == "flame" && (APPLICATION->capabilities() & Application::SupportsFlame)) return new FlameManagedPackPage(inst, nullptr, parent); return new GenericManagedPackPage(inst, nullptr, parent); From feb6f285ce427ef218c925e5416ad7dc7ad67602 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 18 Nov 2022 15:23:28 -0300 Subject: [PATCH 23/30] feat(ManagedPackPage): add reload button when in a fail state Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 10 +++++++++- launcher/ui/pages/instance/ManagedPackPage.ui | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 8b0f715d..10182b8b 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -61,6 +61,14 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi ui->setupUi(this); ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style())); + + ui->reloadButton->setVisible(false); + connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){ + ui->reloadButton->setVisible(false); + + // Pretend we're opening the page again + openedImpl(); + }); } ManagedPackPage::~ManagedPackPage() @@ -154,7 +162,7 @@ void ManagedPackPage::setFailState() ui->updateButton->setText(tr("Cannot update!")); ui->updateButton->setDisabled(true); - // TODO: Perhaps start a timer here when m_loaded is false to try and reload. + ui->reloadButton->setVisible(true); } ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index b7c91798..bbe44a94 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -179,6 +179,13 @@ + + + + Reload page + + + From 089018015a441a35dc1780c9b61b29740bbf8a28 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 18 Nov 2022 15:48:16 -0300 Subject: [PATCH 24/30] refactor(ManagedPackPage): use smart pointers instead of raw ones Signed-off-by: flow --- .../ui/pages/instance/ManagedPackPage.cpp | 42 +++++++++---------- launcher/ui/pages/instance/ManagedPackPage.h | 4 ++ 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 10182b8b..b3816ce9 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -179,14 +179,17 @@ void ModrinthManagedPackPage::parseManagedPack() { qDebug() << "Parsing Modrinth pack"; - auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()); - auto response = new QByteArray(); + if (m_fetch_job && m_fetch_job->isRunning()) + m_fetch_job->abort(); + + m_fetch_job.reset(new NetJob(QString("Modrinth::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network())); + auto response = std::make_shared(); QString id = m_inst->getManagedPackID(); - netJob->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get())); - QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id] { + QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -234,16 +237,12 @@ void ModrinthManagedPackPage::parseManagedPack() m_loaded = true; }); - QObject::connect(netJob, &NetJob::failed, this, &ModrinthManagedPackPage::setFailState); - QObject::connect(netJob, &NetJob::aborted, this, &ModrinthManagedPackPage::setFailState); - QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { - netJob->deleteLater(); - delete response; - }); + QObject::connect(m_fetch_job.get(), &NetJob::failed, this, &ModrinthManagedPackPage::setFailState); + QObject::connect(m_fetch_job.get(), &NetJob::aborted, this, &ModrinthManagedPackPage::setFailState); ui->changelogTextBrowser->setText(tr("Fetching changelogs...")); - netJob->start(); + m_fetch_job->start(); } QString ModrinthManagedPackPage::url() const @@ -319,14 +318,17 @@ void FlameManagedPackPage::parseManagedPack() return; } - auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()); - auto response = new QByteArray(); + if (m_fetch_job && m_fetch_job->isRunning()) + m_fetch_job->abort(); + + m_fetch_job.reset(new NetJob(QString("Flame::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network())); + auto response = std::make_shared(); QString id = m_inst->getManagedPackID(); - netJob->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response)); + m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get())); - QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id] { + QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -371,14 +373,10 @@ void FlameManagedPackPage::parseManagedPack() m_loaded = true; }); - QObject::connect(netJob, &NetJob::failed, this, &FlameManagedPackPage::setFailState); - QObject::connect(netJob, &NetJob::aborted, this, &FlameManagedPackPage::setFailState); - QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { - netJob->deleteLater(); - delete response; - }); + QObject::connect(m_fetch_job.get(), &NetJob::failed, this, &FlameManagedPackPage::setFailState); + QObject::connect(m_fetch_job.get(), &NetJob::aborted, this, &FlameManagedPackPage::setFailState); - netJob->start(); + m_fetch_job->start(); } QString FlameManagedPackPage::url() const diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 282a8111..d29a5e88 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -123,6 +123,8 @@ class ModrinthManagedPackPage final : public ManagedPackPage { void update() override; private: + NetJob::Ptr m_fetch_job = nullptr; + Modrinth::Modpack m_pack; ModrinthAPI m_api; }; @@ -143,6 +145,8 @@ class FlameManagedPackPage final : public ManagedPackPage { void update() override; private: + NetJob::Ptr m_fetch_job = nullptr; + Flame::IndexedPack m_pack; FlameAPI m_api; }; From 4e75419e081dd43b94df0fe751253a6f2139a834 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 19 Nov 2022 08:36:12 -0300 Subject: [PATCH 25/30] fix(ManagedPagePage): don't reload pack info when not needed Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index b3816ce9..16b2cb57 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -66,6 +66,7 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){ ui->reloadButton->setVisible(false); + m_loaded = false; // Pretend we're opening the page again openedImpl(); }); @@ -179,6 +180,10 @@ void ModrinthManagedPackPage::parseManagedPack() { qDebug() << "Parsing Modrinth pack"; + // No need for the extra work because we already have everything we need. + if (m_loaded) + return; + if (m_fetch_job && m_fetch_job->isRunning()) m_fetch_job->abort(); @@ -318,6 +323,10 @@ void FlameManagedPackPage::parseManagedPack() return; } + // No need for the extra work because we already have everything we need. + if (m_loaded) + return; + if (m_fetch_job && m_fetch_job->isRunning()) m_fetch_job->abort(); From 1630a23fb029c4ba7d622d0ae4da5c9fbfc57fe2 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 25 Nov 2022 10:17:43 -0300 Subject: [PATCH 26/30] refactor(InstanceImport): require rvalue from 'extra_info' mappings Signed-off-by: flow --- launcher/InstanceImportTask.cpp | 4 ++-- launcher/InstanceImportTask.h | 2 +- launcher/ui/pages/instance/ManagedPackPage.cpp | 4 ++-- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 7c04ec47..834e9320 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -55,8 +55,8 @@ #include -InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap extra_info) - : m_sourceUrl(sourceUrl), m_extra_info(std::move(extra_info)), m_parent(parent) +InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap&& extra_info) + : m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent) {} bool InstanceImportTask::abort() diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h index 712ef054..6b8ac966 100644 --- a/launcher/InstanceImportTask.h +++ b/launcher/InstanceImportTask.h @@ -56,7 +56,7 @@ class InstanceImportTask : public InstanceTask { Q_OBJECT public: - explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap extra_info = {}); + explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap&& extra_info = {}); bool abort() override; const QVector &getBlockedFiles() const diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 16b2cb57..d8cb9362 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -275,7 +275,7 @@ void ModrinthManagedPackPage::update() extra_info.insert("pack_id", m_pack.id); extra_info.insert("pack_version_id", version.id); - auto extracted = new InstanceImportTask(version.download_url, this, extra_info); + auto extracted = new InstanceImportTask(version.download_url, this, std::move(extra_info)); InstanceName inst_name(m_inst->getManagedPackName(), version.version); inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); @@ -413,7 +413,7 @@ void FlameManagedPackPage::update() extra_info.insert("pack_id", m_inst->getManagedPackID()); extra_info.insert("pack_version_id", QString::number(version.fileId)); - auto extracted = new InstanceImportTask(version.downloadUrl, this, extra_info); + auto extracted = new InstanceImportTask(version.downloadUrl, this, std::move(extra_info)); InstanceName inst_name(m_inst->getManagedPackName(), version.version); inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index d288a869..6023e741 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -208,7 +208,7 @@ void FlamePage::suggestCurrent() extra_info.insert("pack_id", QString::number(current.addonId)); extra_info.insert("pack_version_id", QString::number(version.fileId)); - dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, extra_info)); + dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); QString editedLogoName; editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0); listModel->getLogo(current.logoName, current.logoUrl, diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index c66395f2..8ab2ad1d 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -304,7 +304,7 @@ void ModrinthPage::suggestCurrent() extra_info.insert("pack_id", current.id); extra_info.insert("pack_version_id", ver.id); - dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this, extra_info)); + dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this, std::move(extra_info))); auto iconName = current.iconName; m_model->getLogo(iconName, current.iconUrl.toString(), [this, iconName](QString logo) { dialog->setSuggestedIconFromFile(logo, iconName); }); From 80054e4db26b85f81778f1ac53bd7c123f70fe3c Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 25 Nov 2022 10:19:03 -0300 Subject: [PATCH 27/30] fix(ManagedPackPage): preserve pack ID from Modrinth update Signed-off-by: flow --- launcher/ui/pages/instance/ManagedPackPage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d8cb9362..0be27ffc 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -272,7 +272,8 @@ void ModrinthManagedPackPage::update() auto version = m_pack.versions.at(index); QMap extra_info; - extra_info.insert("pack_id", m_pack.id); + // NOTE: Don't use 'm_pack.id' here, since we didn't completely parse all the metadata for the pack, including this field. + extra_info.insert("pack_id", m_inst->getManagedPackID()); extra_info.insert("pack_version_id", version.id); auto extracted = new InstanceImportTask(version.download_url, this, std::move(extra_info)); From bb386a1162db751136483a59f2cffe8d9a3d1e73 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 3 Dec 2022 10:15:38 -0300 Subject: [PATCH 28/30] fix(ManagedPackPage): only update the current instance exactly Also carry on the original ID to avoid updating the wrong instance. Signed-off-by: flow --- launcher/InstanceImportTask.cpp | 18 ++++++++++++++---- launcher/InstanceList.cpp | 17 +++++++---------- launcher/InstanceList.h | 2 +- launcher/InstanceTask.h | 11 ++++++++++- .../flame/FlameInstanceCreationTask.cpp | 18 ++++++++++++------ .../flame/FlameInstanceCreationTask.h | 14 ++++++++++++-- .../modrinth/ModrinthInstanceCreationTask.cpp | 18 ++++++++++++------ .../modrinth/ModrinthInstanceCreationTask.h | 14 ++++++++++++-- launcher/ui/pages/instance/ManagedPackPage.cpp | 2 ++ 9 files changed, 82 insertions(+), 32 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 834e9320..b97870da 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -265,7 +265,12 @@ void InstanceImportTask::processFlame() Q_ASSERT(pack_version_id_it != m_extra_info.constEnd()); auto pack_version_id = pack_version_id_it.value(); - auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id); + QString original_instance_id; + auto original_instance_id_it = m_extra_info.constFind("original_instance_id"); + if (original_instance_id_it != m_extra_info.constEnd()) + original_instance_id = original_instance_id_it.value(); + + auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); inst_creation_task->setName(*this); inst_creation_task->setIcon(m_instIcon); @@ -273,7 +278,7 @@ void InstanceImportTask::processFlame() inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { - setOverride(inst_creation_task->shouldOverride()); + setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID()); emitSucceeded(); }); connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); @@ -339,7 +344,12 @@ void InstanceImportTask::processModrinth() if (pack_version_id_it != m_extra_info.constEnd()) pack_version_id = pack_version_id_it.value(); - auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id); + QString original_instance_id; + auto original_instance_id_it = m_extra_info.constFind("original_instance_id"); + if (original_instance_id_it != m_extra_info.constEnd()) + original_instance_id = original_instance_id_it.value(); + + auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); inst_creation_task->setName(*this); inst_creation_task->setIcon(m_instIcon); @@ -347,7 +357,7 @@ void InstanceImportTask::processModrinth() inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { - setOverride(inst_creation_task->shouldOverride()); + setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID()); emitSucceeded(); }); connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index cebd70d7..68e3e92c 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -816,7 +816,7 @@ class InstanceStaging : public Task { void childSucceded() { unsigned sleepTime = backoff(); - if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, m_child->shouldOverride())) + if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get())) { emitSucceeded(); return; @@ -880,25 +880,22 @@ QString InstanceList::getStagedInstancePath() return path; } -bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, bool should_override) +bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, InstanceTask const& commiting) { QDir dir; QString instID; InstancePtr inst; + auto should_override = commiting.shouldOverride(); + if (should_override) { - // This is to avoid problems when the instance folder gets manually renamed - if ((inst = getInstanceByManagedName(instanceName.originalName()))) { - instID = QFileInfo(inst->instanceRoot()).fileName(); - } else if ((inst = getInstanceByManagedName(instanceName.modifiedName()))) { - instID = QFileInfo(inst->instanceRoot()).fileName(); - } else { - instID = FS::RemoveInvalidFilenameChars(instanceName.modifiedName(), '-'); - } + instID = commiting.originalInstanceID(); } else { instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir); } + Q_ASSERT(!instID.isEmpty()); + { WatchLock lock(m_watcher, m_instDir); QString destination = FS::PathCombine(m_instDir, instID); diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 3673298f..edacba3c 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -133,7 +133,7 @@ public: * should_override is used when another similar instance already exists, and we want to override it * - for instance, when updating it. */ - bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, bool should_override); + bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, const InstanceTask&); /** * Destroy a previously created staging area given by @keyPath - used when creation fails. diff --git a/launcher/InstanceTask.h b/launcher/InstanceTask.h index e481354c..7c02160a 100644 --- a/launcher/InstanceTask.h +++ b/launcher/InstanceTask.h @@ -49,8 +49,15 @@ class InstanceTask : public Task, public InstanceName { bool shouldOverride() const { return m_override_existing; } + [[nodiscard]] QString originalInstanceID() const { return m_original_instance_id; }; + protected: - void setOverride(bool override) { m_override_existing = override; } + void setOverride(bool override, QString instance_id_to_override = {}) + { + m_override_existing = override; + if (!instance_id_to_override.isEmpty()) + m_original_instance_id = instance_id_to_override; + } protected: /* data */ SettingsObjectPtr m_globalSettings; @@ -60,4 +67,6 @@ class InstanceTask : public Task, public InstanceName { bool m_override_existing = false; bool m_confirm_update = true; + + QString m_original_instance_id; }; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index ad50597e..1e76f252 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -81,13 +81,19 @@ bool FlameCreationTask::updateInstance() auto instance_list = APPLICATION->instances(); // FIXME: How to handle situations when there's more than one install already for a given modpack? - auto inst = instance_list->getInstanceByManagedName(originalName()); + InstancePtr inst; + if (auto original_id = originalInstanceID(); !original_id.isEmpty()) { + inst = instance_list->getInstanceById(original_id); + Q_ASSERT(inst); + } else { + inst = instance_list->getInstanceByManagedName(originalName()); - if (!inst) { - inst = instance_list->getInstanceById(originalName()); + if (!inst) { + inst = instance_list->getInstanceById(originalName()); - if (!inst) - return false; + if (!inst) + return false; + } } QString index_path(FS::PathCombine(m_stagingPath, "manifest.json")); @@ -233,7 +239,7 @@ bool FlameCreationTask::updateInstance() } } - setOverride(true); + setOverride(true, inst->id()); qDebug() << "Will override instance!"; m_instance = inst; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 2a513602..3a1c729f 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -51,11 +51,21 @@ class FlameCreationTask final : public InstanceCreationTask { Q_OBJECT public: - FlameCreationTask(const QString& staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString id, QString version_id) - : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) + FlameCreationTask(const QString& staging_path, + SettingsObjectPtr global_settings, + QWidget* parent, + QString id, + QString version_id, + QString original_instance_id = {}) + : InstanceCreationTask() + , m_parent(parent) + , m_managed_id(std::move(id)) + , m_managed_version_id(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); + + m_original_instance_id = std::move(original_instance_id); } bool abort() override; diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index c043a2e3..1c0e8979 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -33,13 +33,19 @@ bool ModrinthCreationTask::updateInstance() auto instance_list = APPLICATION->instances(); // FIXME: How to handle situations when there's more than one install already for a given modpack? - auto inst = instance_list->getInstanceByManagedName(originalName()); + InstancePtr inst; + if (auto original_id = originalInstanceID(); !original_id.isEmpty()) { + inst = instance_list->getInstanceById(original_id); + Q_ASSERT(inst); + } else { + inst = instance_list->getInstanceByManagedName(originalName()); - if (!inst) { - inst = instance_list->getInstanceById(originalName()); + if (!inst) { + inst = instance_list->getInstanceById(originalName()); - if (!inst) - return false; + if (!inst) + return false; + } } QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json"); @@ -138,7 +144,7 @@ bool ModrinthCreationTask::updateInstance() } - setOverride(true); + setOverride(true, inst->id()); qDebug() << "Will override instance!"; m_instance = inst; diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h index 551674d2..122fc5ce 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h @@ -14,11 +14,21 @@ class ModrinthCreationTask final : public InstanceCreationTask { Q_OBJECT public: - ModrinthCreationTask(QString staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString id, QString version_id = {}) - : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) + ModrinthCreationTask(QString staging_path, + SettingsObjectPtr global_settings, + QWidget* parent, + QString id, + QString version_id = {}, + QString original_instance_id = {}) + : InstanceCreationTask() + , m_parent(parent) + , m_managed_id(std::move(id)) + , m_managed_version_id(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); + + m_original_instance_id = std::move(original_instance_id); } bool abort() override; diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 0be27ffc..c70d70ab 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -275,6 +275,7 @@ void ModrinthManagedPackPage::update() // NOTE: Don't use 'm_pack.id' here, since we didn't completely parse all the metadata for the pack, including this field. extra_info.insert("pack_id", m_inst->getManagedPackID()); extra_info.insert("pack_version_id", version.id); + extra_info.insert("original_instance_id", m_inst->id()); auto extracted = new InstanceImportTask(version.download_url, this, std::move(extra_info)); @@ -413,6 +414,7 @@ void FlameManagedPackPage::update() QMap extra_info; extra_info.insert("pack_id", m_inst->getManagedPackID()); extra_info.insert("pack_version_id", QString::number(version.fileId)); + extra_info.insert("original_instance_id", m_inst->id()); auto extracted = new InstanceImportTask(version.downloadUrl, this, std::move(extra_info)); From 6f50809457a2c974f0f8f15f5158cac7347e18d2 Mon Sep 17 00:00:00 2001 From: flow Date: Mon, 5 Dec 2022 18:13:38 -0300 Subject: [PATCH 29/30] fix(FlamePage): don't assert / suggest blocked modpacks Signed-off-by: flow --- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 6023e741..f9ac4a78 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -217,12 +217,16 @@ void FlamePage::suggestCurrent() void FlamePage::onVersionSelectionChanged(QString data) { - if (data.isNull() || data.isEmpty()) { + bool is_blocked = false; + ui->versionSelectionBox->currentData().toInt(&is_blocked); + + if (data.isNull() || data.isEmpty() || is_blocked) { m_selected_version_index = -1; return; } m_selected_version_index = ui->versionSelectionBox->currentIndex(); + Q_ASSERT(current.versions.at(m_selected_version_index).downloadUrl == ui->versionSelectionBox->currentData().toString()); suggestCurrent(); From 34230bfcf415b4ad314d2534e09b40058ef9eaa2 Mon Sep 17 00:00:00 2001 From: flow Date: Wed, 7 Dec 2022 18:05:46 -0300 Subject: [PATCH 30/30] fix: don't try updating Flame instance names when updating versions Since the exact version string is only available in the manifest, there's no easy way of getting it before commiting to the update, so there's not much of a good way of showing the updated name in the UI, and using the displayName is weird and gives some buggy behavior. We may want to re-enable it in the future if we find a reliable way of showing the correct info on the UI before starting the update. Signed-off-by: flow --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 8 -------- launcher/ui/pages/instance/ManagedPackPage.cpp | 5 +---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 1e76f252..eae66ec7 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -385,14 +385,6 @@ bool FlameCreationTask::createInstance() setAbortable(false); auto inst = m_instance.value(); - // Only change the name if it didn't use a custom name, so that the previous custom name - // is preserved, but if we're using the original one, we update the version string. - // NOTE: This needs to come before the copyManagedPack call! - if (inst->name().contains(inst->getManagedPackVersionName())) { - if (askForChangingInstanceName(m_parent, inst->name(), instance.name()) == InstanceNameChange::ShouldChange) - inst->setName(instance.name()); - } - inst->copyManagedPack(instance); } diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index c70d70ab..7a0d234c 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -418,10 +418,7 @@ void FlameManagedPackPage::update() auto extracted = new InstanceImportTask(version.downloadUrl, this, std::move(extra_info)); - InstanceName inst_name(m_inst->getManagedPackName(), version.version); - inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version)); - extracted->setName(inst_name); - + extracted->setName(m_inst->name()); extracted->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id())); extracted->setIcon(m_inst->iconKey()); extracted->setConfirmUpdate(false);