From bf95cfb30eee52f23d0279284f70931b2c968dd3 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 01:37:28 +0300
Subject: Added CatPacks

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/Application.cpp                         |  12 ++-
 launcher/Application.h                           |   9 +-
 launcher/CMakeLists.txt                          |   2 +
 launcher/ui/MainWindow.cpp                       |   4 +-
 launcher/ui/setupwizard/ThemeWizardPage.cpp      |   2 +-
 launcher/ui/themes/CatPack.cpp                   | 109 +++++++++++++++++++++++
 launcher/ui/themes/CatPack.h                     |  98 ++++++++++++++++++++
 launcher/ui/themes/ThemeManager.cpp              |  82 ++++++++++++++---
 launcher/ui/themes/ThemeManager.h                |  15 ++--
 launcher/ui/widgets/ThemeCustomizationWidget.cpp |  17 ++--
 launcher/ui/widgets/ThemeCustomizationWidget.h   |  34 +++----
 11 files changed, 331 insertions(+), 53 deletions(-)
 create mode 100644 launcher/ui/themes/CatPack.cpp
 create mode 100644 launcher/ui/themes/CatPack.h

(limited to 'launcher')

diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index 724e6e44..d8ac2168 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -1173,7 +1173,17 @@ QIcon Application::getThemedIcon(const QString& name)
     return QIcon::fromTheme(name);
 }
 
-bool Application::openJsonEditor(const QString &filename)
+QList<CatPack*> Application::getValidCatPacks()
+{
+    return m_themeManager->getValidCatPacks();
+}
+
+QString Application::getCatPack(QString catName)
+{
+    return m_themeManager->getCatPack(catName);
+}
+
+bool Application::openJsonEditor(const QString& filename)
 {
     const QString file = QDir::current().absoluteFilePath(filename);
     if (m_settings->get("JsonEditor").toString().isEmpty())
diff --git a/launcher/Application.h b/launcher/Application.h
index ced0af17..55b01cd4 100644
--- a/launcher/Application.h
+++ b/launcher/Application.h
@@ -48,6 +48,7 @@
 #include <BaseInstance.h>
 
 #include "minecraft/launch/MinecraftServerTarget.h"
+#include "ui/themes/CatPack.h"
 
 class LaunchController;
 class LocalPeer;
@@ -126,9 +127,11 @@ public:
 
     void setApplicationTheme(const QString& name);
 
-    shared_qobject_ptr<ExternalUpdater> updater() {
-        return m_updater;
-    }
+    QList<CatPack*> getValidCatPacks();
+
+    QString getCatPack(QString catName = "");
+
+    shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; }
 
     void triggerUpdateCheck();
 
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index ce2771a4..4d0f7d06 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -755,6 +755,8 @@ SET(LAUNCHER_SOURCES
     ui/themes/SystemTheme.h
     ui/themes/ThemeManager.cpp
     ui/themes/ThemeManager.h
+    ui/themes/CatPack.cpp
+    ui/themes/CatPack.h
 
     # Processes
     LaunchController.h
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index e04011ca..8e1b5613 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -924,14 +924,14 @@ void MainWindow::setCatBackground(bool enabled)
         view->setStyleSheet(QString(R"(
 InstanceView
 {
-    background-image: url(:/backgrounds/%1);
+    background-image: url(%1);
     background-attachment: fixed;
     background-clip: padding;
     background-position: bottom right;
     background-repeat: none;
     background-color:palette(base);
 })")
-                                .arg(ThemeManager::getCatImage()));
+                                .arg(APPLICATION->getCatPack()));
     } else {
         view->setStyleSheet(QString());
     }
diff --git a/launcher/ui/setupwizard/ThemeWizardPage.cpp b/launcher/ui/setupwizard/ThemeWizardPage.cpp
index 42826aba..282a01ac 100644
--- a/launcher/ui/setupwizard/ThemeWizardPage.cpp
+++ b/launcher/ui/setupwizard/ThemeWizardPage.cpp
@@ -61,7 +61,7 @@ void ThemeWizardPage::updateIcons()
 void ThemeWizardPage::updateCat()
 {
     qDebug() << "Setting Cat";
-    ui->catImagePreviewButton->setIcon(QIcon(QString(R"(:/backgrounds/%1)").arg(ThemeManager::getCatImage())));
+    ui->catImagePreviewButton->setIcon(QIcon(QString(R"(%1)").arg(APPLICATION->getCatPack())));
 }
 
 void ThemeWizardPage::retranslate()
diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
new file mode 100644
index 00000000..e74b9709
--- /dev/null
+++ b/launcher/ui/themes/CatPack.cpp
@@ -0,0 +1,109 @@
+// 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 "ui/themes/CatPack.h"
+#include <qdatetime.h>
+#include <qjsonarray.h>
+#include <qjsonobject.h>
+#include <qobject.h>
+#include <QDateTime>
+#include <QDir>
+#include <QFileInfo>
+#include "FileSystem.h"
+#include "Json.h"
+#include "ui/themes/ThemeManager.h"
+
+QString BasicCatPack::path()
+{
+    const QDateTime now = QDateTime::currentDateTime();
+    const QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0));
+    const QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0));
+    const QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0));
+
+    QString cat = QString(":/backgrounds/%1").arg(m_id);
+    if (std::abs(now.daysTo(xmas)) <= 4) {
+        cat += "-xmas";
+    } else if (std::abs(now.daysTo(halloween)) <= 4) {
+        cat += "-spooky";
+    } else if (std::abs(now.daysTo(birthday)) <= 12) {
+        cat += "-bday";
+    }
+    return cat;
+}
+
+JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.dir().dirName())
+{
+    QString path = FS::PathCombine("catpacks", m_id);
+
+    if (!FS::ensureFolderPathExists(path)) {
+        themeWarningLog() << "couldn't create folder for catpack!";
+        return;
+    }
+
+    if (manifestInfo.exists() && manifestInfo.isFile()) {
+        try {
+            auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file");
+            const auto root = doc.object();
+            m_name = Json::requireString(root, "name", "Catpack name");
+            m_id = Json::requireString(root, "id", "Catpack ID");
+            m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat"));
+            auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
+            for (auto v : variants) {
+                auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant");
+                m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")),
+                                       date(Json::requireString(variant, "startTime", "Variant startTime")),
+                                       date(Json::requireString(variant, "endTime", "Variant endTime")) };
+            }
+
+        } catch (const Exception& e) {
+            themeWarningLog() << "Couldn't load catpack json: " << e.cause();
+            return;
+        }
+    } else {
+        themeDebugLog() << "No catpack json present.";
+    }
+}
+
+QString JsonCatPack::path()
+{
+    const QDateTime now = QDateTime::currentDateTime();
+    for (auto var : m_variants) {
+        QDateTime startDate(QDate(now.date().year(), var.startTime.mounth, var.startTime.day), QTime(0, 0));
+        QDateTime endDate(QDate(now.date().year(), var.endTime.mounth, var.endTime.day), QTime(0, 0));
+        if (startDate.daysTo(now) > 0 && now.daysTo(endDate) > 0)
+            return var.path;
+    }
+    return m_defaultPath;
+}
diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h
new file mode 100644
index 00000000..d9010b8e
--- /dev/null
+++ b/launcher/ui/themes/CatPack.h
@@ -0,0 +1,98 @@
+// 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.
+ */
+
+#pragma once
+
+#include <QDateTime>
+#include <QFileInfo>
+#include <QList>
+#include <QString>
+
+class CatPack {
+   public:
+    virtual ~CatPack() {}
+    virtual QString id() = 0;
+    virtual QString name() = 0;
+    virtual QString path() = 0;
+};
+
+class BasicCatPack : public CatPack {
+   public:
+    BasicCatPack(QString id, QString name) : m_id(id), m_name(name) {}
+    BasicCatPack(QString id) : BasicCatPack(id, id) {}
+    virtual QString id() { return m_id; };
+    virtual QString name() { return m_name; };
+    virtual QString path();
+
+   protected:
+    QString m_id;
+    QString m_name;
+};
+
+class FileCatPack : public BasicCatPack {
+   public:
+    FileCatPack(QString id, QFileInfo& fileInfo) : BasicCatPack(id), m_path(fileInfo.absoluteFilePath()) {}
+    FileCatPack(QFileInfo& fileInfo) : FileCatPack(fileInfo.baseName(), fileInfo) {}
+    virtual QString path() { return m_path; }
+
+   private:
+    QString m_path;
+};
+
+class JsonCatPack : public BasicCatPack {
+   public:
+    struct date {
+        date(QString d)
+        {
+            auto sp = d.split("-");
+            day = sp[0].toInt();
+            if (sp.length() >= 2)
+                mounth = sp[1].length();
+        }
+        int mounth;
+        int day;
+    };
+    struct Variant {
+        QString path;
+        date startTime;
+        date endTime;
+    };
+    JsonCatPack(QFileInfo& manifestInfo);
+    virtual QString path();
+
+   private:
+    QString m_defaultPath;
+    QList<Variant> m_variants;
+};
diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp
index 94ac8a24..bfd0550a 100644
--- a/launcher/ui/themes/ThemeManager.cpp
+++ b/launcher/ui/themes/ThemeManager.cpp
@@ -22,6 +22,7 @@
 #include <QDirIterator>
 #include <QIcon>
 #include "ui/themes/BrightTheme.h"
+#include "ui/themes/CatPack.h"
 #include "ui/themes/CustomTheme.h"
 #include "ui/themes/DarkTheme.h"
 #include "ui/themes/SystemTheme.h"
