Better split for total/visible recipes and tags hopefully fixing all visual filtering issues

master
Wynd 2026-03-14 01:55:53 +02:00
parent 63675ee055
commit 34c016e832
5 changed files with 47 additions and 12 deletions

View File

@ -33,7 +33,7 @@ class MainActivity : ComponentActivity() {
).allowMainThreadQueries().build() ).allowMainThreadQueries().build()
val recipes = db.recipeWithTagsDao().getAll() val recipes = db.recipeWithTagsDao().getAll()
recipeView.setRecipes(recipes) recipeView.setAllRecipes(recipes)
enableEdgeToEdge() enableEdgeToEdge()

View File

@ -9,9 +9,15 @@ class RecipesView : ViewModel() {
private val _activeRecipe = MutableStateFlow<RecipeWithTags?>(null) private val _activeRecipe = MutableStateFlow<RecipeWithTags?>(null)
val activeRecipe = _activeRecipe.asStateFlow() val activeRecipe = _activeRecipe.asStateFlow()
private val _allRecipes = MutableStateFlow<List<RecipeWithTags>>(arrayListOf())
val allRecipes = _allRecipes.asStateFlow()
private val _recipes = MutableStateFlow<List<RecipeWithTags>>(arrayListOf()) private val _recipes = MutableStateFlow<List<RecipeWithTags>>(arrayListOf())
val recipes = _recipes.asStateFlow() val recipes = _recipes.asStateFlow()
private val _allTagFilters = MutableStateFlow<List<TagFilter>>(arrayListOf())
val allTagFilters = _allTagFilters.asStateFlow()
private val _tagFilters = MutableStateFlow<List<TagFilter>>(arrayListOf()) private val _tagFilters = MutableStateFlow<List<TagFilter>>(arrayListOf())
val tagFilters = _tagFilters.asStateFlow() val tagFilters = _tagFilters.asStateFlow()
@ -28,7 +34,7 @@ class RecipesView : ViewModel() {
val activeFilterNames = _tagFilters.value.filter { f -> f.checked }.map { f -> f.tag } val activeFilterNames = _tagFilters.value.filter { f -> f.checked }.map { f -> f.tag }
val filtersMap = mutableMapOf<String, Int>() val filtersMap = mutableMapOf<String, Int>()
_recipes.value.stream() _allRecipes.value.stream()
.filter { it.tags.isNotEmpty() } .filter { it.tags.isNotEmpty() }
.filter { .filter {
if (activeFilterNames.isNotEmpty()) { if (activeFilterNames.isNotEmpty()) {
@ -44,12 +50,21 @@ class RecipesView : ViewModel() {
} }
} }
val filters = filtersMap.map { TagFilter(it.key, checked = activeFilterNames.contains(it.key), count = it.value) } val filters = filtersMap.map {
_tagFilters.update { filters.distinct().sortedBy { it.tag }.toList() } TagFilter(
it.key,
checked = activeFilterNames.contains(it.key),
count = it.value
)
}
_tagFilters.update { filters.distinctBy { it.tag }.sortedBy { it.tag }.toList() }
} }
fun setTagFilterState(tag: String, state: Boolean) { fun setTagFilterState(tag: String, state: Boolean) {
_tagFilters.value = _tagFilters.value.map { if (tag == it.tag) it.checked = state; it } _tagFilters.update {
_allTagFilters.value
.map { if (tag == it.tag) it.checked = state; it }
}
this.reloadTagFilterState() this.reloadTagFilterState()
} }
@ -58,7 +73,26 @@ class RecipesView : ViewModel() {
_keepScreenOn.update { flag } _keepScreenOn.update { flag }
} }
fun setRecipes(recipes: List<RecipeWithTags>) { fun setAllRecipes(recipes: List<RecipeWithTags>) {
_allRecipes.update { recipes.sortedBy { it.recipe.title } }
_allTagFilters.update {
recipes.flatMap { it.tags }
.distinctBy { it.name }
.map {
TagFilter(
it.name,
false,
_allRecipes.value.count { r ->
r.tags.map { t -> t.name }.contains(it.name)
})
}
.sortedBy { it.tag }
}
setVisibleRecipes(recipes)
}
fun setVisibleRecipes(recipes: List<RecipeWithTags>) {
_recipes.update { recipes.sortedBy { it.recipe.title } } _recipes.update { recipes.sortedBy { it.recipe.title } }
this.reloadTagFilterState() this.reloadTagFilterState()

View File

@ -44,6 +44,7 @@ import java.io.File
@Composable @Composable
fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) { fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
val allRecipes by view.allRecipes.collectAsState()
val recipes by view.recipes.collectAsState() val recipes by view.recipes.collectAsState()
val active by view.activeRecipe.collectAsState() val active by view.activeRecipe.collectAsState()
val search by view.search.collectAsState() val search by view.search.collectAsState()
@ -80,8 +81,8 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
onValueChange = { search -> onValueChange = { search ->
view.setSearch(search) view.setSearch(search)
val newRecipes = val newRecipes =
recipes.filter { filterRecipe(it, search, filters) } allRecipes.filter { filterRecipe(it, search, filters) }
view.setRecipes(newRecipes) view.setVisibleRecipes(newRecipes)
}, },
) )
// Tags / Delete // Tags / Delete
@ -207,14 +208,14 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
openTagFilterDialog = false openTagFilterDialog = false
view.reloadTagFilterState() view.reloadTagFilterState()
activeTags = filters.count { f -> f.checked } activeTags = filters.count { f -> f.checked }
val newRecipes = recipes.filter { val newRecipes = allRecipes.filter {
filterRecipe( filterRecipe(
it, it,
search, search,
filters filters
) )
} }
ctx.recipeView.setRecipes(newRecipes) ctx.recipeView.setVisibleRecipes(newRecipes)
}, },
view, view,
) )

View File

@ -31,7 +31,7 @@ fun import(ctx: MainActivity, nav: NavHostController, setLoading: (Boolean) -> U
handler.post { handler.post {
if (ctx.importError.isEmpty()) { if (ctx.importError.isEmpty()) {
val recipes = ctx.db.recipeWithTagsDao().getAll() val recipes = ctx.db.recipeWithTagsDao().getAll()
ctx.recipeView.setRecipes(recipes) ctx.recipeView.setAllRecipes(recipes)
nav.navigate("list") nav.navigate("list")
} }

View File

@ -112,7 +112,7 @@ fun sync(ctx: MainActivity, nav: NavHostController, setLoading: (Boolean) -> Uni
handler.post { handler.post {
if (ctx.importError.isEmpty()) { if (ctx.importError.isEmpty()) {
val recipes = ctx.db.recipeWithTagsDao().getAll() val recipes = ctx.db.recipeWithTagsDao().getAll()
ctx.recipeView.setRecipes(recipes) ctx.recipeView.setAllRecipes(recipes)
nav.navigate("list") nav.navigate("list")
} }