Updated the recipe filtering so its more efficient
parent
6735593517
commit
9131a028a3
|
|
@ -36,6 +36,7 @@ import xyz.pixelatedw.recipe.MainActivity
|
|||
import xyz.pixelatedw.recipe.R
|
||||
import xyz.pixelatedw.recipe.data.RecipeWithTags
|
||||
import xyz.pixelatedw.recipe.data.RecipesView
|
||||
import xyz.pixelatedw.recipe.data.TagFilter
|
||||
import java.io.File
|
||||
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
|||
val search = view.search.collectAsState()
|
||||
val filters = view.tagFilters.collectAsState()
|
||||
|
||||
var activeRecipes = remember { recipes.value }
|
||||
var activeTags = 0
|
||||
|
||||
val navController = rememberNavController()
|
||||
|
|
@ -54,42 +56,6 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
|||
var openTagFilterDialog by remember { mutableStateOf(false) }
|
||||
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(
|
||||
navController = navController,
|
||||
startDestination = "list"
|
||||
|
|
@ -108,7 +74,11 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
|||
.weight(0.7f)
|
||||
.padding(end = 4.dp),
|
||||
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
|
||||
if (selectedEntries.isNotEmpty()) {
|
||||
|
|
@ -160,8 +130,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
|||
}
|
||||
}
|
||||
LazyColumn {
|
||||
items(recipes.value) { entry ->
|
||||
if (isInSearch(entry)) {
|
||||
items(activeRecipes) { entry ->
|
||||
val isSelected = selectedEntries.contains(entry)
|
||||
RecipePreview(entry, isSelected, onClick = {
|
||||
view.setActive(entry)
|
||||
|
|
@ -179,7 +148,6 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
openDeletionDialog -> {
|
||||
|
|
@ -211,6 +179,13 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
|||
openTagFilterDialog = false
|
||||
view.reloadTagFilterState()
|
||||
activeTags = filters.value.count { f -> f.checked }
|
||||
activeRecipes = recipes.value.filter {
|
||||
filterRecipe(
|
||||
it,
|
||||
search.value,
|
||||
filters.value
|
||||
)
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ fun TagFilterDialog(onAccept: () -> Unit, view: RecipesView) {
|
|||
.wrapContentSize(Alignment.TopStart)
|
||||
) {
|
||||
items(filters.value) { tag ->
|
||||
if (tag.count <= 0) {
|
||||
return@items
|
||||
}
|
||||
|
||||
// TODO This doesn't really feel right lmao, but for now it works
|
||||
val filterChecked = remember { mutableStateOf(tag.checked) }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue