Realtime update of the tags list

master
Wynd 2026-03-01 14:54:11 +02:00
parent 9131a028a3
commit 0507bbf4c7
3 changed files with 24 additions and 48 deletions

View File

@ -44,20 +44,14 @@ class RecipesView : ViewModel() {
} }
} }
if (activeFilterNames.isNotEmpty()) { val filters = filtersMap.map { TagFilter(it.key, checked = activeFilterNames.contains(it.key), count = it.value) }
_tagFilters.value = _tagFilters.value.map { _tagFilters.update { filters.distinct().sortedBy { it.tag }.toList() }
it.count = filtersMap[it.tag] ?: 0
it
}.toList()
} else {
val filters = filtersMap.map { TagFilter(it.key, count = it.value) }.toList()
_tagFilters.update { filters.distinct().sortedBy { it.tag } }
}
} }
fun setTagFilterState(tag: String, state: Boolean) { fun setTagFilterState(tag: String, state: Boolean) {
_tagFilters.value = _tagFilters.value.toMutableList() _tagFilters.value = _tagFilters.value.map { if (tag == it.tag) it.checked = state; it }
.apply { replaceAll { it -> if (tag == it.tag) it.checked = state; it } }.toList()
this.reloadTagFilterState()
} }
fun setKeepScreenOn(flag: Boolean) { fun setKeepScreenOn(flag: Boolean) {
@ -67,19 +61,7 @@ class RecipesView : ViewModel() {
fun setRecipes(recipes: List<RecipeWithTags>) { fun setRecipes(recipes: List<RecipeWithTags>) {
_recipes.update { recipes.sortedBy { it.recipe.title } } _recipes.update { recipes.sortedBy { it.recipe.title } }
val filtersMap = mutableMapOf<String, Int>() this.reloadTagFilterState()
_recipes.value.stream()
.filter { it.tags.isNotEmpty() }
.forEach {
it.tags.forEach { tag ->
val count = filtersMap[tag.name] ?: 0
filtersMap[tag.name] = count + 1;
}
}
val filters = filtersMap.map { it -> TagFilter(it.key, count = it.value) }.toList()
_tagFilters.update { filters.distinct().sortedBy { it.tag } }
} }
fun removeRecipe(recipe: RecipeWithTags) { fun removeRecipe(recipe: RecipeWithTags) {

View File

@ -42,12 +42,12 @@ import java.io.File
@Composable @Composable
fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) { fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
val recipes = view.recipes.collectAsState() val recipes by view.recipes.collectAsState()
val active = view.activeRecipe.collectAsState() val active by view.activeRecipe.collectAsState()
val search = view.search.collectAsState() val search by view.search.collectAsState()
val filters = view.tagFilters.collectAsState() val filters by view.tagFilters.collectAsState()
var activeRecipes = remember { recipes.value } var activeRecipes by remember { mutableStateOf(recipes) }
var activeTags = 0 var activeTags = 0
val navController = rememberNavController() val navController = rememberNavController()
@ -73,11 +73,11 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
modifier = Modifier modifier = Modifier
.weight(0.7f) .weight(0.7f)
.padding(end = 4.dp), .padding(end = 4.dp),
value = search.value.orEmpty(), value = search.orEmpty(),
onValueChange = { search -> onValueChange = { search ->
view.setSearch(search) view.setSearch(search)
activeRecipes = activeRecipes =
recipes.value.filter { filterRecipe(it, search, filters.value) } recipes.filter { filterRecipe(it, search, filters) }
}, },
) )
// Tags / Delete // Tags / Delete
@ -178,12 +178,12 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
onAccept = { onAccept = {
openTagFilterDialog = false openTagFilterDialog = false
view.reloadTagFilterState() view.reloadTagFilterState()
activeTags = filters.value.count { f -> f.checked } activeTags = filters.count { f -> f.checked }
activeRecipes = recipes.value.filter { activeRecipes = recipes.filter {
filterRecipe( filterRecipe(
it, it,
search.value, search,
filters.value filters
) )
} }
}, },
@ -193,7 +193,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
} }
} }
composable("info") { composable("info") {
RecipeInfo(ctx, view, navController, padding, active.value!!) RecipeInfo(ctx, view, navController, padding, active!!)
} }
composable("settings") { composable("settings") {
SettingsScreen(ctx, navController) SettingsScreen(ctx, navController)

View File

@ -16,20 +16,23 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import xyz.pixelatedw.recipe.data.RecipesView import xyz.pixelatedw.recipe.data.RecipesView
@Composable @Composable
fun TagFilterDialog(onAccept: () -> Unit, view: RecipesView) { fun TagFilterDialog(onAccept: () -> Unit, view: RecipesView) {
val filters = view.tagFilters.collectAsState() val filters by view.tagFilters.collectAsState()
Dialog(onDismissRequest = { }) { Dialog(onDismissRequest = { }) {
Card( Card(
@ -46,19 +49,11 @@ fun TagFilterDialog(onAccept: () -> Unit, view: RecipesView) {
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp) .padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
.wrapContentSize(Alignment.TopStart) .wrapContentSize(Alignment.TopStart)
) { ) {
items(filters.value) { tag -> items(filters) { 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) }
Row( Row(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Checkbox(checked = filterChecked.value, onCheckedChange = { Checkbox(checked = tag.checked, onCheckedChange = {
filterChecked.value = !tag.checked
view.setTagFilterState(tag.tag, !tag.checked) view.setTagFilterState(tag.tag, !tag.checked)
}) })
TextButton( TextButton(
@ -68,7 +63,6 @@ fun TagFilterDialog(onAccept: () -> Unit, view: RecipesView) {
containerColor = Color.Transparent containerColor = Color.Transparent
), ),
onClick = { onClick = {
filterChecked.value = !tag.checked
view.setTagFilterState(tag.tag, !tag.checked) view.setTagFilterState(tag.tag, !tag.checked)
} }
) { ) {