Added a toggle to keep the screen active and a recipe deletion button
parent
a33e3be0cc
commit
e996254451
|
|
@ -1,6 +1,7 @@
|
||||||
package xyz.pixelatedw.recipe
|
package xyz.pixelatedw.recipe
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.WindowManager
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
|
@ -19,7 +20,7 @@ import xyz.pixelatedw.recipe.utils.getRecipes
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private val recipeView: RecipesView by viewModels()
|
private val recipeView: RecipesView by viewModels()
|
||||||
private lateinit var db: AppDatabase
|
lateinit var db: AppDatabase
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
|
|
@ -37,4 +38,7 @@ data class Recipe(
|
||||||
interface RecipeDao {
|
interface RecipeDao {
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(recipe: Recipe)
|
fun insert(recipe: Recipe)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(recipe: Recipe)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package xyz.pixelatedw.recipe.data
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
import androidx.room.Embedded
|
import androidx.room.Embedded
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
|
|
@ -42,4 +43,7 @@ interface RecipeWithTagsDao {
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(recipe: RecipeTag)
|
fun insert(recipe: RecipeTag)
|
||||||
|
|
||||||
|
@Query("DELETE FROM recipe WHERE recipe.title = :recipe")
|
||||||
|
fun delete(recipe: String)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,21 @@ class RecipesView : ViewModel() {
|
||||||
private val _search = MutableStateFlow<String?>(null)
|
private val _search = MutableStateFlow<String?>(null)
|
||||||
val search = _search.asStateFlow()
|
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>) {
|
fun setRecipes(recipes: List<RecipeWithTags>) {
|
||||||
_recipes.update { recipes }
|
_recipes.update { recipes }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeRecipe(recipe: RecipeWithTags) {
|
||||||
|
_recipes.value = _recipes.value.toMutableList().apply { remove(recipe) }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
fun setSearch(search: String) {
|
fun setSearch(search: String) {
|
||||||
_search.update { search }
|
_search.update { search }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ import androidx.room.PrimaryKey
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
data class Tag(
|
data class Tag(
|
||||||
@PrimaryKey val name: String
|
@PrimaryKey
|
||||||
|
val name: String
|
||||||
)
|
)
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
composable("info") {
|
composable("info") {
|
||||||
RecipeInfo(padding, active.value!!)
|
RecipeInfo(ctx, view, navController, padding, active.value!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,48 @@
|
||||||
package xyz.pixelatedw.recipe.ui.components
|
package xyz.pixelatedw.recipe.ui.components
|
||||||
|
|
||||||
|
import android.view.WindowManager
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
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.MaterialTheme
|
||||||
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.Modifier
|
||||||
|
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 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.RecipeWithTags
|
||||||
|
import xyz.pixelatedw.recipe.data.RecipesView
|
||||||
import xyz.pixelatedw.recipe.utils.parseMarkdown
|
import xyz.pixelatedw.recipe.utils.parseMarkdown
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@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(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
|
|
@ -28,7 +50,9 @@ fun RecipeInfo(padding: PaddingValues, active: RecipeWithTags) {
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 24.dp, bottom = 24.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = active.recipe.title,
|
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(
|
Box(
|
||||||
modifier = Modifier.fillMaxWidth()
|
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 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue