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.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,23 +130,21 @@ 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)
|
navController.navigate("info")
|
||||||
navController.navigate("info")
|
}, onSelected = { flag ->
|
||||||
}, onSelected = { flag ->
|
selectedEntries =
|
||||||
selectedEntries =
|
selectedEntries.toMutableList().apply {
|
||||||
selectedEntries.toMutableList().apply {
|
if (flag) {
|
||||||
if (flag) {
|
add(entry)
|
||||||
add(entry)
|
} else {
|
||||||
} else {
|
remove(entry)
|
||||||
remove(entry)
|
}
|
||||||
}
|
}.toList()
|
||||||
}.toList()
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue