mirror of
https://github.com/geode-sdk/geode.git
synced 2025-02-17 00:30:26 -05:00
impl searching local mods
This commit is contained in:
parent
65645fe753
commit
435484b6ae
3 changed files with 89 additions and 36 deletions
|
@ -39,6 +39,14 @@ bool ModList::init(ModListSource* src, CCSize const& size) {
|
|||
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->isInMemory()) {
|
||||
m_source->setQuery(m_searchInput->getString());
|
||||
this->gotoPage(0);
|
||||
return;
|
||||
}
|
||||
// Otherwise buffer inputs by a bit
|
||||
// This avoids spamming servers for every character typed,
|
||||
// instead waiting for input to stop to actually do the search
|
||||
std::thread([this] {
|
||||
|
|
|
@ -19,36 +19,66 @@ static bool weightedFuzzyMatch(std::string const& str, std::string const& kw, do
|
|||
return false;
|
||||
}
|
||||
|
||||
static std::pair<std::vector<Mod*>, size_t> getModsWithQuery(server::ModsQuery const& query) {
|
||||
std::vector<std::pair<Mod*, double>> mods;
|
||||
|
||||
// Filter installed mods based on query
|
||||
for (auto& mod : Loader::get()->getAllMods()) {
|
||||
bool addToList = !query.query.has_value();
|
||||
double weighted = 0;
|
||||
if (query.query) {
|
||||
addToList |= weightedFuzzyMatch(mod->getName(), *query.query, 2, weighted);
|
||||
addToList |= weightedFuzzyMatch(mod->getID(), *query.query, 1, weighted);
|
||||
for (auto& dev : mod->getDevelopers()) {
|
||||
addToList |= weightedFuzzyMatch(dev, *query.query, 0.75, weighted);
|
||||
}
|
||||
if (auto details = mod->getDetails()) {
|
||||
addToList |= weightedFuzzyMatch(*details, *query.query, 0.05, weighted);
|
||||
}
|
||||
if (auto desc = mod->getDescription()) {
|
||||
addToList |= weightedFuzzyMatch(*desc, *query.query, 0.2, weighted);
|
||||
}
|
||||
if (weighted < 2) {
|
||||
addToList = false;
|
||||
}
|
||||
}
|
||||
if (addToList) {
|
||||
mods.push_back({ mod, weighted });
|
||||
}
|
||||
}
|
||||
|
||||
// Sort list based on score
|
||||
std::sort(mods.begin(), mods.end(), [](auto a, auto b) {
|
||||
// Sort primarily by score
|
||||
if (a.second != b.second) {
|
||||
return a.second > b.second;
|
||||
}
|
||||
// Sort secondarily alphabetically
|
||||
return a.first->getName() < b.first->getName();
|
||||
});
|
||||
|
||||
// Pick out only the mods in the page and page size specified in the query
|
||||
std::vector<Mod*> result {};
|
||||
for (
|
||||
size_t i = query.page * query.pageSize;
|
||||
i < mods.size() && i < (query.page + 1) * query.pageSize;
|
||||
i += 1
|
||||
) {
|
||||
result.push_back(mods.at(i).first);
|
||||
}
|
||||
// Return paged mods & total count of matching mods
|
||||
return { result, mods.size() };
|
||||
}
|
||||
|
||||
static auto loadInstalledModsPage(server::ModsQuery&& query) {
|
||||
return ModListSource::ProviderPromise([query = std::move(query)](auto resolve, auto, auto, auto const&) {
|
||||
Loader::get()->queueInMainThread([query = std::move(query), resolve = std::move(resolve)] {
|
||||
auto content = ModListSource::Page();
|
||||
std::vector<std::pair<Mod*, double>> mods;
|
||||
|
||||
// todo: finish this
|
||||
for (auto& mod : Loader::get()->getAllMods()) {
|
||||
// bool someMatched = false;
|
||||
double weighted = 0;
|
||||
// if (query.query) {
|
||||
// someMatched += weightedFuzzyMatch(mod->getName(), *query.query, 2, weighted);
|
||||
// }
|
||||
// if (someMatched) {
|
||||
mods.push_back({ mod, weighted });
|
||||
// }
|
||||
auto mods = getModsWithQuery(query);
|
||||
for (auto& mod : mods.first) {
|
||||
content.push_back(InstalledModItem::create(mod));
|
||||
}
|
||||
|
||||
// Sort list based on score
|
||||
std::sort(mods.begin(), mods.end(), [](auto a, auto b) {
|
||||
return a.second < b.second;
|
||||
});
|
||||
for (
|
||||
size_t i = query.page * query.pageSize;
|
||||
i < mods.size() && i < (query.page + 1) * query.pageSize;
|
||||
i += 1
|
||||
) {
|
||||
content.push_back(InstalledModItem::create(mods.at(i).first));
|
||||
}
|
||||
resolve({ content, mods.size() });
|
||||
resolve({ content, mods.second });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -58,7 +88,7 @@ static auto loadServerModsPage(server::ModsQuery&& query) {
|
|||
server::getMods(query)
|
||||
.then([resolve, reject](server::ServerModsList list) {
|
||||
auto content = ModListSource::Page();
|
||||
for (auto mod : list.mods) {
|
||||
for (auto& mod : list.mods) {
|
||||
content.push_back(ServerModItem::create(mod));
|
||||
}
|
||||
resolve({ content, list.totalModCount });
|
||||
|
@ -122,7 +152,7 @@ std::optional<size_t> ModListSource::getItemCount() const {
|
|||
}
|
||||
|
||||
void ModListSource::reset() {
|
||||
m_query.clear();
|
||||
m_query = std::nullopt;
|
||||
m_cachedPages.clear();
|
||||
m_cachedItemCount = std::nullopt;
|
||||
}
|
||||
|
@ -130,15 +160,20 @@ void ModListSource::reset() {
|
|||
void ModListSource::setQuery(std::string const& query) {
|
||||
// Set query & reset cache
|
||||
if (m_query != query) {
|
||||
m_query = query;
|
||||
m_query = query.empty() ? std::nullopt : std::optional(query);
|
||||
m_cachedPages.clear();
|
||||
m_cachedItemCount = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
ModListSource* ModListSource::create(Provider* provider) {
|
||||
bool ModListSource::isInMemory() const {
|
||||
return m_inMemory;
|
||||
}
|
||||
|
||||
ModListSource* ModListSource::create(Provider* provider, bool inMemory) {
|
||||
auto ret = new ModListSource();
|
||||
ret->m_provider = provider;
|
||||
ret->m_inMemory = inMemory;
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
|
@ -147,7 +182,7 @@ ModListSource* ModListSource::get(ModListSourceType type) {
|
|||
switch (type) {
|
||||
default:
|
||||
case ModListSourceType::Installed: {
|
||||
static auto inst = Ref(ModListSource::create(loadInstalledModsPage));
|
||||
static auto inst = Ref(ModListSource::create(loadInstalledModsPage, true));
|
||||
return inst;
|
||||
} break;
|
||||
|
||||
|
@ -155,24 +190,24 @@ ModListSource* ModListSource::get(ModListSourceType type) {
|
|||
static auto inst = Ref(ModListSource::create(+[](server::ModsQuery&& query) {
|
||||
query.featured = true;
|
||||
return loadServerModsPage(std::move(query));
|
||||
}));
|
||||
}, false));
|
||||
return inst;
|
||||
} break;
|
||||
|
||||
case ModListSourceType::Trending: {
|
||||
static auto inst = Ref(ModListSource::create(nullptr));
|
||||
static auto inst = Ref(ModListSource::create(nullptr, false));
|
||||
return inst;
|
||||
} break;
|
||||
|
||||
case ModListSourceType::ModPacks: {
|
||||
static auto inst = Ref(ModListSource::create(nullptr));
|
||||
static auto inst = Ref(ModListSource::create(nullptr, false));
|
||||
return inst;
|
||||
} break;
|
||||
|
||||
case ModListSourceType::All: {
|
||||
static auto inst = Ref(ModListSource::create(+[](server::ModsQuery&& query) {
|
||||
return loadServerModsPage(std::move(query));
|
||||
}));
|
||||
}, false));
|
||||
return inst;
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -39,12 +39,13 @@ public:
|
|||
protected:
|
||||
std::unordered_map<size_t, Page> m_cachedPages;
|
||||
std::optional<size_t> m_cachedItemCount;
|
||||
std::string m_query;
|
||||
std::optional<std::string> m_query;
|
||||
Provider* m_provider = nullptr;
|
||||
bool m_inMemory;
|
||||
|
||||
public:
|
||||
// Create a new source with an arbitary provider
|
||||
static ModListSource* create(Provider* provider);
|
||||
static ModListSource* create(Provider* provider, bool inMemory);
|
||||
|
||||
// Get a standard source (lazily created static instance)
|
||||
static ModListSource* get(ModListSourceType type);
|
||||
|
@ -59,4 +60,13 @@ public:
|
|||
PagePromise loadPage(size_t page, bool update = false);
|
||||
std::optional<size_t> getPageCount() const;
|
||||
std::optional<size_t> getItemCount() const;
|
||||
|
||||
/**
|
||||
* True if the source is already fully loaded in memory (doesn't fetch
|
||||
* from a server or filesystem)
|
||||
*
|
||||
* Used to determine whether things like searching should update the query
|
||||
* instantaniously or buffer a bit to avoid spamming unnecessary requests
|
||||
*/
|
||||
bool isInMemory() const;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue