Updated the recipe filtering so its more efficient

master
Wynd 2026-02-28 21:54:29 +02:00
parent 6735593517
commit 9131a028a3
2 changed files with 69 additions and 54 deletions

View File

@ -36,6 +36,7 @@ import xyz.pixelatedw.recipe.MainActivity
import xyz.pixelatedw.recipe.R import xyz.pixelatedw.recipe.R
import xyz.pixelatedw.recipe.data.RecipeWithTags import xyz.pixelatedw.recipe.data.RecipeWithTags
import xyz.pixelatedw.recipe.data.RecipesView import xyz.pixelatedw.recipe.data.RecipesView
import xyz.pixelatedw.recipe.data.TagFilter
import java.io.File import java.io.File
@ -46,6 +47,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
val search = view.search.collectAsState() val search = view.search.collectAsState()
val filters = view.tagFilters.collectAsState() val filters = view.tagFilters.collectAsState()
var activeRecipes = remember { recipes.value }
var activeTags = 0 var activeTags = 0
val navController = rememberNavController() val navController = rememberNavController()
@ -54,42 +56,6 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
var openTagFilterDialog by remember { mutableStateOf(false) } var openTagFilterDialog by remember { mutableStateOf(false) }
var selectedEntries by remember { mutableStateOf(listOf<RecipeWithTags>()) } var selectedEntries by remember { mutableStateOf(listOf<RecipeWithTags>()) }
val isInSearch = isInSearch@{ entry: RecipeWithTags ->
val isSearchEmpty = search.value == null || search.value!!.isEmpty()
val hasTitle = entry.recipe.title.contains(search.value.orEmpty(), ignoreCase = true)
val hasTags = entry.tags.stream()
.filter { tag -> tag.name.contains(search.value.orEmpty(), ignoreCase = true) }
.count() > 0
if (!isSearchEmpty && !hasTitle && !hasTags) {
return@isInSearch false
}
val totalFilters = filters.value.stream().filter { f -> f.checked }.count()
var checkedFilters = 0
for (filter in filters.value) {
if (filter.checked) {
val hasTagFilters = entry.tags.isNotEmpty() && entry.tags.stream()
.filter { tag -> tag.name.contains(filter.tag, ignoreCase = true) }
.count() > 0
if (hasTagFilters) {
checkedFilters += 1
} else {
checkedFilters -= 1
}
}
}
val hasTagFilters = checkedFilters >= totalFilters
if (totalFilters > 0 && !hasTagFilters) {
return@isInSearch false
}
true
}
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = "list" startDestination = "list"
@ -108,7 +74,11 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
.weight(0.7f) .weight(0.7f)
.padding(end = 4.dp), .padding(end = 4.dp),
value = search.value.orEmpty(), value = search.value.orEmpty(),
onValueChange = { search -> view.setSearch(search) }, onValueChange = { search ->
view.setSearch(search)
activeRecipes =
recipes.value.filter { filterRecipe(it, search, filters.value) }
},
) )
// Tags / Delete // Tags / Delete
if (selectedEntries.isNotEmpty()) { if (selectedEntries.isNotEmpty()) {
@ -160,8 +130,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
} }
} }
LazyColumn { LazyColumn {
items(recipes.value) { entry -> items(activeRecipes) { entry ->
if (isInSearch(entry)) {
val isSelected = selectedEntries.contains(entry) val isSelected = selectedEntries.contains(entry)
RecipePreview(entry, isSelected, onClick = { RecipePreview(entry, isSelected, onClick = {
view.setActive(entry) view.setActive(entry)
@ -179,7 +148,6 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
} }
} }
} }
}
when { when {
openDeletionDialog -> { openDeletionDialog -> {
@ -211,6 +179,13 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
openTagFilterDialog = false openTagFilterDialog = false
view.reloadTagFilterState() view.reloadTagFilterState()
activeTags = filters.value.count { f -> f.checked } activeTags = filters.value.count { f -> f.checked }
activeRecipes = recipes.value.filter {
filterRecipe(
it,
search.value,
filters.value
)
}
}, },
view, view,
) )
@ -225,3 +200,39 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
} }
} }
} }
private fun filterRecipe(
entry: RecipeWithTags,
search: String?,
filters: List<TagFilter>
): Boolean {
val isSearchEmpty = search.isNullOrEmpty()
val hasTitle = entry.recipe.title.contains(search.orEmpty(), ignoreCase = true)
val hasTags = entry.tags.stream()
.filter { tag -> tag.name.contains(search.orEmpty(), ignoreCase = true) }
.count() > 0
if (!isSearchEmpty && !hasTitle && !hasTags) {
return false
}
val totalFilters = filters.stream().filter { f -> f.checked }.count()
var checkedFilters = 0
for (filter in filters) {
if (filter.checked) {
val hasTagFilters = entry.tags.isNotEmpty() && entry.tags.stream()
.filter { tag -> tag.name.contains(filter.tag, ignoreCase = true) }
.count() > 0
if (hasTagFilters) {
checkedFilters += 1
} else {
checkedFilters -= 1
}
}
}
val hasTagFilters = checkedFilters >= totalFilters
return !(totalFilters > 0 && !hasTagFilters)
}

View File

@ -47,6 +47,10 @@ fun TagFilterDialog(onAccept: () -> Unit, view: RecipesView) {
.wrapContentSize(Alignment.TopStart) .wrapContentSize(Alignment.TopStart)
) { ) {
items(filters.value) { tag -> items(filters.value) { tag ->
if (tag.count <= 0) {
return@items
}
// TODO This doesn't really feel right lmao, but for now it works // TODO This doesn't really feel right lmao, but for now it works
val filterChecked = remember { mutableStateOf(tag.checked) } val filterChecked = remember { mutableStateOf(tag.checked) }