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'.
This commit is contained in:
Firenoo committed 2023-02-28 19:36:18 -08:00
1 parent 1d04f271b1
commit ae0d50a7b1
2 files changed
+92 -4

No files matched your search

@@ -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<Filter, MutableList<String>?> = 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<String>?) -> 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 {
//
//}
@@ -31,6 +31,8 @@ class InfoList (initList: Collection<InfoWrapper>,
*/
var filtered: List<InfoWrapper> = listOf()
private val filter: InfoFilter = InfoFilter()
/**
* Binding to the search string in the text box
*/
@@ -69,12 +71,24 @@ class InfoList (initList: Collection<InfoWrapper>,
* 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
// }
}
/**