Added a toggle to keep the screen active and a recipe deletion button

master
Wynd 2025-08-31 01:11:04 +03:00
parent a33e3be0cc
commit e996254451
8 changed files with 168 additions and 6 deletions

View File

@ -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)

View File

@ -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)
}

View File

@ -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)
}

View File

@ -15,10 +15,21 @@ class RecipesView : ViewModel() {
private val _search = MutableStateFlow<String?>(null)
val search = _search.asStateFlow()
private val _keepScreenOn = MutableStateFlow<Boolean>(false)
val keepScreenOn = _keepScreenOn.asStateFlow()
fun setKeepScreenOn(flag: Boolean) {
_keepScreenOn.update { flag }
}
fun setRecipes(recipes: List<RecipeWithTags>) {
_recipes.update { recipes }
}
fun removeRecipe(recipe: RecipeWithTags) {
_recipes.value = _recipes.value.toMutableList().apply { remove(recipe) }.toList()
}
fun setSearch(search: String) {
_search.update { search }
}

View File

@ -8,7 +8,8 @@ import androidx.room.PrimaryKey
@Entity
data class Tag(
@PrimaryKey val name: String
@PrimaryKey
val name: String
)
@Dao

View File

@ -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!!)
}
}
}

View File

@ -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")
}
}
}
}
}

View File

@ -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 }
)
}
}
}