@@ -32,6 +33,7 @@ ThemeManager::ThemeManager(MainWindow* mainWindow)
 {
     m_mainWindow = mainWindow;
     initializeThemes();
+    initializeCatPacks();
 }
 
 /// @brief Adds the Theme to the list of themes
@@ -111,6 +113,16 @@ QList<ITheme*> ThemeManager::getValidApplicationThemes()
     return ret;
 }
 
+QList<CatPack*> ThemeManager::getValidCatPacks()
+{
+    QList<CatPack*> ret;
+    ret.reserve(m_catPacks.size());
+    for (auto&& [id, theme] : m_catPacks) {
+        ret.append(theme.get());
+    }
+    return ret;
+}
+
 void ThemeManager::setIconTheme(const QString& name)
 {
     QIcon::setThemeName(name);
@@ -137,19 +149,63 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial)
     }
 }
 
-QString ThemeManager::getCatImage(QString catName)
+QString ThemeManager::getCatPack(QString catName)
+{
+    auto catIter = m_catPacks.find(!catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString());
+    if (catIter != m_catPacks.end()) {
+        auto& catPack = catIter->second;
+        themeDebugLog() << "applying catpack" << catPack->id();
+        return catPack->path();
+    } else {
+        themeWarningLog() << "Tried to get invalid catPack:" << catName;
+    }
+
+    return m_catPacks.begin()->second->path();
+}
+
+QString ThemeManager::addCatPack(std::unique_ptr<CatPack> catPack)
+{
+    QString id = catPack->id();
+    m_catPacks.emplace(id, std::move(catPack));
+    return id;
+}
+
+void ThemeManager::initializeCatPacks()
 {
-    QDateTime now = QDateTime::currentDateTime();
-    QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0));
-    QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0));
-    QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0));
-    QString cat = !catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString();
-    if (std::abs(now.daysTo(xmas)) <= 4) {
-        cat += "-xmas";
-    } else if (std::abs(now.daysTo(halloween)) <= 4) {
-        cat += "-spooky";
-    } else if (std::abs(now.daysTo(birthday)) <= 12) {
-        cat += "-bday";
+    QList<std::pair<QString, QString>> defaultCats{ { "kitteh", QObject::tr("Background Cat (from MultiMC)") },
+                                                    { "rory", QObject::tr("Rory ID 11 (drawn by Ashtaka)") },
+                                                    { "rory-flat", QObject::tr("Rory ID 11 (flat edition, drawn by Ashtaka)") },
+                                                    { "teawie", QObject::tr("Teawie (drawn by SympathyTea)") } };
+    for (auto [id, name] : defaultCats) {
+        addCatPack(std::unique_ptr<CatPack>(new BasicCatPack(id, name)));
+    }
+    QDir catpacksDir("./catpacks/");
+    QString catpacksFolder = catpacksDir.absoluteFilePath("");
+    themeDebugLog() << "CatPacks Folder Path: " << catpacksFolder;
+
+    auto loadFiles = [this](QDir dir) {
+        // Load image files directly
+        QDirIterator ImageFileIterator(dir.absoluteFilePath(""), { "*.png", "*.gif", "*.jpg", "*.apng", "*.jxl", "*.avif" }, QDir::Files);
+        while (ImageFileIterator.hasNext()) {
+            QFile customCatFile(ImageFileIterator.next());
+            QFileInfo customCatFileInfo(customCatFile);
+            themeDebugLog() << "Loading QSS Theme from:" << customCatFileInfo.absoluteFilePath();
+            addCatPack(std::unique_ptr<CatPack>(new FileCatPack(customCatFileInfo)));
+        }
+    };
+
+    loadFiles(catpacksDir);
+
+    QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+    while (directoryIterator.hasNext()) {
+        QDir dir(directoryIterator.next());
+        QFileInfo manifest(dir.absoluteFilePath("catpack.json"));
+        if (manifest.exists()) {
+            // Load background manifest
+            themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath();
+            addCatPack(std::unique_ptr<CatPack>(new JsonCatPack(manifest)));
+        } else {
+            loadFiles(dir);
+        }
     }
-    return cat;
 }
diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h
index 87f36d9c..bc0d31cd 100644
--- a/launcher/ui/themes/ThemeManager.h
+++ b/launcher/ui/themes/ThemeManager.h
@@ -20,6 +20,7 @@
 #include <QString>
 
 #include "ui/MainWindow.h"
+#include "ui/themes/CatPack.h"
 #include "ui/themes/ITheme.h"
 
 inline auto themeDebugLog()
@@ -40,18 +41,20 @@ class ThemeManager {
     void applyCurrentlySelectedTheme(bool initial = false);
     void setApplicationTheme(const QString& name, bool initial = false);
 
-    /// <summary>
-    /// Returns the cat based on selected cat and with events (Birthday, XMas, etc.)
-    /// </summary>
-    /// <param name="catName">Optional, if you need a specific cat.</param>
-    /// <returns></returns>
-    static QString getCatImage(QString catName = "");
+    /// @brief Returns the background based on selected and with events (Birthday, XMas, etc.)
+    /// @param catName Optional, if you need a specific background.
+    /// @return
+    QString getCatPack(QString catName = "");
+    QList<CatPack*> getValidCatPacks();
 
    private:
     std::map<QString, std::unique_ptr<ITheme>> m_themes;
+    std::map<QString, std::unique_ptr<CatPack>> m_catPacks;
     MainWindow* m_mainWindow;
 
     void initializeThemes();
+    void initializeCatPacks();
     QString addTheme(std::unique_ptr<ITheme> theme);
     ITheme* getTheme(QString themeId);
+    QString addCatPack(std::unique_ptr<CatPack> catPack);
 };
diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp
index dcf13303..e2c5ce3d 100644
--- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp
+++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp
@@ -95,9 +95,14 @@ void ThemeCustomizationWidget::applyWidgetTheme(int index) {
     emit currentWidgetThemeChanged(index);
 }
 
-void ThemeCustomizationWidget::applyCatTheme(int index) {
+void ThemeCustomizationWidget::applyCatTheme(int index)
+{
     auto settings = APPLICATION->settings();
-    settings->set("BackgroundCat", m_catOptions[index].first);
+    auto originalCat = settings->get("BackgroundCat").toString();
+    auto newCat = ui->backgroundCatComboBox->currentData().toString();
+    if (originalCat != newCat) {
+        settings->set("BackgroundCat", newCat);
+    }
 
     emit currentCatChanged(index);
 }
@@ -135,10 +140,10 @@ void ThemeCustomizationWidget::loadSettings()
     }
 
     auto cat = settings->get("BackgroundCat").toString();
-    for (auto& catFromList : m_catOptions) {
-        QIcon catIcon = QIcon(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage(catFromList.first)));
-        ui->backgroundCatComboBox->addItem(catIcon, catFromList.second);
-        if (cat == catFromList.first) {
+    for (auto& catFromList : APPLICATION->getValidCatPacks()) {
+        QIcon catIcon = QIcon(QString("%1").arg(catFromList->path()));
+        ui->backgroundCatComboBox->addItem(catIcon, catFromList->name(), catFromList->id());
+        if (cat == catFromList->id()) {
             ui->backgroundCatComboBox->setCurrentIndex(ui->backgroundCatComboBox->count() - 1);
         }
     }
diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.h b/launcher/ui/widgets/ThemeCustomizationWidget.h
index d955a266..be204e57 100644
--- a/launcher/ui/widgets/ThemeCustomizationWidget.h
+++ b/launcher/ui/widgets/ThemeCustomizationWidget.h
@@ -53,25 +53,17 @@ class ThemeCustomizationWidget : public QWidget {
    private:
     Ui::ThemeCustomizationWidget* ui;
 
-    //TODO finish implementing
-    QList<std::pair<QString, QString>> m_iconThemeOptions{ 
-        { "pe_colored",     QObject::tr("Simple (Colored Icons)") }, 
-        { "pe_light",       QObject::tr("Simple (Light Icons)") },     
-        { "pe_dark",        QObject::tr("Simple (Dark Icons)") },
-        { "pe_blue",        QObject::tr("Simple (Blue Icons)") },    
-        { "breeze_light",   QObject::tr("Breeze Light") }, 
-        { "breeze_dark",    QObject::tr("Breeze Dark") },
-        { "OSX",            QObject::tr("OSX") },        
-        { "iOS",            QObject::tr("iOS") },          
-        { "flat",           QObject::tr("Flat") },
-        { "flat_white",     QObject::tr("Flat (White)") }, 
-        { "multimc",        QObject::tr("Legacy") },      
-        { "custom",         QObject::tr("Custom") } 
-    };
-    QList<std::pair<QString, QString>> m_catOptions{ 
-        { "kitteh",     QObject::tr("Background Cat (from MultiMC)") }, 
-        { "rory",       QObject::tr("Rory ID 11 (drawn by Ashtaka)") }, 
-        { "rory-flat",  QObject::tr("Rory ID 11 (flat edition, drawn by Ashtaka)") },
-        { "teawie",     QObject::tr("Teawie (drawn by SympathyTea)") }
-    };
+    // TODO finish implementing
+    QList<std::pair<QString, QString>> m_iconThemeOptions{ { "pe_colored", QObject::tr("Simple (Colored Icons)") },
+                                                           { "pe_light", QObject::tr("Simple (Light Icons)") },
+                                                           { "pe_dark", QObject::tr("Simple (Dark Icons)") },
+                                                           { "pe_blue", QObject::tr("Simple (Blue Icons)") },
+                                                           { "breeze_light", QObject::tr("Breeze Light") },
+                                                           { "breeze_dark", QObject::tr("Breeze Dark") },
+                                                           { "OSX", QObject::tr("OSX") },
+                                                           { "iOS", QObject::tr("iOS") },
+                                                           { "flat", QObject::tr("Flat") },
+                                                           { "flat_white", QObject::tr("Flat (White)") },
+                                                           { "multimc", QObject::tr("Legacy") },
+                                                           { "custom", QObject::tr("Custom") } };
 };
-- 
cgit 


From 718aca3d066fc24c03b7ac6d625d68829fcaa427 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 09:24:18 +0300
Subject: Fixed date constructor

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

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h
index d9010b8e..9f288d3d 100644
--- a/launcher/ui/themes/CatPack.h
+++ b/launcher/ui/themes/CatPack.h
@@ -79,7 +79,7 @@ class JsonCatPack : public BasicCatPack {
             auto sp = d.split("-");
             day = sp[0].toInt();
             if (sp.length() >= 2)
-                mounth = sp[1].length();
+                mounth = sp[1].toInt();
         }
         int mounth;
         int day;
-- 
cgit 


From f8adb508ab0152af76829e0fdee92b451dcc1acf Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 11:44:40 +0300
Subject: Made catpack id optional in catpack.json

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

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index e74b9709..2d5653a6 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -77,7 +77,8 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di
             auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file");
             const auto root = doc.object();
             m_name = Json::requireString(root, "name", "Catpack name");
-            m_id = Json::requireString(root, "id", "Catpack ID");
+            auto id = Json::ensureString(root, "id", "", "Catpack ID");
+            m_id = id.isEmpty() ? m_id : id;
             m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat"));
             auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
             for (auto v : variants) {
-- 
cgit 


From c5ea8367aaf9d61a6362427a55206d8891f40cda Mon Sep 17 00:00:00 2001
From: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Date: Fri, 23 Jun 2023 14:25:21 +0300
Subject: Update launcher/ui/themes/CatPack.cpp

Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/CatPack.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index 2d5653a6..bee63202 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -78,7 +78,8 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di
             const auto root = doc.object();
             m_name = Json::requireString(root, "name", "Catpack name");
             auto id = Json::ensureString(root, "id", "", "Catpack ID");
-            m_id = id.isEmpty() ? m_id : id;
+            if (!id.isEmpty())
+                m_id = id;
             m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat"));
             auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
             for (auto v : variants) {
-- 
cgit 


From 7579fff532629643384d9b8011e885028ca9a8f0 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 2 Jul 2023 13:34:04 +0300
Subject: Added more options for variants planing

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/CatPack.cpp      | 10 ++++++----
 launcher/ui/themes/CatPack.h        |  4 ++--
 launcher/ui/themes/ThemeManager.cpp |  2 +-
 3 files changed, 9 insertions(+), 7 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index 2d5653a6..a0b06a60 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -99,11 +99,13 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di
 
 QString JsonCatPack::path()
 {
-    const QDateTime now = QDateTime::currentDateTime();
+    const QDate now = QDate::currentDate();
     for (auto var : m_variants) {
-        QDateTime startDate(QDate(now.date().year(), var.startTime.mounth, var.startTime.day), QTime(0, 0));
-        QDateTime endDate(QDate(now.date().year(), var.endTime.mounth, var.endTime.day), QTime(0, 0));
-        if (startDate.daysTo(now) > 0 && now.daysTo(endDate) > 0)
+        QDate startDate(now.year(), var.startTime.month, var.startTime.day);
+        QDate endDate(now.year(), var.endTime.month, var.endTime.day);
+        if (startDate.daysTo(endDate) < 0)  // in this case end date should be next year
+            endDate = endDate.addYears(1);
+        if (startDate.daysTo(now) >= 0 && now.daysTo(endDate) >= 0)
             return var.path;
     }
     return m_defaultPath;
diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h
index 9f288d3d..e22df1f4 100644
--- a/launcher/ui/themes/CatPack.h
+++ b/launcher/ui/themes/CatPack.h
@@ -79,9 +79,9 @@ class JsonCatPack : public BasicCatPack {
             auto sp = d.split("-");
             day = sp[0].toInt();
             if (sp.length() >= 2)
-                mounth = sp[1].toInt();
+                month = sp[1].toInt();
         }
-        int mounth;
+        int month;
         int day;
     };
     struct Variant {
diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp
index bfd0550a..d00b3a99 100644
--- a/launcher/ui/themes/ThemeManager.cpp
+++ b/launcher/ui/themes/ThemeManager.cpp
@@ -189,7 +189,7 @@ void ThemeManager::initializeCatPacks()
         while (ImageFileIterator.hasNext()) {
             QFile customCatFile(ImageFileIterator.next());
             QFileInfo customCatFileInfo(customCatFile);
-            themeDebugLog() << "Loading QSS Theme from:" << customCatFileInfo.absoluteFilePath();
+            themeDebugLog() << "Loading CatPack from:" << customCatFileInfo.absoluteFilePath();
             addCatPack(std::unique_ptr<CatPack>(new FileCatPack(customCatFileInfo)));
         }
     };
-- 
cgit 


From 5d5f1b86fdaa865bf8627acd86163469389ebb83 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 3 Jul 2023 09:21:25 +0300
Subject: fixed logic regarding range over multiple years

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/CatPack.cpp | 29 +++++++++++++++--------------
 launcher/ui/themes/CatPack.h   | 10 +++++-----
 2 files changed, 20 insertions(+), 19 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index 4170febd..435ccdb8 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -34,11 +34,7 @@
  */
 
 #include "ui/themes/CatPack.h"
-#include <qdatetime.h>
-#include <qjsonarray.h>
-#include <qjsonobject.h>
-#include <qobject.h>
-#include <QDateTime>
+#include <QDate>
 #include <QDir>
 #include <QFileInfo>
 #include "FileSystem.h"
@@ -47,10 +43,10 @@
 
 QString BasicCatPack::path()
 {
-    const QDateTime now = QDateTime::currentDateTime();
-    const QDateTime birthday(QDate(now.date().year(), 11, 30), QTime(0, 0));
-    const QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0));
-    const QDateTime halloween(QDate(now.date().year(), 10, 31), QTime(0, 0));
+    const auto now = QDate::currentDate();
+    const auto birthday = QDate(now.year(), 11, 30);
+    const auto xmas = QDate(now.year(), 12, 25);
+    const auto halloween = QDate(now.year(), 10, 31);
 
     QString cat = QString(":/backgrounds/%1").arg(m_id);
     if (std::abs(now.daysTo(xmas)) <= 4) {
@@ -85,8 +81,8 @@ JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.di
             for (auto v : variants) {
                 auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant");
                 m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")),
-                                       date(Json::requireString(variant, "startTime", "Variant startTime")),
-                                       date(Json::requireString(variant, "endTime", "Variant endTime")) };
+                                       PartialDate(Json::requireString(variant, "startTime", "Variant startTime")),
+                                       PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) };
             }
 
         } catch (const Exception& e) {
@@ -104,9 +100,14 @@ QString JsonCatPack::path()
     for (auto var : m_variants) {
         QDate startDate(now.year(), var.startTime.month, var.startTime.day);
         QDate endDate(now.year(), var.endTime.month, var.endTime.day);
-        if (startDate.daysTo(endDate) < 0)  // in this case end date should be next year
-            endDate = endDate.addYears(1);
-        if (startDate.daysTo(now) >= 0 && now.daysTo(endDate) >= 0)
+        if (startDate > endDate) {  // it's spans over multiple years
+            if (endDate <= now)     // end date is in the past so jump one year into the future for endDate
+                endDate = endDate.addYears(1);
+            else  // end date is in the future so jump one year into the past for startDate
+                startDate = startDate.addYears(-1);
+        }
+
+        if (startDate >= now && now >= endDate)
             return var.path;
     }
     return m_defaultPath;
diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h
index e22df1f4..20cb8f61 100644
--- a/launcher/ui/themes/CatPack.h
+++ b/launcher/ui/themes/CatPack.h
@@ -35,7 +35,7 @@
 
 #pragma once
 
-#include <QDateTime>
+#include <QDate>
 #include <QFileInfo>
 #include <QList>
 #include <QString>
@@ -73,8 +73,8 @@ class FileCatPack : public BasicCatPack {
 
 class JsonCatPack : public BasicCatPack {
    public:
-    struct date {
-        date(QString d)
+    struct PartialDate {
+        PartialDate(QString d)
         {
             auto sp = d.split("-");
             day = sp[0].toInt();
@@ -86,8 +86,8 @@ class JsonCatPack : public BasicCatPack {
     };
     struct Variant {
         QString path;
-        date startTime;
-        date endTime;
+        PartialDate startTime;
+        PartialDate endTime;
     };
     JsonCatPack(QFileInfo& manifestInfo);
     virtual QString path();
-- 
cgit 


From 1e9a596908ba85dea974e6d041b53c675f8d7b78 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 16 Jul 2023 14:18:17 +0300
Subject: simplified code in cat packs

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/CatPack.cpp      | 43 +++++++++++++------------------------
 launcher/ui/themes/ThemeManager.cpp | 15 ++++++++-----
 2 files changed, 25 insertions(+), 33 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index 435ccdb8..e1f2caf3 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -61,37 +61,24 @@ QString BasicCatPack::path()
 
 JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.dir().dirName())
 {
-    QString path = FS::PathCombine("catpacks", m_id);
+    QString path = manifestInfo.path();
+    try {
+        auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file");
+        const auto root = doc.object();
+        m_name = Json::requireString(root, "name", "Catpack name");
+        m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Default Cat"));
+        auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
+        for (auto v : variants) {
+            auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant");
+            m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")),
+                                   PartialDate(Json::requireString(variant, "startTime", "Variant startTime")),
+                                   PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) };
+        }
 
-    if (!FS::ensureFolderPathExists(path)) {
-        themeWarningLog() << "couldn't create folder for catpack!";
+    } catch (const Exception& e) {
+        themeWarningLog() << "Couldn't load catpack json:" << e.cause();
         return;
     }
-
-    if (manifestInfo.exists() && manifestInfo.isFile()) {
-        try {
-            auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file");
-            const auto root = doc.object();
-            m_name = Json::requireString(root, "name", "Catpack name");
-            auto id = Json::ensureString(root, "id", "", "Catpack ID");
-            if (!id.isEmpty())
-                m_id = id;
-            m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Deafult Cat"));
-            auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
-            for (auto v : variants) {
-                auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant");
-                m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")),
-                                       PartialDate(Json::requireString(variant, "startTime", "Variant startTime")),
-                                       PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) };
-            }
-
-        } catch (const Exception& e) {
-            themeWarningLog() << "Couldn't load catpack json: " << e.cause();
-            return;
-        }
-    } else {
-        themeDebugLog() << "No catpack json present.";
-    }
 }
 
 QString JsonCatPack::path()
diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp
index d00b3a99..ba09f627 100644
--- a/launcher/ui/themes/ThemeManager.cpp
+++ b/launcher/ui/themes/ThemeManager.cpp
@@ -21,6 +21,7 @@
 #include <QDir>
 #include <QDirIterator>
 #include <QIcon>
+#include <QImageReader>
 #include "ui/themes/BrightTheme.h"
 #include "ui/themes/CatPack.h"
 #include "ui/themes/CustomTheme.h"
@@ -179,13 +180,17 @@ void ThemeManager::initializeCatPacks()
     for (auto [id, name] : defaultCats) {
         addCatPack(std::unique_ptr<CatPack>(new BasicCatPack(id, name)));
     }
-    QDir catpacksDir("./catpacks/");
+    QDir catpacksDir("catpacks");
     QString catpacksFolder = catpacksDir.absoluteFilePath("");
-    themeDebugLog() << "CatPacks Folder Path: " << catpacksFolder;
+    themeDebugLog() << "CatPacks Folder Path:" << catpacksFolder;
 
-    auto loadFiles = [this](QDir dir) {
+    QStringList supportedImageFormats;
+    for (auto format : QImageReader::supportedImageFormats()) {
+        supportedImageFormats.append("*." + format);
+    }
+    auto loadFiles = [this, supportedImageFormats](QDir dir) {
         // Load image files directly
-        QDirIterator ImageFileIterator(dir.absoluteFilePath(""), { "*.png", "*.gif", "*.jpg", "*.apng", "*.jxl", "*.avif" }, QDir::Files);
+        QDirIterator ImageFileIterator(dir.absoluteFilePath(""), supportedImageFormats, QDir::Files);
         while (ImageFileIterator.hasNext()) {
             QFile customCatFile(ImageFileIterator.next());
             QFileInfo customCatFileInfo(customCatFile);
@@ -200,7 +205,7 @@ void ThemeManager::initializeCatPacks()
     while (directoryIterator.hasNext()) {
         QDir dir(directoryIterator.next());
         QFileInfo manifest(dir.absoluteFilePath("catpack.json"));
-        if (manifest.exists()) {
+        if (manifest.isFile()) {
             // Load background manifest
             themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath();
             addCatPack(std::unique_ptr<CatPack>(new JsonCatPack(manifest)));
-- 
cgit 


From de30a72c4e1f051eef2a0bd389fc51e6a64d54c3 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Sun, 16 Jul 2023 15:16:16 +0300
Subject: made the date a object

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/CatPack.cpp      | 58 +++++++++++++++++++++++--------------
 launcher/ui/themes/CatPack.h        |  7 -----
 launcher/ui/themes/ThemeManager.cpp | 21 ++++++++++----
 3 files changed, 53 insertions(+), 33 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index e1f2caf3..ebb100a4 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -39,7 +39,6 @@
 #include <QFileInfo>
 #include "FileSystem.h"
 #include "Json.h"
-#include "ui/themes/ThemeManager.h"
 
 QString BasicCatPack::path()
 {
@@ -59,39 +58,56 @@ QString BasicCatPack::path()
     return cat;
 }
 
+JsonCatPack::PartialDate partialDate(QJsonObject date)
+{
+    auto month = Json::ensureInteger(date, "month", 1);
+    if (month > 12)
+        month = 12;
+    else if (month <= 0)
+        month = 1;
+    auto day = Json::ensureInteger(date, "day", 1);
+    if (day > 31)
+        day = 31;
+    else if (day <= 0)
+        day = 1;
+    return { month, day };
+};
+
 JsonCatPack::JsonCatPack(QFileInfo& manifestInfo) : BasicCatPack(manifestInfo.dir().dirName())
 {
     QString path = manifestInfo.path();
-    try {
-        auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file");
-        const auto root = doc.object();
-        m_name = Json::requireString(root, "name", "Catpack name");
-        m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Default Cat"));
-        auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
-        for (auto v : variants) {
-            auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant");
-            m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")),
-                                   PartialDate(Json::requireString(variant, "startTime", "Variant startTime")),
-                                   PartialDate(Json::requireString(variant, "endTime", "Variant endTime")) };
-        }
-
-    } catch (const Exception& e) {
-        themeWarningLog() << "Couldn't load catpack json:" << e.cause();
-        return;
+    auto doc = Json::requireDocument(manifestInfo.absoluteFilePath(), "CatPack JSON file");
+    const auto root = doc.object();
+    m_name = Json::requireString(root, "name", "Catpack name");
+    m_defaultPath = FS::PathCombine(path, Json::requireString(root, "default", "Default Cat"));
+    auto variants = Json::ensureArray(root, "variants", QJsonArray(), "Catpack Variants");
+    for (auto v : variants) {
+        auto variant = Json::ensureObject(v, QJsonObject(), "Cat variant");
+        m_variants << Variant{ FS::PathCombine(path, Json::requireString(variant, "path", "Variant path")),
+                               partialDate(Json::requireObject(variant, "startTime", "Variant startTime")),
+                               partialDate(Json::requireObject(variant, "endTime", "Variant endTime")) };
     }
 }
 
+QDate ensureDay(int year, int month, int day)
+{
+    QDate date(year, month, 1);
+    if (day > date.daysInMonth())
+        day = date.daysInMonth();
+    return QDate(year, month, day);
+}
+
 QString JsonCatPack::path()
 {
     const QDate now = QDate::currentDate();
     for (auto var : m_variants) {
-        QDate startDate(now.year(), var.startTime.month, var.startTime.day);
-        QDate endDate(now.year(), var.endTime.month, var.endTime.day);
+        QDate startDate = ensureDay(now.year(), var.startTime.month, var.startTime.day);
+        QDate endDate = ensureDay(now.year(), var.endTime.month, var.endTime.day);
         if (startDate > endDate) {  // it's spans over multiple years
             if (endDate <= now)     // end date is in the past so jump one year into the future for endDate
-                endDate = endDate.addYears(1);
+                endDate = ensureDay(now.year() + 1, var.endTime.month, var.endTime.day);
             else  // end date is in the future so jump one year into the past for startDate
-                startDate = startDate.addYears(-1);
+                startDate = ensureDay(now.year() - 1, var.startTime.month, var.startTime.day);
         }
 
         if (startDate >= now && now >= endDate)
diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h
index 20cb8f61..b03a19f0 100644
--- a/launcher/ui/themes/CatPack.h
+++ b/launcher/ui/themes/CatPack.h
@@ -74,13 +74,6 @@ class FileCatPack : public BasicCatPack {
 class JsonCatPack : public BasicCatPack {
    public:
     struct PartialDate {
-        PartialDate(QString d)
-        {
-            auto sp = d.split("-");
-            day = sp[0].toInt();
-            if (sp.length() >= 2)
-                month = sp[1].toInt();
-        }
         int month;
         int day;
     };
diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp
index ba09f627..683642d7 100644
--- a/launcher/ui/themes/ThemeManager.cpp
+++ b/launcher/ui/themes/ThemeManager.cpp
@@ -22,6 +22,7 @@
 #include <QDirIterator>
 #include <QIcon>
 #include <QImageReader>
+#include "Exception.h"
 #include "ui/themes/BrightTheme.h"
 #include "ui/themes/CatPack.h"
 #include "ui/themes/CustomTheme.h"
@@ -43,7 +44,10 @@ ThemeManager::ThemeManager(MainWindow* mainWindow)
 QString ThemeManager::addTheme(std::unique_ptr<ITheme> theme)
 {
     QString id = theme->id();
-    m_themes.emplace(id, std::move(theme));
+    if (m_themes.find(id) == m_themes.end())
+        m_themes.emplace(id, std::move(theme));
+    else
+        themeWarningLog() << "Theme(" << id << ") not added to prevent id duplication";
     return id;
 }
 
@@ -167,7 +171,10 @@ QString ThemeManager::getCatPack(QString catName)
 QString ThemeManager::addCatPack(std::unique_ptr<CatPack> catPack)
 {
     QString id = catPack->id();
-    m_catPacks.emplace(id, std::move(catPack));
+    if (m_catPacks.find(id) == m_catPacks.end())
+        m_catPacks.emplace(id, std::move(catPack));
+    else
+        themeWarningLog() << "CatPack(" << id << ") not added to prevent id duplication";
     return id;
 }
 
@@ -206,9 +213,13 @@ void ThemeManager::initializeCatPacks()
         QDir dir(directoryIterator.next());
         QFileInfo manifest(dir.absoluteFilePath("catpack.json"));
         if (manifest.isFile()) {
-            // Load background manifest
-            themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath();
-            addCatPack(std::unique_ptr<CatPack>(new JsonCatPack(manifest)));
+            try {
+                // Load background manifest
+                themeDebugLog() << "Loading background manifest from:" << manifest.absoluteFilePath();
+                addCatPack(std::unique_ptr<CatPack>(new JsonCatPack(manifest)));
+            } catch (const Exception& e) {
+                themeWarningLog() << "Couldn't load catpack json:" << e.cause();
+            }
         } else {
             loadFiles(dir);
         }
-- 
cgit 


From ec32618e1158beba1cf5b4c91c3835a233eceeeb Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Mon, 17 Jul 2023 10:20:22 +0300
Subject: reveted back to add years

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/CatPack.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp
index ebb100a4..f0d8ddd5 100644
--- a/launcher/ui/themes/CatPack.cpp
+++ b/launcher/ui/themes/CatPack.cpp
@@ -105,9 +105,9 @@ QString JsonCatPack::path()
         QDate endDate = ensureDay(now.year(), var.endTime.month, var.endTime.day);
         if (startDate > endDate) {  // it's spans over multiple years
             if (endDate <= now)     // end date is in the past so jump one year into the future for endDate
-                endDate = ensureDay(now.year() + 1, var.endTime.month, var.endTime.day);
+                endDate = endDate.addYears(1);
             else  // end date is in the future so jump one year into the past for startDate
-                startDate = ensureDay(now.year() - 1, var.startTime.month, var.startTime.day);
+                startDate = startDate.addYears(-1);
         }
 
         if (startDate >= now && now >= endDate)
-- 
cgit 


From f8fcb98c6837c0bf66c2175ea98198449c36b165 Mon Sep 17 00:00:00 2001
From: Sefa Eyeoglu <contact@scrumplex.net>
Date: Tue, 18 Jul 2023 09:06:49 +0200
Subject: fix: generate predictable UUIDs for offline accounts

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
---
 launcher/minecraft/auth/MinecraftAccount.cpp | 32 +++++++++++++++++++++++++++-
 launcher/minecraft/auth/MinecraftAccount.h   |  2 ++
 2 files changed, 33 insertions(+), 1 deletion(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index 3b050ac0..d7b061e5 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -37,6 +37,7 @@
 
 #include "MinecraftAccount.h"
 
+#include <QCryptographicHash>
 #include <QUuid>
 #include <QJsonObject>
 #include <QJsonArray>
@@ -100,7 +101,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
     account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
     account->data.minecraftEntitlement.ownsMinecraft = true;
     account->data.minecraftEntitlement.canPlayMinecraft = true;
-    account->data.minecraftProfile.id = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
+    account->data.minecraftProfile.id = uuidFromUsername(username).toString().remove(QRegularExpression("[{}-]"));
     account->data.minecraftProfile.name = username;
     account->data.minecraftProfile.validity = Katabasis::Validity::Certain;
     return account;
@@ -334,3 +335,32 @@ void MinecraftAccount::incrementUses()
         qWarning() << "Profile" << data.profileId() << "is now in use.";
     }
 }
+
+QUuid MinecraftAccount::uuidFromUsername(QString username) {
+    auto input = QString("OfflinePlayer:%1").arg(username).toUtf8();
+
+    // basically a reimplementation of Java's UUID#nameUUIDFromBytes
+    QByteArray digest = QCryptographicHash::hash(input, QCryptographicHash::Md5);
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+    auto bOr = [](QByteArray& array, int index, char value) {
+        array[index] = array.at(index) | value;
+    };
+    auto bAnd = [](QByteArray& array, int index, char value) {
+        array[index] = array.at(index) & value;
+    };
+#else
+    auto bOr = [](QByteArray& array, qsizetype index, char value) {
+        array[index] |= value;
+    };
+    auto bAnd = [](QByteArray& array, qsizetype index, char value) {
+        array[index] &= value;
+    };
+#endif
+    bAnd(digest, 6, (char) 0x0f); // clear version
+    bOr(digest, 6, (char) 0x30); // set to version 3
+    bAnd(digest, 8, (char) 0x3f); // clear variant
+    bOr(digest, 8, (char) 0x80); // set to IETF variant
+
+    return QUuid::fromRfc4122(digest);
+}
diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h
index 0dcaeb53..67623a5a 100644
--- a/launcher/minecraft/auth/MinecraftAccount.h
+++ b/launcher/minecraft/auth/MinecraftAccount.h
@@ -98,6 +98,8 @@ public: /* construction */
     static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
     static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
 
+    static QUuid uuidFromUsername(QString username);
+
     //! Saves a MinecraftAccount to a JSON object and returns it.
     QJsonObject saveToJson() const;
 
-- 
cgit 


From 391497645ff2054dbc1eac48c8bc49133b86b319 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Tue, 18 Jul 2023 22:33:39 +0300
Subject: feat:made flame instace creation use metadata for recommended version

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../flame/FlameInstanceCreationTask.cpp            | 116 ++++++++++++++-------
 .../modplatform/flame/FlameInstanceCreationTask.h  |   6 +-
 2 files changed, 80 insertions(+), 42 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index b57db288..710ec06a 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -57,15 +57,11 @@
 #include <QDebug>
 #include <QFileInfo>
 
+#include "meta/Index.h"
+#include "meta/VersionList.h"
 #include "minecraft/World.h"
 #include "minecraft/mod/tasks/LocalResourceParse.h"
 
-
-const static QMap<QString, QString> forgemap = { { "1.2.5", "3.4.9.171" },
-                                                 { "1.4.2", "6.0.1.355" },
-                                                 { "1.4.7", "6.6.2.534" },
-                                                 { "1.5.2", "7.8.1.737" } };
-
 static const FlameAPI api;
 
 bool FlameCreationTask::abort()
@@ -259,6 +255,51 @@ bool FlameCreationTask::updateInstance()
     return false;
 }
 
+QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion)
+{
+    if (version == "recommended") {
+        auto vlist = APPLICATION->metadataIndex()->get(uid);
+        if (!vlist) {
+            setError(tr("Failed to get local metadata index for %1").arg(uid));
+            return Q_NULLPTR;
+        }
+
+        if (!vlist->isLoaded()) {
+            vlist->load(Net::Mode::Online);
+        }
+
+        for (int i = 0; i < vlist->versions().size(); i++) {
+            auto version = vlist->versions().at(i);
+            // first recommended build we find, we use.
+            if (!version->isRecommended())
+                continue;
+            auto reqs = version->requiredSet();
+
+            // filter by minecraft version, if the loader depends on a certain version.
+            // not all mod loaders depend on a given Minecraft version, so we won't do this
+            // filtering for those loaders.
+            if (loaderType == "forge") {
+                auto iter = std::find_if(reqs.begin(), reqs.end(), [mcVersion](const Meta::Require& req) {
+                    return req.uid == "net.minecraft" && req.equalsVersion == mcVersion;
+                });
+                if (iter == reqs.end())
+                    continue;
+            }
+            return version->descriptor();
+        }
+
+        setError(tr("Failed to find version for %1 loader").arg(loaderType));
+        return Q_NULLPTR;
+    }
+
+    if (version == Q_NULLPTR || version.isEmpty()) {
+        emitFailed(tr("No loader version set for modpack!"));
+        return Q_NULLPTR;
+    }
+
+    return version;
+}
+
 bool FlameCreationTask::createInstance()
 {
     QEventLoop loop;
@@ -297,22 +338,29 @@ bool FlameCreationTask::createInstance()
         }
     }
 
-    QString forgeVersion;
-    QString fabricVersion;
-    // TODO: is Quilt relevant here?
+    QString loaderType;
+    QString loaderUid;
+    QString loaderVersion;
+
     for (auto& loader : m_pack.minecraft.modLoaders) {
         auto id = loader.id;
         if (id.startsWith("forge-")) {
             id.remove("forge-");
-            forgeVersion = id;
-            continue;
-        }
-        if (id.startsWith("fabric-")) {
+            loaderType = "forge";
+            loaderUid = "net.minecraftforge";
+        } else if (loaderType == "fabric") {
             id.remove("fabric-");
-            fabricVersion = id;
+            loaderType = "fabric";
+            loaderUid = "net.fabricmc.fabric-loader";
+        } else if (loaderType == "quilt") {
+            id.remove("quilt-");
+            loaderType = "quilt";
+            loaderUid = "org.quiltmc.quilt-loader";
+        } else {
+            logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
             continue;
         }
-        logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
+        loaderVersion = id;
     }
 
     QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
@@ -329,19 +377,12 @@ bool FlameCreationTask::createInstance()
     auto components = instance.getPackProfile();
     components->buildingFromScratch();
     components->setComponentVersion("net.minecraft", mcVersion, true);
-    if (!forgeVersion.isEmpty()) {
-        // FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata.
-        if (forgeVersion == "recommended") {
-            if (forgemap.contains(mcVersion)) {
-                forgeVersion = forgemap[mcVersion];
-            } else {
-                logWarning(tr("Could not map recommended Forge version for Minecraft %1").arg(mcVersion));
-            }
-        }
-        components->setComponentVersion("net.minecraftforge", forgeVersion);
+    if (!loaderType.isEmpty()) {
+        auto version = getVersionForLoader(loaderUid, loaderType, loaderVersion, mcVersion);
+        if (version == Q_NULLPTR || version.isEmpty())
+            return false;
+        components->setComponentVersion(loaderUid, version);
     }
-    if (!fabricVersion.isEmpty())
-        components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion);
 
     if (m_instIcon != "default") {
         instance.setIconKey(m_instIcon);
@@ -502,7 +543,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
         m_files_job.reset();
         setError(reason);
     });
-    connect(m_files_job.get(), &NetJob::progress, this, [this](qint64 current, qint64 total){
+    connect(m_files_job.get(), &NetJob::progress, this, [this](qint64 current, qint64 total) {
         setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
         setProgress(current, total);
     });
@@ -545,7 +586,6 @@ void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
     setAbortable(true);
 }
 
-
 void FlameCreationTask::validateZIPResouces()
 {
     qDebug() << "Validating whether resources stored as .zip are in the right place";
@@ -569,7 +609,7 @@ void FlameCreationTask::validateZIPResouces()
             return localPath;
         };
 
-        auto installWorld = [this](QString worldPath){
+        auto installWorld = [this](QString worldPath) {
             qDebug() << "Installing World from" << worldPath;
             QFileInfo worldFileInfo(worldPath);
             World w(worldFileInfo);
@@ -586,29 +626,29 @@ void FlameCreationTask::validateZIPResouces()
         QString worldPath;
 
         switch (type) {
-            case PackedResourceType::Mod :
+            case PackedResourceType::Mod:
                 validatePath(fileName, targetFolder, "mods");
                 break;
-            case PackedResourceType::ResourcePack :
+            case PackedResourceType::ResourcePack:
                 validatePath(fileName, targetFolder, "resourcepacks");
                 break;
-            case PackedResourceType::TexturePack :
+            case PackedResourceType::TexturePack:
                 validatePath(fileName, targetFolder, "texturepacks");
                 break;
-            case PackedResourceType::DataPack :
+            case PackedResourceType::DataPack:
                 validatePath(fileName, targetFolder, "datapacks");
                 break;
-            case PackedResourceType::ShaderPack :
+            case PackedResourceType::ShaderPack:
                 // in theroy flame API can't do this but who knows, that *may* change ?
                 // better to handle it if it *does* occure in the future
                 validatePath(fileName, targetFolder, "shaderpacks");
                 break;
-            case PackedResourceType::WorldSave :
+            case PackedResourceType::WorldSave:
                 worldPath = validatePath(fileName, targetFolder, "saves");
                 installWorld(worldPath);
                 break;
-            case PackedResourceType::UNKNOWN :
-            default :
+            case PackedResourceType::UNKNOWN:
+            default:
                 qDebug() << "Can't Identify" << fileName << "at" << localPath << ", leaving it where it is.";
                 break;
         }
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h
index 0ae4735b..603d3693 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.h
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h
@@ -57,10 +57,7 @@ class FlameCreationTask final : public InstanceCreationTask {
                       QString id,
                       QString version_id,
                       QString original_instance_id = {})
-        : InstanceCreationTask()
-        , m_parent(parent)
-        , m_managed_id(std::move(id))
-        , m_managed_version_id(std::move(version_id))
+        : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id))
     {
         setStagingPath(staging_path);
         setParentSettings(global_settings);
@@ -78,6 +75,7 @@ class FlameCreationTask final : public InstanceCreationTask {
     void setupDownloadJob(QEventLoop&);
     void copyBlockedMods(QList<BlockedMod> const& blocked_mods);
     void validateZIPResouces();
+    QString getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion);
 
    private:
     QWidget* m_parent = nullptr;
-- 
cgit 


From f393aa684e74ca870eb2108e2b74a7c93a70c366 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Tue, 18 Jul 2023 23:59:43 +0300
Subject: wait to load metadata

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../flame/FlameInstanceCreationTask.cpp            | 24 ++++++++++++++--------
 1 file changed, 15 insertions(+), 9 deletions(-)

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index 710ec06a..e8453c60 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -255,17 +255,23 @@ bool FlameCreationTask::updateInstance()
     return false;
 }
 
-QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion)
+QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, QString loaderVersion, QString mcVersion)
 {
-    if (version == "recommended") {
+    if (loaderVersion == "recommended") {
         auto vlist = APPLICATION->metadataIndex()->get(uid);
         if (!vlist) {
             setError(tr("Failed to get local metadata index for %1").arg(uid));
-            return Q_NULLPTR;
+            return {};
         }
 
         if (!vlist->isLoaded()) {
-            vlist->load(Net::Mode::Online);
+            QEventLoop loadVersionLoop;
+            auto task = vlist->getLoadTask();
+            connect(task.get(), &Task::finished, &loadVersionLoop, &QEventLoop::quit);
+            if (!task->isRunning())
+                task->start();
+
+            loadVersionLoop.exec();
         }
 
         for (int i = 0; i < vlist->versions().size(); i++) {
@@ -289,15 +295,15 @@ QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType,
         }
 
         setError(tr("Failed to find version for %1 loader").arg(loaderType));
-        return Q_NULLPTR;
+        return {};
     }
 
-    if (version == Q_NULLPTR || version.isEmpty()) {
+    if (loaderVersion.isEmpty()) {
         emitFailed(tr("No loader version set for modpack!"));
-        return Q_NULLPTR;
+        return {};
     }
 
-    return version;
+    return loaderVersion;
 }
 
 bool FlameCreationTask::createInstance()
@@ -379,7 +385,7 @@ bool FlameCreationTask::createInstance()
     components->setComponentVersion("net.minecraft", mcVersion, true);
     if (!loaderType.isEmpty()) {
         auto version = getVersionForLoader(loaderUid, loaderType, loaderVersion, mcVersion);
-        if (version == Q_NULLPTR || version.isEmpty())
+        if (version.isEmpty())
             return false;
         components->setComponentVersion(loaderUid, version);
     }
-- 
cgit 


From b7bccb905829eebea039a32edf93606f5fc5defa Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 19 Jul 2023 12:27:02 +0300
Subject: removed subdirectory flag

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 launcher/ui/themes/ThemeManager.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp
index 9ed8e129..321f7db4 100644
--- a/launcher/ui/themes/ThemeManager.cpp
+++ b/launcher/ui/themes/ThemeManager.cpp
@@ -84,7 +84,7 @@ void ThemeManager::initializeThemes()
         QString themeFolder = QDir("./themes/").absoluteFilePath("");
         themeDebugLog() << "Theme Folder Path: " << themeFolder;
 
-        QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+        QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot);
         while (directoryIterator.hasNext()) {
             QDir dir(directoryIterator.next());
             QFileInfo themeJson(dir.absoluteFilePath("theme.json"));
@@ -208,7 +208,7 @@ void ThemeManager::initializeCatPacks()
 
     loadFiles(catpacksDir);
 
-    QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+    QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot);
     while (directoryIterator.hasNext()) {
         QDir dir(directoryIterator.next());
         QFileInfo manifest(dir.absoluteFilePath("catpack.json"));
-- 
cgit 


From f8d9cd9a0344d8afa806e7b3b73e8b3c59315d17 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Wed, 19 Jul 2023 23:08:16 +0300
Subject: use range for

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

(limited to 'launcher')

diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index e8453c60..29145d89 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -274,8 +274,7 @@ QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType,
             loadVersionLoop.exec();
         }
 
-        for (int i = 0; i < vlist->versions().size(); i++) {
-            auto version = vlist->versions().at(i);
+        for (auto version : vlist->versions()) {
             // first recommended build we find, we use.
             if (!version->isRecommended())
                 continue;
-- 
cgit 


From 6a01c277e8f98797e3325a2b249e59ee95f43c7e Mon Sep 17 00:00:00 2001
From: tjw123hh <tjw123hh@outlook.com>
Date: Mon, 24 Jul 2023 20:41:22 +0800
Subject: Delete some incorrect  tags

---
 launcher/ui/pages/global/APIPage.ui                     | 2 +-
 launcher/ui/pages/global/JavaPage.ui                    | 2 +-
 launcher/ui/pages/global/MinecraftPage.ui               | 2 +-
 launcher/ui/pages/instance/InstanceSettingsPage.ui      | 2 +-
 program_info/org.prismlauncher.PrismLauncher.desktop.in | 1 +
 5 files changed, 5 insertions(+), 4 deletions(-)
 mode change 100644 => 100755 program_info/org.prismlauncher.PrismLauncher.desktop.in

(limited to 'launcher')

diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui
index 40b89d91..492741ba 100644
--- a/launcher/ui/pages/global/APIPage.ui
+++ b/launcher/ui/pages/global/APIPage.ui
@@ -30,7 +30,7 @@
      </property>
      <widget class="QWidget" name="tab">
       <attribute name="title">
-       <string notr="true">Services</string>
+       <string>Services</string>
       </attribute>
       <layout class="QVBoxLayout" name="verticalLayout_2">
        <item>
diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui
index 6749cbe4..561cf79b 100644
--- a/launcher/ui/pages/global/JavaPage.ui
+++ b/launcher/ui/pages/global/JavaPage.ui
@@ -58,7 +58,7 @@
           <item row="2" column="0">
            <widget class="QLabel" name="labelPermGen">
             <property name="text">
-             <string notr="true">&amp;PermGen:</string>
+             <string>&amp;PermGen:</string>
             </property>
             <property name="buddy">
              <cstring>permGenSpinBox</cstring>
diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui
index a3188dcc..393b0f35 100644
--- a/launcher/ui/pages/global/MinecraftPage.ui
+++ b/launcher/ui/pages/global/MinecraftPage.ui
@@ -39,7 +39,7 @@
      </property>
      <widget class="QWidget" name="minecraftTab">
       <attribute name="title">
-       <string notr="true">General</string>
+       <string>General</string>
       </attribute>
       <layout class="QVBoxLayout" name="verticalLayout_3">
        <item>
diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui
index 323890b9..245433fe 100644
--- a/launcher/ui/pages/instance/InstanceSettingsPage.ui
+++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui
@@ -116,7 +116,7 @@
           <item row="2" column="0">
            <widget class="QLabel" name="labelPermGen">
             <property name="text">
-             <string notr="true">PermGen:</string>
+             <string>PermGen:</string>
             </property>
            </widget>
           </item>
diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in
old mode 100644
new mode 100755
index 20fabe9d..c85c2573
--- a/program_info/org.prismlauncher.PrismLauncher.desktop.in
+++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in
@@ -1,3 +1,4 @@
+#!/usr/bin/env xdg-open
 [Desktop Entry]
 Version=1.0
 Name=Prism Launcher
-- 
cgit 


From f505d43fc0399d944cad9e51ab6cc7189052cba1 Mon Sep 17 00:00:00 2001
From: TheKodeToad <TheKodeToad@proton.me>
Date: Mon, 24 Jul 2023 13:43:26 +0100
Subject: Fix token "0" being replaced

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
---
 launcher/minecraft/MinecraftInstance.cpp     | 2 +-
 launcher/minecraft/auth/AccountData.cpp      | 4 ++++
 launcher/minecraft/auth/MinecraftAccount.cpp | 2 +-
 3 files changed, 6 insertions(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 342e634f..3bcd4df8 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -843,7 +843,7 @@ QMap<QString, QString> MinecraftInstance::createCensorFilterFromSession(AuthSess
     {
         addToFilter(sessionRef.session, tr("<SESSION ID>"));
     }
-    if (sessionRef.access_token != "offline") {
+    if (sessionRef.access_token != "0") {
         addToFilter(sessionRef.access_token, tr("<ACCESS TOKEN>"));
     }
     if(sessionRef.client_token.size()) {
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 44f7e256..0b78cb0c 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -374,6 +374,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
     }
 
     yggdrasilToken = tokenFromJSONV3(data, "ygg");
+    // versions before 7.2 used "offline" as the offline token
+    if (yggdrasilToken.token == "offline")
+        yggdrasilToken.token = "0";
+
     minecraftProfile = profileFromJSONV3(data, "profile");
     if(!entitlementFromJSONV3(data, minecraftEntitlement)) {
         if(minecraftProfile.validity != Katabasis::Validity::None) {
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index d7b061e5..5d279af1 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -94,7 +94,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
 {
     auto account = makeShared<MinecraftAccount>();
     account->data.type = AccountType::Offline;
-    account->data.yggdrasilToken.token = "offline";
+    account->data.yggdrasilToken.token = "0";
     account->data.yggdrasilToken.validity = Katabasis::Validity::Certain;
     account->data.yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
     account->data.yggdrasilToken.extra["userName"] = username;
-- 
cgit 


From 280f041acb449d8eafc138c48339b258a6e99c64 Mon Sep 17 00:00:00 2001
From: tjw123hh <tjw123hh@outlook.com>
Date: Tue, 25 Jul 2023 17:35:31 +0800
Subject: Delete some incorrect `notr="true"` tags

Signed-off-by: tjw123hh <tjw123hh@outlook.com>
---
 launcher/ui/pages/global/LauncherPage.h                 | 2 +-
 program_info/org.prismlauncher.PrismLauncher.desktop.in | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

(limited to 'launcher')

diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h
index 33f66f1b..e06d9897 100644
--- a/launcher/ui/pages/global/LauncherPage.h
+++ b/launcher/ui/pages/global/LauncherPage.h
@@ -62,7 +62,7 @@ public:
 
     QString displayName() const override
     {
-        return "Launcher";
+        return tr("Launcher");
     }
     QIcon icon() const override
     {
diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in
index c85c2573..20fabe9d 100755
--- a/program_info/org.prismlauncher.PrismLauncher.desktop.in
+++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in
@@ -1,4 +1,3 @@
-#!/usr/bin/env xdg-open
 [Desktop Entry]
 Version=1.0
 Name=Prism Launcher
-- 
cgit 


From af59c4171344d6727c8d67205cc02406729250a3 Mon Sep 17 00:00:00 2001
From: seth <getchoo@tuta.io>
Date: Wed, 26 Jul 2023 16:20:30 -0400
Subject: fix: typo in task.h

Signed-off-by: seth <getchoo@tuta.io>
---
 launcher/InstanceImportTask.cpp                                | 6 +++---
 launcher/InstanceList.cpp                                      | 2 +-
 launcher/ResourceDownloadTask.cpp                              | 2 +-
 launcher/launch/steps/Update.cpp                               | 2 +-
 launcher/minecraft/MinecraftLoadAndCheck.cpp                   | 2 +-
 launcher/minecraft/MinecraftUpdate.cpp                         | 4 ++--
 launcher/minecraft/update/AssetUpdateTask.cpp                  | 4 ++--
 launcher/minecraft/update/FMLLibrariesTask.cpp                 | 2 +-
 launcher/minecraft/update/LibrariesTask.cpp                    | 2 +-
 launcher/modplatform/atlauncher/ATLPackInstallTask.cpp         | 4 ++--
 launcher/modplatform/flame/FileResolvingTask.cpp               | 6 +++---
 launcher/modplatform/flame/FlameInstanceCreationTask.cpp       | 4 ++--
 launcher/modplatform/flame/FlamePackExportTask.cpp             | 2 +-
 launcher/modplatform/legacy_ftb/PackInstallTask.cpp            | 2 +-
 launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 2 +-
 launcher/modplatform/technic/SingleZipPackInstallTask.cpp      | 2 +-
 launcher/modplatform/technic/SolderPackInstallTask.cpp         | 2 +-
 launcher/tasks/Task.cpp                                        | 2 +-
 launcher/tasks/Task.h                                          | 2 +-
 19 files changed, 27 insertions(+), 27 deletions(-)

(limited to 'launcher')

diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 352848f0..d6a96deb 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -99,7 +99,7 @@ void InstanceImportTask::executeTask()
 
         connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
         connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
-        connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress);
+        connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propagateStepProgress);
         connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed);
         connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted);
 
@@ -293,7 +293,7 @@ void InstanceImportTask::processFlame()
     });
     connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed);
     connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress);
-    connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
+    connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress);
     connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
     connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
 
@@ -385,7 +385,7 @@ void InstanceImportTask::processModrinth()
     });
     connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
     connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress);
-    connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
+    connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress);
     connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus);
     connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails);
     connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater);
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index b4c520cd..0485db19 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -799,7 +799,7 @@ class InstanceStaging : public Task {
         connect(child, &Task::status, this, &InstanceStaging::setStatus);
         connect(child, &Task::details, this, &InstanceStaging::setDetails);
         connect(child, &Task::progress, this, &InstanceStaging::setProgress);
-        connect(child, &Task::stepProgress, this, &InstanceStaging::propogateStepProgress);
+        connect(child, &Task::stepProgress, this, &InstanceStaging::propagateStepProgress);
         connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceded);
     }
 
diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp
index 06c03c77..8bb9b64e 100644
--- a/launcher/ResourceDownloadTask.cpp
+++ b/launcher/ResourceDownloadTask.cpp
@@ -54,7 +54,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
     m_filesNetJob->addNetAction(Net::Download::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename())));
     connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ResourceDownloadTask::downloadSucceeded);
     connect(m_filesNetJob.get(), &NetJob::progress, this, &ResourceDownloadTask::downloadProgressChanged);
-    connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propogateStepProgress);
+    connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propagateStepProgress);
     connect(m_filesNetJob.get(), &NetJob::failed, this, &ResourceDownloadTask::downloadFailed);
 
     addTask(m_filesNetJob);
diff --git a/launcher/launch/steps/Update.cpp b/launcher/launch/steps/Update.cpp
index 77c8a18e..8df2bc67 100644
--- a/launcher/launch/steps/Update.cpp
+++ b/launcher/launch/steps/Update.cpp
@@ -28,7 +28,7 @@ void Update::executeTask()
     {
         connect(m_updateTask.get(), &Task::finished, this, &Update::updateFinished);
         connect(m_updateTask.get(), &Task::progress, this, &Update::setProgress);
-        connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propogateStepProgress);
+        connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propagateStepProgress);
         connect(m_updateTask.get(), &Task::status, this, &Update::setStatus);
         connect(m_updateTask.get(), &Task::details, this, &Update::setDetails);
         emit progressReportingRequest();
diff --git a/launcher/minecraft/MinecraftLoadAndCheck.cpp b/launcher/minecraft/MinecraftLoadAndCheck.cpp
index 1c3f6fb7..2a369879 100644
--- a/launcher/minecraft/MinecraftLoadAndCheck.cpp
+++ b/launcher/minecraft/MinecraftLoadAndCheck.cpp
@@ -22,7 +22,7 @@ void MinecraftLoadAndCheck::executeTask()
     connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::subtaskFailed);
     connect(m_task.get(), &Task::aborted, this, [this]{ subtaskFailed(tr("Aborted")); });
     connect(m_task.get(), &Task::progress, this, &MinecraftLoadAndCheck::progress);
-    connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propogateStepProgress);
+    connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propagateStepProgress);
     connect(m_task.get(), &Task::status, this, &MinecraftLoadAndCheck::setStatus);
 }
 
diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp
index 35430bb0..236d0224 100644
--- a/launcher/minecraft/MinecraftUpdate.cpp
+++ b/launcher/minecraft/MinecraftUpdate.cpp
@@ -100,7 +100,7 @@ void MinecraftUpdate::next()
         disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed);
         disconnect(task.get(), &Task::aborted, this, &Task::abort);
         disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress);
-        disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress);
+        disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress);
         disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus);
         disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails);
     }
@@ -120,7 +120,7 @@ void MinecraftUpdate::next()
     connect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed);
     connect(task.get(), &Task::aborted, this, &Task::abort);
     connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress);
-    connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress);
+    connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress);
     connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus);
     connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails);
     // if the task is already running, do not start it again
diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp
index 31fd5eb1..fda85ba8 100644
--- a/launcher/minecraft/update/AssetUpdateTask.cpp
+++ b/launcher/minecraft/update/AssetUpdateTask.cpp
@@ -45,7 +45,7 @@ void AssetUpdateTask::executeTask()
     connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed);
     connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); });
     connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress);
-    connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propogateStepProgress);
+    connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress);
 
     qDebug() << m_inst->name() << ": Starting asset index download";
     downloadJob->start();
@@ -84,7 +84,7 @@ void AssetUpdateTask::assetIndexFinished()
         connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed);
         connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); });
         connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress);
-        connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propogateStepProgress);
+        connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress);
         downloadJob->start();
         return;
     }
diff --git a/launcher/minecraft/update/FMLLibrariesTask.cpp b/launcher/minecraft/update/FMLLibrariesTask.cpp
index 75e5c572..d9fa0595 100644
--- a/launcher/minecraft/update/FMLLibrariesTask.cpp
+++ b/launcher/minecraft/update/FMLLibrariesTask.cpp
@@ -75,7 +75,7 @@ void FMLLibrariesTask::executeTask()
     connect(dljob.get(), &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed);
     connect(dljob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); });
     connect(dljob.get(), &NetJob::progress, this, &FMLLibrariesTask::progress);
