From 6d5c629b4316fb37b1ca0705c17867d6d9c771bd Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 10 Apr 2023 00:04:35 +0300
Subject: Added dependencies to the APIs

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/ModIndex.h                    |  9 +++++++
 launcher/modplatform/flame/FlameModIndex.cpp       | 30 +++++++++++++++++++++-
 .../modplatform/modrinth/ModrinthPackIndex.cpp     | 21 ++++++++++++++-
 3 files changed, 58 insertions(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 40f1efc4..ffa3a3ab 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -32,6 +32,8 @@ enum class ResourceProvider { MODRINTH, FLAME };
 
 enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK };
 
+enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE };
+
 class ProviderCapabilities {
    public:
     auto name(ResourceProvider) -> const char*;
@@ -51,6 +53,12 @@ struct DonationData {
     QString url;
 };
 
+struct Dependency {
+    QVariant addonId;
+    DependencyType type;
+    QString version;
+};
+
 struct IndexedVersion {
     QVariant addonId;
     QVariant fileId;
@@ -65,6 +73,7 @@ struct IndexedVersion {
     QString hash;
     bool is_preferred = true;
     QString changelog;
+    QList<Dependency> dependencies;
 
     // For internal use, not provided by APIs
     bool is_currently_selected = false;
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
index 7498e830..a820e3a1 100644
--- a/launcher/modplatform/flame/FlameModIndex.cpp
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -136,7 +136,35 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
         }
     }
 
-    if(load_changelog)
+    auto dependencies = Json::ensureArray(obj, "dependencies");
+    for (auto d : dependencies) {
+        auto dep = Json::ensureObject(d);
+        ModPlatform::Dependency dependency;
+        dependency.addonId = Json::requireInteger(dep, "modId");
+        switch (Json::requireInteger(dep, "relationType")) {
+            case 1:  // EmbeddedLibrary
+                dependency.type = ModPlatform::DependencyType::EMBEDDED;
+                break;
+            case 2:  // OptionalDependency
+                dependency.type = ModPlatform::DependencyType::OPTIONAL;
+                break;
+            case 3:  // RequiredDependency
+                dependency.type = ModPlatform::DependencyType::REQUIRED;
+                break;
+            case 4:  // Tool
+                dependency.type = ModPlatform::DependencyType::TOOL;
+                break;
+            case 5:  // Incompatible
+                dependency.type = ModPlatform::DependencyType::INCOMPATIBLE;
+                break;
+            case 6:  // Include
+                dependency.type = ModPlatform::DependencyType::INCLUDE;
+                break;
+        }
+        file.dependencies.append(dependency);
+    }
+
+    if (load_changelog)
         file.changelog = api.getModFileChangelog(file.addonId.toInt(), file.fileId.toInt());
 
     return file;
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index 7ade131e..8e97ee7c 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -22,7 +22,6 @@
 #include "Json.h"
 #include "minecraft/MinecraftInstance.h"
 #include "minecraft/PackProfile.h"
-#include "net/NetJob.h"
 
 static ModrinthAPI api;
 static ModPlatform::ProviderCapabilities ProviderCaps;
@@ -140,6 +139,26 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
     file.version_number = Json::requireString(obj, "version_number");
     file.changelog = Json::requireString(obj, "changelog");
 
+    auto dependencies = Json::ensureArray(obj, "dependencies");
+    for (auto d : dependencies) {
+        auto dep = Json::ensureObject(d);
+        ModPlatform::Dependency dependency;
+        dependency.addonId = Json::requireString(dep, "project_id");
+        dependency.version = Json::requireString(dep, "version_id");
+        auto depType = Json::requireString(dep, "dependency_type");
+
+        if (depType == "required")
+            dependency.type = ModPlatform::DependencyType::REQUIRED;
+        else if (depType == "optional")
+            dependency.type = ModPlatform::DependencyType::OPTIONAL;
+        else if (depType == "incompatible")
+            dependency.type = ModPlatform::DependencyType::INCOMPATIBLE;
+        else if (depType == "embedded")
+            dependency.type = ModPlatform::DependencyType::EMBEDDED;
+
+        file.dependencies.append(dependency);
+    }
+
     auto files = Json::requireArray(obj, "files");
     int i = 0;
 
-- 
cgit 


From d524935b6726c1a8d589d01abad4d262a55af149 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Tue, 11 Apr 2023 20:55:10 +0300
Subject: Added task to load local mod information

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/LocalModGetTask.cpp | 51 ++++++++++++++++++++++++
 launcher/minecraft/mod/tasks/LocalModGetTask.h   | 46 +++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.cpp
 create mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.h

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetTask.cpp
new file mode 100644
index 00000000..9c056d02
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/LocalModGetTask.cpp
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "LocalModGetTask.h"
+
+#include "FileSystem.h"
+#include "minecraft/mod/MetadataHandler.h"
+
+#ifdef Q_OS_WIN32
+#include <windows.h>
+#endif
+
+LocalModGetTask::LocalModGetTask(QDir index_dir, QVariant addonId) : m_index_dir(index_dir), m_addonId(addonId)
+{
+    // Ensure a '.index' folder exists in the mods folder, and create it if it does not
+    if (!FS::ensureFolderPathExists(index_dir.path())) {
+        emitFailed(QString("Unable to create index for modId %1!").arg(m_addonId.toString()));
+    }
+
+#ifdef Q_OS_WIN32
+    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+#endif
+}
+
+void LocalModGetTask::executeTask()
+{
+    setStatus(tr("Updating index for modId:\n%1").arg(m_addonId.toString()));
+    emit getMod(Metadata::get(m_index_dir, m_addonId));
+}
+
+auto LocalModGetTask::abort() -> bool
+{
+    emitAborted();
+    return true;
+}
diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.h b/launcher/minecraft/mod/tasks/LocalModGetTask.h
new file mode 100644
index 00000000..5b741122
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/LocalModGetTask.h
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <QDir>
+
+#include "minecraft/mod/MetadataHandler.h"
+#include "tasks/Task.h"
+
+class LocalModGetTask : public Task {
+    Q_OBJECT
+   public:
+    using Ptr = shared_qobject_ptr<LocalModGetTask>;
+
+    explicit LocalModGetTask(QDir index_dir, QVariant addonId);
+
+    auto canAbort() const -> bool override { return true; }
+    auto abort() -> bool override;
+
+   protected slots:
+    //! Entry point for tasks.
+    void executeTask() override;
+
+   signals:
+    void getMod(Metadata::ModStruct);
+
+   private:
+    QDir m_index_dir;
+    QVariant m_addonId;
+};
-- 
cgit 


From 4fbd5abe41ac10ecd28974ff857e9bce35c7d264 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 12 Apr 2023 00:45:44 +0300
Subject: Added task to load dependencies

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/MetadataHandler.h           |  57 ++++------
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 116 +++++++++++++++++++++
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  63 +++++++++++
 .../minecraft/mod/tasks/LocalModGetAllTask.cpp     |  52 +++++++++
 launcher/minecraft/mod/tasks/LocalModGetAllTask.h  |  45 ++++++++
 launcher/minecraft/mod/tasks/LocalModGetTask.cpp   |  51 ---------
 launcher/minecraft/mod/tasks/LocalModGetTask.h     |  46 --------
 launcher/modplatform/packwiz/Packwiz.cpp           |  11 ++
 launcher/modplatform/packwiz/Packwiz.h             |  57 +++++-----
 9 files changed, 339 insertions(+), 159 deletions(-)
 create mode 100644 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
 create mode 100644 launcher/minecraft/mod/tasks/GetModDependenciesTask.h
 create mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
 create mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.h
 delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.cpp
 delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.h

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h
index 39723b49..f7f08a79 100644
--- a/launcher/minecraft/mod/MetadataHandler.h
+++ b/launcher/minecraft/mod/MetadataHandler.h
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  PolyMC - Minecraft Launcher
-*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #pragma once
 
@@ -42,28 +42,15 @@ class Metadata {
         return Packwiz::V1::createModFormat(index_dir, internal_mod, mod_slug);
     }
 
-    static void update(QDir& index_dir, ModStruct& mod)
-    {
-        Packwiz::V1::updateModIndex(index_dir, mod);
-    }
+    static void update(QDir& index_dir, ModStruct& mod) { Packwiz::V1::updateModIndex(index_dir, mod); }
 
-    static void remove(QDir& index_dir, QString mod_slug)
-    {
-        Packwiz::V1::deleteModIndex(index_dir, mod_slug);
-    }
+    static void remove(QDir& index_dir, QString mod_slug) { Packwiz::V1::deleteModIndex(index_dir, mod_slug); }
 
-    static void remove(QDir& index_dir, QVariant& mod_id)
-    {
-        Packwiz::V1::deleteModIndex(index_dir, mod_id);
-    }
+    static void remove(QDir& index_dir, QVariant& mod_id) { Packwiz::V1::deleteModIndex(index_dir, mod_id); }
 
-    static auto get(QDir& index_dir, QString mod_slug) -> ModStruct
-    {
-        return Packwiz::V1::getIndexForMod(index_dir, mod_slug);
-    }
+    static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); }
 
-    static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct
-    {
-        return Packwiz::V1::getIndexForMod(index_dir, mod_id);
-    }
+    static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); }
+
+    static auto getAll(QDir& index_dir) -> QList<ModStruct> { return Packwiz::V1::getAllMods(index_dir); }
 };
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
new file mode 100644
index 00000000..dcff1028
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "GetModDependenciesTask.h"
+
+#include "QObjectPtr.h"
+#include "minecraft/mod/MetadataHandler.h"
+#include "minecraft/mod/tasks/LocalModGetAllTask.h"
+#include "modplatform/ModIndex.h"
+#include "tasks/ConcurrentTask.h"
+#include "tasks/SequentialTask.h"
+
+#ifdef Q_OS_WIN32
+#include <windows.h>
+#endif
+
+GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask& api)
+    : m_selected(selected), m_getDependenciesVersionAPI(api)
+{
+    m_getAllMods = makeShared<LocalModGetAllTask>(index_dir);
+    m_getNetworkDep = makeShared<SequentialTask>(this, "GetDepInfo");
+    QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList<Metadata::ModStruct> mods) {
+        m_mods = mods;
+        prepareDependecies();
+    });
+
+#ifdef Q_OS_WIN32
+    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+#endif
+}
+
+void GetModDependenciesTask::executeTask()
+{
+    setStatus(tr("Geting all mods"));
+    m_getAllMods->start();
+}
+
+auto GetModDependenciesTask::abort() -> bool
+{
+    emitAborted();
+    return true;
+}
+
+void GetModDependenciesTask::prepareDependecies()
+{
+    auto c_dependencies = getDependenciesForVersions(m_selected);
+    if (c_dependencies.length() == 0) {
+        emitSucceeded();
+        return;
+    }
+    for (auto dep : c_dependencies) {
+        auto task = m_getDependenciesVersionAPI(
+            dep, 20, [this](QList<ModPlatform::IndexedVersion> new_versions, int level) { addDependecies(new_versions, level - 1); });
+        m_getNetworkDep->addTask(task);
+    }
+    m_getNetworkDep->start();
+}
+
+void GetModDependenciesTask::addDependecies(QList<ModPlatform::IndexedVersion> new_versions, int level)
+{
+    // some mutex?
+    m_dependencies.append(new_versions);
+    auto c_dependencies = getDependenciesForVersions(m_selected);
+    if (c_dependencies.length() == 0) {
+        return;
+    }
+    if (level == 0) {
+        qWarning() << "Dependency cycle exeeded";
+    }
+    for (auto dep : c_dependencies) {
+        auto task = m_getDependenciesVersionAPI(
+            dep, 20, [this](QList<ModPlatform::IndexedVersion> new_versions, int level) { addDependecies(new_versions, level - 1); });
+        m_getNetworkDep->addTask(task);
+    }
+};
+
+QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersions(QList<ModPlatform::IndexedVersion> selected)
+{
+    auto c_dependencies = QList<ModPlatform::Dependency>();
+    for (auto version : selected) {
+        for (auto ver_dep : version.dependencies) {
+            if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
+                if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
+                                            [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                    dep == c_dependencies.end()) {  // check the current dependency list
+                    c_dependencies.append(ver_dep);
+                } else if (auto dep =
+                               std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                           dep == selected.end()) {  // check the selected versions
+                    c_dependencies.append(ver_dep);
+                } else if (auto dep =
+                               std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                           dep == m_mods.end()) {  // check the existing mods
+                    c_dependencies.append(ver_dep);
+                }
+            }
+        }
+    }
+    return c_dependencies;
+};
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
new file mode 100644
index 00000000..28112bba
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <QDir>
+#include <functional>
+
+#include "minecraft/mod/MetadataHandler.h"
+#include "minecraft/mod/tasks/LocalModGetAllTask.h"
+#include "modplatform/ModIndex.h"
+#include "tasks/SequentialTask.h"
+#include "tasks/Task.h"
+
+class GetModDependenciesTask : public Task {
+    Q_OBJECT
+   public:
+    using Ptr = shared_qobject_ptr<GetModDependenciesTask>;
+    using LocalModGetAllTaskPtr = shared_qobject_ptr<LocalModGetAllTask>;
+
+    using NewDependecyVersionAPITask =
+        std::function<Task::Ptr(ModPlatform::Dependency, int, std::function<void(QList<ModPlatform::IndexedVersion>, int)>)>;
+
+    explicit GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask& api);
+
+    auto canAbort() const -> bool override { return true; }
+    auto abort() -> bool override;
+
+   protected slots:
+    //! Entry point for tasks.
+    void executeTask() override;
+
+    void prepareDependecies();
+    void addDependecies(QList<ModPlatform::IndexedVersion>, int);
+    QList<ModPlatform::Dependency> getDependenciesForVersions(QList<ModPlatform::IndexedVersion>);
+
+   signals:
+    void getAllMod(QList<Metadata::ModStruct>);
+
+   private:
+    QList<ModPlatform::IndexedVersion> m_selected;
+    QList<ModPlatform::IndexedVersion> m_dependencies;
+    QList<Metadata::ModStruct> m_mods;
+
+    LocalModGetAllTaskPtr m_getAllMods = nullptr;
+    NewDependecyVersionAPITask m_getDependenciesVersionAPI;
+    SequentialTask::Ptr m_getNetworkDep;
+};
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
new file mode 100644
index 00000000..9e4293ff
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "LocalModGetAllTask.h"
+
+#include "FileSystem.h"
+#include "minecraft/mod/MetadataHandler.h"
+
+#ifdef Q_OS_WIN32
+#include <windows.h>
+#endif
+
+LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir)
+{
+    // Ensure a '.index' folder exists in the mods folder, and create it if it does not
+    if (!FS::ensureFolderPathExists(index_dir.path())) {
+        emitFailed(QString("Unable to create index for all mods!"));
+    }
+
+#ifdef Q_OS_WIN32
+    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+#endif
+}
+
+void LocalModGetAllTask::executeTask()
+{
+    setStatus(tr("Geting all mods"));
+    emit getAllMod(Metadata::getAll(m_index_dir));
+    emitSucceeded();
+}
+
+auto LocalModGetAllTask::abort() -> bool
+{
+    emitAborted();
+    return true;
+}
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
new file mode 100644
index 00000000..09e453e4
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <QDir>
+
+#include "minecraft/mod/MetadataHandler.h"
+#include "tasks/Task.h"
+
+class LocalModGetAllTask : public Task {
+    Q_OBJECT
+   public:
+    using Ptr = shared_qobject_ptr<LocalModGetAllTask>;
+
+    explicit LocalModGetAllTask(QDir index_dir);
+
+    auto canAbort() const -> bool override { return true; }
+    auto abort() -> bool override;
+
+   protected slots:
+    //! Entry point for tasks.
+    void executeTask() override;
+
+   signals:
+    void getAllMod(QList<Metadata::ModStruct>);
+
+   private:
+    QDir m_index_dir;
+};
diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetTask.cpp
deleted file mode 100644
index 9c056d02..00000000
--- a/launcher/minecraft/mod/tasks/LocalModGetTask.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#include "LocalModGetTask.h"
-
-#include "FileSystem.h"
-#include "minecraft/mod/MetadataHandler.h"
-
-#ifdef Q_OS_WIN32
-#include <windows.h>
-#endif
-
-LocalModGetTask::LocalModGetTask(QDir index_dir, QVariant addonId) : m_index_dir(index_dir), m_addonId(addonId)
-{
-    // Ensure a '.index' folder exists in the mods folder, and create it if it does not
-    if (!FS::ensureFolderPathExists(index_dir.path())) {
-        emitFailed(QString("Unable to create index for modId %1!").arg(m_addonId.toString()));
-    }
-
-#ifdef Q_OS_WIN32
-    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
-#endif
-}
-
-void LocalModGetTask::executeTask()
-{
-    setStatus(tr("Updating index for modId:\n%1").arg(m_addonId.toString()));
-    emit getMod(Metadata::get(m_index_dir, m_addonId));
-}
-
-auto LocalModGetTask::abort() -> bool
-{
-    emitAborted();
-    return true;
-}
diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.h b/launcher/minecraft/mod/tasks/LocalModGetTask.h
deleted file mode 100644
index 5b741122..00000000
--- a/launcher/minecraft/mod/tasks/LocalModGetTask.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <QDir>
-
-#include "minecraft/mod/MetadataHandler.h"
-#include "tasks/Task.h"
-
-class LocalModGetTask : public Task {
-    Q_OBJECT
-   public:
-    using Ptr = shared_qobject_ptr<LocalModGetTask>;
-
-    explicit LocalModGetTask(QDir index_dir, QVariant addonId);
-
-    auto canAbort() const -> bool override { return true; }
-    auto abort() -> bool override;
-
-   protected slots:
-    //! Entry point for tasks.
-    void executeTask() override;
-
-   signals:
-    void getMod(Metadata::ModStruct);
-
-   private:
-    QDir m_index_dir;
-    QVariant m_addonId;
-};
diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp
index 510c7309..a2598b97 100644
--- a/launcher/modplatform/packwiz/Packwiz.cpp
+++ b/launcher/modplatform/packwiz/Packwiz.cpp
@@ -21,6 +21,8 @@
 #include <QDebug>
 #include <QDir>
 #include <QObject>
+#include <algorithm>
+#include <iterator>
 
 #include "FileSystem.h"
 #include "StringUtils.h"
@@ -311,4 +313,13 @@ auto V1::getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod
     return {};
 }
 
+auto V1::getAllMods(QDir& index_dir) -> QList<Mod>
+{
+    auto files = index_dir.entryList(QDir::Filter::Files);
+    auto mods = QList<Mod>();
+    std::transform(files.begin(), files.end(), std::back_inserter(mods),
+                   [index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); });
+    return mods;
+}
+
 }  // namespace Packwiz
diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h
index 4b096eec..2801f5d0 100644
--- a/launcher/modplatform/packwiz/Packwiz.h
+++ b/launcher/modplatform/packwiz/Packwiz.h
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  PolyMC - Minecraft Launcher
-*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #pragma once
 
@@ -36,22 +36,22 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul
 class V1 {
    public:
     struct Mod {
-        QString slug {};
-        QString name {};
-        QString filename {};
+        QString slug{};
+        QString name{};
+        QString filename{};
         // FIXME: make side an enum
-        QString side {"both"};
+        QString side{ "both" };
 
         // [download]
-        QString mode {};
-        QUrl url {};
-        QString hash_format {};
-        QString hash {};
+        QString mode{};
+        QUrl url{};
+        QString hash_format{};
+        QString hash{};
 
         // [update]
-        ModPlatform::ResourceProvider provider {};
-        QVariant file_id {};
-        QVariant project_id {};
+        ModPlatform::ResourceProvider provider{};
+        QVariant file_id{};
+        QVariant project_id{};
 
        public:
         // This is a totally heuristic, but should work for now.
@@ -93,6 +93,9 @@ class V1 {
      * If the mod doesn't have a metadata, it simply returns an empty Mod object.
      * */
     static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod;
+
+    /* Gets the metadata for all the mods */
+    static auto getAllMods(QDir& index_dir) -> QList<Mod>;
 };
 
-} // namespace Packwiz
+}  // namespace Packwiz
-- 
cgit 


From 11f8d25d94296aab13f885fde14ff26767082600 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 12 Apr 2023 00:49:50 +0300
Subject: Added missing character

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/packwiz/Packwiz.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp
index a2598b97..33b5f364 100644
--- a/launcher/modplatform/packwiz/Packwiz.cpp
+++ b/launcher/modplatform/packwiz/Packwiz.cpp
@@ -318,7 +318,7 @@ auto V1::getAllMods(QDir& index_dir) -> QList<Mod>
     auto files = index_dir.entryList(QDir::Filter::Files);
     auto mods = QList<Mod>();
     std::transform(files.begin(), files.end(), std::back_inserter(mods),
-                   [index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); });
+                   [&index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); });
     return mods;
 }
 
-- 
cgit 


From 5655a3351551aa36aeeba79b0ac7f2474ca74352 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 14 Apr 2023 18:59:31 +0300
Subject: Added Dependency API

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/ResourceAPI.h                 | 24 +++++++++++
 launcher/modplatform/flame/FlameAPI.h              | 15 +++++--
 .../modplatform/helpers/NetworkResourceAPI.cpp     | 49 ++++++++++++++++------
 launcher/modplatform/helpers/NetworkResourceAPI.h  |  2 +
 launcher/modplatform/modrinth/ModrinthAPI.h        | 35 ++++++++--------
 5 files changed, 93 insertions(+), 32 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h
index 34f33779..a8e144dc 100644
--- a/launcher/modplatform/ResourceAPI.h
+++ b/launcher/modplatform/ResourceAPI.h
@@ -111,6 +111,24 @@ class ResourceAPI {
         std::function<void(QJsonDocument&, ModPlatform::IndexedPack)> on_succeed;
     };
 
+    struct DependencySearchArgs {
+        ModPlatform::Dependency dependency;
+        Version mcVersion;
+        ModLoaderTypes loader;
+
+        DependencySearchArgs(DependencySearchArgs const&) = default;
+        void operator=(DependencySearchArgs other)
+        {
+            dependency = other.dependency;
+            mcVersion = other.mcVersion;
+            loader = other.loader;
+        }
+    };
+
+    struct DependencySearchCallbacks {
+        std::function<void(QJsonDocument&, ModPlatform::Dependency)> on_succeed;
+    };
+
    public:
     /** Gets a list of available sorting methods for this API. */
     [[nodiscard]] virtual auto getSortingMethods() const -> QList<SortingMethod> = 0;
@@ -143,6 +161,12 @@ class ResourceAPI {
         return nullptr;
     }
 
+    [[nodiscard]] virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const
+    {
+        qWarning() << "TODO";
+        return nullptr;
+    }
+
     static auto getModLoaderString(ModLoaderType type) -> const QString
     {
         switch (type) {
diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index 5811d717..91993e64 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -41,14 +41,15 @@ class FlameAPI : public NetworkResourceAPI {
             return 4;
         // TODO: remove this once Quilt drops official Fabric support
         if (loaders & Quilt)  // NOTE: Most if not all Fabric mods should work *currently*
-            return 4;  // Quilt would probably be 5
+            return 4;         // Quilt would probably be 5
         return 0;
     }
 
    private:
     [[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override
     {
-        auto gameVersionStr = args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString();
+        auto gameVersionStr =
+            args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString();
 
         QStringList get_arguments;
         get_arguments.append(QString("classId=%1").arg(getClassId(args.type)));
@@ -73,7 +74,7 @@ class FlameAPI : public NetworkResourceAPI {
 
     [[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override
     {
-        QString url{QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString())};
+        QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString()) };
 
         QStringList get_parameters;
         if (args.mcVersions.has_value())
@@ -83,4 +84,12 @@ class FlameAPI : public NetworkResourceAPI {
 
         return url + get_parameters.join('&');
     };
+
+    [[nodiscard]] std::optional<QString> getDependecyURL(DependencySearchArgs const& args) const override
+    {
+        return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%")
+            .arg(args.dependency.addonId.toString())
+            .arg(args.mcVersion.toString())
+            .arg(getMappedModLoader(args.loader));
+    };
 };
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
index 010ac15e..a7f763d3 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
@@ -24,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
 
     netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response));
 
-    QObject::connect(netJob.get(), &NetJob::succeeded, [=]{
+    QObject::connect(netJob.get(), &NetJob::succeeded, [=] {
         QJsonParseError parse_error{};
         QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
         if (parse_error.error != QJsonParseError::NoError) {
@@ -40,16 +40,14 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
         callbacks.on_succeed(doc);
     });
 
-    QObject::connect(netJob.get(), &NetJob::failed, [=](QString reason){
+    QObject::connect(netJob.get(), &NetJob::failed, [=](QString reason) {
         int network_error_code = -1;
         if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply)
             network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
 
-       callbacks.on_fail(reason, network_error_code); 
-    });
-    QObject::connect(netJob.get(), &NetJob::aborted, [=]{
-       callbacks.on_abort(); 
+        callbacks.on_fail(reason, network_error_code);
     });
+    QObject::connect(netJob.get(), &NetJob::aborted, [=] { callbacks.on_abort(); });
 
     return netJob;
 }
@@ -101,9 +99,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
         callbacks.on_succeed(doc, args.pack);
     });
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] {
-        delete response;
-    });
+    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
 
     return netJob;
 }
@@ -120,9 +116,38 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response)
 
     netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] {
-        delete response;
-    });
+    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
 
     return netJob;
 }
+
+Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, DependencySearchCallbacks&& callbacks) const
+{
+    auto versions_url_optional = getDependecyURL(args);
+    if (!versions_url_optional.has_value())
+        return nullptr;
+
+    auto versions_url = versions_url_optional.value();
+
+    auto netJob = makeShared<NetJob>(QString("%1::Dependecy").arg(args.dependency.addonId.toString()), APPLICATION->network());
+    auto response = new QByteArray();
+
+    netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
+
+    QObject::connect(netJob.get(), &NetJob::succeeded, [=] {
+        QJsonParseError parse_error{};
+        QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+        if (parse_error.error != QJsonParseError::NoError) {
+            qWarning() << "Error while parsing JSON response for getting versions at " << parse_error.offset
+                       << " reason: " << parse_error.errorString();
+            qWarning() << *response;
+            return;
+        }
+
+        callbacks.on_succeed(doc, args.dependency);
+    });
+
+    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
+
+    return netJob;
+};
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h
index 94813bec..bbe0a2c7 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.h
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.h
@@ -14,9 +14,11 @@ class NetworkResourceAPI : public ResourceAPI {
 
     Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override;
     Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override;
+    Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const override;
 
    protected:
     [[nodiscard]] virtual auto getSearchURL(SearchArgs const& args) const -> std::optional<QString> = 0;
     [[nodiscard]] virtual auto getInfoURL(QString const& id) const -> std::optional<QString> = 0;
     [[nodiscard]] virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional<QString> = 0;
+    [[nodiscard]] virtual auto getDependecyURL(DependencySearchArgs const& args) const -> std::optional<QString> = 0;
 };
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h
index b91ac5c1..2d6049ba 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.h
+++ b/launcher/modplatform/modrinth/ModrinthAPI.h
@@ -12,13 +12,9 @@
 
 class ModrinthAPI : public NetworkResourceAPI {
    public:
-    auto currentVersion(QString hash,
-                        QString hash_format,
-                        QByteArray* response) -> Task::Ptr;
+    auto currentVersion(QString hash, QString hash_format, QByteArray* response) -> Task::Ptr;
 
-    auto currentVersions(const QStringList& hashes,
-                         QString hash_format,
-                         QByteArray* response) -> Task::Ptr;
+    auto currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response) -> Task::Ptr;
 
     auto latestVersion(QString hash,
                        QString hash_format,
@@ -28,8 +24,8 @@ class ModrinthAPI : public NetworkResourceAPI {
 
     auto latestVersions(const QStringList& hashes,
                         QString hash_format,
-                       std::optional<std::list<Version>> mcVersions,
-                       std::optional<ModLoaderTypes> loaders,
+                        std::optional<std::list<Version>> mcVersions,
+                        std::optional<ModLoaderTypes> loaders,
                         QByteArray* response) -> Task::Ptr;
 
     Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override;
@@ -42,7 +38,7 @@ class ModrinthAPI : public NetworkResourceAPI {
     static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList
     {
         QStringList l;
-        for (auto loader : {Forge, Fabric, Quilt}) {
+        for (auto loader : { Forge, Fabric, Quilt }) {
             if (types & loader) {
                 l << getModLoaderString(loader);
             }
@@ -55,8 +51,7 @@ class ModrinthAPI : public NetworkResourceAPI {
     static auto getModLoaderFilters(ModLoaderTypes types) -> const QString
     {
         QStringList l;
-        for (auto loader : getModLoaderStrings(types))
-        {
+        for (auto loader : getModLoaderStrings(types)) {
             l << QString("\"categories:%1\"").arg(loader);
         }
         return l.join(',');
@@ -139,16 +134,22 @@ class ModrinthAPI : public NetworkResourceAPI {
     auto getGameVersionsArray(std::list<Version> mcVersions) const -> QString
     {
         QString s;
-        for(auto& ver : mcVersions){
+        for (auto& ver : mcVersions) {
             s += QString("\"versions:%1\",").arg(ver.toString());
         }
-        s.remove(s.length() - 1, 1); //remove last comma
+        s.remove(s.length() - 1, 1);  // remove last comma
         return s.isEmpty() ? QString() : s;
     }
 
-    inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool
-    {
-        return loaders & (Forge | Fabric | Quilt);
-    }
+    inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool { return loaders & (Forge | Fabric | Quilt); }
 
+    [[nodiscard]] std::optional<QString> getDependecyURL(DependencySearchArgs const& args) const override
+    {
+        return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version)
+                                                     : QString("%1/project/%2/version?game_versions=[\"%1\"]&loaders=[\"%1\"]")
+                                                           .arg(BuildConfig.MODRINTH_PROD_URL)
+                                                           .arg(args.dependency.addonId.toString())
+                                                           .arg(args.mcVersion.toString())
+                                                           .arg(getModLoaderStrings(args.loader).join("\",\""));
+    };
 };
-- 
cgit 


From 4fe497cd682258ca80501be2ad616de7a40043d9 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 14 Apr 2023 23:02:33 +0300
Subject: First working version with curseforge mods

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/CMakeLists.txt                            |  4 ++
 launcher/ResourceDownloadTask.h                    | 51 ++++++++++----------
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 54 +++++++++++++++-------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   | 16 ++++---
 launcher/modplatform/flame/FlameModIndex.cpp       | 48 +++++++++++++------
 launcher/modplatform/flame/FlameModIndex.h         |  6 +--
 launcher/modplatform/flame/FlamePackIndex.h        | 10 ++--
 .../modplatform/modrinth/ModrinthPackIndex.cpp     | 19 ++++++++
 launcher/modplatform/modrinth/ModrinthPackIndex.h  |  3 +-
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     | 40 ++++++++++++----
 launcher/ui/pages/modplatform/ModModel.cpp         | 16 ++++++-
 launcher/ui/pages/modplatform/ModModel.h           |  2 +
 launcher/ui/pages/modplatform/ResourceModel.cpp    | 39 ++++++++++++++++
 launcher/ui/pages/modplatform/ResourceModel.h      |  8 ++++
 launcher/ui/pages/modplatform/ResourcePackModel.h  |  1 +
 launcher/ui/pages/modplatform/ResourcePage.cpp     |  5 ++
 launcher/ui/pages/modplatform/ResourcePage.h       |  5 +-
 launcher/ui/pages/modplatform/ShaderPackModel.h    |  1 +
 .../modplatform/flame/FlameResourceModels.cpp      | 17 ++++++-
 .../pages/modplatform/flame/FlameResourceModels.h  |  3 ++
 .../modrinth/ModrinthResourceModels.cpp            | 26 +++++++++--
 .../modplatform/modrinth/ModrinthResourceModels.h  |  4 ++
 22 files changed, 293 insertions(+), 85 deletions(-)

(limited to 'launcher')

diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 074570e3..fca8c914 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -359,6 +359,10 @@ set(MINECRAFT_SOURCES
     minecraft/mod/tasks/LocalWorldSaveParseTask.cpp
     minecraft/mod/tasks/LocalResourceParse.h
     minecraft/mod/tasks/LocalResourceParse.cpp
+    minecraft/mod/tasks/GetModDependenciesTask.h
+    minecraft/mod/tasks/GetModDependenciesTask.cpp
+    minecraft/mod/tasks/LocalModGetAllTask.h
+    minecraft/mod/tasks/LocalModGetAllTask.cpp
 
     # Assets
     minecraft/AssetsUtils.h
diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index 73ad2d07..f2118524 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -1,41 +1,45 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  Prism Launcher - Minecraft Launcher
-*  Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
-*  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  Prism Launcher - Minecraft Launcher
+ *  Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
+ *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #pragma once
 
 #include "net/NetJob.h"
 #include "tasks/SequentialTask.h"
 
-#include "modplatform/ModIndex.h"
 #include "minecraft/mod/tasks/LocalModUpdateTask.h"
+#include "modplatform/ModIndex.h"
 
 class ResourceFolderModel;
 
 class ResourceDownloadTask : public SequentialTask {
     Q_OBJECT
-public:
-    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr<ResourceFolderModel> packs, bool is_indexed = true);
+   public:
+    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack,
+                                  ModPlatform::IndexedVersion version,
+                                  const std::shared_ptr<ResourceFolderModel> packs,
+                                  bool is_indexed = true);
     const QString& getFilename() const { return m_pack_version.fileName; }
     const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
+    const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; }
 
-private:
+   private:
     ModPlatform::IndexedPack m_pack;
     ModPlatform::IndexedVersion m_pack_version;
     const std::shared_ptr<ResourceFolderModel> m_pack_model;
@@ -47,11 +51,8 @@ private:
     void downloadFailed(QString reason);
     void downloadSucceeded();
 
-    std::tuple<QString, QString> to_delete {"", ""};
+    std::tuple<QString, QString> to_delete{ "", "" };
 
-private slots:
+   private slots:
     void hasOldResource(QString name, QString filename);
 };
-
-
-
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index dcff1028..9cc227f2 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -30,11 +30,12 @@
 #include <windows.h>
 #endif
 
-GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask& api)
+GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api)
     : m_selected(selected), m_getDependenciesVersionAPI(api)
 {
     m_getAllMods = makeShared<LocalModGetAllTask>(index_dir);
     m_getNetworkDep = makeShared<SequentialTask>(this, "GetDepInfo");
+    connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit);
     QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList<Metadata::ModStruct> mods) {
         m_mods = mods;
         prepareDependecies();
@@ -49,6 +50,8 @@ void GetModDependenciesTask::executeTask()
 {
     setStatus(tr("Geting all mods"));
     m_getAllMods->start();
+    loop.exec();
+    emitSucceeded();
 }
 
 auto GetModDependenciesTask::abort() -> bool
@@ -61,22 +64,21 @@ void GetModDependenciesTask::prepareDependecies()
 {
     auto c_dependencies = getDependenciesForVersions(m_selected);
     if (c_dependencies.length() == 0) {
-        emitSucceeded();
+        m_getNetworkDep->start();
         return;
     }
     for (auto dep : c_dependencies) {
-        auto task = m_getDependenciesVersionAPI(
-            dep, 20, [this](QList<ModPlatform::IndexedVersion> new_versions, int level) { addDependecies(new_versions, level - 1); });
+        auto task = m_getDependenciesVersionAPI(dep, [this](ModPlatform::IndexedVersion new_version) { addDependecies(new_version, 20); });
         m_getNetworkDep->addTask(task);
     }
     m_getNetworkDep->start();
 }
 
-void GetModDependenciesTask::addDependecies(QList<ModPlatform::IndexedVersion> new_versions, int level)
+void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_version, int level)
 {
     // some mutex?
-    m_dependencies.append(new_versions);
-    auto c_dependencies = getDependenciesForVersions(m_selected);
+    m_dependencies.append(new_version);
+    auto c_dependencies = getDependenciesForVersion(new_version);
     if (c_dependencies.length() == 0) {
         return;
     }
@@ -85,7 +87,7 @@ void GetModDependenciesTask::addDependecies(QList<ModPlatform::IndexedVersion> n
     }
     for (auto dep : c_dependencies) {
         auto task = m_getDependenciesVersionAPI(
-            dep, 20, [this](QList<ModPlatform::IndexedVersion> new_versions, int level) { addDependecies(new_versions, level - 1); });
+            dep, [this, level](ModPlatform::IndexedVersion new_versions) { addDependecies(new_versions, level - 1); });
         m_getNetworkDep->addTask(task);
     }
 };
@@ -99,18 +101,36 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
                 if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
                                             [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
                     dep == c_dependencies.end()) {  // check the current dependency list
-                    c_dependencies.append(ver_dep);
-                } else if (auto dep =
-                               std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
-                           dep == selected.end()) {  // check the selected versions
-                    c_dependencies.append(ver_dep);
-                } else if (auto dep =
-                               std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
-                           dep == m_mods.end()) {  // check the existing mods
-                    c_dependencies.append(ver_dep);
+                    if (auto dep =
+                            std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                        dep == selected.end()) {  // check the selected versions
+                        if (auto dep =
+                                std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                            dep == m_mods.end()) {  // check the existing mods
+                            c_dependencies.append(ver_dep);
+                        }
+                    }
                 }
             }
         }
     }
     return c_dependencies;
 };
+
+QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(ModPlatform::IndexedVersion version)
+{
+    auto c_dependencies = QList<ModPlatform::Dependency>();
+    for (auto ver_dep : version.dependencies) {
+        if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
+            if (auto dep =
+                    std::find_if(c_dependencies.begin(), c_dependencies.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                dep == c_dependencies.end()) {  // check the current dependency list
+                if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                    dep == m_mods.end()) {  // check the existing mods
+                    c_dependencies.append(ver_dep);
+                }
+            }
+        }
+    }
+    return c_dependencies;
+};
\ No newline at end of file
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 28112bba..4353c1e1 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -18,6 +18,8 @@
 
 #pragma once
 
+#include <qcoreevent.h>
+#include <qeventloop.h>
 #include <QDir>
 #include <functional>
 
@@ -33,24 +35,23 @@ class GetModDependenciesTask : public Task {
     using Ptr = shared_qobject_ptr<GetModDependenciesTask>;
     using LocalModGetAllTaskPtr = shared_qobject_ptr<LocalModGetAllTask>;
 
-    using NewDependecyVersionAPITask =
-        std::function<Task::Ptr(ModPlatform::Dependency, int, std::function<void(QList<ModPlatform::IndexedVersion>, int)>)>;
+    using NewDependecyVersionAPITask = std::function<Task::Ptr(ModPlatform::Dependency, std::function<void(ModPlatform::IndexedVersion)>)>;
 
-    explicit GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask& api);
+    explicit GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api);
 
     auto canAbort() const -> bool override { return true; }
     auto abort() -> bool override;
 
+    auto getDependecies() const -> QList<ModPlatform::IndexedVersion> { return m_dependencies; }
+
    protected slots:
     //! Entry point for tasks.
     void executeTask() override;
 
     void prepareDependecies();
-    void addDependecies(QList<ModPlatform::IndexedVersion>, int);
+    void addDependecies(ModPlatform::IndexedVersion, int);
     QList<ModPlatform::Dependency> getDependenciesForVersions(QList<ModPlatform::IndexedVersion>);
-
-   signals:
-    void getAllMod(QList<Metadata::ModStruct>);
+    QList<ModPlatform::Dependency> getDependenciesForVersion(ModPlatform::IndexedVersion);
 
    private:
     QList<ModPlatform::IndexedVersion> m_selected;
@@ -60,4 +61,5 @@ class GetModDependenciesTask : public Task {
     LocalModGetAllTaskPtr m_getAllMods = nullptr;
     NewDependecyVersionAPITask m_getDependenciesVersionAPI;
     SequentialTask::Ptr m_getNetworkDep;
+    QEventLoop loop;
 };
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
index a820e3a1..38ecb9ab 100644
--- a/launcher/modplatform/flame/FlameModIndex.cpp
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -39,15 +39,15 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj)
     auto links_obj = Json::ensureObject(obj, "links");
 
     pack.extraData.issuesUrl = Json::ensureString(links_obj, "issuesUrl");
-    if(pack.extraData.issuesUrl.endsWith('/'))
+    if (pack.extraData.issuesUrl.endsWith('/'))
         pack.extraData.issuesUrl.chop(1);
 
     pack.extraData.sourceUrl = Json::ensureString(links_obj, "sourceUrl");
-    if(pack.extraData.sourceUrl.endsWith('/'))
+    if (pack.extraData.sourceUrl.endsWith('/'))
         pack.extraData.sourceUrl.chop(1);
 
     pack.extraData.wikiUrl = Json::ensureString(links_obj, "wikiUrl");
-    if(pack.extraData.wikiUrl.endsWith('/'))
+    if (pack.extraData.wikiUrl.endsWith('/'))
         pack.extraData.wikiUrl.chop(1);
 
     if (!pack.extraData.body.isEmpty())
@@ -56,7 +56,7 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj)
 
 void FlameMod::loadBody(ModPlatform::IndexedPack& pack, QJsonObject& obj)
 {
-    pack.extraData.body  = api.getModDescription(pack.addonId.toInt());
+    pack.extraData.body = api.getModDescription(pack.addonId.toInt());
 
     if (!pack.extraData.issuesUrl.isEmpty() || !pack.extraData.sourceUrl.isEmpty() || !pack.extraData.wikiUrl.isEmpty())
         pack.extraDataLoaded = true;
@@ -64,12 +64,12 @@ void FlameMod::loadBody(ModPlatform::IndexedPack& pack, QJsonObject& obj)
 
 static QString enumToString(int hash_algorithm)
 {
-    switch(hash_algorithm){
-    default:
-    case 1:
-        return "sha1";
-    case 2:
-        return "md5";
+    switch (hash_algorithm) {
+        default:
+        case 1:
+            return "sha1";
+        case 2:
+            return "md5";
     }
 }
 
@@ -84,12 +84,12 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
 
     for (auto versionIter : arr) {
         auto obj = versionIter.toObject();
-        
+
         auto file = loadIndexedPackVersion(obj);
-        if(!file.addonId.isValid())
+        if (!file.addonId.isValid())
             file.addonId = pack.addonId;
 
-        if(file.fileId.isValid()) // Heuristic to check if the returned value is valid
+        if (file.fileId.isValid())  // Heuristic to check if the returned value is valid
             unsortedVersions.append(file);
     }
 
@@ -169,3 +169,25 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
 
     return file;
 }
+
+ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr)
+{
+    QVector<ModPlatform::IndexedVersion> unsortedVersions;
+    for (auto versionIter : arr) {
+        auto obj = versionIter.toObject();
+
+        auto file = loadIndexedPackVersion(obj);
+        if (!file.addonId.isValid())
+            file.addonId = m.addonId;
+
+        if (file.fileId.isValid())  // Heuristic to check if the returned value is valid
+            unsortedVersions.append(file);
+    }
+
+    auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
+        // dates are in RFC 3339 format
+        return a.date > b.date;
+    };
+    std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
+    return unsortedVersions.front();
+};
diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h
index 33c4a529..306959e0 100644
--- a/launcher/modplatform/flame/FlameModIndex.h
+++ b/launcher/modplatform/flame/FlameModIndex.h
@@ -6,8 +6,8 @@
 
 #include "modplatform/ModIndex.h"
 
-#include "BaseInstance.h"
 #include <QNetworkAccessManager>
+#include "BaseInstance.h"
 
 namespace FlameMod {
 
@@ -19,5 +19,5 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
                              const shared_qobject_ptr<QNetworkAccessManager>& network,
                              const BaseInstance* inst);
 auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion;
-
-}  // namespace FlameMod
+auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion;
+}  // namespace FlameMod
\ No newline at end of file
diff --git a/launcher/modplatform/flame/FlamePackIndex.h b/launcher/modplatform/flame/FlamePackIndex.h
index 1ca0fc0e..b089b722 100644
--- a/launcher/modplatform/flame/FlamePackIndex.h
+++ b/launcher/modplatform/flame/FlamePackIndex.h
@@ -4,6 +4,7 @@
 #include <QMetaType>
 #include <QString>
 #include <QVector>
+#include "modplatform/ModIndex.h"
 
 namespace Flame {
 
@@ -27,8 +28,7 @@ struct ModpackExtra {
     QString sourceUrl;
 };
 
-struct IndexedPack
-{
+struct IndexedPack {
     int addonId;
     QString name;
     QString description;
@@ -43,9 +43,9 @@ struct IndexedPack
     ModpackExtra extra;
 };
 
-void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
+void loadIndexedPack(IndexedPack& m, QJsonObject& obj);
 void loadIndexedInfo(IndexedPack&, QJsonObject&);
-void loadIndexedPackVersions(IndexedPack & m, QJsonArray & arr);
-}
+void loadIndexedPackVersions(IndexedPack& m, QJsonArray& arr);
+}  // namespace Flame
 
 Q_DECLARE_METATYPE(Flame::IndexedPack)
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index 8e97ee7c..9f898c39 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -214,3 +214,22 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
 
     return {};
 }
+
+auto Modrinth::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    QVector<ModPlatform::IndexedVersion> unsortedVersions;
+
+    for (auto versionIter : arr) {
+        auto obj = versionIter.toObject();
+        auto file = loadIndexedPackVersion(obj);
+
+        if (file.fileId.isValid())  // Heuristic to check if the returned value is valid
+            unsortedVersions.append(file);
+    }
+    auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
+        // dates are in RFC 3339 format
+        return a.date > b.date;
+    };
+    std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
+    return unsortedVersions.front();
+}
\ No newline at end of file
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h
index e73e4b18..8aa53a11 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.h
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h
@@ -19,8 +19,8 @@
 
 #include "modplatform/ModIndex.h"
 
-#include "BaseInstance.h"
 #include <QNetworkAccessManager>
+#include "BaseInstance.h"
 
 namespace Modrinth {
 
@@ -31,5 +31,6 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
                              const shared_qobject_ptr<QNetworkAccessManager>& network,
                              const BaseInstance* inst);
 auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion;
+auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion;
 
 }  // namespace Modrinth
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index edb7d063..e1041d95 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -18,17 +18,22 @@
  */
 
 #include "ResourceDownloadDialog.h"
+#include <qeventloop.h>
+#include <qlist.h>
 
 #include <QPushButton>
+#include <algorithm>
+#include <cstddef>
 
 #include "Application.h"
 #include "ResourceDownloadTask.h"
 
 #include "minecraft/mod/ModFolderModel.h"
 #include "minecraft/mod/ResourcePackFolderModel.h"
-#include "minecraft/mod/TexturePackFolderModel.h"
 #include "minecraft/mod/ShaderPackFolderModel.h"
+#include "minecraft/mod/TexturePackFolderModel.h"
 
+#include "modplatform/ModIndex.h"
 #include "ui/dialogs/ReviewMessageBox.h"
 
 #include "ui/pages/modplatform/ResourcePage.h"
@@ -41,7 +46,10 @@
 namespace ResourceDownload {
 
 ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, const std::shared_ptr<ResourceFolderModel> base_model)
-    : QDialog(parent), m_base_model(base_model), m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel), m_vertical_layout(this)
+    : QDialog(parent)
+    , m_base_model(base_model)
+    , m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
+    , m_vertical_layout(this)
 {
     setObjectName(QStringLiteral("ResourceDownloadDialog"));
 
@@ -102,7 +110,8 @@ void ResourceDownloadDialog::initializeContainer()
 void ResourceDownloadDialog::connectButtons()
 {
     auto OkButton = m_buttons.button(QDialogButtonBox::Ok);
-    OkButton->setToolTip(tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString()));
+    OkButton->setToolTip(
+        tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString()));
     connect(OkButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm);
 
     auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel);
@@ -120,6 +129,26 @@ void ResourceDownloadDialog::confirm()
     auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString()));
     confirm_dialog->retranslateUi(resourcesString());
 
+    if (auto model = dynamic_cast<ModFolderModel*>(getBaseModel().get()); model) {
+        QList<ModPlatform::IndexedVersion> selectedVers;
+        for (auto& task : keys) {
+            auto selected = m_selected.constFind(task).value();
+            selectedVers.append(selected->getVersion());
+        }
+
+        auto dir = model->indexDir();
+        auto dependencies = m_selectedPage->getDependecies(dir, selectedVers);
+
+        for (auto dep : dependencies) {
+            dep.is_currently_selected = true;
+            auto pack = ModPlatform::IndexedPack{
+                .addonId = dep.addonId, .provider = ModPlatform::ResourceProvider::FLAME, .name = dep.fileName, .slug = dep.fileName
+            };
+            m_selected.insert(dep.fileName, makeShared<ResourceDownloadTask>(pack, dep, getBaseModel(), true));
+        }
+
+        keys = m_selected.keys();
+    }
     for (auto& task : keys) {
         auto selected = m_selected.constFind(task).value();
         confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() });
@@ -205,8 +234,6 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s
     m_selectedPage->setSearchTerm(prev_page->getSearchTerm());
 }
 
-
-
 ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr<ModFolderModel>& mods, BaseInstance* instance)
     : ResourceDownloadDialog(parent, mods), m_instance(instance)
 {
@@ -232,7 +259,6 @@ QList<BasePage*> ModDownloadDialog::getPages()
     return pages;
 }
 
-
 ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent,
                                                        const std::shared_ptr<ResourcePackFolderModel>& resource_packs,
                                                        BaseInstance* instance)
@@ -258,7 +284,6 @@ QList<BasePage*> ResourcePackDownloadDialog::getPages()
     return pages;
 }
 
-
 TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent,
                                                      const std::shared_ptr<TexturePackFolderModel>& resource_packs,
                                                      BaseInstance* instance)
@@ -284,7 +309,6 @@ QList<BasePage*> TexturePackDownloadDialog::getPages()
     return pages;
 }
 
-
 ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent,
                                                    const std::shared_ptr<ShaderPackFolderModel>& shaders,
                                                    BaseInstance* instance)
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 3ffe6cb0..bdbfe460 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -24,7 +24,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
 
     std::optional<std::list<Version>> versions{};
 
-    { // Version filter
+    {  // Version filter
         if (!m_filter->versions.empty())
             versions = m_filter->versions;
     }
@@ -49,6 +49,20 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
     return { pack, versions, profile->getModLoaders() };
 }
 
+ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(ModPlatform::Dependency& dep)
+{
+    auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
+
+    Q_ASSERT(profile);
+    Q_ASSERT(m_filter);
+
+    std::optional<std::list<Version>> versions{};
+    if (!m_filter->versions.empty())
+        versions = m_filter->versions;
+
+    return { dep, versions->front(), profile->getModLoaders().value() };
+};
+
 ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
 {
     auto& pack = m_packs[entry.row()];
diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h
index 5d4a7785..ca536f8f 100644
--- a/launcher/ui/pages/modplatform/ModModel.h
+++ b/launcher/ui/pages/modplatform/ModModel.h
@@ -32,6 +32,7 @@ class ModModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0;
+    ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0;
 
     void setFilter(std::shared_ptr<ModFilterWidget::Filter> filter) { m_filter = filter; }
 
@@ -39,6 +40,7 @@ class ModModel : public ResourceModel {
     ResourceAPI::SearchArgs createSearchArguments() override;
     ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
     ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override;
+    ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) override;
 
    protected:
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0;
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index db7d26f8..42dd8dae 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -3,6 +3,8 @@
 // SPDX-License-Identifier: GPL-3.0-only
 
 #include "ResourceModel.h"
+#include <qdir.h>
+#include <qlist.h>
 
 #include <QCryptographicHash>
 #include <QIcon>
@@ -14,6 +16,7 @@
 #include "BuildConfig.h"
 #include "Json.h"
 
+#include "minecraft/mod/tasks/GetModDependenciesTask.h"
 #include "net/Download.h"
 #include "net/NetJob.h"
 
@@ -321,6 +324,11 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra
 {
     NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions");
 }
+ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr)
+{
+    NEED_FOR_CALLBACK_ASSERT("loadDependencyVersions");
+    return {};
+}
 
 /* Default callbacks */
 
@@ -441,4 +449,35 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
     emit projectInfoUpdated();
 }
 
+QList<ModPlatform::IndexedVersion> ResourceModel::getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> selected)
+{
+    auto task = new GetModDependenciesTask(
+        dir, selected, [this](ModPlatform::Dependency dependency, std::function<void(ModPlatform::IndexedVersion)> succeeded) -> Task::Ptr {
+            auto args{ createDependecyArguments(dependency) };
+            auto callbacks{ createDependecyCallbacks() };
+
+            // Use default if no callbacks are set
+            if (!callbacks.on_succeed)
+                callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto pack) {
+                    ModPlatform::IndexedVersion ver;
+                    try {
+                        auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
+                        ver = loadDependencyVersions(dependency, arr);
+                    } catch (const JSONValidationError& e) {
+                        qDebug() << doc;
+                        qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
+                        return;
+                    }
+
+                    succeeded(ver);
+                };
+
+            return m_api->getDependencyVersion(std::move(args), std::move(callbacks));
+        });
+
+    task->start();
+
+    return task->getDependecies();
+};
+
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 46a02d6e..0292b84b 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -4,12 +4,14 @@
 
 #pragma once
 
+#include <qdir.h>
 #include <optional>
 
 #include <QAbstractListModel>
 
 #include "QObjectPtr.h"
 
+#include "modplatform/ModIndex.h"
 #include "modplatform/ResourceAPI.h"
 
 #include "tasks/ConcurrentTask.h"
@@ -68,6 +70,9 @@ class ResourceModel : public QAbstractListModel {
     virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0;
     virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; }
 
+    virtual ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) { return {}; };
+    virtual ResourceAPI::DependencySearchCallbacks createDependecyCallbacks() { return {}; }
+
     /** Requests the API for more entries. */
     virtual void search();
 
@@ -80,6 +85,8 @@ class ResourceModel : public QAbstractListModel {
     /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */
     std::optional<QIcon> getIcon(QModelIndex&, const QUrl&);
 
+    QList<ModPlatform::IndexedVersion> getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> m_selected);
+
    protected:
     /** Resets the model's data. */
     void clearData();
@@ -104,6 +111,7 @@ class ResourceModel : public QAbstractListModel {
     virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&);
     virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&);
     virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&);
+    virtual ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr);
 
    protected:
     /* Basic search parameters */
diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h
index e2b4a195..40b271d6 100644
--- a/launcher/ui/pages/modplatform/ResourcePackModel.h
+++ b/launcher/ui/pages/modplatform/ResourcePackModel.h
@@ -28,6 +28,7 @@ class ResourcePackResourceModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0;
+    ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0;
 
    public slots:
     ResourceAPI::SearchArgs createSearchArguments() override;
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index bbd465bc..ec43521f 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -408,4 +408,9 @@ void ResourcePage::openUrl(const QUrl& url)
     QDesktopServices::openUrl(url);
 }
 
+QList<ModPlatform::IndexedVersion> ResourcePage::getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> selected)
+{
+    return m_model->getDependecies(dir, selected);
+};
+
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index 1896d53e..07f87929 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <qdir.h>
 #include <QTimer>
 #include <QWidget>
 
@@ -75,9 +76,11 @@ class ResourcePage : public QWidget, public BasePage {
     virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
     virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
 
+    QList<ModPlatform::IndexedVersion> getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> m_selected);
+
    protected slots:
     virtual void triggerSearch() {}
-   
+
     void onSelectionChanged(QModelIndex first, QModelIndex second);
     void onVersionSelectionChanged(QString data);
     void onResourceSelected();
diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h
index f3c695e9..60d74777 100644
--- a/launcher/ui/pages/modplatform/ShaderPackModel.h
+++ b/launcher/ui/pages/modplatform/ShaderPackModel.h
@@ -28,6 +28,7 @@ class ShaderPackResourceModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0;
+    ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0;
 
    public slots:
     ResourceAPI::SearchArgs createSearchArguments() override;
diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
index e3d0bc14..563ff963 100644
--- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
@@ -29,6 +29,11 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr
     FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
+auto FlameModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return FlameMod::loadDependencyVersions(m, arr);
+};
+
 auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return Json::ensureArray(obj.object(), "data");
@@ -52,6 +57,11 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m
     FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
+auto FlameResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return FlameMod::loadDependencyVersions(m, arr);
+};
+
 auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return Json::ensureArray(obj.object(), "data");
@@ -81,13 +91,18 @@ void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m,
         auto const& mc_versions = version.mcVersion;
 
         if (std::any_of(mc_versions.constBegin(), mc_versions.constEnd(),
-                        [this](auto const& mc_version){ return Version(mc_version) <= maximumTexturePackVersion(); }))
+                        [this](auto const& mc_version) { return Version(mc_version) <= maximumTexturePackVersion(); }))
             filtered_versions.push_back(version);
     }
 
     m.versions = filtered_versions;
 }
 
+auto FlameTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return FlameMod::loadDependencyVersions(m, arr);
+};
+
 ResourceAPI::SearchArgs FlameTexturePackModel::createSearchArguments()
 {
     auto args = TexturePackResourceModel::createSearchArguments();
diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
index 0252ac40..2f4413ac 100644
--- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
+++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
@@ -24,6 +24,7 @@ class FlameModModel : public ModModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -42,6 +43,7 @@ class FlameResourcePackModel : public ResourcePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -60,6 +62,7 @@ class FlameTexturePackModel : public TexturePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     ResourceAPI::SearchArgs createSearchArguments() override;
     ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
index f5d1cc28..047e3aaa 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
@@ -42,12 +42,17 @@ void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJso
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
+auto ModrinthModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return ::Modrinth::loadDependencyVersions(m, arr);
+};
+
 auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
 }
 
-ModrinthResourcePackModel::ModrinthResourcePackModel(const BaseInstance& base)  : ResourcePackResourceModel(base, new ModrinthAPI){}
+ModrinthResourcePackModel::ModrinthResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new ModrinthAPI) {}
 
 void ModrinthResourcePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)
 {
@@ -64,12 +69,17 @@ void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
+auto ModrinthResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return ::Modrinth::loadDependencyVersions(m, arr);
+};
+
 auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
 }
 
-ModrinthTexturePackModel::ModrinthTexturePackModel(const BaseInstance& base)  : TexturePackResourceModel(base, new ModrinthAPI){}
+ModrinthTexturePackModel::ModrinthTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new ModrinthAPI) {}
 
 void ModrinthTexturePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)
 {
@@ -86,12 +96,17 @@ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack&
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
+auto ModrinthTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return ::Modrinth::loadDependencyVersions(m, arr);
+};
+
 auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
 }
 
-ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base)  : ShaderPackResourceModel(base, new ModrinthAPI){}
+ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new ModrinthAPI) {}
 
 void ModrinthShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)
 {
@@ -108,6 +123,11 @@ void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack&
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
+auto ModrinthShaderPackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+{
+    return ::Modrinth::loadDependencyVersions(m, arr);
+};
+
 auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
index b351b19b..77157a41 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
@@ -40,6 +40,7 @@ class ModrinthModModel : public ModModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -58,6 +59,7 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -76,6 +78,7 @@ class ModrinthTexturePackModel : public TexturePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -94,6 +97,7 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
-- 
cgit 


From 5079ce8d64d68d3fd2925baf18976385e44ebdc2 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 14 Apr 2023 23:18:37 +0300
Subject: Fixed headers

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 1 +
 launcher/minecraft/mod/tasks/GetModDependenciesTask.h   | 3 +--
 launcher/ui/dialogs/ResourceDownloadDialog.cpp          | 4 ++--
 launcher/ui/pages/modplatform/ResourceModel.cpp         | 4 ++--
 launcher/ui/pages/modplatform/ResourceModel.h           | 2 +-
 launcher/ui/pages/modplatform/ResourcePage.h            | 3 +--
 6 files changed, 8 insertions(+), 9 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 9cc227f2..1247e763 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -19,6 +19,7 @@
 
 #include "GetModDependenciesTask.h"
 
+#include <QDebug>
 #include "QObjectPtr.h"
 #include "minecraft/mod/MetadataHandler.h"
 #include "minecraft/mod/tasks/LocalModGetAllTask.h"
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 4353c1e1..1670cb6f 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -18,9 +18,8 @@
 
 #pragma once
 
-#include <qcoreevent.h>
-#include <qeventloop.h>
 #include <QDir>
+#include <QEventLoop>
 #include <functional>
 
 #include "minecraft/mod/MetadataHandler.h"
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index e1041d95..143a6e50 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -18,8 +18,8 @@
  */
 
 #include "ResourceDownloadDialog.h"
-#include <qeventloop.h>
-#include <qlist.h>
+#include <QEventLoop>
+#include <QList>
 
 #include <QPushButton>
 #include <algorithm>
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index 42dd8dae..eb8c1820 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -3,8 +3,8 @@
 // SPDX-License-Identifier: GPL-3.0-only
 
 #include "ResourceModel.h"
-#include <qdir.h>
-#include <qlist.h>
+#include <QDir>
+#include <QList>
 
 #include <QCryptographicHash>
 #include <QIcon>
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 0292b84b..5dbef794 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <qdir.h>
+#include <QDir>
 #include <optional>
 
 #include <QAbstractListModel>
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index 07f87929..4fffd506 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -4,12 +4,11 @@
 
 #pragma once
 
-#include <qdir.h>
+#include <QDir>
 #include <QTimer>
 #include <QWidget>
 
 #include "modplatform/ModIndex.h"
-#include "modplatform/ResourceAPI.h"
 
 #include "ui/pages/BasePage.h"
 #include "ui/widgets/ProgressWidget.h"
-- 
cgit 


From bcea19b957bb0db4270b7573540af40143cca7de Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sat, 15 Apr 2023 00:10:45 +0300
Subject: Tried to fix codeQL

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 17 +++++++++--------
 launcher/minecraft/mod/tasks/GetModDependenciesTask.h   |  9 +++++----
 launcher/ui/pages/modplatform/ModModel.cpp              |  2 +-
 launcher/ui/pages/modplatform/ModModel.h                |  2 +-
 launcher/ui/pages/modplatform/ResourceModel.cpp         |  3 ++-
 launcher/ui/pages/modplatform/ResourceModel.h           |  2 +-
 6 files changed, 19 insertions(+), 16 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 1247e763..aeaa4b5b 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -75,7 +75,7 @@ void GetModDependenciesTask::prepareDependecies()
     m_getNetworkDep->start();
 }
 
-void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_version, int level)
+void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& new_version, int level)
 {
     // some mutex?
     m_dependencies.append(new_version);
@@ -85,6 +85,7 @@ void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_vers
     }
     if (level == 0) {
         qWarning() << "Dependency cycle exeeded";
+        return;
     }
     for (auto dep : c_dependencies) {
         auto task = m_getDependenciesVersionAPI(
@@ -93,20 +94,20 @@ void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_vers
     }
 };
 
-QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersions(QList<ModPlatform::IndexedVersion> selected)
+QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersions(const QList<ModPlatform::IndexedVersion>& selected)
 {
     auto c_dependencies = QList<ModPlatform::Dependency>();
     for (auto version : selected) {
         for (auto ver_dep : version.dependencies) {
             if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
                 if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                            [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                                            [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
                     dep == c_dependencies.end()) {  // check the current dependency list
                     if (auto dep =
-                            std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                            std::find_if(selected.begin(), selected.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
                         dep == selected.end()) {  // check the selected versions
                         if (auto dep =
-                                std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                                std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
                             dep == m_mods.end()) {  // check the existing mods
                             c_dependencies.append(ver_dep);
                         }
@@ -118,15 +119,15 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
     return c_dependencies;
 };
 
-QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(ModPlatform::IndexedVersion version)
+QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version)
 {
     auto c_dependencies = QList<ModPlatform::Dependency>();
     for (auto ver_dep : version.dependencies) {
         if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
             if (auto dep =
-                    std::find_if(c_dependencies.begin(), c_dependencies.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                    std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
                 dep == c_dependencies.end()) {  // check the current dependency list
-                if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
                     dep == m_mods.end()) {  // check the existing mods
                     c_dependencies.append(ver_dep);
                 }
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 1670cb6f..7f7e1fb1 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -34,7 +34,8 @@ class GetModDependenciesTask : public Task {
     using Ptr = shared_qobject_ptr<GetModDependenciesTask>;
     using LocalModGetAllTaskPtr = shared_qobject_ptr<LocalModGetAllTask>;
 
-    using NewDependecyVersionAPITask = std::function<Task::Ptr(ModPlatform::Dependency, std::function<void(ModPlatform::IndexedVersion)>)>;
+    using NewDependecyVersionAPITask =
+        std::function<Task::Ptr(const ModPlatform::Dependency&, std::function<void(const ModPlatform::IndexedVersion&)>)>;
 
     explicit GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api);
 
@@ -48,9 +49,9 @@ class GetModDependenciesTask : public Task {
     void executeTask() override;
 
     void prepareDependecies();
-    void addDependecies(ModPlatform::IndexedVersion, int);
-    QList<ModPlatform::Dependency> getDependenciesForVersions(QList<ModPlatform::IndexedVersion>);
-    QList<ModPlatform::Dependency> getDependenciesForVersion(ModPlatform::IndexedVersion);
+    void addDependecies(const ModPlatform::IndexedVersion&, int);
+    QList<ModPlatform::Dependency> getDependenciesForVersions(const QList<ModPlatform::IndexedVersion>&);
+    QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&);
 
    private:
     QList<ModPlatform::IndexedVersion> m_selected;
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index bdbfe460..19c20e65 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -49,7 +49,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
     return { pack, versions, profile->getModLoaders() };
 }
 
-ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(ModPlatform::Dependency& dep)
+ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(const ModPlatform::Dependency& dep)
 {
     auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
 
diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h
index ca536f8f..97638902 100644
--- a/launcher/ui/pages/modplatform/ModModel.h
+++ b/launcher/ui/pages/modplatform/ModModel.h
@@ -40,7 +40,7 @@ class ModModel : public ResourceModel {
     ResourceAPI::SearchArgs createSearchArguments() override;
     ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
     ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override;
-    ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) override;
+    ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) override;
 
    protected:
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0;
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index eb8c1820..75585d6f 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -452,7 +452,8 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
 QList<ModPlatform::IndexedVersion> ResourceModel::getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> selected)
 {
     auto task = new GetModDependenciesTask(
-        dir, selected, [this](ModPlatform::Dependency dependency, std::function<void(ModPlatform::IndexedVersion)> succeeded) -> Task::Ptr {
+        dir, selected,
+        [this](const ModPlatform::Dependency& dependency, std::function<void(const ModPlatform::IndexedVersion&)> succeeded) -> Task::Ptr {
             auto args{ createDependecyArguments(dependency) };
             auto callbacks{ createDependecyCallbacks() };
 
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 5dbef794..ce327c3b 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -70,7 +70,7 @@ class ResourceModel : public QAbstractListModel {
     virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0;
     virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; }
 
-    virtual ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) { return {}; };
+    virtual ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) { return {}; };
     virtual ResourceAPI::DependencySearchCallbacks createDependecyCallbacks() { return {}; }
 
     /** Requests the API for more entries. */
-- 
cgit 


From 7bd26ce4687b498fb91d42594da07fea1eca5552 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 17 Apr 2023 00:49:35 +0300
Subject: Semi fixed the Modrinth dependency implementation

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 22 ++++++++++++----------
 launcher/modplatform/ResourceAPI.h                 |  2 +-
 .../modplatform/modrinth/ModrinthPackIndex.cpp     |  5 +++--
 launcher/ui/pages/modplatform/ResourceModel.cpp    | 11 +++++++++--
 4 files changed, 25 insertions(+), 15 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index aeaa4b5b..92e652c0 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -69,7 +69,8 @@ void GetModDependenciesTask::prepareDependecies()
         return;
     }
     for (auto dep : c_dependencies) {
-        auto task = m_getDependenciesVersionAPI(dep, [this](ModPlatform::IndexedVersion new_version) { addDependecies(new_version, 20); });
+        auto task =
+            m_getDependenciesVersionAPI(dep, [this](const ModPlatform::IndexedVersion& new_version) { addDependecies(new_version, 20); });
         m_getNetworkDep->addTask(task);
     }
     m_getNetworkDep->start();
@@ -89,7 +90,7 @@ void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& n
     }
     for (auto dep : c_dependencies) {
         auto task = m_getDependenciesVersionAPI(
-            dep, [this, level](ModPlatform::IndexedVersion new_versions) { addDependecies(new_versions, level - 1); });
+            dep, [this, level](const ModPlatform::IndexedVersion& new_versions) { addDependecies(new_versions, level - 1); });
         m_getNetworkDep->addTask(task);
     }
 };
@@ -101,13 +102,13 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
         for (auto ver_dep : version.dependencies) {
             if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
                 if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                            [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                                            [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
                     dep == c_dependencies.end()) {  // check the current dependency list
-                    if (auto dep =
-                            std::find_if(selected.begin(), selected.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+                    if (auto dep = std::find_if(selected.begin(), selected.end(),
+                                                [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
                         dep == selected.end()) {  // check the selected versions
-                        if (auto dep =
-                                std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                        if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
+                                                    [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; });
                             dep == m_mods.end()) {  // check the existing mods
                             c_dependencies.append(ver_dep);
                         }
@@ -124,10 +125,11 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
     auto c_dependencies = QList<ModPlatform::Dependency>();
     for (auto ver_dep : version.dependencies) {
         if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
-            if (auto dep =
-                    std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; });
+            if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
+                                        [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
                 dep == c_dependencies.end()) {  // check the current dependency list
-                if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; });
+                if (auto dep =
+                        std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; });
                     dep == m_mods.end()) {  // check the existing mods
                     c_dependencies.append(ver_dep);
                 }
diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h
index a8e144dc..c23444b3 100644
--- a/launcher/modplatform/ResourceAPI.h
+++ b/launcher/modplatform/ResourceAPI.h
@@ -126,7 +126,7 @@ class ResourceAPI {
     };
 
     struct DependencySearchCallbacks {
-        std::function<void(QJsonDocument&, ModPlatform::Dependency)> on_succeed;
+        std::function<void(QJsonDocument&, const ModPlatform::Dependency&)> on_succeed;
     };
 
    public:
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index 9f898c39..ee957680 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -22,6 +22,7 @@
 #include "Json.h"
 #include "minecraft/MinecraftInstance.h"
 #include "minecraft/PackProfile.h"
+#include "modplatform/ModIndex.h"
 
 static ModrinthAPI api;
 static ModPlatform::ProviderCapabilities ProviderCaps;
@@ -144,7 +145,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
         auto dep = Json::ensureObject(d);
         ModPlatform::Dependency dependency;
         dependency.addonId = Json::requireString(dep, "project_id");
-        dependency.version = Json::requireString(dep, "version_id");
+        dependency.version = Json::ensureString(dep, "version_id");
         auto depType = Json::requireString(dep, "dependency_type");
 
         if (depType == "required")
@@ -231,5 +232,5 @@ auto Modrinth::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr
         return a.date > b.date;
     };
     std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
-    return unsortedVersions.front();
+    return unsortedVersions.length() != 0 ? unsortedVersions.front() : ModPlatform::IndexedVersion();
 }
\ No newline at end of file
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index 75585d6f..c1ffd0da 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -459,11 +459,18 @@ QList<ModPlatform::IndexedVersion> ResourceModel::getDependecies(QDir& dir, QLis
 
             // Use default if no callbacks are set
             if (!callbacks.on_succeed)
-                callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto pack) {
+                callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto& pack) {
                     ModPlatform::IndexedVersion ver;
                     try {
-                        auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
+                        auto arr = dependency.version.length() != 0 && doc.isObject()
+                                       ? Json::toJsonArray(QList<QJsonObject>() << doc.object())
+                                   : doc.isObject() ? Json::ensureArray(doc.object(), "data")
+                                                    : doc.array();
                         ver = loadDependencyVersions(dependency, arr);
+                        if (!ver.addonId.isValid()) {
+                            qWarning() << "Error while reading " << debugName() << " resource version empty ";
+                            qDebug() << doc;
+                        }
                     } catch (const JSONValidationError& e) {
                         qDebug() << doc;
                         qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
-- 
cgit 


From f3f8f3574af20e279e41d3a02f337d5d59fc4a7e Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 17 Apr 2023 01:10:02 +0300
Subject: Small headers removal

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp |  8 ------
 .../minecraft/mod/tasks/LocalModUpdateTask.cpp     | 33 +++++++++++-----------
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     |  1 -
 3 files changed, 16 insertions(+), 26 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 92e652c0..f1f8581f 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -27,10 +27,6 @@
 #include "tasks/ConcurrentTask.h"
 #include "tasks/SequentialTask.h"
 
-#ifdef Q_OS_WIN32
-#include <windows.h>
-#endif
-
 GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api)
     : m_selected(selected), m_getDependenciesVersionAPI(api)
 {
@@ -41,10 +37,6 @@ GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform
         m_mods = mods;
         prepareDependecies();
     });
-
-#ifdef Q_OS_WIN32
-    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
-#endif
 }
 
 void GetModDependenciesTask::executeTask()
diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp
index cc4e252c..6b139ca1 100644
--- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp
@@ -1,25 +1,24 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  PolyMC - Minecraft Launcher
-*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
-*  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #include "LocalModUpdateTask.h"
 
-#include "Application.h"
 #include "FileSystem.h"
 #include "minecraft/mod/MetadataHandler.h"
 
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 143a6e50..fe4692d6 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -23,7 +23,6 @@
 
 #include <QPushButton>
 #include <algorithm>
-#include <cstddef>
 
 #include "Application.h"
 #include "ResourceDownloadTask.h"
-- 
cgit 


From 31e84780a882622385dda0c574c128046d625eba Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 17 Apr 2023 20:03:49 +0300
Subject: Hope to fix windows build errors

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/dialogs/ResourceDownloadDialog.cpp | 4 +---
 launcher/ui/pages/modplatform/ResourcePage.cpp | 3 ---
 2 files changed, 1 insertion(+), 6 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index fe4692d6..610f2449 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -140,9 +140,7 @@ void ResourceDownloadDialog::confirm()
 
         for (auto dep : dependencies) {
             dep.is_currently_selected = true;
-            auto pack = ModPlatform::IndexedPack{
-                .addonId = dep.addonId, .provider = ModPlatform::ResourceProvider::FLAME, .name = dep.fileName, .slug = dep.fileName
-            };
+            auto pack = ModPlatform::IndexedPack{ dep.addonId, ModPlatform::ResourceProvider::FLAME, dep.fileName, dep.fileName };
             m_selected.insert(dep.fileName, makeShared<ResourceDownloadTask>(pack, dep, getBaseModel(), true));
         }
 
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index ec43521f..02412fd9 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -43,9 +43,6 @@
 #include <QKeyEvent>
 
 #include "Markdown.h"
-#include "ResourceDownloadTask.h"
-
-#include "minecraft/MinecraftInstance.h"
 
 #include "ui/dialogs/ResourceDownloadDialog.h"
 #include "ui/pages/modplatform/ResourceModel.h"
-- 
cgit 


From fac33498dbd50fd9af60164e786534615586d6ac Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 17 Apr 2023 20:41:00 +0300
Subject: Made some copy by reference

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp   |  2 +-
 launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp       |  2 +-
 launcher/minecraft/mod/tasks/LocalModGetAllTask.h         |  2 +-
 launcher/modplatform/flame/FlameModIndex.cpp              |  2 +-
 launcher/modplatform/flame/FlameModIndex.h                |  2 +-
 launcher/modplatform/modrinth/ModrinthPackIndex.cpp       |  2 +-
 launcher/modplatform/modrinth/ModrinthPackIndex.h         |  2 +-
 launcher/ui/pages/modplatform/ModModel.h                  |  2 +-
 launcher/ui/pages/modplatform/ResourceModel.cpp           | 15 +++++++++------
 launcher/ui/pages/modplatform/ResourceModel.h             |  2 +-
 launcher/ui/pages/modplatform/ResourcePackModel.h         |  2 +-
 launcher/ui/pages/modplatform/ShaderPackModel.h           |  2 +-
 .../ui/pages/modplatform/flame/FlameResourceModels.cpp    |  6 +++---
 launcher/ui/pages/modplatform/flame/FlameResourceModels.h |  6 +++---
 .../pages/modplatform/modrinth/ModrinthResourceModels.cpp |  8 ++++----
 .../pages/modplatform/modrinth/ModrinthResourceModels.h   |  8 ++++----
 16 files changed, 34 insertions(+), 31 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index f1f8581f..7f184765 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -33,7 +33,7 @@ GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform
     m_getAllMods = makeShared<LocalModGetAllTask>(index_dir);
     m_getNetworkDep = makeShared<SequentialTask>(this, "GetDepInfo");
     connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit);
-    QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList<Metadata::ModStruct> mods) {
+    QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMods, [this](QList<Metadata::ModStruct> mods) {
         m_mods = mods;
         prepareDependecies();
     });
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
index 9e4293ff..67058807 100644
--- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
@@ -41,7 +41,7 @@ LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir)
 void LocalModGetAllTask::executeTask()
 {
     setStatus(tr("Geting all mods"));
-    emit getAllMod(Metadata::getAll(m_index_dir));
+    emit getAllMods(Metadata::getAll(m_index_dir));
     emitSucceeded();
 }
 
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
index 09e453e4..bf4b78b7 100644
--- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
+++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
@@ -38,7 +38,7 @@ class LocalModGetAllTask : public Task {
     void executeTask() override;
 
    signals:
-    void getAllMod(QList<Metadata::ModStruct>);
+    void getAllMods(QList<Metadata::ModStruct>);
 
    private:
     QDir m_index_dir;
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
index 38ecb9ab..120bfc91 100644
--- a/launcher/modplatform/flame/FlameModIndex.cpp
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -170,7 +170,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
     return file;
 }
 
-ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr)
+ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr)
 {
     QVector<ModPlatform::IndexedVersion> unsortedVersions;
     for (auto versionIter : arr) {
diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h
index 306959e0..aa0d6f81 100644
--- a/launcher/modplatform/flame/FlameModIndex.h
+++ b/launcher/modplatform/flame/FlameModIndex.h
@@ -19,5 +19,5 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
                              const shared_qobject_ptr<QNetworkAccessManager>& network,
                              const BaseInstance* inst);
 auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion;
-auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion;
+auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion;
 }  // namespace FlameMod
\ No newline at end of file
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index ee957680..879260a3 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -216,7 +216,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
     return {};
 }
 
-auto Modrinth::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto Modrinth::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     QVector<ModPlatform::IndexedVersion> unsortedVersions;
 
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h
index 8aa53a11..a8d986c5 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.h
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h
@@ -31,6 +31,6 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
                              const shared_qobject_ptr<QNetworkAccessManager>& network,
                              const BaseInstance* inst);
 auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion;
-auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion;
+auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion;
 
 }  // namespace Modrinth
diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h
index 97638902..59b27dda 100644
--- a/launcher/ui/pages/modplatform/ModModel.h
+++ b/launcher/ui/pages/modplatform/ModModel.h
@@ -32,7 +32,7 @@ class ModModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0;
-    ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0;
+    ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0;
 
     void setFilter(std::shared_ptr<ModFilterWidget::Filter> filter) { m_filter = filter; }
 
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index c1ffd0da..c1746d41 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -324,7 +324,7 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra
 {
     NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions");
 }
-ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr)
+ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr)
 {
     NEED_FOR_CALLBACK_ASSERT("loadDependencyVersions");
     return {};
@@ -451,7 +451,7 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
 
 QList<ModPlatform::IndexedVersion> ResourceModel::getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> selected)
 {
-    auto task = new GetModDependenciesTask(
+    auto task = std::make_unique<GetModDependenciesTask>(
         dir, selected,
         [this](const ModPlatform::Dependency& dependency, std::function<void(const ModPlatform::IndexedVersion&)> succeeded) -> Task::Ptr {
             auto args{ createDependecyArguments(dependency) };
@@ -462,14 +462,17 @@ QList<ModPlatform::IndexedVersion> ResourceModel::getDependecies(QDir& dir, QLis
                 callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto& pack) {
                     ModPlatform::IndexedVersion ver;
                     try {
-                        auto arr = dependency.version.length() != 0 && doc.isObject()
-                                       ? Json::toJsonArray(QList<QJsonObject>() << doc.object())
-                                   : doc.isObject() ? Json::ensureArray(doc.object(), "data")
-                                                    : doc.array();
+                        QJsonArray arr;
+                        if (dependency.version.length() != 0 && doc.isObject()) {
+                            arr.append(doc.object());
+                        } else {
+                            arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
+                        }
                         ver = loadDependencyVersions(dependency, arr);
                         if (!ver.addonId.isValid()) {
                             qWarning() << "Error while reading " << debugName() << " resource version empty ";
                             qDebug() << doc;
+                            return;
                         }
                     } catch (const JSONValidationError& e) {
                         qDebug() << doc;
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index ce327c3b..3b1f4748 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -111,7 +111,7 @@ class ResourceModel : public QAbstractListModel {
     virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&);
     virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&);
     virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&);
-    virtual ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr);
+    virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr);
 
    protected:
     /* Basic search parameters */
diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h
index 40b271d6..8ff4d8a2 100644
--- a/launcher/ui/pages/modplatform/ResourcePackModel.h
+++ b/launcher/ui/pages/modplatform/ResourcePackModel.h
@@ -28,7 +28,7 @@ class ResourcePackResourceModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0;
-    ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0;
+    ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0;
 
    public slots:
     ResourceAPI::SearchArgs createSearchArguments() override;
diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h
index 60d74777..17a07aa4 100644
--- a/launcher/ui/pages/modplatform/ShaderPackModel.h
+++ b/launcher/ui/pages/modplatform/ShaderPackModel.h
@@ -28,7 +28,7 @@ class ShaderPackResourceModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0;
-    ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0;
+    ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0;
 
    public slots:
     ResourceAPI::SearchArgs createSearchArguments() override;
diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
index 563ff963..08bf22fe 100644
--- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
@@ -29,7 +29,7 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr
     FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto FlameModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return FlameMod::loadDependencyVersions(m, arr);
 };
@@ -57,7 +57,7 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m
     FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto FlameResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto FlameResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return FlameMod::loadDependencyVersions(m, arr);
 };
@@ -98,7 +98,7 @@ void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m,
     m.versions = filtered_versions;
 }
 
-auto FlameTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto FlameTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return FlameMod::loadDependencyVersions(m, arr);
 };
diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
index 2f4413ac..7871d9aa 100644
--- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
+++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
@@ -24,7 +24,7 @@ class FlameModModel : public ModModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -43,7 +43,7 @@ class FlameResourcePackModel : public ResourcePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -62,7 +62,7 @@ class FlameTexturePackModel : public TexturePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     ResourceAPI::SearchArgs createSearchArguments() override;
     ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
index 047e3aaa..53be2d2c 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
@@ -42,7 +42,7 @@ void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJso
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return ::Modrinth::loadDependencyVersions(m, arr);
 };
@@ -69,7 +69,7 @@ void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto ModrinthResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return ::Modrinth::loadDependencyVersions(m, arr);
 };
@@ -96,7 +96,7 @@ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack&
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto ModrinthTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return ::Modrinth::loadDependencyVersions(m, arr);
 };
@@ -123,7 +123,7 @@ void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack&
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthShaderPackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion
+auto ModrinthShaderPackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
     return ::Modrinth::loadDependencyVersions(m, arr);
 };
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
index 77157a41..0045fe86 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
@@ -40,7 +40,7 @@ class ModrinthModModel : public ModModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -59,7 +59,7 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -78,7 +78,7 @@ class ModrinthTexturePackModel : public TexturePackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -97,7 +97,7 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel {
     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 loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
+    auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
-- 
cgit 


From c1490cd62703975c5478aea1156d0bbefcc37bc8 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 20 Apr 2023 00:57:09 +0300
Subject: Refator task to work with multiple providers

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/CMakeLists.txt                            |   2 -
 launcher/ResourceDownloadTask.h                    |   1 +
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 201 +++++++++++++--------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  62 ++++---
 .../minecraft/mod/tasks/LocalModGetAllTask.cpp     |  52 ------
 launcher/minecraft/mod/tasks/LocalModGetAllTask.h  |  45 -----
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     |  69 +++++--
 launcher/ui/dialogs/ResourceDownloadDialog.h       |  15 +-
 launcher/ui/pages/modplatform/ResourceModel.cpp    |  42 -----
 launcher/ui/pages/modplatform/ResourceModel.h      |   2 -
 launcher/ui/pages/modplatform/ResourcePage.cpp     |   5 -
 launcher/ui/pages/modplatform/ResourcePage.h       |   2 -
 12 files changed, 219 insertions(+), 279 deletions(-)
 delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
 delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.h

(limited to 'launcher')

diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index fca8c914..19356b94 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -361,8 +361,6 @@ set(MINECRAFT_SOURCES
     minecraft/mod/tasks/LocalResourceParse.cpp
     minecraft/mod/tasks/GetModDependenciesTask.h
     minecraft/mod/tasks/GetModDependenciesTask.cpp
-    minecraft/mod/tasks/LocalModGetAllTask.h
-    minecraft/mod/tasks/LocalModGetAllTask.cpp
 
     # Assets
     minecraft/AssetsUtils.h
diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index f2118524..29d3ae0a 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -38,6 +38,7 @@ class ResourceDownloadTask : public SequentialTask {
     const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
     const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; }
+    const ModPlatform::IndexedPack& getPack() const { return m_pack; }
 
    private:
     ModPlatform::IndexedPack m_pack;
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 7f184765..966eea19 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -20,90 +20,74 @@
 #include "GetModDependenciesTask.h"
 
 #include <QDebug>
+#include <algorithm>
+#include <memory>
+#include "Json.h"
 #include "QObjectPtr.h"
 #include "minecraft/mod/MetadataHandler.h"
-#include "minecraft/mod/tasks/LocalModGetAllTask.h"
 #include "modplatform/ModIndex.h"
+#include "modplatform/flame/FlameAPI.h"
+#include "modplatform/modrinth/ModrinthAPI.h"
 #include "tasks/ConcurrentTask.h"
 #include "tasks/SequentialTask.h"
+#include "ui/pages/modplatform/ModModel.h"
+#include "ui/pages/modplatform/flame/FlameResourceModels.h"
+#include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h"
 
-GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api)
-    : m_selected(selected), m_getDependenciesVersionAPI(api)
+static Version mcVersions(BaseInstance* inst)
 {
-    m_getAllMods = makeShared<LocalModGetAllTask>(index_dir);
-    m_getNetworkDep = makeShared<SequentialTask>(this, "GetDepInfo");
-    connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit);
-    QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMods, [this](QList<Metadata::ModStruct> mods) {
-        m_mods = mods;
-        prepareDependecies();
-    });
+    return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion();
 }
 
-void GetModDependenciesTask::executeTask()
+static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst)
 {
-    setStatus(tr("Geting all mods"));
-    m_getAllMods->start();
-    loop.exec();
-    emitSucceeded();
+    return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getModLoaders().value();
 }
 
-auto GetModDependenciesTask::abort() -> bool
+GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
+                                               BaseInstance* instance,
+                                               ModFolderModel* folder,
+                                               QList<std::shared_ptr<PackDependecny>> selected)
+    : SequentialTask(parent, "Get dependencies"), m_selected(selected), m_version(mcVersions(instance)), m_loaderType(mcLoaders(instance))
 {
-    emitAborted();
-    return true;
-}
+    m_providers.append(Provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
+                                 std::make_shared<FlameAPI>() });
+    m_providers.append(Provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared<ResourceDownload::ModrinthModModel>(*instance),
+                                 std::make_shared<ModrinthAPI>() });
+    for (auto mod : folder->allMods())
+        m_mods.append(mod->metadata());
+    prepare();
+};
 
-void GetModDependenciesTask::prepareDependecies()
+void GetModDependenciesTask::prepare()
 {
-    auto c_dependencies = getDependenciesForVersions(m_selected);
-    if (c_dependencies.length() == 0) {
-        m_getNetworkDep->start();
-        return;
-    }
-    for (auto dep : c_dependencies) {
-        auto task =
-            m_getDependenciesVersionAPI(dep, [this](const ModPlatform::IndexedVersion& new_version) { addDependecies(new_version, 20); });
-        m_getNetworkDep->addTask(task);
+    for (auto sel : m_selected) {
+        for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) {
+            addTask(prepareDependencyTask(dep, sel->pack.provider, 20));
+        }
     }
-    m_getNetworkDep->start();
 }
 
-void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& new_version, int level)
-{
-    // some mutex?
-    m_dependencies.append(new_version);
-    auto c_dependencies = getDependenciesForVersion(new_version);
-    if (c_dependencies.length() == 0) {
-        return;
-    }
-    if (level == 0) {
-        qWarning() << "Dependency cycle exeeded";
-        return;
-    }
-    for (auto dep : c_dependencies) {
-        auto task = m_getDependenciesVersionAPI(
-            dep, [this, level](const ModPlatform::IndexedVersion& new_versions) { addDependecies(new_versions, level - 1); });
-        m_getNetworkDep->addTask(task);
-    }
-};
-
-QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersions(const QList<ModPlatform::IndexedVersion>& selected)
+QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version,
+                                                                                 const ModPlatform::ResourceProvider providerName)
 {
     auto c_dependencies = QList<ModPlatform::Dependency>();
-    for (auto version : selected) {
-        for (auto ver_dep : version.dependencies) {
-            if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
-                if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                            [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
-                    dep == c_dependencies.end()) {  // check the current dependency list
-                    if (auto dep = std::find_if(selected.begin(), selected.end(),
-                                                [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
-                        dep == selected.end()) {  // check the selected versions
-                        if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
-                                                    [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; });
-                            dep == m_mods.end()) {  // check the existing mods
-                            c_dependencies.append(ver_dep);
-                        }
+    for (auto ver_dep : version.dependencies) {
+        if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
+            if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
+                                        [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; });
+                dep == c_dependencies.end()) {  // check the current dependency list
+                if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
+                                            [&ver_dep, providerName](std::shared_ptr<PackDependecny> i) {
+                                                return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName;
+                                            });
+                    dep == m_selected.end()) {  // check the selected versions
+                    if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
+                                                [&ver_dep, providerName](std::shared_ptr<Metadata::ModStruct> i) {
+                                                    return i->project_id == ver_dep.addonId && i->provider == providerName;
+                                                });
+                        dep == m_mods.end()) {  // check the existing mods
+                        c_dependencies.append(ver_dep);
                     }
                 }
             }
@@ -112,21 +96,80 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
     return c_dependencies;
 };
 
-QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version)
+Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep,
+                                                        const ModPlatform::ResourceProvider providerName,
+                                                        int level)
 {
-    auto c_dependencies = QList<ModPlatform::Dependency>();
-    for (auto ver_dep : version.dependencies) {
-        if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
-            if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                        [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
-                dep == c_dependencies.end()) {  // check the current dependency list
-                if (auto dep =
-                        std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; });
-                    dep == m_mods.end()) {  // check the existing mods
-                    c_dependencies.append(ver_dep);
-                }
+    auto pDep = std::make_shared<PackDependecny>();
+    pDep->dependency = dep;
+    pDep->pack = { dep.addonId, providerName };
+    m_pack_dependencies.append(pDep);
+    auto provider =
+        std::find_if(m_providers.begin(), m_providers.end(), [providerName](const Provider& p) { return p.name == providerName; });
+    // if (provider == m_providers.end()) {
+    //     qWarning() << "Unsuported provider for dependency check";
+    //     return nullptr;
+    // }
+
+    auto tasks = makeShared<SequentialTask>(this, QString("DependencyInfo: %1").arg(dep.addonId.toString()));
+
+    auto responseInfo = new QByteArray();
+    auto info = provider->api->getProject(dep.addonId.toString(), responseInfo);
+    QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] {
+        QJsonParseError parse_error{};
+        QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error);
+        if (parse_error.error != QJsonParseError::NoError) {
+            qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset
+                       << " reason: " << parse_error.errorString();
+            qWarning() << *responseInfo;
+            return;
+        }
+        try {
+            auto obj = provider->name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data")
+                                                                              : Json::requireObject(doc);
+            provider->mod->loadIndexedPack(pDep->pack, obj);
+        } catch (const JSONValidationError& e) {
+            qDebug() << doc;
+            qWarning() << "Error while reading mod info: " << e.cause();
+        }
+    });
+    tasks->addTask(info);
+
+    ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
+    ResourceAPI::DependencySearchCallbacks callbacks;
+
+    callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) {
+        try {
+            QJsonArray arr;
+            if (dep.version.length() != 0 && doc.isObject()) {
+                arr.append(doc.object());
+            } else {
+                arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
+            }
+            pDep->version = provider->mod->loadDependencyVersions(dep, arr);
+            if (!pDep->version.addonId.isValid()) {
+                qWarning() << "Error while reading mod version empty ";
+                qDebug() << doc;
+                return;
             }
+            pDep->version.is_currently_selected = true;
+            pDep->pack.versions = { pDep->version };
+            pDep->pack.versionsLoaded = true;
+        } catch (const JSONValidationError& e) {
+            qDebug() << doc;
+            qWarning() << "Error while reading mod version: " << e.cause();
+            return;
         }
-    }
-    return c_dependencies;
-};
\ No newline at end of file
+        if (level == 0) {
+            qWarning() << "Dependency cycle exeeded";
+            return;
+        }
+        for (auto dep : getDependenciesForVersion(pDep->version, provider->name)) {
+            addTask(prepareDependencyTask(dep, provider->name, level - 1));
+        }
+    };
+
+    auto version = provider->api->getDependencyVersion(std::move(args), std::move(callbacks));
+    tasks->addTask(version);
+    return tasks;
+};
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 7f7e1fb1..d83d6e27 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -18,48 +18,64 @@
 
 #pragma once
 
+#include <qlist.h>
+#include <qvariant.h>
 #include <QDir>
 #include <QEventLoop>
+#include <QList>
 #include <functional>
+#include <memory>
 
 #include "minecraft/mod/MetadataHandler.h"
-#include "minecraft/mod/tasks/LocalModGetAllTask.h"
+#include "minecraft/mod/ModFolderModel.h"
 #include "modplatform/ModIndex.h"
+#include "modplatform/ResourceAPI.h"
 #include "tasks/SequentialTask.h"
 #include "tasks/Task.h"
+#include "ui/pages/modplatform/ModModel.h"
 
-class GetModDependenciesTask : public Task {
+class GetModDependenciesTask : public SequentialTask {
     Q_OBJECT
    public:
     using Ptr = shared_qobject_ptr<GetModDependenciesTask>;
-    using LocalModGetAllTaskPtr = shared_qobject_ptr<LocalModGetAllTask>;
 
-    using NewDependecyVersionAPITask =
-        std::function<Task::Ptr(const ModPlatform::Dependency&, std::function<void(const ModPlatform::IndexedVersion&)>)>;
+    struct PackDependecny {
+        ModPlatform::Dependency dependency;
+        ModPlatform::IndexedPack pack;
+        ModPlatform::IndexedVersion version;
+        PackDependecny(){};
+        PackDependecny(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v)
+        {
+            pack = p;
+            version = v;
+        }
+    };
 
-    explicit GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api);
+    struct Provider {
+        ModPlatform::ResourceProvider name;
+        std::shared_ptr<ResourceDownload::ModModel> mod;
+        std::shared_ptr<ResourceAPI> api;
+    };
 
-    auto canAbort() const -> bool override { return true; }
-    auto abort() -> bool override;
+    explicit GetModDependenciesTask(QObject* parent,
+                                    BaseInstance* instance,
+                                    ModFolderModel* folder,
+                                    QList<std::shared_ptr<PackDependecny>> selected);
 
-    auto getDependecies() const -> QList<ModPlatform::IndexedVersion> { return m_dependencies; }
+    auto getDependecies() const -> QList<std::shared_ptr<PackDependecny>> { return m_pack_dependencies; }
 
    protected slots:
-    //! Entry point for tasks.
-    void executeTask() override;
-
-    void prepareDependecies();
-    void addDependecies(const ModPlatform::IndexedVersion&, int);
-    QList<ModPlatform::Dependency> getDependenciesForVersions(const QList<ModPlatform::IndexedVersion>&);
-    QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&);
+    Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int);
+    QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&,
+                                                             const ModPlatform::ResourceProvider providerName);
+    void prepare();
 
    private:
-    QList<ModPlatform::IndexedVersion> m_selected;
-    QList<ModPlatform::IndexedVersion> m_dependencies;
-    QList<Metadata::ModStruct> m_mods;
+    QList<std::shared_ptr<PackDependecny>> m_pack_dependencies;
+    QList<std::shared_ptr<Metadata::ModStruct>> m_mods;
+    QList<std::shared_ptr<PackDependecny>> m_selected;
+    QList<Provider> m_providers;
 
-    LocalModGetAllTaskPtr m_getAllMods = nullptr;
-    NewDependecyVersionAPITask m_getDependenciesVersionAPI;
-    SequentialTask::Ptr m_getNetworkDep;
-    QEventLoop loop;
+    Version m_version;
+    ResourceAPI::ModLoaderTypes m_loaderType;
 };
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
deleted file mode 100644
index 67058807..00000000
--- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#include "LocalModGetAllTask.h"
-
-#include "FileSystem.h"
-#include "minecraft/mod/MetadataHandler.h"
-
-#ifdef Q_OS_WIN32
-#include <windows.h>
-#endif
-
-LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir)
-{
-    // Ensure a '.index' folder exists in the mods folder, and create it if it does not
-    if (!FS::ensureFolderPathExists(index_dir.path())) {
-        emitFailed(QString("Unable to create index for all mods!"));
-    }
-
-#ifdef Q_OS_WIN32
-    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
-#endif
-}
-
-void LocalModGetAllTask::executeTask()
-{
-    setStatus(tr("Geting all mods"));
-    emit getAllMods(Metadata::getAll(m_index_dir));
-    emitSucceeded();
-}
-
-auto LocalModGetAllTask::abort() -> bool
-{
-    emitAborted();
-    return true;
-}
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
deleted file mode 100644
index bf4b78b7..00000000
--- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <QDir>
-
-#include "minecraft/mod/MetadataHandler.h"
-#include "tasks/Task.h"
-
-class LocalModGetAllTask : public Task {
-    Q_OBJECT
-   public:
-    using Ptr = shared_qobject_ptr<LocalModGetAllTask>;
-
-    explicit LocalModGetAllTask(QDir index_dir);
-
-    auto canAbort() const -> bool override { return true; }
-    auto abort() -> bool override;
-
-   protected slots:
-    //! Entry point for tasks.
-    void executeTask() override;
-
-   signals:
-    void getAllMods(QList<Metadata::ModStruct>);
-
-   private:
-    QDir m_index_dir;
-};
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 610f2449..03466bba 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -23,8 +23,10 @@
 
 #include <QPushButton>
 #include <algorithm>
+#include <memory>
 
 #include "Application.h"
+#include "QObjectPtr.h"
 #include "ResourceDownloadTask.h"
 
 #include "minecraft/mod/ModFolderModel.h"
@@ -32,7 +34,10 @@
 #include "minecraft/mod/ShaderPackFolderModel.h"
 #include "minecraft/mod/TexturePackFolderModel.h"
 
+#include "minecraft/mod/tasks/GetModDependenciesTask.h"
 #include "modplatform/ModIndex.h"
+#include "ui/dialogs/CustomMessageBox.h"
+#include "ui/dialogs/ProgressDialog.h"
 #include "ui/dialogs/ReviewMessageBox.h"
 
 #include "ui/pages/modplatform/ResourcePage.h"
@@ -122,30 +127,38 @@ void ResourceDownloadDialog::connectButtons()
 
 void ResourceDownloadDialog::confirm()
 {
-    auto keys = m_selected.keys();
-    keys.sort(Qt::CaseInsensitive);
-
     auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString()));
     confirm_dialog->retranslateUi(resourcesString());
 
-    if (auto model = dynamic_cast<ModFolderModel*>(getBaseModel().get()); model) {
-        QList<ModPlatform::IndexedVersion> selectedVers;
-        for (auto& task : keys) {
-            auto selected = m_selected.constFind(task).value();
-            selectedVers.append(selected->getVersion());
-        }
-
-        auto dir = model->indexDir();
-        auto dependencies = m_selectedPage->getDependecies(dir, selectedVers);
-
-        for (auto dep : dependencies) {
-            dep.is_currently_selected = true;
-            auto pack = ModPlatform::IndexedPack{ dep.addonId, ModPlatform::ResourceProvider::FLAME, dep.fileName, dep.fileName };
-            m_selected.insert(dep.fileName, makeShared<ResourceDownloadTask>(pack, dep, getBaseModel(), true));
-        }
-
-        keys = m_selected.keys();
+    if (auto task = getModDependenciesTask(); task) {
+        connect(task.get(), &Task::failed, this,
+                [&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
+
+        connect(task.get(), &Task::succeeded, this, [&]() {
+            QStringList warnings = task->warnings();
+            if (warnings.count()) {
+                CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->exec();
+            }
+        });
+
+        // Check for updates
+        ProgressDialog progress_dialog(this);
+        progress_dialog.setSkipButton(true, tr("Abort"));
+        progress_dialog.setWindowTitle(tr("Checking for dependencies..."));
+        auto ret = progress_dialog.execWithTask(task.get());
+
+        // If the dialog was skipped / some download error happened
+        if (ret == QDialog::DialogCode::Rejected) {
+            QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection);
+            return;
+        } else
+            for (auto dep : task->getDependecies()) {
+                addResource(dep->pack, dep->version, true);
+            }
     }
+
+    auto keys = m_selected.keys();
+    keys.sort(Qt::CaseInsensitive);
     for (auto& task : keys) {
         auto selected = m_selected.constFind(task).value();
         confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() });
@@ -173,6 +186,7 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage()
 
 void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed)
 {
+    qWarning() << "DebugName: " << pack.name;
     removeResource(pack, ver);
 
     ver.is_currently_selected = true;
@@ -256,6 +270,21 @@ QList<BasePage*> ModDownloadDialog::getPages()
     return pages;
 }
 
+GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask()
+{
+    if (auto model = dynamic_cast<ModFolderModel*>(getBaseModel().get()); model) {
+        auto keys = m_selected.keys();
+        QList<std::shared_ptr<GetModDependenciesTask::PackDependecny>> selectedVers;
+        for (auto& task : keys) {
+            auto selected = m_selected.constFind(task).value();
+            selectedVers.append(std::make_shared<GetModDependenciesTask::PackDependecny>(selected->getPack(), selected->getVersion()));
+        }
+
+        return makeShared<GetModDependenciesTask>(this, m_instance, model, selectedVers);
+    }
+    return nullptr;
+};
+
 ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent,
                                                        const std::shared_ptr<ResourcePackFolderModel>& resource_packs,
                                                        BaseInstance* instance)
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h
index 5678dc8b..f498df01 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.h
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.h
@@ -25,7 +25,9 @@
 #include <QLayout>
 
 #include "QObjectPtr.h"
+#include "minecraft/mod/tasks/GetModDependenciesTask.h"
 #include "modplatform/ModIndex.h"
+#include "tasks/Task.h"
 #include "ui/pages/BasePageProvider.h"
 
 class BaseInstance;
@@ -80,6 +82,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
    protected:
     [[nodiscard]] virtual QString geometrySaveKey() const { return ""; }
 
+    [[nodiscard]] virtual GetModDependenciesTask::Ptr getModDependenciesTask() { return nullptr; }
+
    protected:
     const std::shared_ptr<ResourceFolderModel> m_base_model;
 
@@ -92,8 +96,6 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
     QHash<QString, DownloadTaskPtr> m_selected;
 };
 
-
-
 class ModDownloadDialog final : public ResourceDownloadDialog {
     Q_OBJECT
 
@@ -106,6 +108,7 @@ class ModDownloadDialog final : public ResourceDownloadDialog {
     [[nodiscard]] QString geometrySaveKey() const override { return "ModDownloadGeometry"; }
 
     QList<BasePage*> getPages() override;
+    GetModDependenciesTask::Ptr getModDependenciesTask() override;
 
    private:
     BaseInstance* m_instance;
@@ -135,8 +138,8 @@ class TexturePackDownloadDialog final : public ResourceDownloadDialog {
 
    public:
     explicit TexturePackDownloadDialog(QWidget* parent,
-                                        const std::shared_ptr<TexturePackFolderModel>& resource_packs,
-                                        BaseInstance* instance);
+                                       const std::shared_ptr<TexturePackFolderModel>& resource_packs,
+                                       BaseInstance* instance);
     ~TexturePackDownloadDialog() override = default;
 
     //: String that gets appended to the texture pack download dialog title ("Download " + resourcesString())
@@ -153,9 +156,7 @@ class ShaderPackDownloadDialog final : public ResourceDownloadDialog {
     Q_OBJECT
 
    public:
-    explicit ShaderPackDownloadDialog(QWidget* parent,
-                                      const std::shared_ptr<ShaderPackFolderModel>& shader_packs,
-                                      BaseInstance* instance);
+    explicit ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr<ShaderPackFolderModel>& shader_packs, BaseInstance* instance);
     ~ShaderPackDownloadDialog() override = default;
 
     //: String that gets appended to the shader pack download dialog title ("Download " + resourcesString())
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index c1746d41..97b9efa9 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -449,46 +449,4 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
     emit projectInfoUpdated();
 }
 
-QList<ModPlatform::IndexedVersion> ResourceModel::getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> selected)
-{
-    auto task = std::make_unique<GetModDependenciesTask>(
-        dir, selected,
-        [this](const ModPlatform::Dependency& dependency, std::function<void(const ModPlatform::IndexedVersion&)> succeeded) -> Task::Ptr {
-            auto args{ createDependecyArguments(dependency) };
-            auto callbacks{ createDependecyCallbacks() };
-
-            // Use default if no callbacks are set
-            if (!callbacks.on_succeed)
-                callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto& pack) {
-                    ModPlatform::IndexedVersion ver;
-                    try {
-                        QJsonArray arr;
-                        if (dependency.version.length() != 0 && doc.isObject()) {
-                            arr.append(doc.object());
-                        } else {
-                            arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
-                        }
-                        ver = loadDependencyVersions(dependency, arr);
-                        if (!ver.addonId.isValid()) {
-                            qWarning() << "Error while reading " << debugName() << " resource version empty ";
-                            qDebug() << doc;
-                            return;
-                        }
-                    } catch (const JSONValidationError& e) {
-                        qDebug() << doc;
-                        qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
-                        return;
-                    }
-
-                    succeeded(ver);
-                };
-
-            return m_api->getDependencyVersion(std::move(args), std::move(callbacks));
-        });
-
-    task->start();
-
-    return task->getDependecies();
-};
-
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 3b1f4748..3ea567af 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -85,8 +85,6 @@ class ResourceModel : public QAbstractListModel {
     /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */
     std::optional<QIcon> getIcon(QModelIndex&, const QUrl&);
 
-    QList<ModPlatform::IndexedVersion> getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> m_selected);
-
    protected:
     /** Resets the model's data. */
     void clearData();
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index 02412fd9..1baa24ee 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -405,9 +405,4 @@ void ResourcePage::openUrl(const QUrl& url)
     QDesktopServices::openUrl(url);
 }
 
-QList<ModPlatform::IndexedVersion> ResourcePage::getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> selected)
-{
-    return m_model->getDependecies(dir, selected);
-};
-
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index 4fffd506..a8299728 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -75,8 +75,6 @@ class ResourcePage : public QWidget, public BasePage {
     virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
     virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
 
-    QList<ModPlatform::IndexedVersion> getDependecies(QDir& dir, QList<ModPlatform::IndexedVersion> m_selected);
-
    protected slots:
     virtual void triggerSearch() {}
 
-- 
cgit 


From ffaa47bf54bc5b320049064a897c8ad0737574ee Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 20 Apr 2023 22:35:10 +0300
Subject: Small cleanup

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/MetadataHandler.h           |  2 -
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 36 +++++++-------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  6 +--
 launcher/modplatform/packwiz/Packwiz.cpp           | 11 -----
 launcher/modplatform/packwiz/Packwiz.h             | 57 ++++++++++------------
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     |  1 -
 launcher/ui/dialogs/ResourceDownloadDialog.h       |  1 -
 launcher/ui/pages/modplatform/ModModel.cpp         | 16 +-----
 launcher/ui/pages/modplatform/ModModel.h           |  3 +-
 launcher/ui/pages/modplatform/ResourceModel.cpp    |  5 --
 launcher/ui/pages/modplatform/ResourceModel.h      |  4 --
 launcher/ui/pages/modplatform/ResourcePackModel.h  |  1 -
 launcher/ui/pages/modplatform/ResourcePage.cpp     |  3 ++
 launcher/ui/pages/modplatform/ResourcePage.h       |  4 +-
 launcher/ui/pages/modplatform/ShaderPackModel.h    |  1 -
 .../modplatform/flame/FlameResourceModels.cpp      | 10 ----
 .../pages/modplatform/flame/FlameResourceModels.h  |  2 -
 .../modrinth/ModrinthResourceModels.cpp            | 15 ------
 .../modplatform/modrinth/ModrinthResourceModels.h  |  3 --
 19 files changed, 54 insertions(+), 127 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h
index f7f08a79..ea9078e0 100644
--- a/launcher/minecraft/mod/MetadataHandler.h
+++ b/launcher/minecraft/mod/MetadataHandler.h
@@ -51,6 +51,4 @@ class Metadata {
     static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); }
 
     static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); }
-
-    static auto getAll(QDir& index_dir) -> QList<ModStruct> { return Packwiz::V1::getAllMods(index_dir); }
 };
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 966eea19..e1760f16 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -48,12 +48,15 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
                                                BaseInstance* instance,
                                                ModFolderModel* folder,
                                                QList<std::shared_ptr<PackDependecny>> selected)
-    : SequentialTask(parent, "Get dependencies"), m_selected(selected), m_version(mcVersions(instance)), m_loaderType(mcLoaders(instance))
+    : SequentialTask(parent, "Get dependencies")
+    , m_selected(selected)
+    , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
+                        std::make_shared<FlameAPI>() }
+    , m_modrinth_provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared<ResourceDownload::ModrinthModModel>(*instance),
+                           std::make_shared<ModrinthAPI>() }
+    , m_version(mcVersions(instance))
+    , m_loaderType(mcLoaders(instance))
 {
-    m_providers.append(Provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
-                                 std::make_shared<FlameAPI>() });
-    m_providers.append(Provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared<ResourceDownload::ModrinthModModel>(*instance),
-                                 std::make_shared<ModrinthAPI>() });
     for (auto mod : folder->allMods())
         m_mods.append(mod->metadata());
     prepare();
@@ -104,17 +107,12 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
     pDep->dependency = dep;
     pDep->pack = { dep.addonId, providerName };
     m_pack_dependencies.append(pDep);
-    auto provider =
-        std::find_if(m_providers.begin(), m_providers.end(), [providerName](const Provider& p) { return p.name == providerName; });
-    // if (provider == m_providers.end()) {
-    //     qWarning() << "Unsuported provider for dependency check";
-    //     return nullptr;
-    // }
+    auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
 
     auto tasks = makeShared<SequentialTask>(this, QString("DependencyInfo: %1").arg(dep.addonId.toString()));
 
     auto responseInfo = new QByteArray();
-    auto info = provider->api->getProject(dep.addonId.toString(), responseInfo);
+    auto info = provider.api->getProject(dep.addonId.toString(), responseInfo);
     QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] {
         QJsonParseError parse_error{};
         QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error);
@@ -125,9 +123,9 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             return;
         }
         try {
-            auto obj = provider->name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data")
-                                                                              : Json::requireObject(doc);
-            provider->mod->loadIndexedPack(pDep->pack, obj);
+            auto obj = provider.name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data")
+                                                                             : Json::requireObject(doc);
+            provider.mod->loadIndexedPack(pDep->pack, obj);
         } catch (const JSONValidationError& e) {
             qDebug() << doc;
             qWarning() << "Error while reading mod info: " << e.cause();
@@ -146,7 +144,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             } else {
                 arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
             }
-            pDep->version = provider->mod->loadDependencyVersions(dep, arr);
+            pDep->version = provider.mod->loadDependencyVersions(dep, arr);
             if (!pDep->version.addonId.isValid()) {
                 qWarning() << "Error while reading mod version empty ";
                 qDebug() << doc;
@@ -164,12 +162,12 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             qWarning() << "Dependency cycle exeeded";
             return;
         }
-        for (auto dep : getDependenciesForVersion(pDep->version, provider->name)) {
-            addTask(prepareDependencyTask(dep, provider->name, level - 1));
+        for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) {
+            addTask(prepareDependencyTask(dep, provider.name, level - 1));
         }
     };
 
-    auto version = provider->api->getDependencyVersion(std::move(args), std::move(callbacks));
+    auto version = provider.api->getDependencyVersion(std::move(args), std::move(callbacks));
     tasks->addTask(version);
     return tasks;
 };
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index d83d6e27..40f80ebf 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -18,11 +18,10 @@
 
 #pragma once
 
-#include <qlist.h>
-#include <qvariant.h>
 #include <QDir>
 #include <QEventLoop>
 #include <QList>
+#include <QVariant>
 #include <functional>
 #include <memory>
 
@@ -74,7 +73,8 @@ class GetModDependenciesTask : public SequentialTask {
     QList<std::shared_ptr<PackDependecny>> m_pack_dependencies;
     QList<std::shared_ptr<Metadata::ModStruct>> m_mods;
     QList<std::shared_ptr<PackDependecny>> m_selected;
-    QList<Provider> m_providers;
+    Provider m_flame_provider;
+    Provider m_modrinth_provider;
 
     Version m_version;
     ResourceAPI::ModLoaderTypes m_loaderType;
diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp
index 33b5f364..510c7309 100644
--- a/launcher/modplatform/packwiz/Packwiz.cpp
+++ b/launcher/modplatform/packwiz/Packwiz.cpp
@@ -21,8 +21,6 @@
 #include <QDebug>
 #include <QDir>
 #include <QObject>
-#include <algorithm>
-#include <iterator>
 
 #include "FileSystem.h"
 #include "StringUtils.h"
@@ -313,13 +311,4 @@ auto V1::getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod
     return {};
 }
 
-auto V1::getAllMods(QDir& index_dir) -> QList<Mod>
-{
-    auto files = index_dir.entryList(QDir::Filter::Files);
-    auto mods = QList<Mod>();
-    std::transform(files.begin(), files.end(), std::back_inserter(mods),
-                   [&index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); });
-    return mods;
-}
-
 }  // namespace Packwiz
diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h
index 2801f5d0..4b096eec 100644
--- a/launcher/modplatform/packwiz/Packwiz.h
+++ b/launcher/modplatform/packwiz/Packwiz.h
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
+*  PolyMC - Minecraft Launcher
+*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, version 3.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
 
 #pragma once
 
@@ -36,22 +36,22 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul
 class V1 {
    public:
     struct Mod {
-        QString slug{};
-        QString name{};
-        QString filename{};
+        QString slug {};
+        QString name {};
+        QString filename {};
         // FIXME: make side an enum
-        QString side{ "both" };
+        QString side {"both"};
 
         // [download]
-        QString mode{};
-        QUrl url{};
-        QString hash_format{};
-        QString hash{};
+        QString mode {};
+        QUrl url {};
+        QString hash_format {};
+        QString hash {};
 
         // [update]
-        ModPlatform::ResourceProvider provider{};
-        QVariant file_id{};
-        QVariant project_id{};
+        ModPlatform::ResourceProvider provider {};
+        QVariant file_id {};
+        QVariant project_id {};
 
        public:
         // This is a totally heuristic, but should work for now.
@@ -93,9 +93,6 @@ class V1 {
      * If the mod doesn't have a metadata, it simply returns an empty Mod object.
      * */
     static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod;
-
-    /* Gets the metadata for all the mods */
-    static auto getAllMods(QDir& index_dir) -> QList<Mod>;
 };
 
-}  // namespace Packwiz
+} // namespace Packwiz
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 03466bba..dc1d927e 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -26,7 +26,6 @@
 #include <memory>
 
 #include "Application.h"
-#include "QObjectPtr.h"
 #include "ResourceDownloadTask.h"
 
 #include "minecraft/mod/ModFolderModel.h"
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h
index f498df01..9610c8b3 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.h
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.h
@@ -27,7 +27,6 @@
 #include "QObjectPtr.h"
 #include "minecraft/mod/tasks/GetModDependenciesTask.h"
 #include "modplatform/ModIndex.h"
-#include "tasks/Task.h"
 #include "ui/pages/BasePageProvider.h"
 
 class BaseInstance;
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 19c20e65..3ffe6cb0 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -24,7 +24,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
 
     std::optional<std::list<Version>> versions{};
 
-    {  // Version filter
+    { // Version filter
         if (!m_filter->versions.empty())
             versions = m_filter->versions;
     }
@@ -49,20 +49,6 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
     return { pack, versions, profile->getModLoaders() };
 }
 
-ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(const ModPlatform::Dependency& dep)
-{
-    auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
-
-    Q_ASSERT(profile);
-    Q_ASSERT(m_filter);
-
-    std::optional<std::list<Version>> versions{};
-    if (!m_filter->versions.empty())
-        versions = m_filter->versions;
-
-    return { dep, versions->front(), profile->getModLoaders().value() };
-};
-
 ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
 {
     auto& pack = m_packs[entry.row()];
diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h
index 59b27dda..f7563171 100644
--- a/launcher/ui/pages/modplatform/ModModel.h
+++ b/launcher/ui/pages/modplatform/ModModel.h
@@ -32,7 +32,7 @@ class ModModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0;
-    ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0;
+    virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) = 0;
 
     void setFilter(std::shared_ptr<ModFilterWidget::Filter> filter) { m_filter = filter; }
 
@@ -40,7 +40,6 @@ class ModModel : public ResourceModel {
     ResourceAPI::SearchArgs createSearchArguments() override;
     ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
     ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override;
-    ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) override;
 
    protected:
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0;
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index 97b9efa9..b1e936f8 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -324,11 +324,6 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra
 {
     NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions");
 }
-ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr)
-{
-    NEED_FOR_CALLBACK_ASSERT("loadDependencyVersions");
-    return {};
-}
 
 /* Default callbacks */
 
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 3ea567af..c0844589 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -70,9 +70,6 @@ class ResourceModel : public QAbstractListModel {
     virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0;
     virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; }
 
-    virtual ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) { return {}; };
-    virtual ResourceAPI::DependencySearchCallbacks createDependecyCallbacks() { return {}; }
-
     /** Requests the API for more entries. */
     virtual void search();
 
@@ -109,7 +106,6 @@ class ResourceModel : public QAbstractListModel {
     virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&);
     virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&);
     virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&);
-    virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr);
 
    protected:
     /* Basic search parameters */
diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h
index 8ff4d8a2..e2b4a195 100644
--- a/launcher/ui/pages/modplatform/ResourcePackModel.h
+++ b/launcher/ui/pages/modplatform/ResourcePackModel.h
@@ -28,7 +28,6 @@ class ResourcePackResourceModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0;
-    ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0;
 
    public slots:
     ResourceAPI::SearchArgs createSearchArguments() override;
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index 1baa24ee..bbd465bc 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -43,6 +43,9 @@
 #include <QKeyEvent>
 
 #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/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index a8299728..1896d53e 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -4,11 +4,11 @@
 
 #pragma once
 
-#include <QDir>
 #include <QTimer>
 #include <QWidget>
 
 #include "modplatform/ModIndex.h"
+#include "modplatform/ResourceAPI.h"
 
 #include "ui/pages/BasePage.h"
 #include "ui/widgets/ProgressWidget.h"
@@ -77,7 +77,7 @@ class ResourcePage : public QWidget, public BasePage {
 
    protected slots:
     virtual void triggerSearch() {}
-
+   
     void onSelectionChanged(QModelIndex first, QModelIndex second);
     void onVersionSelectionChanged(QString data);
     void onResourceSelected();
diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h
index 17a07aa4..f3c695e9 100644
--- a/launcher/ui/pages/modplatform/ShaderPackModel.h
+++ b/launcher/ui/pages/modplatform/ShaderPackModel.h
@@ -28,7 +28,6 @@ class ShaderPackResourceModel : public ResourceModel {
     void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0;
     void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0;
-    ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0;
 
    public slots:
     ResourceAPI::SearchArgs createSearchArguments() override;
diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
index 08bf22fe..b233a845 100644
--- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp
@@ -57,11 +57,6 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m
     FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto FlameResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
-{
-    return FlameMod::loadDependencyVersions(m, arr);
-};
-
 auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return Json::ensureArray(obj.object(), "data");
@@ -98,11 +93,6 @@ void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m,
     m.versions = filtered_versions;
 }
 
-auto FlameTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
-{
-    return FlameMod::loadDependencyVersions(m, arr);
-};
-
 ResourceAPI::SearchArgs FlameTexturePackModel::createSearchArguments()
 {
     auto args = TexturePackResourceModel::createSearchArguments();
diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
index 7871d9aa..f3ef918a 100644
--- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
+++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h
@@ -43,7 +43,6 @@ class FlameResourcePackModel : public ResourcePackResourceModel {
     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 loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -62,7 +61,6 @@ class FlameTexturePackModel : public TexturePackResourceModel {
     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 loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     ResourceAPI::SearchArgs createSearchArguments() override;
     ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
index 53be2d2c..e9f09387 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
@@ -69,11 +69,6 @@ void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
-{
-    return ::Modrinth::loadDependencyVersions(m, arr);
-};
-
 auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
@@ -96,11 +91,6 @@ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack&
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
-{
-    return ::Modrinth::loadDependencyVersions(m, arr);
-};
-
 auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
@@ -123,11 +113,6 @@ void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack&
     ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
 }
 
-auto ModrinthShaderPackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
-{
-    return ::Modrinth::loadDependencyVersions(m, arr);
-};
-
 auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
 {
     return obj.object().value("hits").toArray();
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
index 0045fe86..6cd19c41 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h
@@ -59,7 +59,6 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel {
     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 loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -78,7 +77,6 @@ class ModrinthTexturePackModel : public TexturePackResourceModel {
     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 loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
@@ -97,7 +95,6 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel {
     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 loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override;
 
     auto documentToArray(QJsonDocument& obj) const -> QJsonArray override;
 };
-- 
cgit 


From 2c744da9f7352073e744015a4c1da42794bcd004 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 20 Apr 2023 22:51:20 +0300
Subject: More cleanup

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/MetadataHandler.h        | 55 ++++++++++++++++---------
 launcher/ui/dialogs/ResourceDownloadDialog.cpp  |  1 -
 launcher/ui/pages/modplatform/ResourceModel.cpp |  3 --
 launcher/ui/pages/modplatform/ResourceModel.h   |  2 -
 4 files changed, 35 insertions(+), 26 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h
index ea9078e0..39723b49 100644
--- a/launcher/minecraft/mod/MetadataHandler.h
+++ b/launcher/minecraft/mod/MetadataHandler.h
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
+*  PolyMC - Minecraft Launcher
+*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, version 3.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
 
 #pragma once
 
@@ -42,13 +42,28 @@ class Metadata {
         return Packwiz::V1::createModFormat(index_dir, internal_mod, mod_slug);
     }
 
-    static void update(QDir& index_dir, ModStruct& mod) { Packwiz::V1::updateModIndex(index_dir, mod); }
+    static void update(QDir& index_dir, ModStruct& mod)
+    {
+        Packwiz::V1::updateModIndex(index_dir, mod);
+    }
 
-    static void remove(QDir& index_dir, QString mod_slug) { Packwiz::V1::deleteModIndex(index_dir, mod_slug); }
+    static void remove(QDir& index_dir, QString mod_slug)
+    {
+        Packwiz::V1::deleteModIndex(index_dir, mod_slug);
+    }
 
-    static void remove(QDir& index_dir, QVariant& mod_id) { Packwiz::V1::deleteModIndex(index_dir, mod_id); }
+    static void remove(QDir& index_dir, QVariant& mod_id)
+    {
+        Packwiz::V1::deleteModIndex(index_dir, mod_id);
+    }
 
-    static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); }
+    static auto get(QDir& index_dir, QString mod_slug) -> ModStruct
+    {
+        return Packwiz::V1::getIndexForMod(index_dir, mod_slug);
+    }
 
-    static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); }
+    static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct
+    {
+        return Packwiz::V1::getIndexForMod(index_dir, mod_id);
+    }
 };
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index dc1d927e..38c57361 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -185,7 +185,6 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage()
 
 void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed)
 {
-    qWarning() << "DebugName: " << pack.name;
     removeResource(pack, ver);
 
     ver.is_currently_selected = true;
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index b1e936f8..db7d26f8 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -3,8 +3,6 @@
 // SPDX-License-Identifier: GPL-3.0-only
 
 #include "ResourceModel.h"
-#include <QDir>
-#include <QList>
 
 #include <QCryptographicHash>
 #include <QIcon>
@@ -16,7 +14,6 @@
 #include "BuildConfig.h"
 #include "Json.h"
 
-#include "minecraft/mod/tasks/GetModDependenciesTask.h"
 #include "net/Download.h"
 #include "net/NetJob.h"
 
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index c0844589..46a02d6e 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -4,14 +4,12 @@
 
 #pragma once
 
-#include <QDir>
 #include <optional>
 
 #include <QAbstractListModel>
 
 #include "QObjectPtr.h"
 
-#include "modplatform/ModIndex.h"
 #include "modplatform/ResourceAPI.h"
 
 #include "tasks/ConcurrentTask.h"
-- 
cgit 


From b4fa6e120a98fde89443b262f351412f36de7566 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 21 Apr 2023 18:41:40 +0300
Subject: Fixed tipo

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/flame/FlameAPI.h               | 2 +-
 launcher/modplatform/helpers/NetworkResourceAPI.cpp | 4 ++--
 launcher/modplatform/helpers/NetworkResourceAPI.h   | 2 +-
 launcher/modplatform/modrinth/ModrinthAPI.h         | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index 91993e64..3b4af952 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -85,7 +85,7 @@ class FlameAPI : public NetworkResourceAPI {
         return url + get_parameters.join('&');
     };
 
-    [[nodiscard]] std::optional<QString> getDependecyURL(DependencySearchArgs const& args) const override
+    [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
     {
         return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%")
             .arg(args.dependency.addonId.toString())
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
index a7f763d3..9f95cde4 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
@@ -123,13 +123,13 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response)
 
 Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, DependencySearchCallbacks&& callbacks) const
 {
-    auto versions_url_optional = getDependecyURL(args);
+    auto versions_url_optional = getDependencyURL(args);
     if (!versions_url_optional.has_value())
         return nullptr;
 
     auto versions_url = versions_url_optional.value();
 
-    auto netJob = makeShared<NetJob>(QString("%1::Dependecy").arg(args.dependency.addonId.toString()), APPLICATION->network());
+    auto netJob = makeShared<NetJob>(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network());
     auto response = new QByteArray();
 
     netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h
index bbe0a2c7..93865713 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.h
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.h
@@ -20,5 +20,5 @@ class NetworkResourceAPI : public ResourceAPI {
     [[nodiscard]] virtual auto getSearchURL(SearchArgs const& args) const -> std::optional<QString> = 0;
     [[nodiscard]] virtual auto getInfoURL(QString const& id) const -> std::optional<QString> = 0;
     [[nodiscard]] virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional<QString> = 0;
-    [[nodiscard]] virtual auto getDependecyURL(DependencySearchArgs const& args) const -> std::optional<QString> = 0;
+    [[nodiscard]] virtual auto getDependencyURL(DependencySearchArgs const& args) const -> std::optional<QString> = 0;
 };
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h
index 2d6049ba..07c8cf2a 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.h
+++ b/launcher/modplatform/modrinth/ModrinthAPI.h
@@ -143,7 +143,7 @@ class ModrinthAPI : public NetworkResourceAPI {
 
     inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool { return loaders & (Forge | Fabric | Quilt); }
 
-    [[nodiscard]] std::optional<QString> getDependecyURL(DependencySearchArgs const& args) const override
+    [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
     {
         return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version)
                                                      : QString("%1/project/%2/version?game_versions=[\"%1\"]&loaders=[\"%1\"]")
-- 
cgit 


From 42bc91463e8dc7c078476c8606937552ce623c62 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 21 Apr 2023 20:37:17 +0300
Subject: Updated links

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ResourceDownloadTask.h                |  3 ++-
 launcher/modplatform/flame/FlameAPI.h          |  2 +-
 launcher/modplatform/modrinth/ModrinthAPI.h    |  2 +-
 launcher/ui/dialogs/ResourceDownloadDialog.cpp | 12 ++++++++----
 launcher/ui/dialogs/ReviewMessageBox.cpp       | 12 ++++++++++--
 launcher/ui/dialogs/ReviewMessageBox.h         |  7 ++++---
 6 files changed, 26 insertions(+), 12 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index 29d3ae0a..a12c05b8 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -38,7 +38,8 @@ class ResourceDownloadTask : public SequentialTask {
     const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
     const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; }
-    const ModPlatform::IndexedPack& getPack() const { return m_pack; }
+    ModPlatform::IndexedPack& getPack() { return m_pack; }
+    const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; }
 
    private:
     ModPlatform::IndexedPack m_pack;
diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index 3b4af952..4ffc36d2 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -87,7 +87,7 @@ class FlameAPI : public NetworkResourceAPI {
 
     [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
     {
-        return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%")
+        return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%3")
             .arg(args.dependency.addonId.toString())
             .arg(args.mcVersion.toString())
             .arg(getMappedModLoader(args.loader));
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h
index 07c8cf2a..95722ccb 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.h
+++ b/launcher/modplatform/modrinth/ModrinthAPI.h
@@ -146,7 +146,7 @@ class ModrinthAPI : public NetworkResourceAPI {
     [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
     {
         return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version)
-                                                     : QString("%1/project/%2/version?game_versions=[\"%1\"]&loaders=[\"%1\"]")
+                                                     : QString("%1/project/%2/version?game_versions=[\"%3\"]&loaders=[\"%4\"]")
                                                            .arg(BuildConfig.MODRINTH_PROD_URL)
                                                            .arg(args.dependency.addonId.toString())
                                                            .arg(args.mcVersion.toString())
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 38c57361..c16dcca7 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -124,6 +124,8 @@ void ResourceDownloadDialog::connectButtons()
     connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help);
 }
 
+static ModPlatform::ProviderCapabilities ProviderCaps;
+
 void ResourceDownloadDialog::confirm()
 {
     auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString()));
@@ -160,7 +162,8 @@ void ResourceDownloadDialog::confirm()
     keys.sort(Qt::CaseInsensitive);
     for (auto& task : keys) {
         auto selected = m_selected.constFind(task).value();
-        confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() });
+        confirm_dialog->appendResource(
+            { task, selected->getFilename(), selected->getCustomPath(), ProviderCaps.name(selected->getProvider()) });
     }
 
     if (confirm_dialog->exec()) {
@@ -206,9 +209,10 @@ void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModP
     if (auto selected_task_it = m_selected.find(pack.name); selected_task_it != m_selected.end()) {
         auto selected_task = *selected_task_it;
         auto old_version_id = selected_task->getVersionID();
-
-        // If the new and old version IDs don't match, search for the old one and deselect it.
-        if (ver.fileId != old_version_id)
+        if (selected_task->getProvider() != pack.provider)  // If the pack name matches but they are different providers search for the
+                                                            // old one(in the actual pack) and deselect it.
+            getVersionWithID(selected_task->getPack(), old_version_id).is_currently_selected = false;
+        else if (ver.fileId != old_version_id)  // If the new and old version IDs don't match, search for the old one and deselect it.
             getVersionWithID(pack, old_version_id).is_currently_selected = false;
     }
 
diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp
index 7b2df278..86e68aae 100644
--- a/launcher/ui/dialogs/ReviewMessageBox.cpp
+++ b/launcher/ui/dialogs/ReviewMessageBox.cpp
@@ -40,7 +40,8 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info)
     auto filenameItem = new QTreeWidgetItem(itemTop);
     filenameItem->setText(0, tr("Filename: %1").arg(info.filename));
 
-    itemTop->insertChildren(0, { filenameItem });
+    auto childIndx = 0;
+    itemTop->insertChildren(childIndx++, { filenameItem });
 
     if (!info.custom_file_path.isEmpty()) {
         auto customPathItem = new QTreeWidgetItem(itemTop);
@@ -49,9 +50,16 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info)
         itemTop->insertChildren(1, { customPathItem });
 
         itemTop->setIcon(1, QIcon(APPLICATION->getThemedIcon("status-yellow")));
-        itemTop->setToolTip(1, tr("This file will be downloaded to a folder location different from the default, possibly due to its loader requiring it."));
+        itemTop->setToolTip(
+            childIndx++,
+            tr("This file will be downloaded to a folder location different from the default, possibly due to its loader requiring it."));
     }
 
+    auto providerItem = new QTreeWidgetItem(itemTop);
+    providerItem->setText(0, tr("Provider: %1").arg(info.provider));
+
+    itemTop->insertChildren(childIndx++, { providerItem });
+
     ui->modTreeWidget->addTopLevelItem(itemTop);
 }
 
diff --git a/launcher/ui/dialogs/ReviewMessageBox.h b/launcher/ui/dialogs/ReviewMessageBox.h
index 5ec2bc23..9579da33 100644
--- a/launcher/ui/dialogs/ReviewMessageBox.h
+++ b/launcher/ui/dialogs/ReviewMessageBox.h
@@ -13,9 +13,10 @@ class ReviewMessageBox : public QDialog {
     static auto create(QWidget* parent, QString&& title, QString&& icon = "") -> ReviewMessageBox*;
 
     using ResourceInformation = struct res_info {
-        QString name;  
-        QString filename;  
-        QString custom_file_path {};
+        QString name;
+        QString filename;
+        QString custom_file_path{};
+        QString provider;
     };
 
     void appendResource(ResourceInformation&& info);
-- 
cgit 


From 10aac4fe1721c3e1cf83bacefddc086918ca03da Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 21 Apr 2023 21:03:01 +0300
Subject: Fixed assert

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ResourceDownloadTask.h                | 52 +++++++++++++-------------
 launcher/ui/dialogs/ResourceDownloadDialog.cpp | 21 ++++++-----
 2 files changed, 38 insertions(+), 35 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index 73ad2d07..27c3c2ec 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -1,41 +1,46 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  Prism Launcher - Minecraft Launcher
-*  Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
-*  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  Prism Launcher - Minecraft Launcher
+ *  Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
+ *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #pragma once
 
 #include "net/NetJob.h"
 #include "tasks/SequentialTask.h"
 
-#include "modplatform/ModIndex.h"
 #include "minecraft/mod/tasks/LocalModUpdateTask.h"
+#include "modplatform/ModIndex.h"
 
 class ResourceFolderModel;
 
 class ResourceDownloadTask : public SequentialTask {
     Q_OBJECT
-public:
-    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr<ResourceFolderModel> packs, bool is_indexed = true);
+   public:
+    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack,
+                                  ModPlatform::IndexedVersion version,
+                                  const std::shared_ptr<ResourceFolderModel> packs,
+                                  bool is_indexed = true);
     const QString& getFilename() const { return m_pack_version.fileName; }
     const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
+    ModPlatform::IndexedPack& getPack() { return m_pack; }
+    const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; }
 
-private:
+   private:
     ModPlatform::IndexedPack m_pack;
     ModPlatform::IndexedVersion m_pack_version;
     const std::shared_ptr<ResourceFolderModel> m_pack_model;
@@ -47,11 +52,8 @@ private:
     void downloadFailed(QString reason);
     void downloadSucceeded();
 
-    std::tuple<QString, QString> to_delete {"", ""};
+    std::tuple<QString, QString> to_delete{ "", "" };
 
-private slots:
+   private slots:
     void hasOldResource(QString name, QString filename);
 };
-
-
-
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index edb7d063..7fb4a657 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -26,8 +26,8 @@
 
 #include "minecraft/mod/ModFolderModel.h"
 #include "minecraft/mod/ResourcePackFolderModel.h"
-#include "minecraft/mod/TexturePackFolderModel.h"
 #include "minecraft/mod/ShaderPackFolderModel.h"
+#include "minecraft/mod/TexturePackFolderModel.h"
 
 #include "ui/dialogs/ReviewMessageBox.h"
 
@@ -41,7 +41,10 @@
 namespace ResourceDownload {
 
 ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, const std::shared_ptr<ResourceFolderModel> base_model)
-    : QDialog(parent), m_base_model(base_model), m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel), m_vertical_layout(this)
+    : QDialog(parent)
+    , m_base_model(base_model)
+    , m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
+    , m_vertical_layout(this)
 {
     setObjectName(QStringLiteral("ResourceDownloadDialog"));
 
@@ -102,7 +105,8 @@ void ResourceDownloadDialog::initializeContainer()
 void ResourceDownloadDialog::connectButtons()
 {
     auto OkButton = m_buttons.button(QDialogButtonBox::Ok);
-    OkButton->setToolTip(tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString()));
+    OkButton->setToolTip(
+        tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString()));
     connect(OkButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm);
 
     auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel);
@@ -169,8 +173,10 @@ void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModP
         auto selected_task = *selected_task_it;
         auto old_version_id = selected_task->getVersionID();
 
-        // If the new and old version IDs don't match, search for the old one and deselect it.
-        if (ver.fileId != old_version_id)
+        if (selected_task->getProvider() != pack.provider)  // If the pack name matches but they are different providers search for the
+                                                            // old one(in the actual pack) and deselect it.
+            getVersionWithID(selected_task->getPack(), old_version_id).is_currently_selected = false;
+        else if (ver.fileId != old_version_id)  // If the new and old version IDs don't match, search for the old one and deselect it.
             getVersionWithID(pack, old_version_id).is_currently_selected = false;
     }
 
@@ -205,8 +211,6 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s
     m_selectedPage->setSearchTerm(prev_page->getSearchTerm());
 }
 
-
-
 ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr<ModFolderModel>& mods, BaseInstance* instance)
     : ResourceDownloadDialog(parent, mods), m_instance(instance)
 {
@@ -232,7 +236,6 @@ QList<BasePage*> ModDownloadDialog::getPages()
     return pages;
 }
 
-
 ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent,
                                                        const std::shared_ptr<ResourcePackFolderModel>& resource_packs,
                                                        BaseInstance* instance)
@@ -258,7 +261,6 @@ QList<BasePage*> ResourcePackDownloadDialog::getPages()
     return pages;
 }
 
-
 TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent,
                                                      const std::shared_ptr<TexturePackFolderModel>& resource_packs,
                                                      BaseInstance* instance)
@@ -284,7 +286,6 @@ QList<BasePage*> TexturePackDownloadDialog::getPages()
     return pages;
 }
 
-
 ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent,
                                                    const std::shared_ptr<ShaderPackFolderModel>& shaders,
                                                    BaseInstance* instance)
-- 
cgit 


From f7931c2ee202025740caf424fa00ffb76743a1d2 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sat, 22 Apr 2023 00:47:51 +0300
Subject: Better version handling

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ResourceDownloadTask.h                  |  1 -
 launcher/modplatform/ModIndex.h                  | 37 +++++++++++++-----------
 launcher/ui/dialogs/ResourceDownloadDialog.cpp   | 20 ++-----------
 launcher/ui/pages/modplatform/ModModel.cpp       | 16 ++++++++--
 launcher/ui/pages/modplatform/ModPage.cpp        | 18 +++++-------
 launcher/ui/pages/modplatform/ResourceModel.cpp  | 30 +++++++++++++++++++
 launcher/ui/pages/modplatform/ResourceModel.h    |  4 +++
 launcher/ui/pages/modplatform/ResourcePage.cpp   |  6 ++++
 launcher/ui/pages/modplatform/ResourcePage.h     |  3 +-
 launcher/ui/pages/modplatform/ShaderPackPage.cpp |  8 ++---
 10 files changed, 90 insertions(+), 53 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index 27c3c2ec..0d90bd36 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -37,7 +37,6 @@ class ResourceDownloadTask : public SequentialTask {
     const QString& getFilename() const { return m_pack_version.fileName; }
     const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
-    ModPlatform::IndexedPack& getPack() { return m_pack; }
     const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; }
 
    private:
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 40f1efc4..de0af78c 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -1,23 +1,24 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  PolyMC - Minecraft Launcher
-*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #pragma once
 
+#include <qvariant.h>
 #include <QList>
 #include <QMetaType>
 #include <QString>
@@ -95,6 +96,7 @@ struct IndexedPack {
 
     bool versionsLoaded = false;
     QVector<IndexedVersion> versions;
+    QVariant loadedFileId;  // to check for already downloaded mods
 
     // Don't load by default, since some modplatform don't have that info
     bool extraDataLoaded = true;
@@ -110,11 +112,12 @@ struct IndexedPack {
     }
     [[nodiscard]] bool isAnyVersionSelected() const
     {
+        if (loadedFileId.isValid())
+            return true;
         if (!versionsLoaded)
             return false;
 
-        return std::any_of(versions.constBegin(), versions.constEnd(),
-                [](auto const& v) { return v.is_currently_selected; });
+        return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; });
     }
 };
 
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 7fb4a657..562dda33 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -159,26 +159,10 @@ void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlat
     m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty());
 }
 
-static ModPlatform::IndexedVersion& getVersionWithID(ModPlatform::IndexedPack& pack, QVariant id)
-{
-    Q_ASSERT(pack.versionsLoaded);
-    auto it = std::find_if(pack.versions.begin(), pack.versions.end(), [id](auto const& v) { return v.fileId == id; });
-    Q_ASSERT(it != pack.versions.end());
-    return *it;
-}
-
 void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver)
 {
-    if (auto selected_task_it = m_selected.find(pack.name); selected_task_it != m_selected.end()) {
-        auto selected_task = *selected_task_it;
-        auto old_version_id = selected_task->getVersionID();
-
-        if (selected_task->getProvider() != pack.provider)  // If the pack name matches but they are different providers search for the
-                                                            // old one(in the actual pack) and deselect it.
-            getVersionWithID(selected_task->getPack(), old_version_id).is_currently_selected = false;
-        else if (ver.fileId != old_version_id)  // If the new and old version IDs don't match, search for the old one and deselect it.
-            getVersionWithID(pack, old_version_id).is_currently_selected = false;
-    }
+    dynamic_cast<ResourcePage*>(m_container->getPage(Modrinth::id()))->removeResourceFromPage(pack.name);
+    dynamic_cast<ResourcePage*>(m_container->getPage(Flame::id()))->removeResourceFromPage(pack.name);
 
     // Deselect the new version too, since all versions of that pack got removed.
     ver.is_currently_selected = false;
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 3ffe6cb0..b69d2cf9 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -6,12 +6,24 @@
 
 #include "minecraft/MinecraftInstance.h"
 #include "minecraft/PackProfile.h"
+#include "minecraft/mod/ModFolderModel.h"
+#include "modplatform/ModIndex.h"
 
 #include <QMessageBox>
 
 namespace ResourceDownload {
 
-ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {}
+ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst)
+{
+    auto folder = static_cast<MinecraftInstance const&>(m_base_instance).loaderModList();
+    for (auto mod : folder->allMods()) {
+        auto meta = mod->metadata();
+        ModPlatform::IndexedPack pack{ meta->project_id, meta->provider, meta->name, meta->slug };
+        pack.loadedFileId = meta->file_id;
+        qWarning() << pack.loadedFileId;
+        addPack(pack);
+    }
+}
 
 /******** Make data requests ********/
 
@@ -24,7 +36,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
 
     std::optional<std::list<Version>> versions{};
 
-    { // Version filter
+    {  // Version filter
         if (!m_filter->versions.empty())
             versions = m_filter->versions;
     }
diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp
index 04be43ad..efff1ff4 100644
--- a/launcher/ui/pages/modplatform/ModPage.cpp
+++ b/launcher/ui/pages/modplatform/ModPage.cpp
@@ -55,8 +55,7 @@
 
 namespace ResourceDownload {
 
-ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance)
-    : ResourcePage(dialog, instance)
+ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance)
 {
     connect(m_ui->searchButton, &QPushButton::clicked, this, &ModPage::triggerSearch);
     connect(m_ui->resourceFilterButton, &QPushButton::clicked, this, &ModPage::filterMods);
@@ -75,12 +74,10 @@ void ModPage::setFilterWidget(unique_qobject_ptr<ModFilterWidget>& widget)
     m_filter_widget->setInstance(&static_cast<MinecraftInstance&>(m_base_instance));
     m_filter = m_filter_widget->getFilter();
 
-    connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, [&]{
-        m_ui->searchButton->setStyleSheet("text-decoration: underline");
-    });
-    connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, [&]{
-        m_ui->searchButton->setStyleSheet("text-decoration: none");
-    });
+    connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this,
+            [&] { m_ui->searchButton->setStyleSheet("text-decoration: underline"); });
+    connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this,
+            [&] { m_ui->searchButton->setStyleSheet("text-decoration: none"); });
 }
 
 /******** Callbacks to events in the UI (set up in the derived classes) ********/
@@ -128,8 +125,8 @@ void ModPage::updateVersionList()
     for (int i = 0; i < current_pack.versions.size(); i++) {
         auto version = current_pack.versions[i];
         bool valid = false;
-        for(auto& mcVer : m_filter->versions){
-            //NOTE: Flame doesn't care about loader, so passing it changes nothing.
+        for (auto& mcVer : m_filter->versions) {
+            // NOTE: Flame doesn't care about loader, so passing it changes nothing.
             if (validateVersion(version, mcVer.toString(), packProfile->getModLoaders())) {
                 valid = true;
                 break;
@@ -151,6 +148,7 @@ void ModPage::updateVersionList()
 void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
 {
     bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
+    m_model->addPack(pack);
     m_parent_dialog->addResource(pack, version, is_indexed);
 }
 
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index db7d26f8..c7c34a7c 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -3,12 +3,14 @@
 // SPDX-License-Identifier: GPL-3.0-only
 
 #include "ResourceModel.h"
+#include <qlist.h>
 
 #include <QCryptographicHash>
 #include <QIcon>
 #include <QMessageBox>
 #include <QPixmapCache>
 #include <QUrl>
+#include <algorithm>
 
 #include "Application.h"
 #include "BuildConfig.h"
@@ -335,6 +337,14 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
         ModPlatform::IndexedPack pack;
         try {
             loadIndexedPack(pack, packObj);
+            if (auto sel =
+                    std::find_if(m_selected.begin(), m_selected.end(),
+                                 [&pack](ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; });
+                sel != m_selected.end()) {
+                pack.versionsLoaded = sel->versionsLoaded;
+                pack.versions = sel->versions;
+                pack.loadedFileId = sel->loadedFileId;
+            }
             newList.append(pack);
         } catch (const JSONValidationError& e) {
             qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause();
@@ -398,6 +408,11 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind
     try {
         auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
         loadIndexedPackVersions(current_pack, arr);
+        if (current_pack.loadedFileId.isValid())
+            if (auto ver = std::find_if(current_pack.versions.begin(), current_pack.versions.end(),
+                                        [&current_pack](ModPlatform::IndexedVersion v) { return v.fileId == current_pack.loadedFileId; });
+                ver != current_pack.versions.end())
+                ver->is_currently_selected = true;
     } catch (const JSONValidationError& e) {
         qDebug() << doc;
         qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
@@ -441,4 +456,19 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
     emit projectInfoUpdated();
 }
 
+void ResourceModel::removePack(QString& rem)
+{
+    m_selected.removeIf([&rem](ModPlatform::IndexedPack i) { return rem == i.name; });
+    auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](ModPlatform::IndexedPack i) { return rem == i.name; });
+    if (pack == m_packs.end()) {  // ignore it if is not in the current search
+        return;
+    }
+    if (!pack->versionsLoaded) {
+        pack->loadedFileId = {};
+        return;
+    }
+    for (auto& ver : pack->versions)
+        ver.is_currently_selected = false;
+}
+
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 46a02d6e..5eb63901 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -80,6 +80,9 @@ class ResourceModel : public QAbstractListModel {
     /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */
     std::optional<QIcon> getIcon(QModelIndex&, const QUrl&);
 
+    void addPack(ModPlatform::IndexedPack& add) { m_selected.append(add); }
+    void removePack(QString& rem);
+
    protected:
     /** Resets the model's data. */
     void clearData();
@@ -124,6 +127,7 @@ class ResourceModel : public QAbstractListModel {
     QSet<QUrl> m_failed_icon_actions;
 
     QList<ModPlatform::IndexedPack> m_packs;
+    QList<ModPlatform::IndexedPack> m_selected;
 
     // HACK: We need this to prevent callbacks from calling the model after it has already been deleted.
     // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better?
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index bbd465bc..24347dbd 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -308,6 +308,7 @@ void ResourcePage::onVersionSelectionChanged(QString data)
 
 void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
 {
+    m_model->addPack(pack);
     m_parent_dialog->addResource(pack, version);
 }
 
@@ -316,6 +317,11 @@ void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModP
     m_parent_dialog->removeResource(pack, version);
 }
 
+void ResourcePage::removeResourceFromPage(QString& name)
+{
+    m_model->removePack(name);
+}
+
 void ResourcePage::onResourceSelected()
 {
     if (m_selected_version_index < 0)
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index 1896d53e..a9db52e3 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -74,10 +74,11 @@ class ResourcePage : public QWidget, public BasePage {
 
     virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
     virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
+    virtual void removeResourceFromPage(QString& name);
 
    protected slots:
     virtual void triggerSearch() {}
-   
+
     void onSelectionChanged(QModelIndex first, QModelIndex second);
     void onVersionSelectionChanged(QString data);
     void onResourceSelected();
diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp
index 251c07e7..1b9b2b83 100644
--- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp
+++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp
@@ -13,8 +13,7 @@
 
 namespace ResourceDownload {
 
-ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance)
-    : ResourcePage(dialog, instance)
+ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance)
 {
     connect(m_ui->searchButton, &QPushButton::clicked, this, &ShaderPackResourcePage::triggerSearch);
     connect(m_ui->packView, &QListView::doubleClicked, this, &ShaderPackResourcePage::onResourceSelected);
@@ -38,7 +37,8 @@ QMap<QString, QString> ShaderPackResourcePage::urlHandlers() const
 {
     QMap<QString, QString> map;
     map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth");
-    map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), "curseforge");
+    map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"),
+               "curseforge");
     map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge");
     return map;
 }
@@ -47,7 +47,7 @@ void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack,
 {
     if (version.loaders.contains(QStringLiteral("canvas")))
         version.custom_target_folder = QStringLiteral("resourcepacks");
-
+    m_model->addPack(pack);
     m_parent_dialog->addResource(pack, version);
 }
 
-- 
cgit 


From 75116364c6daea5affb029038d2a7d20bc601beb Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sat, 22 Apr 2023 00:55:11 +0300
Subject: Small Cleanup

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/ModIndex.h                 | 1 -
 launcher/ui/pages/modplatform/ModModel.cpp      | 1 -
 launcher/ui/pages/modplatform/ResourceModel.cpp | 2 +-
 3 files changed, 1 insertion(+), 3 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index de0af78c..b736aaf4 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -18,7 +18,6 @@
 
 #pragma once
 
-#include <qvariant.h>
 #include <QList>
 #include <QMetaType>
 #include <QString>
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index b69d2cf9..251200f7 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -20,7 +20,6 @@ ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceMo
         auto meta = mod->metadata();
         ModPlatform::IndexedPack pack{ meta->project_id, meta->provider, meta->name, meta->slug };
         pack.loadedFileId = meta->file_id;
-        qWarning() << pack.loadedFileId;
         addPack(pack);
     }
 }
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index c7c34a7c..0e74395f 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -3,10 +3,10 @@
 // SPDX-License-Identifier: GPL-3.0-only
 
 #include "ResourceModel.h"
-#include <qlist.h>
 
 #include <QCryptographicHash>
 #include <QIcon>
+#include <QList>
 #include <QMessageBox>
 #include <QPixmapCache>
 #include <QUrl>
-- 
cgit 


From 460e83207f9ae087846fc9ca210799e41f51a326 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sat, 22 Apr 2023 01:18:27 +0300
Subject: Fixed removeIf for Qt version

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/modplatform/ResourceModel.cpp | 34 ++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index 0e74395f..459c8c72 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -458,7 +458,39 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
 
 void ResourceModel::removePack(QString& rem)
 {
-    m_selected.removeIf([&rem](ModPlatform::IndexedPack i) { return rem == i.name; });
+    auto pred = [&rem](ModPlatform::IndexedPack i) { return rem == i.name; };
+#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
+    m_selected.removeIf(pred);
+#else
+    {  // well partial implementation of remove_if in case the QT Version is not high enough
+        const auto cbegin = m_selected.cbegin();
+        const auto cend = m_selected.cend();
+        const auto t_it = std::find_if(cbegin, cend, pred);
+        auto result = std::distance(cbegin, t_it);
+        if (result != m_selected.size()) {
+            // now detach:
+            const auto e = m_selected.end();
+
+            auto it = std::next(m_selected.begin(), result);
+            auto dest = it;
+
+            // Loop Invariants:
+            // - it != e
+            // - [next(it), e[ still to be checked
+            // - [c.begin(), dest[ are result
+            while (++it != e) {
+                if (!pred(*it)) {
+                    *dest = std::move(*it);
+                    ++dest;
+                }
+            }
+
+            result = std::distance(dest, e);
+            m_selected.erase(dest, e);
+        }
+    }
+#endif
+    // m_selected.removeAt(qsizetype i)
     auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](ModPlatform::IndexedPack i) { return rem == i.name; });
     if (pack == m_packs.end()) {  // ignore it if is not in the current search
         return;
-- 
cgit 


From f738d7566e45f618634c4d40ec45f78f96fac588 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sat, 22 Apr 2023 22:27:33 +0300
Subject: Fixed code qulity

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/modplatform/ResourceModel.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index 459c8c72..a58ce549 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -337,9 +337,9 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
         ModPlatform::IndexedPack pack;
         try {
             loadIndexedPack(pack, packObj);
-            if (auto sel =
-                    std::find_if(m_selected.begin(), m_selected.end(),
-                                 [&pack](ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; });
+            if (auto sel = std::find_if(
+                    m_selected.begin(), m_selected.end(),
+                    [&pack](const ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; });
                 sel != m_selected.end()) {
                 pack.versionsLoaded = sel->versionsLoaded;
                 pack.versions = sel->versions;
@@ -409,8 +409,9 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind
         auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
         loadIndexedPackVersions(current_pack, arr);
         if (current_pack.loadedFileId.isValid())
-            if (auto ver = std::find_if(current_pack.versions.begin(), current_pack.versions.end(),
-                                        [&current_pack](ModPlatform::IndexedVersion v) { return v.fileId == current_pack.loadedFileId; });
+            if (auto ver =
+                    std::find_if(current_pack.versions.begin(), current_pack.versions.end(),
+                                 [&current_pack](const ModPlatform::IndexedVersion& v) { return v.fileId == current_pack.loadedFileId; });
                 ver != current_pack.versions.end())
                 ver->is_currently_selected = true;
     } catch (const JSONValidationError& e) {
@@ -458,7 +459,7 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
 
 void ResourceModel::removePack(QString& rem)
 {
-    auto pred = [&rem](ModPlatform::IndexedPack i) { return rem == i.name; };
+    auto pred = [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; };
 #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
     m_selected.removeIf(pred);
 #else
@@ -491,7 +492,7 @@ void ResourceModel::removePack(QString& rem)
     }
 #endif
     // m_selected.removeAt(qsizetype i)
-    auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](ModPlatform::IndexedPack i) { return rem == i.name; });
+    auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; });
     if (pack == m_packs.end()) {  // ignore it if is not in the current search
         return;
     }
-- 
cgit 


From 248920a2211db0c55d01273cc36c735a629b0325 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 27 Apr 2023 01:33:46 +0300
Subject: Removed extra code

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/ModIndex.h                  |  3 --
 launcher/ui/dialogs/ResourceDownloadDialog.cpp   |  4 +--
 launcher/ui/pages/modplatform/ModModel.cpp       | 11 +------
 launcher/ui/pages/modplatform/ModPage.cpp        |  2 +-
 launcher/ui/pages/modplatform/ResourceModel.cpp  | 41 ++++--------------------
 launcher/ui/pages/modplatform/ResourcePage.cpp   |  2 +-
 launcher/ui/pages/modplatform/ShaderPackPage.cpp |  2 +-
 launcher/ui/widgets/PageContainer.cpp            |  5 +++
 launcher/ui/widgets/PageContainer.h              |  1 +
 9 files changed, 18 insertions(+), 53 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index b736aaf4..4497088c 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -95,7 +95,6 @@ struct IndexedPack {
 
     bool versionsLoaded = false;
     QVector<IndexedVersion> versions;
-    QVariant loadedFileId;  // to check for already downloaded mods
 
     // Don't load by default, since some modplatform don't have that info
     bool extraDataLoaded = true;
@@ -111,8 +110,6 @@ struct IndexedPack {
     }
     [[nodiscard]] bool isAnyVersionSelected() const
     {
-        if (loadedFileId.isValid())
-            return true;
         if (!versionsLoaded)
             return false;
 
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 562dda33..4ba38374 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -161,8 +161,8 @@ void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlat
 
 void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver)
 {
-    dynamic_cast<ResourcePage*>(m_container->getPage(Modrinth::id()))->removeResourceFromPage(pack.name);
-    dynamic_cast<ResourcePage*>(m_container->getPage(Flame::id()))->removeResourceFromPage(pack.name);
+    for (auto page : m_container->getPages())
+        static_cast<ResourcePage*>(page)->removeResourceFromPage(pack.name);
 
     // Deselect the new version too, since all versions of that pack got removed.
     ver.is_currently_selected = false;
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 251200f7..6a206a7c 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -13,16 +13,7 @@
 
 namespace ResourceDownload {
 
-ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst)
-{
-    auto folder = static_cast<MinecraftInstance const&>(m_base_instance).loaderModList();
-    for (auto mod : folder->allMods()) {
-        auto meta = mod->metadata();
-        ModPlatform::IndexedPack pack{ meta->project_id, meta->provider, meta->name, meta->slug };
-        pack.loadedFileId = meta->file_id;
-        addPack(pack);
-    }
-}
+ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {}
 
 /******** Make data requests ********/
 
diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp
index efff1ff4..8a4f55cb 100644
--- a/launcher/ui/pages/modplatform/ModPage.cpp
+++ b/launcher/ui/pages/modplatform/ModPage.cpp
@@ -148,8 +148,8 @@ void ModPage::updateVersionList()
 void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
 {
     bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
-    m_model->addPack(pack);
     m_parent_dialog->addResource(pack, version, is_indexed);
+    m_model->addPack(pack);
 }
 
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index a58ce549..b83cad0d 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -343,7 +343,6 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
                 sel != m_selected.end()) {
                 pack.versionsLoaded = sel->versionsLoaded;
                 pack.versions = sel->versions;
-                pack.loadedFileId = sel->loadedFileId;
             }
             newList.append(pack);
         } catch (const JSONValidationError& e) {
@@ -408,12 +407,6 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind
     try {
         auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
         loadIndexedPackVersions(current_pack, arr);
-        if (current_pack.loadedFileId.isValid())
-            if (auto ver =
-                    std::find_if(current_pack.versions.begin(), current_pack.versions.end(),
-                                 [&current_pack](const ModPlatform::IndexedVersion& v) { return v.fileId == current_pack.loadedFileId; });
-                ver != current_pack.versions.end())
-                ver->is_currently_selected = true;
     } catch (const JSONValidationError& e) {
         qDebug() << doc;
         qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
@@ -463,41 +456,19 @@ void ResourceModel::removePack(QString& rem)
 #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
     m_selected.removeIf(pred);
 #else
-    {  // well partial implementation of remove_if in case the QT Version is not high enough
-        const auto cbegin = m_selected.cbegin();
-        const auto cend = m_selected.cend();
-        const auto t_it = std::find_if(cbegin, cend, pred);
-        auto result = std::distance(cbegin, t_it);
-        if (result != m_selected.size()) {
-            // now detach:
-            const auto e = m_selected.end();
-
-            auto it = std::next(m_selected.begin(), result);
-            auto dest = it;
-
-            // Loop Invariants:
-            // - it != e
-            // - [next(it), e[ still to be checked
-            // - [c.begin(), dest[ are result
-            while (++it != e) {
-                if (!pred(*it)) {
-                    *dest = std::move(*it);
-                    ++dest;
-                }
-            }
-
-            result = std::distance(dest, e);
-            m_selected.erase(dest, e);
-        }
+    {
+        for (auto it = m_selected.begin(); it != m_selected.end();)
+            if (pred(*it))
+                it = m_selected.erase(it);
+            else
+                ++it;
     }
 #endif
-    // m_selected.removeAt(qsizetype i)
     auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; });
     if (pack == m_packs.end()) {  // ignore it if is not in the current search
         return;
     }
     if (!pack->versionsLoaded) {
-        pack->loadedFileId = {};
         return;
     }
     for (auto& ver : pack->versions)
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index 24347dbd..d41503e8 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -308,8 +308,8 @@ void ResourcePage::onVersionSelectionChanged(QString data)
 
 void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
 {
-    m_model->addPack(pack);
     m_parent_dialog->addResource(pack, version);
+    m_model->addPack(pack);
 }
 
 void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp
index 1b9b2b83..729e714c 100644
--- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp
+++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp
@@ -47,8 +47,8 @@ void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack,
 {
     if (version.loaders.contains(QStringLiteral("canvas")))
         version.custom_target_folder = QStringLiteral("resourcepacks");
-    m_model->addPack(pack);
     m_parent_dialog->addResource(pack, version);
+    m_model->addPack(pack);
 }
 
 }  // namespace ResourceDownload
diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp
index 0a06a351..84a4e0de 100644
--- a/launcher/ui/widgets/PageContainer.cpp
+++ b/launcher/ui/widgets/PageContainer.cpp
@@ -135,6 +135,11 @@ BasePage* PageContainer::getPage(QString pageId)
     return m_model->findPageEntryById(pageId);
 }
 
+const QList<BasePage*> PageContainer::getPages() const
+{
+    return m_model->pages();
+}
+
 void PageContainer::refreshContainer()
 {
     m_proxyModel->invalidate();
diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h
index 97e294dc..ad74d43a 100644
--- a/launcher/ui/widgets/PageContainer.h
+++ b/launcher/ui/widgets/PageContainer.h
@@ -80,6 +80,7 @@ public:
 
     virtual bool selectPage(QString pageId) override;
     BasePage* getPage(QString pageId) override;
+    const QList<BasePage*> getPages() const;
 
     void refreshContainer() override;
     virtual void setParentContainer(BasePageContainer * container)
-- 
cgit 


From 61a235561896fc82a19da00126e361bb56d61c69 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 27 Apr 2023 01:41:26 +0300
Subject: Removed formated but not used files

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ResourceDownloadTask.h            | 51 +++++++++++++++---------------
 launcher/modplatform/ModIndex.h            | 33 +++++++++----------
 launcher/ui/pages/modplatform/ModModel.cpp |  4 +--
 3 files changed, 43 insertions(+), 45 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index 0d90bd36..73ad2d07 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -1,45 +1,41 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  Prism Launcher - Minecraft Launcher
- *  Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
- *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
+*  Prism Launcher - Minecraft Launcher
+*  Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
+*  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, version 3.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
 
 #pragma once
 
 #include "net/NetJob.h"
 #include "tasks/SequentialTask.h"
 
-#include "minecraft/mod/tasks/LocalModUpdateTask.h"
 #include "modplatform/ModIndex.h"
+#include "minecraft/mod/tasks/LocalModUpdateTask.h"
 
 class ResourceFolderModel;
 
 class ResourceDownloadTask : public SequentialTask {
     Q_OBJECT
-   public:
-    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack,
-                                  ModPlatform::IndexedVersion version,
-                                  const std::shared_ptr<ResourceFolderModel> packs,
-                                  bool is_indexed = true);
+public:
+    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr<ResourceFolderModel> packs, bool is_indexed = true);
     const QString& getFilename() const { return m_pack_version.fileName; }
     const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
-    const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; }
 
-   private:
+private:
     ModPlatform::IndexedPack m_pack;
     ModPlatform::IndexedVersion m_pack_version;
     const std::shared_ptr<ResourceFolderModel> m_pack_model;
@@ -51,8 +47,11 @@ class ResourceDownloadTask : public SequentialTask {
     void downloadFailed(QString reason);
     void downloadSucceeded();
 
-    std::tuple<QString, QString> to_delete{ "", "" };
+    std::tuple<QString, QString> to_delete {"", ""};
 
-   private slots:
+private slots:
     void hasOldResource(QString name, QString filename);
 };
+
+
+
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 4497088c..40f1efc4 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, version 3.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
+*  PolyMC - Minecraft Launcher
+*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, version 3.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
 
 #pragma once
 
@@ -113,7 +113,8 @@ struct IndexedPack {
         if (!versionsLoaded)
             return false;
 
-        return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; });
+        return std::any_of(versions.constBegin(), versions.constEnd(),
+                [](auto const& v) { return v.is_currently_selected; });
     }
 };
 
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 6a206a7c..3ffe6cb0 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -6,8 +6,6 @@
 
 #include "minecraft/MinecraftInstance.h"
 #include "minecraft/PackProfile.h"
-#include "minecraft/mod/ModFolderModel.h"
-#include "modplatform/ModIndex.h"
 
 #include <QMessageBox>
 
@@ -26,7 +24,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
 
     std::optional<std::list<Version>> versions{};
 
-    {  // Version filter
+    { // Version filter
         if (!m_filter->versions.empty())
             versions = m_filter->versions;
     }
-- 
cgit 


From f8bf71e152aba15d23b5b92382bb112de125d4d1 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 3 May 2023 00:49:54 +0300
Subject: Moved the selected resources to one list

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ResourceDownloadTask.cpp                | 11 +++--
 launcher/ResourceDownloadTask.h                  | 25 ++++++----
 launcher/modplatform/ModIndex.h                  |  1 -
 launcher/ui/dialogs/ResourceDownloadDialog.cpp   | 59 ++++++++++++++----------
 launcher/ui/dialogs/ResourceDownloadDialog.h     |  9 ++--
 launcher/ui/pages/modplatform/ModPage.cpp        |  7 +--
 launcher/ui/pages/modplatform/ModPage.h          |  2 +-
 launcher/ui/pages/modplatform/ResourceModel.cpp  | 29 ++++++++----
 launcher/ui/pages/modplatform/ResourceModel.h    | 14 ++++--
 launcher/ui/pages/modplatform/ResourcePage.cpp   | 17 +++++--
 launcher/ui/pages/modplatform/ResourcePage.h     | 13 ++++--
 launcher/ui/pages/modplatform/ShaderPackPage.cpp | 10 ++--
 launcher/ui/pages/modplatform/ShaderPackPage.h   |  2 +-
 13 files changed, 124 insertions(+), 75 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp
index 98bcf259..f7d3487a 100644
--- a/launcher/ResourceDownloadTask.cpp
+++ b/launcher/ResourceDownloadTask.cpp
@@ -27,8 +27,9 @@
 ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack,
                                            ModPlatform::IndexedVersion version,
                                            const std::shared_ptr<ResourceFolderModel> packs,
-                                           bool is_indexed)
-    : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs)
+                                           bool is_indexed,
+                                           QString custom_target_folder)
+    : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs), m_custom_target_folder(custom_target_folder)
 {
     if (auto model = dynamic_cast<ModFolderModel*>(m_pack_model.get()); model && is_indexed) {
         m_update_task.reset(new LocalModUpdateTask(model->indexDir(), m_pack, m_pack_version));
@@ -40,13 +41,13 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack,
     m_filesNetJob.reset(new NetJob(tr("Resource download"), APPLICATION->network()));
     m_filesNetJob->setStatus(tr("Downloading resource:\n%1").arg(m_pack_version.downloadUrl));
 
-    QDir dir { m_pack_model->dir() };
+    QDir dir{ m_pack_model->dir() };
     {
         // FIXME: Make this more generic. May require adding additional info to IndexedVersion,
         //        or adquiring a reference to the base instance.
-        if (!m_pack_version.custom_target_folder.isEmpty()) {
+        if (!m_custom_target_folder.isEmpty()) {
             dir.cdUp();
-            dir.cd(m_pack_version.custom_target_folder);
+            dir.cd(m_custom_target_folder);
         }
     }
 
diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index 73ad2d07..fe41170a 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -22,23 +22,31 @@
 #include "net/NetJob.h"
 #include "tasks/SequentialTask.h"
 
-#include "modplatform/ModIndex.h"
 #include "minecraft/mod/tasks/LocalModUpdateTask.h"
+#include "modplatform/ModIndex.h"
 
 class ResourceFolderModel;
 
 class ResourceDownloadTask : public SequentialTask {
     Q_OBJECT
-public:
-    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr<ResourceFolderModel> packs, bool is_indexed = true);
+   public:
+    explicit ResourceDownloadTask(ModPlatform::IndexedPack pack,
+                                  ModPlatform::IndexedVersion version,
+                                  const std::shared_ptr<ResourceFolderModel> packs,
+                                  bool is_indexed = true,
+                                  QString custom_target_folder = {});
     const QString& getFilename() const { return m_pack_version.fileName; }
-    const QString& getCustomPath() const { return m_pack_version.custom_target_folder; }
+    const QString& getCustomPath() const { return m_custom_target_folder; }
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
+    const QString& getName() const { return m_pack.name; }
+    ModPlatform::IndexedPack& getPack() { return m_pack; }
+    // void setSelectedVersion(ModPlatform::IndexedVersion version) { m_pack_version = std::move(version); }
 
-private:
+   private:
     ModPlatform::IndexedPack m_pack;
     ModPlatform::IndexedVersion m_pack_version;
     const std::shared_ptr<ResourceFolderModel> m_pack_model;
+    QString m_custom_target_folder;
 
     NetJob::Ptr m_filesNetJob;
     LocalModUpdateTask::Ptr m_update_task;
@@ -47,11 +55,8 @@ private:
     void downloadFailed(QString reason);
     void downloadSucceeded();
 
-    std::tuple<QString, QString> to_delete {"", ""};
+    std::tuple<QString, QString> to_delete{ "", "" };
 
-private slots:
+   private slots:
     void hasOldResource(QString name, QString filename);
 };
-
-
-
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 40f1efc4..1b99a88e 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -68,7 +68,6 @@ struct IndexedVersion {
 
     // For internal use, not provided by APIs
     bool is_currently_selected = false;
-    QString custom_target_folder;
 };
 
 struct ExtraPackData {
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 4ba38374..ef3200a2 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -20,6 +20,7 @@
 #include "ResourceDownloadDialog.h"
 
 #include <QPushButton>
+#include <algorithm>
 
 #include "Application.h"
 #include "ResourceDownloadTask.h"
@@ -118,21 +119,24 @@ void ResourceDownloadDialog::connectButtons()
 
 void ResourceDownloadDialog::confirm()
 {
-    auto keys = m_selected.keys();
-    keys.sort(Qt::CaseInsensitive);
+    auto selected = getTasks();
+    std::sort(selected.begin(), selected.end(), [](const DownloadTaskPtr& a, const DownloadTaskPtr& b) {
+        return QString::compare(a->getName(), b->getName(), Qt::CaseInsensitive) < 0;
+    });
 
     auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString()));
     confirm_dialog->retranslateUi(resourcesString());
 
-    for (auto& task : keys) {
-        auto selected = m_selected.constFind(task).value();
-        confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() });
+    for (auto& task : selected) {
+        confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath() });
     }
 
     if (confirm_dialog->exec()) {
         auto deselected = confirm_dialog->deselectedResources();
-        for (auto name : deselected) {
-            m_selected.remove(name);
+        for (auto page : m_container->getPages()) {
+            auto res = static_cast<ResourcePage*>(page);
+            for (auto name : deselected)
+                res->removeResourceFromPage(name);
         }
 
         this->accept();
@@ -149,32 +153,39 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage()
     return m_selectedPage;
 }
 
-void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed)
+void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver)
 {
-    removeResource(pack, ver);
-
-    ver.is_currently_selected = true;
-    m_selected.insert(pack.name, makeShared<ResourceDownloadTask>(pack, ver, getBaseModel(), is_indexed));
-
-    m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty());
+    removeResource(pack.name);
+    m_selectedPage->addResourceToPage(pack, ver, getBaseModel());
+    setButtonStatus();
 }
 
-void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver)
+void ResourceDownloadDialog::removeResource(const QString& pack_name)
 {
-    for (auto page : m_container->getPages())
-        static_cast<ResourcePage*>(page)->removeResourceFromPage(pack.name);
-
-    // Deselect the new version too, since all versions of that pack got removed.
-    ver.is_currently_selected = false;
-
-    m_selected.remove(pack.name);
+    for (auto page : m_container->getPages()) {
+        static_cast<ResourcePage*>(page)->removeResourceFromPage(pack_name);
+    }
+    setButtonStatus();
+}
 
-    m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty());
+void ResourceDownloadDialog::setButtonStatus()
+{
+    bool selected;
+    for (auto page : m_container->getPages()) {
+        auto res = static_cast<ResourcePage*>(page);
+        selected = selected || res->hasSelectedPacks();
+    }
+    m_buttons.button(QDialogButtonBox::Ok)->setEnabled(selected);
 }
 
 const QList<ResourceDownloadDialog::DownloadTaskPtr> ResourceDownloadDialog::getTasks()
 {
-    return m_selected.values();
+    QList<DownloadTaskPtr> selected;
+    for (auto page : m_container->getPages()) {
+        auto res = static_cast<ResourcePage*>(page);
+        selected.append(res->selectedPacks());
+    }
+    return selected;
 }
 
 void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* selected)
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h
index 5678dc8b..204e870f 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.h
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.h
@@ -62,8 +62,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
     bool selectPage(QString pageId);
     ResourcePage* getSelectedPage();
 
-    void addResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, bool is_indexed = false);
-    void removeResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
+    void addResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
+    void removeResource(const QString&);
 
     const QList<DownloadTaskPtr> getTasks();
     [[nodiscard]] const std::shared_ptr<ResourceFolderModel> getBaseModel() const { return m_base_model; }
@@ -79,6 +79,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
 
    protected:
     [[nodiscard]] virtual QString geometrySaveKey() const { return ""; }
+    void setButtonStatus();
 
    protected:
     const std::shared_ptr<ResourceFolderModel> m_base_model;
@@ -88,12 +89,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
 
     QDialogButtonBox m_buttons;
     QVBoxLayout m_vertical_layout;
-
-    QHash<QString, DownloadTaskPtr> m_selected;
 };
 
-
-
 class ModDownloadDialog final : public ResourceDownloadDialog {
     Q_OBJECT
 
diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp
index 8a4f55cb..a6186d89 100644
--- a/launcher/ui/pages/modplatform/ModPage.cpp
+++ b/launcher/ui/pages/modplatform/ModPage.cpp
@@ -145,11 +145,12 @@ void ModPage::updateVersionList()
     updateSelectionButton();
 }
 
-void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
+void ModPage::addResourceToPage(ModPlatform::IndexedPack& pack,
+                                ModPlatform::IndexedVersion& version,
+                                const std::shared_ptr<ResourceFolderModel> base_model)
 {
     bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
-    m_parent_dialog->addResource(pack, version, is_indexed);
-    m_model->addPack(pack);
+    m_model->addPack(pack, version, base_model, is_indexed);
 }
 
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h
index c3b58cd6..6ecf8a94 100644
--- a/launcher/ui/pages/modplatform/ModPage.h
+++ b/launcher/ui/pages/modplatform/ModPage.h
@@ -50,7 +50,7 @@ class ModPage : public ResourcePage {
 
     [[nodiscard]] QMap<QString, QString> urlHandlers() const override;
 
-    void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override;
+    void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>) override;
 
     virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const -> bool = 0;
 
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index b83cad0d..056b28cc 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -337,14 +337,15 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
         ModPlatform::IndexedPack pack;
         try {
             loadIndexedPack(pack, packObj);
-            if (auto sel = std::find_if(
-                    m_selected.begin(), m_selected.end(),
-                    [&pack](const ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; });
+            if (auto sel = std::find_if(m_selected.begin(), m_selected.end(),
+                                        [&pack](const DownloadTaskPtr i) {
+                                            const auto ipack = i->getPack();
+                                            return ipack.provider == pack.provider && ipack.addonId == pack.addonId;
+                                        });
                 sel != m_selected.end()) {
-                pack.versionsLoaded = sel->versionsLoaded;
-                pack.versions = sel->versions;
-            }
-            newList.append(pack);
+                newList.append(sel->get()->getPack());
+            } else
+                newList.append(pack);
         } catch (const JSONValidationError& e) {
             qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause();
             continue;
@@ -450,9 +451,19 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
     emit projectInfoUpdated();
 }
 
-void ResourceModel::removePack(QString& rem)
+void ResourceModel::addPack(ModPlatform::IndexedPack& pack,
+                            ModPlatform::IndexedVersion& version,
+                            const std::shared_ptr<ResourceFolderModel> packs,
+                            bool is_indexed,
+                            QString custom_target_folder)
+{
+    version.is_currently_selected = true;
+    m_selected.append(makeShared<ResourceDownloadTask>(pack, version, packs, is_indexed, custom_target_folder));
+}
+
+void ResourceModel::removePack(const QString& rem)
 {
-    auto pred = [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; };
+    auto pred = [&rem](const DownloadTaskPtr i) { return rem == i->getName(); };
 #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
     m_selected.removeIf(pred);
 #else
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 5eb63901..735d1687 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -10,6 +10,7 @@
 
 #include "QObjectPtr.h"
 
+#include "ResourceDownloadTask.h"
 #include "modplatform/ResourceAPI.h"
 
 #include "tasks/ConcurrentTask.h"
@@ -29,6 +30,8 @@ class ResourceModel : public QAbstractListModel {
     Q_PROPERTY(QString search_term MEMBER m_search_term WRITE setSearchTerm)
 
    public:
+    using DownloadTaskPtr = shared_qobject_ptr<ResourceDownloadTask>;
+
     ResourceModel(ResourceAPI* api);
     ~ResourceModel() override;
 
@@ -80,8 +83,13 @@ class ResourceModel : public QAbstractListModel {
     /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */
     std::optional<QIcon> getIcon(QModelIndex&, const QUrl&);
 
-    void addPack(ModPlatform::IndexedPack& add) { m_selected.append(add); }
-    void removePack(QString& rem);
+    void addPack(ModPlatform::IndexedPack& pack,
+                 ModPlatform::IndexedVersion& version,
+                 const std::shared_ptr<ResourceFolderModel> packs,
+                 bool is_indexed = false,
+                 QString custom_target_folder = {});
+    void removePack(const QString& rem);
+    QList<DownloadTaskPtr> selectedPacks() { return m_selected; }
 
    protected:
     /** Resets the model's data. */
@@ -127,7 +135,7 @@ class ResourceModel : public QAbstractListModel {
     QSet<QUrl> m_failed_icon_actions;
 
     QList<ModPlatform::IndexedPack> m_packs;
-    QList<ModPlatform::IndexedPack> m_selected;
+    QList<DownloadTaskPtr> m_selected;
 
     // HACK: We need this to prevent callbacks from calling the model after it has already been deleted.
     // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better?
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index d41503e8..4ebdea56 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -37,6 +37,7 @@
  */
 
 #include "ResourcePage.h"
+#include "modplatform/ModIndex.h"
 #include "ui_ResourcePage.h"
 
 #include <QDesktopServices>
@@ -309,15 +310,21 @@ void ResourcePage::onVersionSelectionChanged(QString data)
 void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
 {
     m_parent_dialog->addResource(pack, version);
-    m_model->addPack(pack);
 }
 
-void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
+void ResourcePage::removeResourceFromDialog(const QString& pack_name)
 {
-    m_parent_dialog->removeResource(pack, version);
+    m_parent_dialog->removeResource(pack_name);
 }
 
-void ResourcePage::removeResourceFromPage(QString& name)
+void ResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack,
+                                     ModPlatform::IndexedVersion& ver,
+                                     const std::shared_ptr<ResourceFolderModel> base_model)
+{
+    m_model->addPack(pack, ver, base_model);
+}
+
+void ResourcePage::removeResourceFromPage(const QString& name)
 {
     m_model->removePack(name);
 }
@@ -333,7 +340,7 @@ void ResourcePage::onResourceSelected()
 
     auto& version = current_pack.versions[m_selected_version_index];
     if (version.is_currently_selected)
-        removeResourceFromDialog(current_pack, version);
+        removeResourceFromDialog(current_pack.name);
     else
         addResourceToDialog(current_pack, version);
 
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index a9db52e3..df68e6fd 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -7,10 +7,12 @@
 #include <QTimer>
 #include <QWidget>
 
+#include "ResourceDownloadTask.h"
 #include "modplatform/ModIndex.h"
 #include "modplatform/ResourceAPI.h"
 
 #include "ui/pages/BasePage.h"
+#include "ui/pages/modplatform/ResourceModel.h"
 #include "ui/widgets/ProgressWidget.h"
 
 namespace Ui {
@@ -27,6 +29,7 @@ class ResourceModel;
 class ResourcePage : public QWidget, public BasePage {
     Q_OBJECT
    public:
+    using DownloadTaskPtr = shared_qobject_ptr<ResourceDownloadTask>;
     ~ResourcePage() override;
 
     /* Affects what the user sees */
@@ -72,9 +75,13 @@ class ResourcePage : public QWidget, public BasePage {
     virtual void updateSelectionButton();
     virtual void updateVersionList();
 
-    virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
-    virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
-    virtual void removeResourceFromPage(QString& name);
+    void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
+    void removeResourceFromDialog(const QString& pack_name);
+    virtual void removeResourceFromPage(const QString& name);
+    virtual void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>);
+
+    QList<DownloadTaskPtr> selectedPacks() { return m_model->selectedPacks(); }
+    bool hasSelectedPacks() { return !(m_model->selectedPacks().isEmpty()); }
 
    protected slots:
     virtual void triggerSearch() {}
diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp
index 729e714c..c7a69418 100644
--- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp
+++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp
@@ -43,12 +43,14 @@ QMap<QString, QString> ShaderPackResourcePage::urlHandlers() const
     return map;
 }
 
-void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
+void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack,
+                                               ModPlatform::IndexedVersion& version,
+                                               const std::shared_ptr<ResourceFolderModel> base_model)
 {
+    QString custom_target_folder;
     if (version.loaders.contains(QStringLiteral("canvas")))
-        version.custom_target_folder = QStringLiteral("resourcepacks");
-    m_parent_dialog->addResource(pack, version);
-    m_model->addPack(pack);
+        custom_target_folder = QStringLiteral("resourcepacks");
+    m_model->addPack(pack, version, base_model, false, custom_target_folder);
 }
 
 }  // namespace ResourceDownload
diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h
index 972419a8..8a293f74 100644
--- a/launcher/ui/pages/modplatform/ShaderPackPage.h
+++ b/launcher/ui/pages/modplatform/ShaderPackPage.h
@@ -40,7 +40,7 @@ class ShaderPackResourcePage : public ResourcePage {
 
     [[nodiscard]] bool supportsFiltering() const override { return false; };
 
-    void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override;
+    void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>) override;
 
     [[nodiscard]] QMap<QString, QString> urlHandlers() const override;
 
-- 
cgit 


From f6ed2036b34177d7f932007dc5b3cc3d59f99aea Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 3 May 2023 00:55:18 +0300
Subject: Removed comment

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ResourceDownloadTask.h | 1 -
 1 file changed, 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h
index fe41170a..32b1120c 100644
--- a/launcher/ResourceDownloadTask.h
+++ b/launcher/ResourceDownloadTask.h
@@ -40,7 +40,6 @@ class ResourceDownloadTask : public SequentialTask {
     const QVariant& getVersionID() const { return m_pack_version.fileId; }
     const QString& getName() const { return m_pack.name; }
     ModPlatform::IndexedPack& getPack() { return m_pack; }
-    // void setSelectedVersion(ModPlatform::IndexedVersion version) { m_pack_version = std::move(version); }
 
    private:
     ModPlatform::IndexedPack m_pack;
-- 
cgit 


From e4449a0ba32593b4fd76e3f2ced176e5b3bbd952 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 3 May 2023 09:09:07 +0300
Subject: Initialized variable

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index ef3200a2..90922c8e 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -170,7 +170,7 @@ void ResourceDownloadDialog::removeResource(const QString& pack_name)
 
 void ResourceDownloadDialog::setButtonStatus()
 {
-    bool selected;
+    auto selected = false;
     for (auto page : m_container->getPages()) {
         auto res = static_cast<ResourcePage*>(page);
         selected = selected || res->hasSelectedPacks();
-- 
cgit 


From f7b912fc9d804902a725fa903be8574e1e202f69 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 4 May 2023 21:52:48 +0300
Subject: Fixed comments

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 32 +++++++++++++++-------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   | 20 +++++++-------
 .../minecraft/mod/tasks/LocalModUpdateTask.cpp     |  2 +-
 launcher/modplatform/ModIndex.h                    |  4 ++-
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     | 23 ++++++++++++++--
 launcher/ui/dialogs/ResourceDownloadDialog.h       |  2 ++
 launcher/ui/dialogs/ReviewMessageBox.cpp           | 12 ++++++++
 launcher/ui/dialogs/ReviewMessageBox.h             |  1 +
 8 files changed, 71 insertions(+), 25 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index e1760f16..2f08ae6d 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -1,8 +1,7 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *  Prism Launcher - Minecraft Launcher
+ *  Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -47,7 +46,7 @@ static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst)
 GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
                                                BaseInstance* instance,
                                                ModFolderModel* folder,
-                                               QList<std::shared_ptr<PackDependecny>> selected)
+                                               QList<std::shared_ptr<PackDependency>> selected)
     : SequentialTask(parent, "Get dependencies")
     , m_selected(selected)
     , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
@@ -66,7 +65,7 @@ void GetModDependenciesTask::prepare()
 {
     for (auto sel : m_selected) {
         for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) {
-            addTask(prepareDependencyTask(dep, sel->pack.provider, 20));
+            addTask(prepareDependencyTask(dep, sel->pack.provider, sel->pack.addonId, 20));
         }
     }
 }
@@ -81,7 +80,7 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
                                         [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; });
                 dep == c_dependencies.end()) {  // check the current dependency list
                 if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
-                                            [&ver_dep, providerName](std::shared_ptr<PackDependecny> i) {
+                                            [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
                                                 return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName;
                                             });
                     dep == m_selected.end()) {  // check the selected versions
@@ -90,7 +89,15 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
                                                     return i->project_id == ver_dep.addonId && i->provider == providerName;
                                                 });
                         dep == m_mods.end()) {  // check the existing mods
-                        c_dependencies.append(ver_dep);
+                        if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(),
+                                                    [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
+                                                        return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName;
+                                                    });
+                            dep == m_pack_dependencies.end()) {  // check loaded dependencies
+                            c_dependencies.append(ver_dep);
+                        } else {  // already there just append the required_by
+                            dep->get()->version.required_by.append(version.addonId);
+                        }
                     }
                 }
             }
@@ -101,11 +108,13 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
 
 Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep,
                                                         const ModPlatform::ResourceProvider providerName,
+                                                        QVariant required_by,
                                                         int level)
 {
-    auto pDep = std::make_shared<PackDependecny>();
+    auto pDep = std::make_shared<PackDependency>();
     pDep->dependency = dep;
     pDep->pack = { dep.addonId, providerName };
+    pDep->version.required_by.append(required_by);
     m_pack_dependencies.append(pDep);
     auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
 
@@ -136,7 +145,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
     ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
     ResourceAPI::DependencySearchCallbacks callbacks;
 
-    callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) {
+    callbacks.on_succeed = [dep, provider, pDep, level, required_by, this](auto& doc, auto& pack) {
         try {
             QJsonArray arr;
             if (dep.version.length() != 0 && doc.isObject()) {
@@ -144,6 +153,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             } else {
                 arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
             }
+            auto required_by = pDep->version.required_by;
             pDep->version = provider.mod->loadDependencyVersions(dep, arr);
             if (!pDep->version.addonId.isValid()) {
                 qWarning() << "Error while reading mod version empty ";
@@ -151,8 +161,10 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
                 return;
             }
             pDep->version.is_currently_selected = true;
+            pDep->version.required_by = required_by;
             pDep->pack.versions = { pDep->version };
             pDep->pack.versionsLoaded = true;
+
         } catch (const JSONValidationError& e) {
             qDebug() << doc;
             qWarning() << "Error while reading mod version: " << e.cause();
@@ -163,7 +175,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             return;
         }
         for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) {
-            addTask(prepareDependencyTask(dep, provider.name, level - 1));
+            addTask(prepareDependencyTask(dep, provider.name, pDep->pack.addonId, level - 1));
         }
     };
 
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 40f80ebf..c8d378ef 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Prism Launcher - Minecraft Launcher
+ *  Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -38,12 +38,12 @@ class GetModDependenciesTask : public SequentialTask {
    public:
     using Ptr = shared_qobject_ptr<GetModDependenciesTask>;
 
-    struct PackDependecny {
+    struct PackDependency {
         ModPlatform::Dependency dependency;
         ModPlatform::IndexedPack pack;
         ModPlatform::IndexedVersion version;
-        PackDependecny(){};
-        PackDependecny(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v)
+        PackDependency(){};
+        PackDependency(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v)
         {
             pack = p;
             version = v;
@@ -59,20 +59,20 @@ class GetModDependenciesTask : public SequentialTask {
     explicit GetModDependenciesTask(QObject* parent,
                                     BaseInstance* instance,
                                     ModFolderModel* folder,
-                                    QList<std::shared_ptr<PackDependecny>> selected);
+                                    QList<std::shared_ptr<PackDependency>> selected);
 
-    auto getDependecies() const -> QList<std::shared_ptr<PackDependecny>> { return m_pack_dependencies; }
+    auto getDependecies() const -> QList<std::shared_ptr<PackDependency>> { return m_pack_dependencies; }
 
    protected slots:
-    Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int);
+    Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, QVariant, int);
     QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&,
                                                              const ModPlatform::ResourceProvider providerName);
     void prepare();
 
    private:
-    QList<std::shared_ptr<PackDependecny>> m_pack_dependencies;
+    QList<std::shared_ptr<PackDependency>> m_pack_dependencies;
     QList<std::shared_ptr<Metadata::ModStruct>> m_mods;
-    QList<std::shared_ptr<PackDependecny>> m_selected;
+    QList<std::shared_ptr<PackDependency>> m_selected;
     Provider m_flame_provider;
     Provider m_modrinth_provider;
 
diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp
index 6b139ca1..4352fad9 100644
--- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
+ *  Prism Launcher - Minecraft Launcher
  *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
  *
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 5ff7bbc9..5b439935 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
+ *  Prism Launcher - Minecraft Launcher
  *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -78,6 +79,7 @@ struct IndexedVersion {
     // For internal use, not provided by APIs
     bool is_currently_selected = false;
     QString custom_target_folder;
+    QList<QVariant> required_by;
 };
 
 struct ExtraPackData {
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 9c28acd9..ca2d409c 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -126,6 +126,22 @@ void ResourceDownloadDialog::connectButtons()
 
 static ModPlatform::ProviderCapabilities ProviderCaps;
 
+QStringList ResourceDownloadDialog::getReqiredBy(QList<QVariant> req_by)
+{
+    auto req = QStringList();
+    auto keys = m_selected.keys();
+    for (auto r : req_by) {
+        for (auto& task : keys) {
+            auto selected = m_selected.constFind(task).value()->getPack();
+            if (selected.addonId == r) {
+                req.append(selected.name);
+                break;
+            }
+        }
+    }
+    return req;
+}
+
 void ResourceDownloadDialog::confirm()
 {
     auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString()));
@@ -162,8 +178,9 @@ void ResourceDownloadDialog::confirm()
     keys.sort(Qt::CaseInsensitive);
     for (auto& task : keys) {
         auto selected = m_selected.constFind(task).value();
+        auto required_by = getReqiredBy(selected->getVersion().required_by);
         confirm_dialog->appendResource(
-            { task, selected->getFilename(), selected->getCustomPath(), ProviderCaps.name(selected->getProvider()) });
+            { task, selected->getFilename(), selected->getCustomPath(), ProviderCaps.name(selected->getProvider()), required_by });
     }
 
     if (confirm_dialog->exec()) {
@@ -261,10 +278,10 @@ GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask()
 {
     if (auto model = dynamic_cast<ModFolderModel*>(getBaseModel().get()); model) {
         auto keys = m_selected.keys();
-        QList<std::shared_ptr<GetModDependenciesTask::PackDependecny>> selectedVers;
+        QList<std::shared_ptr<GetModDependenciesTask::PackDependency>> selectedVers;
         for (auto& task : keys) {
             auto selected = m_selected.constFind(task).value();
-            selectedVers.append(std::make_shared<GetModDependenciesTask::PackDependecny>(selected->getPack(), selected->getVersion()));
+            selectedVers.append(std::make_shared<GetModDependenciesTask::PackDependency>(selected->getPack(), selected->getVersion()));
         }
 
         return makeShared<GetModDependenciesTask>(this, m_instance, model, selectedVers);
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h
index 9610c8b3..1145f63a 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.h
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.h
@@ -83,6 +83,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
 
     [[nodiscard]] virtual GetModDependenciesTask::Ptr getModDependenciesTask() { return nullptr; }
 
+    QStringList getReqiredBy(QList<QVariant> req_by);
+
    protected:
     const std::shared_ptr<ResourceFolderModel> m_base_model;
 
diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp
index 86e68aae..e18519c3 100644
--- a/launcher/ui/dialogs/ReviewMessageBox.cpp
+++ b/launcher/ui/dialogs/ReviewMessageBox.cpp
@@ -60,6 +60,18 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info)
 
     itemTop->insertChildren(childIndx++, { providerItem });
 
+    if (!info.required_by.isEmpty()) {
+        auto requiredByItem = new QTreeWidgetItem(itemTop);
+        QString req;
+        if (info.required_by.length() == 1)
+            req = info.required_by.back();
+        else
+            req = QString("[%1]").arg(info.required_by.join(", "));
+        requiredByItem->setText(0, tr("Required by: %1").arg(req));
+
+        itemTop->insertChildren(childIndx++, { requiredByItem });
+    }
+
     ui->modTreeWidget->addTopLevelItem(itemTop);
 }
 
diff --git a/launcher/ui/dialogs/ReviewMessageBox.h b/launcher/ui/dialogs/ReviewMessageBox.h
index 9579da33..a520cc2a 100644
--- a/launcher/ui/dialogs/ReviewMessageBox.h
+++ b/launcher/ui/dialogs/ReviewMessageBox.h
@@ -17,6 +17,7 @@ class ReviewMessageBox : public QDialog {
         QString filename;
         QString custom_file_path{};
         QString provider;
+        QStringList required_by;
     };
 
     void appendResource(ResourceInformation&& info);
-- 
cgit 


From 107b4702895afdbaf9912006d91c910bb6634361 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 4 May 2023 23:54:46 +0300
Subject: Updated required_by as dependency

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp    | 12 +++---------
 launcher/minecraft/mod/tasks/GetModDependenciesTask.h |  2 +-
 launcher/modplatform/ModIndex.h                       |  1 -
 launcher/ui/dialogs/ResourceDownloadDialog.cpp        | 19 ++++++++++---------
 launcher/ui/dialogs/ReviewMessageBox.cpp              | 17 +++++++++++------
 5 files changed, 25 insertions(+), 26 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 2f08ae6d..96d343a1 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -65,7 +65,7 @@ void GetModDependenciesTask::prepare()
 {
     for (auto sel : m_selected) {
         for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) {
-            addTask(prepareDependencyTask(dep, sel->pack.provider, sel->pack.addonId, 20));
+            addTask(prepareDependencyTask(dep, sel->pack.provider, 20));
         }
     }
 }
@@ -95,8 +95,6 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
                                                     });
                             dep == m_pack_dependencies.end()) {  // check loaded dependencies
                             c_dependencies.append(ver_dep);
-                        } else {  // already there just append the required_by
-                            dep->get()->version.required_by.append(version.addonId);
                         }
                     }
                 }
@@ -108,13 +106,11 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
 
 Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep,
                                                         const ModPlatform::ResourceProvider providerName,
-                                                        QVariant required_by,
                                                         int level)
 {
     auto pDep = std::make_shared<PackDependency>();
     pDep->dependency = dep;
     pDep->pack = { dep.addonId, providerName };
-    pDep->version.required_by.append(required_by);
     m_pack_dependencies.append(pDep);
     auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
 
@@ -145,7 +141,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
     ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
     ResourceAPI::DependencySearchCallbacks callbacks;
 
-    callbacks.on_succeed = [dep, provider, pDep, level, required_by, this](auto& doc, auto& pack) {
+    callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) {
         try {
             QJsonArray arr;
             if (dep.version.length() != 0 && doc.isObject()) {
@@ -153,7 +149,6 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             } else {
                 arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
             }
-            auto required_by = pDep->version.required_by;
             pDep->version = provider.mod->loadDependencyVersions(dep, arr);
             if (!pDep->version.addonId.isValid()) {
                 qWarning() << "Error while reading mod version empty ";
@@ -161,7 +156,6 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
                 return;
             }
             pDep->version.is_currently_selected = true;
-            pDep->version.required_by = required_by;
             pDep->pack.versions = { pDep->version };
             pDep->pack.versionsLoaded = true;
 
@@ -175,7 +169,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             return;
         }
         for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) {
-            addTask(prepareDependencyTask(dep, provider.name, pDep->pack.addonId, level - 1));
+            addTask(prepareDependencyTask(dep, provider.name, level - 1));
         }
     };
 
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index c8d378ef..aca3c004 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -64,7 +64,7 @@ class GetModDependenciesTask : public SequentialTask {
     auto getDependecies() const -> QList<std::shared_ptr<PackDependency>> { return m_pack_dependencies; }
 
    protected slots:
-    Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, QVariant, int);
+    Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int);
     QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&,
                                                              const ModPlatform::ResourceProvider providerName);
     void prepare();
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index edf92416..a19fc0eb 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -78,7 +78,6 @@ struct IndexedVersion {
 
     // For internal use, not provided by APIs
     bool is_currently_selected = false;
-    QList<QVariant> required_by;
 };
 
 struct ExtraPackData {
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index c74aaace..b65f2ffd 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -125,16 +125,17 @@ void ResourceDownloadDialog::connectButtons()
 
 static ModPlatform::ProviderCapabilities ProviderCaps;
 
-QStringList getReqiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, QList<QVariant> req_by)
+QStringList getReqiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, QVariant addonId)
 {
     auto req = QStringList();
-    for (auto r : req_by) {
-        for (auto& task : tasks) {
-            auto selected = task->getPack();
-            if (selected.addonId == r) {
-                req.append(selected.name);
-                break;
-            }
+    for (auto& task : tasks) {
+        auto deps = task->getVersion().dependencies;
+        if (auto dep = std::find_if(deps.begin(), deps.end(),
+                                    [addonId](const ModPlatform::Dependency& d) {
+                                        return d.addonId == addonId && d.type == ModPlatform::DependencyType::REQUIRED;
+                                    });
+            dep) {
+            req.append(task->getName());
         }
     }
     return req;
@@ -178,7 +179,7 @@ void ResourceDownloadDialog::confirm()
     });
     for (auto& task : selected) {
         confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(),
-                                         ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getVersion().required_by) });
+                                         ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack().addonId) });
     }
 
     if (confirm_dialog->exec()) {
diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp
index e18519c3..7b33765f 100644
--- a/launcher/ui/dialogs/ReviewMessageBox.cpp
+++ b/launcher/ui/dialogs/ReviewMessageBox.cpp
@@ -62,12 +62,17 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info)
 
     if (!info.required_by.isEmpty()) {
         auto requiredByItem = new QTreeWidgetItem(itemTop);
-        QString req;
-        if (info.required_by.length() == 1)
-            req = info.required_by.back();
-        else
-            req = QString("[%1]").arg(info.required_by.join(", "));
-        requiredByItem->setText(0, tr("Required by: %1").arg(req));
+        if (info.required_by.length() == 1) {
+            requiredByItem->setText(0, tr("Required by: %1").arg(info.required_by.back()));
+        } else {
+            requiredByItem->setText(0, tr("Required by:"));
+            auto i = 0;
+            for (auto req : info.required_by) {
+                auto reqItem = new QTreeWidgetItem(requiredByItem);
+                reqItem->setText(0, req);
+                reqItem->insertChildren(i++, { reqItem });
+            }
+        }
 
         itemTop->insertChildren(childIndx++, { requiredByItem });
     }
-- 
cgit 


From 469ef3e06d93f9b00d7c23ac03f4eff07385e446 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 5 May 2023 00:04:24 +0300
Subject: Fixed code error

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index b65f2ffd..18106701 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -134,7 +134,7 @@ QStringList getReqiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, Q
                                     [addonId](const ModPlatform::Dependency& d) {
                                         return d.addonId == addonId && d.type == ModPlatform::DependencyType::REQUIRED;
                                     });
-            dep) {
+            dep != deps.end()) {
             req.append(task->getName());
         }
     }
-- 
cgit 


From ec157b766efd9eb781a8ca85fb9c28674e073da0 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Thu, 4 May 2023 23:42:42 -0700
Subject: feat(mod parsing): load extra mod details - (image, license,
 issuetracker)

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/Mod.cpp                     |  46 +++++
 launcher/minecraft/mod/Mod.h                       |  20 ++
 launcher/minecraft/mod/ModDetails.h                |  90 +++++++++
 launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 210 +++++++++++++++++++++
 launcher/minecraft/mod/tasks/LocalModParseTask.h   |   3 +
 5 files changed, 369 insertions(+)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index c495cd47..392f7f2e 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -41,9 +41,11 @@
 #include <QString>
 #include <QRegularExpression>
 
+#include "MTPixmapCache.h"
 #include "MetadataHandler.h"
 #include "Version.h"
 #include "minecraft/mod/ModDetails.h"
+#include "minecraft/mod/tasks/LocalModParseTask.h"
 
 static ModPlatform::ProviderCapabilities ProviderCaps;
 
@@ -201,6 +203,9 @@ void Mod::finishResolvingWithDetails(ModDetails&& details)
     m_local_details = std::move(details);
     if (metadata)
         setMetadata(std::move(metadata));
+    if (!iconPath().isEmpty()) {
+        m_pack_image_cache_key.was_read_attempt = false;
+    }
 };
 
 auto Mod::provider() const -> std::optional<QString>
@@ -210,6 +215,47 @@ auto Mod::provider() const -> std::optional<QString>
     return {};
 }
 
+
+void Mod::setIcon(QImage new_image) const
+{
+    QMutexLocker locker(&m_data_lock);
+
+    Q_ASSERT(!new_image.isNull());
+
+    if (m_pack_image_cache_key.key.isValid())
+        PixmapCache::remove(m_pack_image_cache_key.key);
+
+    // scale the image to avoid flooding the pixmapcache
+    auto pixmap = QPixmap::fromImage(new_image.scaled({128, 128}, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
+
+    m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
+    m_pack_image_cache_key.was_ever_used = true;
+    m_pack_image_cache_key.was_read_attempt = true;
+}
+
+QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const
+{
+    QPixmap cached_image;
+    if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
+        if (size.isNull())
+            return cached_image;
+        return cached_image.scaled(size, mode);
+    }
+
+    // No valid image we can get
+    if ((!m_pack_image_cache_key.was_ever_used && m_pack_image_cache_key.was_read_attempt) || iconPath().isEmpty())
+        return {};
+
+    if (m_pack_image_cache_key.was_ever_used) {
+        qDebug() << "Mod" << name() << "Had it's icon evicted form the cache. reloading...";
+        PixmapCache::markCacheMissByEviciton();
+    }
+    // Imaged got evicted from the cache or an attmept to load it has not been made. load it and retry.
+    m_pack_image_cache_key.was_read_attempt = true;
+    ModUtils::loadIconFile(*this);
+    return icon(size);
+}
+
 bool Mod::valid() const
 {
     return !m_local_details.mod_id.isEmpty();
diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h
index c4032538..4be0842f 100644
--- a/launcher/minecraft/mod/Mod.h
+++ b/launcher/minecraft/mod/Mod.h
@@ -38,6 +38,10 @@
 #include <QDateTime>
 #include <QFileInfo>
 #include <QList>
+#include <QImage>
+#include <QMutex>
+#include <QPixmap>
+#include <QPixmapCache>
 
 #include <optional>
 
@@ -65,6 +69,13 @@ public:
     auto status()      const -> ModStatus;
     auto provider()    const -> std::optional<QString>;
 
+    /** Get the intneral path to the mod's icon file*/
+    QString iconPath() const { return m_local_details.icon_file; };
+    /** Gets the icon of the mod, converted to a QPixmap for drawing, and scaled to size. */
+    [[nodiscard]] QPixmap icon(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const;
+    /** Thread-safe. */
+    void setIcon(QImage new_image) const;
+
     auto metadata() -> std::shared_ptr<Metadata::ModStruct>;
     auto metadata() const -> const std::shared_ptr<Metadata::ModStruct>;
 
@@ -85,4 +96,13 @@ public:
 
 protected:
     ModDetails m_local_details;
+
+    mutable QMutex m_data_lock;
+
+    struct {
+        QPixmapCache::Key key;
+        bool was_ever_used = false;
+        bool was_read_attempt = false;
+    } mutable m_pack_image_cache_key;
+    
 };
diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h
index 176e4fc1..eb3770d6 100644
--- a/launcher/minecraft/mod/ModDetails.h
+++ b/launcher/minecraft/mod/ModDetails.h
@@ -39,6 +39,7 @@
 
 #include <QString>
 #include <QStringList>
+#include <QUrl>
 
 #include "minecraft/mod/MetadataHandler.h"
 
@@ -49,6 +50,77 @@ enum class ModStatus {
     Unknown,        // Default status
 };
 
+struct ModLicense {
+    QString name = {};
+    QString id = {};
+    QString url = {};
+    QString description = {};
+
+    ModLicense() {}
+
+    ModLicense(const QString license) {
+        // FIXME: come up with a better license parseing. 
+        // handle SPDX identifiers? https://spdx.org/licenses/
+        auto parts = license.split(' ');
+        QStringList notNameParts  = {};
+        for (auto part : parts) {
+            auto url = QUrl::fromUserInput(part);
+            if (url.isValid()) {
+                this->url = url.toString();
+                notNameParts.append(part);
+                continue;
+            }
+        }
+
+        for (auto part : notNameParts) {
+            parts.removeOne(part);
+        }
+        
+        auto licensePart = parts.join(' ');
+        this->name = licensePart;
+        this->description = licensePart;
+
+        if (parts.size() == 1) {
+            this->id = parts.first();
+        }
+        
+    }
+
+    ModLicense(const QString name, const QString id, const QString url, const QString description) {
+        this->name = name;
+        this->id = id;
+        this->url = url;
+        this->description = description;
+    }
+
+    ModLicense(const ModLicense& other)
+        : name(other.name)
+        , id(other.id)
+        , url(other.url)
+        , description(other.description)
+    {}
+
+    ModLicense& operator=(const ModLicense& other)
+    {
+        this->name = other.name;
+        this->id = other.id;
+        this->url = other.url;
+        this->description = other.description;
+
+        return *this;
+    }
+
+    ModLicense& operator=(const ModLicense&& other)
+    {
+        this->name = other.name;
+        this->id = other.id;
+        this->url = other.url;
+        this->description = other.description;
+
+        return *this;
+    }
+};
+
 struct ModDetails
 {
     /* Mod ID as defined in the ModLoader-specific metadata */
@@ -72,6 +144,15 @@ struct ModDetails
     /* List of the author's names */
     QStringList authors = {};
 
+    /* Issue Tracker URL */
+    QString issue_tracker = {};
+
+    /* License */
+    QList<ModLicense> licenses = {};
+
+    /* Path of mod logo */
+    QString icon_file = {};
+
     /* Installation status of the mod */
     ModStatus status = ModStatus::Unknown;
 
@@ -89,6 +170,9 @@ struct ModDetails
         , homeurl(other.homeurl)
         , description(other.description)
         , authors(other.authors)
+        , issue_tracker(other.issue_tracker)
+        , licenses(other.licenses)
+        , icon_file(other.icon_file)
         , status(other.status)
     {}
 
@@ -101,6 +185,9 @@ struct ModDetails
         this->homeurl = other.homeurl;
         this->description = other.description;
         this->authors = other.authors;
+        this->issue_tracker = other.issue_tracker;
+        this->licenses = other.licenses;
+        this->icon_file = other.icon_file;
         this->status = other.status;
 
         return *this;
@@ -115,6 +202,9 @@ struct ModDetails
         this->homeurl = other.homeurl;
         this->description = other.description;
         this->authors = other.authors;
+        this->issue_tracker = other.issue_tracker;
+        this->licenses = other.licenses;
+        this->icon_file = other.icon_file;
         this->status = other.status;
 
         return *this;
diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
index 5342d693..084b0afb 100644
--- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
@@ -52,6 +52,10 @@ ModDetails ReadMCModInfo(QByteArray contents)
             authors = firstObj.value("authors").toArray();
         }
 
+        if (firstObj.contains("logoFile")) {
+            details.icon_file = firstObj.value("logoFile").toString();
+        }
+
         for (auto author : authors) {
             details.authors.append(author.toString());
         }
@@ -166,6 +170,30 @@ ModDetails ReadMCModTOML(QByteArray contents)
     }
     details.homeurl = homeurl;
 
+    QString issueTrackerURL = "";
+    if (auto issueTrackerURLDatum = tomlData["issueTrackerURL"].as_string()) {
+        issueTrackerURL = QString::fromStdString(issueTrackerURLDatum->get());
+    } else if (auto issueTrackerURLDatum = (*modsTable)["issueTrackerURL"].as_string()) {
+        issueTrackerURL = QString::fromStdString(issueTrackerURLDatum->get());
+    }
+    details.issue_tracker = issueTrackerURL;
+
+    QString license = "";
+    if (auto licenseDatum = tomlData["license"].as_string()) {
+        license = QString::fromStdString(licenseDatum->get());
+    } else if (auto licenseDatum =(*modsTable)["license"].as_string()) {
+        license = QString::fromStdString(licenseDatum->get());
+    }
+    details.licenses.push_back(ModLicense(license));
+
+    QString logoFile = "";
+    if (auto logoFileDatum = tomlData["logoFile"].as_string()) {
+        logoFile = QString::fromStdString(logoFileDatum->get());
+    } else if (auto logoFileDatum =(*modsTable)["logoFile"].as_string()) {
+        logoFile = QString::fromStdString(logoFileDatum->get());
+    }
+    details.icon_file = logoFile;
+
     return details;
 }
 
@@ -201,6 +229,57 @@ ModDetails ReadFabricModInfo(QByteArray contents)
             if (contact.contains("homepage")) {
                 details.homeurl = contact.value("homepage").toString();
             }
+            if (contact.contains("issues")) {
+                details.issue_tracker = contact.value("issues").toString();
+            }
+        }
+
+        if (object.contains("license")) {
+            auto license = object.value("license");
+            if (license.isArray()) {
+                for (auto l : license.toArray()) {
+                    if (l.isString()) {
+                        details.licenses.append(ModLicense(l.toString()));
+                    } else if (l.isObject()) {
+                        auto obj = l.toObject();
+                        details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(),
+                                                           obj.value("url").toString(), obj.value("description").toString()));
+                    }
+                }
+            } else if (license.isString()) {
+                details.licenses.append(ModLicense(license.toString()));
+            } else if (license.isObject()) {
+                auto obj = license.toObject();
+                details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(), obj.value("url").toString(),
+                                                   obj.value("description").toString()));
+            }
+        }
+
+        if (object.contains("icon")) {
+            auto icon = object.value("icon");
+            if (icon.isObject()) {
+                auto obj = icon.toObject();
+                // take the largest icon
+                int largest = 0;
+                for (auto key : obj.keys()) {
+                    auto size = key.split('x').first().toInt();
+                    if (size > largest) {
+                        largest = size;
+                    }
+                }
+                if (largest > 0) {
+                    auto key = QString::number(largest) + "x" + largest;
+                    details.icon_file = obj.value(key).toString();
+                } else { // parsing the sizes failed
+                    // take the first
+                    for (auto icon : obj) {
+                        details.icon_file = icon.toString();
+                        break;
+                    }
+                }
+            } else if (icon.isString()) {
+                details.icon_file = icon.toString();
+            }
         }
     }
     return details;
@@ -238,6 +317,58 @@ ModDetails ReadQuiltModInfo(QByteArray contents)
         if (modContact.contains("homepage")) {
             details.homeurl = Json::requireString(modContact.value("homepage"));
         }
+        if (modContact.contains("issues")) {
+            details.issue_tracker = Json::requireString(modContact.value("issues"));
+        }
+
+        if (modMetadata.contains("license")) {
+            auto license = modMetadata.value("license");
+            if (license.isArray()) {
+                for (auto l : license.toArray()) {
+                    if (l.isString()) {
+                        details.licenses.append(ModLicense(l.toString()));
+                    } else if (l.isObject()) {
+                        auto obj = l.toObject();
+                        details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(),
+                                                           obj.value("url").toString(), obj.value("description").toString()));
+                    }
+                }
+            } else if (license.isString()) {
+                details.licenses.append(ModLicense(license.toString()));
+            } else if (license.isObject()) {
+                auto obj = license.toObject();
+                details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(), obj.value("url").toString(),
+                                                   obj.value("description").toString()));
+            }
+        }
+
+        if (modMetadata.contains("icon")) {
+            auto icon = modMetadata.value("icon");
+            if (icon.isObject()) {
+                auto obj = icon.toObject();
+                // take the largest icon
+                int largest = 0;
+                for (auto key : obj.keys()) {
+                    auto size = key.split('x').first().toInt();
+                    if (size > largest) {
+                        largest = size;
+                    }
+                }
+                if (largest > 0) {
+                    auto key = QString::number(largest) + "x" + largest;
+                    details.icon_file = obj.value(key).toString();
+                } else { // parsing the sizes failed
+                    // take the first
+                    for (auto icon : obj) {
+                        details.icon_file = icon.toString();
+                        break;
+                    }
+                }
+            } else if (icon.isString()) {
+                details.icon_file = icon.toString();
+            }
+        }
+
     }
     return details;
 }
@@ -515,6 +646,85 @@ bool validate(QFileInfo file)
     return ModUtils::process(mod, ProcessingLevel::BasicInfoOnly) && mod.valid();
 }
 
+bool processIconPNG(const Mod& mod, QByteArray&& raw_data)
+{
+    auto img = QImage::fromData(raw_data);
+    if (!img.isNull()) {
+        mod.setIcon(img);
+    } else {
+        qWarning() << "Failed to parse mod logo:" << mod.iconPath() << "from" << mod.name();
+        return false;
+    }
+    return true;
+}
+
+bool loadIconFile(const Mod& mod) {
+    if (mod.iconPath().isEmpty()) {
+        qWarning() << "No Iconfile set, be sure to parse the mod first";
+        return false;
+    }
+
+    auto png_invalid = [&mod]() {
+        qWarning() << "Mod at" << mod.fileinfo().filePath() << "does not have a valid icon";
+        return false;
+    };
+
+    switch (mod.type()) {
+        case ResourceType::FOLDER:
+        {
+            QFileInfo icon_info(FS::PathCombine(mod.fileinfo().filePath(), mod.iconPath()));
+            if (icon_info.exists() && icon_info.isFile()) {
+                QFile icon(icon_info.filePath());
+                if (!icon.open(QIODevice::ReadOnly))
+                    return false;
+                auto data = icon.readAll();
+                
+                bool icon_result = ModUtils::processIconPNG(mod, std::move(data));
+
+                icon.close();
+
+                if (!icon_result) {
+                    return png_invalid();  // icon invalid
+                }
+            }
+        }
+        case ResourceType::ZIPFILE:
+        {
+            QuaZip zip(mod.fileinfo().filePath());
+            if (!zip.open(QuaZip::mdUnzip))
+                return false;
+
+            QuaZipFile file(&zip);
+
+            if (zip.setCurrentFile(mod.iconPath())) {
+                if (!file.open(QIODevice::ReadOnly)) {
+                    qCritical() << "Failed to open file in zip.";
+                    zip.close();
+                    return png_invalid();
+                }
+
+                auto data = file.readAll();
+
+                bool icon_result = ModUtils::processIconPNG(mod, std::move(data));
+
+                file.close();
+                if (!icon_result) {
+                    return png_invalid();  // icon png invalid
+                }
+            } else {
+                return png_invalid();  // could not set icon as current file.
+            }
+        }
+        case ResourceType::LITEMOD:
+        {
+            return false; // can lightmods even have icons?
+        }
+        default:
+            qWarning() << "Invalid type for mod, can not load icon.";
+            return false;
+    }
+}
+
 }  // namespace ModUtils
 
 LocalModParseTask::LocalModParseTask(int token, ResourceType type, const QFileInfo& modFile)
diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.h b/launcher/minecraft/mod/tasks/LocalModParseTask.h
index 38dae135..a0321709 100644
--- a/launcher/minecraft/mod/tasks/LocalModParseTask.h
+++ b/launcher/minecraft/mod/tasks/LocalModParseTask.h
@@ -25,6 +25,9 @@ bool processLitemod(Mod& mod, ProcessingLevel level = ProcessingLevel::Full);
 
 /** Checks whether a file is valid as a mod or not. */
 bool validate(QFileInfo file);
+
+bool processIconPNG(const Mod& mod, QByteArray&& raw_data);
+bool loadIconFile(const Mod& mod);
 }  // namespace ModUtils
 
 class LocalModParseTask : public Task {
-- 
cgit 


From 9913080a829acb4ca921c3a68e0caefad0ebcaa1 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Thu, 4 May 2023 23:44:28 -0700
Subject: feat(modpage): mod icon in description and column

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/ModFolderModel.cpp | 8 ++++++--
 launcher/minecraft/mod/ModFolderModel.h   | 1 +
 launcher/ui/widgets/InfoFrame.cpp         | 2 +-
 3 files changed, 8 insertions(+), 3 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 6ae25d33..8a58b9d7 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -57,7 +57,7 @@
 ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed, bool create_dir)
     : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed)
 {
-    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
+    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER, SortType::NAME };
 }
 
 QVariant ModFolderModel::data(const QModelIndex &index, int role) const
@@ -118,7 +118,9 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
     case Qt::DecorationRole: {
         if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
             return APPLICATION->getThemedIcon("status-yellow");
-
+        if (column == ImageColumn) {
+            return at(row)->icon(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+        }
         return {};
     }
     case Qt::CheckStateRole:
@@ -151,6 +153,8 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
             return tr("Last changed");
         case ProviderColumn:
             return tr("Provider");
+        case ImageColumn:
+            return tr("Image");
         default:
             return QVariant();
         }
diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h
index 46f5087f..20018e9c 100644
--- a/launcher/minecraft/mod/ModFolderModel.h
+++ b/launcher/minecraft/mod/ModFolderModel.h
@@ -68,6 +68,7 @@ public:
         VersionColumn,
         DateColumn,
         ProviderColumn,
+        ImageColumn,
         NUM_COLUMNS
     };
     enum ModStatusAction {
diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp
index fdc581b4..6f4036a2 100644
--- a/launcher/ui/widgets/InfoFrame.cpp
+++ b/launcher/ui/widgets/InfoFrame.cpp
@@ -88,7 +88,7 @@ void InfoFrame::updateWithMod(Mod const& m)
         setDescription(m.description());
     }
 
-    setImage();
+    setImage(m.icon({64,64}));
 }
 
 void InfoFrame::updateWithResource(const Resource& resource)
-- 
cgit 


From d384d991fad80cdadf6486d61e5c06a692a0031d Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Thu, 4 May 2023 23:45:24 -0700
Subject: feat(texturepackPage): icon column

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/TexturePack.cpp             |  25 +++--
 launcher/minecraft/mod/TexturePack.h               |   6 +-
 launcher/minecraft/mod/TexturePackFolderModel.cpp  | 102 ++++++++++++++++++++-
 launcher/minecraft/mod/TexturePackFolderModel.h    |  20 ++++
 .../mod/tasks/LocalTexturePackParseTask.cpp        |  67 +++++++++++++-
 .../mod/tasks/LocalTexturePackParseTask.h          |   5 +-
 6 files changed, 211 insertions(+), 14 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp
index 99d55584..8ff1e852 100644
--- a/launcher/minecraft/mod/TexturePack.cpp
+++ b/launcher/minecraft/mod/TexturePack.cpp
@@ -23,6 +23,8 @@
 #include <QMap>
 #include <QRegularExpression>
 
+#include "MTPixmapCache.h"
+
 #include "minecraft/mod/tasks/LocalTexturePackParseTask.h"
 
 void TexturePack::setDescription(QString new_description)
@@ -32,34 +34,41 @@ void TexturePack::setDescription(QString new_description)
     m_description = new_description;
 }
 
-void TexturePack::setImage(QImage new_image)
+void TexturePack::setImage(QImage new_image) const
 {
     QMutexLocker locker(&m_data_lock);
 
     Q_ASSERT(!new_image.isNull());
 
     if (m_pack_image_cache_key.key.isValid())
-        QPixmapCache::remove(m_pack_image_cache_key.key);
+        PixmapCache::remove(m_pack_image_cache_key.key);
+
+    // scale the image to avoid flooding the pixmapcache
+    auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding));
 
-    m_pack_image_cache_key.key = QPixmapCache::insert(QPixmap::fromImage(new_image));
+    m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
     m_pack_image_cache_key.was_ever_used = true;
 }
 
-QPixmap TexturePack::image(QSize size)
+QPixmap TexturePack::image(QSize size, Qt::AspectRatioMode mode) const
 {
     QPixmap cached_image;
-    if (QPixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
+    if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
         if (size.isNull())
             return cached_image;
-        return cached_image.scaled(size);
+        return cached_image.scaled(size, mode);
     }
 
     // No valid image we can get
-    if (!m_pack_image_cache_key.was_ever_used)
+    if (!m_pack_image_cache_key.was_ever_used) {
         return {};
+    } else {
+        qDebug() << "Texture Pack" << name() << "Had it's image evicted from the cache. reloading...";
+        PixmapCache::markCacheMissByEviciton();
+    }
 
     // Imaged got evicted from the cache. Re-process it and retry.
-    TexturePackUtils::process(*this);
+    TexturePackUtils::processPackPNG(*this);
     return image(size);
 }
 
diff --git a/launcher/minecraft/mod/TexturePack.h b/launcher/minecraft/mod/TexturePack.h
index 81bd5c69..57700565 100644
--- a/launcher/minecraft/mod/TexturePack.h
+++ b/launcher/minecraft/mod/TexturePack.h
@@ -40,13 +40,13 @@ class TexturePack : public Resource {
     [[nodiscard]] QString description() const { return m_description; }
 
     /** Gets the image of the texture pack, converted to a QPixmap for drawing, and scaled to size. */
-    [[nodiscard]] QPixmap image(QSize size);
+    [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const;
 
     /** Thread-safe. */
     void setDescription(QString new_description);
 
     /** Thread-safe. */
-    void setImage(QImage new_image);
+    void setImage(QImage new_image) const;
 
     bool valid() const override;
 
@@ -65,5 +65,5 @@ class TexturePack : public Resource {
     struct {
         QPixmapCache::Key key;
         bool was_ever_used = false;
-    } m_pack_image_cache_key;
+    } mutable m_pack_image_cache_key;
 };
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index 1e218537..dd93a469 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -33,6 +33,9 @@
  *      See the License for the specific language governing permissions and
  *      limitations under the License.
  */
+#include <QCoreApplication>
+
+#include "Application.h"
 
 #include "TexturePackFolderModel.h"
 
@@ -41,7 +44,9 @@
 
 TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
     : ResourceFolderModel(QDir(dir), instance)
-{}
+{
+    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::NAME };
+}
 
 Task* TexturePackFolderModel::createUpdateTask()
 {
@@ -52,3 +57,98 @@ Task* TexturePackFolderModel::createParseTask(Resource& resource)
 {
     return new LocalTexturePackParseTask(m_next_resolution_ticket, static_cast<TexturePack&>(resource));
 }
+
+
+QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
+{
+    if (!validateIndex(index))
+        return {};
+
+    int row = index.row();
+    int column = index.column();
+
+    switch (role) {
+        case Qt::DisplayRole:
+            switch (column) {
+                case NameColumn:
+                    return m_resources[row]->name();
+                case DateColumn:
+                    return m_resources[row]->dateTimeChanged();
+                default:
+                    return {};
+            }
+        case Qt::ToolTipRole:
+            if (column == NameColumn) {
+                if (at(row)->isSymLinkUnder(instDirPath())) {
+                    return m_resources[row]->internal_id() +
+                        tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original."
+                           "\nCanonical Path: %1")
+                            .arg(at(row)->fileinfo().canonicalFilePath());;
+                }
+                if (at(row)->isMoreThanOneHardLink()) {
+                    return m_resources[row]->internal_id() +
+                        tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original.");
+                }
+            }
+            
+            return m_resources[row]->internal_id();
+        case Qt::DecorationRole: {
+            if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
+                return APPLICATION->getThemedIcon("status-yellow");
+            if (column == ImageColumn) {
+                return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+            }
+            return {};
+        }
+        case Qt::CheckStateRole:
+            switch (column) {
+                case ActiveColumn:
+                    return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked;
+                default:
+                    return {};
+            }
+        default:
+            return {};
+    }
+}
+
+QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    switch (role) {
+        case Qt::DisplayRole:
+            switch (section) {
+                case NameColumn:
+                    return tr("Name");
+                case DateColumn:
+                    return tr("Last modified");
+                case ImageColumn:
+                    return tr("Image");
+                default:
+                    return {};
+            }
+        case Qt::ToolTipRole: {
+            switch (section) {
+                case ActiveColumn:
+                    //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc.
+                    return tr("Is the resource enabled?");
+                case NameColumn:
+                    //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc.
+                    return tr("The name of the resource.");
+                case DateColumn:
+                    //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc.
+                    return tr("The date and time this resource was last changed (or added).");
+                default:
+                    return {};
+            }
+        }
+        default:
+            break;
+    }
+
+    return {};
+}
+
+int TexturePackFolderModel::columnCount(const QModelIndex& parent) const
+{
+    return parent.isValid() ? 0 : NUM_COLUMNS;
+}
\ No newline at end of file
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h
index 246997bd..4467691a 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.h
+++ b/launcher/minecraft/mod/TexturePackFolderModel.h
@@ -38,12 +38,32 @@
 
 #include "ResourceFolderModel.h"
 
+#include "TexturePack.h"
+
 class TexturePackFolderModel : public ResourceFolderModel
 {
     Q_OBJECT
 
 public:
+
+    enum Columns
+    {
+        ActiveColumn = 0,
+        NameColumn,
+        DateColumn,
+        ImageColumn,
+        NUM_COLUMNS
+    };
+
     explicit TexturePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
+
+    [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+    [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+    [[nodiscard]] int columnCount(const QModelIndex &parent) const override;
+
     [[nodiscard]] Task* createUpdateTask() override;
     [[nodiscard]] Task* createParseTask(Resource&) override;
+
+    RESOURCE_HELPERS(TexturePack)
 };
diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
index 38f1d7c1..a72e8115 100644
--- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
@@ -131,6 +131,7 @@ bool processZIP(TexturePack& pack, ProcessingLevel level)
         bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data));
 
         file.close();
+        zip.close();
         if (!packPNG_result) {
             return false;
         }
@@ -147,7 +148,7 @@ bool processPackTXT(TexturePack& pack, QByteArray&& raw_data)
     return true;
 }
 
-bool processPackPNG(TexturePack& pack, QByteArray&& raw_data)
+bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data)
 {
     auto img = QImage::fromData(raw_data);
     if (!img.isNull()) {
@@ -159,6 +160,70 @@ bool processPackPNG(TexturePack& pack, QByteArray&& raw_data)
     return true;
 }
 
+bool processPackPNG(const TexturePack& pack)
+{   
+    auto png_invalid = [&pack]() {
+        qWarning() << "Texture pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png";
+        return false;
+    };
+
+    switch (pack.type()) {
+        case ResourceType::FOLDER: 
+        {
+            QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
+            if (image_file_info.exists() && image_file_info.isFile()) {
+                QFile pack_png_file(image_file_info.filePath());
+                if (!pack_png_file.open(QIODevice::ReadOnly))
+                    return png_invalid();  // can't open pack.png file
+
+                auto data = pack_png_file.readAll();
+
+                bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data));
+
+                pack_png_file.close();
+                if (!pack_png_result) {
+                    return png_invalid();  // pack.png invalid
+                }
+            } else {
+                return png_invalid();  // pack.png does not exists or is not a valid file.
+            }
+        }
+        case ResourceType::ZIPFILE:
+        {
+            Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
+
+            QuaZip zip(pack.fileinfo().filePath());
+            if (!zip.open(QuaZip::mdUnzip))
+                return false;  // can't open zip file
+
+            QuaZipFile file(&zip);
+            if (zip.setCurrentFile("pack.png")) {
+                if (!file.open(QIODevice::ReadOnly)) {
+                    qCritical() << "Failed to open file in zip.";
+                    zip.close();
+                    return png_invalid();
+                }
+
+                auto data = file.readAll();
+
+                bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data));
+
+                file.close();
+                if (!pack_png_result) {
+                    zip.close();
+                    return png_invalid();  // pack.png invalid
+                }
+            } else {
+                zip.close();
+                return png_invalid();  // could not set pack.mcmeta as current file.
+            }
+        }
+        default:
+            qWarning() << "Invalid type for resource pack parse task!";
+            return false;
+    }
+}
+
 bool validate(QFileInfo file)
 {
     TexturePack rp{ file };
diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
index 1589f8cb..6b91565a 100644
--- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
+++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
@@ -36,7 +36,10 @@ bool processZIP(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full
 bool processFolder(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
 
 bool processPackTXT(TexturePack& pack, QByteArray&& raw_data);
-bool processPackPNG(TexturePack& pack, QByteArray&& raw_data);
+bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data);
+
+/// processes ONLY the pack.png (rest of the pack may be invalid)
+bool processPackPNG(const TexturePack& pack);
 
 /** Checks whether a file is valid as a texture pack or not. */
 bool validate(QFileInfo file);
-- 
cgit 


From ed185f047fa2efc80cc622165583e57f21ffa560 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Thu, 4 May 2023 23:46:00 -0700
Subject: feat(resourcePackPage): icon column

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/ResourcePack.cpp            | 19 ++++--
 launcher/minecraft/mod/ResourcePack.h              |  6 +-
 launcher/minecraft/mod/ResourcePackFolderModel.cpp | 21 +++++--
 launcher/minecraft/mod/ResourcePackFolderModel.h   |  1 +
 .../mod/tasks/LocalResourcePackParseTask.cpp       | 67 +++++++++++++++++++++-
 .../mod/tasks/LocalResourcePackParseTask.h         |  5 +-
 6 files changed, 103 insertions(+), 16 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp
index 876d5c3e..5fc9d7a6 100644
--- a/launcher/minecraft/mod/ResourcePack.cpp
+++ b/launcher/minecraft/mod/ResourcePack.cpp
@@ -39,7 +39,7 @@ void ResourcePack::setDescription(QString new_description)
     m_description = new_description;
 }
 
-void ResourcePack::setImage(QImage new_image)
+void ResourcePack::setImage(QImage new_image) const
 {
     QMutexLocker locker(&m_data_lock);
 
@@ -48,7 +48,10 @@ void ResourcePack::setImage(QImage new_image)
     if (m_pack_image_cache_key.key.isValid())
         PixmapCache::instance().remove(m_pack_image_cache_key.key);
 
-    m_pack_image_cache_key.key = PixmapCache::instance().insert(QPixmap::fromImage(new_image));
+    // scale the image to avoid flooding the pixmapcache
+    auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding));
+
+    m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap);
     m_pack_image_cache_key.was_ever_used = true;
 
     // This can happen if the pixmap is too big to fit in the cache :c
@@ -58,21 +61,25 @@ void ResourcePack::setImage(QImage new_image)
     }
 }
 
-QPixmap ResourcePack::image(QSize size)
+QPixmap ResourcePack::image(QSize size, Qt::AspectRatioMode mode) const
 {
     QPixmap cached_image;
     if (PixmapCache::instance().find(m_pack_image_cache_key.key, &cached_image)) {
         if (size.isNull())
             return cached_image;
-        return cached_image.scaled(size);
+        return cached_image.scaled(size, mode);
     }
 
     // No valid image we can get
-    if (!m_pack_image_cache_key.was_ever_used)
+    if (!m_pack_image_cache_key.was_ever_used) {
         return {};
+    } else {
+        qDebug() << "Resource Pack" << name() << "Had it's image evicted from the cache. reloading...";
+        PixmapCache::markCacheMissByEviciton();
+    }
 
     // Imaged got evicted from the cache. Re-process it and retry.
-    ResourcePackUtils::process(*this);
+    ResourcePackUtils::processPackPNG(*this);
     return image(size);
 }
 
diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h
index 7cb414d8..da354bc1 100644
--- a/launcher/minecraft/mod/ResourcePack.h
+++ b/launcher/minecraft/mod/ResourcePack.h
@@ -31,7 +31,7 @@ class ResourcePack : public Resource {
     [[nodiscard]] QString description() const { return m_description; }
 
     /** Gets the image of the resource pack, converted to a QPixmap for drawing, and scaled to size. */
-    [[nodiscard]] QPixmap image(QSize size);
+    [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const;
 
     /** Thread-safe. */
     void setPackFormat(int new_format_id);
@@ -40,7 +40,7 @@ class ResourcePack : public Resource {
     void setDescription(QString new_description);
 
     /** Thread-safe. */
-    void setImage(QImage new_image);
+    void setImage(QImage new_image) const;
 
     bool valid() const override;
 
@@ -67,5 +67,5 @@ class ResourcePack : public Resource {
     struct {
         QPixmapCache::Key key;
         bool was_ever_used = false;
-    } m_pack_image_cache_key;
+    } mutable m_pack_image_cache_key;
 };
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index 6eba4e2e..c8c0c773 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -35,6 +35,8 @@
  */
 
 #include "ResourcePackFolderModel.h"
+#include <qnamespace.h>
+#include <qsize.h>
 
 #include <QIcon>
 #include <QStyle>
@@ -48,7 +50,7 @@
 ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
     : ResourceFolderModel(QDir(dir), instance)
 {
-    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE };
+    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE, SortType::NAME };
 }
 
 QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
@@ -84,9 +86,11 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
                     return {};
             }
         case Qt::DecorationRole: {
-            if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
+            if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
                 return APPLICATION->getThemedIcon("status-yellow");
-
+            if (column == ImageColumn) {
+                return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+            }
             return {};
         }
         case Qt::ToolTipRole: {
@@ -94,7 +98,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
                 //: The string being explained by this is in the format: ID (Lower version - Upper version)
                 return tr("The resource pack format ID, as well as the Minecraft versions it was designed for.");
             }
-            if (column == NAME_COLUMN) {
+            if (column == NameColumn) {
                 if (at(row)->isSymLinkUnder(instDirPath())) {
                     return m_resources[row]->internal_id() +
                         tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original."
@@ -133,6 +137,8 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
                     return tr("Pack Format");
                 case DateColumn:
                     return tr("Last changed");
+                case ImageColumn:
+                    return tr("Image");
                 default:
                     return {};
             }
@@ -151,6 +157,13 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
                 default:
                     return {};
             }
+        case Qt::SizeHintRole:
+            switch (section) {
+                case ImageColumn:
+                    return QSize(64,0);
+                default:
+                    return {};
+            }
         default:
             return {};
     }
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h
index 66d5a074..71532f30 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.h
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.h
@@ -14,6 +14,7 @@ public:
         NameColumn,
         PackFormatColumn,
         DateColumn,
+        ImageColumn,
         NUM_COLUMNS
     };
 
diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp
index 4bf0b80d..a67c56a8 100644
--- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp
@@ -165,15 +165,16 @@ bool processZIP(ResourcePack& pack, ProcessingLevel level)
         bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data));
 
         file.close();
+        zip.close();
         if (!pack_png_result) {
             return png_invalid();  // pack.png invalid
         }
     } else {
+        zip.close();
         return png_invalid();  // could not set pack.mcmeta as current file.
     }
 
     zip.close();
-
     return true;
 }
 
@@ -193,7 +194,7 @@ bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data)
     return true;
 }
 
-bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data)
+bool processPackPNG(const ResourcePack& pack, QByteArray&& raw_data)
 {
     auto img = QImage::fromData(raw_data);
     if (!img.isNull()) {
@@ -205,6 +206,68 @@ bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data)
     return true;
 }
 
+bool processPackPNG(const ResourcePack& pack)
+{   
+    auto png_invalid = [&pack]() {
+        qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png";
+        return false;
+    };
+
+    switch (pack.type()) {
+        case ResourceType::FOLDER: 
+        {
+            QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
+            if (image_file_info.exists() && image_file_info.isFile()) {
+                QFile pack_png_file(image_file_info.filePath());
+                if (!pack_png_file.open(QIODevice::ReadOnly))
+                    return png_invalid();  // can't open pack.png file
+
+                auto data = pack_png_file.readAll();
+
+                bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data));
+
+                pack_png_file.close();
+                if (!pack_png_result) {
+                    return png_invalid();  // pack.png invalid
+                }
+            } else {
+                return png_invalid();  // pack.png does not exists or is not a valid file.
+            }
+        }
+        case ResourceType::ZIPFILE:
+        {
+            Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
+
+            QuaZip zip(pack.fileinfo().filePath());
+            if (!zip.open(QuaZip::mdUnzip))
+                return false;  // can't open zip file
+
+            QuaZipFile file(&zip);
+            if (zip.setCurrentFile("pack.png")) {
+                if (!file.open(QIODevice::ReadOnly)) {
+                    qCritical() << "Failed to open file in zip.";
+                    zip.close();
+                    return png_invalid();
+                }
+
+                auto data = file.readAll();
+
+                bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data));
+
+                file.close();
+                if (!pack_png_result) {
+                    return png_invalid();  // pack.png invalid
+                }
+            } else {
+                return png_invalid();  // could not set pack.mcmeta as current file.
+            }
+        }
+        default:
+            qWarning() << "Invalid type for resource pack parse task!";
+            return false;
+    }
+}
+
 bool validate(QFileInfo file)
 {
     ResourcePack rp{ file };
diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h
index d0c24c2b..58d90b3b 100644
--- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h
+++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h
@@ -35,7 +35,10 @@ bool processZIP(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Ful
 bool processFolder(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
 
 bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data);
-bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data);
+bool processPackPNG(const ResourcePack& pack, QByteArray&& raw_data);
+
+/// processes ONLY the pack.png (rest of the pack may be invalid)
+bool processPackPNG(const ResourcePack& pack);
 
 /** Checks whether a file is valid as a resource pack or not. */
 bool validate(QFileInfo file);
-- 
cgit 


From fd7338d3f3f72ca9532f11c9759ad02bbc759c7c Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Thu, 4 May 2023 23:47:27 -0700
Subject: fix: grow pixmapcache if it is evicting too fast

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/MTPixmapCache.h | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

(limited to 'launcher')

diff --git a/launcher/MTPixmapCache.h b/launcher/MTPixmapCache.h
index 57847a0e..271788c0 100644
--- a/launcher/MTPixmapCache.h
+++ b/launcher/MTPixmapCache.h
@@ -3,6 +3,8 @@
 #include <QCoreApplication>
 #include <QPixmapCache>
 #include <QThread>
+#include <QTime>
+#include <QDebug>
 
 #define GET_TYPE()                                                          \
     Qt::ConnectionType type;                                                \
@@ -60,6 +62,8 @@ class PixmapCache final : public QObject {
     DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&)
     DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&)
     DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int)
+    DEFINE_FUNC_NO_PARAM(markCacheMissByEviciton, bool)
+    DEFINE_FUNC_ONE_PARAM(setFastEvictionThreshold, bool, int)
 
     // NOTE: Every function returns something non-void to simplify the macros.
    private slots:
@@ -90,6 +94,43 @@ class PixmapCache final : public QObject {
         return true;
     }
 
+    /** 
+     *  Mark that a cach miss occured because of a eviciton if too man of these occure to fast the cache size is increased 
+     * @return if the cache size was increased
+     */
+    bool _markCacheMissByEviciton()
+    {
+        auto now = QTime::currentTime();
+        if (!m_last_cache_miss_by_eviciton.isNull()) {
+            auto diff = m_last_cache_miss_by_eviciton.msecsTo(now);
+            if (diff < 1000) {  // less than a second ago
+                ++m_consecutive_fast_evicitons;
+            } else {
+                m_consecutive_fast_evicitons = 0;
+            }
+        }
+        m_last_cache_miss_by_eviciton = now;
+        if (m_consecutive_fast_evicitons >= m_consecutive_fast_evicitons_threshold) {
+            // double the cache size
+            auto newSize = _cacheLimit() * 2;
+            qDebug() << m_consecutive_fast_evicitons << "pixmap cache misses by eviction happened too fast, doubling cache size to"
+                     << newSize;
+            _setCacheLimit(newSize);
+            m_consecutive_fast_evicitons = 0;
+            return true;
+        }
+        return false;
+    }
+
+    bool _setFastEvictionThreshold(int threshold)
+    {
+        m_consecutive_fast_evicitons_threshold = threshold;
+        return true;
+    }
+
    private:
     static PixmapCache* s_instance;
+    QTime m_last_cache_miss_by_eviciton;
+    int m_consecutive_fast_evicitons = 0;
+    int m_consecutive_fast_evicitons_threshold = 15;
 };
-- 
cgit 


From 2fe3dc5960a6cc231891a91dd68fcc8b159e9365 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Fri, 5 May 2023 11:13:36 -0700
Subject: fix: fix qchar conversion and codeql

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/MTPixmapCache.h                           |  2 +-
 launcher/minecraft/mod/Mod.cpp                     |  4 ++--
 launcher/minecraft/mod/ResourcePackFolderModel.cpp |  8 +++-----
 launcher/minecraft/mod/TexturePackFolderModel.cpp  |  8 +++-----
 launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 12 ++++++------
 5 files changed, 15 insertions(+), 19 deletions(-)

(limited to 'launcher')

diff --git a/launcher/MTPixmapCache.h b/launcher/MTPixmapCache.h
index 271788c0..65cbe032 100644
--- a/launcher/MTPixmapCache.h
+++ b/launcher/MTPixmapCache.h
@@ -95,7 +95,7 @@ class PixmapCache final : public QObject {
     }
 
     /** 
-     *  Mark that a cach miss occured because of a eviciton if too man of these occure to fast the cache size is increased 
+     *  Mark that a cache miss occurred because of a eviction if too many of these occur too fast the cache size is increased 
      * @return if the cache size was increased
      */
     bool _markCacheMissByEviciton()
diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index 392f7f2e..aabc2db4 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -206,7 +206,7 @@ void Mod::finishResolvingWithDetails(ModDetails&& details)
     if (!iconPath().isEmpty()) {
         m_pack_image_cache_key.was_read_attempt = false;
     }
-};
+}
 
 auto Mod::provider() const -> std::optional<QString>
 {
@@ -250,7 +250,7 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const
         qDebug() << "Mod" << name() << "Had it's icon evicted form the cache. reloading...";
         PixmapCache::markCacheMissByEviciton();
     }
-    // Imaged got evicted from the cache or an attmept to load it has not been made. load it and retry.
+    // Image got evicted from the cache or an attempt to load it has not been made. load it and retry.
     m_pack_image_cache_key.was_read_attempt = true;
     ModUtils::loadIconFile(*this);
     return icon(size);
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index c8c0c773..349353a5 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -158,12 +158,10 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
                     return {};
             }
         case Qt::SizeHintRole:
-            switch (section) {
-                case ImageColumn:
-                    return QSize(64,0);
-                default:
-                    return {};
+            if (section == ImageColumn) {
+                return QSize(64,0);
             }
+            return {};
         default:
             return {};
     }
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index dd93a469..f053eab1 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -101,12 +101,10 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
             return {};
         }
         case Qt::CheckStateRole:
-            switch (column) {
-                case ActiveColumn:
-                    return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked;
-                default:
-                    return {};
+            if (column == ActiveColumn) {
+                    return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked;   
             }
+            return {};
         default:
             return {};
     }
diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
index 084b0afb..f045bde3 100644
--- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
@@ -268,12 +268,12 @@ ModDetails ReadFabricModInfo(QByteArray contents)
                     }
                 }
                 if (largest > 0) {
-                    auto key = QString::number(largest) + "x" + largest;
+                    auto key = QString::number(largest) + "x" + QString::number(largest);
                     details.icon_file = obj.value(key).toString();
                 } else { // parsing the sizes failed
                     // take the first
-                    for (auto icon : obj) {
-                        details.icon_file = icon.toString();
+                    for (auto i : obj) {
+                        details.icon_file = i.toString();
                         break;
                     }
                 }
@@ -355,12 +355,12 @@ ModDetails ReadQuiltModInfo(QByteArray contents)
                     }
                 }
                 if (largest > 0) {
-                    auto key = QString::number(largest) + "x" + largest;
+                    auto key = QString::number(largest) + "x" + QString::number(largest);
                     details.icon_file = obj.value(key).toString();
                 } else { // parsing the sizes failed
                     // take the first
-                    for (auto icon : obj) {
-                        details.icon_file = icon.toString();
+                    for (auto i : obj) {
+                        details.icon_file = i.toString();
                         break;
                     }
                 }
-- 
cgit 


From ee94be624eb11a12d4eb3e07c32ea4734b3ba6dc Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Fri, 5 May 2023 11:28:19 -0700
Subject: use 32x32 images for image column

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/Mod.cpp                     | 2 +-
 launcher/minecraft/mod/ModFolderModel.cpp          | 2 +-
 launcher/minecraft/mod/ResourcePack.cpp            | 2 +-
 launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +-
 launcher/minecraft/mod/TexturePack.cpp             | 2 +-
 launcher/minecraft/mod/TexturePackFolderModel.cpp  | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index aabc2db4..f236d2ac 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -226,7 +226,7 @@ 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({128, 128}, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
+    auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
 
     m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
     m_pack_image_cache_key.was_ever_used = true;
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 8a58b9d7..f1c26e68 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -119,7 +119,7 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
         if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
             return APPLICATION->getThemedIcon("status-yellow");
         if (column == ImageColumn) {
-            return at(row)->icon(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+            return at(row)->icon({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding);
         }
         return {};
     }
diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp
index 5fc9d7a6..9aea22ef 100644
--- a/launcher/minecraft/mod/ResourcePack.cpp
+++ b/launcher/minecraft/mod/ResourcePack.cpp
@@ -49,7 +49,7 @@ 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(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding));
+    auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
 
     m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap);
     m_pack_image_cache_key.was_ever_used = true;
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index 349353a5..b11e2262 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -89,7 +89,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
             if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
                 return APPLICATION->getThemedIcon("status-yellow");
             if (column == ImageColumn) {
-                return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+                return at(row)->image({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding);
             }
             return {};
         }
diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp
index 8ff1e852..c7a50a97 100644
--- a/launcher/minecraft/mod/TexturePack.cpp
+++ b/launcher/minecraft/mod/TexturePack.cpp
@@ -44,7 +44,7 @@ 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(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding));
+    auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding));
 
     m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
     m_pack_image_cache_key.was_ever_used = true;
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index f053eab1..e115cce6 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -96,7 +96,7 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
             if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
                 return APPLICATION->getThemedIcon("status-yellow");
             if (column == ImageColumn) {
-                return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+                return at(row)->image({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding);
             }
             return {};
         }
-- 
cgit 


From 3cfcc83ea99e8f42dba8848b5ef885c296b4566a Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Fri, 5 May 2023 13:46:01 -0700
Subject: change: don't toggle a resource's enabeling just by selecting it.
 only if they are on the checkbox.

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/ui/pages/instance/ExternalResourcesPage.cpp | 1 -
 1 file changed, 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
index 1115ddc3..6c11b85b 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
@@ -96,7 +96,6 @@ void ExternalResourcesPage::itemActivated(const QModelIndex&)
         return;
 
     auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
-    m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE);
 }
 
 void ExternalResourcesPage::filterTextChanged(const QString& newContents)
-- 
cgit 


From 74e7c13a177afdb503a642cb9c97d71e72249291 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Fri, 5 May 2023 13:46:38 -0700
Subject: feat: display license and issue tracker

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/Mod.cpp                     |   9 ++
 launcher/minecraft/mod/Mod.h                       |   2 +
 launcher/minecraft/mod/ModDetails.h                |  11 +-
 launcher/minecraft/mod/ModFolderModel.cpp          |   1 -
 launcher/minecraft/mod/tasks/LocalModParseTask.cpp |   3 +-
 launcher/ui/widgets/InfoFrame.cpp                  | 120 ++++++++++++++++++++-
 launcher/ui/widgets/InfoFrame.h                    |   4 +
 launcher/ui/widgets/InfoFrame.ui                   |  92 +++++++++++-----
 8 files changed, 209 insertions(+), 33 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index f236d2ac..e613ddeb 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -215,6 +215,15 @@ auto Mod::provider() const -> std::optional<QString>
     return {};
 }
 
+auto Mod::licenses() const -> const QList<ModLicense>&
+{
+    return details().licenses;
+}
+
+ auto Mod::issueTracker() const -> QString
+{
+    return details().issue_tracker;
+}
 
 void Mod::setIcon(QImage new_image) const
 {
diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h
index 4be0842f..d4e419f4 100644
--- a/launcher/minecraft/mod/Mod.h
+++ b/launcher/minecraft/mod/Mod.h
@@ -68,6 +68,8 @@ public:
     auto authors()     const -> QStringList;
     auto status()      const -> ModStatus;
     auto provider()    const -> std::optional<QString>;
+    auto licenses()     const -> const QList<ModLicense>&;
+    auto issueTracker() const -> QString;
 
     /** Get the intneral path to the mod's icon file*/
     QString iconPath() const { return m_local_details.icon_file; };
diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h
index eb3770d6..b4e59d52 100644
--- a/launcher/minecraft/mod/ModDetails.h
+++ b/launcher/minecraft/mod/ModDetails.h
@@ -64,8 +64,11 @@ struct ModLicense {
         auto parts = license.split(' ');
         QStringList notNameParts  = {};
         for (auto part : parts) {
-            auto url = QUrl::fromUserInput(part);
-            if (url.isValid()) {
+            auto url = QUrl(part);
+            if (part.startsWith("(") && part.endsWith(")"))
+                url = QUrl(part.mid(1, part.size() - 2));
+
+            if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
                 this->url = url.toString();
                 notNameParts.append(part);
                 continue;
@@ -119,6 +122,10 @@ struct ModLicense {
 
         return *this;
     }
+
+    bool isEmpty() {
+        return this->name.isEmpty() && this->id.isEmpty() && this->url.isEmpty() && this->description.isEmpty();
+    }
 };
 
 struct ModDetails
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index f1c26e68..8843f79f 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -52,7 +52,6 @@
 
 #include "minecraft/mod/tasks/LocalModParseTask.h"
 #include "minecraft/mod/tasks/ModFolderLoadTask.h"
-#include "modplatform/ModIndex.h"
 
 ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed, bool create_dir)
     : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed)
diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
index f045bde3..264019f8 100644
--- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
@@ -184,7 +184,8 @@ ModDetails ReadMCModTOML(QByteArray contents)
     } else if (auto licenseDatum =(*modsTable)["license"].as_string()) {
         license = QString::fromStdString(licenseDatum->get());
     }
-    details.licenses.push_back(ModLicense(license));
+    if (!license.isEmpty())
+        details.licenses.append(ModLicense(license));
 
     QString logoFile = "";
     if (auto logoFileDatum = tomlData["logoFile"].as_string()) {
diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp
index 6f4036a2..9c041bfe 100644
--- a/launcher/ui/widgets/InfoFrame.cpp
+++ b/launcher/ui/widgets/InfoFrame.cpp
@@ -47,6 +47,8 @@ InfoFrame::InfoFrame(QWidget *parent) :
     ui->setupUi(this);
     ui->descriptionLabel->setHidden(true);
     ui->nameLabel->setHidden(true);
+    ui->licenseLabel->setHidden(true);
+    ui->issueTrackerLabel->setHidden(true);
     updateHiddenState();
 }
 
@@ -89,6 +91,40 @@ void InfoFrame::updateWithMod(Mod const& m)
     }
 
     setImage(m.icon({64,64}));
+
+    auto licenses = m.licenses();
+    QString licenseText = "";
+    if (!licenses.empty()) {
+        for (auto l : licenses) {
+            if (!licenseText.isEmpty()) {
+                licenseText += "\n"; // add newline between licenses
+            }
+            if (!l.name.isEmpty()) {
+                if (l.url.isEmpty()) {
+                    licenseText += l.name;
+                } else {
+                    licenseText += "<a href=\"" + l.url + "\">" + l.name + "</a>";
+                }
+            } else if (!l.url.isEmpty()) {
+                licenseText += "<a href=\"" + l.url + "\">" + l.url + "</a>";
+            }
+            if (!l.description.isEmpty() && l.description != l.name) {
+               licenseText += " " + l.description;
+            }
+        } 
+    }
+    if (!licenseText.isEmpty()) {
+        setLicense(tr("License: %1").arg(licenseText));
+    } else {
+        setLicense();
+    }
+
+    QString issueTracker = "";
+    if (!m.issueTracker().isEmpty()) {
+        issueTracker += tr("Report issues to: ");
+        issueTracker += "<a href=\"" + m.issueTracker() + "\">" + m.issueTracker() + "</a>";
+    } 
+    setIssueTracker(issueTracker);
 }
 
 void InfoFrame::updateWithResource(const Resource& resource)
@@ -177,16 +213,16 @@ void InfoFrame::clear()
     setName();
     setDescription();
     setImage();
+    setLicense();
+    setIssueTracker();
 }
 
 void InfoFrame::updateHiddenState()
 {
-    if(ui->descriptionLabel->isHidden() && ui->nameLabel->isHidden())
-    {
+    if (ui->descriptionLabel->isHidden() && ui->nameLabel->isHidden() && ui->licenseLabel->isHidden() &&
+        ui->issueTrackerLabel->isHidden()) {
         setHidden(true);
-    }
-    else
-    {
+    } else {
         setHidden(false);
     }
 }
@@ -251,6 +287,66 @@ void InfoFrame::setDescription(QString text)
     ui->descriptionLabel->setText(labeltext);
 }
 
+void InfoFrame::setLicense(QString text)
+{
+    if(text.isEmpty())
+    {
+        ui->licenseLabel->setHidden(true);
+        updateHiddenState();
+        return;
+    }
+    else
+    {
+        ui->licenseLabel->setHidden(false);
+        updateHiddenState();
+    }
+    ui->licenseLabel->setToolTip("");
+    QString intermediatetext = text.trimmed();
+    bool prev(false);
+    QChar rem('\n');
+    QString finaltext;
+    finaltext.reserve(intermediatetext.size());
+    foreach(const QChar& c, intermediatetext)
+    {
+        if(c == rem && prev){
+            continue;
+        }
+        prev = c == rem;
+        finaltext += c;
+    }
+    QString labeltext;
+    labeltext.reserve(300);
+    if(finaltext.length() > 290)
+    {
+        ui->licenseLabel->setOpenExternalLinks(false);
+        ui->licenseLabel->setTextFormat(Qt::TextFormat::RichText);
+        m_description = text;
+        // This allows injecting HTML here.
+        labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>");
+        QObject::connect(ui->licenseLabel, &QLabel::linkActivated, this, &InfoFrame::licenseEllipsisHandler);
+    }
+    else
+    {
+        ui->licenseLabel->setTextFormat(Qt::TextFormat::AutoText);
+        labeltext.append(finaltext);
+    }
+    ui->licenseLabel->setText(labeltext);
+}
+
+void InfoFrame::setIssueTracker(QString text)
+{
+    if(text.isEmpty())
+    {
+        ui->issueTrackerLabel->setHidden(true);
+    }
+    else
+    {
+        ui->issueTrackerLabel->setText(text);
+        ui->issueTrackerLabel->setHidden(false);
+    }
+    updateHiddenState();
+}
+
 void InfoFrame::setImage(QPixmap img)
 {
     if (img.isNull()) {
@@ -275,6 +371,20 @@ void InfoFrame::descriptionEllipsisHandler(QString link)
     }
 }
 
+void InfoFrame::licenseEllipsisHandler(QString link)
+{
+    if(!m_current_box)
+    {
+        m_current_box = CustomMessageBox::selectable(this, "", m_license);
+        connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed);
+        m_current_box->show();
+    }
+    else
+    {
+        m_current_box->setText(m_license);
+    }
+}
+
 void InfoFrame::boxClosed(int result)
 {
     m_current_box = nullptr;
diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h
index 84523e28..7eb679a9 100644
--- a/launcher/ui/widgets/InfoFrame.h
+++ b/launcher/ui/widgets/InfoFrame.h
@@ -36,6 +36,8 @@ class InfoFrame : public QFrame {
     void setName(QString text = {});
     void setDescription(QString text = {});
     void setImage(QPixmap img = {});
+    void setLicense(QString text = {});
+    void setIssueTracker(QString text = {});
 
     void clear();
 
@@ -48,6 +50,7 @@ class InfoFrame : public QFrame {
 
    public slots:
     void descriptionEllipsisHandler(QString link);
+    void licenseEllipsisHandler(QString link);
     void boxClosed(int result);
 
    private:
@@ -56,5 +59,6 @@ class InfoFrame : public QFrame {
    private:
     Ui::InfoFrame* ui;
     QString m_description;
+    QString m_license;
     class QMessageBox* m_current_box = nullptr;
 };
diff --git a/launcher/ui/widgets/InfoFrame.ui b/launcher/ui/widgets/InfoFrame.ui
index 9e407ce9..c4d8c83d 100644
--- a/launcher/ui/widgets/InfoFrame.ui
+++ b/launcher/ui/widgets/InfoFrame.ui
@@ -35,8 +35,36 @@
    <property name="bottomMargin">
     <number>0</number>
    </property>
-   <item row="0" column="1">
-    <widget class="QLabel" name="nameLabel">
+   <item row="0" column="0" rowspan="2">
+    <widget class="QLabel" name="iconLabel">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>64</width>
+       <height>64</height>
+      </size>
+     </property>
+     <property name="text">
+      <string notr="true"/>
+     </property>
+     <property name="scaledContents">
+      <bool>false</bool>
+     </property>
+     <property name="margin">
+      <number>0</number>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLabel" name="descriptionLabel">
+     <property name="toolTip">
+      <string notr="true"/>
+     </property>
      <property name="text">
       <string notr="true"/>
      </property>
@@ -57,11 +85,8 @@
      </property>
     </widget>
    </item>
-   <item row="1" column="1">
-    <widget class="QLabel" name="descriptionLabel">
-     <property name="toolTip">
-      <string notr="true"/>
-     </property>
+   <item row="0" column="1">
+    <widget class="QLabel" name="nameLabel">
      <property name="text">
       <string notr="true"/>
      </property>
@@ -82,28 +107,47 @@
      </property>
     </widget>
    </item>
-   <item row="0" column="0" rowspan="2">
-    <widget class="QLabel" name="iconLabel">
-     <property name="minimumSize">
-      <size>
-       <width>0</width>
-       <height>0</height>
-      </size>
+   <item row="2" column="1">
+    <widget class="QLabel" name="licenseLabel">
+     <property name="text">
+      <string/>
      </property>
-     <property name="maximumSize">
-      <size>
-       <width>64</width>
-       <height>64</height>
-      </size>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
      </property>
+     <property name="alignment">
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+     <property name="openExternalLinks">
+      <bool>true</bool>
+     </property>
+     <property name="textInteractionFlags">
+      <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLabel" name="issueTrackerLabel">
      <property name="text">
-      <string notr="true"/>
+      <string/>
      </property>
-     <property name="scaledContents">
-      <bool>false</bool>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
      </property>
-     <property name="margin">
-      <number>0</number>
+     <property name="alignment">
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+     <property name="openExternalLinks">
+      <bool>true</bool>
+     </property>
+     <property name="textInteractionFlags">
+      <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
      </property>
     </widget>
    </item>
-- 
cgit 


From 94cd831e8d15349e6e3428574cdada1b734f2e61 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 14 May 2023 22:13:53 +0300
Subject: Made sure the metadata is valid when checking mod deps

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 96d343a1..948837d4 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -57,7 +57,8 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
     , m_loaderType(mcLoaders(instance))
 {
     for (auto mod : folder->allMods())
-        m_mods.append(mod->metadata());
+        if (auto meta = mod->metadata(); meta)
+            m_mods.append(meta);
     prepare();
 };
 
-- 
cgit 


From 086a7e19f099c6c9b9529afb2360300e534876bf Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Wed, 24 May 2023 20:15:34 -0700
Subject: feat: Column on left, hideable

- columns are hideable (saves to settings)
- image column moved to left
- datamodals can provide resize modes

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/ModFolderModel.cpp          |  6 +-
 launcher/minecraft/mod/ModFolderModel.h            |  4 +-
 launcher/minecraft/mod/ResourceFolderModel.cpp     | 66 ++++++++++++++++++++++
 launcher/minecraft/mod/ResourceFolderModel.h       | 12 ++++
 launcher/minecraft/mod/ResourcePackFolderModel.cpp |  6 +-
 launcher/minecraft/mod/ResourcePackFolderModel.h   |  4 +-
 launcher/minecraft/mod/ShaderPackFolderModel.h     |  2 +
 launcher/minecraft/mod/TexturePackFolderModel.cpp  |  9 ++-
 launcher/minecraft/mod/TexturePackFolderModel.h    |  4 +-
 .../ui/pages/instance/ExternalResourcesPage.cpp    | 15 +++++
 launcher/ui/pages/instance/ExternalResourcesPage.h |  1 +
 launcher/ui/widgets/ModListView.cpp                |  9 +++
 launcher/ui/widgets/ModListView.h                  |  2 +
 13 files changed, 131 insertions(+), 9 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 8843f79f..59e078f1 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -37,6 +37,7 @@
 #include "ModFolderModel.h"
 
 #include <FileSystem.h>
+#include <qheaderview.h>
 #include <QDebug>
 #include <QFileSystemWatcher>
 #include <QIcon>
@@ -56,7 +57,8 @@
 ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed, bool create_dir)
     : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed)
 {
-    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER, SortType::NAME };
+    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
 }
 
 QVariant ModFolderModel::data(const QModelIndex &index, int role) const
@@ -143,7 +145,7 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
         switch (section)
         {
         case ActiveColumn:
-            return QString();
+            return tr("Enable");
         case NameColumn:
             return tr("Name");
         case VersionColumn:
diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h
index 20018e9c..c1f9a2b6 100644
--- a/launcher/minecraft/mod/ModFolderModel.h
+++ b/launcher/minecraft/mod/ModFolderModel.h
@@ -64,11 +64,11 @@ public:
     enum Columns
     {
         ActiveColumn = 0,
+        ImageColumn,
         NameColumn,
         VersionColumn,
         DateColumn,
         ProviderColumn,
-        ImageColumn,
         NUM_COLUMNS
     };
     enum ModStatusAction {
@@ -78,6 +78,8 @@ public:
     };
     ModFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed = false, bool create_dir = true);
 
+    virtual QString id() const override { return "mods"; }
+
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp
index e1973468..ba64497b 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourceFolderModel.cpp
@@ -8,12 +8,15 @@
 #include <QStyle>
 #include <QThreadPool>
 #include <QUrl>
+#include <QMenu>
 
 #include "Application.h"
 #include "FileSystem.h"
 
+#include "QVariantUtils.h"
 #include "minecraft/mod/tasks/BasicFolderLoadTask.h"
 
+#include "settings/Setting.h"
 #include "tasks/Task.h"
 
 ResourceFolderModel::ResourceFolderModel(QDir dir, std::shared_ptr<const BaseInstance> instance, QObject* parent, bool create_dir)
@@ -471,6 +474,8 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio
     switch (role) {
         case Qt::DisplayRole:
             switch (section) {
+                case ACTIVE_COLUMN:
+                    return tr("Enable");
                 case NAME_COLUMN:
                     return tr("Name");
                 case DATE_COLUMN:
@@ -500,6 +505,67 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio
     return {};
 }
 
+void ResourceFolderModel::setupHeaderAction(QAction* act, int column)
+{
+    Q_ASSERT(act);
+
+    act->setText(headerData(column, Qt::Orientation::Horizontal).toString());
+}
+
+void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
+{
+    auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
+    auto setting = (APPLICATION->settings()->contains(setting_name)) ?
+        APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
+
+    auto hiddenColumns = QVariantUtils::toList<int>(setting->get());
+    auto index = hiddenColumns.indexOf(column);
+    if (index >= 0 && !hidden) {
+        hiddenColumns.removeAt(index);
+    } else if ( index < 0 && hidden) {
+        hiddenColumns.append(column);
+    }
+    setting->set(QVariantUtils::fromList(hiddenColumns));
+}
+
+void ResourceFolderModel::loadHiddenColumns(QTreeView *tree)
+{
+    auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
+    auto setting = (APPLICATION->settings()->contains(setting_name)) ?
+        APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
+
+    auto hiddenColumns = QVariantUtils::toList<int>(setting->get().toList());
+    for (auto col : hiddenColumns) {
+        tree->setColumnHidden(col, true);
+    }
+
+}
+
+std::unique_ptr<QMenu> ResourceFolderModel::createHeaderContextMenu(QWidget* parent, QTreeView* tree)
+{
+    auto menu = std::make_unique<QMenu>(parent);
+
+    menu->addSeparator()->setText(tr("Show / Hide Columns"));
+
+    for (int col = 0; col < columnCount(); ++col) {
+        auto act = new QAction();
+        setupHeaderAction(act, col);
+
+        act->setCheckable(true);
+        act->setChecked(!tree->isColumnHidden(col));
+
+        connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled){
+            tree->setColumnHidden(col, !toggled);
+            saveHiddenColumn(col, !toggled);
+        });
+
+        menu->addAction(act);
+
+    }
+
+    return menu;
+}
+
 QSortFilterProxyModel* ResourceFolderModel::createFilterProxyModel(QObject* parent)
 {
     return new ProxyModel(parent);
diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h
index fdf5f331..54627c80 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.h
+++ b/launcher/minecraft/mod/ResourceFolderModel.h
@@ -1,5 +1,8 @@
 #pragma once
 
+#include <QHeaderView>
+#include <QAction>
+#include <QTreeView>
 #include <QAbstractListModel>
 #include <QDir>
 #include <QFileSystemWatcher>
@@ -29,6 +32,8 @@ class ResourceFolderModel : public QAbstractListModel {
     ResourceFolderModel(QDir, std::shared_ptr<const BaseInstance>, QObject* parent = nullptr, bool create_dir = true);
     ~ResourceFolderModel() override;
 
+    virtual QString id() const { return "resource"; }
+
     /** Starts watching the paths for changes.
      *
      *  Returns whether starting to watch all the paths was successful.
@@ -110,6 +115,11 @@ class ResourceFolderModel : public QAbstractListModel {
 
     [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
 
+    void setupHeaderAction(QAction* act, int column);
+    void saveHiddenColumn(int column, bool hidden);
+    void loadHiddenColumns(QTreeView* tree);
+    std::unique_ptr<QMenu> createHeaderContextMenu(QWidget* parent, QTreeView* tree);
+    
     /** This creates a proxy model to filter / sort the model for a UI.
      *
      *  The actual comparisons and filtering are done directly by the Resource, so to modify behavior go there instead!
@@ -117,6 +127,7 @@ class ResourceFolderModel : public QAbstractListModel {
     QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr);
 
     [[nodiscard]] SortType columnToSortKey(size_t column) const;
+    [[nodiscard]] QList<QHeaderView::ResizeMode> columnResizeModes() const { return m_column_resize_modes; }
 
     class ProxyModel : public QSortFilterProxyModel {
        public:
@@ -187,6 +198,7 @@ class ResourceFolderModel : public QAbstractListModel {
     // Represents the relationship between a column's index (represented by the list index), and it's sorting key.
     // As such, the order in with they appear is very important!
     QList<SortType> m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE };
+    QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents };
 
     bool m_can_interact = true;
 
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index b11e2262..7ec5668c 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -50,7 +50,9 @@
 ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
     : ResourceFolderModel(QDir(dir), instance)
 {
-    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE, SortType::NAME };
+    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
+
 }
 
 QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
@@ -130,7 +132,7 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
         case Qt::DisplayRole:
             switch (section) {
                 case ActiveColumn:
-                    return QString();
+                    return tr("Enable");
                 case NameColumn:
                     return tr("Name");
                 case PackFormatColumn:
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h
index 71532f30..bbec9619 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.h
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.h
@@ -11,15 +11,17 @@ public:
     enum Columns
     {
         ActiveColumn = 0,
+        ImageColumn,
         NameColumn,
         PackFormatColumn,
         DateColumn,
-        ImageColumn,
         NUM_COLUMNS
     };
 
     explicit ResourcePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
 
+    virtual QString id() const override { return "resourcepacks"; }
+
     [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
     [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h
index 6f3f2811..e010f6ed 100644
--- a/launcher/minecraft/mod/ShaderPackFolderModel.h
+++ b/launcher/minecraft/mod/ShaderPackFolderModel.h
@@ -9,4 +9,6 @@ class ShaderPackFolderModel : public ResourceFolderModel {
     explicit ShaderPackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
         : ResourceFolderModel(QDir(dir), instance)
     {}
+    
+    virtual QString id() const override { return "shaderpacks"; }
 };
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index e115cce6..c88f8f37 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -45,7 +45,9 @@
 TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
     : ResourceFolderModel(QDir(dir), instance)
 {
-    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::NAME };
+    m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE };
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
+
 }
 
 Task* TexturePackFolderModel::createUpdateTask()
@@ -115,6 +117,8 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta
     switch (role) {
         case Qt::DisplayRole:
             switch (section) {
+                case ActiveColumn:
+                    return tr("Enable");
                 case NameColumn:
                     return tr("Name");
                 case DateColumn:
@@ -149,4 +153,5 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta
 int TexturePackFolderModel::columnCount(const QModelIndex& parent) const
 {
     return parent.isValid() ? 0 : NUM_COLUMNS;
-}
\ No newline at end of file
+}
+
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h
index 4467691a..ce9c06c4 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.h
+++ b/launcher/minecraft/mod/TexturePackFolderModel.h
@@ -49,14 +49,16 @@ public:
     enum Columns
     {
         ActiveColumn = 0,
+        ImageColumn,
         NameColumn,
         DateColumn,
-        ImageColumn,
         NUM_COLUMNS
     };
 
     explicit TexturePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
 
+    virtual QString id() const override { return "texturepacks"; }
+
     [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
     [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
index 6c11b85b..bee11d9a 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
@@ -24,6 +24,8 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
     m_filterModel->setSourceModel(m_model.get());
     m_filterModel->setFilterKeyColumn(-1);
     ui->treeView->setModel(m_filterModel);
+    // must come after setModel
+    ui->treeView->setResizeModes(m_model->columnResizeModes());
 
     ui->treeView->installEventFilter(this);
     ui->treeView->sortByColumn(1, Qt::AscendingOrder);
@@ -44,6 +46,13 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
     auto selection_model = ui->treeView->selectionModel();
     connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current);
     connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged);
+
+    auto viewHeader = ui->treeView->header();
+    viewHeader->setContextMenuPolicy(Qt::CustomContextMenu);
+
+    connect(viewHeader, &QHeaderView::customContextMenuRequested, this, &ExternalResourcesPage::ShowHeaderContextMenu);
+
+    m_model->loadHiddenColumns(ui->treeView);
 }
 
 ExternalResourcesPage::~ExternalResourcesPage()
@@ -65,6 +74,12 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos)
     delete menu;
 }
 
+void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos)
+{
+    auto menu = m_model->createHeaderContextMenu(this, ui->treeView);
+    menu->exec(ui->treeView->mapToGlobal(pos));
+}
+
 void ExternalResourcesPage::openedImpl()
 {
     m_model->startWatching();
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h
index d17fbb7f..906e6df7 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.h
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.h
@@ -60,6 +60,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
     virtual void viewConfigs();
 
     void ShowContextMenu(const QPoint& pos);
+    void ShowHeaderContextMenu(const QPoint& pos);
 
    protected:
     BaseInstance* m_instance = nullptr;
diff --git a/launcher/ui/widgets/ModListView.cpp b/launcher/ui/widgets/ModListView.cpp
index 09b03a76..893cd120 100644
--- a/launcher/ui/widgets/ModListView.cpp
+++ b/launcher/ui/widgets/ModListView.cpp
@@ -79,3 +79,12 @@ void ModListView::setModel ( QAbstractItemModel* model )
         });
     }
 }
+
+void ModListView::setResizeModes(const QList<QHeaderView::ResizeMode> &modes)
+{
+    auto head = header();
+    for(int i = 0; i < modes.count(); i++) {
+        head->setSectionResizeMode(i, modes[i]);
+    }
+}
+
diff --git a/launcher/ui/widgets/ModListView.h b/launcher/ui/widgets/ModListView.h
index 881e092f..3f0b3b0e 100644
--- a/launcher/ui/widgets/ModListView.h
+++ b/launcher/ui/widgets/ModListView.h
@@ -14,6 +14,7 @@
  */
 
 #pragma once
+#include <QHeaderView>
 #include <QTreeView>
 
 class ModListView: public QTreeView
@@ -22,4 +23,5 @@ class ModListView: public QTreeView
 public:
     explicit ModListView ( QWidget* parent = 0 );
     virtual void setModel ( QAbstractItemModel* model );
+    virtual void setResizeModes (const QList<QHeaderView::ResizeMode>& modes);
 };
-- 
cgit 


From bf0a577fb9d063d90d0003227fce08f32fa09dd1 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 28 May 2023 16:57:35 +0300
Subject: Fixed repaint issue

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/modplatform/ResourcePage.cpp | 10 ++++++----
 launcher/ui/pages/modplatform/ResourcePage.h   |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index 4ebdea56..1edd4f81 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -312,9 +312,11 @@ void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatfo
     m_parent_dialog->addResource(pack, version);
 }
 
-void ResourcePage::removeResourceFromDialog(const QString& pack_name)
+void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack)
 {
-    m_parent_dialog->removeResource(pack_name);
+    m_parent_dialog->removeResource(pack.name);
+    for (auto& ver : pack.versions)
+        ver.is_currently_selected = false;
 }
 
 void ResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack,
@@ -340,7 +342,7 @@ void ResourcePage::onResourceSelected()
 
     auto& version = current_pack.versions[m_selected_version_index];
     if (version.is_currently_selected)
-        removeResourceFromDialog(current_pack.name);
+        removeResourceFromDialog(current_pack);
     else
         addResourceToDialog(current_pack, version);
 
@@ -351,7 +353,7 @@ void ResourcePage::onResourceSelected()
     updateSelectionButton();
 
     /* Force redraw on the resource list when the selection changes */
-    m_ui->packView->adjustSize();
+    m_ui->packView->repaint();
 }
 
 void ResourcePage::openUrl(const QUrl& url)
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index df68e6fd..41b0d0e4 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -76,7 +76,7 @@ class ResourcePage : public QWidget, public BasePage {
     virtual void updateVersionList();
 
     void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
-    void removeResourceFromDialog(const QString& pack_name);
+    void removeResourceFromDialog(ModPlatform::IndexedPack& pack);
     virtual void removeResourceFromPage(const QString& name);
     virtual void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>);
 
-- 
cgit 


From bdff8591aa945bd193f0fdae613f14dea6fb4809 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 28 May 2023 17:54:46 +0300
Subject: Removed extra loop

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/modplatform/ResourcePage.cpp | 8 +++-----
 launcher/ui/pages/modplatform/ResourcePage.h   | 2 +-
 2 files changed, 4 insertions(+), 6 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index c8b3bb61..736034ad 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -314,11 +314,9 @@ void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack::Ptr pack, ModPl
     m_parent_dialog->addResource(pack, version);
 }
 
-void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack::Ptr pack)
+void ResourcePage::removeResourceFromDialog(const QString& pack_name)
 {
-    m_parent_dialog->removeResource(pack->name);
-    for (auto& ver : pack->versions)
-        ver.is_currently_selected = false;
+    m_parent_dialog->removeResource(pack_name);
 }
 
 void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack,
@@ -344,7 +342,7 @@ void ResourcePage::onResourceSelected()
 
     auto& version = current_pack->versions[m_selected_version_index];
     if (version.is_currently_selected)
-        removeResourceFromDialog(current_pack);
+        removeResourceFromDialog(current_pack->name);
     else
         addResourceToDialog(current_pack, version);
 
diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h
index cc7aa707..b4a87f57 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.h
+++ b/launcher/ui/pages/modplatform/ResourcePage.h
@@ -76,7 +76,7 @@ class ResourcePage : public QWidget, public BasePage {
     virtual void updateVersionList();
 
     void addResourceToDialog(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&);
-    void removeResourceFromDialog(ModPlatform::IndexedPack::Ptr pack);
+    void removeResourceFromDialog(const QString& pack_name);
     virtual void removeResourceFromPage(const QString& name);
     virtual void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>);
 
-- 
cgit 


From b4dff181f7dd222086c9405ab49347633dcb7ff8 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 28 May 2023 18:22:55 +0300
Subject: Fixed Ptr logic

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp     | 18 ++++++++++--------
 launcher/minecraft/mod/tasks/GetModDependenciesTask.h  |  4 ++--
 launcher/ui/dialogs/ResourceDownloadDialog.cpp         |  2 +-
 3 files changed, 13 insertions(+), 11 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 948837d4..bd80a661 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -65,8 +65,8 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
 void GetModDependenciesTask::prepare()
 {
     for (auto sel : m_selected) {
-        for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) {
-            addTask(prepareDependencyTask(dep, sel->pack.provider, 20));
+        for (auto dep : getDependenciesForVersion(sel->version, sel->pack->provider)) {
+            addTask(prepareDependencyTask(dep, sel->pack->provider, 20));
         }
     }
 }
@@ -82,7 +82,7 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
                 dep == c_dependencies.end()) {  // check the current dependency list
                 if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
                                             [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
-                                                return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName;
+                                                return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
                                             });
                     dep == m_selected.end()) {  // check the selected versions
                     if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
@@ -92,7 +92,7 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
                         dep == m_mods.end()) {  // check the existing mods
                         if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(),
                                                     [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
-                                                        return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName;
+                                                        return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
                                                     });
                             dep == m_pack_dependencies.end()) {  // check loaded dependencies
                             c_dependencies.append(ver_dep);
@@ -111,7 +111,9 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
 {
     auto pDep = std::make_shared<PackDependency>();
     pDep->dependency = dep;
-    pDep->pack = { dep.addonId, providerName };
+    pDep->pack = std::make_shared<ModPlatform::IndexedPack>();
+    pDep->pack->addonId = dep.addonId;
+    pDep->pack->provider = providerName;
     m_pack_dependencies.append(pDep);
     auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
 
@@ -131,7 +133,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
         try {
             auto obj = provider.name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data")
                                                                              : Json::requireObject(doc);
-            provider.mod->loadIndexedPack(pDep->pack, obj);
+            provider.mod->loadIndexedPack(*pDep->pack, obj);
         } catch (const JSONValidationError& e) {
             qDebug() << doc;
             qWarning() << "Error while reading mod info: " << e.cause();
@@ -157,8 +159,8 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
                 return;
             }
             pDep->version.is_currently_selected = true;
-            pDep->pack.versions = { pDep->version };
-            pDep->pack.versionsLoaded = true;
+            pDep->pack->versions = { pDep->version };
+            pDep->pack->versionsLoaded = true;
 
         } catch (const JSONValidationError& e) {
             qDebug() << doc;
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index aca3c004..3824e781 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -40,10 +40,10 @@ class GetModDependenciesTask : public SequentialTask {
 
     struct PackDependency {
         ModPlatform::Dependency dependency;
-        ModPlatform::IndexedPack pack;
+        ModPlatform::IndexedPack::Ptr pack;
         ModPlatform::IndexedVersion version;
         PackDependency(){};
-        PackDependency(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v)
+        PackDependency(const ModPlatform::IndexedPack::Ptr p, const ModPlatform::IndexedVersion& v)
         {
             pack = p;
             version = v;
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 6bb9b78a..495ee8ed 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -179,7 +179,7 @@ void ResourceDownloadDialog::confirm()
     });
     for (auto& task : selected) {
         confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(),
-                                         ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack().addonId) });
+                                         ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack()->addonId) });
     }
 
     if (confirm_dialog->exec()) {
-- 
cgit 


From b9503ff15f355f0ddc2f2bdb841877766d5fe99d Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 28 May 2023 18:27:02 +0300
Subject: Added Q_DECLARE_METATYPE(ModPlatform::IndexedPack::Ptr)

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/ModIndex.h | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index dcc3484d..82da2ab2 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
-*  PolyMC - Minecraft Launcher
-*  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
-*
-*  This program is free software: you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation, version 3.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ *  PolyMC - Minecraft Launcher
+ *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 
 #pragma once
 
@@ -115,12 +115,12 @@ struct IndexedPack {
         if (!versionsLoaded)
             return false;
 
-        return std::any_of(versions.constBegin(), versions.constEnd(),
-                [](auto const& v) { return v.is_currently_selected; });
+        return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; });
     }
 };
 
 }  // namespace ModPlatform
 
 Q_DECLARE_METATYPE(ModPlatform::IndexedPack)
+Q_DECLARE_METATYPE(ModPlatform::IndexedPack::Ptr)
 Q_DECLARE_METATYPE(ModPlatform::ResourceProvider)
-- 
cgit 


From 10436ed70cc967da8d1d9ee5bca497ec8f70a66f Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 28 May 2023 19:15:41 +0300
Subject: Fixed code quality

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/flame/FlameCheckUpdate.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp
index ca7262c2..e09aeb3d 100644
--- a/launcher/modplatform/flame/FlameCheckUpdate.cpp
+++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp
@@ -130,8 +130,7 @@ void FlameCheckUpdate::executeTask()
         setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name()));
         setProgress(i++, m_mods.size());
 
-        ModPlatform::IndexedPack pack{ mod->metadata()->project_id.toString() };
-        auto latest_ver = api.getLatestVersion({ pack, m_game_versions, m_loaders });
+        auto latest_ver = api.getLatestVersion({ { mod->metadata()->project_id.toString() }, m_game_versions, m_loaders });
 
         // Check if we were aborted while getting the latest version
         if (m_was_aborted) {
-- 
cgit 


From 4eb9083ddc3c57f45d252ceae18d3e9dbf4ee4a3 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Sun, 28 May 2023 13:00:08 -0700
Subject: refactor: column names as class property, use string names in setting

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/ModFolderModel.cpp          |  9 +++------
 launcher/minecraft/mod/ResourceFolderModel.cpp     | 13 ++++++-------
 launcher/minecraft/mod/ResourceFolderModel.h       |  3 +++
 launcher/minecraft/mod/ResourcePackFolderModel.cpp |  8 +++-----
 launcher/minecraft/mod/TexturePackFolderModel.cpp  |  7 +++----
 5 files changed, 18 insertions(+), 22 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 02e77b30..b49aac18 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -57,6 +57,8 @@
 ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir)
     : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed)
 {
+    m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" });
+    m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER};
     m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
 }
@@ -145,17 +147,12 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
         switch (section)
         {
         case ActiveColumn:
-            return tr("Enable");
         case NameColumn:
-            return tr("Name");
         case VersionColumn:
-            return tr("Version");
         case DateColumn:
-            return tr("Last changed");
         case ProviderColumn:
-            return tr("Provider");
         case ImageColumn:
-            return tr("Image");
+            return columnNames().at(section);
         default:
             return QVariant();
         }
diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp
index 838fca53..2997a43d 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourceFolderModel.cpp
@@ -475,11 +475,9 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio
         case Qt::DisplayRole:
             switch (section) {
                 case ACTIVE_COLUMN:
-                    return tr("Enable");
                 case NAME_COLUMN:
-                    return tr("Name");
                 case DATE_COLUMN:
-                    return tr("Last modified");
+                    return columnNames().at(section);
                 default:
                     return {};
             }
@@ -509,7 +507,7 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column)
 {
     Q_ASSERT(act);
 
-    act->setText(headerData(column, Qt::Orientation::Horizontal).toString());
+    act->setText(columnNames().at(column));
 }
 
 void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
@@ -518,12 +516,13 @@ void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
     auto setting = (APPLICATION->settings()->contains(setting_name)) ?
         APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
 
-    auto hiddenColumns = QVariantUtils::toList<int>(setting->get());
-    auto index = hiddenColumns.indexOf(column);
+    auto hiddenColumns = QVariantUtils::toList<QString>(setting->get());
+    auto name = columnNames(false).at(column);
+    auto index = hiddenColumns.indexOf(name);
     if (index >= 0 && !hidden) {
         hiddenColumns.removeAt(index);
     } else if ( index < 0 && hidden) {
-        hiddenColumns.append(column);
+        hiddenColumns.append(name);
     }
     setting->set(QVariantUtils::fromList(hiddenColumns));
 }
diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h
index e1dc685b..138815cf 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.h
+++ b/launcher/minecraft/mod/ResourceFolderModel.h
@@ -97,6 +97,7 @@ class ResourceFolderModel : public QAbstractListModel {
 
     /* Basic columns */
     enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS };
+    QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; };
 
     [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast<int>(size()); }
     [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; };
@@ -198,6 +199,8 @@ class ResourceFolderModel : public QAbstractListModel {
     // Represents the relationship between a column's index (represented by the list index), and it's sorting key.
     // As such, the order in with they appear is very important!
     QList<SortType> m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE };
+    QStringList m_column_names = {"Enable", "Name", "Last Modified"};
+    QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")};
     QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents };
 
     bool m_can_interact = true;
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index 8a7b1049..989554de 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -50,6 +50,8 @@
 ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance)
     : ResourceFolderModel(QDir(dir), instance)
 {
+    m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" });
+    m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE};
     m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
 
@@ -132,15 +134,11 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
         case Qt::DisplayRole:
             switch (section) {
                 case ActiveColumn:
-                    return tr("Enable");
                 case NameColumn:
-                    return tr("Name");
                 case PackFormatColumn:
-                    return tr("Pack Format");
                 case DateColumn:
-                    return tr("Last changed");
                 case ImageColumn:
-                    return tr("Image");
+                    return columnNames().at(section);
                 default:
                     return {};
             }
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index 76145b3b..898d128f 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -45,6 +45,8 @@
 TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance)
     : ResourceFolderModel(QDir(dir), instance)
 {
+    m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified" });
+    m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE };
     m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
 
@@ -118,13 +120,10 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta
         case Qt::DisplayRole:
             switch (section) {
                 case ActiveColumn:
-                    return tr("Enable");
                 case NameColumn:
-                    return tr("Name");
                 case DateColumn:
-                    return tr("Last modified");
                 case ImageColumn:
-                    return tr("Image");
+                    return columnNames().at(section);
                 default:
                     return {};
             }
-- 
cgit 


From 5fe9e30f394a8025cdb6aa11b4cc11b9a2bb6a64 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Sun, 28 May 2023 14:53:15 -0700
Subject: fix: use instance settings, make image column user resizeable, fix
 memory leak

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/ModFolderModel.cpp          |  2 +-
 launcher/minecraft/mod/ResourceFolderModel.cpp     | 29 ++++++++++++----------
 launcher/minecraft/mod/ResourceFolderModel.h       |  2 +-
 launcher/minecraft/mod/ResourcePackFolderModel.cpp |  2 +-
 launcher/minecraft/mod/TexturePackFolderModel.cpp  |  2 +-
 .../ui/pages/instance/ExternalResourcesPage.cpp    |  3 ++-
 6 files changed, 22 insertions(+), 18 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index b49aac18..e745f954 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -60,7 +60,7 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool
     m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" });
     m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER};
-    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
 }
 
 QVariant ModFolderModel::data(const QModelIndex &index, int role) const
diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp
index 2997a43d..b60f8182 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourceFolderModel.cpp
@@ -513,10 +513,10 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column)
 void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
 {
     auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
-    auto setting = (APPLICATION->settings()->contains(setting_name)) ?
-        APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
+    auto setting = (m_instance->settings()->contains(setting_name)) ?
+        m_instance->settings()->getSetting(setting_name) : m_instance->settings()->registerSetting(setting_name);
 
-    auto hiddenColumns = QVariantUtils::toList<QString>(setting->get());
+    auto hiddenColumns = setting->get().toStringList();
     auto name = columnNames(false).at(column);
     auto index = hiddenColumns.indexOf(name);
     if (index >= 0 && !hidden) {
@@ -524,30 +524,33 @@ void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
     } else if ( index < 0 && hidden) {
         hiddenColumns.append(name);
     }
-    setting->set(QVariantUtils::fromList(hiddenColumns));
+    setting->set(hiddenColumns);
 }
 
 void ResourceFolderModel::loadHiddenColumns(QTreeView *tree)
 {
     auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
-    auto setting = (APPLICATION->settings()->contains(setting_name)) ?
-        APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
-
-    auto hiddenColumns = QVariantUtils::toList<int>(setting->get().toList());
-    for (auto col : hiddenColumns) {
-        tree->setColumnHidden(col, true);
+    auto setting = (m_instance->settings()->contains(setting_name)) ?
+        m_instance->settings()->getSetting(setting_name) : m_instance->settings()->registerSetting(setting_name);
+
+    auto hiddenColumns = setting->get().toStringList();
+    auto col_names = columnNames(false);
+    for (auto col_name : hiddenColumns) {
+        auto index = col_names.indexOf(col_name);
+        if (index >= 0)
+            tree->setColumnHidden(index, true);
     }
 
 }
 
-std::unique_ptr<QMenu> ResourceFolderModel::createHeaderContextMenu(QWidget* parent, QTreeView* tree)
+QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree)
 {
-    auto menu = std::make_unique<QMenu>(parent);
+    auto menu = new QMenu(tree);
 
     menu->addSeparator()->setText(tr("Show / Hide Columns"));
 
     for (int col = 0; col < columnCount(); ++col) {
-        auto act = new QAction();
+        auto act = new QAction(menu);
         setupHeaderAction(act, col);
 
         act->setCheckable(true);
diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h
index 138815cf..3c9c4d89 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.h
+++ b/launcher/minecraft/mod/ResourceFolderModel.h
@@ -119,7 +119,7 @@ class ResourceFolderModel : public QAbstractListModel {
     void setupHeaderAction(QAction* act, int column);
     void saveHiddenColumn(int column, bool hidden);
     void loadHiddenColumns(QTreeView* tree);
-    std::unique_ptr<QMenu> createHeaderContextMenu(QWidget* parent, QTreeView* tree);
+    QMenu* createHeaderContextMenu(QTreeView* tree);
     
     /** This creates a proxy model to filter / sort the model for a UI.
      *
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index 989554de..14a28b47 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -53,7 +53,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc
     m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" });
     m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE};
-    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents};
 
 }
 
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index 898d128f..531a7023 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -48,7 +48,7 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance*
     m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified" });
     m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE };
-    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents};
 
 }
 
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
index bee11d9a..2f824ffb 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
@@ -76,8 +76,9 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos)
 
 void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos)
 {
-    auto menu = m_model->createHeaderContextMenu(this, ui->treeView);
+    auto menu = m_model->createHeaderContextMenu(ui->treeView);
     menu->exec(ui->treeView->mapToGlobal(pos));
+    menu->deleteLater();
 }
 
 void ExternalResourcesPage::openedImpl()
-- 
cgit 


From 1e702ee40f211286f85fa5353704e358e7fe14a9 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 7 Jun 2023 00:16:23 +0300
Subject: Added dynamic page extra info

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/BasePage.h                       | 24 +++++++++++-----------
 .../ui/pages/instance/ExternalResourcesPage.cpp    | 19 ++++++++++++++++-
 launcher/ui/pages/instance/ExternalResourcesPage.h |  1 +
 launcher/ui/widgets/PageContainer.cpp              |  4 ++++
 4 files changed, 35 insertions(+), 13 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/BasePage.h b/launcher/ui/pages/BasePage.h
index ceb24040..5537c28f 100644
--- a/launcher/ui/pages/BasePage.h
+++ b/launcher/ui/pages/BasePage.h
@@ -35,15 +35,16 @@
 
 #pragma once
 
-#include <QString>
 #include <QIcon>
+#include <QString>
+#include <functional>
 #include <memory>
 
 #include "BasePageContainer.h"
 
-class BasePage
-{
-public:
+class BasePage {
+   public:
+    using updateExtraInfoFunc = std::function<void(QString)>;
     virtual ~BasePage() {}
     virtual QString id() const = 0;
     virtual QString displayName() const = 0;
@@ -63,17 +64,16 @@ public:
     }
     virtual void openedImpl() {}
     virtual void closedImpl() {}
-    virtual void setParentContainer(BasePageContainer * container)
-    {
-        m_container = container;
-    };
-    virtual void retranslate() { }
+    virtual void setParentContainer(BasePageContainer* container) { m_container = container; };
+    virtual void retranslate() {}
 
-public:
+   public:
     int stackIndex = -1;
     int listIndex = -1;
-protected:
-    BasePageContainer * m_container = nullptr;
+    updateExtraInfoFunc updateExtraInfo;
+
+   protected:
+    BasePageContainer* m_container = nullptr;
     bool isOpened = false;
 };
 
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
index 1115ddc3..e5567c80 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
@@ -9,6 +9,7 @@
 
 #include <QKeyEvent>
 #include <QMenu>
+#include <algorithm>
 
 ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared_ptr<ResourceFolderModel> model, QWidget* parent)
     : QMainWindow(parent), m_instance(instance), ui(new Ui::ExternalResourcesPage), m_model(model)
@@ -43,6 +44,13 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
 
     auto selection_model = ui->treeView->selectionModel();
     connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current);
+    auto updateExtra = [this]() {
+        if (updateExtraInfo)
+            updateExtraInfo(extraHeaderInfoString());
+    };
+    connect(selection_model, &QItemSelectionModel::selectionChanged, this, updateExtra);
+    connect(model.get(), &ResourceFolderModel::updateFinished, this, updateExtra);
+
     connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged);
 }
 
@@ -248,6 +256,15 @@ bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, const
     int row = sourceCurrent.row();
     Resource const& resource = m_model->at(row);
     ui->frame->updateWithResource(resource);
-
     return true;
 }
+
+QString ExternalResourcesPage::extraHeaderInfoString()
+{
+    if (ui && ui->treeView && ui->treeView->selectionModel()) {
+        auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
+        if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0)
+            return tr("[%1 installed, %2 selected]").arg(m_model->size()).arg(count);
+    }
+    return tr("[%1 installed]").arg(m_model->size());
+}
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h
index d17fbb7f..fd200193 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.h
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.h
@@ -29,6 +29,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
     virtual QString helpPage() const override = 0;
 
     virtual bool shouldDisplay() const override = 0;
+    QString extraHeaderInfoString();
 
     void openedImpl() override;
     void closedImpl() override;
diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp
index 38a22897..34df42ec 100644
--- a/launcher/ui/widgets/PageContainer.cpp
+++ b/launcher/ui/widgets/PageContainer.cpp
@@ -93,6 +93,10 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId,
         page->listIndex = counter;
         page->setParentContainer(this);
         counter++;
+        page->updateExtraInfo = [this](QString info) {
+            if (m_currentPage)
+                m_header->setText(m_currentPage->displayName() + info);
+        };
     }
     m_model->setPages(pages);
 
-- 
cgit 


From d4f2059b78bd53fccb20657d11b3386e427ec795 Mon Sep 17 00:00:00 2001
From: clickdevin <git@clickdevin.me>
Date: Wed, 14 Jun 2023 10:42:37 -0400
Subject: Fix bugs when updating curseforge modpacks

Signed-off-by: clickdevin <git@clickdevin.me>
---
 launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index dae93d1c..35443e71 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -153,6 +153,9 @@ bool FlameCreationTask::updateInstance()
 
                     old_files.remove(file.key());
                     files_iterator = files.erase(files_iterator);
+
+                    if (files_iterator != files.begin())
+                        files_iterator--;
                 }
             }
 
-- 
cgit 


From 6667ff9330cc080ca3c5fc2dd90af6b8420bf3fc Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 15 Jun 2023 12:32:48 +0300
Subject: Updated text and fixed mod page text update

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../ui/pages/instance/ExternalResourcesPage.cpp    | 39 ++++++++++++++++++++--
 launcher/ui/pages/instance/ModFolderPage.cpp       | 27 ++++++---------
 2 files changed, 47 insertions(+), 19 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
index e5567c80..e50fa635 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp
@@ -1,3 +1,38 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ *  Prism Launcher - Minecraft Launcher
+ *  Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ *      Copyright 2013-2021 MultiMC Contributors
+ *
+ *      Licensed under the Apache License, Version 2.0 (the "License");
+ *      you may not use this file except in compliance with the License.
+ *      You may obtain a copy of the License at
+ *
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *      Unless required by applicable law or agreed to in writing, software
+ *      distributed under the License is distributed on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *      See the License for the specific language governing permissions and
+ *      limitations under the License.
+ */
+
 #include "ExternalResourcesPage.h"
 #include "ui/dialogs/CustomMessageBox.h"
 #include "ui_ExternalResourcesPage.h"
@@ -264,7 +299,7 @@ QString ExternalResourcesPage::extraHeaderInfoString()
     if (ui && ui->treeView && ui->treeView->selectionModel()) {
         auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
         if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0)
-            return tr("[%1 installed, %2 selected]").arg(m_model->size()).arg(count);
+            return tr(" (%1 installed, %2 selected)").arg(m_model->size()).arg(count);
     }
-    return tr("[%1 installed]").arg(m_model->size());
+    return tr(" (%1 installed)").arg(m_model->size());
 }
diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp
index 4548af59..1d090ef4 100644
--- a/launcher/ui/pages/instance/ModFolderPage.cpp
+++ b/launcher/ui/pages/instance/ModFolderPage.cpp
@@ -4,6 +4,7 @@
  *  Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
  *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
  *  Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
+ *  Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -86,28 +87,20 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel>
         connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods);
 
         auto check_allow_update = [this] {
-            return (!m_instance || !m_instance->isRunning()) &&
-                   (ui->treeView->selectionModel()->hasSelection() || !m_model->empty());
+            return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty());
         };
 
-        connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] {
-            ui->actionUpdateItem->setEnabled(check_allow_update());
-        });
+        connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
+                [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
 
-        connect(mods.get(), &ModFolderModel::rowsInserted, this, [this, check_allow_update] {
-            ui->actionUpdateItem->setEnabled(check_allow_update());
-        });
+        connect(mods.get(), &ModFolderModel::rowsInserted, this,
+                [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
 
-        connect(mods.get(), &ModFolderModel::rowsRemoved, this, [this, check_allow_update] {
-            ui->actionUpdateItem->setEnabled(check_allow_update());
-        });
+        connect(mods.get(), &ModFolderModel::rowsRemoved, this,
+                [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
 
-        connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update, mods] {
-            ui->actionUpdateItem->setEnabled(check_allow_update());
-
-            // Prevent a weird crash when trying to open the mods page twice in a session o.O
-            disconnect(mods.get(), &ModFolderModel::updateFinished, this, 0);
-        });
+        connect(mods.get(), &ModFolderModel::updateFinished, this,
+                [this, check_allow_update, mods] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
 
         connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged);
         ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning());
-- 
cgit 


From 147366bc0a905869f41bd8577337354bc7894e88 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 15 Jun 2023 22:59:41 +0300
Subject: Made ByteSynkArray to use shared_ptr

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/EnsureMetadataTask.cpp        |  16 +-
 launcher/modplatform/ResourceAPI.h                 |   4 +-
 .../modplatform/atlauncher/ATLPackInstallTask.cpp  |  17 +-
 .../modplatform/atlauncher/ATLPackInstallTask.h    |   9 +-
 launcher/modplatform/flame/FileResolvingTask.cpp   |  25 +-
 launcher/modplatform/flame/FlameAPI.cpp            |  20 +-
 launcher/modplatform/flame/FlameAPI.h              |  14 +-
 launcher/modplatform/flame/FlameCheckUpdate.cpp    |   4 +-
 .../flame/FlameInstanceCreationTask.cpp            |   2 +-
 .../modplatform/helpers/NetworkResourceAPI.cpp     |  31 +-
 launcher/modplatform/helpers/NetworkResourceAPI.h  |   3 +-
 launcher/modplatform/legacy_ftb/PackFetchTask.cpp  |  68 ++--
 launcher/modplatform/legacy_ftb/PackFetchTask.h    |  26 +-
 launcher/modplatform/modrinth/ModrinthAPI.cpp      |  22 +-
 launcher/modplatform/modrinth/ModrinthAPI.h        |  18 +-
 .../modplatform/modrinth/ModrinthCheckUpdate.cpp   |   2 +-
 .../modrinth/ModrinthPackExportTask.cpp            |   4 +-
 .../modplatform/modrinth/ModrinthPackExportTask.h  |   2 +-
 .../modplatform/technic/SolderPackInstallTask.cpp  |  33 +-
 .../modplatform/technic/SolderPackInstallTask.h    |  73 ++--
 launcher/net/ByteArraySink.h                       |   7 +-
 launcher/net/Download.cpp                          |   3 +-
 launcher/net/Download.h                            |   2 +-
 launcher/net/Upload.cpp                            | 366 +++++++++++----------
 launcher/net/Upload.h                              |  42 +--
 launcher/news/NewsChecker.cpp                      |  19 +-
 launcher/news/NewsChecker.h                        |   2 +-
 launcher/ui/pages/instance/ManagedPackPage.cpp     |   4 +-
 .../pages/modplatform/atlauncher/AtlListModel.cpp  |   8 +-
 .../ui/pages/modplatform/atlauncher/AtlListModel.h |  29 +-
 .../atlauncher/AtlOptionalModDialog.cpp            |   8 +-
 .../modplatform/atlauncher/AtlOptionalModDialog.h  |   4 +-
 launcher/ui/pages/modplatform/flame/FlameModel.cpp |   6 +-
 launcher/ui/pages/modplatform/flame/FlameModel.h   |  53 ++-
 launcher/ui/pages/modplatform/flame/FlamePage.cpp  |   7 +-
 .../pages/modplatform/modrinth/ModrinthModel.cpp   |  18 +-
 .../ui/pages/modplatform/modrinth/ModrinthModel.h  |   4 +-
 .../ui/pages/modplatform/modrinth/ModrinthPage.cpp |  20 +-
 .../ui/pages/modplatform/technic/TechnicModel.cpp  |  12 +-
 .../ui/pages/modplatform/technic/TechnicModel.h    |  27 +-
 .../ui/pages/modplatform/technic/TechnicPage.cpp   |  15 +-
 .../ui/pages/modplatform/technic/TechnicPage.h     |   2 +-
 42 files changed, 492 insertions(+), 559 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp
index 34d969f0..080dd580 100644
--- a/launcher/modplatform/EnsureMetadataTask.cpp
+++ b/launcher/modplatform/EnsureMetadataTask.cpp
@@ -212,12 +212,12 @@ Task::Ptr EnsureMetadataTask::modrinthVersionsTask()
 {
     auto hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first();
 
-    auto* response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     auto ver_task = modrinth_api.currentVersions(m_mods.keys(), hash_type, response);
 
     // Prevents unfortunate timings when aborting the task
     if (!ver_task)
-        return Task::Ptr{nullptr};
+        return Task::Ptr{ nullptr };
 
     connect(ver_task.get(), &Task::succeeded, this, [this, response] {
         QJsonParseError parse_error{};
@@ -264,7 +264,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask()
     for (auto const& data : m_temp_versions)
         addonIds.insert(data.addonId.toString(), data.hash);
 
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     Task::Ptr proj_task;
 
     if (addonIds.isEmpty()) {
@@ -277,7 +277,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask()
 
     // Prevents unfortunate timings when aborting the task
     if (!proj_task)
-        return Task::Ptr{nullptr};
+        return Task::Ptr{ nullptr };
 
     connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] {
         QJsonParseError parse_error{};
@@ -345,7 +345,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask()
 // Flame
 Task::Ptr EnsureMetadataTask::flameVersionsTask()
 {
-    auto* response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
 
     QList<uint> fingerprints;
     for (auto& murmur : m_mods.keys()) {
@@ -413,7 +413,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask()
     QHash<QString, QString> addonIds;
     for (auto const& hash : m_mods.keys()) {
         if (m_temp_versions.contains(hash)) {
-            auto const& data = m_temp_versions.find(hash).value();
+            auto data = m_temp_versions.find(hash).value();
 
             auto id_str = data.addonId.toString();
             if (!id_str.isEmpty())
@@ -421,7 +421,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask()
         }
     }
 
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     Task::Ptr proj_task;
 
     if (addonIds.isEmpty()) {
@@ -434,7 +434,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask()
 
     // Prevents unfortunate timings when aborting the task
     if (!proj_task)
-        return Task::Ptr{nullptr};
+        return Task::Ptr{ nullptr };
 
     connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] {
         QJsonParseError parse_error{};
diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h
index 34f33779..e24971d5 100644
--- a/launcher/modplatform/ResourceAPI.h
+++ b/launcher/modplatform/ResourceAPI.h
@@ -121,12 +121,12 @@ class ResourceAPI {
         qWarning() << "TODO";
         return nullptr;
     }
-    [[nodiscard]] virtual Task::Ptr getProject(QString addonId, QByteArray* response) const
+    [[nodiscard]] virtual Task::Ptr getProject(QString addonId, std::shared_ptr<QByteArray> response) const
     {
         qWarning() << "TODO";
         return nullptr;
     }
-    [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const
+    [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const
     {
         qWarning() << "TODO";
         return nullptr;
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 07e0bf23..2522020d 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -82,9 +82,9 @@ void PackInstallTask::executeTask()
 {
     qDebug() << "PackInstallTask::executeTask: " << QThread::currentThreadId();
     NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) };
-    auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json")
-            .arg(m_pack_safe_name).arg(m_version_name);
-    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
+    auto searchUrl =
+        QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json").arg(m_pack_safe_name).arg(m_version_name);
+    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
 
     QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded);
     QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed);
@@ -99,11 +99,12 @@ void PackInstallTask::onDownloadSucceeded()
     qDebug() << "PackInstallTask::onDownloadSucceeded: " << QThread::currentThreadId();
     jobPtr.reset();
 
-    QJsonParseError parse_error {};
-    QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
-    if(parse_error.error != QJsonParseError::NoError) {
-        qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset << " reason: " << parse_error.errorString();
-        qWarning() << response;
+    QJsonParseError parse_error{};
+    QJsonDocument doc = QJsonDocument::fromJson(*response.get(), &parse_error);
+    if (parse_error.error != QJsonParseError::NoError) {
+        qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset
+                   << " reason: " << parse_error.errorString();
+        qWarning() << *response.get();
         return;
     }
     auto obj = doc.object();
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h
index 90e25ae2..bfe4d90a 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h
@@ -40,12 +40,13 @@
 #include "ATLPackManifest.h"
 
 #include "InstanceTask.h"
-#include "net/NetJob.h"
-#include "settings/INISettingsObject.h"
+#include "meta/Version.h"
 #include "minecraft/MinecraftInstance.h"
 #include "minecraft/PackProfile.h"
-#include "meta/Version.h"
+#include "net/NetJob.h"
+#include "settings/INISettingsObject.h"
 
+#include <memory>
 #include <optional>
 
 namespace ATLauncher {
@@ -123,7 +124,7 @@ private:
     bool abortable = false;
 
     NetJob::Ptr jobPtr;
-    QByteArray response;
+    std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
 
     InstallMode m_install_mode;
     QString m_pack_name;
diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp
index 83db642e..ce7a6055 100644
--- a/launcher/modplatform/flame/FileResolvingTask.cpp
+++ b/launcher/modplatform/flame/FileResolvingTask.cpp
@@ -25,15 +25,16 @@ void Flame::FileResolvingTask::executeTask()
     setProgress(0, 3);
     m_dljob.reset(new NetJob("Mod id resolver", m_network));
     result.reset(new QByteArray());
-    //build json data to send
+    // build json data to send
     QJsonObject object;
 
-    object["fileIds"] = QJsonArray::fromVariantList(std::accumulate(m_toProcess.files.begin(), m_toProcess.files.end(), QVariantList(), [](QVariantList& l, const File& s) {
-        l.push_back(s.fileId);
-        return l;
-    }));
+    object["fileIds"] = QJsonArray::fromVariantList(
+        std::accumulate(m_toProcess.files.begin(), m_toProcess.files.end(), QVariantList(), [](QVariantList& l, const File& s) {
+            l.push_back(s.fileId);
+            return l;
+        }));
     QByteArray data = Json::toText(object);
-    auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data);
+    auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result, data);
     m_dljob->addNetAction(dl);
 
     auto step_progress = std::make_shared<TaskStepProgress>();
@@ -87,17 +88,15 @@ void Flame::FileResolvingTask::netJobFinished()
         auto fileid = Json::requireInteger(Json::requireObject(file)["id"]);
         auto& out = m_toProcess.files[fileid];
         try {
-           out.parseFromObject(Json::requireObject(file));
+            out.parseFromObject(Json::requireObject(file));
         } catch (const JSONValidationError& e) {
             qDebug() << "Blocked mod on curseforge" << out.fileName;
             auto hash = out.hash;
-            if(!hash.isEmpty()) {
+            if (!hash.isEmpty()) {
                 auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash);
                 auto output = std::make_shared<QByteArray>();
-                auto dl = Net::Download::makeByteArray(QUrl(url), output.get());
-                QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() {
-                    out.resolved = true;
-                });
+                auto dl = Net::Download::makeByteArray(QUrl(url), output);
+                QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; });
 
                 m_checkJob->addNetAction(dl);
                 blockedProjects.insert(&out, output);
@@ -169,7 +168,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
             auto projectId = mod->projectId;
             auto output = std::make_shared<QByteArray>();
             auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId);
-            auto dl = Net::Download::makeByteArray(url, output.get());
+            auto dl = Net::Download::makeByteArray(url, output);
             qDebug() << "Fetching url slug for file:" << mod->fileName;
             QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() {
                 auto mod = block->at(index);  // use the shared_ptr so it is captured and only freed when we are done
diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp
index 92590a08..5b0b1d8b 100644
--- a/launcher/modplatform/flame/FlameAPI.cpp
+++ b/launcher/modplatform/flame/FlameAPI.cpp
@@ -11,7 +11,7 @@
 #include "net/NetJob.h"
 #include "net/Upload.h"
 
-Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, QByteArray* response)
+Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, std::shared_ptr<QByteArray> response)
 {
     auto netJob = makeShared<NetJob>(QString("Flame::MatchFingerprints"), APPLICATION->network());
 
@@ -28,8 +28,6 @@ Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, QByteArra
 
     netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
-
     return netJob;
 }
 
@@ -43,7 +41,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
     netJob->addNetAction(Net::Download::makeByteArray(
         QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog")
             .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))),
-        response.get()));
+        response));
 
     QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] {
         QJsonParseError parse_error{};
@@ -75,8 +73,8 @@ auto FlameAPI::getModDescription(int modId) -> QString
 
     auto netJob = makeShared<NetJob>(QString("Flame::ModDescription"), APPLICATION->network());
     auto response = std::make_shared<QByteArray>();
-    netJob->addNetAction(Net::Download::makeByteArray(
-        QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get()));
+    netJob->addNetAction(
+        Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response));
 
     QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] {
         QJsonParseError parse_error{};
@@ -115,7 +113,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
     auto response = std::make_shared<QByteArray>();
     ModPlatform::IndexedVersion ver;
 
-    netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get()));
+    netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
 
     QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] {
         QJsonParseError parse_error{};
@@ -137,7 +135,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
             for (auto file : arr) {
                 auto file_obj = Json::requireObject(file);
                 auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj);
-                if(file_tmp.date > ver_tmp.date) {
+                if (file_tmp.date > ver_tmp.date) {
                     ver_tmp = file_tmp;
                     latest_file_obj = file_obj;
                 }
@@ -160,7 +158,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
     return ver;
 }
 
-Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) const
+Task::Ptr FlameAPI::getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const
 {
     auto netJob = makeShared<NetJob>(QString("Flame::GetProjects"), APPLICATION->network());
 
@@ -177,13 +175,12 @@ Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) cons
 
     netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
     QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; });
 
     return netJob;
 }
 
-Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) const
+Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, std::shared_ptr<QByteArray> response) const
 {
     auto netJob = makeShared<NetJob>(QString("Flame::GetFiles"), APPLICATION->network());
 
@@ -200,7 +197,6 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) c
 
     netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
     QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; });
 
     return netJob;
diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index 5811d717..49ba12b0 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <memory>
 #include "modplatform/ModIndex.h"
 #include "modplatform/helpers/NetworkResourceAPI.h"
 
@@ -14,9 +15,9 @@ class FlameAPI : public NetworkResourceAPI {
 
     auto getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion;
 
-    Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override;
-    Task::Ptr matchFingerprints(const QList<uint>& fingerprints, QByteArray* response);
-    Task::Ptr getFiles(const QStringList& fileIds, QByteArray* response) const;
+    Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
+    Task::Ptr matchFingerprints(const QList<uint>& fingerprints, std::shared_ptr<QByteArray> response);
+    Task::Ptr getFiles(const QStringList& fileIds, std::shared_ptr<QByteArray> response) const;
 
     [[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
 
@@ -41,14 +42,15 @@ class FlameAPI : public NetworkResourceAPI {
             return 4;
         // TODO: remove this once Quilt drops official Fabric support
         if (loaders & Quilt)  // NOTE: Most if not all Fabric mods should work *currently*
-            return 4;  // Quilt would probably be 5
+            return 4;         // Quilt would probably be 5
         return 0;
     }
 
    private:
     [[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override
     {
-        auto gameVersionStr = args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString();
+        auto gameVersionStr =
+            args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString();
 
         QStringList get_arguments;
         get_arguments.append(QString("classId=%1").arg(getClassId(args.type)));
@@ -73,7 +75,7 @@ class FlameAPI : public NetworkResourceAPI {
 
     [[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override
     {
-        QString url{QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString())};
+        QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString()) };
 
         QStringList get_parameters;
         if (args.mcVersions.has_value())
diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp
index e09aeb3d..a2628e34 100644
--- a/launcher/modplatform/flame/FlameCheckUpdate.cpp
+++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp
@@ -31,7 +31,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info)
 
     auto get_project_job = new NetJob("Flame::GetProjectJob", APPLICATION->network());
 
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(ver_info.addonId.toString());
     auto dl = Net::Download::makeByteArray(url, response);
     get_project_job->addNetAction(dl);
@@ -75,7 +75,7 @@ ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId)
 
     auto get_file_info_job = new NetJob("Flame::GetFileInfoJob", APPLICATION->network());
 
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId));
     auto dl = Net::Download::makeByteArray(url, response);
     get_file_info_job->addNetAction(dl);
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index dae93d1c..3aa156e1 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -179,7 +179,7 @@ bool FlameCreationTask::updateInstance()
             fileIds.append(QString::number(file.fileId));
         }
 
-        auto* raw_response = new QByteArray;
+        auto raw_response = std::make_shared<QByteArray>();
         auto job = api.getFiles(fileIds, raw_response);
 
         QEventLoop loop;
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
index a3c592fd..0ed2410e 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: GPL-3.0-only
 
 #include "NetworkResourceAPI.h"
+#include <memory>
 
 #include "Application.h"
 #include "net/NetJob.h"
@@ -19,12 +20,12 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
 
     auto search_url = search_url_optional.value();
 
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     auto netJob = makeShared<NetJob>(QString("%1::Search").arg(debugName()), APPLICATION->network());
 
     netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response));
 
-    QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks]{
+    QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks] {
         QJsonParseError parse_error{};
         QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
         if (parse_error.error != QJsonParseError::NoError) {
@@ -40,27 +41,21 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
         callbacks.on_succeed(doc);
     });
 
-    QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason){
+    QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason) {
         int network_error_code = -1;
         if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply)
             network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
 
-       callbacks.on_fail(reason, network_error_code); 
-    });
-    QObject::connect(netJob.get(), &NetJob::aborted, [callbacks]{
-       callbacks.on_abort(); 
-    });
-    QObject::connect(netJob.get(), &NetJob::finished, [response] {
-        delete response;
+        callbacks.on_fail(reason, network_error_code);
     });
-
+    QObject::connect(netJob.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); });
 
     return netJob;
 }
 
 Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfoCallbacks&& callbacks) const
 {
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     auto job = getProject(args.pack.addonId.toString(), response);
 
     QObject::connect(job.get(), &NetJob::succeeded, [response, callbacks, args] {
@@ -88,7 +83,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
     auto versions_url = versions_url_optional.value();
 
     auto netJob = makeShared<NetJob>(QString("%1::Versions").arg(args.pack.name), APPLICATION->network());
-    auto response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
 
     netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
 
@@ -105,14 +100,10 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
         callbacks.on_succeed(doc, args.pack);
     });
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] {
-        delete response;
-    });
-
     return netJob;
 }
 
-Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) const
+Task::Ptr NetworkResourceAPI::getProject(QString addonId, std::shared_ptr<QByteArray> response) const
 {
     auto project_url_optional = getInfoURL(addonId);
     if (!project_url_optional.has_value())
@@ -124,9 +115,5 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response)
 
     netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] {
-        delete response;
-    });
-
     return netJob;
 }
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h
index 94813bec..84604e41 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.h
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.h
@@ -4,13 +4,14 @@
 
 #pragma once
 
+#include <memory>
 #include "modplatform/ResourceAPI.h"
 
 class NetworkResourceAPI : public ResourceAPI {
    public:
     Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const override;
 
-    Task::Ptr getProject(QString addonId, QByteArray* response) const override;
+    Task::Ptr getProject(QString addonId, std::shared_ptr<QByteArray> response) const override;
 
     Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override;
     Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override;
diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp
index e8768c5c..a8a0fc2c 100644
--- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp
+++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp
@@ -51,11 +51,11 @@ void PackFetchTask::fetch()
 
     QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml");
     qDebug() << "Downloading public version info from" << publicPacksUrl.toString();
-    jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData));
+    jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, publicModpacksXmlFileData));
 
     QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml");
     qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString();
-    jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData));
+    jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, thirdPartyModpacksXmlFileData));
 
     QObject::connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished);
     QObject::connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed);
@@ -64,22 +64,19 @@ void PackFetchTask::fetch()
     jobPtr->start();
 }
 
-void PackFetchTask::fetchPrivate(const QStringList & toFetch)
+void PackFetchTask::fetchPrivate(const QStringList& toFetch)
 {
     QString privatePackBaseUrl = BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1.xml";
 
-    for (auto &packCode: toFetch)
-    {
-        QByteArray *data = new QByteArray();
-        NetJob *job = new NetJob("Fetching private pack", m_network);
+    for (auto& packCode : toFetch) {
+        auto data = std::make_shared<QByteArray>();
+        NetJob* job = new NetJob("Fetching private pack", m_network);
         job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data));
 
-        QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode]
-        {
+        QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] {
             ModpackList packs;
             parseAndAddPacks(*data, PackType::Private, packs);
-            foreach(Modpack currentPack, packs)
-            {
+            foreach (Modpack currentPack, packs) {
                 currentPack.packCode = packCode;
                 emit privateFileDownloadFinished(currentPack);
             }
@@ -87,24 +84,20 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch)
             job->deleteLater();
 
             data->clear();
-            delete data;
         });
 
-        QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason)
-        {
+        QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) {
             emit privateFileDownloadFailed(reason, packCode);
             job->deleteLater();
 
             data->clear();
-            delete data;
         });
 
-        QObject::connect(job, &NetJob::aborted, this, [this, job, data]{
+        QObject::connect(job, &NetJob::aborted, this, [this, job, data] {
             emit aborted();
             job->deleteLater();
 
             data->clear();
-            delete data;
         });
 
         job->start();
@@ -117,27 +110,22 @@ void PackFetchTask::fileDownloadFinished()
 
     QStringList failedLists;
 
-    if(!parseAndAddPacks(publicModpacksXmlFileData, PackType::Public, publicPacks))
-    {
+    if (!parseAndAddPacks(*publicModpacksXmlFileData, PackType::Public, publicPacks)) {
         failedLists.append(tr("Public Packs"));
     }
 
-    if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks))
-    {
+    if (!parseAndAddPacks(*thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks)) {
         failedLists.append(tr("Third Party Packs"));
     }
 
-    if(failedLists.size() > 0)
-    {
+    if (failedLists.size() > 0) {
         emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- ")));
-    }
-    else
-    {
+    } else {
         emit finished(publicPacks, thirdPartyPacks);
     }
 }
 
-bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, ModpackList &list)
+bool PackFetchTask::parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list)
 {
     QDomDocument doc;
 
@@ -145,8 +133,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
     int errorLine = -1;
     int errorCol = -1;
 
-    if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol))
-    {
+    if (!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) {
         auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:%3!").arg(errorMsg).arg(errorLine).arg(errorCol);
         qWarning() << fullErrMsg;
         data.clear();
@@ -154,8 +141,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
     }
 
     QDomNodeList nodes = doc.elementsByTagName("modpack");
-    for(int i = 0; i < nodes.length(); i++)
-    {
+    for (int i = 0; i < nodes.length(); i++) {
         QDomElement element = nodes.at(i).toElement();
 
         Modpack modpack;
@@ -169,26 +155,20 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
         modpack.broken = false;
         modpack.bugged = false;
 
-        //remove empty if the xml is bugged
-        for(QString curr : modpack.oldVersions)
-        {
-            if(curr.isNull() || curr.isEmpty())
-            {
+        // remove empty if the xml is bugged
+        for (QString curr : modpack.oldVersions) {
+            if (curr.isNull() || curr.isEmpty()) {
                 modpack.oldVersions.removeAll(curr);
                 modpack.bugged = true;
                 qWarning() << "Removed some empty versions from" << modpack.name;
             }
         }
 
-        if(modpack.oldVersions.size() < 1)
-        {
-            if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty())
-            {
+        if (modpack.oldVersions.size() < 1) {
+            if (!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) {
                 modpack.oldVersions.append(modpack.currentVersion);
                 qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")";
-            }
-            else
-            {
+            } else {
                 modpack.broken = true;
                 qWarning() << "Broken pack:" << modpack.name << " => No valid version!";
             }
@@ -218,4 +198,4 @@ void PackFetchTask::fileDownloadAborted()
     emit aborted();
 }
 
-}
+}  // namespace LegacyFTB
diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.h b/launcher/modplatform/legacy_ftb/PackFetchTask.h
index 8f3c4f3b..f2116ce9 100644
--- a/launcher/modplatform/legacy_ftb/PackFetchTask.h
+++ b/launcher/modplatform/legacy_ftb/PackFetchTask.h
@@ -1,41 +1,41 @@
 #pragma once
 
-#include "net/NetJob.h"
-#include <QTemporaryDir>
 #include <QByteArray>
 #include <QObject>
+#include <QTemporaryDir>
+#include <memory>
 #include "PackHelpers.h"
+#include "net/NetJob.h"
 
 namespace LegacyFTB {
 
 class PackFetchTask : public QObject {
-
     Q_OBJECT
 
-public:
-    PackFetchTask(shared_qobject_ptr<QNetworkAccessManager> network) : QObject(nullptr), m_network(network) {};
+   public:
+    PackFetchTask(shared_qobject_ptr<QNetworkAccessManager> network) : QObject(nullptr), m_network(network){};
     virtual ~PackFetchTask() = default;
 
     void fetch();
-    void fetchPrivate(const QStringList &toFetch);
+    void fetchPrivate(const QStringList& toFetch);
 
-private:
+   private:
     shared_qobject_ptr<QNetworkAccessManager> m_network;
     NetJob::Ptr jobPtr;
 
-    QByteArray publicModpacksXmlFileData;
-    QByteArray thirdPartyModpacksXmlFileData;
+    std::shared_ptr<QByteArray> publicModpacksXmlFileData = std::make_shared<QByteArray>();
+    std::shared_ptr<QByteArray> thirdPartyModpacksXmlFileData = std::make_shared<QByteArray>();
 
-    bool parseAndAddPacks(QByteArray &data, PackType packType, ModpackList &list);
+    bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list);
     ModpackList publicPacks;
     ModpackList thirdPartyPacks;
 
-protected slots:
+   protected slots:
     void fileDownloadFinished();
     void fileDownloadFailed(QString reason);
     void fileDownloadAborted();
 
-signals:
+   signals:
     void finished(ModpackList publicPacks, ModpackList thirdPartyPacks);
     void failed(QString reason);
     void aborted();
@@ -44,4 +44,4 @@ signals:
     void privateFileDownloadFailed(QString reason, QString packCode);
 };
 
-}
+}  // namespace LegacyFTB
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp
index 29e3d129..364cf3f3 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.cpp
+++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp
@@ -9,19 +9,17 @@
 #include "net/NetJob.h"
 #include "net/Upload.h"
 
-Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response)
+Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, std::shared_ptr<QByteArray> response)
 {
     auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersion"), APPLICATION->network());
 
     netJob->addNetAction(Net::Download::makeByteArray(
         QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
-
     return netJob;
 }
 
-Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response)
+Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, std::shared_ptr<QByteArray> response)
 {
     auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersions"), APPLICATION->network());
 
@@ -35,8 +33,6 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f
 
     netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
-
     return netJob;
 }
 
@@ -44,7 +40,7 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash,
                                      QString hash_format,
                                      std::optional<std::list<Version>> mcVersions,
                                      std::optional<ModLoaderTypes> loaders,
-                                     QByteArray* response)
+                                     std::shared_ptr<QByteArray> response)
 {
     auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersion"), APPLICATION->network());
 
@@ -67,8 +63,6 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash,
     netJob->addNetAction(Net::Upload::makeByteArray(
         QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
-
     return netJob;
 }
 
@@ -76,7 +70,7 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes,
                                       QString hash_format,
                                       std::optional<std::list<Version>> mcVersions,
                                       std::optional<ModLoaderTypes> loaders,
-                                      QByteArray* response)
+                                      std::shared_ptr<QByteArray> response)
 {
     auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersions"), APPLICATION->network());
 
@@ -101,22 +95,16 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes,
 
     netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
-
     return netJob;
 }
 
-Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) const
+Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const
 {
     auto netJob = makeShared<NetJob>(QString("Modrinth::GetProjects"), APPLICATION->network());
     auto searchUrl = getMultipleModInfoURL(addonIds);
 
     netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
 
-    QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] {
-        delete response;
-    });
-
     return netJob;
 }
 
diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h
index b91ac5c1..98f20b51 100644
--- a/launcher/modplatform/modrinth/ModrinthAPI.h
+++ b/launcher/modplatform/modrinth/ModrinthAPI.h
@@ -12,27 +12,23 @@
 
 class ModrinthAPI : public NetworkResourceAPI {
    public:
-    auto currentVersion(QString hash,
-                        QString hash_format,
-                        QByteArray* response) -> Task::Ptr;
+    auto currentVersion(QString hash, QString hash_format, std::shared_ptr<QByteArray> response) -> Task::Ptr;
 
-    auto currentVersions(const QStringList& hashes,
-                         QString hash_format,
-                         QByteArray* response) -> Task::Ptr;
+    auto currentVersions(const QStringList& hashes, QString hash_format, std::shared_ptr<QByteArray> response) -> Task::Ptr;
 
     auto latestVersion(QString hash,
                        QString hash_format,
                        std::optional<std::list<Version>> mcVersions,
                        std::optional<ModLoaderTypes> loaders,
-                       QByteArray* response) -> Task::Ptr;
+                       std::shared_ptr<QByteArray> response) -> Task::Ptr;
 
     auto latestVersions(const QStringList& hashes,
                         QString hash_format,
-                       std::optional<std::list<Version>> mcVersions,
-                       std::optional<ModLoaderTypes> loaders,
-                        QByteArray* response) -> Task::Ptr;
+                        std::optional<std::list<Version>> mcVersions,
+                        std::optional<ModLoaderTypes> loaders,
+                        std::shared_ptr<QByteArray> response) -> Task::Ptr;
 
-    Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override;
+    Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
 
    public:
     [[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
index 4fe91ce7..6a3f12f9 100644
--- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
+++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
@@ -71,7 +71,7 @@ void ModrinthCheckUpdate::executeTask()
     hashing_task.start();
     loop.exec();
 
-    auto* response = new QByteArray();
+    auto response = std::make_shared<QByteArray>();
     auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response);
 
     QEventLoop lock;
diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
index bff9bf42..c607bb89 100644
--- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
@@ -157,7 +157,7 @@ void ModrinthPackExportTask::makeApiRequest()
     if (pendingHashes.isEmpty())
         buildZip();
     else {
-        QByteArray* response = new QByteArray;
+        auto response = std::make_shared<QByteArray>();
         task = api.currentVersions(pendingHashes.values(), "sha512", response);
         connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); });
         connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed);
@@ -165,7 +165,7 @@ void ModrinthPackExportTask::makeApiRequest()
     }
 }
 
-void ModrinthPackExportTask::parseApiResponse(const QByteArray* response)
+void ModrinthPackExportTask::parseApiResponse(const std::shared_ptr<QByteArray> response)
 {
     task = nullptr;
 
diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h
index af00ffaa..96f292c1 100644
--- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h
+++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h
@@ -69,7 +69,7 @@ class ModrinthPackExportTask : public Task {
     void collectFiles();
     void collectHashes();
     void makeApiRequest();
-    void parseApiResponse(const QByteArray* response);
+    void parseApiResponse(const std::shared_ptr<QByteArray> response);
     void buildZip();
     void finish();
 
diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp
index c26d6a5a..6a05d17a 100644
--- a/launcher/modplatform/technic/SolderPackInstallTask.cpp
+++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp
@@ -37,20 +37,19 @@
 
 #include <FileSystem.h>
 #include <Json.h>
-#include <QtConcurrentRun>
 #include <MMCZip.h>
+#include <QtConcurrentRun>
 
-#include "TechnicPackProcessor.h"
 #include "SolderPackManifest.h"
+#include "TechnicPackProcessor.h"
 #include "net/ChecksumValidator.h"
 
-Technic::SolderPackInstallTask::SolderPackInstallTask(
-    shared_qobject_ptr<QNetworkAccessManager> network,
-    const QUrl &solderUrl,
-    const QString &pack,
-    const QString &version,
-    const QString &minecraftVersion
-) {
+Technic::SolderPackInstallTask::SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network,
+                                                      const QUrl& solderUrl,
+                                                      const QString& pack,
+                                                      const QString& version,
+                                                      const QString& minecraftVersion)
+{
     m_solderUrl = solderUrl;
     m_pack = pack;
     m_version = version;
@@ -58,9 +57,9 @@ Technic::SolderPackInstallTask::SolderPackInstallTask(
     m_minecraftVersion = minecraftVersion;
 }
 
-bool Technic::SolderPackInstallTask::abort() {
-    if(m_abortable)
-    {
+bool Technic::SolderPackInstallTask::abort()
+{
+    if (m_abortable) {
         return m_filesNetJob->abort();
     }
     return false;
@@ -72,7 +71,7 @@ void Technic::SolderPackInstallTask::executeTask()
 
     m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network));
     auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version);
-    m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, &m_response));
+    m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, m_response));
 
     auto job = m_filesNetJob.get();
     connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded);
@@ -85,11 +84,11 @@ void Technic::SolderPackInstallTask::fileListSucceeded()
 {
     setStatus(tr("Downloading modpack"));
 
-    QJsonParseError parse_error {};
-    QJsonDocument doc = QJsonDocument::fromJson(m_response, &parse_error);
+    QJsonParseError parse_error{};
+    QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error);
     if (parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
-        qWarning() << m_response;
+        qWarning() << *m_response;
         return;
     }
     auto obj = doc.object();
@@ -110,7 +109,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded()
     m_filesNetJob.reset(new NetJob(tr("Downloading modpack"), m_network));
 
     int i = 0;
-    for (const auto &mod : build.mods) {
+    for (const auto& mod : build.mods) {
         auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i));
 
         auto dl = Net::Download::makeFile(mod.url, path);
diff --git a/launcher/modplatform/technic/SolderPackInstallTask.h b/launcher/modplatform/technic/SolderPackInstallTask.h
index aa14ce88..f2c6a83a 100644
--- a/launcher/modplatform/technic/SolderPackInstallTask.h
+++ b/launcher/modplatform/technic/SolderPackInstallTask.h
@@ -40,45 +40,48 @@
 #include <tasks/Task.h>
 
 #include <QUrl>
+#include <memory>
 
-namespace Technic
-{
-    class SolderPackInstallTask : public InstanceTask
-    {
-        Q_OBJECT
-    public:
-        explicit SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network, const QUrl &solderUrl, const QString& pack, const QString& version, const QString &minecraftVersion);
+namespace Technic {
+class SolderPackInstallTask : public InstanceTask {
+    Q_OBJECT
+   public:
+    explicit SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network,
+                                   const QUrl& solderUrl,
+                                   const QString& pack,
+                                   const QString& version,
+                                   const QString& minecraftVersion);
 
-        bool canAbort() const override { return true; }
-        bool abort() override;
+    bool canAbort() const override { return true; }
+    bool abort() override;
 
-    protected:
-        //! Entry point for tasks.
-        virtual void executeTask() override;
+   protected:
+    //! Entry point for tasks.
+    virtual void executeTask() override;
 
-    private slots:
-        void fileListSucceeded();
-        void downloadSucceeded();
-        void downloadFailed(QString reason);
-        void downloadProgressChanged(qint64 current, qint64 total);
-        void downloadAborted();
-        void extractFinished();
-        void extractAborted();
+   private slots:
+    void fileListSucceeded();
+    void downloadSucceeded();
+    void downloadFailed(QString reason);
+    void downloadProgressChanged(qint64 current, qint64 total);
+    void downloadAborted();
+    void extractFinished();
+    void extractAborted();
 
-    private:
-        bool m_abortable = false;
+   private:
+    bool m_abortable = false;
 
-        shared_qobject_ptr<QNetworkAccessManager> m_network;
+    shared_qobject_ptr<QNetworkAccessManager> m_network;
 
-        NetJob::Ptr m_filesNetJob;
-        QUrl m_solderUrl;
-        QString m_pack;
-        QString m_version;
-        QString m_minecraftVersion;
-        QByteArray m_response;
-        QTemporaryDir m_outputDir;
-        int m_modCount;
-        QFuture<bool> m_extractFuture;
-        QFutureWatcher<bool> m_extractFutureWatcher;
-    };
-}
+    NetJob::Ptr m_filesNetJob;
+    QUrl m_solderUrl;
+    QString m_pack;
+    QString m_version;
+    QString m_minecraftVersion;
+    std::shared_ptr<QByteArray> m_response = std::make_shared<QByteArray>();
+    QTemporaryDir m_outputDir;
+    int m_modCount;
+    QFuture<bool> m_extractFuture;
+    QFutureWatcher<bool> m_extractFutureWatcher;
+};
+}  // namespace Technic
diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h
index 728193b3..d6b17d60 100644
--- a/launcher/net/ByteArraySink.h
+++ b/launcher/net/ByteArraySink.h
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-3.0-only
 /*
- *  PolyMC - Minecraft Launcher
+ *  Prism Launcher - Minecraft Launcher
  *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ *  Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -46,7 +47,7 @@ namespace Net {
  */
 class ByteArraySink : public Sink {
    public:
-    ByteArraySink(QByteArray* output) : m_output(output){};
+    ByteArraySink(std::shared_ptr<QByteArray> output) : m_output(output){};
 
     virtual ~ByteArraySink() = default;
 
@@ -93,6 +94,6 @@ class ByteArraySink : public Sink {
     auto hasLocalData() -> bool override { return false; }
 
    private:
-    QByteArray* m_output;
+    std::shared_ptr<QByteArray> m_output;
 };
 }  // namespace Net
diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp
index 7f8d3a06..4ea45c63 100644
--- a/launcher/net/Download.cpp
+++ b/launcher/net/Download.cpp
@@ -41,6 +41,7 @@
 
 #include <QDateTime>
 #include <QFileInfo>
+#include <memory>
 
 #include "ByteArraySink.h"
 #include "ChecksumValidator.h"
@@ -69,7 +70,7 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down
     return dl;
 }
 
-auto Download::makeByteArray(QUrl url, QByteArray* output, Options options) -> Download::Ptr
+auto Download::makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options) -> Download::Ptr
 {
     auto dl = makeShared<Download>();
     dl->m_url = url;
diff --git a/launcher/net/Download.h b/launcher/net/Download.h
index 920164a3..2e861732 100644
--- a/launcher/net/Download.h
+++ b/launcher/net/Download.h
@@ -60,7 +60,7 @@ class Download : public NetAction {
     ~Download() override = default;
 
     static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr;
-    static auto makeByteArray(QUrl url, QByteArray* output, Options options = Option::NoOptions) -> Download::Ptr;
+    static auto makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options = Option::NoOptions) -> Download::Ptr;
     static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr;
 
    public:
diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp
index 4f9553ed..3f6f5829 100644
--- a/launcher/net/Upload.cpp
+++ b/launcher/net/Upload.cpp
@@ -39,218 +39,226 @@
 #include "Upload.h"
 
 #include <utility>
-#include "ByteArraySink.h"
-#include "BuildConfig.h"
 #include "Application.h"
+#include "BuildConfig.h"
+#include "ByteArraySink.h"
 
 #include "net/Logging.h"
 
 namespace Net {
 
-    bool Upload::abort()
-    {
-        if (m_reply) {
-            m_reply->abort();
-        } else {
-            m_state = State::AbortedByUser;
-        }
-        return true;
+bool Upload::abort()
+{
+    if (m_reply) {
+        m_reply->abort();
+    } else {
+        m_state = State::AbortedByUser;
     }
+    return true;
+}
 
-    void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
-        setProgress(bytesReceived, bytesTotal);
-    }
+void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+{
+    setProgress(bytesReceived, bytesTotal);
+}
 
-    void Upload::downloadError(QNetworkReply::NetworkError error) {
-        if (error == QNetworkReply::OperationCanceledError) {
-            qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString();
-            m_state = State::AbortedByUser;
-        } else {
-            // error happened during download.
-            qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error;
-            m_state = State::Failed;
-        }
+void Upload::downloadError(QNetworkReply::NetworkError error)
+{
+    if (error == QNetworkReply::OperationCanceledError) {
+        qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString();
+        m_state = State::AbortedByUser;
+    } else {
+        // error happened during download.
+        qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error;
+        m_state = State::Failed;
     }
+}
 
-    void Upload::sslErrors(const QList<QSslError> &errors) {
-        int i = 1;
-        for (const auto& error : errors) {
-            qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString();
-            auto cert = error.certificate();
-            qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText();
-            i++;
-        }
+void Upload::sslErrors(const QList<QSslError>& errors)
+{
+    int i = 1;
+    for (const auto& error : errors) {
+        qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : "
+                                   << error.errorString();
+        auto cert = error.certificate();
+        qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText();
+        i++;
     }
+}
 
-    bool Upload::handleRedirect()
-    {
-        QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl();
-        if (!redirect.isValid()) {
-            if (!m_reply->hasRawHeader("Location")) {
-                // no redirect -> it's fine to continue
-                return false;
-            }
-            // there is a Location header, but it's not correct. we need to apply some workarounds...
-            QByteArray redirectBA = m_reply->rawHeader("Location");
-            if (redirectBA.size() == 0) {
-                // empty, yet present redirect header? WTF?
-                return false;
-            }
-            QString redirectStr = QString::fromUtf8(redirectBA);
-
-            if (redirectStr.startsWith("//")) {
-                /*
-                 * IF the URL begins with //, we need to insert the URL scheme.
-                 * See: https://bugreports.qt.io/browse/QTBUG-41061
-                 * See: http://tools.ietf.org/html/rfc3986#section-4.2
-                 */
-                redirectStr = m_reply->url().scheme() + ":" + redirectStr;
-            } else if (redirectStr.startsWith("/")) {
-                /*
-                 * IF the URL begins with /, we need to process it as a relative URL
-                 */
-                auto url = m_reply->url();
-                url.setPath(redirectStr, QUrl::TolerantMode);
-                redirectStr = url.toString();
-            }
+bool Upload::handleRedirect()
+{
+    QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl();
+    if (!redirect.isValid()) {
+        if (!m_reply->hasRawHeader("Location")) {
+            // no redirect -> it's fine to continue
+            return false;
+        }
+        // there is a Location header, but it's not correct. we need to apply some workarounds...
+        QByteArray redirectBA = m_reply->rawHeader("Location");
+        if (redirectBA.size() == 0) {
+            // empty, yet present redirect header? WTF?
+            return false;
+        }
+        QString redirectStr = QString::fromUtf8(redirectBA);
 
+        if (redirectStr.startsWith("//")) {
             /*
-             * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues.
-             * FIXME: report Qt bug for this
+             * IF the URL begins with //, we need to insert the URL scheme.
+             * See: https://bugreports.qt.io/browse/QTBUG-41061
+             * See: http://tools.ietf.org/html/rfc3986#section-4.2
              */
-            redirect = QUrl(redirectStr, QUrl::TolerantMode);
-            if (!redirect.isValid()) {
-                qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr;
-                downloadError(QNetworkReply::ProtocolFailure);
-                return false;
-            }
-            qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect;
-        } else {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect;
+            redirectStr = m_reply->url().scheme() + ":" + redirectStr;
+        } else if (redirectStr.startsWith("/")) {
+            /*
+             * IF the URL begins with /, we need to process it as a relative URL
+             */
+            auto url = m_reply->url();
+            url.setPath(redirectStr, QUrl::TolerantMode);
+            redirectStr = url.toString();
         }
 
-        m_url = QUrl(redirect.toString());
-        qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString();
-        startAction(m_network);
-        return true;
-    }
-
-    void Upload::downloadFinished() {
-        // handle HTTP redirection first
-        // very unlikely for post requests, still can happen
-        if (handleRedirect()) {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString();
-            return;
+        /*
+         * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues.
+         * FIXME: report Qt bug for this
+         */
+        redirect = QUrl(redirectStr, QUrl::TolerantMode);
+        if (!redirect.isValid()) {
+            qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr;
+            downloadError(QNetworkReply::ProtocolFailure);
+            return false;
         }
+        qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect;
+    } else {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect;
+    }
 
-        // if the download failed before this point ...
-        if (m_state == State::Succeeded) {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString();
-            m_sink->abort();
-            m_reply.reset();
-            emit succeeded();
-            return;
-        } else if (m_state == State::Failed) {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString();
-            m_sink->abort();
-            m_reply.reset();
-            emit failed("");
-            return;
-        } else if (m_state == State::AbortedByUser) {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString();
-            m_sink->abort();
-            m_reply.reset();
-            emit aborted();
-            return;
-        }
+    m_url = QUrl(redirect.toString());
+    qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString();
+    startAction(m_network);
+    return true;
+}
 
-        // make sure we got all the remaining data, if any
-        auto data = m_reply->readAll();
-        if (data.size()) {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes";
-            m_state = m_sink->write(data);
-        }
+void Upload::downloadFinished()
+{
+    // handle HTTP redirection first
+    // very unlikely for post requests, still can happen
+    if (handleRedirect()) {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString();
+        return;
+    }
 
-        // otherwise, finalize the whole graph
-        m_state = m_sink->finalize(*m_reply.get());
-        if (m_state != State::Succeeded) {
-            qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString();
-            m_sink->abort();
-            m_reply.reset();
-            emit failed("");
-            return;
-        }
+    // if the download failed before this point ...
+    if (m_state == State::Succeeded) {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString();
+        m_sink->abort();
         m_reply.reset();
-        qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString();
         emit succeeded();
+        return;
+    } else if (m_state == State::Failed) {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit failed("");
+        return;
+    } else if (m_state == State::AbortedByUser) {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit aborted();
+        return;
     }
 
-    void Upload::downloadReadyRead() {
-        if (m_state == State::Running) {
-            auto data = m_reply->readAll();
-            m_state = m_sink->write(data);
-        }
+    // make sure we got all the remaining data, if any
+    auto data = m_reply->readAll();
+    if (data.size()) {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes";
+        m_state = m_sink->write(data);
+    }
+
+    // otherwise, finalize the whole graph
+    m_state = m_sink->finalize(*m_reply.get());
+    if (m_state != State::Succeeded) {
+        qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit failed("");
+        return;
     }
+    m_reply.reset();
+    qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString();
+    emit succeeded();
+}
 
-    void Upload::executeTask() {
-        setStatus(tr("Uploading %1").arg(m_url.toString()));
+void Upload::downloadReadyRead()
+{
+    if (m_state == State::Running) {
+        auto data = m_reply->readAll();
+        m_state = m_sink->write(data);
+    }
+}
 
-        if (m_state == State::AbortedByUser) {
-            qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString();
-            emit aborted();
+void Upload::executeTask()
+{
+    setStatus(tr("Uploading %1").arg(m_url.toString()));
+
+    if (m_state == State::AbortedByUser) {
+        qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString();
+        emit aborted();
+        return;
+    }
+    QNetworkRequest request(m_url);
+    m_state = m_sink->init(request);
+    switch (m_state) {
+        case State::Succeeded:
+            emitSucceeded();
+            qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString();
             return;
-        }
-        QNetworkRequest request(m_url);
-        m_state = m_sink->init(request);
-        switch (m_state) {
-            case State::Succeeded:
-                emitSucceeded();
-                qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString();
-                return;
-            case State::Running:
-                qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString();
-                break;
-            case State::Inactive:
-            case State::Failed:
-                emitFailed("");
-                return;
-            case State::AbortedByUser:
-                emitAborted();
-                return;
-        }
+        case State::Running:
+            qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString();
+            break;
+        case State::Inactive:
+        case State::Failed:
+            emitFailed("");
+            return;
+        case State::AbortedByUser:
+            emitAborted();
+            return;
+    }
 
-        request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8());
-        // TODO remove duplication
-        if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) {
-            request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8());
-        } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() ||
-                   request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) {
-            QString token = APPLICATION->getModrinthAPIToken();
-            if (!token.isNull())
-                request.setRawHeader("Authorization", token.toUtf8());
-        }
+    request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8());
+    // TODO remove duplication
+    if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) {
+        request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8());
+    } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() ||
+               request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) {
+        QString token = APPLICATION->getModrinthAPIToken();
+        if (!token.isNull())
+            request.setRawHeader("Authorization", token.toUtf8());
+    }
 
-        //TODO other types of post requests ?
-        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
-        QNetworkReply* rep = m_network->post(request, m_post_data);
+    // TODO other types of post requests ?
+    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
+    QNetworkReply* rep = m_network->post(request, m_post_data);
 
-        m_reply.reset(rep);
-        connect(rep, &QNetworkReply::downloadProgress, this,  &Upload::downloadProgress);
-        connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished);
-#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
-        connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError);
+    m_reply.reset(rep);
+    connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress);
+    connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)  // QNetworkReply::errorOccurred added in 5.15
+    connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError);
 #else
-        connect(rep, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &Upload::downloadError);
+    connect(rep, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &Upload::downloadError);
 #endif
-        connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors);
-        connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead);
-    }
+    connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors);
+    connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead);
+}
 
-    Upload::Ptr Upload::makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data) {
-        auto up = makeShared<Upload>();
-        up->m_url = std::move(url);
-        up->m_sink.reset(new ByteArraySink(output));
-        up->m_post_data = std::move(m_post_data);
-        return up;
-    }
-} // Net
+Upload::Ptr Upload::makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, QByteArray m_post_data)
+{
+    auto up = makeShared<Upload>();
+    up->m_url = std::move(url);
+    up->m_sink.reset(new ByteArraySink(output));
+    up->m_post_data = std::move(m_post_data);
+    return up;
+}
+}  // namespace Net
diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h
index e8f0ea40..0b0c9497 100644
--- a/launcher/net/Upload.h
+++ b/launcher/net/Upload.h
@@ -42,31 +42,31 @@
 
 namespace Net {
 
-    class Upload : public NetAction {
-        Q_OBJECT
+class Upload : public NetAction {
+    Q_OBJECT
 
-    public:
-        using Ptr = shared_qobject_ptr<Upload>;
+   public:
+    using Ptr = shared_qobject_ptr<Upload>;
 
-        static Upload::Ptr makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data);
-        auto abort() -> bool override;
-        auto canAbort() const -> bool override { return true; };
+    static Upload::Ptr makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, QByteArray m_post_data);
+    auto abort() -> bool override;
+    auto canAbort() const -> bool override { return true; };
 
-    protected slots:
-        void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
-        void downloadError(QNetworkReply::NetworkError error) override;
-        void sslErrors(const QList<QSslError> & errors) override;
-        void downloadFinished() override;
-        void downloadReadyRead() override;
+   protected slots:
+    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
+    void downloadError(QNetworkReply::NetworkError error) override;
+    void sslErrors(const QList<QSslError>& errors) override;
+    void downloadFinished() override;
+    void downloadReadyRead() override;
 
-    public slots:
-        void executeTask() override;
-    private:
-        std::unique_ptr<Sink> m_sink;
-        QByteArray m_post_data;
+   public slots:
+    void executeTask() override;
 
-        bool handleRedirect();
-    };
+   private:
+    std::unique_ptr<Sink> m_sink;
+    QByteArray m_post_data;
 
-} // Net
+    bool handleRedirect();
+};
 
+}  // namespace Net
diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp
index 1f1520d0..4f02bf5e 100644
--- a/launcher/news/NewsChecker.cpp
+++ b/launcher/news/NewsChecker.cpp
@@ -58,7 +58,7 @@ void NewsChecker::reloadNews()
     qDebug() << "Reloading news.";
 
     NetJob::Ptr job{ new NetJob("News RSS Feed", m_network) };
-    job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData));
+    job->addNetAction(Net::Download::makeByteArray(m_feedUrl, newsData));
     QObject::connect(job.get(), &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished);
     QObject::connect(job.get(), &NetJob::failed, this, &NewsChecker::rssDownloadFailed);
     m_newsNetJob.reset(job);
@@ -79,32 +79,27 @@ void NewsChecker::rssDownloadFinished()
         int errorCol = -1;
 
         // Parse the XML.
-        if (!doc.setContent(newsData, false, &errorMsg, &errorLine, &errorCol))
-        {
+        if (!doc.setContent(*newsData, false, &errorMsg, &errorLine, &errorCol)) {
             QString fullErrorMsg = QString("Error parsing RSS feed XML. %1 at %2:%3.").arg(errorMsg).arg(errorLine).arg(errorCol);
             fail(fullErrorMsg);
-            newsData.clear();
+            newsData->clear();
             return;
         }
-        newsData.clear();
+        newsData->clear();
     }
 
     // If the parsing succeeded, read it.
     QDomNodeList items = doc.elementsByTagName("entry");
     m_newsEntries.clear();
-    for (int i = 0; i < items.length(); i++)
-    {
+    for (int i = 0; i < items.length(); i++) {
         QDomElement element = items.at(i).toElement();
         NewsEntryPtr entry;
         entry.reset(new NewsEntry());
         QString errorMsg = "An unknown error occurred.";
-        if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg))
-        {
+        if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg)) {
             qDebug() << "Loaded news entry" << entry->title;
             m_newsEntries.append(entry);
-        }
-        else
-        {
+        } else {
             qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg;
         }
     }
diff --git a/launcher/news/NewsChecker.h b/launcher/news/NewsChecker.h
index 8467a541..41babfff 100644
--- a/launcher/news/NewsChecker.h
+++ b/launcher/news/NewsChecker.h
@@ -85,7 +85,7 @@ protected: /* data */
     //! True if news has been loaded.
     bool m_loadedNews;
 
-    QByteArray newsData;
+    std::shared_ptr<QByteArray> newsData = std::make_shared<QByteArray>();
 
     /*!
      * Gets the error message that was given last time the news was loaded.
diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp
index d0701a7a..e0a7314f 100644
--- a/launcher/ui/pages/instance/ManagedPackPage.cpp
+++ b/launcher/ui/pages/instance/ManagedPackPage.cpp
@@ -226,7 +226,7 @@ void ModrinthManagedPackPage::parseManagedPack()
 
     QString id = m_inst->getManagedPackID();
 
-    m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get()));
+    m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response));
 
     QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] {
         QJsonParseError parse_error{};
@@ -369,7 +369,7 @@ void FlameManagedPackPage::parseManagedPack()
 
     QString id = m_inst->getManagedPackID();
 
-    m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get()));
+    m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response));
 
     QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] {
         QJsonParseError parse_error{};
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp
index 9ad26f47..2ab86529 100644
--- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp
@@ -88,7 +88,7 @@ void ListModel::request()
 
     auto netJob = makeShared<NetJob>("Atl::Request", APPLICATION->network());
     auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json");
-    netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response));
+    netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), response));
     jobPtr = netJob;
     jobPtr->start();
 
@@ -101,10 +101,10 @@ void ListModel::requestFinished()
     jobPtr.reset();
 
     QJsonParseError parse_error;
-    QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
+    QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
     if(parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
-        qWarning() << response;
+        qWarning() << *response;
         return;
     }
 
@@ -120,7 +120,7 @@ void ListModel::requestFinished()
             ATLauncher::loadIndexedPack(pack, packObj);
         }
         catch (const JSONValidationError &e) {
-            qDebug() << QString::fromUtf8(response);
+            qDebug() << QString::fromUtf8(*response);
             qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause();
             return;
         }
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h
index 2574c48d..ed1fdc9f 100644
--- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h
@@ -18,42 +18,41 @@
 
 #include <QAbstractListModel>
 
-#include "net/NetJob.h"
-#include <QIcon>
 #include <modplatform/atlauncher/ATLPackIndex.h>
+#include <QIcon>
+#include "net/NetJob.h"
 
 namespace Atl {
 
 typedef QMap<QString, QIcon> LogoMap;
 typedef std::function<void(QString)> LogoCallback;
 
-class ListModel : public QAbstractListModel
-{
+class ListModel : public QAbstractListModel {
     Q_OBJECT
 
-public:
-    ListModel(QObject *parent);
+   public:
+    ListModel(QObject* parent);
     virtual ~ListModel();
 
-    int rowCount(const QModelIndex &parent) const override;
-    int columnCount(const QModelIndex &parent) const override;
-    QVariant data(const QModelIndex &index, int role) const override;
+    int rowCount(const QModelIndex& parent) const override;
+    int columnCount(const QModelIndex& parent) const override;
+    QVariant data(const QModelIndex& index, int role) const override;
 
     void request();
 
-    void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
+    void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
 
-private slots:
+   private slots:
     void requestFinished();
     void requestFailed(QString reason);
 
     void logoFailed(QString logo);
     void logoLoaded(QString logo, QIcon out);
 
-private:
+   private:
     void requestLogo(QString file, QString url);
 
-private:
+   private:
     QList<ATLauncher::IndexedPack> modpacks;
 
     QStringList m_failedLogos;
@@ -62,7 +61,7 @@ private:
     QMap<QString, LogoCallback> waitingCallbacks;
 
     NetJob::Ptr jobPtr;
-    QByteArray response;
+    std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
 };
 
-}
+}  // namespace Atl
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp
index cdb4532c..7b61daa7 100644
--- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp
@@ -152,7 +152,7 @@ Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const {
 void AtlOptionalModListModel::useShareCode(const QString& code) {
     m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network()));
     auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code);
-    m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), &m_response));
+    m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), m_response));
 
     connect(m_jobPtr.get(), &NetJob::succeeded,
             this, &AtlOptionalModListModel::shareCodeSuccess);
@@ -166,10 +166,10 @@ void AtlOptionalModListModel::shareCodeSuccess() {
     m_jobPtr.reset();
 
     QJsonParseError parse_error {};
-    auto doc = QJsonDocument::fromJson(m_response, &parse_error);
+    auto doc = QJsonDocument::fromJson(*m_response, &parse_error);
     if (parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
-        qWarning() << m_response;
+        qWarning() << *m_response;
         return;
     }
     auto obj = doc.object();
@@ -179,7 +179,7 @@ void AtlOptionalModListModel::shareCodeSuccess() {
         ATLauncher::loadShareCodeResponse(response, obj);
     }
     catch (const JSONValidationError& e) {
-        qDebug() << QString::fromUtf8(m_response);
+        qDebug() << QString::fromUtf8(*m_response);
         qWarning() << "Error while reading response from ATLauncher: " << e.cause();
         return;
     }
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h
index 8e02444e..639f0d48 100644
--- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h
@@ -82,9 +82,9 @@ private:
     void toggleMod(ATLauncher::VersionMod mod, int index);
     void setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit = true);
 
-private:
+   private:
     NetJob::Ptr m_jobPtr;
-    QByteArray m_response;
+    std::shared_ptr<QByteArray> m_response = std::make_shared<QByteArray>();
 
     ATLauncher::PackVersion m_version;
     QVector<ATLauncher::VersionMod> m_mods;
diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp
index 5961ea02..54d0b003 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp
@@ -169,7 +169,7 @@ void ListModel::performPaginatedSearch()
                          .arg(currentSearchTerm)
                          .arg(currentSort + 1);
 
-    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
+    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
     jobPtr = netJob;
     jobPtr->start();
     QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished);
@@ -202,11 +202,11 @@ void Flame::ListModel::searchRequestFinished()
     jobPtr.reset();
 
     QJsonParseError parse_error;
-    QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
+    QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
     if (parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset
                    << " reason: " << parse_error.errorString();
-        qWarning() << response;
+        qWarning() << *response;
         return;
     }
 
diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h
index cab666cc..b3bc96b8 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModel.h
+++ b/launcher/ui/pages/modplatform/flame/FlameModel.h
@@ -3,46 +3,44 @@
 #include <RWStorage.h>
 
 #include <QAbstractListModel>
-#include <QSortFilterProxyModel>
-#include <QThreadPool>
 #include <QIcon>
-#include <QStyledItemDelegate>
 #include <QList>
+#include <QMetaType>
+#include <QSortFilterProxyModel>
 #include <QString>
 #include <QStringList>
-#include <QMetaType>
+#include <QStyledItemDelegate>
+#include <QThreadPool>
 
-#include <functional>
 #include <net/NetJob.h>
+#include <functional>
 
 #include <modplatform/flame/FlamePackIndex.h>
 
 namespace Flame {
 
-
 typedef QMap<QString, QIcon> LogoMap;
 typedef std::function<void(QString)> LogoCallback;
 
-class ListModel : public QAbstractListModel
-{
+class ListModel : public QAbstractListModel {
     Q_OBJECT
 
-public:
-    ListModel(QObject *parent);
+   public:
+    ListModel(QObject* parent);
     virtual ~ListModel();
 
-    int rowCount(const QModelIndex &parent) const override;
-    int columnCount(const QModelIndex &parent) const override;
-    QVariant data(const QModelIndex &index, int role) const override;
-    bool setData(const QModelIndex &index, const QVariant &value, int role) override;
-    Qt::ItemFlags flags(const QModelIndex &index) const override;
-    bool canFetchMore(const QModelIndex & parent) const override;
-    void fetchMore(const QModelIndex & parent) override;
+    int rowCount(const QModelIndex& parent) const override;
+    int columnCount(const QModelIndex& parent) const override;
+    QVariant data(const QModelIndex& index, int role) const override;
+    bool setData(const QModelIndex& index, const QVariant& value, int role) override;
+    Qt::ItemFlags flags(const QModelIndex& index) const override;
+    bool canFetchMore(const QModelIndex& parent) const override;
+    void fetchMore(const QModelIndex& parent) override;
 
-    void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
-    void searchWithTerm(const QString & term, const int sort);
+    void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
+    void searchWithTerm(const QString& term, const int sort);
 
-private slots:
+   private slots:
     void performPaginatedSearch();
 
     void logoFailed(QString logo);
@@ -51,10 +49,10 @@ private slots:
     void searchRequestFinished();
     void searchRequestFailed(QString reason);
 
-private:
+   private:
     void requestLogo(QString file, QString url);
 
-private:
+   private:
     QList<IndexedPack> modpacks;
     QStringList m_failedLogos;
     QStringList m_loadingLogos;
@@ -64,14 +62,9 @@ private:
     QString currentSearchTerm;
     int currentSort = 0;
     int nextSearchOffset = 0;
-    enum SearchState {
-        None,
-        CanPossiblyFetchMore,
-        ResetRequested,
-        Finished
-    } searchState = None;
+    enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
     NetJob::Ptr jobPtr;
-    QByteArray response;
+    std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
 };
 
-}
+}  // namespace Flame
diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp
index f9ac4a78..cef26bb6 100644
--- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp
@@ -130,7 +130,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
     if (current.versionsLoaded == false) {
         qDebug() << "Loading flame modpack versions";
         auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network());
-        auto response = new QByteArray();
+        auto response = std::make_shared<QByteArray>();
         int addonId = current.addonId;
         netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response));
 
@@ -170,10 +170,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
             }
             suggestCurrent();
         });
-        QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
-            netJob->deleteLater();
-            delete response;
-        });
+        QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
         netJob->start();
     } else {
         for (auto version : current.versions) {
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp
index 346a00b0..675589d0 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp
@@ -129,27 +129,27 @@ void ModpackListModel::performPaginatedSearch()
     // TODO: Move to standalone API
     auto netJob = makeShared<NetJob>("Modrinth::SearchModpack", APPLICATION->network());
     auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL +
-                            "/search?"
-                            "offset=%1&"
-                            "limit=%2&"
-                            "query=%3&"
-                            "index=%4&"
-                            "facets=[[\"project_type:modpack\"]]")
+                                "/search?"
+                                "offset=%1&"
+                                "limit=%2&"
+                                "query=%3&"
+                                "index=%4&"
+                                "facets=[[\"project_type:modpack\"]]")
                             .arg(nextSearchOffset)
                             .arg(m_modpacks_per_page)
                             .arg(currentSearchTerm)
                             .arg(currentSort);
 
-    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), &m_all_response));
+    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), m_all_response));
 
     QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] {
         QJsonParseError parse_error_all{};
 
-        QJsonDocument doc_all = QJsonDocument::fromJson(m_all_response, &parse_error_all);
+        QJsonDocument doc_all = QJsonDocument::fromJson(*m_all_response, &parse_error_all);
         if (parse_error_all.error != QJsonParseError::NoError) {
             qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parse_error_all.offset
                        << " reason: " << parse_error_all.errorString();
-            qWarning() << m_all_response;
+            qWarning() << *m_all_response;
             return;
         }
 
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h
index 6e6be4b9..b9e9c3da 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h
@@ -110,9 +110,9 @@ class ModpackListModel : public QAbstractListModel {
 
     NetJob::Ptr jobPtr;
 
-    QByteArray m_all_response;
+    std::shared_ptr<QByteArray> m_all_response = std::make_shared<QByteArray>();
     QByteArray m_specific_response;
 
     int m_modpacks_per_page = 20;
 };
-}  // namespace ModPlatform
+}  // namespace Modrinth
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
index 0bb11d83..c71dd903 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
@@ -123,7 +123,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
         qDebug() << "Loading modrinth modpack information";
 
         auto netJob = new NetJob(QString("Modrinth::PackInformation(%1)").arg(current.name), APPLICATION->network());
-        auto response = new QByteArray();
+        auto response = std::make_shared<QByteArray>();
 
         QString id = current.id;
 
@@ -162,10 +162,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
 
             suggestCurrent();
         });
-        QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
-            netJob->deleteLater();
-            delete response;
-        });
+        QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
         netJob->start();
     } else
         updateUI();
@@ -174,7 +171,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
         qDebug() << "Loading modrinth modpack versions";
 
         auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(current.name), APPLICATION->network());
-        auto response = new QByteArray();
+        auto response = std::make_shared<QByteArray>();
 
         QString id = current.id;
 
@@ -217,10 +214,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
 
             suggestCurrent();
         });
-        QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
-            netJob->deleteLater();
-            delete response;
-        });
+        QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
         netJob->start();
 
     } else {
@@ -260,10 +254,8 @@ void ModrinthPage::updateUI()
             text += donates.join(", ");
         }
 
-        if (!current.extra.issuesUrl.isEmpty()
-         || !current.extra.sourceUrl.isEmpty()
-         || !current.extra.wikiUrl.isEmpty()
-         || !current.extra.discordUrl.isEmpty()) {
+        if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty() ||
+            !current.extra.discordUrl.isEmpty()) {
             text += "<br><br>" + tr("External links:") + "<br>";
         }
 
diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp
index 50f0c72d..7975fd58 100644
--- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp
+++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp
@@ -134,7 +134,7 @@ void Technic::ListModel::performSearch()
         ).arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm);
         searchMode = List;
     }
-    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
+    netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
     jobPtr = netJob;
     jobPtr->start();
     QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished);
@@ -146,11 +146,11 @@ void Technic::ListModel::searchRequestFinished()
     jobPtr.reset();
 
     QJsonParseError parse_error;
-    QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
-    if(parse_error.error != QJsonParseError::NoError)
-    {
-        qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset << " reason: " << parse_error.errorString();
-        qWarning() << response;
+    QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
+    if (parse_error.error != QJsonParseError::NoError) {
+        qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset
+                   << " reason: " << parse_error.errorString();
+        qWarning() << *response;
         return;
     }
 
diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h
index 5eea124c..0f1a814e 100644
--- a/launcher/ui/pages/modplatform/technic/TechnicModel.h
+++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h
@@ -44,33 +44,32 @@ namespace Technic {
 
 typedef std::function<void(QString)> LogoCallback;
 
-class ListModel : public QAbstractListModel
-{
+class ListModel : public QAbstractListModel {
     Q_OBJECT
 
-public:
-    ListModel(QObject *parent);
+   public:
+    ListModel(QObject* parent);
     virtual ~ListModel();
 
     virtual QVariant data(const QModelIndex& index, int role) const;
     virtual int columnCount(const QModelIndex& parent) const;
     virtual int rowCount(const QModelIndex& parent) const;
 
-    void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
-    void searchWithTerm(const QString & term);
+    void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
+    void searchWithTerm(const QString& term);
 
-private slots:
+   private slots:
     void searchRequestFinished();
     void searchRequestFailed();
 
     void logoFailed(QString logo);
     void logoLoaded(QString logo, QString out);
 
-private:
+   private:
     void performSearch();
     void requestLogo(QString logo, QString url);
 
-private:
+   private:
     QList<Modpack> modpacks;
     QStringList m_failedLogos;
     QStringList m_loadingLogos;
@@ -78,17 +77,13 @@ private:
     QMap<QString, LogoCallback> waitingCallbacks;
 
     QString currentSearchTerm;
-    enum SearchState {
-        None,
-        ResetRequested,
-        Finished
-    } searchState = None;
+    enum SearchState { None, ResetRequested, Finished } searchState = None;
     enum SearchMode {
         List,
         Single,
     } searchMode = List;
     NetJob::Ptr jobPtr;
-    QByteArray response;
+    std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
 };
 
-}
+}  // namespace Technic
diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp
index 859da97e..fc678fa2 100644
--- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp
+++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp
@@ -143,7 +143,7 @@ void TechnicPage::suggestCurrent()
 
     auto netJob = makeShared<NetJob>(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network());
     QString slug = current.slug;
-    netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response));
+    netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), response));
     QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug]
     {
         jobPtr.reset();
@@ -154,7 +154,7 @@ void TechnicPage::suggestCurrent()
         }
 
         QJsonParseError parse_error {};
-        QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
+        QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
         QJsonObject obj = doc.object();
         if(parse_error.error != QJsonParseError::NoError)
         {
@@ -249,7 +249,7 @@ void TechnicPage::metadataLoaded()
 
         auto netJob = makeShared<NetJob>(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network());
         auto url = QString("%1/modpack/%2").arg(current.url, current.slug);
-        netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response));
+        netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), response));
 
         QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded);
 
@@ -291,11 +291,11 @@ void TechnicPage::onSolderLoaded() {
 
     current.versions.clear();
 
-    QJsonParseError parse_error {};
-    auto doc = QJsonDocument::fromJson(response, &parse_error);
+    QJsonParseError parse_error{};
+    auto doc = QJsonDocument::fromJson(*response, &parse_error);
     if (parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
-        qWarning() << response;
+        qWarning() << *response;
         fallback();
         return;
     }
@@ -304,8 +304,7 @@ void TechnicPage::onSolderLoaded() {
     TechnicSolder::Pack pack;
     try {
         TechnicSolder::loadPack(pack, obj);
-    }
-    catch (const JSONValidationError& err) {
+    } catch (const JSONValidationError& err) {
         qCritical() << "Couldn't parse Solder pack metadata:" << err.cause();
         fallback();
         return;
diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h
index f4a3b61d..753261b3 100644
--- a/launcher/ui/pages/modplatform/technic/TechnicPage.h
+++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h
@@ -104,5 +104,5 @@ private:
     QString selectedVersion;
 
     NetJob::Ptr jobPtr;
-    QByteArray response;
+    std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
 };
-- 
cgit 


From 0161520b332f485483f57acc305ad71a00d63fbc Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 18 Jun 2023 23:27:26 +0300
Subject: Fixed leaks

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/EnsureMetadataTask.cpp        |   9 +-
 .../modplatform/atlauncher/ATLPackInstallTask.h    |  40 ++++----
 launcher/modplatform/helpers/HashUtils.cpp         |  14 +--
 launcher/modplatform/helpers/HashUtils.h           |   6 ++
 .../modplatform/modrinth/ModrinthCheckUpdate.cpp   |   5 +-
 launcher/ui/dialogs/NewsDialog.cpp                 |   2 +-
 .../pages/modplatform/atlauncher/AtlListModel.cpp  |  91 +++++++----------
 .../atlauncher/AtlUserInteractionSupportImpl.h     |   8 +-
 .../ui/pages/modplatform/legacy_ftb/ListModel.cpp  | 112 ++++++++-------------
 .../ui/pages/modplatform/technic/TechnicModel.cpp  | 106 +++++++------------
 10 files changed, 164 insertions(+), 229 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp
index 080dd580..a04a2534 100644
--- a/launcher/modplatform/EnsureMetadataTask.cpp
+++ b/launcher/modplatform/EnsureMetadataTask.cpp
@@ -10,6 +10,7 @@
 
 #include "modplatform/flame/FlameAPI.h"
 #include "modplatform/flame/FlameModIndex.h"
+#include "modplatform/helpers/HashUtils.h"
 #include "modplatform/modrinth/ModrinthAPI.h"
 #include "modplatform/modrinth/ModrinthPackIndex.h"
 
@@ -24,8 +25,8 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource
     auto hash_task = createNewHash(mod);
     if (!hash_task)
         return;
-    connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { m_mods.insert(hash_task->getResult(), mod); });
-    connect(hash_task.get(), &Task::failed, [this, hash_task, mod] { emitFail(mod, "", RemoveFromList::No); });
+    connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); });
+    connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
     hash_task->start();
 }
 
@@ -37,8 +38,8 @@ EnsureMetadataTask::EnsureMetadataTask(QList<Mod*>& mods, QDir dir, ModPlatform:
         auto hash_task = createNewHash(mod);
         if (!hash_task)
             continue;
-        connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { m_mods.insert(hash_task->getResult(), mod); });
-        connect(hash_task.get(), &Task::failed, [this, hash_task, mod] { emitFail(mod, "", RemoveFromList::No); });
+        connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); });
+        connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
         m_hashing_task->addTask(hash_task);
     }
 }
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h
index bfe4d90a..b82f523f 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h
@@ -58,8 +58,7 @@ enum class InstallMode {
 };
 
 class UserInteractionSupport {
-
-public:
+   public:
     /**
      * Requests a user interaction to select which optional mods should be installed.
      */
@@ -75,23 +74,27 @@ public:
      * Requests a user interaction to display a message.
      */
     virtual void displayMessage(QString message) = 0;
+
+    virtual ~UserInteractionSupport() = default;
 };
 
-class PackInstallTask : public InstanceTask
-{
-Q_OBJECT
+class PackInstallTask : public InstanceTask {
+    Q_OBJECT
 
-public:
-    explicit PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode = InstallMode::Install);
-    virtual ~PackInstallTask(){}
+   public:
+    explicit PackInstallTask(UserInteractionSupport* support,
+                             QString packName,
+                             QString version,
+                             InstallMode installMode = InstallMode::Install);
+    virtual ~PackInstallTask() { delete m_support; }
 
     bool canAbort() const override { return true; }
     bool abort() override;
 
-protected:
+   protected:
     virtual void executeTask() override;
 
-private slots:
+   private slots:
     void onDownloadSucceeded();
     void onDownloadFailed(QString reason);
     void onDownloadAborted();
@@ -99,7 +102,7 @@ private slots:
     void onModsDownloaded();
     void onModsExtracted();
 
-private:
+   private:
     QString getDirForModType(ModType type, QString raw);
     QString getVersionForLoader(QString uid);
     QString detectLibrary(VersionLibrary library);
@@ -111,15 +114,13 @@ private:
     void installConfigs();
     void extractConfigs();
     void downloadMods();
-    bool extractMods(
-        const QMap<QString, VersionMod> &toExtract,
-        const QMap<QString, VersionMod> &toDecomp,
-        const QMap<QString, QString> &toCopy
-    );
+    bool extractMods(const QMap<QString, VersionMod>& toExtract,
+                     const QMap<QString, VersionMod>& toDecomp,
+                     const QMap<QString, QString>& toCopy);
     void install();
 
-private:
-    UserInteractionSupport *m_support;
+   private:
+    UserInteractionSupport* m_support;
 
     bool abortable = false;
 
@@ -146,7 +147,6 @@ private:
 
     QFuture<bool> m_modExtractFuture;
     QFutureWatcher<bool> m_modExtractFutureWatcher;
-
 };
 
-}
+}  // namespace ATLauncher
diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp
index 81c94e1b..6df1eaf9 100644
--- a/launcher/modplatform/helpers/HashUtils.cpp
+++ b/launcher/modplatform/helpers/HashUtils.cpp
@@ -71,6 +71,7 @@ void ModrinthHasher::executeTask()
         emitFailed("Empty hash!");
     } else {
         emitSucceeded();
+        emit getResults(m_hash);
     }
 }
 
@@ -91,10 +92,9 @@ void FlameHasher::executeTask()
     }
 }
 
-
-BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::ResourceProvider provider)
-    : Hasher(file_path), provider(provider) { 
-    setObjectName(QString("BlockedModHasher: %1").arg(file_path)); 
+BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::ResourceProvider provider) : Hasher(file_path), provider(provider)
+{
+    setObjectName(QString("BlockedModHasher: %1").arg(file_path));
     hash_type = ProviderCaps.hashType(provider).first();
 }
 
@@ -123,11 +123,13 @@ void BlockedModHasher::executeTask()
     }
 }
 
-QStringList BlockedModHasher::getHashTypes() {
+QStringList BlockedModHasher::getHashTypes()
+{
     return ProviderCaps.hashType(provider);
 }
 
-bool BlockedModHasher::useHashType(QString type) {
+bool BlockedModHasher::useHashType(QString type)
+{
     auto types = ProviderCaps.hashType(provider);
     if (types.contains(type)) {
         hash_type = type;
diff --git a/launcher/modplatform/helpers/HashUtils.h b/launcher/modplatform/helpers/HashUtils.h
index 91146a52..f3b9e030 100644
--- a/launcher/modplatform/helpers/HashUtils.h
+++ b/launcher/modplatform/helpers/HashUtils.h
@@ -1,5 +1,6 @@
 #pragma once
 
+#include <qtmetamacros.h>
 #include <QString>
 
 #include "modplatform/ModIndex.h"
@@ -8,6 +9,7 @@
 namespace Hashing {
 
 class Hasher : public Task {
+    Q_OBJECT
    public:
     using Ptr = shared_qobject_ptr<Hasher>;
 
@@ -21,6 +23,9 @@ class Hasher : public Task {
     QString getResult() const { return m_hash; };
     QString getPath() const { return m_path; };
 
+   signals:
+    void getResults(QString hash);
+
    protected:
     QString m_hash;
     QString m_path;
@@ -48,6 +53,7 @@ class BlockedModHasher : public Hasher {
 
     QStringList getHashTypes();
     bool useHashType(QString type);
+
    private:
     ModPlatform::ResourceProvider provider;
     QString hash_type;
diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
index 6a3f12f9..36002bad 100644
--- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
+++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
@@ -53,12 +53,11 @@ void ModrinthCheckUpdate::executeTask()
         // (though it will rarely happen, if at all)
         if (mod->metadata()->hash_format != best_hash_type) {
             auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath());
-            connect(hash_task.get(), &Task::succeeded, [&] {
-                QString hash(hash_task->getResult());
+            connect(hash_task.get(), &Hashing::Hasher::getResults, [&hashes, &mappings, mod](QString hash) {
                 hashes.append(hash);
                 mappings.insert(hash, mod);
             });
-            connect(hash_task.get(), &Task::failed, [this, hash_task] { failed("Failed to generate hash"); });
+            connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); });
             hashing_task.addTask(hash_task);
         } else {
             hashes.append(hash);
diff --git a/launcher/ui/dialogs/NewsDialog.cpp b/launcher/ui/dialogs/NewsDialog.cpp
index e1b5dd74..b646e391 100644
--- a/launcher/ui/dialogs/NewsDialog.cpp
+++ b/launcher/ui/dialogs/NewsDialog.cpp
@@ -32,7 +32,7 @@ NewsDialog::~NewsDialog()
 
 void NewsDialog::selectedArticleChanged(const QString& new_title)
 {
-    auto const& article_entry = m_entries.constFind(new_title).value();
+    auto article_entry = m_entries.constFind(new_title).value();
 
     ui->articleTitleLabel->setText(QString("<a href='%1'>%2</a>").arg(article_entry->link, new_title));
 
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp
index 2ab86529..c6b087d6 100644
--- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp
@@ -16,62 +16,49 @@
 
 #include "AtlListModel.h"
 
-#include <BuildConfig.h>
 #include <Application.h>
+#include <BuildConfig.h>
 #include <Json.h>
 
 namespace Atl {
 
-ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
-{
-}
+ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
 
-ListModel::~ListModel()
-{
-}
+ListModel::~ListModel() {}
 
-int ListModel::rowCount(const QModelIndex &parent) const
+int ListModel::rowCount(const QModelIndex& parent) const
 {
     return parent.isValid() ? 0 : modpacks.size();
 }
 
-int ListModel::columnCount(const QModelIndex &parent) const
+int ListModel::columnCount(const QModelIndex& parent) const
 {
     return parent.isValid() ? 0 : 1;
 }
 
-QVariant ListModel::data(const QModelIndex &index, int role) const
+QVariant ListModel::data(const QModelIndex& index, int role) const
 {
     int pos = index.row();
-    if(pos >= modpacks.size() || pos < 0 || !index.isValid())
-    {
+    if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
         return QString("INVALID INDEX %1").arg(pos);
     }
 
     ATLauncher::IndexedPack pack = modpacks.at(pos);
-    if(role == Qt::DisplayRole)
-    {
+    if (role == Qt::DisplayRole) {
         return pack.name;
-    }
-    else if (role == Qt::ToolTipRole)
-    {
+    } else if (role == Qt::ToolTipRole) {
         return pack.name;
-    }
-    else if(role == Qt::DecorationRole)
-    {
-        if(m_logoMap.contains(pack.safeName))
-        {
+    } else if (role == 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);
+        ((ListModel*)this)->requestLogo(pack.safeName, url);
 
         return icon;
-    }
-    else if(role == Qt::UserRole)
-    {
+    } else if (role == Qt::UserRole) {
         QVariant v;
         v.setValue(pack);
         return v;
@@ -102,7 +89,7 @@ void ListModel::requestFinished()
 
     QJsonParseError parse_error;
     QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
-    if(parse_error.error != QJsonParseError::NoError) {
+    if (parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
         qWarning() << *response;
         return;
@@ -111,26 +98,28 @@ void ListModel::requestFinished()
     QList<ATLauncher::IndexedPack> newList;
 
     auto packs = doc.array();
-    for(auto packRaw : packs) {
+    for (auto packRaw : packs) {
         auto packObj = packRaw.toObject();
 
         ATLauncher::IndexedPack pack;
 
         try {
             ATLauncher::loadIndexedPack(pack, packObj);
-        }
-        catch (const JSONValidationError &e) {
+        } catch (const JSONValidationError& e) {
             qDebug() << QString::fromUtf8(*response);
             qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause();
             return;
         }
 
         // ignore packs without a published version
-        if(pack.versions.length() == 0) continue;
+        if (pack.versions.length() == 0)
+            continue;
         // only display public packs (for now)
-        if(pack.type != ATLauncher::PackType::Public) continue;
+        if (pack.type != ATLauncher::PackType::Public)
+            continue;
         // ignore "system" packs (Vanilla, Vanilla with Forge, etc)
-        if(pack.system) continue;
+        if (pack.system)
+            continue;
 
         newList.append(pack);
     }
@@ -145,14 +134,12 @@ void ListModel::requestFailed(QString reason)
     jobPtr.reset();
 }
 
-void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback)
+void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback)
 {
-    if(m_logoMap.contains(logo))
-    {
-        callback(APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
-    }
-    else
-    {
+    if (m_logoMap.contains(logo)) {
+        callback(
+            APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
+    } else {
         requestLogo(logo, logoUrl);
     }
 }
@@ -168,36 +155,34 @@ void ListModel::logoLoaded(QString logo, QIcon out)
     m_loadingLogos.removeAll(logo);
     m_logoMap.insert(logo, out);
 
-    for(int i = 0; i < modpacks.size(); i++) {
-        if(modpacks[i].safeName == logo) {
-            emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
+    for (int i = 0; i < modpacks.size(); i++) {
+        if (modpacks[i].safeName == logo) {
+            emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
         }
     }
 }
 
 void ListModel::requestLogo(QString file, QString url)
 {
-    if(m_loadingLogos.contains(file) || m_failedLogos.contains(file))
-    {
+    if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) {
         return;
     }
 
     MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0)));
-    NetJob *job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network());
+    auto job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network());
     job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
 
     auto fullPath = entry->getFullPath();
-    QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath]
-    {
+    QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath, job] {
+        job->deleteLater();
         emit logoLoaded(file, QIcon(fullPath));
-        if(waitingCallbacks.contains(file))
-        {
+        if (waitingCallbacks.contains(file)) {
             waitingCallbacks.value(file)(fullPath);
         }
     });
 
-    QObject::connect(job, &NetJob::failed, this, [this, file]
-    {
+    QObject::connect(job, &NetJob::failed, this, [this, file, job] {
+        job->deleteLater();
         emit logoFailed(file);
     });
 
@@ -206,4 +191,4 @@ void ListModel::requestLogo(QString file, QString url)
     m_loadingLogos.append(file);
 }
 
-}
+}  // namespace Atl
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
index 37010b3f..adeb53cb 100644
--- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
+++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
@@ -42,15 +42,15 @@
 class AtlUserInteractionSupportImpl : public QObject, public ATLauncher::UserInteractionSupport {
     Q_OBJECT
 
-public:
+   public:
     AtlUserInteractionSupportImpl(QWidget* parent);
+    virtual ~AtlUserInteractionSupportImpl() = default;
 
-private:
+   private:
     QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) override;
     std::optional<QVector<QString>> chooseOptionalMods(ATLauncher::PackVersion version, QVector<ATLauncher::VersionMod> mods) override;
     void displayMessage(QString message) override;
 
-private:
+   private:
     QWidget* m_parent;
-
 };
diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
index 2343b79f..a3e29201 100644
--- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
+++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
@@ -35,14 +35,15 @@
 
 #include "ListModel.h"
 #include "Application.h"
+#include "QObjectPtr.h"
 #include "net/HttpMetaCache.h"
 #include "net/NetJob.h"
 
-#include "StringUtils.h"
 #include <Version.h>
+#include "StringUtils.h"
 
-#include <QtMath>
 #include <QLabel>
+#include <QtMath>
 
 #include <RWStorage.h>
 
@@ -50,33 +51,33 @@
 
 namespace LegacyFTB {
 
-FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent)
+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
+bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
 {
     Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<Modpack>();
     Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<Modpack>();
 
-    if(currentSorting == Sorting::ByGameVersion) {
+    if (currentSorting == Sorting::ByGameVersion) {
         Version lv(leftPack.mcVersion);
         Version rv(rightPack.mcVersion);
         return lv < rv;
 
-    } else if(currentSorting == Sorting::ByName) {
+    } else if (currentSorting == Sorting::ByName) {
         return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0;
     }
 
-    //UHM, some inavlid value set?!
+    // UHM, some inavlid value set?!
     qWarning() << "Invalid sorting set!";
     return true;
 }
 
-bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
 {
     return true;
 }
@@ -102,18 +103,13 @@ FilterModel::Sorting FilterModel::getCurrentSorting()
     return currentSorting;
 }
 
-ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
-{
-}
+ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
 
-ListModel::~ListModel()
-{
-}
+ListModel::~ListModel() {}
 
 QString ListModel::translatePackType(PackType type) const
 {
-    switch(type)
-    {
+    switch (type) {
         case PackType::Public:
             return tr("Public Modpack");
         case PackType::ThirdParty:
@@ -125,67 +121,51 @@ QString ListModel::translatePackType(PackType type) const
     return QString();
 }
 
-int ListModel::rowCount(const QModelIndex &parent) const
+int ListModel::rowCount(const QModelIndex& parent) const
 {
     return parent.isValid() ? 0 : modpacks.size();
 }
 
-int ListModel::columnCount(const QModelIndex &parent) const
+int ListModel::columnCount(const QModelIndex& parent) const
 {
     return parent.isValid() ? 0 : 1;
 }
 
-QVariant ListModel::data(const QModelIndex &index, int role) const
+QVariant ListModel::data(const QModelIndex& index, int role) const
 {
     int pos = index.row();
-    if(pos >= modpacks.size() || pos < 0 || !index.isValid())
-    {
+    if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
         return QString("INVALID INDEX %1").arg(pos);
     }
 
     Modpack pack = modpacks.at(pos);
-    if(role == Qt::DisplayRole)
-    {
+    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
+    } 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("<br>")).left(edit.lastIndexOf(" ")).append("...");
             return edit;
-
         }
         return pack.description;
-    }
-    else if(role == Qt::DecorationRole)
-    {
-        if(m_logoMap.contains(pack.logo))
-        {
+    } else if (role == 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);
+        ((ListModel*)this)->requestLogo(pack.logo);
         return icon;
-    }
-    else if(role == Qt::ForegroundRole)
-    {
-        if(pack.broken)
-        {
-            //FIXME: Hardcoded color
+    } 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
+        } else if (pack.bugged) {
+            // FIXME: Hardcoded color
+            // bugged pack, currently only indicates bugged xml
             return QColor(244, 229, 66);
         }
-    }
-    else if(role == Qt::UserRole)
-    {
+    } else if (role == Qt::UserRole) {
         QVariant v;
         v.setValue(pack);
         return v;
@@ -222,8 +202,7 @@ Modpack ListModel::at(int row)
 
 void ListModel::remove(int row)
 {
-    if(row < 0 || row >= modpacks.size())
-    {
+    if (row < 0 || row >= modpacks.size()) {
         qWarning() << "Attempt to remove FTB modpacks with invalid row" << row;
         return;
     }
@@ -247,27 +226,25 @@ void ListModel::logoFailed(QString logo)
 
 void ListModel::requestLogo(QString file)
 {
-    if(m_loadingLogos.contains(file) || m_failedLogos.contains(file))
-    {
+    if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) {
         return;
     }
 
     MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0)));
-    NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network());
+    NetJob* job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network());
     job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry));
 
     auto fullPath = entry->getFullPath();
-    QObject::connect(job, &NetJob::finished, this, [this, file, fullPath]
-    {
+    QObject::connect(job, &NetJob::finished, this, [this, file, fullPath, job] {
+        job->deleteLater();
         emit logoLoaded(file, QIcon(fullPath));
-        if(waitingCallbacks.contains(file))
-        {
+        if (waitingCallbacks.contains(file)) {
             waitingCallbacks.value(file)(fullPath);
         }
     });
 
-    QObject::connect(job, &NetJob::failed, this, [this, file]
-    {
+    QObject::connect(job, &NetJob::failed, this, [this, file, job] {
+        job->deleteLater();
         emit logoFailed(file);
     });
 
@@ -276,21 +253,18 @@ void ListModel::requestLogo(QString file)
     m_loadingLogos.append(file);
 }
 
-void ListModel::getLogo(const QString &logo, LogoCallback callback)
+void ListModel::getLogo(const QString& logo, LogoCallback callback)
 {
-    if(m_logoMap.contains(logo))
-    {
+    if (m_logoMap.contains(logo)) {
         callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
-    }
-    else
-    {
+    } else {
         requestLogo(logo);
     }
 }
 
-Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
+Qt::ItemFlags ListModel::flags(const QModelIndex& index) const
 {
     return QAbstractListModel::flags(index);
 }
 
-}
+}  // namespace LegacyFTB
diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp
index 7975fd58..f08eb289 100644
--- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp
+++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp
@@ -40,39 +40,28 @@
 
 #include <QIcon>
 
-Technic::ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
-{
-}
+Technic::ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
 
-Technic::ListModel::~ListModel()
-{
-}
+Technic::ListModel::~ListModel() {}
 
 QVariant Technic::ListModel::data(const QModelIndex& index, int role) const
 {
     int pos = index.row();
-    if(pos >= modpacks.size() || pos < 0 || !index.isValid())
-    {
+    if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
         return QString("INVALID INDEX %1").arg(pos);
     }
 
     Modpack pack = modpacks.at(pos);
-    if(role == Qt::DisplayRole)
-    {
+    if (role == Qt::DisplayRole) {
         return pack.name;
-    }
-    else if(role == Qt::DecorationRole)
-    {
-        if(m_logoMap.contains(pack.logoName))
-        {
+    } else if (role == 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);
+        ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl);
         return icon;
-    }
-    else if(role == Qt::UserRole)
-    {
+    } else if (role == Qt::UserRole) {
         QVariant v;
         v.setValue(pack);
         return v;
@@ -92,16 +81,15 @@ int Technic::ListModel::rowCount(const QModelIndex& parent) const
 
 void Technic::ListModel::searchWithTerm(const QString& term)
 {
-    if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) {
+    if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) {
         return;
     }
     currentSearchTerm = term;
-    if(jobPtr) {
+    if (jobPtr) {
         jobPtr->abort();
         searchState = ResetRequested;
         return;
-    }
-    else {
+    } else {
         beginResetModel();
         modpacks.clear();
         endResetModel();
@@ -115,23 +103,17 @@ void Technic::ListModel::performSearch()
     auto netJob = makeShared<NetJob>("Technic::Search", APPLICATION->network());
     QString searchUrl = "";
     if (currentSearchTerm.isEmpty()) {
-        searchUrl = QString("%1trending?build=%2")
-                .arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD);
+        searchUrl = QString("%1trending?build=%2").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD);
         searchMode = List;
-    }
-    else if (currentSearchTerm.startsWith("http://api.technicpack.net/modpack/")) {
-        searchUrl = QString("https://%1?build=%2")
-                .arg(currentSearchTerm.mid(7), BuildConfig.TECHNIC_API_BUILD);
+    } else if (currentSearchTerm.startsWith("http://api.technicpack.net/modpack/")) {
+        searchUrl = QString("https://%1?build=%2").arg(currentSearchTerm.mid(7), BuildConfig.TECHNIC_API_BUILD);
         searchMode = Single;
-    }
-    else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) {
+    } else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) {
         searchUrl = QString("%1?build=%2").arg(currentSearchTerm, 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);
+    } else {
+        searchUrl =
+            QString("%1search?build=%2&q=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm);
         searchMode = List;
     }
     netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
@@ -161,7 +143,7 @@ void Technic::ListModel::searchRequestFinished()
         switch (searchMode) {
             case List: {
                 auto objs = Json::requireArray(root, "modpacks");
-                for (auto technicPack: objs) {
+                for (auto technicPack : objs) {
                     Modpack pack;
                     auto technicPackObject = Json::requireObject(technicPack);
                     pack.name = Json::requireString(technicPackObject, "name");
@@ -170,11 +152,10 @@ void Technic::ListModel::searchRequestFinished()
                         continue;
 
                     auto rawURL = Json::ensureString(technicPackObject, "iconUrl", "null");
-                    if(rawURL == "null") {
+                    if (rawURL == "null") {
                         pack.logoUrl = "null";
                         pack.logoName = "null";
-                    }
-                    else {
+                    } else {
                         pack.logoUrl = rawURL;
                         pack.logoName = rawURL.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0);
                     }
@@ -199,8 +180,7 @@ void Technic::ListModel::searchRequestFinished()
 
                     pack.logoUrl = iconUrl;
                     pack.logoName = iconUrl.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0);
-                }
-                else {
+                } else {
                     pack.logoUrl = "null";
                     pack.logoName = "null";
                 }
@@ -210,10 +190,8 @@ void Technic::ListModel::searchRequestFinished()
                 break;
             }
         }
-    }
-    catch (const JSONValidationError &err)
-    {
-        qCritical() << "Couldn't parse technic search results:" << err.cause() ;
+    } catch (const JSONValidationError& err) {
+        qCritical() << "Couldn't parse technic search results:" << err.cause();
         return;
     }
     searchState = Finished;
@@ -229,12 +207,9 @@ void Technic::ListModel::searchRequestFinished()
 
 void Technic::ListModel::getLogo(const QString& logo, const QString& logoUrl, Technic::LogoCallback callback)
 {
-    if(m_logoMap.contains(logo))
-    {
+    if (m_logoMap.contains(logo)) {
         callback(APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo))->getFullPath());
-    }
-    else
-    {
+    } else {
         requestLogo(logo, logoUrl);
     }
 }
@@ -243,30 +218,24 @@ void Technic::ListModel::searchRequestFailed()
 {
     jobPtr.reset();
 
-    if(searchState == ResetRequested)
-    {
+    if (searchState == ResetRequested) {
         beginResetModel();
         modpacks.clear();
         endResetModel();
 
         performSearch();
-    }
-    else
-    {
+    } else {
         searchState = Finished;
     }
 }
 
-
 void Technic::ListModel::logoLoaded(QString logo, QString out)
 {
     m_loadingLogos.removeAll(logo);
     m_logoMap.insert(logo, QIcon(out));
-    for(int i = 0; i < modpacks.size(); i++)
-    {
-        if(modpacks[i].logoName == logo)
-        {
-            emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
+    for (int i = 0; i < modpacks.size(); i++) {
+        if (modpacks[i].logoName == logo) {
+            emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
         }
     }
 }
@@ -279,24 +248,23 @@ void Technic::ListModel::logoFailed(QString logo)
 
 void Technic::ListModel::requestLogo(QString logo, QString url)
 {
-    if(m_loadingLogos.contains(logo) || m_failedLogos.contains(logo) || logo == "null")
-    {
+    if (m_loadingLogos.contains(logo) || m_failedLogos.contains(logo) || logo == "null") {
         return;
     }
 
     MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo));
-    NetJob *job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network());
+    auto job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network());
     job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
 
     auto fullPath = entry->getFullPath();
 
-    QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath]
-    {
+    QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] {
+        job->deleteLater();
         logoLoaded(logo, fullPath);
     });
 
-    QObject::connect(job, &NetJob::failed, this, [this, logo]
-    {
+    QObject::connect(job, &NetJob::failed, this, [this, logo, job] {
+        job->deleteLater();
         logoFailed(logo);
     });
 
-- 
cgit 


From 4e66f55d8426559942d92e61556747528be03cdf Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 18 Jun 2023 23:32:17 +0300
Subject: Removed extra headers

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/helpers/HashUtils.h               | 1 -
 launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp | 1 -
 2 files changed, 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/helpers/HashUtils.h b/launcher/modplatform/helpers/HashUtils.h
index f3b9e030..a541ae8f 100644
--- a/launcher/modplatform/helpers/HashUtils.h
+++ b/launcher/modplatform/helpers/HashUtils.h
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <qtmetamacros.h>
 #include <QString>
 
 #include "modplatform/ModIndex.h"
diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
index a3e29201..330dd4fb 100644
--- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
+++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
@@ -35,7 +35,6 @@
 
 #include "ListModel.h"
 #include "Application.h"
-#include "QObjectPtr.h"
 #include "net/HttpMetaCache.h"
 #include "net/NetJob.h"
 
-- 
cgit 


From 1bdde1f947f57801f2fcb1a0f881f19bd8e1e29d Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 00:36:37 +0300
Subject: Small fixes

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 61 ++++++++++++----------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  2 +-
 launcher/modplatform/ModIndex.h                    |  2 +-
 launcher/modplatform/ResourceAPI.h                 |  8 ---
 launcher/modplatform/flame/FlameModIndex.cpp       | 12 +++--
 .../modplatform/modrinth/ModrinthPackIndex.cpp     | 10 ++--
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     | 10 ++--
 7 files changed, 54 insertions(+), 51 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index bd80a661..54116e28 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -33,7 +33,7 @@
 #include "ui/pages/modplatform/flame/FlameResourceModels.h"
 #include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h"
 
-static Version mcVersions(BaseInstance* inst)
+static Version mcVersion(BaseInstance* inst)
 {
     return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion();
 }
@@ -53,7 +53,7 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
                         std::make_shared<FlameAPI>() }
     , m_modrinth_provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared<ResourceDownload::ModrinthModModel>(*instance),
                            std::make_shared<ModrinthAPI>() }
-    , m_version(mcVersions(instance))
+    , m_version(mcVersion(instance))
     , m_loaderType(mcLoaders(instance))
 {
     for (auto mod : folder->allMods())
@@ -74,33 +74,38 @@ void GetModDependenciesTask::prepare()
 QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version,
                                                                                  const ModPlatform::ResourceProvider providerName)
 {
-    auto c_dependencies = QList<ModPlatform::Dependency>();
+    QList<ModPlatform::Dependency> c_dependencies;
     for (auto ver_dep : version.dependencies) {
-        if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
-            if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                        [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; });
-                dep == c_dependencies.end()) {  // check the current dependency list
-                if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
-                                            [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
-                                                return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
-                                            });
-                    dep == m_selected.end()) {  // check the selected versions
-                    if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
-                                                [&ver_dep, providerName](std::shared_ptr<Metadata::ModStruct> i) {
-                                                    return i->project_id == ver_dep.addonId && i->provider == providerName;
-                                                });
-                        dep == m_mods.end()) {  // check the existing mods
-                        if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(),
-                                                    [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
-                                                        return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
-                                                    });
-                            dep == m_pack_dependencies.end()) {  // check loaded dependencies
-                            c_dependencies.append(ver_dep);
-                        }
-                    }
-                }
-            }
-        }
+        if (ver_dep.type != ModPlatform::DependencyType::REQUIRED)
+            continue;
+
+        if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
+                                    [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; });
+            dep != c_dependencies.end())
+            continue;  // check the current dependency list
+
+        if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
+                                    [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
+                                        return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
+                                    });
+            dep != m_selected.end())
+            continue;  // check the selected versions
+
+        if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
+                                    [&ver_dep, providerName](std::shared_ptr<Metadata::ModStruct> i) {
+                                        return i->project_id == ver_dep.addonId && i->provider == providerName;
+                                    });
+            dep != m_mods.end())
+            continue;  // check the existing mods
+
+        if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(),
+                                    [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
+                                        return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
+                                    });
+            dep != m_pack_dependencies.end())  // check loaded dependencies
+            continue;
+
+        c_dependencies.append(ver_dep);
     }
     return c_dependencies;
 };
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 3824e781..99d5afb0 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -42,7 +42,7 @@ class GetModDependenciesTask : public SequentialTask {
         ModPlatform::Dependency dependency;
         ModPlatform::IndexedPack::Ptr pack;
         ModPlatform::IndexedVersion version;
-        PackDependency(){};
+        PackDependency() = default;
         PackDependency(const ModPlatform::IndexedPack::Ptr p, const ModPlatform::IndexedVersion& v)
         {
             pack = p;
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 64b44055..7236e63e 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -34,7 +34,7 @@ enum class ResourceProvider { MODRINTH, FLAME };
 
 enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK };
 
-enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE };
+enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN };
 
 class ProviderCapabilities {
    public:
diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h
index c23444b3..63b917f1 100644
--- a/launcher/modplatform/ResourceAPI.h
+++ b/launcher/modplatform/ResourceAPI.h
@@ -115,14 +115,6 @@ class ResourceAPI {
         ModPlatform::Dependency dependency;
         Version mcVersion;
         ModLoaderTypes loader;
-
-        DependencySearchArgs(DependencySearchArgs const&) = default;
-        void operator=(DependencySearchArgs other)
-        {
-            dependency = other.dependency;
-            mcVersion = other.mcVersion;
-            loader = other.loader;
-        }
     };
 
     struct DependencySearchCallbacks {
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
index 120bfc91..9c8eb832 100644
--- a/launcher/modplatform/flame/FlameModIndex.cpp
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -160,6 +160,10 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
             case 6:  // Include
                 dependency.type = ModPlatform::DependencyType::INCLUDE;
                 break;
+                default:
+                dependency.type = ModPlatform::DependencyType::UNKNOWN;
+                break;
+                
         }
         file.dependencies.append(dependency);
     }
@@ -172,7 +176,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
 
 ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr)
 {
-    QVector<ModPlatform::IndexedVersion> unsortedVersions;
+    QVector<ModPlatform::IndexedVersion> versions;
     for (auto versionIter : arr) {
         auto obj = versionIter.toObject();
 
@@ -181,13 +185,13 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::
             file.addonId = m.addonId;
 
         if (file.fileId.isValid())  // Heuristic to check if the returned value is valid
-            unsortedVersions.append(file);
+            versions.append(file);
     }
 
     auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
         // dates are in RFC 3339 format
         return a.date > b.date;
     };
-    std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
-    return unsortedVersions.front();
+    std::sort(versions.begin(), versions.end(), orderSortPredicate);
+    return versions.front();
 };
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index 879260a3..92b48e5f 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -156,6 +156,8 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
             dependency.type = ModPlatform::DependencyType::INCOMPATIBLE;
         else if (depType == "embedded")
             dependency.type = ModPlatform::DependencyType::EMBEDDED;
+        else
+            dependency.type = ModPlatform::DependencyType::UNKNOWN;
 
         file.dependencies.append(dependency);
     }
@@ -218,19 +220,19 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
 
 auto Modrinth::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
 {
-    QVector<ModPlatform::IndexedVersion> unsortedVersions;
+    QVector<ModPlatform::IndexedVersion> versions;
 
     for (auto versionIter : arr) {
         auto obj = versionIter.toObject();
         auto file = loadIndexedPackVersion(obj);
 
         if (file.fileId.isValid())  // Heuristic to check if the returned value is valid
-            unsortedVersions.append(file);
+            versions.append(file);
     }
     auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
         // dates are in RFC 3339 format
         return a.date > b.date;
     };
-    std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
-    return unsortedVersions.length() != 0 ? unsortedVersions.front() : ModPlatform::IndexedVersion();
+    std::sort(versions.begin(), versions.end(), orderSortPredicate);
+    return versions.length() != 0 ? versions.front() : ModPlatform::IndexedVersion();
 }
\ No newline at end of file
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index 819cf7de..c7d9da4e 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -125,7 +125,7 @@ void ResourceDownloadDialog::connectButtons()
 
 static ModPlatform::ProviderCapabilities ProviderCaps;
 
-QStringList getReqiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, QVariant addonId)
+QStringList getRequiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, QVariant addonId)
 {
     auto req = QStringList();
     for (auto& task : tasks) {
@@ -167,10 +167,10 @@ void ResourceDownloadDialog::confirm()
         if (ret == QDialog::DialogCode::Rejected) {
             QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection);
             return;
-        } else
-            for (auto dep : task->getDependecies()) {
+        } else {
+            for (auto dep : task->getDependecies())
                 addResource(dep->pack, dep->version);
-            }
+        }
     }
 
     auto selected = getTasks();
@@ -179,7 +179,7 @@ void ResourceDownloadDialog::confirm()
     });
     for (auto& task : selected) {
         confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(),
-                                         ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack()->addonId) });
+                                         ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task->getPack()->addonId) });
     }
 
     if (confirm_dialog->exec()) {
-- 
cgit 


From 3ee0fec7298d467d5b8b48a5144794f58bc2ce28 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 12:22:22 +0300
Subject: Removed mods from lambda

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/instance/ModFolderPage.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp
index 1d090ef4..90e7d0d6 100644
--- a/launcher/ui/pages/instance/ModFolderPage.cpp
+++ b/launcher/ui/pages/instance/ModFolderPage.cpp
@@ -100,7 +100,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel>
                 [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
 
         connect(mods.get(), &ModFolderModel::updateFinished, this,
-                [this, check_allow_update, mods] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
+                [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
 
         connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged);
         ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning());
-- 
cgit 


From d02858040ef0d1f691b3456bb0ac271c484a7c57 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 13:09:37 +0300
Subject: Fixes #1212

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/pages/modplatform/ModPage.cpp      | 16 ++++++-------
 launcher/ui/pages/modplatform/ResourcePage.cpp | 31 +++++++++++++++-----------
 2 files changed, 25 insertions(+), 22 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp
index 95064d16..60a43128 100644
--- a/launcher/ui/pages/modplatform/ModPage.cpp
+++ b/launcher/ui/pages/modplatform/ModPage.cpp
@@ -89,17 +89,13 @@ void ModPage::filterMods()
 
 void ModPage::triggerSearch()
 {
-    auto changed = m_filter_widget->changed();
     m_filter = m_filter_widget->getFilter();
+    m_ui->packView->clearSelection();
+    m_ui->packDescription->clear();
+    m_ui->versionSelectionBox->clear();
+    updateSelectionButton();
 
-    if (changed) {
-        m_ui->packView->clearSelection();
-        m_ui->packDescription->clear();
-        m_ui->versionSelectionBox->clear();
-        updateSelectionButton();
-    }
-
-    static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), changed);
+    static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), m_filter_widget->changed());
     m_fetch_progress.watch(m_model->activeSearchJob().get());
 }
 
@@ -122,6 +118,8 @@ void ModPage::updateVersionList()
     QString mcVersion = packProfile->getComponentVersion("net.minecraft");
 
     auto current_pack = getCurrentPack();
+    if (!current_pack)
+        return;
     for (int i = 0; i < current_pack->versions.size(); i++) {
         auto version = current_pack->versions[i];
         bool valid = false;
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index 1d2509d8..aab2ee89 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -174,7 +174,11 @@ ModPlatform::IndexedPack::Ptr ResourcePage::getCurrentPack() const
 void ResourcePage::updateUi()
 {
     auto current_pack = getCurrentPack();
-
+    if (!current_pack) {
+        m_ui->packDescription->setHtml({});
+        m_ui->packDescription->flush();
+        return;
+    }
     QString text = "";
     QString name = current_pack->name;
 
@@ -240,8 +244,8 @@ void ResourcePage::updateSelectionButton()
     }
 
     m_ui->resourceSelectionButton->setEnabled(true);
-    if (getCurrentPack()) {
-        if (!getCurrentPack()->isVersionSelected(m_selected_version_index))
+    if (auto current_pack = getCurrentPack(); current_pack) {
+        if (!current_pack->isVersionSelected(m_selected_version_index))
             m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString()));
         else
             m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString()));
@@ -258,13 +262,14 @@ void ResourcePage::updateVersionList()
     m_ui->versionSelectionBox->clear();
     m_ui->versionSelectionBox->blockSignals(false);
 
-    for (int i = 0; i < current_pack->versions.size(); i++) {
-        auto& version = current_pack->versions[i];
-        if (optedOut(version))
-            continue;
+    if (current_pack)
+        for (int i = 0; i < current_pack->versions.size(); i++) {
+            auto& version = current_pack->versions[i];
+            if (optedOut(version))
+                continue;
 
-        m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i));
-    }
+            m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i));
+        }
 
     if (m_ui->versionSelectionBox->count() == 0) {
         m_ui->versionSelectionBox->addItem(tr("No valid version found."), QVariant(-1));
@@ -283,7 +288,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
     auto current_pack = getCurrentPack();
 
     bool request_load = false;
-    if (!current_pack->versionsLoaded) {
+    if (!current_pack || !current_pack->versionsLoaded) {
         m_ui->resourceSelectionButton->setText(tr("Loading versions..."));
         m_ui->resourceSelectionButton->setEnabled(false);
 
@@ -292,7 +297,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
         updateVersionList();
     }
 
-    if (!current_pack->extraDataLoaded)
+    if (current_pack && !current_pack->extraDataLoaded)
         request_load = true;
 
     if (request_load)
@@ -340,7 +345,7 @@ void ResourcePage::onResourceSelected()
         return;
 
     auto current_pack = getCurrentPack();
-    if (!current_pack->versionsLoaded)
+    if (!current_pack || !current_pack->versionsLoaded)
         return;
 
     auto& version = current_pack->versions[m_selected_version_index];
@@ -386,7 +391,7 @@ void ResourcePage::openUrl(const QUrl& url)
         const QString slug = match.captured(1);
 
         // ensure the user isn't opening the same mod
-        if (slug != getCurrentPack()->slug) {
+        if (auto current_pack = getCurrentPack(); current_pack && slug != current_pack->slug) {
             m_parent_dialog->selectPage(page);
 
             auto newPage = m_parent_dialog->getSelectedPage();
-- 
cgit 


From 8ad9692daab303bba6f5337f6660d8437ec8f330 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 14:10:29 +0300
Subject: Changed qWarning to qDebug for raw data

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 54116e28..274ff3c9 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -132,7 +132,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
         if (parse_error.error != QJsonParseError::NoError) {
             qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset
                        << " reason: " << parse_error.errorString();
-            qWarning() << *responseInfo;
+            qDebug() << *responseInfo;
             return;
         }
         try {
-- 
cgit 


From 6fd729e285f67c74633d27575717070f3577a132 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 17:42:16 +0300
Subject: Fixed regresion regarding modrinth project_id in dependence array

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 63 ++++++++++++++--------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  1 +
 .../modplatform/modrinth/ModrinthPackIndex.cpp     |  2 +-
 launcher/ui/dialogs/ResourceDownloadDialog.cpp     | 16 ++++--
 4 files changed, 55 insertions(+), 27 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 274ff3c9..02281a35 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -79,28 +79,34 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
         if (ver_dep.type != ModPlatform::DependencyType::REQUIRED)
             continue;
 
+        auto isOnlyVersion = providerName == ModPlatform::ResourceProvider::MODRINTH && ver_dep.addonId.toString().isEmpty();
         if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                    [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; });
+                                    [&ver_dep, isOnlyVersion](const ModPlatform::Dependency& i) {
+                                        return isOnlyVersion ? i.version == ver_dep.version : i.addonId == ver_dep.addonId;
+                                    });
             dep != c_dependencies.end())
             continue;  // check the current dependency list
 
         if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
-                                    [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
-                                        return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
+                                    [&ver_dep, providerName, isOnlyVersion](std::shared_ptr<PackDependency> i) {
+                                        return i->pack->provider == providerName && (isOnlyVersion ? i->version.version == ver_dep.version
+                                                                                                   : i->pack->addonId == ver_dep.addonId);
                                     });
             dep != m_selected.end())
             continue;  // check the selected versions
 
         if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
-                                    [&ver_dep, providerName](std::shared_ptr<Metadata::ModStruct> i) {
-                                        return i->project_id == ver_dep.addonId && i->provider == providerName;
+                                    [&ver_dep, providerName, isOnlyVersion](std::shared_ptr<Metadata::ModStruct> i) {
+                                        return i->provider == providerName &&
+                                               (isOnlyVersion ? i->file_id == ver_dep.version : i->project_id == ver_dep.addonId);
                                     });
             dep != m_mods.end())
             continue;  // check the existing mods
 
         if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(),
-                                    [&ver_dep, providerName](std::shared_ptr<PackDependency> i) {
-                                        return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName;
+                                    [&ver_dep, providerName, isOnlyVersion](std::shared_ptr<PackDependency> i) {
+                                        return i->pack->provider == providerName && (isOnlyVersion ? i->version.version == ver_dep.addonId
+                                                                                                   : i->pack->addonId == ver_dep.addonId);
                                     });
             dep != m_pack_dependencies.end())  // check loaded dependencies
             continue;
@@ -110,22 +116,11 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
     return c_dependencies;
 };
 
-Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep,
-                                                        const ModPlatform::ResourceProvider providerName,
-                                                        int level)
+Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr<PackDependency> pDep)
 {
-    auto pDep = std::make_shared<PackDependency>();
-    pDep->dependency = dep;
-    pDep->pack = std::make_shared<ModPlatform::IndexedPack>();
-    pDep->pack->addonId = dep.addonId;
-    pDep->pack->provider = providerName;
-    m_pack_dependencies.append(pDep);
-    auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
-
-    auto tasks = makeShared<SequentialTask>(this, QString("DependencyInfo: %1").arg(dep.addonId.toString()));
-
+    auto provider = pDep->pack->provider == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
     auto responseInfo = new QByteArray();
-    auto info = provider.api->getProject(dep.addonId.toString(), responseInfo);
+    auto info = provider.api->getProject(pDep->pack->addonId.toString(), responseInfo);
     QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] {
         QJsonParseError parse_error{};
         QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error);
@@ -144,7 +139,27 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             qWarning() << "Error while reading mod info: " << e.cause();
         }
     });
-    tasks->addTask(info);
+    return info;
+}
+
+Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep,
+                                                        const ModPlatform::ResourceProvider providerName,
+                                                        int level)
+{
+    auto pDep = std::make_shared<PackDependency>();
+    pDep->dependency = dep;
+    pDep->pack = std::make_shared<ModPlatform::IndexedPack>();
+    pDep->pack->addonId = dep.addonId;
+    pDep->pack->provider = providerName;
+    m_pack_dependencies.append(pDep);
+    auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
+
+    auto tasks = makeShared<SequentialTask>(
+        this, QString("DependencyInfo: %1").arg(dep.addonId.toString().isEmpty() ? dep.version : dep.addonId.toString()));
+
+    if (!dep.addonId.toString().isEmpty()) {
+        tasks->addTask(getProjectInfoTask(pDep));
+    }
 
     ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
     ResourceAPI::DependencySearchCallbacks callbacks;
@@ -176,6 +191,10 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             qWarning() << "Dependency cycle exeeded";
             return;
         }
+        if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) {
+            pDep->pack->addonId = pDep->version.addonId;
+            addTask(getProjectInfoTask(pDep));
+        }
         for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) {
             addTask(prepareDependencyTask(dep, provider.name, level - 1));
         }
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 99d5afb0..f1876c61 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -68,6 +68,7 @@ class GetModDependenciesTask : public SequentialTask {
     QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&,
                                                              const ModPlatform::ResourceProvider providerName);
     void prepare();
+    Task::Ptr getProjectInfoTask(std::shared_ptr<PackDependency> pDep);
 
    private:
     QList<std::shared_ptr<PackDependency>> m_pack_dependencies;
diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
index 92b48e5f..b4037349 100644
--- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp
@@ -144,7 +144,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
     for (auto d : dependencies) {
         auto dep = Json::ensureObject(d);
         ModPlatform::Dependency dependency;
-        dependency.addonId = Json::requireString(dep, "project_id");
+        dependency.addonId = Json::ensureString(dep, "project_id");
         dependency.version = Json::ensureString(dep, "version_id");
         auto depType = Json::requireString(dep, "dependency_type");
 
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index c7d9da4e..4f59f560 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -125,14 +125,22 @@ void ResourceDownloadDialog::connectButtons()
 
 static ModPlatform::ProviderCapabilities ProviderCaps;
 
-QStringList getRequiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, QVariant addonId)
+QStringList getRequiredBy(QList<ResourceDownloadDialog::DownloadTaskPtr> tasks, ResourceDownloadDialog::DownloadTaskPtr pack)
 {
+    auto addonId = pack->getPack()->addonId;
+    auto provider = pack->getPack()->provider;
+    auto version = pack->getVersionID();
     auto req = QStringList();
     for (auto& task : tasks) {
+        if (provider != task->getPack()->provider)
+            continue;
         auto deps = task->getVersion().dependencies;
         if (auto dep = std::find_if(deps.begin(), deps.end(),
-                                    [addonId](const ModPlatform::Dependency& d) {
-                                        return d.addonId == addonId && d.type == ModPlatform::DependencyType::REQUIRED;
+                                    [addonId, provider, version](const ModPlatform::Dependency& d) {
+                                        return d.type == ModPlatform::DependencyType::REQUIRED &&
+                                               (provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty()
+                                                    ? version == d.version
+                                                    : d.addonId == addonId);
                                     });
             dep != deps.end()) {
             req.append(task->getName());
@@ -179,7 +187,7 @@ void ResourceDownloadDialog::confirm()
     });
     for (auto& task : selected) {
         confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(),
-                                         ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task->getPack()->addonId) });
+                                         ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task) });
     }
 
     if (confirm_dialog->exec()) {
-- 
cgit 


From c13a90540cf782debddd63f1d2da46e43ed48c7a Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 21:20:35 +0300
Subject: Added overide for Quilt/Fabric

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 28 +++++++++++++++++--
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  1 +
 launcher/modplatform/ModIndex.h                    | 16 +++++++++++
 launcher/modplatform/flame/FlameAPI.h              | 32 +++++++++++++++++++---
 4 files changed, 71 insertions(+), 6 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 02281a35..093304b3 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -25,11 +25,13 @@
 #include "QObjectPtr.h"
 #include "minecraft/mod/MetadataHandler.h"
 #include "modplatform/ModIndex.h"
+#include "modplatform/ResourceAPI.h"
 #include "modplatform/flame/FlameAPI.h"
 #include "modplatform/modrinth/ModrinthAPI.h"
 #include "tasks/ConcurrentTask.h"
 #include "tasks/SequentialTask.h"
 #include "ui/pages/modplatform/ModModel.h"
+#include "ui/pages/modplatform/ResourceModel.h"
 #include "ui/pages/modplatform/flame/FlameResourceModels.h"
 #include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h"
 
@@ -71,6 +73,21 @@ void GetModDependenciesTask::prepare()
     }
 }
 
+auto GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName)
+    -> ModPlatform::Dependency
+{
+    if (auto isQuilt = m_loaderType & ResourceAPI::Quilt; isQuilt || m_loaderType & ResourceAPI::Fabric) {
+        auto overide = ModPlatform::getOverrideDeps();
+        auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, providerName, isQuilt](auto o) {
+            return o.provider == providerName && dep.addonId == (isQuilt ? o.fabric : o.quilt);
+        });
+        if (over != overide.cend()) {
+            return { isQuilt ? over->quilt : over->fabric, dep.type };
+        }
+    }
+    return dep;
+}
+
 QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version,
                                                                                  const ModPlatform::ResourceProvider providerName)
 {
@@ -111,7 +128,7 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
             dep != m_pack_dependencies.end())  // check loaded dependencies
             continue;
 
-        c_dependencies.append(ver_dep);
+        c_dependencies.append(getOverride(ver_dep, providerName));
     }
     return c_dependencies;
 };
@@ -151,6 +168,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
     pDep->pack = std::make_shared<ModPlatform::IndexedPack>();
     pDep->pack->addonId = dep.addonId;
     pDep->pack->provider = providerName;
+
     m_pack_dependencies.append(pDep);
     auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
 
@@ -193,7 +211,13 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
         }
         if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) {
             pDep->pack->addonId = pDep->version.addonId;
-            addTask(getProjectInfoTask(pDep));
+            auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name);
+            if (dep.addonId != pDep->version.addonId) {
+                auto toRemoveID = pDep->version.addonId;
+                m_pack_dependencies.removeIf([toRemoveID](auto v) { return v->pack->addonId == toRemoveID; });
+                addTask(prepareDependencyTask(dep, provider.name, level));
+            } else
+                addTask(getProjectInfoTask(pDep));
         }
         for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) {
             addTask(prepareDependencyTask(dep, provider.name, level - 1));
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index f1876c61..7a4990f7 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -69,6 +69,7 @@ class GetModDependenciesTask : public SequentialTask {
                                                              const ModPlatform::ResourceProvider providerName);
     void prepare();
     Task::Ptr getProjectInfoTask(std::shared_ptr<PackDependency> pDep);
+    auto getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName) -> ModPlatform::Dependency;
 
    private:
     QList<std::shared_ptr<PackDependency>> m_pack_dependencies;
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 7236e63e..3b0a03a1 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -129,6 +129,22 @@ struct IndexedPack {
     }
 };
 
+struct OverrideDep {
+    QString quilt;
+    QString fabric;
+    QString slug;
+    ModPlatform::ResourceProvider provider;
+};
+
+inline auto getOverrideDeps() -> QList<OverrideDep>
+{
+    return { { "634179", "306612", "API", ModPlatform::ResourceProvider::FLAME },
+             { "720410", "308769", "KotlinLibraries", ModPlatform::ResourceProvider::FLAME },
+
+             { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH },
+             { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } };
+};
+
 }  // namespace ModPlatform
 
 Q_DECLARE_METATYPE(ModPlatform::IndexedPack)
diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index 4ffc36d2..89561a89 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -4,7 +4,9 @@
 
 #pragma once
 
+#include <algorithm>
 #include "modplatform/ModIndex.h"
+#include "modplatform/ResourceAPI.h"
 #include "modplatform/helpers/NetworkResourceAPI.h"
 
 class FlameAPI : public NetworkResourceAPI {
@@ -74,22 +76,44 @@ class FlameAPI : public NetworkResourceAPI {
 
     [[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override
     {
-        QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString()) };
+        auto mappedModLoader = getMappedModLoader(args.loaders.value());
+        auto addonId = args.pack.addonId.toString();
+        if (args.loaders.value() & Quilt) {
+            auto overide = ModPlatform::getOverrideDeps();
+            auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) {
+                return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt;
+            });
+            if (over != overide.cend()) {
+                mappedModLoader = 5;
+            }
+        }
+        QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(addonId) };
 
         QStringList get_parameters;
         if (args.mcVersions.has_value())
             get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString()));
         if (args.loaders.has_value())
-            get_parameters.append(QString("modLoaderType=%1").arg(getMappedModLoader(args.loaders.value())));
+            get_parameters.append(QString("modLoaderType=%1").arg(mappedModLoader));
 
         return url + get_parameters.join('&');
     };
 
     [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
     {
+        auto mappedModLoader = getMappedModLoader(args.loader);
+        auto addonId = args.dependency.addonId.toString();
+        if (args.loader & Quilt) {
+            auto overide = ModPlatform::getOverrideDeps();
+            auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) {
+                return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt;
+            });
+            if (over != overide.cend()) {
+                mappedModLoader = 5;
+            }
+        }
         return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%3")
-            .arg(args.dependency.addonId.toString())
+            .arg(addonId)
             .arg(args.mcVersion.toString())
-            .arg(getMappedModLoader(args.loader));
+            .arg(mappedModLoader);
     };
 };
-- 
cgit 


From f6f0fbbd9f16afad16b8a401f87d741eba4be677 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 21:23:48 +0300
Subject: Fixed removeIf

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 093304b3..93c7f259 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -214,7 +214,17 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name);
             if (dep.addonId != pDep->version.addonId) {
                 auto toRemoveID = pDep->version.addonId;
-                m_pack_dependencies.removeIf([toRemoveID](auto v) { return v->pack->addonId == toRemoveID; });
+
+                auto pred = [toRemoveID](auto v) { return v->pack->addonId == toRemoveID; };
+#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
+                m_pack_dependencies.removeIf(pred);
+#else
+                for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();)
+                    if (pred(*it))
+                        it = m_pack_dependencies.erase(it);
+                    else
+                        ++it;
+#endif
                 addTask(prepareDependencyTask(dep, provider.name, level));
             } else
                 addTask(getProjectInfoTask(pDep));
-- 
cgit 


From b62e4c0cc79d9d3074b37d879bb00df68c2973bc Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 19 Jun 2023 21:32:19 +0300
Subject: Fixed build

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 6 +++---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.h   | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 93c7f259..00611f32 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -73,8 +73,8 @@ void GetModDependenciesTask::prepare()
     }
 }
 
-auto GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName)
-    -> ModPlatform::Dependency
+ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep,
+                                                            const ModPlatform::ResourceProvider providerName)
 {
     if (auto isQuilt = m_loaderType & ResourceAPI::Quilt; isQuilt || m_loaderType & ResourceAPI::Fabric) {
         auto overide = ModPlatform::getOverrideDeps();
@@ -215,7 +215,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             if (dep.addonId != pDep->version.addonId) {
                 auto toRemoveID = pDep->version.addonId;
 
-                auto pred = [toRemoveID](auto v) { return v->pack->addonId == toRemoveID; };
+                auto pred = [toRemoveID](const std::shared_ptr<PackDependency>& v) { return v->pack->addonId == toRemoveID; };
 #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
                 m_pack_dependencies.removeIf(pred);
 #else
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 7a4990f7..e2ad4825 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -69,7 +69,7 @@ class GetModDependenciesTask : public SequentialTask {
                                                              const ModPlatform::ResourceProvider providerName);
     void prepare();
     Task::Ptr getProjectInfoTask(std::shared_ptr<PackDependency> pDep);
-    auto getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName) -> ModPlatform::Dependency;
+    ModPlatform::Dependency getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName);
 
    private:
     QList<std::shared_ptr<PackDependency>> m_pack_dependencies;
-- 
cgit 


From f769b0b4c63888ac95416a4cc834aad2395f9b74 Mon Sep 17 00:00:00 2001
From: Alfio <tomarchioalfio5@gmail.com>
Date: Tue, 20 Jun 2023 10:25:11 +0200
Subject: Remove inconsistent/unneeded question marks in UI

Signed-off-by: P2 <tomarchioalfio5@gmail.com>
---
 launcher/minecraft/auth/AccountList.cpp            | 6 +++---
 launcher/ui/pages/global/LauncherPage.ui           | 8 ++++----
 launcher/ui/pages/global/MinecraftPage.ui          | 2 +-
 launcher/ui/pages/instance/InstanceSettingsPage.ui | 8 ++++----
 4 files changed, 12 insertions(+), 12 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index 9e2fd111..c2794147 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -333,13 +333,13 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
 
             case MigrationColumn: {
                 if(account->isMSA() || account->isOffline()) {
-                    return tr("N/A", "Can Migrate?");
+                    return tr("N/A", "Can Migrate");
                 }
                 if (account->canMigrate()) {
-                    return tr("Yes", "Can Migrate?");
+                    return tr("Yes", "Can Migrate");
                 }
                 else {
-                    return tr("No", "Can Migrate?");
+                    return tr("No", "Can Migrate");
                 }
             }
 
diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui
index 55bd3eea..d9116bfc 100644
--- a/launcher/ui/pages/global/LauncherPage.ui
+++ b/launcher/ui/pages/global/LauncherPage.ui
@@ -172,7 +172,7 @@
              <string>Disable using metadata provided by mod providers (like Modrinth or Curseforge) for mods.</string>
             </property>
             <property name="text">
-             <string>Disable using metadata for mods?</string>
+             <string>Disable using metadata for mods</string>
             </property>
            </widget>
           </item>
@@ -307,21 +307,21 @@
           <item>
            <widget class="QCheckBox" name="showConsoleCheck">
             <property name="text">
-             <string>Show console while the game is &amp;running?</string>
+             <string>Show console while the game is &amp;running</string>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QCheckBox" name="autoCloseConsoleCheck">
             <property name="text">
-             <string>&amp;Automatically close console when the game quits?</string>
+             <string>&amp;Automatically close console when the game quits</string>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QCheckBox" name="showConsoleErrorCheck">
             <property name="text">
-             <string>Show console when the game &amp;crashes?</string>
+             <string>Show console when the game &amp;crashes</string>
             </property>
            </widget>
           </item>
diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui
index 103881b5..8f5de725 100644
--- a/launcher/ui/pages/global/MinecraftPage.ui
+++ b/launcher/ui/pages/global/MinecraftPage.ui
@@ -51,7 +51,7 @@
           <item>
            <widget class="QCheckBox" name="maximizedCheckBox">
             <property name="text">
-             <string>Start Minecraft &amp;maximized?</string>
+             <string>Start Minecraft &amp;maximized</string>
             </property>
            </widget>
           </item>
diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui
index 19d6dc02..8427965d 100644
--- a/launcher/ui/pages/instance/InstanceSettingsPage.ui
+++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui
@@ -269,7 +269,7 @@
           <item>
            <widget class="QCheckBox" name="maximizedCheckBox">
             <property name="text">
-             <string>Start Minecraft maximized?</string>
+             <string>Start Minecraft maximized</string>
             </property>
            </widget>
           </item>
@@ -341,21 +341,21 @@
           <item>
            <widget class="QCheckBox" name="showConsoleCheck">
             <property name="text">
-             <string>Show console while the game is running?</string>
+             <string>Show console while the game is running</string>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QCheckBox" name="autoCloseConsoleCheck">
             <property name="text">
-             <string>Automatically close console when the game quits?</string>
+             <string>Automatically close console when the game quits</string>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QCheckBox" name="showConsoleErrorCheck">
             <property name="text">
-             <string>Show console when the game crashes?</string>
+             <string>Show console when the game crashes</string>
             </property>
            </widget>
           </item>
-- 
cgit 


From 3e3be9ae6f902cc292ee26e4d330b078ddbb2a46 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Tue, 20 Jun 2023 13:28:57 +0300
Subject: Added fallback for quilt if the API or Kotilin is not present

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 38 ++++++++++++++--------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  1 +
 2 files changed, 26 insertions(+), 13 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 00611f32..ebc9cf40 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -31,7 +31,6 @@
 #include "tasks/ConcurrentTask.h"
 #include "tasks/SequentialTask.h"
 #include "ui/pages/modplatform/ModModel.h"
-#include "ui/pages/modplatform/ResourceModel.h"
 #include "ui/pages/modplatform/flame/FlameResourceModels.h"
 #include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h"
 
@@ -192,6 +191,16 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             }
             pDep->version = provider.mod->loadDependencyVersions(dep, arr);
             if (!pDep->version.addonId.isValid()) {
+                if (m_loaderType & ResourceAPI::Quilt) {  // falback for quilt
+                    auto overide = ModPlatform::getOverrideDeps();
+                    auto over = std::find_if(overide.cbegin(), overide.cend(),
+                                             [dep, provider](auto o) { return o.provider == provider.name && dep.addonId == o.quilt; });
+                    if (over != overide.cend()) {
+                        removePack(dep.addonId);
+                        addTask(prepareDependencyTask({ over->fabric, dep.type }, provider.name, level));
+                        return;
+                    }
+                }
                 qWarning() << "Error while reading mod version empty ";
                 qDebug() << doc;
                 return;
@@ -213,18 +222,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
             pDep->pack->addonId = pDep->version.addonId;
             auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name);
             if (dep.addonId != pDep->version.addonId) {
-                auto toRemoveID = pDep->version.addonId;
-
-                auto pred = [toRemoveID](const std::shared_ptr<PackDependency>& v) { return v->pack->addonId == toRemoveID; };
-#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
-                m_pack_dependencies.removeIf(pred);
-#else
-                for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();)
-                    if (pred(*it))
-                        it = m_pack_dependencies.erase(it);
-                    else
-                        ++it;
-#endif
+                removePack(pDep->version.addonId);
                 addTask(prepareDependencyTask(dep, provider.name, level));
             } else
                 addTask(getProjectInfoTask(pDep));
@@ -238,3 +236,17 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
     tasks->addTask(version);
     return tasks;
 };
+
+void GetModDependenciesTask::removePack(const QVariant addonId)
+{
+    auto pred = [addonId](const std::shared_ptr<PackDependency>& v) { return v->pack->addonId == addonId; };
+#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
+    m_pack_dependencies.removeIf(pred);
+#else
+    for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();)
+        if (pred(*it))
+            it = m_pack_dependencies.erase(it);
+        else
+            ++it;
+#endif
+}
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index e2ad4825..50eba6af 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -70,6 +70,7 @@ class GetModDependenciesTask : public SequentialTask {
     void prepare();
     Task::Ptr getProjectInfoTask(std::shared_ptr<PackDependency> pDep);
     ModPlatform::Dependency getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName);
+    void removePack(const QVariant addonId);
 
    private:
     QList<std::shared_ptr<PackDependency>> m_pack_dependencies;
-- 
cgit 


From a32a3e25adbb20e31749828cca84a3ff3878f094 Mon Sep 17 00:00:00 2001
From: Jakub Wroński <kubawronski161@gmail.com>
Date: Tue, 20 Jun 2023 12:11:28 +0200
Subject: Fix compiling on FreeBSD
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Jakub Wroński <kubawronski161@gmail.com>
---
 launcher/FileSystem.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'launcher')

diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp
index d98526df..835ad925 100644
--- a/launcher/FileSystem.cpp
+++ b/launcher/FileSystem.cpp
@@ -102,7 +102,7 @@ namespace fs = ghc::filesystem;
 #include <linux/fs.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
-#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
+#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD)
 #include <sys/attr.h>
 #include <sys/clonefile.h>
 #elif defined(Q_OS_WIN)
@@ -1151,7 +1151,7 @@ bool clone_file(const QString& src, const QString& dst, std::error_code& ec)
         return false;
     }
 
-#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
+#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD)
 
     if (!macos_bsd_clonefile(src_path, dst_path, ec)) {
         qDebug() << "failed macos_bsd_clonefile:";
@@ -1380,7 +1380,7 @@ bool linux_ficlone(const std::string& src_path, const std::string& dst_path, std
     return true;
 }
 
-#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
+#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD)
 
 bool macos_bsd_clonefile(const std::string& src_path, const std::string& dst_path, std::error_code& ec)
 {
-- 
cgit 


From 009623823d6036ea22b34b21812758666fb8f7ba Mon Sep 17 00:00:00 2001
From: James Beddek <telans@posteo.de>
Date: Tue, 20 Jun 2023 23:00:13 +1200
Subject: Modrinth: use default icon for non-managed packs

Fixes: #317
Signed-off-by: James Beddek <telans@posteo.de>
---
 launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
index bb8227aa..76f07277 100644
--- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
@@ -214,7 +214,7 @@ bool ModrinthCreationTask::createInstance()
 
     if (m_instIcon != "default") {
         instance.setIconKey(m_instIcon);
-    } else {
+    } else if (!m_managed_id.isEmpty()) {
         instance.setIconKey("modrinth");
     }
 
-- 
cgit 


From f2692e60f3b7f1281750c4e97268830b9db30e95 Mon Sep 17 00:00:00 2001
From: Chris Lane <git@chrislane.com>
Date: Tue, 20 Jun 2023 12:44:44 +0100
Subject: Add missing space in java checker debug message

Signed-off-by: Chris Lane <git@chrislane.com>
---
 launcher/java/JavaChecker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp
index b4c55b3d..916a010c 100644
--- a/launcher/java/JavaChecker.cpp
+++ b/launcher/java/JavaChecker.cpp
@@ -85,7 +85,7 @@ void JavaChecker::performCheck()
     process->setProgram(m_path);
     process->setProcessChannelMode(QProcess::SeparateChannels);
     process->setProcessEnvironment(CleanEnviroment());
-    qDebug() << "Running java checker: " + m_path + args.join(" ");;
+    qDebug() << "Running java checker: " + m_path + " " + args.join(" ");;
 
     connect(process.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &JavaChecker::finished);
     connect(process.get(), &QProcess::errorOccurred, this, &JavaChecker::error);
-- 
cgit 


From 07f3d27fb89e1e5a32ca25e7111c98a29ab12e8c Mon Sep 17 00:00:00 2001
From: Chris Lane <git@chrislane.com>
Date: Tue, 20 Jun 2023 15:36:25 +0100
Subject: Clean up 'Running java checker' debug msg code

Signed-off-by: Chris Lane <git@chrislane.com>
---
 launcher/java/JavaChecker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp
index 916a010c..755e34c6 100644
--- a/launcher/java/JavaChecker.cpp
+++ b/launcher/java/JavaChecker.cpp
@@ -85,7 +85,7 @@ void JavaChecker::performCheck()
     process->setProgram(m_path);
     process->setProcessChannelMode(QProcess::SeparateChannels);
     process->setProcessEnvironment(CleanEnviroment());
-    qDebug() << "Running java checker: " + m_path + " " + args.join(" ");;
+    qDebug() << "Running java checker:" << m_path << args.join(" ");
 
     connect(process.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &JavaChecker::finished);
     connect(process.get(), &QProcess::errorOccurred, this, &JavaChecker::error);
-- 
cgit 


From 9ad29e8d85d66b9008892bd3298cc7d709c2ad17 Mon Sep 17 00:00:00 2001
From: Chris Lane <git@chrislane.com>
Date: Tue, 20 Jun 2023 15:51:31 +0100
Subject: Remove extra spaces in one more Java checker debug

Signed-off-by: Chris Lane <git@chrislane.com>
---
 launcher/java/JavaChecker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp
index 755e34c6..e4a686c2 100644
--- a/launcher/java/JavaChecker.cpp
+++ b/launcher/java/JavaChecker.cpp
@@ -128,7 +128,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
     result.outLog = m_stdout;
     qDebug() << "STDOUT" << m_stdout;
     qWarning() << "STDERR" << m_stderr;
-    qDebug() << "Java checker finished with status " << status << " exit code " << exitcode;
+    qDebug() << "Java checker finished with status" << status << "exit code" << exitcode;
 
     if (status == QProcess::CrashExit || exitcode == 1)
     {
-- 
cgit 


From 470518eb3a3e0e43d67b7a15823c060755ad3284 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Wed, 21 Jun 2023 02:31:40 -0700
Subject: fix: resize columns on hide ^& uniform heights

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
 launcher/minecraft/mod/ModFolderModel.cpp           | 2 +-
 launcher/minecraft/mod/ResourceFolderModel.cpp      | 4 ++++
 launcher/minecraft/mod/ResourceFolderModel.h        | 2 +-
 launcher/ui/pages/instance/ExternalResourcesPage.ui | 3 +++
 4 files changed, 9 insertions(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index e745f954..af98d834 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -60,7 +60,7 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool
     m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" });
     m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER};
-    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
 }
 
 QVariant ModFolderModel::data(const QModelIndex &index, int role) const
diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp
index b60f8182..7700fd36 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourceFolderModel.cpp
@@ -558,6 +558,10 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree)
 
         connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled){
             tree->setColumnHidden(col, !toggled);
+            for(int c = 0; c < columnCount(); ++c) {
+                if (m_column_resize_modes.at(c) == QHeaderView::ResizeToContents)
+                    tree->resizeColumnToContents(c);
+            }
             saveHiddenColumn(col, !toggled);
         });
 
diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h
index 3c9c4d89..eb1d7c4f 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.h
+++ b/launcher/minecraft/mod/ResourceFolderModel.h
@@ -201,7 +201,7 @@ class ResourceFolderModel : public QAbstractListModel {
     QList<SortType> m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE };
     QStringList m_column_names = {"Enable", "Name", "Last Modified"};
     QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")};
-    QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents };
+    QList<QHeaderView::ResizeMode> m_column_resize_modes = {  QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents };
 
     bool m_can_interact = true;
 
diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui
index 33a03336..f676361c 100644
--- a/launcher/ui/pages/instance/ExternalResourcesPage.ui
+++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui
@@ -62,6 +62,9 @@
       <property name="dragDropMode">
        <enum>QAbstractItemView::DropOnly</enum>
       </property>
+      <property name="uniformRowHeights">
+       <bool>true</bool>
+      </property>
      </widget>
     </item>
    </layout>
-- 
cgit 


From 2e82c1d40cd43aef4745726d51dd6a9df2d8f78b Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 21 Jun 2023 23:22:25 +0300
Subject: Added regex expresion to exclude .DS_Store files

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/dialogs/ExportMrPackDialog.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'launcher')

diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp
index 239873f6..561b92e4 100644
--- a/launcher/ui/dialogs/ExportMrPackDialog.cpp
+++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp
@@ -53,6 +53,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent)
     const QDir root(instance->gameRoot());
     proxy = new FileIgnoreProxy(instance->gameRoot(), this);
     proxy->setSourceModel(model);
+    proxy->setFilterRegularExpression("^(?!\\.DS_Store).+$");
 
     const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden);
 
-- 
cgit 


From 03361e51efb20802c419e15228e8dc086c4d273b Mon Sep 17 00:00:00 2001
From: seth <getchoo@tuta.io>
Date: Thu, 22 Jun 2023 15:58:53 -0400
Subject: chore: add 'suggest a feature' message in help

Signed-off-by: seth <getchoo@tuta.io>
---
 launcher/ui/MainWindow.ui | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui
index f67fb185..113dfc1e 100644
--- a/launcher/ui/MainWindow.ui
+++ b/launcher/ui/MainWindow.ui
@@ -577,7 +577,7 @@
      <normaloff>.</normaloff>.</iconset>
    </property>
    <property name="text">
-    <string>Report a &amp;Bug...</string>
+    <string>Report a Bug or Suggest a Feature</string>
    </property>
    <property name="toolTip">
     <string>Open the bug tracker to report a bug with %1.</string>
-- 
cgit 


From a4521ac0bbd0472c0f8bbf184d1b2f5b54ed8e0b Mon Sep 17 00:00:00 2001
From: seth <getchoo@tuta.io>
Date: Thu, 22 Jun 2023 16:15:03 -0400
Subject: chore: avoid confusion in file/url import dialog

Signed-off-by: seth <getchoo@tuta.io>
---
 launcher/ui/pages/modplatform/ImportPage.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h
index 8d13ac10..c2acb92d 100644
--- a/launcher/ui/pages/modplatform/ImportPage.h
+++ b/launcher/ui/pages/modplatform/ImportPage.h
@@ -57,7 +57,7 @@ public:
     virtual ~ImportPage();
     virtual QString displayName() const override
     {
-        return tr("Import from zip");
+        return tr("Import");
     }
     virtual QIcon icon() const override
     {
-- 
cgit 


From 763b3c323613473a1d9678e15f92a712884ab7c3 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 10:38:26 +0300
Subject: Added Thumbs.db to excluded files in MrPackExport

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp
index 561b92e4..60ecefd5 100644
--- a/launcher/ui/dialogs/ExportMrPackDialog.cpp
+++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp
@@ -53,7 +53,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent)
     const QDir root(instance->gameRoot());
     proxy = new FileIgnoreProxy(instance->gameRoot(), this);
     proxy->setSourceModel(model);
-    proxy->setFilterRegularExpression("^(?!\\.DS_Store).+$");
+    proxy->setFilterRegularExpression("^(?!(\\.DS_Store)|([tT]humbs\\.db)).+$");
 
     const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden);
 
-- 
cgit 


From 67db141203864123f65d93723e7eed43328b8d97 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 14:38:23 +0300
Subject: Renamed getResults to resultsReady

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/EnsureMetadataTask.cpp            | 4 ++--
 launcher/modplatform/atlauncher/ATLPackInstallTask.cpp | 2 +-
 launcher/modplatform/helpers/HashUtils.cpp             | 2 +-
 launcher/modplatform/helpers/HashUtils.h               | 2 +-
 launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp  | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp
index a04a2534..93b5ce76 100644
--- a/launcher/modplatform/EnsureMetadataTask.cpp
+++ b/launcher/modplatform/EnsureMetadataTask.cpp
@@ -25,7 +25,7 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource
     auto hash_task = createNewHash(mod);
     if (!hash_task)
         return;
-    connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); });
+    connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
     connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
     hash_task->start();
 }
@@ -38,7 +38,7 @@ EnsureMetadataTask::EnsureMetadataTask(QList<Mod*>& mods, QDir dir, ModPlatform:
         auto hash_task = createNewHash(mod);
         if (!hash_task)
             continue;
-        connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); });
+        connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
         connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
         m_hashing_task->addTask(hash_task);
     }
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 2522020d..22ea02da 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -100,7 +100,7 @@ void PackInstallTask::onDownloadSucceeded()
     jobPtr.reset();
 
     QJsonParseError parse_error{};
-    QJsonDocument doc = QJsonDocument::fromJson(*response.get(), &parse_error);
+    QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
     if (parse_error.error != QJsonParseError::NoError) {
         qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset
                    << " reason: " << parse_error.errorString();
diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp
index 6df1eaf9..7d188a2f 100644
--- a/launcher/modplatform/helpers/HashUtils.cpp
+++ b/launcher/modplatform/helpers/HashUtils.cpp
@@ -71,7 +71,7 @@ void ModrinthHasher::executeTask()
         emitFailed("Empty hash!");
     } else {
         emitSucceeded();
-        emit getResults(m_hash);
+        emit resultsReady(m_hash);
     }
 }
 
diff --git a/launcher/modplatform/helpers/HashUtils.h b/launcher/modplatform/helpers/HashUtils.h
index a541ae8f..73a2435a 100644
--- a/launcher/modplatform/helpers/HashUtils.h
+++ b/launcher/modplatform/helpers/HashUtils.h
@@ -23,7 +23,7 @@ class Hasher : public Task {
     QString getPath() const { return m_path; };
 
    signals:
-    void getResults(QString hash);
+    void resultsReady(QString hash);
 
    protected:
     QString m_hash;
diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
index 36002bad..a7c22832 100644
--- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
+++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp
@@ -53,7 +53,7 @@ void ModrinthCheckUpdate::executeTask()
         // (though it will rarely happen, if at all)
         if (mod->metadata()->hash_format != best_hash_type) {
             auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath());
-            connect(hash_task.get(), &Hashing::Hasher::getResults, [&hashes, &mappings, mod](QString hash) {
+            connect(hash_task.get(), &Hashing::Hasher::resultsReady, [&hashes, &mappings, mod](QString hash) {
                 hashes.append(hash);
                 mappings.insert(hash, mod);
             });
-- 
cgit 


From 28de461067b0fec69ebcb9bdcd213d02244b39bb Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 21:38:41 +0300
Subject: Fixed hashers

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/modplatform/helpers/HashUtils.cpp | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'launcher')

diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp
index 7d188a2f..6ff1d171 100644
--- a/launcher/modplatform/helpers/HashUtils.cpp
+++ b/launcher/modplatform/helpers/HashUtils.cpp
@@ -89,6 +89,7 @@ void FlameHasher::executeTask()
         emitFailed("Empty hash!");
     } else {
         emitSucceeded();
+        emit resultsReady(m_hash);
     }
 }
 
@@ -120,6 +121,7 @@ void BlockedModHasher::executeTask()
         emitFailed("Empty hash!");
     } else {
         emitSucceeded();
+        emit resultsReady(m_hash);
     }
 }
 
-- 
cgit 


From 750209b8bbeaf75b93a6ae6e55d9192c38fd6f7d Mon Sep 17 00:00:00 2001
From: leo78913 <leo3758@riseup.net>
Date: Fri, 23 Jun 2023 16:55:51 -0300
Subject: fix: fix crash when hiding columns on resource packs page

Signed-off-by: leo78913 <leo3758@riseup.net>
---
 launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index 14a28b47..41455599 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -53,7 +53,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc
     m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" });
     m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") });
     m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE};
-    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents};
+    m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents };
 
 }
 
-- 
cgit 


From d74a23d5b217195e71cce47a07e2141b0eaa9fc3 Mon Sep 17 00:00:00 2001
From: TheKodeToad <TheKodeToad@proton.me>
Date: Fri, 23 Jun 2023 21:00:55 +0100
Subject: Update developers

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
---
 launcher/ui/dialogs/AboutDialog.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp
index 76e3d8ed..88739463 100644
--- a/launcher/ui/dialogs/AboutDialog.cpp
+++ b/launcher/ui/dialogs/AboutDialog.cpp
@@ -71,13 +71,18 @@ QString getCreditsHtml()
     //: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Developers"
     stream << "<h3>" << QObject::tr("%1 Developers", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "</h3>\n";
     stream << QString("<p>Sefa Eyeoglu (Scrumplex) %1</p>\n")   .arg(getWebsite("https://scrumplex.net"));
-    stream << QString("<p>dada513 %1</p>\n")                    .arg(getGitHub("dada513"));
+    stream << QString("<p>d-513 %1</p>\n")                      .arg(getGitHub("d-513"));
     stream << QString("<p>txtsd %1</p>\n")                      .arg(getWebsite("https://ihavea.quest"));
     stream << QString("<p>timoreo %1</p>\n")                    .arg(getGitHub("timoreo22"));
     stream << QString("<p>Ezekiel Smith (ZekeSmith) %1</p>\n")  .arg(getGitHub("ZekeSmith"));
     stream << QString("<p>cozyGalvinism %1</p>\n")              .arg(getGitHub("cozyGalvinism"));
-    stream << QString("<p>DioEgizio %1</p>\n")      .arg(getGitHub("DioEgizio"));
-    stream << QString("<p>flowln %1</p>\n")         .arg(getGitHub("flowln"));
+    stream << QString("<p>DioEgizio %1</p>\n")                  .arg(getGitHub("DioEgizio"));
+    stream << QString("<p>flowln %1</p>\n")                     .arg(getGitHub("flowln"));
+    stream << QString("<p>ViRb3 %1</p>\n")                      .arg(getGitHub("ViRb3"));
+    stream << QString("<p>Rachel Powers (Ryex) %1</p>\n")       .arg(getGitHub("Ryex"));
+    stream << QString("<p>TayouVR %1</p>\n")                    .arg(getGitHub("TayouVR"));
+    stream << QString("<p>TheKodeToad %1</p>\n")                .arg(getGitHub("TheKodeToad"));
+    stream << QString("<p>getchoo %1</p>\n")                    .arg(getGitHub("getchoo"));
     stream << "<br />\n";
 
     // TODO: possibly retrieve from git history at build time?
-- 
cgit 


From 20ba6e5fb50177d5145459951a69edc7b3302e95 Mon Sep 17 00:00:00 2001
From: James Beddek <telans@posteo.de>
Date: Sat, 24 Jun 2023 15:42:58 +1200
Subject: modrinth: use encoded url when exporting pack

Ensures that necessary url components such as spaces are encoded.
Prevents an error when submitting the resulting file to modrinth.

See https://discord.com/channels/734077874708938864/1120070731242410024

Fixes: #1226
Signed-off-by: James Beddek <telans@posteo.de>
---
 launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
index c607bb89..4cd88aa6 100644
--- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
@@ -134,8 +134,8 @@ void ModrinthPackExportTask::collectHashes()
                     QCryptographicHash sha1(QCryptographicHash::Algorithm::Sha1);
                     sha1.addData(data);
 
-                    ResolvedFile file{ sha1.result().toHex(), sha512.result().toHex(), url.toString(), openFile.size() };
-                    resolvedFiles[relative] = file;
+                    ResolvedFile resolvedFile{ sha1.result().toHex(), sha512.result().toHex(), url.toEncoded(), openFile.size() };
+                    resolvedFiles[relative] = resolvedFile;
 
                     // nice! we've managed to resolve based on local metadata!
                     // no need to enqueue it
-- 
cgit 


From 8b576fd2bd442a61092de870b4323c280b04d2d6 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sat, 24 Jun 2023 15:59:55 +0300
Subject: Added translation

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 2 +-
 launcher/modplatform/flame/FlameModIndex.cpp            | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index b1058ee6..f8ecdb33 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -48,7 +48,7 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
                                                BaseInstance* instance,
                                                ModFolderModel* folder,
                                                QList<std::shared_ptr<PackDependency>> selected)
-    : SequentialTask(parent, "Get dependencies")
+    : SequentialTask(parent, tr("Get dependencies"))
     , m_selected(selected)
     , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
                         std::make_shared<FlameAPI>() }
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
index 9c8eb832..227ce489 100644
--- a/launcher/modplatform/flame/FlameModIndex.cpp
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -160,10 +160,9 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
             case 6:  // Include
                 dependency.type = ModPlatform::DependencyType::INCLUDE;
                 break;
-                default:
+            default:
                 dependency.type = ModPlatform::DependencyType::UNKNOWN;
                 break;
-                
         }
         file.dependencies.append(dependency);
     }
-- 
cgit 


From 514080653f2a862c6d3b2f1efb279a6707ccfb1c Mon Sep 17 00:00:00 2001
From: TheKodeToad <TheKodeToad@proton.me>
Date: Sun, 25 Jun 2023 11:56:28 +0100
Subject: Fix unsafe usage of std::optional::value in FlameAPI

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
---
 launcher/modplatform/flame/FlameAPI.h | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h
index a0611957..0a6dc78f 100644
--- a/launcher/modplatform/flame/FlameAPI.h
+++ b/launcher/modplatform/flame/FlameAPI.h
@@ -77,24 +77,28 @@ class FlameAPI : public NetworkResourceAPI {
 
     [[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override
     {
-        auto mappedModLoader = getMappedModLoader(args.loaders.value());
         auto addonId = args.pack.addonId.toString();
-        if (args.loaders.value() & Quilt) {
-            auto overide = ModPlatform::getOverrideDeps();
-            auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) {
-                return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt;
-            });
-            if (over != overide.cend()) {
-                mappedModLoader = 5;
-            }
-        }
         QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(addonId) };
 
         QStringList get_parameters;
         if (args.mcVersions.has_value())
             get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString()));
-        if (args.loaders.has_value())
+
+        if (args.loaders.has_value()) {
+            int mappedModLoader = getMappedModLoader(args.loaders.value());
+
+            if (args.loaders.value() & Quilt) {
+                auto overide = ModPlatform::getOverrideDeps();
+                auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) {
+                    return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt;
+                });
+                if (over != overide.cend()) {
+                    mappedModLoader = 5;
+                }
+            }
+
             get_parameters.append(QString("modLoaderType=%1").arg(mappedModLoader));
+        }
 
         return url + get_parameters.join('&');
     };
-- 
cgit