From 589d8b6923531a53cbccabb8b79ed9861d0fe27c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 16 Aug 2023 19:53:39 +0300 Subject: [PATCH 01/36] feat:Added remove metadata button Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 18 ++++++---- launcher/minecraft/mod/Mod.h | 2 ++ launcher/minecraft/mod/ModFolderModel.cpp | 19 +++++++++++ launcher/minecraft/mod/ModFolderModel.h | 1 + launcher/modplatform/ModIndex.h | 1 - .../pages/instance/ExternalResourcesPage.ui | 11 +++++++ launcher/ui/pages/instance/ModFolderPage.cpp | 33 +++++++++++++++++++ launcher/ui/pages/instance/ModFolderPage.h | 1 + 8 files changed, 79 insertions(+), 7 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index ae3dea8d8..c9952998c 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -132,17 +132,23 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_trash) - if (!preserve_metadata) { qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name()); - if (metadata()) { - Metadata::remove(index_dir, metadata()->slug); - } else { - auto n = name(); - Metadata::remove(index_dir, n); - } + destroyMetadata(index_dir); } return Resource::destroy(attempt_trash); } +void Mod::destroyMetadata(QDir& index_dir) +{ + if (metadata()) { + Metadata::remove(index_dir, metadata()->slug); + } else { + auto n = name(); + Metadata::remove(index_dir, n); + } + m_local_details.metadata = nullptr; +} + auto Mod::details() const -> const ModDetails& { return m_local_details; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 6dafecfc5..e97ee9d3b 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -93,6 +93,8 @@ class Mod : public Resource { // Delete all the files of this mod auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool; + // Delete the metadata only + void destroyMetadata(QDir& index_dir); void finishResolvingWithDetails(ModDetails&& details); diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 280e70d7b..d6ce98ed9 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -228,6 +228,25 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) return true; } +bool ModFolderModel::deleteModsMeatadata(const QModelIndexList& indexes) +{ + if (indexes.isEmpty()) + return true; + + for (auto i : indexes) { + if (i.column() != 0) { + continue; + } + auto m = at(i.row()); + auto index_dir = indexDir(); + m->destroyMetadata(index_dir); + } + + update(); + + return true; +} + bool ModFolderModel::isValid() { return m_dir.exists() && m_dir.isReadable(); diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 06fd78149..c512c58f0 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -79,6 +79,7 @@ class ModFolderModel : public ResourceFolderModel { /// Deletes all the selected mods bool deleteMods(const QModelIndexList& indexes); + bool deleteModsMeatadata(const QModelIndexList& indexes); bool isValid(); diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index cad217034..0e18ccd17 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -128,7 +128,6 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 3c8366917..56adce476 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -168,6 +168,17 @@ Go to mods home page + + + false + + + Remove metadata + + + Remove selected mod metadata + + diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 0f5e29cb6..146e1d973 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -92,6 +92,10 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->addAction(ui->actionVisitItemPage); connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); + ui->actionRemoveItemMetadata->setToolTip(tr("Remove mod's metadata")); + ui->actionsToolbar->insertActionAfter(ui->actionRemoveItem, ui->actionRemoveItemMetadata); + connect(ui->actionRemoveItemMetadata, &QAction::triggered, this, &ModFolderPage::deleteModMetadata); + auto check_allow_update = [this] { return ui->treeView->selectionModel()->hasSelection() || !m_model->empty(); }; connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { @@ -104,11 +108,16 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr if (selected <= 1) { ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); + + ui->actionRemoveItemMetadata->setToolTip(tr("Remove mod's metadata")); } else { ui->actionVisitItemPage->setText(tr("Visit mods' pages")); ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); + + ui->actionRemoveItemMetadata->setToolTip(tr("Remove mods' metadata")); } ui->actionVisitItemPage->setEnabled(selected != 0); + ui->actionRemoveItemMetadata->setEnabled(selected != 0); }); connect(mods.get(), &ModFolderModel::rowsInserted, this, @@ -297,3 +306,27 @@ void ModFolderPage::visitModPages() DesktopServices::openUrl(url); } } + +void ModFolderPage::deleteModMetadata() +{ + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + QString text; + auto selectionCount = m_model->selectedMods(selection).length(); + if (selectionCount == 0) + return; + else if (selectionCount > 1) + text = tr("You are about to remove the metadata for %1 mods.\n" + "Are you sure?") + .arg(selectionCount); + else + text = tr("You are about to remove the metadata for %1.\n" + "Are you sure?") + .arg(m_model->at(selection.at(0).row())->name()); + + auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), text, QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response == QMessageBox::Yes) + m_model->deleteModsMeatadata(selection); +} diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index a23dcae18..0c654d0d1 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -61,6 +61,7 @@ class ModFolderPage : public ExternalResourcesPage { private slots: void removeItems(const QItemSelection& selection) override; + void deleteModMetadata(); void installMods(); void updateMods(); From f919d363b706e4c00317b56849702d8f95446bdb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 16 Aug 2023 20:02:32 +0300 Subject: [PATCH 02/36] made safe for vegetarians Signed-off-by: Trial97 --- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.h | 2 +- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index d6ce98ed9..42ee94991 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -228,7 +228,7 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) return true; } -bool ModFolderModel::deleteModsMeatadata(const QModelIndexList& indexes) +bool ModFolderModel::deleteModsMetadata(const QModelIndexList& indexes) { if (indexes.isEmpty()) return true; diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index c512c58f0..4d1bafaed 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -79,7 +79,7 @@ class ModFolderModel : public ResourceFolderModel { /// Deletes all the selected mods bool deleteMods(const QModelIndexList& indexes); - bool deleteModsMeatadata(const QModelIndexList& indexes); + bool deleteModsMetadata(const QModelIndexList& indexes); bool isValid(); diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 146e1d973..d4e7a25c9 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -328,5 +328,5 @@ void ModFolderPage::deleteModMetadata() ->exec(); if (response == QMessageBox::Yes) - m_model->deleteModsMeatadata(selection); + m_model->deleteModsMetadata(selection); } From 6c2c724bd99d442f7856da1a2ef4ebdd674064d1 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Wed, 16 Aug 2023 21:03:09 +0300 Subject: [PATCH 03/36] Update launcher/ui/pages/instance/ExternalResourcesPage.ui Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/pages/instance/ExternalResourcesPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 56adce476..ba703f77d 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -176,7 +176,7 @@ Remove metadata - Remove selected mod metadata + Remove mod's metadata From b0e197de38858c3fe6bc5fbb62570efd3359c802 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 16 Aug 2023 21:26:43 +0300 Subject: [PATCH 04/36] removed warning for one mod selected Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 25 +++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index d4e7a25c9..b42bbf466 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -310,23 +310,20 @@ void ModFolderPage::visitModPages() void ModFolderPage::deleteModMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - QString text; auto selectionCount = m_model->selectedMods(selection).length(); if (selectionCount == 0) return; - else if (selectionCount > 1) - text = tr("You are about to remove the metadata for %1 mods.\n" - "Are you sure?") - .arg(selectionCount); - else - text = tr("You are about to remove the metadata for %1.\n" - "Are you sure?") - .arg(m_model->at(selection.at(0).row())->name()); + if (selectionCount > 1) { + auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), + tr("You are about to remove the metadata for %1 mods.\n" + "Are you sure?") + .arg(selectionCount), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); - auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), text, QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) - ->exec(); + if (response != QMessageBox::Yes) + return; + } - if (response == QMessageBox::Yes) - m_model->deleteModsMetadata(selection); + m_model->deleteModsMetadata(selection); } From 44ff247f5f71ebeb95423ca37bf82d9913073522 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 20:03:02 +0300 Subject: [PATCH 05/36] feat:refactored modpack ux Signed-off-by: Trial97 --- launcher/modplatform/ResourceAPI.h | 2 + .../helpers/NetworkResourceAPI.cpp | 3 +- .../ui/pages/modplatform/ResourceModel.cpp | 57 ++++++++++ launcher/ui/pages/modplatform/ResourceModel.h | 1 + .../ui/pages/modplatform/ResourcePage.cpp | 3 - .../modplatform/atlauncher/AtlFilterModel.cpp | 3 +- .../modplatform/atlauncher/AtlListModel.cpp | 56 +++++++--- .../pages/modplatform/atlauncher/AtlPage.cpp | 4 +- .../pages/modplatform/atlauncher/AtlPage.ui | 93 +++++++++------- .../ui/pages/modplatform/flame/FlameModel.cpp | 55 +++++++-- .../ui/pages/modplatform/flame/FlameModel.h | 5 +- .../ui/pages/modplatform/flame/FlamePage.cpp | 10 ++ .../ui/pages/modplatform/flame/FlamePage.h | 5 +- .../modplatform/import_ftb/ImportFTBPage.cpp | 29 ++++- .../modplatform/import_ftb/ImportFTBPage.h | 3 + .../modplatform/import_ftb/ImportFTBPage.ui | 52 ++++++++- .../modplatform/import_ftb/ListModel.cpp | 105 ++++++++++++++++-- .../pages/modplatform/import_ftb/ListModel.h | 22 ++++ .../modplatform/legacy_ftb/ListModel.cpp | 90 ++++++++++----- .../pages/modplatform/legacy_ftb/ListModel.h | 2 + .../ui/pages/modplatform/legacy_ftb/Page.cpp | 13 +++ .../ui/pages/modplatform/legacy_ftb/Page.h | 5 +- .../ui/pages/modplatform/legacy_ftb/Page.ui | 49 +++++--- .../modplatform/modrinth/ModrinthModel.cpp | 62 +++++++++-- .../modplatform/modrinth/ModrinthModel.h | 5 +- .../modplatform/modrinth/ModrinthPage.cpp | 10 ++ .../pages/modplatform/modrinth/ModrinthPage.h | 4 + .../modplatform/technic/TechnicModel.cpp | 72 ++++++++---- .../pages/modplatform/technic/TechnicModel.h | 2 + .../pages/modplatform/technic/TechnicPage.cpp | 13 +++ .../pages/modplatform/technic/TechnicPage.h | 5 +- launcher/ui/widgets/ProjectItem.cpp | 2 +- 32 files changed, 679 insertions(+), 163 deletions(-) diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index a92217a06..bd0d2824f 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -109,6 +109,8 @@ class ResourceAPI { }; struct ProjectInfoCallbacks { std::function on_succeed; + std::function on_fail; + std::function on_abort; }; struct DependencySearchArgs { diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index 46b966620..506eb187e 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -72,7 +72,8 @@ Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfo callbacks.on_succeed(doc, args.pack); }); - + QObject::connect(job.get(), &NetJob::failed, [callbacks](QString reason) { callbacks.on_fail(reason); }); + QObject::connect(job.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); }); return job; } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 0a7edb7b7..96803531b 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -132,6 +132,36 @@ void ResourceModel::search() if (hasActiveSearchJob()) return; + if (m_search_term.startsWith("#")) { + auto projectId = m_search_term.removeFirst(); + if (!projectId.isEmpty()) { + ResourceAPI::ProjectInfoCallbacks callbacks; + + // Use defaults if no callbacks are set + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestFailed(reason, -1); + }; + if (!callbacks.on_abort) + callbacks.on_abort = [this] { + if (!s_running_models.constFind(this).value()) + return; + searchRequestAborted(); + }; + + if (!callbacks.on_succeed) + callbacks.on_succeed = [this](auto& doc, auto pack) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestForOneSucceeded(doc); + }; + if (auto job = m_api->getProjectInfo({ projectId }, std::move(callbacks)); job) + runSearchJob(job); + return; + } + } auto args{ createSearchArguments() }; auto callbacks{ createSearchCallbacks() }; @@ -194,6 +224,12 @@ void ResourceModel::loadEntry(QModelIndex& entry) return; infoRequestSucceeded(doc, pack, entry); }; + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { + if (!s_running_models.constFind(this).value()) + return; + QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info:%1").arg(reason)); + }; if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job) runInfoJob(job); @@ -372,6 +408,27 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) endInsertRows(); } +void ResourceModel::searchRequestForOneSucceeded(QJsonDocument& doc) +{ + ModPlatform::IndexedPack::Ptr pack = std::make_shared(); + + try { + auto obj = Json::requireObject(doc); + if (obj.contains("data")) + obj = Json::requireObject(obj, "data"); + loadIndexedPack(*pack, obj); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause(); + } + + m_search_state = SearchState::Finished; + + beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + 1); + m_packs.append(pack); + endInsertRows(); +} + void ResourceModel::searchRequestFailed([[maybe_unused]] QString reason, int network_error_code) { switch (network_error_code) { diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index cc813d6e6..ecf4f8f79 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -149,6 +149,7 @@ class ResourceModel : public QAbstractListModel { private: /* Default search request callbacks */ void searchRequestSucceeded(QJsonDocument&); + void searchRequestForOneSucceeded(QJsonDocument&); void searchRequestFailed(QString reason, int network_error_code); void searchRequestAborted(); diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index c087e2be3..fc7d64a48 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -44,9 +44,6 @@ #include #include "Markdown.h" -#include "ResourceDownloadTask.h" - -#include "minecraft/MinecraftInstance.h" #include "ui/dialogs/ResourceDownloadDialog.h" #include "ui/pages/modplatform/ResourceModel.h" diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp index 9cd5eed53..dee3784e5 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp @@ -67,9 +67,10 @@ bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParen if (searchTerm.isEmpty()) { return true; } - QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); ATLauncher::IndexedPack pack = sourceModel()->data(index, Qt::UserRole).value(); + if (searchTerm.startsWith("#")) + return QString::number(pack.id) == searchTerm.mid(1); return pack.name.contains(searchTerm, Qt::CaseInsensitive); } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 39f4f346a..b6fb71535 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -21,6 +21,7 @@ #include #include "net/ApiDownload.h" +#include "ui/widgets/ProjectItem.h" namespace Atl { @@ -46,27 +47,50 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } ATLauncher::IndexedPack pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name; - } else if (role == Qt::ToolTipRole) { - return pack.name; - } else if (role == Qt::DecorationRole) { - if (m_logoMap.contains(pack.safeName)) { - return (m_logoMap.value(pack.safeName)); + switch (role) { + case Qt::ToolTipRole: { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks + QString edit = pack.description.left(97); + edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); + return edit; + } + return pack.description; } - auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); + case Qt::DecorationRole: { + if (m_logoMap.contains(pack.safeName)) { + return (m_logoMap.value(pack.safeName)); + } + auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); - auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); - ((ListModel*)this)->requestLogo(pack.safeName, url); + auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); + ((ListModel*)this)->requestLogo(pack.safeName, url); - return icon; - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; + return icon; + } + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return pack.description; + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; } - return QVariant(); + return {}; } void ListModel::request() diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 5e3b9ecf1..c7e800278 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -35,11 +35,11 @@ */ #include "AtlPage.h" +#include "ui/widgets/ProjectItem.h" #include "ui_AtlPage.h" #include "BuildConfig.h" -#include "AtlOptionalModDialog.h" #include "AtlUserInteractionSupportImpl.h" #include "modplatform/atlauncher/ATLPackInstallTask.h" #include "ui/dialogs/NewInstanceDialog.h" @@ -71,6 +71,8 @@ AtlPage::AtlPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &AtlPage::onSortingSelectionChanged); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &AtlPage::onSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &AtlPage::onVersionSelectionChanged); + + ui->packView->setItemDelegate(new ProjectItemDelegate(this)); } AtlPage::~AtlPage() diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui b/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui index 746aa6d1c..8b6747331 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui @@ -11,44 +11,7 @@ - - - - - - true - - - - 96 - 48 - - - - - - - - true - - - true - - - - - - - Warning: This is still a work in progress. If you run into issues with the imported modpack, it may be a bug. - - - true - - - - - - + @@ -68,7 +31,34 @@ - + + + + + + true + + + true + + + + + + + true + + + + 96 + 48 + + + + + + + Search and filter... @@ -78,6 +68,31 @@ + + + + Search + + + + + + + + true + + + + Warning: This is still a work in progress. If you run into issues with the imported modpack, it may be a bug. + + + Qt::AlignCenter + + + true + + + diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index ff21d0109..e488f0787 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -1,6 +1,8 @@ #include "FlameModel.h" #include #include "Application.h" +#include "modplatform/ResourceAPI.h" +#include "modplatform/flame/FlameAPI.h" #include "ui/widgets/ProjectItem.h" #include "net/ApiDownload.h" @@ -161,6 +163,25 @@ void ListModel::fetchMore(const QModelIndex& parent) void ListModel::performPaginatedSearch() { + if (currentSearchTerm.startsWith("#")) { + auto projectId = currentSearchTerm.removeFirst(); + if (!projectId.isEmpty()) { + ResourceAPI::ProjectInfoCallbacks callbacks; + + // Use defaults if no callbacks are set + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + + if (!callbacks.on_succeed) + callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + static const FlameAPI api; + if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { + jobPtr = job; + jobPtr->start(); + } + return; + } + } auto netJob = makeShared("Flame::Search", APPLICATION->network()); auto searchUrl = QString( "https://api.curseforge.com/v1/mods/search?" @@ -189,23 +210,24 @@ void ListModel::searchWithTerm(const QString& term, int sort) } currentSearchTerm = term; currentSort = sort; - if (jobPtr) { + if (hasActiveSearchJob()) { jobPtr->abort(); searchState = ResetRequested; return; - } else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; } + beginResetModel(); + modpacks.clear(); + endResetModel(); + searchState = None; + nextSearchOffset = 0; performPaginatedSearch(); } void Flame::ListModel::searchRequestFinished() { - jobPtr.reset(); + if (hasActiveSearchJob()) + return; QJsonParseError parse_error; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); @@ -246,6 +268,25 @@ void Flame::ListModel::searchRequestFinished() endInsertRows(); } +void Flame::ListModel::searchRequestForOneSucceeded(QJsonDocument& doc) +{ + jobPtr.reset(); + + auto packObj = Json::ensureObject(doc.object(), "data"); + + Flame::IndexedPack pack; + try { + Flame::loadIndexedPack(pack, packObj); + } catch (const JSONValidationError& e) { + qWarning() << "Error while loading pack from CurseForge: " << e.cause(); + return; + } + + beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1); + modpacks.append({ pack }); + endInsertRows(); +} + void Flame::ListModel::searchRequestFailed(QString reason) { jobPtr.reset(); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index b3bc96b8c..cd73fce30 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -40,6 +40,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term, const int sort); + [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + private slots: void performPaginatedSearch(); @@ -48,6 +50,7 @@ class ListModel : public QAbstractListModel { void searchRequestFinished(); void searchRequestFailed(QString reason); + void searchRequestForOneSucceeded(QJsonDocument&); private: void requestLogo(QString file, QString url); @@ -63,7 +66,7 @@ class ListModel : public QAbstractListModel { int currentSort = 0; int nextSearchOffset = 0; enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; - NetJob::Ptr jobPtr; + Task::Ptr jobPtr; std::shared_ptr response = std::make_shared(); }; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 183e16f90..79fcc8211 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -61,6 +61,11 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(paren ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); + m_search_timer.setSingleShot(true); + + connect(&m_search_timer, &QTimer::timeout, this, &FlamePage::triggerSearch); + // index is used to set the sorting with the curseforge api ui->sortByBox->addItem(tr("Sort by Featured")); ui->sortByBox->addItem(tr("Sort by Popularity")); @@ -90,6 +95,11 @@ bool FlamePage::eventFilter(QObject* watched, QEvent* event) triggerSearch(); keyEvent->accept(); return true; + } else { + if (m_search_timer.isActive()) + m_search_timer.stop(); + + m_search_timer.start(350); } } return QWidget::eventFilter(watched, event); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index ff5c79750..a45c9e404 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -39,7 +39,7 @@ #include #include -#include "tasks/Task.h" +#include #include "ui/pages/BasePage.h" namespace Ui { @@ -86,4 +86,7 @@ class FlamePage : public QWidget, public BasePage { Flame::IndexedPack current; int m_selected_version_index = -1; + + // Used to do instant searching with a delay to cache quick changes + QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp index 5c9ff63b2..d3ead0837 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp @@ -17,6 +17,7 @@ */ #include "ImportFTBPage.h" +#include "ui/widgets/ProjectItem.h" #include "ui_ImportFTBPage.h" #include @@ -32,17 +33,30 @@ ImportFTBPage::ImportFTBPage(NewInstanceDialog* dialog, QWidget* parent) : QWidg ui->setupUi(this); { + currentModel = new FilterModel(this); listModel = new ListModel(this); + currentModel->setSourceModel(listModel); - ui->modpackList->setModel(listModel); + ui->modpackList->setModel(currentModel); ui->modpackList->setSortingEnabled(true); ui->modpackList->header()->hide(); ui->modpackList->setIndentation(0); ui->modpackList->setIconSize(QSize(42, 42)); + + for (int i = 0; i < currentModel->getAvailableSortings().size(); i++) { + ui->sortByBox->addItem(currentModel->getAvailableSortings().keys().at(i)); + } + + ui->sortByBox->setCurrentText(currentModel->translateCurrentSorting()); } connect(ui->modpackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &ImportFTBPage::onPublicPackSelectionChanged); + connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &ImportFTBPage::onSortingSelectionChanged); + + connect(ui->searchEdit, &QLineEdit::textChanged, this, &ImportFTBPage::triggerSearch); + + ui->modpackList->setItemDelegate(new ProjectItemDelegate(this)); ui->modpackList->selectionModel()->reset(); } @@ -86,7 +100,7 @@ void ImportFTBPage::onPublicPackSelectionChanged(QModelIndex now, QModelIndex pr onPackSelectionChanged(); return; } - Modpack selectedPack = listModel->data(now, Qt::UserRole).value(); + Modpack selectedPack = currentModel->data(now, Qt::UserRole).value(); onPackSelectionChanged(&selectedPack); } @@ -101,4 +115,15 @@ void ImportFTBPage::onPackSelectionChanged(Modpack* pack) dialog->setSuggestedPack(); } +void ImportFTBPage::onSortingSelectionChanged(QString sort) +{ + FilterModel::Sorting toSet = currentModel->getAvailableSortings().value(sort); + currentModel->setSorting(toSet); +} + +void ImportFTBPage::triggerSearch() +{ + currentModel->setSearchTerm(ui->searchEdit->text()); +} + } // namespace FTBImportAPP diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h index 54c49f7b7..8e9661272 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h @@ -53,12 +53,15 @@ class ImportFTBPage : public QWidget, public BasePage { void suggestCurrent(); void onPackSelectionChanged(Modpack* pack = nullptr); private slots: + void onSortingSelectionChanged(QString data); void onPublicPackSelectionChanged(QModelIndex first, QModelIndex second); + void triggerSearch(); private: bool initialized = false; Modpack selected; ListModel* listModel = nullptr; + FilterModel* currentModel = nullptr; NewInstanceDialog* dialog = nullptr; Ui::ImportFTBPage* ui = nullptr; diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui index 32d548b0d..5e09fb6d1 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui @@ -10,8 +10,8 @@ 1011 - - + + @@ -21,6 +21,54 @@ + + + + + + Search and filter... + + + true + + + + + + + Search + + + + + + + + + + + + 265 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp index dc78f451c..134bdc0c3 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp @@ -23,7 +23,9 @@ #include #include #include "FileSystem.h" +#include "StringUtils.h" #include "modplatform/import_ftb/PackHelpers.h" +#include "ui/widgets/ProjectItem.h" namespace FTBImportAPP { @@ -71,18 +73,99 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } auto pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name; - } else if (role == Qt::DecorationRole) { - return pack.icon; - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; - } else if (role == Qt::ToolTipRole) { - return tr("Minecraft %1").arg(pack.mcVersion); + if (role == Qt::ToolTipRole) { } - return QVariant(); + switch (role) { + case Qt::ToolTipRole: + return tr("Minecraft %1").arg(pack.mcVersion); + case Qt::DecorationRole: + return pack.icon; + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return tr("Minecraft %1").arg(pack.mcVersion); + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; + } + + return {}; +} + +FilterModel::FilterModel(QObject* parent) : QSortFilterProxyModel(parent) +{ + currentSorting = Sorting::ByGameVersion; + sortings.insert(tr("Sort by Name"), Sorting::ByName); + sortings.insert(tr("Sort by Game Version"), Sorting::ByGameVersion); +} + +bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const +{ + Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value(); + Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value(); + + if (currentSorting == Sorting::ByGameVersion) { + Version lv(leftPack.mcVersion); + Version rv(rightPack.mcVersion); + return lv < rv; + + } else if (currentSorting == Sorting::ByName) { + return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0; + } + + // UHM, some inavlid value set?! + qWarning() << "Invalid sorting set!"; + return true; +} + +bool FilterModel::filterAcceptsRow([[maybe_unused]] int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const +{ + if (searchTerm.isEmpty()) { + return true; + } + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + Modpack pack = sourceModel()->data(index, Qt::UserRole).value(); + return pack.name.contains(searchTerm, Qt::CaseInsensitive); +} + +void FilterModel::setSearchTerm(const QString term) +{ + searchTerm = term.trimmed(); + invalidate(); +} + +const QMap FilterModel::getAvailableSortings() +{ + return sortings; +} + +QString FilterModel::translateCurrentSorting() +{ + return sortings.key(currentSorting); +} + +void FilterModel::setSorting(Sorting s) +{ + currentSorting = s; + invalidate(); +} + +FilterModel::Sorting FilterModel::getCurrentSorting() +{ + return currentSorting; } } // namespace FTBImportAPP \ No newline at end of file diff --git a/launcher/ui/pages/modplatform/import_ftb/ListModel.h b/launcher/ui/pages/modplatform/import_ftb/ListModel.h index c67aa8963..111928276 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ListModel.h +++ b/launcher/ui/pages/modplatform/import_ftb/ListModel.h @@ -20,11 +20,33 @@ #include #include +#include #include #include "modplatform/import_ftb/PackHelpers.h" namespace FTBImportAPP { +class FilterModel : public QSortFilterProxyModel { + Q_OBJECT + public: + FilterModel(QObject* parent = Q_NULLPTR); + enum Sorting { ByName, ByGameVersion }; + const QMap getAvailableSortings(); + QString translateCurrentSorting(); + void setSorting(Sorting sorting); + Sorting getCurrentSorting(); + void setSearchTerm(QString term); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; + + private: + QMap sortings; + Sorting currentSorting; + QString searchTerm; +}; + class ListModel : public QAbstractListModel { Q_OBJECT diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 356d919d9..49666cf6e 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -41,6 +41,7 @@ #include #include "StringUtils.h" +#include "ui/widgets/ProjectItem.h" #include #include @@ -79,7 +80,20 @@ bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) co bool FilterModel::filterAcceptsRow([[maybe_unused]] int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const { - return true; + if (searchTerm.isEmpty()) { + return true; + } + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + Modpack pack = sourceModel()->data(index, Qt::UserRole).value(); + if (searchTerm.startsWith("#")) + return pack.packCode == searchTerm.mid(1); + return pack.name.contains(searchTerm, Qt::CaseInsensitive); +} + +void FilterModel::setSearchTerm(const QString term) +{ + searchTerm = term.trimmed(); + invalidate(); } const QMap FilterModel::getAvailableSortings() @@ -139,39 +153,57 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } Modpack pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name + "\n" + translatePackType(pack.type); - } else if (role == Qt::ToolTipRole) { - if (pack.description.length() > 100) { - // some magic to prevent to long tooltips and replace html linebreaks - QString edit = pack.description.left(97); - edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); - return edit; + switch (role) { + case Qt::ToolTipRole: { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks + QString edit = pack.description.left(97); + edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); + return edit; + } + return pack.description; } - return pack.description; - } else if (role == Qt::DecorationRole) { - if (m_logoMap.contains(pack.logo)) { - return (m_logoMap.value(pack.logo)); + case Qt::DecorationRole: { + if (m_logoMap.contains(pack.logo)) { + return (m_logoMap.value(pack.logo)); + } + QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + ((ListModel*)this)->requestLogo(pack.logo); + return icon; } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel*)this)->requestLogo(pack.logo); - return icon; - } else if (role == Qt::ForegroundRole) { - if (pack.broken) { - // FIXME: Hardcoded color - return QColor(255, 0, 50); - } else if (pack.bugged) { - // FIXME: Hardcoded color - // bugged pack, currently only indicates bugged xml - return QColor(244, 229, 66); + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; } - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; + case Qt::ForegroundRole: { + if (pack.broken) { + // FIXME: Hardcoded color + return QColor(255, 0, 50); + } else if (pack.bugged) { + // FIXME: Hardcoded color + // bugged pack, currently only indicates bugged xml + return QColor(244, 229, 66); + } + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return pack.description; + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; } - return QVariant(); + return {}; } void ListModel::fill(ModpackList modpacks_) diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h index 51a58d991..c802a4b56 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h @@ -25,6 +25,7 @@ class FilterModel : public QSortFilterProxyModel { QString translateCurrentSorting(); void setSorting(Sorting sorting); Sorting getCurrentSorting(); + void setSearchTerm(QString term); protected: bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; @@ -33,6 +34,7 @@ class FilterModel : public QSortFilterProxyModel { private: QMap sortings; Sorting currentSorting; + QString searchTerm; }; class ListModel : public QAbstractListModel { diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index 0103bbaa2..4104f1391 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -35,6 +35,7 @@ */ #include "Page.h" +#include "ui/widgets/ProjectItem.h" #include "ui_Page.h" #include @@ -110,6 +111,8 @@ Page::Page(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &Page::onSortingSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &Page::onVersionSelectionItemChanged); + connect(ui->searchEdit, &QLineEdit::textChanged, this, &Page::triggerSearch); + connect(ui->publicPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPublicPackSelectionChanged); connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onThirdPartyPackSelectionChanged); connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPrivatePackSelectionChanged); @@ -125,6 +128,9 @@ Page::Page(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog ui->thirdPartyPackList->selectionModel()->reset(); ui->privatePackList->selectionModel()->reset(); + ui->publicPackList->setItemDelegate(new ProjectItemDelegate(this)); + ui->thirdPartyPackList->setItemDelegate(new ProjectItemDelegate(this)); + ui->privatePackList->setItemDelegate(new ProjectItemDelegate(this)); onTabChanged(ui->tabWidget->currentIndex()); } @@ -319,6 +325,8 @@ void Page::onTabChanged(int tab) currentModpackInfo = ui->publicPackDescription; } + triggerSearch(); + currentList->selectionModel()->reset(); QModelIndex idx = currentList->currentIndex(); if (idx.isValid()) { @@ -358,4 +366,9 @@ void Page::onRemovePackClicked() onPackSelectionChanged(); } +void Page::triggerSearch() +{ + currentModel->setSearchTerm(ui->searchEdit->text()); +} + } // namespace LegacyFTB diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index a12b0745d..4d317b7c0 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -43,7 +43,6 @@ #include "QObjectPtr.h" #include "modplatform/legacy_ftb/PackFetchTask.h" #include "modplatform/legacy_ftb/PackHelpers.h" -#include "tasks/Task.h" #include "ui/pages/BasePage.h" class NewInstanceDialog; @@ -56,8 +55,6 @@ class Page; class ListModel; class FilterModel; -class PrivatePackListModel; -class PrivatePackFilterModel; class PrivatePackManager; class Page : public QWidget, public BasePage { @@ -98,6 +95,8 @@ class Page : public QWidget, public BasePage { void onAddPackClicked(); void onRemovePackClicked(); + void triggerSearch(); + private: FilterModel* currentModel = nullptr; QTreeView* currentList = nullptr; diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.ui b/launcher/ui/pages/modplatform/legacy_ftb/Page.ui index ad08dc255..56cba7485 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.ui +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.ui @@ -10,8 +10,29 @@ 602 - - + + + + + + + Search and filter... + + + true + + + + + + + Search + + + + + + 0 @@ -36,9 +57,9 @@ - - true - + + true + @@ -50,10 +71,10 @@ - - true - - + + true + + @@ -104,16 +125,16 @@ - - true - - + + true + + - + diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index ebc5556c6..16949ebae 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -38,8 +38,8 @@ #include "BuildConfig.h" #include "Json.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" +#include "modplatform/modrinth/ModrinthAPI.h" +#include "net/NetJob.h" #include "ui/widgets/ProjectItem.h" #include "net/ApiDownload.h" @@ -130,7 +130,28 @@ bool ModpackListModel::setData(const QModelIndex& index, const QVariant& value, void ModpackListModel::performPaginatedSearch() { - // TODO: Move to standalone API + if (hasActiveSearchJob()) + return; + + if (currentSearchTerm.startsWith("#")) { + auto projectId = currentSearchTerm.removeFirst(); + if (!projectId.isEmpty()) { + ResourceAPI::ProjectInfoCallbacks callbacks; + + // Use defaults if no callbacks are set + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + + if (!callbacks.on_succeed) + callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + static const ModrinthAPI api; + if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { + jobPtr = job; + jobPtr->start(); + } + return; + } + } // TODO: Move to standalone API auto netJob = makeShared("Modrinth::SearchModpack", APPLICATION->network()); auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL + "/search?" @@ -167,16 +188,17 @@ void ModpackListModel::performPaginatedSearch() void ModpackListModel::refresh() { - if (jobPtr) { + if (hasActiveSearchJob()) { jobPtr->abort(); searchState = ResetRequested; return; - } else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; } + + beginResetModel(); + modpacks.clear(); + endResetModel(); + searchState = None; + nextSearchOffset = 0; performPaginatedSearch(); } @@ -307,9 +329,29 @@ void ModpackListModel::searchRequestFinished(QJsonDocument& doc_all) endInsertRows(); } +void ModpackListModel::searchRequestForOneSucceeded(QJsonDocument& doc) +{ + jobPtr.reset(); + + auto packObj = doc.object(); + + Modrinth::Modpack pack; + try { + Modrinth::loadIndexedPack(pack, packObj); + pack.id = Json::ensureString(packObj, "id", pack.id); + } catch (const JSONValidationError& e) { + qWarning() << "Error while loading mod from " << m_parent->debugName() << ": " << e.cause(); + return; + } + + beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1); + modpacks.append({ pack }); + endInsertRows(); +} + void ModpackListModel::searchRequestFailed(QString reason) { - auto failed_action = jobPtr->getFailedActions().at(0); + auto failed_action = dynamic_cast(jobPtr.get())->getFailedActions().at(0); if (!failed_action->m_reply) { // Network error QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load modpacks.")); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index 721c69f55..f5e686a80 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -73,6 +73,8 @@ class ModpackListModel : public QAbstractListModel { void refresh(); void searchWithTerm(const QString& term, const int sort); + [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); inline auto canFetchMore(const QModelIndex& parent) const -> bool override @@ -83,6 +85,7 @@ class ModpackListModel : public QAbstractListModel { public slots: void searchRequestFinished(QJsonDocument& doc_all); void searchRequestFailed(QString reason); + void searchRequestForOneSucceeded(QJsonDocument&); protected slots: @@ -111,7 +114,7 @@ class ModpackListModel : public QAbstractListModel { int nextSearchOffset = 0; enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; - NetJob::Ptr jobPtr; + Task::Ptr jobPtr; std::shared_ptr m_all_response = std::make_shared(); QByteArray m_specific_response; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 41fd5003f..72c9da358 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -64,6 +64,11 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); + m_search_timer.setSingleShot(true); + + connect(&m_search_timer, &QTimer::timeout, this, &ModrinthPage::triggerSearch); + ui->sortByBox->addItem(tr("Sort by Relevance")); ui->sortByBox->addItem(tr("Sort by Total Downloads")); ui->sortByBox->addItem(tr("Sort by Follows")); @@ -102,6 +107,11 @@ bool ModrinthPage::eventFilter(QObject* watched, QEvent* event) this->triggerSearch(); keyEvent->accept(); return true; + } else { + if (m_search_timer.isActive()) + m_search_timer.stop(); + + m_search_timer.start(350); } } return QObject::eventFilter(watched, event); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index b7054c886..0705ca99b 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -42,6 +42,7 @@ #include "modplatform/modrinth/ModrinthPackManifest.h" +#include #include namespace Ui { @@ -88,4 +89,7 @@ class ModrinthPage : public QWidget, public BasePage { Modrinth::Modpack current; QString selectedVersion; + + // Used to do instant searching with a delay to cache quick changes + QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index e8c5ac922..3cd1d9a2d 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -39,6 +39,7 @@ #include "Json.h" #include "net/ApiDownload.h" +#include "ui/widgets/ProjectItem.h" #include @@ -54,21 +55,47 @@ QVariant Technic::ListModel::data(const QModelIndex& index, int role) const } Modpack pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name; - } else if (role == Qt::DecorationRole) { - if (m_logoMap.contains(pack.logoName)) { - return (m_logoMap.value(pack.logoName)); + switch (role) { + case Qt::ToolTipRole: { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks + QString edit = pack.description.left(97); + edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); + return edit; + } + return pack.description; } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); - return icon; - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; + case Qt::DecorationRole: { + if (m_logoMap.contains(pack.logoName)) { + return (m_logoMap.value(pack.logoName)); + } + QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); + return icon; + } + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return pack.description; + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; } - return QVariant(); + + return {}; } int Technic::ListModel::columnCount(const QModelIndex& parent) const @@ -87,21 +114,25 @@ void Technic::ListModel::searchWithTerm(const QString& term) return; } currentSearchTerm = term; - if (jobPtr) { + if (hasActiveSearchJob()) { jobPtr->abort(); searchState = ResetRequested; return; - } else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; } + + beginResetModel(); + modpacks.clear(); + endResetModel(); + searchState = None; + performSearch(); } void Technic::ListModel::performSearch() { + if (hasActiveSearchJob()) + return; + auto netJob = makeShared("Technic::Search", APPLICATION->network()); QString searchUrl = ""; if (currentSearchTerm.isEmpty()) { @@ -113,6 +144,9 @@ void Technic::ListModel::performSearch() } else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) { searchUrl = QString("%1?build=%2").arg(currentSearchTerm, BuildConfig.TECHNIC_API_BUILD); searchMode = Single; + } else if (currentSearchTerm.startsWith("#")) { + searchUrl = QString("https://api.technicpack.net/modpack/%1?build=%2").arg(currentSearchTerm.mid(1), BuildConfig.TECHNIC_API_BUILD); + searchMode = Single; } else { searchUrl = QString("%1search?build=%2&q=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index d7a635d41..c0d13ae82 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -58,6 +58,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term); + [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + private slots: void searchRequestFinished(); void searchRequestFailed(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 54b86feba..518d049e8 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -34,6 +34,7 @@ */ #include "TechnicPage.h" +#include "ui/widgets/ProjectItem.h" #include "ui_TechnicPage.h" #include @@ -59,8 +60,15 @@ TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(p model = new Technic::ListModel(this); ui->packView->setModel(model); + m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); + m_search_timer.setSingleShot(true); + + connect(&m_search_timer, &QTimer::timeout, this, &TechnicPage::triggerSearch); + connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &TechnicPage::onSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &TechnicPage::onVersionSelectionChanged); + + ui->packView->setItemDelegate(new ProjectItemDelegate(this)); } bool TechnicPage::eventFilter(QObject* watched, QEvent* event) @@ -71,6 +79,11 @@ bool TechnicPage::eventFilter(QObject* watched, QEvent* event) triggerSearch(); keyEvent->accept(); return true; + } else { + if (m_search_timer.isActive()) + m_search_timer.stop(); + + m_search_timer.start(350); } } return QWidget::eventFilter(watched, event); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 91b61eaf2..1e36fbd31 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -35,12 +35,12 @@ #pragma once +#include #include #include #include "TechnicData.h" #include "net/NetJob.h" -#include "tasks/Task.h" #include "ui/pages/BasePage.h" namespace Ui { @@ -91,4 +91,7 @@ class TechnicPage : public QWidget, public BasePage { NetJob::Ptr jobPtr; std::shared_ptr response = std::make_shared(); + + // Used to do instant searching with a delay to cache quick changes + QTimer m_search_timer; }; diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index 1481c1b6b..60b92b28b 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -34,8 +34,8 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o icon_width = icon_size.width(); icon_height = icon_size.height(); - icon_x_margin = (rect.height() - icon_width) / 2; icon_y_margin = (rect.height() - icon_height) / 2; + icon_x_margin = icon_y_margin; // use same margins for consistency } // Centralize icon with a margin to separate from the other elements From 4c52b18bdd3112b5e92de61860fd8eff8ecdde9b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 20:19:51 +0300 Subject: [PATCH 06/36] replaced removeFirst with mid Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourceModel.cpp | 2 +- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 96803531b..74c1d2171 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -133,7 +133,7 @@ void ResourceModel::search() return; if (m_search_term.startsWith("#")) { - auto projectId = m_search_term.removeFirst(); + auto projectId = m_search_term.mid(1); if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index e488f0787..e4388c246 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -164,7 +164,7 @@ void ListModel::fetchMore(const QModelIndex& parent) void ListModel::performPaginatedSearch() { if (currentSearchTerm.startsWith("#")) { - auto projectId = currentSearchTerm.removeFirst(); + auto projectId = currentSearchTerm.mid(1); if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 16949ebae..36a1c47a9 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -134,7 +134,7 @@ void ModpackListModel::performPaginatedSearch() return; if (currentSearchTerm.startsWith("#")) { - auto projectId = currentSearchTerm.removeFirst(); + auto projectId = currentSearchTerm.mid(1); if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; From 58efd3e9e27e09d55dac1d185f8de81cf2121f23 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 21:43:57 +0300 Subject: [PATCH 07/36] fixed code scaning Signed-off-by: Trial97 --- launcher/modplatform/ResourceAPI.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index bd0d2824f..8af5ebd14 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -108,7 +108,7 @@ class ResourceAPI { void operator=(ProjectInfoArgs other) { pack = other.pack; } }; struct ProjectInfoCallbacks { - std::function on_succeed; + std::function on_succeed; std::function on_fail; std::function on_abort; }; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 74c1d2171..018721f94 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -152,7 +152,7 @@ void ResourceModel::search() }; if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto pack) { + callbacks.on_succeed = [this](auto& doc, auto& pack) { if (!s_running_models.constFind(this).value()) return; searchRequestForOneSucceeded(doc); @@ -219,9 +219,10 @@ void ResourceModel::loadEntry(QModelIndex& entry) // Use default if no callbacks are set if (!callbacks.on_succeed) - callbacks.on_succeed = [this, entry](auto& doc, auto pack) { + callbacks.on_succeed = [this, entry](auto& doc, auto& newpack) { if (!s_running_models.constFind(this).value()) return; + auto pack = newpack; infoRequestSucceeded(doc, pack, entry); }; if (!callbacks.on_fail) From 05094b7382aafc0a9dcda17c13d5294dbaa89c36 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 22:24:30 +0300 Subject: [PATCH 08/36] more fixes Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index e4388c246..17875a604 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -173,7 +173,7 @@ void ListModel::performPaginatedSearch() callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const FlameAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 36a1c47a9..efb1fe44e 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -143,7 +143,7 @@ void ModpackListModel::performPaginatedSearch() callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const ModrinthAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; From 4036cecfc02142c403a45e18474ad7aab6fc8834 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Aug 2023 15:04:42 +0300 Subject: [PATCH 09/36] Added progress widget to some modpack providers Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlameModel.h | 1 + launcher/ui/pages/modplatform/flame/FlamePage.cpp | 10 +++++++++- launcher/ui/pages/modplatform/flame/FlamePage.h | 3 +++ launcher/ui/pages/modplatform/flame/FlamePage.ui | 4 ++-- launcher/ui/pages/modplatform/modrinth/ModrinthModel.h | 1 + .../ui/pages/modplatform/modrinth/ModrinthPage.cpp | 10 +++++++++- launcher/ui/pages/modplatform/modrinth/ModrinthPage.h | 3 +++ launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui | 10 +++++----- launcher/ui/pages/modplatform/technic/TechnicModel.h | 1 + launcher/ui/pages/modplatform/technic/TechnicPage.cpp | 10 +++++++++- launcher/ui/pages/modplatform/technic/TechnicPage.h | 3 +++ launcher/ui/pages/modplatform/technic/TechnicPage.ui | 4 ++-- 12 files changed, 48 insertions(+), 12 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index cd73fce30..fd8496dfb 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -41,6 +41,7 @@ class ListModel : public QAbstractListModel { void searchWithTerm(const QString& term, const int sort); [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: void performPaginatedSearch(); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 79fcc8211..50656f427 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -50,7 +50,8 @@ static FlameAPI api; -FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog) +FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) + : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog), m_fetch_progress(this, false) { ui->setupUi(this); connect(ui->searchButton, &QPushButton::clicked, this, &FlamePage::triggerSearch); @@ -66,6 +67,12 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(paren connect(&m_search_timer, &QTimer::timeout, this, &FlamePage::triggerSearch); + m_fetch_progress.hideIfInactive(true); + m_fetch_progress.setFixedHeight(24); + m_fetch_progress.progressFormat(""); + + ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount()); + // index is used to set the sorting with the curseforge api ui->sortByBox->addItem(tr("Sort by Featured")); ui->sortByBox->addItem(tr("Sort by Popularity")); @@ -124,6 +131,7 @@ void FlamePage::openedImpl() void FlamePage::triggerSearch() { listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); + m_fetch_progress.watch(listModel->activeSearchJob().get()); } void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index a45c9e404..d35858fbc 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -41,6 +41,7 @@ #include #include #include "ui/pages/BasePage.h" +#include "ui/widgets/ProgressWidget.h" namespace Ui { class FlamePage; @@ -87,6 +88,8 @@ class FlamePage : public QWidget, public BasePage { int m_selected_version_index = -1; + ProgressWidget m_fetch_progress; + // Used to do instant searching with a delay to cache quick changes QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.ui b/launcher/ui/pages/modplatform/flame/FlamePage.ui index 71d195135..f9e1fe67f 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.ui +++ b/launcher/ui/pages/modplatform/flame/FlamePage.ui @@ -47,7 +47,7 @@
- + @@ -77,7 +77,7 @@ - + diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index f5e686a80..2a9d62261 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -74,6 +74,7 @@ class ModpackListModel : public QAbstractListModel { void searchWithTerm(const QString& term, const int sort); [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 72c9da358..f7fa8fd78 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -52,7 +52,8 @@ #include #include -ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog) +ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) + : QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog), m_fetch_progress(this, false) { ui->setupUi(this); @@ -69,6 +70,12 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget connect(&m_search_timer, &QTimer::timeout, this, &ModrinthPage::triggerSearch); + m_fetch_progress.hideIfInactive(true); + m_fetch_progress.setFixedHeight(24); + m_fetch_progress.progressFormat(""); + + ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount()); + ui->sortByBox->addItem(tr("Sort by Relevance")); ui->sortByBox->addItem(tr("Sort by Total Downloads")); ui->sortByBox->addItem(tr("Sort by Follows")); @@ -319,6 +326,7 @@ void ModrinthPage::suggestCurrent() void ModrinthPage::triggerSearch() { m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); + m_fetch_progress.watch(m_model->activeSearchJob().get()); } void ModrinthPage::onVersionSelectionChanged(QString version) diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 0705ca99b..4240dcafb 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -41,6 +41,7 @@ #include "ui/pages/BasePage.h" #include "modplatform/modrinth/ModrinthPackManifest.h" +#include "ui/widgets/ProgressWidget.h" #include #include @@ -90,6 +91,8 @@ class ModrinthPage : public QWidget, public BasePage { Modrinth::Modpack current; QString selectedVersion; + ProgressWidget m_fetch_progress; + // Used to do instant searching with a delay to cache quick changes QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui index 6d8b2b675..78a25feae 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui @@ -10,8 +10,8 @@ 600 - - + + @@ -29,7 +29,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -77,7 +77,7 @@ - + diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index c0d13ae82..aeb4f3084 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -59,6 +59,7 @@ class ListModel : public QAbstractListModel { void searchWithTerm(const QString& term); [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: void searchRequestFinished(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 518d049e8..190b7c68f 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -52,7 +52,8 @@ #include "net/ApiDownload.h" -TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog) +TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) + : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog), m_fetch_progress(this, false) { ui->setupUi(this); connect(ui->searchButton, &QPushButton::clicked, this, &TechnicPage::triggerSearch); @@ -65,6 +66,12 @@ TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(p connect(&m_search_timer, &QTimer::timeout, this, &TechnicPage::triggerSearch); + m_fetch_progress.hideIfInactive(true); + m_fetch_progress.setFixedHeight(24); + m_fetch_progress.progressFormat(""); + + ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount()); + connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &TechnicPage::onSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &TechnicPage::onVersionSelectionChanged); @@ -113,6 +120,7 @@ void TechnicPage::openedImpl() void TechnicPage::triggerSearch() { model->searchWithTerm(ui->searchEdit->text()); + m_fetch_progress.watch(model->activeSearchJob().get()); } void TechnicPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex second) diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 1e36fbd31..01439337d 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -42,6 +42,7 @@ #include "TechnicData.h" #include "net/NetJob.h" #include "ui/pages/BasePage.h" +#include "ui/widgets/ProgressWidget.h" namespace Ui { class TechnicPage; @@ -92,6 +93,8 @@ class TechnicPage : public QWidget, public BasePage { NetJob::Ptr jobPtr; std::shared_ptr response = std::make_shared(); + ProgressWidget m_fetch_progress; + // Used to do instant searching with a delay to cache quick changes QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.ui b/launcher/ui/pages/modplatform/technic/TechnicPage.ui index 15bf645fb..b988eda2b 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.ui +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.ui @@ -11,7 +11,7 @@ - + @@ -44,7 +44,7 @@ - + From 8c607ae7348206c29a8a8ce5e2db421138bd89ff Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Aug 2023 20:02:12 +0300 Subject: [PATCH 10/36] removed extra if Signed-off-by: Trial97 --- .../ui/pages/modplatform/ResourceModel.cpp | 34 ++++++++----------- .../ui/pages/modplatform/flame/FlameModel.cpp | 8 ++--- .../modplatform/modrinth/ModrinthModel.cpp | 8 ++--- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 018721f94..cb8f1920f 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -137,26 +137,22 @@ void ResourceModel::search() if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; - // Use defaults if no callbacks are set - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { - if (!s_running_models.constFind(this).value()) - return; - searchRequestFailed(reason, -1); - }; - if (!callbacks.on_abort) - callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) - return; - searchRequestAborted(); - }; + callbacks.on_fail = [this](QString reason) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestFailed(reason, -1); + }; + callbacks.on_abort = [this] { + if (!s_running_models.constFind(this).value()) + return; + searchRequestAborted(); + }; - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto& pack) { - if (!s_running_models.constFind(this).value()) - return; - searchRequestForOneSucceeded(doc); - }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestForOneSucceeded(doc); + }; if (auto job = m_api->getProjectInfo({ projectId }, std::move(callbacks)); job) runSearchJob(job); return; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 17875a604..8875a9452 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -168,12 +168,8 @@ void ListModel::performPaginatedSearch() if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; - // Use defaults if no callbacks are set - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; - - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const FlameAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index efb1fe44e..f691a185d 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -138,12 +138,8 @@ void ModpackListModel::performPaginatedSearch() if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; - // Use defaults if no callbacks are set - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; - - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const ModrinthAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; From 07d8598638247d8dfb2fcd2e38c4498e90570f6e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Aug 2023 23:40:32 +0300 Subject: [PATCH 11/36] added catpacks tests Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 10 +++-- launcher/ui/themes/CatPack.h | 9 ++-- tests/CMakeLists.txt | 3 ++ tests/CatPack_test.cpp | 77 ++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 tests/CatPack_test.cpp diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index f0d8ddd55..bbcb58bc8 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -99,18 +99,22 @@ QDate ensureDay(int year, int month, int day) QString JsonCatPack::path() { - const QDate now = QDate::currentDate(); + return path(QDate::currentDate()); +} + +QString JsonCatPack::path(QDate now) +{ for (auto var : m_variants) { QDate startDate = ensureDay(now.year(), var.startTime.month, var.startTime.day); QDate endDate = ensureDay(now.year(), var.endTime.month, var.endTime.day); if (startDate > endDate) { // it's spans over multiple years - if (endDate <= now) // end date is in the past so jump one year into the future for endDate + if (endDate < now) // end date is in the past so jump one year into the future for endDate endDate = endDate.addYears(1); else // end date is in the future so jump one year into the past for startDate startDate = startDate.addYears(-1); } - if (startDate >= now && now >= endDate) + if (startDate <= now && now <= endDate) return var.path; } return m_defaultPath; diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index fdd117a7f..1d310e796 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -52,9 +52,9 @@ class BasicCatPack : public CatPack { public: BasicCatPack(QString id, QString name) : m_id(id), m_name(name) {} BasicCatPack(QString id) : BasicCatPack(id, id) {} - virtual QString id() { return m_id; } - virtual QString name() { return m_name; } - virtual QString path(); + virtual QString id() override { return m_id; } + virtual QString name() override { return m_name; } + virtual QString path() override; protected: QString m_id; @@ -83,7 +83,8 @@ class JsonCatPack : public BasicCatPack { PartialDate endTime; }; JsonCatPack(QFileInfo& manifestInfo); - virtual QString path(); + virtual QString path() override; + QString path(QDate now); private: QString m_defaultPath; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a26a49fec..1a49fd700 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,3 +56,6 @@ ecm_add_test(Index_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}: ecm_add_test(Version_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME Version) + +ecm_add_test(CatPack_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test + TEST_NAME CatPack) \ No newline at end of file diff --git a/tests/CatPack_test.cpp b/tests/CatPack_test.cpp new file mode 100644 index 000000000..a84ba6511 --- /dev/null +++ b/tests/CatPack_test.cpp @@ -0,0 +1,77 @@ +#include + +#include +#include +#include +#include +#include "FileSystem.h" +#include "ui/themes/CatPack.h" + +class CatPackTest : public QObject { + Q_OBJECT + private slots: + void test_catPack() + { + QString fileContent = R"({ + "name": "My Cute Cat", + "default": "maxwell.png", + "variants": [ + { + "startTime": { "day": 12, "month": 4 }, + "endTime": { "day": 12, "month": 4 }, + "path": "oneDay.png" + }, + { + "startTime": { "day": 20, "month": 12 }, + "endTime": { "day": 28, "month": 12 }, + "path": "christmas.png" + }, + { + "startTime": { "day": 30, "month": 12 }, + "endTime": { "day": 1, "month": 1 }, + "path": "newyear2.png" + }, + { + "startTime": { "day": 28, "month": 12 }, + "endTime": { "day": 3, "month": 1 }, + "path": "newyear.png" + } + ] +})"; +#if defined(Q_OS_WIN) + QString fileName = "test_SaveAlreadyExistingFile.ini"; + QFile file(fileName); + QCOMPARE(file.open(QFile::WriteOnly | QFile::Text), true); +#else + QTemporaryFile file; + QCOMPARE(file.open(), true); + QCOMPARE(file.fileName().isEmpty(), false); + QString fileName = file.fileName(); +#endif + QTextStream stream(&file); + stream << fileContent; + file.close(); + auto fileinfo = QFileInfo(fileName); + try { + auto cat = JsonCatPack(fileinfo); + QCOMPARE(cat.path(QDate(2023, 4, 12)), FS::PathCombine(fileinfo.path(), "oneDay.png")); + QCOMPARE(cat.path(QDate(2023, 4, 11)), FS::PathCombine(fileinfo.path(), "maxwell.png")); + QCOMPARE(cat.path(QDate(2023, 4, 13)), FS::PathCombine(fileinfo.path(), "maxwell.png")); + QCOMPARE(cat.path(QDate(2023, 12, 21)), FS::PathCombine(fileinfo.path(), "christmas.png")); + QCOMPARE(cat.path(QDate(2023, 12, 28)), FS::PathCombine(fileinfo.path(), "christmas.png")); + QCOMPARE(cat.path(QDate(2023, 12, 29)), FS::PathCombine(fileinfo.path(), "newyear.png")); + QCOMPARE(cat.path(QDate(2023, 12, 30)), FS::PathCombine(fileinfo.path(), "newyear2.png")); + QCOMPARE(cat.path(QDate(2023, 12, 31)), FS::PathCombine(fileinfo.path(), "newyear2.png")); + QCOMPARE(cat.path(QDate(2024, 1, 1)), FS::PathCombine(fileinfo.path(), "newyear2.png")); + QCOMPARE(cat.path(QDate(2024, 1, 2)), FS::PathCombine(fileinfo.path(), "newyear.png")); + QCOMPARE(cat.path(QDate(2024, 1, 3)), FS::PathCombine(fileinfo.path(), "newyear.png")); + QCOMPARE(cat.path(QDate(2024, 1, 4)), FS::PathCombine(fileinfo.path(), "maxwell.png")); + } catch (const Exception& e) { + QFAIL(e.cause().toLatin1()); + } + } +}; + +QTEST_GUILESS_MAIN(CatPackTest) + +#include "CatPack_test.moc" From 311e36b5d6dfaed449a3bbdada3d2e5b87f2b6d9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 28 Aug 2023 11:52:26 +0300 Subject: [PATCH 12/36] added new line Signed-off-by: Trial97 --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1a49fd700..59e0e3144 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -58,4 +58,4 @@ ecm_add_test(Version_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR TEST_NAME Version) ecm_add_test(CatPack_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test - TEST_NAME CatPack) \ No newline at end of file + TEST_NAME CatPack) From bdc2fca711d3ad110d7ef2a2c1ae99537144a00e Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 28 Aug 2023 10:26:03 +0200 Subject: [PATCH 13/36] refactor(nix): don't instantiate nixpkgs See https://zimbatm.com/notes/1000-instances-of-nixpkgs Signed-off-by: Sefa Eyeoglu --- flake.nix | 14 ++++- nix/default.nix | 31 ---------- nix/distribution.nix | 36 ++++++------ nix/{package.nix => pkg/default.nix} | 0 nix/pkg/wrapper.nix | 86 ++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 49 deletions(-) delete mode 100644 nix/default.nix rename nix/{package.nix => pkg/default.nix} (100%) create mode 100644 nix/pkg/wrapper.nix diff --git a/flake.nix b/flake.nix index c3148fe03..8f31ccec5 100644 --- a/flake.nix +++ b/flake.nix @@ -23,5 +23,17 @@ outputs = inputs: inputs.flake-parts.lib.mkFlake {inherit inputs;} - {imports = [./nix];}; + { + imports = [ + ./nix/dev.nix + ./nix/distribution.nix + ]; + + systems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + }; } diff --git a/nix/default.nix b/nix/default.nix deleted file mode 100644 index 71c95c2cf..000000000 --- a/nix/default.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ - inputs, - self, - ... -}: { - imports = [ - ./dev.nix - ./distribution.nix - ]; - - _module.args = { - # User-friendly version number. - version = builtins.substring 0 8 self.lastModifiedDate; - }; - - perSystem = {system, ...}: { - # Nixpkgs instantiated for supported systems with our overlay. - _module.args.pkgs = import inputs.nixpkgs { - inherit system; - overlays = [self.overlays.default]; - }; - }; - - # Supported systems. - systems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; -} diff --git a/nix/distribution.nix b/nix/distribution.nix index d0904d41d..0dde1e4f0 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -1,30 +1,32 @@ { inputs, self, - version, ... }: { perSystem = {pkgs, ...}: { - packages = { - inherit (pkgs) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher; - default = pkgs.prismlauncher; + packages = let + ourPackages = self.overlays.default pkgs null; + in { + inherit (ourPackages) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher; + default = ourPackages.prismlauncher; }; }; flake = { - overlays.default = final: prev: let - # Helper function to build prism against different versions of Qt. - mkPrism = qt: - qt.callPackage ./package.nix { - inherit (inputs) libnbtplusplus; - inherit (prev.darwin.apple_sdk.frameworks) Cocoa; - inherit self version; - }; - in { - prismlauncher-qt5-unwrapped = mkPrism final.libsForQt5; - prismlauncher-qt5 = prev.prismlauncher-qt5.override {prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped;}; - prismlauncher-unwrapped = mkPrism final.qt6Packages; - prismlauncher = prev.prismlauncher.override {inherit (final) prismlauncher-unwrapped;}; + overlays.default = final: _: let + version = builtins.substring 0 8 self.lastModifiedDate; + + # common args for prismlauncher evaluations + unwrappedArgs = { + inherit (inputs) libnbtplusplus; + inherit (final.darwin.apple_sdk.frameworks) Cocoa; + inherit self version; + }; + in rec { + prismlauncher-qt5-unwrapped = final.libsForQt5.callPackage ./pkg unwrappedArgs; + prismlauncher-qt5 = final.libsForQt5.callPackage ./pkg/wrapper.nix {prismlauncher-unwrapped = prismlauncher-qt5-unwrapped;}; + prismlauncher-unwrapped = final.qt6Packages.callPackage ./pkg unwrappedArgs; + prismlauncher = final.qt6Packages.callPackage ./pkg/wrapper.nix {inherit prismlauncher-unwrapped;}; }; }; } diff --git a/nix/package.nix b/nix/pkg/default.nix similarity index 100% rename from nix/package.nix rename to nix/pkg/default.nix diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix new file mode 100644 index 000000000..3bf5b3f85 --- /dev/null +++ b/nix/pkg/wrapper.nix @@ -0,0 +1,86 @@ +{ + lib, + stdenv, + symlinkJoin, + prismlauncher-unwrapped, + wrapQtAppsHook, + qtbase, # needed for wrapQtAppsHook + qtsvg, + qtwayland, + xorg, + libpulseaudio, + libGL, + glfw, + openal, + jdk8, + jdk17, + gamemode, + flite, + mesa-demos, + msaClientID ? null, + gamemodeSupport ? stdenv.isLinux, + textToSpeechSupport ? stdenv.isLinux, + jdks ? [jdk17 jdk8], + additionalLibs ? [], + additionalPrograms ? [], +}: let + prismlauncherFinal = prismlauncher-unwrapped.override { + inherit msaClientID gamemodeSupport; + }; +in + symlinkJoin { + name = "prismlauncher-${prismlauncherFinal.version}"; + + paths = [prismlauncherFinal]; + + nativeBuildInputs = [ + wrapQtAppsHook + ]; + + buildInputs = + [ + qtbase + qtsvg + ] + ++ lib.optional (lib.versionAtLeast qtbase.version "6" && stdenv.isLinux) qtwayland; + + postBuild = '' + wrapQtAppsHook + ''; + + qtWrapperArgs = let + runtimeLibs = + (with xorg; [ + libX11 + libXext + libXcursor + libXrandr + libXxf86vm + ]) + ++ [ + libpulseaudio + libGL + glfw + openal + stdenv.cc.cc.lib + ] + ++ lib.optional gamemodeSupport gamemode.lib + ++ lib.optional textToSpeechSupport flite + ++ additionalLibs; + + runtimePrograms = + [ + xorg.xrandr + mesa-demos # need glxinfo + ] + ++ additionalPrograms; + in + ["--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}"] + ++ lib.optionals stdenv.isLinux [ + "--set LD_LIBRARY_PATH /run/opengl-driver/lib:${lib.makeLibraryPath runtimeLibs}" + # xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 + "--prefix PATH : ${lib.makeBinPath runtimePrograms}" + ]; + + inherit (prismlauncherFinal) meta; + } From f23a8e4b4b80cff4b2e15fa1783dbf046d2dfc18 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 29 Aug 2023 23:30:10 +0100 Subject: [PATCH 14/36] Enable antialiasing for mod and pack icons Signed-off-by: TheKodeToad --- launcher/minecraft/mod/Mod.cpp | 5 +++-- launcher/minecraft/mod/ResourcePack.cpp | 5 +++-- launcher/minecraft/mod/TexturePack.cpp | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index ae3dea8d8..b59c6d37c 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -246,7 +246,8 @@ void Mod::setIcon(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = + QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; @@ -259,7 +260,7 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size, mode); + return cached_image.scaled(size, mode, Qt::SmoothTransformation); } // No valid image we can get diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index dab0f6d67..2bb51dc5b 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -50,7 +50,8 @@ void ResourcePack::setImage(QImage new_image) const PixmapCache::instance().remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = + QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap); m_pack_image_cache_key.was_ever_used = true; @@ -68,7 +69,7 @@ QPixmap ResourcePack::image(QSize size, Qt::AspectRatioMode mode) const if (PixmapCache::instance().find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size, mode); + return cached_image.scaled(size, mode, Qt::SmoothTransformation); } // No valid image we can get diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp index 7d8c67137..04cc36310 100644 --- a/launcher/minecraft/mod/TexturePack.cpp +++ b/launcher/minecraft/mod/TexturePack.cpp @@ -44,7 +44,8 @@ void TexturePack::setImage(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = + QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; @@ -56,7 +57,7 @@ QPixmap TexturePack::image(QSize size, Qt::AspectRatioMode mode) const if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size, mode); + return cached_image.scaled(size, mode, Qt::SmoothTransformation); } // No valid image we can get From 584e800279351cdd592d1012ca885dd86b9f26f2 Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 30 Aug 2023 11:13:39 -0400 Subject: [PATCH 15/36] fix: remove -Wextra-semi this flag is unavailable on gcc versions < 8. we could detect the version of the compiler here, but i don't think we lose much in this flags removal and this is a simpler option Signed-off-by: seth --- cmake/CompilerWarnings.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 635e54289..69e57b4d5 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -75,7 +75,6 @@ function( set(CLANG_WARNINGS -Wall -Wextra # reasonable and standard - -Wextra-semi # Warn about semicolon after in-class function definition. -Wshadow # warn the user if a variable declaration shadows one from a parent context -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps # catch hard to track down memory errors From 707da5a25a11a8ae6c60f619f37b9fdcb7970082 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 30 Aug 2023 21:59:41 +0200 Subject: [PATCH 16/36] fix(nix): include udev dependency See https://github.com/NixOS/nixpkgs/pull/252425 Signed-off-by: Sefa Eyeoglu --- nix/pkg/wrapper.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 3bf5b3f85..8d160143d 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -17,6 +17,7 @@ gamemode, flite, mesa-demos, + udev, msaClientID ? null, gamemodeSupport ? stdenv.isLinux, textToSpeechSupport ? stdenv.isLinux, @@ -58,11 +59,15 @@ in libXxf86vm ]) ++ [ + # lwjgl libpulseaudio libGL glfw openal stdenv.cc.cc.lib + + # oshi + udev ] ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional textToSpeechSupport flite From 6cfe2dbc50d0dbe53c59012375fcd0cf3a8558a9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 31 Aug 2023 17:34:05 +0300 Subject: [PATCH 17/36] moved catpack data to testdata Signed-off-by: Trial97 --- tests/CatPack_test.cpp | 41 ++---------------------------- tests/testdata/CatPacks/index.json | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 39 deletions(-) create mode 100644 tests/testdata/CatPacks/index.json diff --git a/tests/CatPack_test.cpp b/tests/CatPack_test.cpp index a84ba6511..330d1a814 100644 --- a/tests/CatPack_test.cpp +++ b/tests/CatPack_test.cpp @@ -12,45 +12,8 @@ class CatPackTest : public QObject { private slots: void test_catPack() { - QString fileContent = R"({ - "name": "My Cute Cat", - "default": "maxwell.png", - "variants": [ - { - "startTime": { "day": 12, "month": 4 }, - "endTime": { "day": 12, "month": 4 }, - "path": "oneDay.png" - }, - { - "startTime": { "day": 20, "month": 12 }, - "endTime": { "day": 28, "month": 12 }, - "path": "christmas.png" - }, - { - "startTime": { "day": 30, "month": 12 }, - "endTime": { "day": 1, "month": 1 }, - "path": "newyear2.png" - }, - { - "startTime": { "day": 28, "month": 12 }, - "endTime": { "day": 3, "month": 1 }, - "path": "newyear.png" - } - ] -})"; -#if defined(Q_OS_WIN) - QString fileName = "test_SaveAlreadyExistingFile.ini"; - QFile file(fileName); - QCOMPARE(file.open(QFile::WriteOnly | QFile::Text), true); -#else - QTemporaryFile file; - QCOMPARE(file.open(), true); - QCOMPARE(file.fileName().isEmpty(), false); - QString fileName = file.fileName(); -#endif - QTextStream stream(&file); - stream << fileContent; - file.close(); + auto dataDir = QDir(QFINDTESTDATA("testdata/CatPacks")).absolutePath(); + auto fileName = FS::PathCombine(dataDir, "index.json"); auto fileinfo = QFileInfo(fileName); try { auto cat = JsonCatPack(fileinfo); diff --git a/tests/testdata/CatPacks/index.json b/tests/testdata/CatPacks/index.json new file mode 100644 index 000000000..c55813dbb --- /dev/null +++ b/tests/testdata/CatPacks/index.json @@ -0,0 +1,26 @@ +{ + "name": "My Cute Cat", + "default": "maxwell.png", + "variants": [ + { + "startTime": { "day": 12, "month": 4 }, + "endTime": { "day": 12, "month": 4 }, + "path": "oneDay.png" + }, + { + "startTime": { "day": 20, "month": 12 }, + "endTime": { "day": 28, "month": 12 }, + "path": "christmas.png" + }, + { + "startTime": { "day": 30, "month": 12 }, + "endTime": { "day": 1, "month": 1 }, + "path": "newyear2.png" + }, + { + "startTime": { "day": 28, "month": 12 }, + "endTime": { "day": 3, "month": 1 }, + "path": "newyear.png" + } + ] +} From 7e65aea2ef790d8f2e424e618d9ab9acd476f045 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 31 Aug 2023 19:04:41 +0300 Subject: [PATCH 18/36] format json Signed-off-by: Trial97 --- tests/testdata/CatPacks/index.json | 72 ++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/tests/testdata/CatPacks/index.json b/tests/testdata/CatPacks/index.json index c55813dbb..b5401d230 100644 --- a/tests/testdata/CatPacks/index.json +++ b/tests/testdata/CatPacks/index.json @@ -1,26 +1,50 @@ { - "name": "My Cute Cat", - "default": "maxwell.png", - "variants": [ - { - "startTime": { "day": 12, "month": 4 }, - "endTime": { "day": 12, "month": 4 }, - "path": "oneDay.png" - }, - { - "startTime": { "day": 20, "month": 12 }, - "endTime": { "day": 28, "month": 12 }, - "path": "christmas.png" - }, - { - "startTime": { "day": 30, "month": 12 }, - "endTime": { "day": 1, "month": 1 }, - "path": "newyear2.png" - }, - { - "startTime": { "day": 28, "month": 12 }, - "endTime": { "day": 3, "month": 1 }, - "path": "newyear.png" - } - ] + "name": "My Cute Cat", + "default": "maxwell.png", + "variants": [ + { + "startTime": { + "day": 12, + "month": 4 + }, + "endTime": { + "day": 12, + "month": 4 + }, + "path": "oneDay.png" + }, + { + "startTime": { + "day": 20, + "month": 12 + }, + "endTime": { + "day": 28, + "month": 12 + }, + "path": "christmas.png" + }, + { + "startTime": { + "day": 30, + "month": 12 + }, + "endTime": { + "day": 1, + "month": 1 + }, + "path": "newyear2.png" + }, + { + "startTime": { + "day": 28, + "month": 12 + }, + "endTime": { + "day": 3, + "month": 1 + }, + "path": "newyear.png" + } + ] } From eb66e37b8311fb830727e2632c6a00301b36b1f1 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:29:16 -0400 Subject: [PATCH 19/36] fix opening files from curseforge: links on linux Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> --- program_info/org.prismlauncher.PrismLauncher.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index 816c00595..98ac92fe5 100644 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -4,7 +4,7 @@ Name=Prism Launcher Comment=A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. Type=Application Terminal=false -Exec=@Launcher_APP_BINARY_NAME@ +Exec=@Launcher_APP_BINARY_NAME@ %u StartupNotify=true Icon=org.prismlauncher.PrismLauncher Categories=Game;ActionGame;AdventureGame;Simulation; From 984e870bca6ac4e8264ba7221bd99b54c0bb0fc9 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:32:35 -0400 Subject: [PATCH 20/36] actually it can handle multiple files just fine Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> --- program_info/org.prismlauncher.PrismLauncher.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index 98ac92fe5..76f4b19c0 100644 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -4,7 +4,7 @@ Name=Prism Launcher Comment=A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. Type=Application Terminal=false -Exec=@Launcher_APP_BINARY_NAME@ %u +Exec=@Launcher_APP_BINARY_NAME@ %U StartupNotify=true Icon=org.prismlauncher.PrismLauncher Categories=Game;ActionGame;AdventureGame;Simulation; From 88f3e19f815e67f6cb38c2b9df2dbf6008d4d60a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 Sep 2023 00:17:45 +0000 Subject: [PATCH 21/36] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-parts': 'github:hercules-ci/flake-parts/59cf3f1447cfc75087e7273b04b31e689a8599fb' (2023-08-01) → 'github:hercules-ci/flake-parts/7f53fdb7bdc5bb237da7fefef12d099e4fd611ca' (2023-09-01) • Updated input 'flake-parts/nixpkgs-lib': 'github:NixOS/nixpkgs/9e1960bc196baf6881340d53dccb203a951745a2?dir=lib' (2023-08-01) → 'github:NixOS/nixpkgs/3e52e76b70d5508f3cec70b882a29199f4d1ee85?dir=lib' (2023-08-31) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/cddebdb60de376c1bdb7a4e6ee3d98355453fe56' (2023-08-27) → 'github:nixos/nixpkgs/bfb7dfec93f3b5d7274db109f2990bc889861caf' (2023-09-02) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index f27ca5207..b1486ea69 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1690933134, - "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "lastModified": 1693611461, + "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", "type": "github" }, "original": { @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693145325, - "narHash": "sha256-Gat9xskErH1zOcLjYMhSDBo0JTBZKfGS0xJlIRnj6Rc=", + "lastModified": 1693626178, + "narHash": "sha256-Rpiy6lIOu4zny8tfGuIeN1ji9eSz9nPmm9yBhh/4IOM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "cddebdb60de376c1bdb7a4e6ee3d98355453fe56", + "rev": "bfb7dfec93f3b5d7274db109f2990bc889861caf", "type": "github" }, "original": { @@ -108,11 +108,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1690881714, - "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "lastModified": 1693471703, + "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", "type": "github" }, "original": { From bbf4e3b04d98eac840134b1687aba63ec180ead0 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 3 Sep 2023 18:11:23 -0400 Subject: [PATCH 22/36] refactor(nix): use fixed points over rec Signed-off-by: seth --- nix/distribution.nix | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/nix/distribution.nix b/nix/distribution.nix index 0dde1e4f0..6b93d355f 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -3,18 +3,28 @@ self, ... }: { - perSystem = {pkgs, ...}: { + perSystem = { + lib, + pkgs, + ... + }: { packages = let - ourPackages = self.overlays.default pkgs null; + ourPackages = lib.fix (final: self.overlays.default ({inherit (pkgs) darwin;} // final) pkgs); in { - inherit (ourPackages) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher; + inherit + (ourPackages) + prismlauncher-qt5-unwrapped + prismlauncher-qt5 + prismlauncher-unwrapped + prismlauncher + ; default = ourPackages.prismlauncher; }; }; flake = { - overlays.default = final: _: let - version = builtins.substring 0 8 self.lastModifiedDate; + overlays.default = final: prev: let + version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; # common args for prismlauncher evaluations unwrappedArgs = { @@ -22,11 +32,13 @@ inherit (final.darwin.apple_sdk.frameworks) Cocoa; inherit self version; }; - in rec { - prismlauncher-qt5-unwrapped = final.libsForQt5.callPackage ./pkg unwrappedArgs; - prismlauncher-qt5 = final.libsForQt5.callPackage ./pkg/wrapper.nix {prismlauncher-unwrapped = prismlauncher-qt5-unwrapped;}; - prismlauncher-unwrapped = final.qt6Packages.callPackage ./pkg unwrappedArgs; - prismlauncher = final.qt6Packages.callPackage ./pkg/wrapper.nix {inherit prismlauncher-unwrapped;}; + in { + prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs; + prismlauncher-qt5 = prev.libsForQt5.callPackage ./pkg/wrapper.nix { + prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped; + }; + prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg unwrappedArgs; + prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix {inherit (final) prismlauncher-unwrapped;}; }; }; } From 2918d61b16934980ed43fa52ead291e37a66732c Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 4 Sep 2023 08:52:56 +0200 Subject: [PATCH 23/36] refactor(nix): use pre-commit flake module Signed-off-by: Sefa Eyeoglu --- flake.nix | 2 ++ nix/dev.nix | 38 +++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/flake.nix b/flake.nix index 8f31ccec5..d45282aa6 100644 --- a/flake.nix +++ b/flake.nix @@ -25,6 +25,8 @@ {inherit inputs;} { imports = [ + inputs.pre-commit-hooks.flakeModule + ./nix/dev.nix ./nix/distribution.nix ]; diff --git a/nix/dev.nix b/nix/dev.nix index a9c1dc65d..c476ed10f 100644 --- a/nix/dev.nix +++ b/nix/dev.nix @@ -1,37 +1,33 @@ { - inputs, - self, - ... -}: { perSystem = { - system, + config, + lib, pkgs, ... }: { - checks = { - pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run { - src = self; - hooks = { - markdownlint.enable = true; + pre-commit.settings = { + hooks = { + markdownlint.enable = true; - alejandra.enable = true; - deadnix.enable = true; - nil.enable = true; + alejandra.enable = true; + deadnix.enable = true; + nil.enable = true; - clang-format = { - enable = true; - types_or = ["c" "c++" "java" "json" "objective-c"]; - }; + clang-format = { + enable = true; + types_or = ["c" "c++" "java" "json" "objective-c"]; }; - - tools.clang-tools = pkgs.clang-tools_16; }; + + tools.clang-tools = lib.mkForce pkgs.clang-tools_16; }; devShells.default = pkgs.mkShell { - inherit (self.checks.${system}.pre-commit-check) shellHook; + shellHook = '' + ${config.pre-commit.installationScript} + ''; - inputsFrom = [self.packages.${system}.prismlauncher-unwrapped]; + inputsFrom = [config.packages.prismlauncher-unwrapped]; buildInputs = with pkgs; [ccache ninja]; }; From e1558446717c83f14c575e0b8759f6a370633477 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 10:22:11 +0000 Subject: [PATCH 24/36] chore(deps): update cachix/install-nix-action action to v23 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index ad4016ff4..16dbd7240 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 - uses: DeterminateSystems/update-flake-lock@v20 with: From 94c1cd6bcfbc7a66286c18bf1d1c3854f49deb64 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Sep 2023 14:13:44 +0100 Subject: [PATCH 25/36] CurseForge shader downloading Signed-off-by: TheKodeToad --- launcher/modplatform/flame/FlameAPI.h | 2 + .../ui/dialogs/ResourceDownloadDialog.cpp | 2 + .../modplatform/flame/FlameResourceModels.cpp | 23 ++++++++++ .../modplatform/flame/FlameResourceModels.h | 17 ++++++++ .../modplatform/flame/FlameResourcePages.cpp | 43 +++++++++++++++++++ .../modplatform/flame/FlameResourcePages.h | 28 ++++++++++++ 6 files changed, 115 insertions(+) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 47350c33e..e22d8f0d8 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -38,6 +38,8 @@ class FlameAPI : public NetworkResourceAPI { return 6; case ModPlatform::ResourceType::RESOURCE_PACK: return 12; + case ModPlatform::ResourceType::SHADER_PACK: + return 6552; } } diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 9e121bb61..bf76b01e3 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -370,6 +370,8 @@ QList ShaderPackDownloadDialog::getPages() { QList pages; pages.append(ModrinthShaderPackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameShaderPackPage::create(this, *m_instance)); return pages; } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index c80e4f999..7d18e72a6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -121,4 +121,27 @@ auto FlameTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonAr return Json::ensureArray(obj.object(), "data"); } +FlameShaderPackModel::FlameShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new FlameAPI) {} + +void FlameShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadIndexedPack(m, obj); +} + +// We already deal with the URLs when initializing the pack, due to the API response's structure +void FlameShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadBody(m, obj); +} + +void FlameShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); +} + +auto FlameShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return Json::ensureArray(obj.object(), "data"); +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 6cfd6a6f8..76dbd7b3d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -68,4 +68,21 @@ class FlameTexturePackModel : public TexturePackResourceModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class FlameShaderPackModel : public ShaderPackResourceModel { + Q_OBJECT + + public: + FlameShaderPackModel(const BaseInstance&); + ~FlameShaderPackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index 1403e98f9..23373ec9d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -173,6 +173,45 @@ void FlameTexturePackPage::openUrl(const QUrl& url) TexturePackResourcePage::openUrl(url); } +FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) + : ShaderPackResourcePage(dialog, instance) +{ + m_model = new FlameShaderPackModel(instance); + m_ui->packView->setModel(m_model); + + addSortings(); + + // sometimes Qt just ignores virtual slots and doesn't work as intended it seems, + // so it's best not to connect them in the parent's constructor... + connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + +bool FlameShaderPackPage::optedOut(ModPlatform::IndexedVersion& ver) const +{ + return isOptedOut(ver); +} + +void FlameShaderPackPage::openUrl(const QUrl& url) +{ + if (url.scheme().isEmpty()) { + QString query = url.query(QUrl::FullyDecoded); + + if (query.startsWith("remoteUrl=")) { + // attempt to resolve url from warning page + query.remove(0, 10); + ShaderPackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary + return; + } + } + + ShaderPackResourcePage::openUrl(url); +} + // I don't know why, but doing this on the parent class makes it so that // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... @@ -188,5 +227,9 @@ auto FlameTexturePackPage::shouldDisplay() const -> bool { return true; } +auto FlameShaderPackPage::shouldDisplay() const -> bool +{ + return true; +} } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 035da2d5f..f2f5cecad 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -44,6 +44,7 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/ShaderPackPage.h" #include "ui/pages/modplatform/TexturePackPage.h" namespace ResourceDownload { @@ -155,4 +156,31 @@ class FlameTexturePackPage : public TexturePackResourcePage { void openUrl(const QUrl& url) override; }; +class FlameShaderPackPage : public ShaderPackResourcePage { + Q_OBJECT + + public: + static FlameShaderPackPage* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance) + { + return ShaderPackResourcePage::create(dialog, instance); + } + + FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); + ~FlameShaderPackPage() override = default; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + + bool optedOut(ModPlatform::IndexedVersion& ver) const override; + + void openUrl(const QUrl& url) override; +}; + } // namespace ResourceDownload From 7dd2530027fb17997283e1ec812f036328057d39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 15:02:01 +0000 Subject: [PATCH 26/36] chore(deps): update actions/checkout action to v4 --- .github/workflows/backport.yml | 2 +- .github/workflows/build.yml | 4 ++-- .github/workflows/codeql.yml | 2 +- .github/workflows/trigger_release.yml | 2 +- .github/workflows/update-flake.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 08cfb56dd..c705ff7b0 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -20,7 +20,7 @@ jobs: if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d044f4faf..e0434ce68 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -125,7 +125,7 @@ jobs: # PREPARE ## - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' @@ -620,7 +620,7 @@ jobs: options: --privileged steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 if: inputs.build_type == 'Debug' with: submodules: 'true' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0cd1f6e40..a77b4ae1e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,7 +8,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index 2a46ff5e7..bda75e354 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -26,7 +26,7 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' path: 'PrismLauncher-source' diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 16dbd7240..6a16b0369 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 - uses: DeterminateSystems/update-flake-lock@v20 From e7d6be531f1e4101aa808818159cfeb0db394a67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:22:12 +0000 Subject: [PATCH 27/36] chore(deps): update actions/cache action to v3.3.2 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0434ce68..059795a11 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,7 +164,7 @@ jobs: - name: Retrieve ccache cache (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' - uses: actions/cache@v3.3.1 + uses: actions/cache@v3.3.2 with: path: '${{ github.workspace }}\.ccache' key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }} From 89e434bd5bedcd92bfa99102011607027be20060 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 9 Sep 2023 14:32:50 -0400 Subject: [PATCH 28/36] refactor(nix): don't concat final attr in fixed point Signed-off-by: seth --- nix/distribution.nix | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/nix/distribution.nix b/nix/distribution.nix index 6b93d355f..c8fa01c59 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -9,7 +9,7 @@ ... }: { packages = let - ourPackages = lib.fix (final: self.overlays.default ({inherit (pkgs) darwin;} // final) pkgs); + ourPackages = lib.fix (final: self.overlays.default final pkgs); in { inherit (ourPackages) @@ -29,16 +29,21 @@ # common args for prismlauncher evaluations unwrappedArgs = { inherit (inputs) libnbtplusplus; - inherit (final.darwin.apple_sdk.frameworks) Cocoa; + inherit ((final.darwin or prev.darwin).apple_sdk.frameworks) Cocoa; inherit self version; }; in { prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs; + prismlauncher-qt5 = prev.libsForQt5.callPackage ./pkg/wrapper.nix { prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped; }; + prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg unwrappedArgs; - prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix {inherit (final) prismlauncher-unwrapped;}; + + prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix { + inherit (final) prismlauncher-unwrapped; + }; }; }; } From 6aa821df9c5cb2cd79e03ddad043ab49acfdd5a3 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 9 Sep 2023 14:34:38 -0400 Subject: [PATCH 29/36] refactor(nix): match inputs value in flake Signed-off-by: seth --- flake.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index d45282aa6..a58d66fb9 100644 --- a/flake.nix +++ b/flake.nix @@ -20,12 +20,14 @@ }; }; - outputs = inputs: - inputs.flake-parts.lib.mkFlake - {inherit inputs;} - { + outputs = { + flake-parts, + pre-commit-hooks, + ... + } @ inputs: + flake-parts.lib.mkFlake {inherit inputs;} { imports = [ - inputs.pre-commit-hooks.flakeModule + pre-commit-hooks.flakeModule ./nix/dev.nix ./nix/distribution.nix From 10192c540b85999c9a5cd075d695d1a4298ff9e5 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 9 Sep 2023 15:10:15 -0400 Subject: [PATCH 30/36] feat(nix): add source filtering this - along with garnix - should mostly eliminate unneeded (re)builds Signed-off-by: seth --- flake.lock | 16 ++++++++++++++++ flake.nix | 1 + nix/distribution.nix | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index b1486ea69..df6039cf4 100644 --- a/flake.lock +++ b/flake.lock @@ -89,6 +89,21 @@ "type": "github" } }, + "nix-filter": { + "locked": { + "lastModified": 1693833173, + "narHash": "sha256-hlMABKrGbEiJD5dwUSfnw1CQ3bG7KKwDV+Nx3bEZd7U=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "ac030bd9ba98e318e1f4c4328d60766ade8ebe8b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1693626178, @@ -156,6 +171,7 @@ "flake-compat": "flake-compat", "flake-parts": "flake-parts", "libnbtplusplus": "libnbtplusplus", + "nix-filter": "nix-filter", "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks" } diff --git a/flake.nix b/flake.nix index a58d66fb9..afb0ec63a 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,7 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-parts.url = "github:hercules-ci/flake-parts"; + nix-filter.url = "github:numtide/nix-filter"; pre-commit-hooks = { url = "github:cachix/pre-commit-hooks.nix"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/distribution.nix b/nix/distribution.nix index c8fa01c59..ca9999dcb 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -26,11 +26,27 @@ overlays.default = final: prev: let version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; + filteredSelf = inputs.nix-filter.lib.filter { + root = ../.; + include = [ + "buildconfig" + "cmake" + "launcher" + "libraries" + "program_info" + "tests" + ../COPYING.md + ../CMakeLists.txt + ]; + }; + # common args for prismlauncher evaluations unwrappedArgs = { + self = filteredSelf; + inherit (inputs) libnbtplusplus; inherit ((final.darwin or prev.darwin).apple_sdk.frameworks) Cocoa; - inherit self version; + inherit version; }; in { prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs; From 82a0a5bca12851afb276851569af8716e85e66c1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 10 Sep 2023 00:17:57 +0000 Subject: [PATCH 31/36] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/bfb7dfec93f3b5d7274db109f2990bc889861caf' (2023-09-02) → 'github:nixos/nixpkgs/b200e0df08f80c32974a6108ce431d8a8a5e6547' (2023-09-07) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b1486ea69..9290736b3 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693626178, - "narHash": "sha256-Rpiy6lIOu4zny8tfGuIeN1ji9eSz9nPmm9yBhh/4IOM=", + "lastModified": 1694062546, + "narHash": "sha256-PiGI4f2BGnZcedP6slLjCLGLRLXPa9+ogGGgVPfGxys=", "owner": "nixos", "repo": "nixpkgs", - "rev": "bfb7dfec93f3b5d7274db109f2990bc889861caf", + "rev": "b200e0df08f80c32974a6108ce431d8a8a5e6547", "type": "github" }, "original": { From 9afe80b0e00d9520abe4d91a3075b019e85c80d7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 17 Sep 2023 00:18:04 +0000 Subject: [PATCH 32/36] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/b200e0df08f80c32974a6108ce431d8a8a5e6547' (2023-09-07) → 'github:nixos/nixpkgs/46688f8eb5cd6f1298d873d4d2b9cf245e09e88e' (2023-09-15) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa' (2023-08-17) → 'github:cachix/pre-commit-hooks.nix/4f883a76282bc28eb952570afc3d8a1bf6f481d7' (2023-09-10) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 9290736b3..6fbcf0526 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694062546, - "narHash": "sha256-PiGI4f2BGnZcedP6slLjCLGLRLXPa9+ogGGgVPfGxys=", + "lastModified": 1694760568, + "narHash": "sha256-3G07BiXrp2YQKxdcdms22MUx6spc6A++MSePtatCYuI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b200e0df08f80c32974a6108ce431d8a8a5e6547", + "rev": "46688f8eb5cd6f1298d873d4d2b9cf245e09e88e", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1692274144, - "narHash": "sha256-BxTQuRUANQ81u8DJznQyPmRsg63t4Yc+0kcyq6OLz8s=", + "lastModified": 1694364351, + "narHash": "sha256-oadhSCqopYXxURwIA6/Anpe5IAG11q2LhvTJNP5zE6o=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa", + "rev": "4f883a76282bc28eb952570afc3d8a1bf6f481d7", "type": "github" }, "original": { From 97ced1f459664949943b3f0ef424ea792be1c716 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 19 Sep 2023 13:45:12 -0400 Subject: [PATCH 33/36] fix(nix): include libusb1 as a runtime dependency Signed-off-by: seth --- nix/pkg/wrapper.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 8d160143d..8bc255e71 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -18,9 +18,11 @@ flite, mesa-demos, udev, + libusb1, msaClientID ? null, gamemodeSupport ? stdenv.isLinux, textToSpeechSupport ? stdenv.isLinux, + controllerSupport ? stdenv.isLinux, jdks ? [jdk17 jdk8], additionalLibs ? [], additionalPrograms ? [], @@ -71,6 +73,7 @@ in ] ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional textToSpeechSupport flite + ++ lib.optional controllerSupport libusb1 ++ additionalLibs; runtimePrograms = From 97da8892b9fcb285f7023a671090b4a3becdf2d8 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 19 Sep 2023 13:45:52 -0400 Subject: [PATCH 34/36] chore(nix): add meta.mainProgram attribute Signed-off-by: seth --- nix/pkg/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/pkg/default.nix b/nix/pkg/default.nix index 074214c4b..fd19a0b3d 100644 --- a/nix/pkg/default.nix +++ b/nix/pkg/default.nix @@ -58,6 +58,7 @@ assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is on dontWrapQtApps = true; meta = with lib; { + mainProgram = "prismlauncher"; homepage = "https://prismlauncher.org/"; description = "A free, open source launcher for Minecraft"; longDescription = '' From fa65ac3ff71c27a17c5e1a6b1d75842b1c6e62ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 24 Sep 2023 00:18:03 +0000 Subject: [PATCH 35/36] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nix-filter': 'github:numtide/nix-filter/ac030bd9ba98e318e1f4c4328d60766ade8ebe8b' (2023-09-04) → 'github:numtide/nix-filter/41fd48e00c22b4ced525af521ead8792402de0ea' (2023-09-16) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/46688f8eb5cd6f1298d873d4d2b9cf245e09e88e' (2023-09-15) → 'github:nixos/nixpkgs/e12483116b3b51a185a33a272bf351e357ba9a99' (2023-09-21) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 8096fcebc..f96336551 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nix-filter": { "locked": { - "lastModified": 1693833173, - "narHash": "sha256-hlMABKrGbEiJD5dwUSfnw1CQ3bG7KKwDV+Nx3bEZd7U=", + "lastModified": 1694857738, + "narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=", "owner": "numtide", "repo": "nix-filter", - "rev": "ac030bd9ba98e318e1f4c4328d60766ade8ebe8b", + "rev": "41fd48e00c22b4ced525af521ead8792402de0ea", "type": "github" }, "original": { @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694760568, - "narHash": "sha256-3G07BiXrp2YQKxdcdms22MUx6spc6A++MSePtatCYuI=", + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "46688f8eb5cd6f1298d873d4d2b9cf245e09e88e", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { From 1684cff7acde56aba7c8db232a918d96e220be29 Mon Sep 17 00:00:00 2001 From: alexia Date: Mon, 25 Sep 2023 15:46:22 +0200 Subject: [PATCH 36/36] Update links to Minecraft Wiki Minecraft Wiki has officially moved from Fandom to their own wiki. I updated some links I found in comments. Signed-off-by: alexia --- launcher/minecraft/MinecraftInstance.cpp | 2 +- launcher/minecraft/mod/DataPack.cpp | 2 +- launcher/minecraft/mod/DataPack.h | 2 +- launcher/minecraft/mod/ResourcePack.cpp | 2 +- launcher/minecraft/mod/ResourcePack.h | 2 +- launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp | 2 +- launcher/ui/widgets/InfoFrame.cpp | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 0e64c46d4..86ef3b30e 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -311,7 +311,7 @@ QString MinecraftInstance::getLocalLibraryPath() const bool MinecraftInstance::supportsDemo() const { Version instance_ver{ getPackProfile()->getComponentVersion("net.minecraft") }; - // Demo mode was introduced in 1.3.1: https://minecraft.fandom.com/wiki/Demo_mode#History + // Demo mode was introduced in 1.3.1: https://minecraft.wiki/w/Demo_mode#History // FIXME: Due to Version constraints atm, this can't handle well non-release versions return instance_ver >= Version("1.3.1"); } diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index 7bf5a3112..fc2d3f68b 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -28,7 +28,7 @@ #include "Version.h" // Values taken from: -// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_data_pack#%22pack_format%22 +// https://minecraft.wiki/w/Tutorials/Creating_a_data_pack#%22pack_format%22 static const QMap> s_pack_format_versions = { { 4, { Version("1.13"), Version("1.14.4") } }, { 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } }, diff --git a/launcher/minecraft/mod/DataPack.h b/launcher/minecraft/mod/DataPack.h index fc2703c7a..b3787b238 100644 --- a/launcher/minecraft/mod/DataPack.h +++ b/launcher/minecraft/mod/DataPack.h @@ -63,7 +63,7 @@ class DataPack : public Resource { mutable QMutex m_data_lock; /* The 'version' of a data pack, as defined in the pack.mcmeta file. - * See https://minecraft.fandom.com/wiki/Data_pack#pack.mcmeta + * See https://minecraft.wiki/w/Data_pack#pack.mcmeta */ int m_pack_format = 0; diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 2bb51dc5b..074534405 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -11,7 +11,7 @@ #include "minecraft/mod/tasks/LocalResourcePackParseTask.h" // Values taken from: -// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta +// https://minecraft.wiki/w/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta static const QMap> s_pack_format_versions = { { 1, { Version("1.6.1"), Version("1.8.9") } }, { 2, { Version("1.9"), Version("1.10.2") } }, { 3, { Version("1.11"), Version("1.12.2") } }, { 4, { Version("1.13"), Version("1.14.4") } }, diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h index da354bc1c..c06f3793d 100644 --- a/launcher/minecraft/mod/ResourcePack.h +++ b/launcher/minecraft/mod/ResourcePack.h @@ -51,7 +51,7 @@ class ResourcePack : public Resource { mutable QMutex m_data_lock; /* The 'version' of a resource pack, as defined in the pack.mcmeta file. - * See https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta + * See https://minecraft.wiki/w/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta */ int m_pack_format = 0; diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp index 5bb448778..82f6b9df9 100644 --- a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp @@ -133,7 +133,7 @@ bool processZIP(DataPack& pack, ProcessingLevel level) return true; } -// https://minecraft.fandom.com/wiki/Data_pack#pack.mcmeta +// https://minecraft.wiki/w/Data_pack#pack.mcmeta bool processMCMeta(DataPack& pack, QByteArray&& raw_data) { try { diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp index 73cbf891c..7b9f4f594 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp @@ -178,7 +178,7 @@ bool processZIP(ResourcePack& pack, ProcessingLevel level) return true; } -// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta +// https://minecraft.wiki/w/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data) { try { diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 1f03f9eaf..69f72fea2 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -158,12 +158,12 @@ QString InfoFrame::renderColorCodes(QString input) // // TODO: Wrap links inside tags - // https://minecraft.fandom.com/wiki/Formatting_codes#Color_codes + // https://minecraft.wiki/w/Formatting_codes#Color_codes const QMap color_codes_map = { { '0', "#000000" }, { '1', "#0000AA" }, { '2', "#00AA00" }, { '3', "#00AAAA" }, { '4', "#AA0000" }, { '5', "#AA00AA" }, { '6', "#FFAA00" }, { '7', "#AAAAAA" }, { '8', "#555555" }, { '9', "#5555FF" }, { 'a', "#55FF55" }, { 'b', "#55FFFF" }, { 'c', "#FF5555" }, { 'd', "#FF55FF" }, { 'e', "#FFFF55" }, { 'f', "#FFFFFF" } }; - // https://minecraft.fandom.com/wiki/Formatting_codes#Formatting_codes + // https://minecraft.wiki/w/Formatting_codes#Formatting_codes const QMap formatting_codes_map = { { 'l', "b" }, { 'm', "s" }, { 'n', "u" }, { 'o', "i" } }; QString html("");