From bdd8698e54826977cb1c44aaab23452546b03253 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 25 Mar 2024 01:05:48 +0200 Subject: [PATCH] implement uninstalling in new ui :3 --- loader/src/ui/mods/list/ModItem.cpp | 11 ++ .../ui/mods/popups/ConfirmUninstallPopup.cpp | 77 +++++++++ .../ui/mods/popups/ConfirmUninstallPopup.hpp | 22 +++ loader/src/ui/mods/popups/ModPopup.cpp | 159 +++++++++++------- loader/src/ui/mods/popups/ModPopup.hpp | 6 +- 5 files changed, 215 insertions(+), 60 deletions(-) create mode 100644 loader/src/ui/mods/popups/ConfirmUninstallPopup.cpp create mode 100644 loader/src/ui/mods/popups/ConfirmUninstallPopup.hpp diff --git a/loader/src/ui/mods/list/ModItem.cpp b/loader/src/ui/mods/list/ModItem.cpp index 2513332d..6ac55a65 100644 --- a/loader/src/ui/mods/list/ModItem.cpp +++ b/loader/src/ui/mods/list/ModItem.cpp @@ -169,6 +169,17 @@ void ModItem::updateState() { // Update enable toggle state if (m_enableToggle && m_source.asMod()) { m_enableToggle->toggle(m_source.asMod()->isOrWillBeEnabled()); + + // Disable the toggle if the mod has been uninstalled + if (modRequestedActionIsUninstall(m_source.asMod()->getRequestedAction())) { + m_enableToggle->setEnabled(false); + auto off = typeinfo_cast(m_enableToggle->m_offButton->getNormalImage()); + auto on = typeinfo_cast(m_enableToggle->m_onButton->getNormalImage()); + off->setColor(ccGRAY); + off->setOpacity(105); + on->setColor(ccGRAY); + on->setOpacity(105); + } } } diff --git a/loader/src/ui/mods/popups/ConfirmUninstallPopup.cpp b/loader/src/ui/mods/popups/ConfirmUninstallPopup.cpp new file mode 100644 index 00000000..af724441 --- /dev/null +++ b/loader/src/ui/mods/popups/ConfirmUninstallPopup.cpp @@ -0,0 +1,77 @@ +#include "ConfirmUninstallPopup.hpp" + +bool ConfirmUninstallPopup::setup(Mod* mod) { + m_mod = mod; + + this->setTitle("Uninstall " + mod->getName()); + + auto text = TextArea::create( + fmt::format("Are you sure you want to \nuninstall {}?", mod->getName()), + "chatFont.fnt", + 1.f, m_size.width - 35, + ccp(.5f, .5f), 20.f, false + ); + m_mainLayer->addChildAtPosition(text, Anchor::Center, ccp(0, 20)); + + auto deleteDataLabel = CCLabelBMFont::create("Delete the Mod's save data", "bigFont.fnt"); + deleteDataLabel->setScale(.35f); + m_buttonMenu->addChildAtPosition(deleteDataLabel, Anchor::Center, ccp(-70, -15), ccp(0, .5f)); + + m_deleteDataToggle = CCMenuItemToggler::createWithStandardSprites(this, nullptr, .6f); + m_buttonMenu->addChildAtPosition(m_deleteDataToggle, Anchor::Center, ccp(-88, -15)); + + auto cancelSpr = ButtonSprite::create("Cancel", "goldFont.fnt", "GJ_button_01.png", .8f); + cancelSpr->setScale(.85f); + auto cancelBtn = CCMenuItemSpriteExtra::create( + cancelSpr, this, menu_selector(ConfirmUninstallPopup::onClose) + ); + m_buttonMenu->addChildAtPosition(cancelBtn, Anchor::Bottom, ccp(-52, 28)); + + auto uninstallSpr = ButtonSprite::create("Uninstall", "goldFont.fnt", "GJ_button_01.png", .8f); + uninstallSpr->setScale(.85f); + auto uninstallBtn = CCMenuItemSpriteExtra::create( + uninstallSpr, this, menu_selector(ConfirmUninstallPopup::onUninstall) + ); + m_buttonMenu->addChildAtPosition(uninstallBtn, Anchor::Bottom, ccp(42, 28)); + + return true; +} + +void ConfirmUninstallPopup::onUninstall(CCObject*) { + auto res = m_mod->uninstall(m_deleteDataToggle->isToggled()); + + if (res) { + FLAlertLayer::create( + "Mod Uninstalled", + m_mod->getName() + " has been uninstalled!", + "OK" + )->show(); + } + else { + FLAlertLayer::create( + "Error Uninstalling", + "Error uninstalling " + m_mod->getName() + ": " + res.unwrapErr(), + "OK" + )->show(); + } + + if (m_updateParentState) { + m_updateParentState(); + } + + this->onClose(nullptr); +} + +ConfirmUninstallPopup* ConfirmUninstallPopup::create(Mod* mod) { + auto ret = new ConfirmUninstallPopup(); + if (ret && ret->initAnchored(300, 150, mod, "square01_001.png", { 0, 0, 94, 94 })) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; +} + +void ConfirmUninstallPopup::onUpdateParentState(MiniFunction listener) { + m_updateParentState = listener; +} diff --git a/loader/src/ui/mods/popups/ConfirmUninstallPopup.hpp b/loader/src/ui/mods/popups/ConfirmUninstallPopup.hpp new file mode 100644 index 00000000..99064681 --- /dev/null +++ b/loader/src/ui/mods/popups/ConfirmUninstallPopup.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +using namespace geode::prelude; + +class ConfirmUninstallPopup : public Popup { +protected: + Mod* m_mod; + CCMenuItemToggler* m_deleteDataToggle; + MiniFunction m_updateParentState = nullptr; + + bool setup(Mod* mod) override; + + void onUninstall(CCObject*); + +public: + static ConfirmUninstallPopup* create(Mod* mod); + + // todo: replace all of these with a single event + void onUpdateParentState(MiniFunction listener); +}; diff --git a/loader/src/ui/mods/popups/ModPopup.cpp b/loader/src/ui/mods/popups/ModPopup.cpp index 5ba9cd7e..f047c61e 100644 --- a/loader/src/ui/mods/popups/ModPopup.cpp +++ b/loader/src/ui/mods/popups/ModPopup.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "ConfirmUninstallPopup.hpp" bool ModPopup::setup(ModSource&& src) { m_source = std::move(src); @@ -226,47 +227,76 @@ bool ModPopup::setup(ModSource&& src) { m_installMenu->setContentSize(installContainer->getContentSize() - ccp(10, 10)); m_installMenu->setAnchorPoint({ .5f, .5f }); - for (auto stat : std::initializer_list> { - { - &m_enableBtn, - "GJ_completesIcon_001.png", "Enable", "GJ_button_01.png", - "GJ_deleteIcon_001.png", "Disable", "GJ_button_06.png", - menu_selector(ModPopup::onEnable) - }, - { - &m_installBtn, - "GJ_downloadsIcon_001.png", "Install", "GE_button_01.png"_spr, - "edit_delBtn_001.png", "Uninstall", "GE_button_05.png"_spr, - nullptr - }, - }) { - auto onSpr = createGeodeButton( - CCSprite::createWithSpriteFrameName(std::get<1>(stat)), - std::get<2>(stat), - std::get<3>(stat) - ); - onSpr->setScale(.5f); - auto offSpr = createGeodeButton( - CCSprite::createWithSpriteFrameName(std::get<4>(stat)), - std::get<5>(stat), - std::get<6>(stat) - ); - offSpr->setScale(.5f); - auto toggle = CCMenuItemToggler::create(offSpr, onSpr, this, std::get<7>(stat)); - toggle->m_notClickable = true; - m_installMenu->addChild(toggle); - *std::get<0>(stat) = toggle; - } + auto enableModOffSpr = createGeodeButton( + CCSprite::createWithSpriteFrameName("GJ_completesIcon_001.png"), + "Enable", + "GJ_button_01.png" + ); + enableModOffSpr->setScale(.5f); + auto enableModOnSpr = createGeodeButton( + CCSprite::createWithSpriteFrameName("GJ_deleteIcon_001.png"), + "Disable", + "GJ_button_06.png" + ); + enableModOnSpr->setScale(.5f); + m_enableBtn = CCMenuItemToggler::create( + enableModOffSpr, enableModOnSpr, + this, menu_selector(ModPopup::onEnable) + ); + m_enableBtn->m_notClickable = true; + m_installMenu->addChild(m_enableBtn); + + auto reenableModOffSpr = createGeodeButton( + CCSprite::createWithSpriteFrameName("reset.png"_spr), + "Re-Enable", + "GE_button_05.png"_spr + ); + reenableModOffSpr->setScale(.5f); + auto reenableModOnSpr = createGeodeButton( + CCSprite::createWithSpriteFrameName("reset.png"_spr), + "Re-Disable", + "GE_button_05.png"_spr + ); + reenableModOnSpr->setScale(.5f); + m_reenableBtn = CCMenuItemToggler::create( + reenableModOffSpr, reenableModOnSpr, + this, menu_selector(ModPopup::onEnable) + ); + m_reenableBtn->m_notClickable = true; + m_installMenu->addChild(m_reenableBtn); + + auto installModSpr = createGeodeButton( + CCSprite::createWithSpriteFrameName("GJ_downloadsIcon_001.png"), + "Install", + "GE_button_01.png"_spr + ); + installModSpr->setScale(.5f); + m_installBtn = CCMenuItemSpriteExtra::create( + installModSpr, this, nullptr + ); + m_installMenu->addChild(m_installBtn); + + auto uninstallModSpr = createGeodeButton( + CCSprite::createWithSpriteFrameName("delete-white.png"_spr), + "Uninstall", + "GE_button_05.png"_spr + ); + uninstallModSpr->setScale(.5f); + m_uninstallBtn = CCMenuItemSpriteExtra::create( + uninstallModSpr, this, menu_selector(ModPopup::onUninstall) + ); + m_installMenu->addChild(m_uninstallBtn); + + m_installStatusLabel = CCLabelBMFont::create("", "bigFont.fnt"); + m_installStatusLabel->setOpacity(120); + m_installMenu->addChild(m_installStatusLabel); m_installMenu->setLayout( RowLayout::create() ->setDefaultScaleLimits(.1f, 1) ->setAxisAlignment(AxisAlignment::Center) ); + m_installMenu->getLayout()->ignoreInvisibleChildren(true); installContainer->addChildAtPosition(m_installMenu, Anchor::Center); leftColumn->addChild(installContainer); @@ -408,39 +438,32 @@ bool ModPopup::setup(ModSource&& src) { } void ModPopup::updateState() { - auto shouldEnableEnableBtn = - m_source.asMod() && - !modRequestedActionIsUninstall(m_source.asMod()->getRequestedAction()); - - auto shouldEnableInstallBtn = - !modRequestedActionIsToggle(m_source.asMod()->getRequestedAction()); - + auto asMod = m_source.asMod(); + auto asServer = m_source.asServer(); auto wantsRestart = m_source.wantsRestart(); - auto enableBtnOff = static_cast(m_enableBtn->m_offButton->getNormalImage()); - auto enableBtnOn = static_cast(m_enableBtn->m_onButton->getNormalImage()); - auto installBtnOff = static_cast(m_installBtn->m_offButton->getNormalImage()); - auto installBtnOn = static_cast(m_installBtn->m_onButton->getNormalImage()); + m_enableBtn->toggle(asMod && asMod->isOrWillBeEnabled()); + m_enableBtn->setVisible(asMod && asMod->getRequestedAction() == ModRequestedAction::None); - m_enableBtn->toggle(m_source.asMod() && m_source.asMod()->isOrWillBeEnabled()); - m_enableBtn->setEnabled(shouldEnableEnableBtn); - enableBtnOff->setOpacity(shouldEnableEnableBtn ? 255 : 105); - enableBtnOff->setColor(shouldEnableEnableBtn ? ccc3(255, 255, 255) : ccc3(155, 155, 155)); - enableBtnOn->setOpacity(shouldEnableEnableBtn ? 255 : 105); - enableBtnOn->setColor(shouldEnableEnableBtn ? ccc3(255, 255, 255) : ccc3(155, 155, 155)); + m_reenableBtn->toggle(m_enableBtn->isToggled()); + m_reenableBtn->setVisible(asMod && modRequestedActionIsToggle(asMod->getRequestedAction())); - // todo: uninstall just installed server mods - m_installBtn->toggle(m_source.asMod() && modRequestedActionIsUninstall(m_source.asMod()->getRequestedAction())); - m_installBtn->setEnabled(shouldEnableInstallBtn); - installBtnOff->setOpacity(shouldEnableInstallBtn ? 255 : 105); - installBtnOff->setColor(shouldEnableInstallBtn ? ccc3(255, 255, 255) : ccc3(155, 155, 155)); - installBtnOn->setOpacity(shouldEnableInstallBtn ? 255 : 105); - installBtnOn->setColor(shouldEnableInstallBtn ? ccc3(255, 255, 255) : ccc3(155, 155, 155)); + m_installBtn->setVisible(asServer); + m_uninstallBtn->setVisible(asMod && asMod->getRequestedAction() == ModRequestedAction::None); m_installBG->setColor(wantsRestart ? to3B(ColorProvider::get()->color("mod-list-restart-required-label"_spr)) : ccc3(0, 0, 0)); m_installBG->setOpacity(wantsRestart ? 40 : 75); m_restartRequiredLabel->setVisible(wantsRestart); + if (asMod && modRequestedActionIsUninstall(asMod->getRequestedAction())) { + m_installStatusLabel->setString("Mod has been uninstalled"); + } + else { + m_installStatusLabel->setString(""); + } + + m_installMenu->updateLayout(); + // Propagate update up the chain if (m_updateParentState) { m_updateParentState(); @@ -633,6 +656,24 @@ void ModPopup::onEnable(CCObject*) { this->updateState(); } +void ModPopup::onUninstall(CCObject*) { + if (auto mod = m_source.asMod()) { + auto popup = ConfirmUninstallPopup::create(mod); + popup->onUpdateParentState([this] { + this->updateState(); + this->onClose(nullptr); + }); + popup->show(); + } + else { + FLAlertLayer::create( + "Error Uninstalling Mod", + "This mod can not be uninstalled! (It is not installed at all)", + "OK" + )->show(); + } +} + void ModPopup::onLink(CCObject* sender) { auto url = static_cast(static_cast(sender)->getUserObject("url")); web::openLinkInBrowser(url->getCString()); diff --git a/loader/src/ui/mods/popups/ModPopup.hpp b/loader/src/ui/mods/popups/ModPopup.hpp index 8ba153b7..a8a9d98e 100644 --- a/loader/src/ui/mods/popups/ModPopup.hpp +++ b/loader/src/ui/mods/popups/ModPopup.hpp @@ -20,7 +20,10 @@ protected: CCNode* m_tags; CCMenu* m_installMenu; CCMenuItemToggler* m_enableBtn; - CCMenuItemToggler* m_installBtn; + CCMenuItemToggler* m_reenableBtn; + CCMenuItemSpriteExtra* m_uninstallBtn; + CCMenuItemSpriteExtra* m_installBtn; + CCLabelBMFont* m_installStatusLabel; CCScale9Sprite* m_installBG; ButtonSprite* m_restartRequiredLabel; CCNode* m_rightColumn; @@ -42,6 +45,7 @@ protected: void loadTab(Tab tab); void onTab(CCObject* sender); void onEnable(CCObject*); + void onUninstall(CCObject*); void onLink(CCObject*); void onSupport(CCObject*);