From ae0d50a7b10f9e67ad7dcae613124ada33db56b4 Mon Sep 17 00:00:00 2001 From: Firenoo <49818773+firenoo@users.noreply.github.com> Date: Thu, 23 Feb 2023 23:07:21 -0800 Subject: [PATCH] Add filter options to Advanced memory card search New way to filter P2P tunnels through the search bar via "tags". A tag starts with '@' and filters based off some set of criteria. Tags are space separated. You can still search based on the name, but the name search is based off of string tokens rather than a complete match. If for whatever reason a tunnel is named '@...', you can wrap the query in double quotes '"' to force it to search as a name. Tags added: '@in', '@out', '@b', '@u'. --- .../betterp2p/client/gui/InfoFilter.kt | 74 +++++++++++++++++++ .../betterp2p/client/gui/InfoList.kt | 22 +++++- 2 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/projecturanus/betterp2p/client/gui/InfoFilter.kt diff --git a/src/main/java/com/projecturanus/betterp2p/client/gui/InfoFilter.kt b/src/main/java/com/projecturanus/betterp2p/client/gui/InfoFilter.kt new file mode 100644 index 0000000..88302c9 --- /dev/null +++ b/src/main/java/com/projecturanus/betterp2p/client/gui/InfoFilter.kt @@ -0,0 +1,74 @@ +package com.projecturanus.betterp2p.client.gui + +/** + * Extend the default filtering. Holds information about the search filter. + * + * There are 3 modes of filtering: + * - By input/output: Using `@in/@out` filters by input/output respectively. + * - By bound/unbound: Use `@b` or `@u` filters by input/output respectively. + * - By name: Use the name + * If someone comes and says "sort by freq pls" then we can add it at that time + */ +class InfoFilter { + + /** + * Active filters to use when filtering entries. + */ + val activeFilters: MutableMap?> = mutableMapOf() + + /** + * Parse the query string for filters and update the active + * filter list. + */ + fun updateFilter(query: String) { + val tokens = query.split("\\s+".toRegex()) // split by whitespace + activeFilters.clear() + tokens.forEach { + when { + it.matches(Filter.INPUT.pattern) -> { + activeFilters.putIfAbsent(Filter.INPUT, null) + } + it.matches(Filter.OUTPUT.pattern) -> { + activeFilters.putIfAbsent(Filter.OUTPUT, null) + } + it.matches(Filter.BOUND.pattern) -> { + activeFilters.putIfAbsent(Filter.BOUND, null) + } + it.matches(Filter.UNBOUND.pattern) -> { + activeFilters.putIfAbsent(Filter.UNBOUND, null) + } + else -> { + activeFilters.putIfAbsent(Filter.NAME, mutableListOf()) + activeFilters[Filter.NAME]!!.add(it) + } + } + } + } +} + +/** + * The different filter types. Probably will let these be adjustable in the + * config. + */ +enum class Filter(val pattern: Regex, val filter: (InfoWrapper, List?) -> Boolean) { + INPUT("\\A@in\\z".toRegex(), { it, _ -> !it.output }), + OUTPUT("\\A@out\\z".toRegex(), { it, _ -> it.output }), + BOUND("\\A@b\\z".toRegex(), { it, _ -> it.frequency != 0L }), + UNBOUND("\\A@u\\z".toRegex(), { it, _ -> it.frequency == 0L || it.error }), + NAME("\"?.+\"?".toRegex(), filter@{ it, strs -> + val name = it.name.lowercase() + for (f in strs!!) { + // Ppl better not troll and use double quotes in their P2P tunnel names + val query = f.removeSurrounding("\"") + if (name.contains(query)) { + return@filter true + } + } + false + }); + +} + +//fun parseQuery(search: String): InfoFilter { +// +//} diff --git a/src/main/java/com/projecturanus/betterp2p/client/gui/InfoList.kt b/src/main/java/com/projecturanus/betterp2p/client/gui/InfoList.kt index 2f60e06..cae8a91 100644 --- a/src/main/java/com/projecturanus/betterp2p/client/gui/InfoList.kt +++ b/src/main/java/com/projecturanus/betterp2p/client/gui/InfoList.kt @@ -31,6 +31,8 @@ class InfoList (initList: Collection, */ var filtered: List = listOf() + private val filter: InfoFilter = InfoFilter() + /** * Binding to the search string in the text box */ @@ -69,12 +71,24 @@ class InfoList (initList: Collection, * Updates the filtered list. */ fun refilter() { + filter.updateFilter(searchStr.lowercase()) filtered = sorted.filter { - it.frequency.toHexString().contains(searchStr.uppercase()) || - it.frequency.toHexString().format4().contains(searchStr.uppercase()) || - it.name.lowercase().contains(searchStr.lowercase()) || - it.code == selectedEntry + if (it.code == selectedEntry) { + return@filter true + } + for ((f, strs) in filter.activeFilters) { + if(!f.filter(it, strs?.toList())) { + return@filter false + } + } + true } +// filtered = sorted.filter { +// it.frequency.toHexString().contains(searchStr.uppercase()) || +// it.frequency.toHexString().format4().contains(searchStr.uppercase()) || +// it.name.lowercase().contains(searchStr.lowercase()) || +// it.code == selectedEntry +// } } /**