-    connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propogateStepProgress);
+    connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propagateStepProgress);
     downloadJob.reset(dljob);
     downloadJob->start();
 }
diff --git a/launcher/minecraft/update/LibrariesTask.cpp b/launcher/minecraft/update/LibrariesTask.cpp
index 415b9a66..9d1c0295 100644
--- a/launcher/minecraft/update/LibrariesTask.cpp
+++ b/launcher/minecraft/update/LibrariesTask.cpp
@@ -70,7 +70,7 @@ void LibrariesTask::executeTask()
     connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed);
     connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); });
     connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress);
-    connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propogateStepProgress);
+    connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propagateStepProgress);
 
     downloadJob->start();
 }
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 22ea02da..82a51c27 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -684,7 +684,7 @@ void PackInstallTask::installConfigs()
         abortable = true;
         setProgress(current, total);
     });
-    connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress);
+    connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress);
     connect(jobPtr.get(), &NetJob::aborted, [&]{
         abortable = false;
         jobPtr.reset();
@@ -852,7 +852,7 @@ void PackInstallTask::downloadMods()
         abortable = true;
         setProgress(current, total);
     });
-    connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress);
+    connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress);
     connect(jobPtr.get(), &NetJob::aborted, [&]
     {
         abortable = false;
diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp
index 34bd401d..ae168bbd 100644
--- a/launcher/modplatform/flame/FileResolvingTask.cpp
+++ b/launcher/modplatform/flame/FileResolvingTask.cpp
@@ -52,7 +52,7 @@ void Flame::FileResolvingTask::executeTask()
         stepProgress(*step_progress);
         emitFailed(reason);
     });
