add mod list sorting

This commit is contained in:
HJfod 2024-04-01 22:02:04 +03:00
parent 2e482cedfb
commit 6304e8c6d7
6 changed files with 110 additions and 20 deletions

View file

@ -1,6 +1,7 @@
#include "ModList.hpp"
#include <Geode/utils/ColorProvider.hpp>
#include "../popups/FiltersPopup.hpp"
#include "../popups/SortPopup.hpp"
#include "../GeodeStyle.hpp"
#include "../ModsLayer.hpp"
@ -38,14 +39,14 @@ bool ModList::init(ModListSource* src, CCSize const& size) {
searchBG->ignoreAnchorPointForPosition(false);
m_searchMenu->addChildAtPosition(searchBG, Anchor::Center);
m_searchInput = TextInput::create(size.width + 25, "Search Mods");
m_searchInput = TextInput::create(size.width - 5, "Search Mods");
m_searchInput->setScale(.75f);
m_searchInput->setAnchorPoint({ 0, .5f });
m_searchInput->setTextAlign(TextInputAlign::Left);
m_searchInput->setCallback([this](auto const&) {
// If the source is already in memory, we can immediately update the
// search query
if (m_source->isInstalledMods()) {
if (typeinfo_cast<InstalledModListSource*>(m_source)) {
m_source->search(m_searchInput->getString());
return;
}
@ -66,11 +67,15 @@ bool ModList::init(ModListSource* src, CCSize const& size) {
m_searchMenu->addChildAtPosition(m_searchInput, Anchor::Left, ccp(7.5f, 0));
auto searchFiltersMenu = CCMenu::create();
searchFiltersMenu->setContentWidth(size.width - m_searchInput->getScaledContentWidth() - 10);
searchFiltersMenu->setContentWidth(size.width - m_searchInput->getScaledContentWidth() - 5);
searchFiltersMenu->setAnchorPoint({ 1, .5f });
searchFiltersMenu->setScale(.75f);
// todo: sort button
auto sortBtn = CCMenuItemSpriteExtra::create(
GeodeSquareSprite::createWithSpriteFrameName("GJ_sortIcon_001.png"),
this, menu_selector(ModList::onSort)
);
searchFiltersMenu->addChild(sortBtn);
auto filterBtn = CCMenuItemSpriteExtra::create(
GeodeSquareSprite::createWithSpriteFrameName("GJ_filterIcon_001.png"),
@ -93,7 +98,7 @@ bool ModList::init(ModListSource* src, CCSize const& size) {
m_topContainer->addChild(m_searchMenu);
// Check for updates on installed mods, and show an update all button if there are some
if (m_source->isInstalledMods()) {
if (typeinfo_cast<InstalledModListSource*>(m_source)) {
m_checkUpdatesListener.bind(this, &ModList::onCheckUpdates);
m_checkUpdatesListener.setFilter(ModsLayer::checkInstalledModsForUpdates().listen());
@ -464,6 +469,10 @@ void ModList::onFilters(CCObject*) {
FiltersPopup::create(m_source)->show();
}
void ModList::onSort(CCObject*) {
SortPopup::create(m_source)->show();
}
void ModList::onClearFilters(CCObject*) {
m_searchInput->setString("", true);
}

View file

@ -51,6 +51,7 @@ protected:
void onPage(CCObject*);
void onShowStatusDetails(CCObject*);
void onFilters(CCObject*);
void onSort(CCObject*);
void onClearFilters(CCObject*);
void onToggleUpdates(CCObject*);
void onUpdateAll(CCObject*);

View file

@ -0,0 +1,72 @@
#include "SortPopup.hpp"
bool SortPopup::setup(ModListSource* src) {
m_noElasticity = true;
m_source = src;
this->setTitle("Search Sorting");
auto container = CCNode::create();
container->setContentSize({ 200, 115 });
if (auto server = typeinfo_cast<ServerModListSource*>(src)) {
for (auto& [name, sort] : std::initializer_list<std::pair<const char*, server::ModsSort>> {
{ "Most Downloads", server::ModsSort::Downloads },
{ "Recently Published", server::ModsSort::RecentlyPublished },
{ "Recently Updated", server::ModsSort::RecentlyUpdated },
}) {
auto node = CCMenu::create();
node->setContentSize({ container->getContentWidth(), 22 });
auto toggle = CCMenuItemToggler::createWithStandardSprites(
this, menu_selector(SortPopup::onSelect), .6f
);
toggle->m_notClickable = true;
toggle->setUserData(reinterpret_cast<void*>(sort));
if (server->getQuery().sorting == sort) {
toggle->toggle(true);
m_selected = static_cast<size_t>(sort);
}
node->addChildAtPosition(toggle, Anchor::Left, ccp(15, 0));
m_options.push_back(toggle);
auto label = CCLabelBMFont::create(name, "bigFont.fnt");
label->setScale(.5f);
node->addChildAtPosition(label, Anchor::Left, ccp(30, 0), ccp(0, .5f));
container->addChild(node);
}
}
container->setLayout(
ColumnLayout::create()
->setAxisReverse(true)
);
m_mainLayer->addChildAtPosition(container, Anchor::Center, ccp(0, -5), ccp(.5f, .5f));
return true;
}
void SortPopup::onSelect(CCObject* sender) {
m_selected = reinterpret_cast<uintptr_t>(static_cast<CCMenuItemToggler*>(sender)->getUserData());
for (auto option : m_options) {
option->toggle(m_selected == reinterpret_cast<uintptr_t>(option->getUserData()));
}
}
void SortPopup::onClose(CCObject* sender) {
if (auto server = typeinfo_cast<ServerModListSource*>(m_source)) {
server->getQueryMut()->sorting = static_cast<server::ModsSort>(m_selected);
}
Popup::onClose(sender);
}
SortPopup* SortPopup::create(ModListSource* src) {
auto ret = new SortPopup();
if (ret && ret->init(230, 165, src)) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}

View file

@ -0,0 +1,23 @@
#pragma once
#include <Geode/ui/Popup.hpp>
#include "../sources/ModListSource.hpp"
#include "../GeodeStyle.hpp"
#include <server/Server.hpp>
using namespace geode::prelude;
class SortPopup : public GeodePopup<ModListSource*> {
protected:
ModListSource* m_source;
std::vector<CCMenuItemToggler*> m_options;
size_t m_selected;
bool setup(ModListSource* src) override;
void onClose(CCObject* sender) override;
void onSelect(CCObject*);
public:
static SortPopup* create(ModListSource* src);
};

View file

@ -246,10 +246,6 @@ InvalidateQueryAfter<InstalledModsQuery> InstalledModListSource::getQueryMut() {
return InvalidateQueryAfter(m_query, this);
}
bool InstalledModListSource::isInstalledMods() const {
return true;
}
bool InstalledModListSource::wantsRestart() const {
for (auto mod : Loader::get()->getAllMods()) {
if (mod->getRequestedAction() != ModRequestedAction::None) {
@ -355,10 +351,6 @@ InvalidateQueryAfter<server::ModsQuery> ServerModListSource::getQueryMut() {
return InvalidateQueryAfter(m_query, this);
}
bool ServerModListSource::isInstalledMods() const {
return false;
}
bool ServerModListSource::wantsRestart() const {
// todo
return false;
@ -385,9 +377,6 @@ std::unordered_set<std::string> ModPackListSource::getModTags() const {
}
void ModPackListSource::setModTags(std::unordered_set<std::string> const& set) {}
bool ModPackListSource::isInstalledMods() const {
return false;
}
bool ModPackListSource::wantsRestart() const {
return false;
}

View file

@ -89,7 +89,6 @@ public:
/**
* True if the source consists only of installed mods
*/
virtual bool isInstalledMods() const = 0;
virtual bool wantsRestart() const = 0;
};
@ -129,7 +128,6 @@ public:
InstalledModsQuery const& getQuery() const;
InvalidateQueryAfter<InstalledModsQuery> getQueryMut();
bool isInstalledMods() const override;
bool wantsRestart() const override;
};
@ -160,7 +158,6 @@ public:
server::ModsQuery const& getQuery() const;
InvalidateQueryAfter<server::ModsQuery> getQueryMut();
bool isInstalledMods() const override;
bool wantsRestart() const override;
};
@ -178,6 +175,5 @@ public:
std::unordered_set<std::string> getModTags() const override;
void setModTags(std::unordered_set<std::string> const& tags) override;
bool isInstalledMods() const override;
bool wantsRestart() const override;
};