From e99625445155dd6d5f5de0db0b215e7077fca0f9 Mon Sep 17 00:00:00 2001 From: Wynd Date: Sun, 31 Aug 2025 01:11:04 +0300 Subject: [PATCH] Added a toggle to keep the screen active and a recipe deletion button --- .../xyz/pixelatedw/recipe/MainActivity.kt | 3 +- .../java/xyz/pixelatedw/recipe/data/Recipe.kt | 4 + .../pixelatedw/recipe/data/RecipeWithTags.kt | 4 + .../xyz/pixelatedw/recipe/data/RecipesView.kt | 11 +++ .../java/xyz/pixelatedw/recipe/data/Tag.kt | 3 +- .../recipe/ui/components/MainScreen.kt | 2 +- .../ui/components/RecipeDeletionDialog.kt | 53 +++++++++++ .../recipe/ui/components/RecipeInfo.kt | 94 ++++++++++++++++++- 8 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeDeletionDialog.kt diff --git a/app/src/main/java/xyz/pixelatedw/recipe/MainActivity.kt b/app/src/main/java/xyz/pixelatedw/recipe/MainActivity.kt index f1e3ff2..3fc9dc8 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/MainActivity.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/MainActivity.kt @@ -1,6 +1,7 @@ package xyz.pixelatedw.recipe import android.os.Bundle +import android.view.WindowManager import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge @@ -19,7 +20,7 @@ import xyz.pixelatedw.recipe.utils.getRecipes class MainActivity : ComponentActivity() { private val recipeView: RecipesView by viewModels() - private lateinit var db: AppDatabase + lateinit var db: AppDatabase override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/xyz/pixelatedw/recipe/data/Recipe.kt b/app/src/main/java/xyz/pixelatedw/recipe/data/Recipe.kt index 9de1e64..5b62da3 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/data/Recipe.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/data/Recipe.kt @@ -5,6 +5,7 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import androidx.core.net.toUri import androidx.room.Dao +import androidx.room.Delete import androidx.room.Entity import androidx.room.Insert import androidx.room.OnConflictStrategy @@ -37,4 +38,7 @@ data class Recipe( interface RecipeDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(recipe: Recipe) + + @Delete + fun delete(recipe: Recipe) } diff --git a/app/src/main/java/xyz/pixelatedw/recipe/data/RecipeWithTags.kt b/app/src/main/java/xyz/pixelatedw/recipe/data/RecipeWithTags.kt index 93ddb11..8cb532d 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/data/RecipeWithTags.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/data/RecipeWithTags.kt @@ -2,6 +2,7 @@ package xyz.pixelatedw.recipe.data import android.os.Parcelable import androidx.room.Dao +import androidx.room.Delete import androidx.room.Embedded import androidx.room.Entity import androidx.room.Insert @@ -42,4 +43,7 @@ interface RecipeWithTagsDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(recipe: RecipeTag) + + @Query("DELETE FROM recipe WHERE recipe.title = :recipe") + fun delete(recipe: String) } diff --git a/app/src/main/java/xyz/pixelatedw/recipe/data/RecipesView.kt b/app/src/main/java/xyz/pixelatedw/recipe/data/RecipesView.kt index b7b4072..eeb4d3c 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/data/RecipesView.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/data/RecipesView.kt @@ -15,10 +15,21 @@ class RecipesView : ViewModel() { private val _search = MutableStateFlow(null) val search = _search.asStateFlow() + private val _keepScreenOn = MutableStateFlow(false) + val keepScreenOn = _keepScreenOn.asStateFlow() + + fun setKeepScreenOn(flag: Boolean) { + _keepScreenOn.update { flag } + } + fun setRecipes(recipes: List) { _recipes.update { recipes } } + fun removeRecipe(recipe: RecipeWithTags) { + _recipes.value = _recipes.value.toMutableList().apply { remove(recipe) }.toList() + } + fun setSearch(search: String) { _search.update { search } } diff --git a/app/src/main/java/xyz/pixelatedw/recipe/data/Tag.kt b/app/src/main/java/xyz/pixelatedw/recipe/data/Tag.kt index 7ea9d62..1b1779d 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/data/Tag.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/data/Tag.kt @@ -8,7 +8,8 @@ import androidx.room.PrimaryKey @Entity data class Tag( - @PrimaryKey val name: String + @PrimaryKey + val name: String ) @Dao diff --git a/app/src/main/java/xyz/pixelatedw/recipe/ui/components/MainScreen.kt b/app/src/main/java/xyz/pixelatedw/recipe/ui/components/MainScreen.kt index 4180600..5a81b5c 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/ui/components/MainScreen.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/ui/components/MainScreen.kt @@ -84,7 +84,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) { } } composable("info") { - RecipeInfo(padding, active.value!!) + RecipeInfo(ctx, view, navController, padding, active.value!!) } } } diff --git a/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeDeletionDialog.kt b/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeDeletionDialog.kt new file mode 100644 index 0000000..49cef0b --- /dev/null +++ b/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeDeletionDialog.kt @@ -0,0 +1,53 @@ +package xyz.pixelatedw.recipe.ui.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog + +@Composable +fun RecipeDeletionDialog(onAccept: ( ) -> Unit, onDismiss: () -> Unit) { + Dialog(onDismissRequest = { onDismiss() }) { + Card( + modifier = Modifier + .fillMaxWidth() + .height(200.dp) + .padding(16.dp), + shape = RoundedCornerShape(16.dp), + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.height(100.dp).wrapContentSize(Alignment.Center) + ) { + Text( + text = "Do you really wish to permanently delete this recipe ?", + textAlign = TextAlign.Center, + ) + } + + Row(modifier = Modifier.fillMaxWidth().padding(end = 16.dp), horizontalArrangement = Arrangement.End) { + TextButton(onClick = onDismiss) { + Text("Dismiss") + } + TextButton(onClick = onAccept) { + Text("Confirm") + } + } + } + } +} diff --git a/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeInfo.kt b/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeInfo.kt index 550cbe3..61dba90 100644 --- a/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeInfo.kt +++ b/app/src/main/java/xyz/pixelatedw/recipe/ui/components/RecipeInfo.kt @@ -1,26 +1,48 @@ package xyz.pixelatedw.recipe.ui.components +import android.view.WindowManager import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import xyz.pixelatedw.recipe.data.Recipe +import androidx.navigation.NavHostController +import xyz.pixelatedw.recipe.MainActivity import xyz.pixelatedw.recipe.data.RecipeWithTags +import xyz.pixelatedw.recipe.data.RecipesView import xyz.pixelatedw.recipe.utils.parseMarkdown +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun RecipeInfo(padding: PaddingValues, active: RecipeWithTags) { +fun RecipeInfo( + ctx: MainActivity, + view: RecipesView, + nav: NavHostController, + padding: PaddingValues, + active: RecipeWithTags +) { + val keepScreen = view.keepScreenOn.collectAsState() + val openDeletionDialog = remember { mutableStateOf(false) } + Column( modifier = Modifier .verticalScroll(rememberScrollState()) @@ -28,7 +50,9 @@ fun RecipeInfo(padding: PaddingValues, active: RecipeWithTags) { ) { Row( horizontalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() + .padding(top = 24.dp, bottom = 24.dp) ) { Text( text = active.recipe.title, @@ -37,6 +61,55 @@ fun RecipeInfo(padding: PaddingValues, active: RecipeWithTags) { ) } + Row(modifier = Modifier.fillMaxWidth()) { + Box( + modifier = Modifier + .fillMaxHeight() + .padding(start = 16.dp) + ) { + Text( + text = "Keep Screen On", + style = MaterialTheme.typography.bodySmall, + ) + Switch( + modifier = Modifier.padding(start = 16.dp, top = 16.dp), + checked = keepScreen.value, + onCheckedChange = { + view.setKeepScreenOn(it) + if (it) { + ctx.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } else { + ctx.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(end = 16.dp), + horizontalArrangement = Arrangement.End + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .padding(start = 16.dp) + ) { + Button( + onClick = { + openDeletionDialog.value = true + }, + colors = ButtonDefaults.buttonColors(containerColor = Color.Red) + ) { + Text( + text = "Delete", + style = MaterialTheme.typography.bodyMedium + ) + } + } + } + } + Box( modifier = Modifier.fillMaxWidth() ) { @@ -48,4 +121,19 @@ fun RecipeInfo(padding: PaddingValues, active: RecipeWithTags) { ) } } + + when { + openDeletionDialog.value -> { + RecipeDeletionDialog( + onAccept = { + view.removeRecipe(active) + ctx.db.recipeDao().delete(active.recipe) + ctx.db.recipeWithTagsDao().delete(active.recipe.title) + openDeletionDialog.value = false + nav.popBackStack() + }, + onDismiss = { openDeletionDialog.value = false } + ) + } + } }