From dd1d83558f62c26002370c1706103d4a4e0d0612 Mon Sep 17 00:00:00 2001 From: Justin <52604018+hiimjustin000@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:30:58 -0500 Subject: [PATCH] Add a button that copies the mod list (#1039) * New image arguments format * add ampersand support whoops * first moves oh lord * it's finished holy moly * made it slightly better * almost forgot * texture revamp by @Alphalaneous * why is it not loading * whoops * FINALLY * targetsOutdatedVersion * i love abi breaks * how's this * this thing * this is driving me nuts --- loader/resources/mod.json.in | 4 ++ loader/src/loader/CopyButtonSetting.cpp | 43 ++++++++++++++ loader/src/loader/CopyButtonSetting.hpp | 76 +++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 loader/src/loader/CopyButtonSetting.cpp create mode 100644 loader/src/loader/CopyButtonSetting.hpp diff --git a/loader/resources/mod.json.in b/loader/resources/mod.json.in index ea3f2df8..7ccb494b 100644 --- a/loader/resources/mod.json.in +++ b/loader/resources/mod.json.in @@ -91,6 +91,10 @@ "name": "Expand Installed Mods List", "description": "Make the installed mods list a single infinite scrollable list instead of having pages" }, + "copy-mods": { + "type": "custom:copy-mods", + "name": "" + }, "developer-title": { "type": "title", "name": "Developer Settings" diff --git a/loader/src/loader/CopyButtonSetting.cpp b/loader/src/loader/CopyButtonSetting.cpp new file mode 100644 index 00000000..ef160414 --- /dev/null +++ b/loader/src/loader/CopyButtonSetting.cpp @@ -0,0 +1,43 @@ +#include "CopyButtonSetting.hpp" +#include + +$on_mod(Loaded) { + (void)Mod::get()->registerCustomSettingType("copy-mods", &CopyButtonSetting::parse); +} + +SettingNodeV3* CopyButtonSetting::createNode(float width) { + return CopyButtonSettingNode::create(std::static_pointer_cast(shared_from_this()), width); +} + +void CopyButtonSettingNode::onCopy(CCObject*) { + auto mods = Loader::get()->getAllMods(); + if (mods.empty()) { + Notification::create("No mods installed", NotificationIcon::Info, 0.5f)->show(); + return; + } + + std::sort(mods.begin(), mods.end(), [](Mod* a, Mod* b) { + auto const s1 = a->getID(); + auto const s2 = b->getID(); + return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), [](auto a, auto b) { + return std::tolower(a) < std::tolower(b); + }); + }); + + std::string modsList; + using namespace std::string_view_literals; + for (int i = 0; i < mods.size(); i++) { + auto& mod = mods[i]; + modsList += fmt::format("{} | [{}] {}{}", + mod->isEnabled() ? "x"sv : + mod->hasLoadProblems() ? "!"sv : + mod->targetsOutdatedVersion() ? "*"sv : + " "sv, + mod->getVersion().toVString(), mod->getID(), + i < mods.size() ? "\n" : "" + ); + } + clipboard::write(modsList); + + Notification::create("Mods list copied to clipboard", NotificationIcon::Info, 0.5f)->show(); +} diff --git a/loader/src/loader/CopyButtonSetting.hpp b/loader/src/loader/CopyButtonSetting.hpp new file mode 100644 index 00000000..07c3c47d --- /dev/null +++ b/loader/src/loader/CopyButtonSetting.hpp @@ -0,0 +1,76 @@ +#include +#include + +using namespace geode::prelude; + +class CopyButtonSetting : public SettingV3 { +public: + static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { + auto res = std::make_shared(); + auto root = checkJson(json, "CopyButtonSetting"); + + res->init(key, modID, root); + res->parseNameAndDescription(root); + + return root.ok(std::static_pointer_cast(res)); + } + + bool load(matjson::Value const& json) override { + return true; + } + bool save(matjson::Value& json) const override { + return true; + } + + bool isDefaultValue() const override { + return true; + } + void reset() override {} + + SettingNodeV3* createNode(float width) override; +}; + +class CopyButtonSettingNode : public SettingNodeV3 { +protected: + bool init(std::shared_ptr setting, float width) { + if (!SettingNodeV3::init(setting, width)) + return false; + + auto buttonSprite = createGeodeButton("Copy Mods"); + buttonSprite->setScale(.5f); + auto button = CCMenuItemSpriteExtra::create( + buttonSprite, this, menu_selector(CopyButtonSettingNode::onCopy) + ); + this->getButtonMenu()->addChildAtPosition(button, Anchor::Center); + this->getButtonMenu()->setPosition(getContentSize() / 2); + this->getButtonMenu()->setAnchorPoint({ .5f, .5f }); + this->getButtonMenu()->updateLayout(); + + this->updateState(nullptr); + + return true; + } + + void onCopy(CCObject*); + + void onCommit() override {} + void onResetToDefault() override {} + +public: + static CopyButtonSettingNode* create(std::shared_ptr setting, float width) { + auto ret = new CopyButtonSettingNode(); + if (ret && ret->init(setting, width)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } + + bool hasUncommittedChanges() const override { + return false; + } + bool hasNonDefaultValue() const override { + return false; + } +};