-    connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress);
+    connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress);
     connect(m_dljob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
         qDebug() << "Resolve slug progress" << current << total;
         step_progress->update(current, total);
@@ -118,7 +118,7 @@ void Flame::FileResolvingTask::netJobFinished()
         stepProgress(*step_progress);
         emitFailed(reason);
     });
-    connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress);
+    connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress);
     connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
         qDebug() << "Resolve slug progress" << current << total;
         step_progress->update(current, total);
@@ -195,7 +195,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished()
             stepProgress(*step_progress);
             emitFailed(reason);
         });
-        connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress);
+        connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress);
         connect(m_slugJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
             qDebug() << "Resolve slug progress" << current << total;
             step_progress->update(current, total);
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index 29145d89..e17cf1c2 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -432,7 +432,7 @@ bool FlameCreationTask::createInstance()
     });
     connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress);
     connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus);
-    connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propogateStepProgress);
+    connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propagateStepProgress);
     connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails);
     m_mod_id_resolver->start();
 
@@ -552,7 +552,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
         setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
         setProgress(current, total);
     });
-    connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propogateStepProgress);
+    connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propagateStepProgress);
     connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
 
     setStatus(tr("Downloading mods..."));
diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp
index ac0da214..87bf780c 100644
--- a/launcher/modplatform/flame/FlamePackExportTask.cpp
+++ b/launcher/modplatform/flame/FlamePackExportTask.cpp
@@ -166,7 +166,7 @@ void FlamePackExportTask::collectHashes()
         stepProgress(*progressStep);
         emitFailed(reason);
     });
-    connect(hashingTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress);
+    connect(hashingTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propagateStepProgress);
 
     connect(hashingTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) {
         progressStep->update(current, total);
diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
index a4c78397..1afe5783 100644
--- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
+++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
@@ -81,7 +81,7 @@ void PackInstallTask::downloadPack()
 
     connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::unzip);
     connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::emitFailed);
-    connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress);
+    connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress);
     connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::emitAborted);
 
     netJobContainer->start();
diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
index 76f07277..bd0b828c 100644
--- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
@@ -267,7 +267,7 @@ bool ModrinthCreationTask::createInstance()
         setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
         setProgress(current, total); 
     });
-    connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propogateStepProgress);
+    connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propagateStepProgress);
 
     setStatus(tr("Downloading mods..."));
     m_files_job->start();
diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp
index f07ca24a..ab91c466 100644
--- a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp
+++ b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp
@@ -50,7 +50,7 @@ void Technic::SingleZipPackInstallTask::executeTask()
     auto job = m_filesNetJob.get();
     connect(job, &NetJob::succeeded, this, &Technic::SingleZipPackInstallTask::downloadSucceeded);
     connect(job, &NetJob::progress, this, &Technic::SingleZipPackInstallTask::downloadProgressChanged);
-    connect(job, &NetJob::stepProgress, this, &Technic::SingleZipPackInstallTask::propogateStepProgress);
+    connect(job, &NetJob::stepProgress, this, &Technic::SingleZipPackInstallTask::propagateStepProgress);
     connect(job, &NetJob::failed, this, &Technic::SingleZipPackInstallTask::downloadFailed);
     m_filesNetJob->start();
 }
diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp
index 6a05d17a..cc1d261e 100644
--- a/launcher/modplatform/technic/SolderPackInstallTask.cpp
+++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp
@@ -126,7 +126,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded()
 
     connect(m_filesNetJob.get(), &NetJob::succeeded, this, &Technic::SolderPackInstallTask::downloadSucceeded);
     connect(m_filesNetJob.get(), &NetJob::progress, this, &Technic::SolderPackInstallTask::downloadProgressChanged);
-    connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &Technic::SolderPackInstallTask::propogateStepProgress);
+    connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &Technic::SolderPackInstallTask::propagateStepProgress);
     connect(m_filesNetJob.get(), &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed);
     connect(m_filesNetJob.get(), &NetJob::aborted, this, &Technic::SolderPackInstallTask::downloadAborted);
     m_filesNetJob->start();
diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp
index 29c55cd4..fd82ec00 100644
--- a/launcher/tasks/Task.cpp
+++ b/launcher/tasks/Task.cpp
@@ -161,7 +161,7 @@ void Task::emitSucceeded()
     emit finished();
 }
 
-void Task::propogateStepProgress(TaskStepProgress const& task_progress)
+void Task::propagateStepProgress(TaskStepProgress const& task_progress)
 {
     emit stepProgress(task_progress);
 }
diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h
index 6d8bbbb4..57177697 100644
--- a/launcher/tasks/Task.h
+++ b/launcher/tasks/Task.h
@@ -167,7 +167,7 @@ class Task : public QObject, public QRunnable {
     virtual void emitAborted();
     virtual void emitFailed(QString reason = "");
 
-    virtual void propogateStepProgress(TaskStepProgress const& task_progress);
+    virtual void propagateStepProgress(TaskStepProgress const& task_progress);
 
    public slots:
     void setStatus(const QString& status);
-- 
cgit