CRUD работает

This commit is contained in:
maxnes3 2023-11-25 03:02:32 +04:00
parent f4fa24f50a
commit da844b15f7
8 changed files with 206 additions and 41 deletions

View File

@ -26,13 +26,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
val database by lazy { MobileAppDataBase.getInstance(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.deleteDatabase("my-db")
CoroutineScope(Dispatchers.IO).launch {
MobileAppDataBase.initialDataBase()
}
setContent {
MobileAppTheme {
// A surface container using the 'background' color from the theme

View File

@ -33,8 +33,11 @@ val buttonHeightStandard = 72.dp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlaceholderInputField(label: String, isSingleLine: Boolean, onTextChanged: (String) -> Unit){
fun PlaceholderInputField(label: String, startValue: String? = null, isSingleLine: Boolean, onTextChanged: (String) -> Unit){
var text = remember { mutableStateOf("") }
startValue?.let{
text.value = startValue
}
OutlinedTextField(
value = text.value,
@ -161,7 +164,7 @@ fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClic
fun PlaceholderTextFieldPreview() {
MobileAppTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
PlaceholderInputField("Email", true, { })
PlaceholderInputField("Email", null,true, { })
}
}
}

View File

@ -16,12 +16,14 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@ -29,18 +31,25 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import com.example.mobileapp.R
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.ui.theme.BackgroundItem2
import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2
import kotlin.reflect.typeOf
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat
import java.util.Date
val dateFormat = SimpleDateFormat("dd.MM.yyyy")
@Composable
fun <T : Any> DataListScroll(navController: NavHostController, dataList: List<T>){
@ -70,10 +79,20 @@ inline fun <reified T> List<*>.isListOf(): Boolean {
@Composable
fun StoryListItem(item: Story, navController: NavHostController){
val context = LocalContext.current
val isExpanded = remember {
mutableStateOf(false)
}
val showDialog = remember {
mutableStateOf(false)
}
val delete = remember {
mutableStateOf(false)
}
Card(
modifier = Modifier
.fillMaxWidth()
@ -105,7 +124,7 @@ fun StoryListItem(item: Story, navController: NavHostController){
modifier = Modifier.padding(8.dp)
){
Text(
text = item.title,
text = "${item.title} | ${dateFormat.format(Date(item.postdate!!))}",
fontSize = 20.sp,
fontWeight = FontWeight.Bold
)
@ -121,15 +140,35 @@ fun StoryListItem(item: Story, navController: NavHostController){
horizontalArrangement = Arrangement.End
){
DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = {
navController.navigate("editstory/" + item.id)
navController.navigate("editstory/${item.id}")
})
DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = {
navController.navigate("story")
showDialog.value = !showDialog.value
})
}
}
}
}
if(showDialog.value) {
DialogWindow(label = "Подтверждение",
message = "Вы уверены что хотите удалить запись?", onConfirmAction = {
delete.value = !delete.value
showDialog.value = !showDialog.value
}, onDismissAction = {
showDialog.value = !showDialog.value
})
}
if(delete.value) {
LaunchedEffect(Unit){
withContext(Dispatchers.IO){
MobileAppDataBase.getInstance(context).storyDao().delete(item)
}
}
delete.value = !delete.value
navController.navigate("story")
}
}
@Composable
@ -187,7 +226,7 @@ fun MailListItem(item: Mail){
modifier = Modifier.padding(8.dp)
){
Text(
text = "item.username",
text = "item.username | ${dateFormat.format(Date(item.postdate!!))}",
fontSize = 20.sp,
fontWeight = FontWeight.Bold)
Text(text = item.message)
@ -257,3 +296,41 @@ fun addNewListItem(navController: NavHostController, destination: String){
}
}
}
@Composable
fun DialogWindow(label: String, message: String, onConfirmAction: () -> Unit, onDismissAction: () -> Unit){
AlertDialog(onDismissRequest = onDismissAction,
title = {
Text(text = label,
fontSize = 20.sp,
fontWeight = FontWeight.Bold)
},
text = {
Text(text = message)
},
confirmButton = {
Button(
onClick = onConfirmAction,
colors = ButtonDefaults.buttonColors(
containerColor = ButtonColor2
),
shape = RoundedCornerShape(5.dp)
) {
Text(text = "Подтвердить",
color = Color.White)
}
},
dismissButton = {
Button(
onClick = onDismissAction,
colors = ButtonDefaults.buttonColors(
containerColor = ButtonColor1
),
shape = RoundedCornerShape(5.dp)
) {
Text(text = "Отмена",
color = Color.Black)
}
}
)
}

View File

@ -28,8 +28,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.mobileapp.R
import com.example.mobileapp.screens.Authorization
import com.example.mobileapp.screens.EditMailScreen
@ -122,20 +124,19 @@ fun NavBar(navController: NavHostController) {
EditStoryScreen(navController = navController)
bottomBarState.value = false
}
composable("editstory/{storyId}"){ navBackStackEntry ->
val storyId = navBackStackEntry.arguments?.getInt("storyId")
EditStoryScreen(navController = navController, storyId = storyId)
bottomBarState.value = false
composable(
"editstory/{id}",
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
backStackEntry.arguments?.let {
EditStoryScreen(navController = navController, storyId = it.getInt("id"))
bottomBarState.value = false
}
}
composable("editmail"){ // Без аргумента
EditMailScreen(navController = navController)
bottomBarState.value = false
}
composable("editmail/{mailId}"){ navBackStackEntry ->
val mailId = navBackStackEntry.arguments?.getInt("mailId")
EditMailScreen(navController = navController, mailId = mailId)
bottomBarState.value = false
}
}
}
}

View File

@ -32,17 +32,17 @@ abstract class MobileAppDataBase : RoomDatabase() {
@Volatile
private var INSTANCE: MobileAppDataBase? = null
suspend fun initialDataBase(){
suspend fun initialDataBase(appContext: Context){
INSTANCE?.let { database ->
val userDao = database.userDao()
userDao.insert(User(id = 1, login = "Дзюнзи Ито", password = "1234", email = "ito@gmail.com"))
userDao.insert(User(id = 2, login = "Стивен Кинг", password = "4321", email = "king@gmail.com"))
/*val storyDao = database.storyDao()
val storyDao = database.storyDao()
storyDao.insert(Story(title = "Переулок", description = "История ужасов от Дзюнзи Ито",
cover = BitmapFactory.decodeResource(null, R.drawable.dzun), userId = 1))
cover = BitmapFactory.decodeResource(appContext.resources, R.drawable.dzun), userId = 1))
storyDao.insert(Story(title = "Чужак", description = "Знаменитая книга стивена кинга",
cover = BitmapFactory.decodeResource(null, R.drawable.king), userId = 2))*/
cover = BitmapFactory.decodeResource(appContext.resources, R.drawable.king), userId = 2))
val mailDao = database.mailDao()
mailDao.insert(Mail(message = "Выложил новые страницы", userId = 1))
@ -61,7 +61,7 @@ abstract class MobileAppDataBase : RoomDatabase() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
CoroutineScope(Dispatchers.IO).launch {
initialDataBase()
initialDataBase(appContext)
}
}
})

View File

@ -56,7 +56,7 @@ fun Authorization(navController: NavHostController){
.size(512.dp)
.padding(8.dp)
.align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Логин", true, onTextChanged = {})
PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {})
PasswordInputField(label = "Пароль", onPasswordChanged = {})
NavigationButton(navController = navController, destination = "main", label = "Вход",
backgroundColor = ButtonColor2, textColor = Color.White)

View File

@ -1,5 +1,13 @@
package com.example.mobileapp.screens
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageDecoder
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@ -14,6 +22,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
@ -25,6 +34,7 @@ import com.example.mobileapp.components.NavigationButton
import com.example.mobileapp.components.PasswordInputField
import com.example.mobileapp.components.PlaceholderInputField
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2
@ -34,16 +44,70 @@ import kotlinx.coroutines.withContext
@Composable
fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) {
val context = LocalContext.current
val story = remember { mutableStateOf<Story?>(null) }
val cover = remember { mutableStateOf<Bitmap>(BitmapFactory.decodeResource(context.resources, R.drawable.editplaceholder)) }
val title = remember { mutableStateOf("") }
val description = remember { mutableStateOf("") }
val imageData = remember { mutableStateOf<Uri?>(null) }
val launcher =
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {uri: Uri? ->
imageData.value = uri
}
imageData.value?.let {
if (Build.VERSION.SDK_INT < 28) {
cover.value = MediaStore.Images
.Media.getBitmap(context.contentResolver, imageData.value)
} else {
val source = ImageDecoder
.createSource(context.contentResolver, imageData.value!!)
cover.value = ImageDecoder.decodeBitmap(source)
}
}
storyId?.let{
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
story.value = MobileAppDataBase.getInstance(context).storyDao().getById(storyId!!)
val story = MobileAppDataBase.getInstance(context).storyDao().getById(storyId!!)
cover.value = story!!.cover
title.value = story!!.title
description.value = story!!.description
}
}
}
val edit = remember { mutableStateOf(false) }
if (edit.value){
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
storyId?.let {
MobileAppDataBase.getInstance(context).storyDao()
.update(
Story(
id = storyId,
title = title.value,
description = description.value,
cover = cover.value,
userId = 1)
)
} ?: run {
MobileAppDataBase.getInstance(context).storyDao()
.insert(
Story(
title = title.value,
description = description.value,
cover = cover.value,
userId = 1)
)
}
}
}
edit.value = !edit.value
navController.navigate("story")
}
Column(
modifier = Modifier
.fillMaxSize()
@ -51,28 +115,49 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) {
verticalArrangement = Arrangement.Bottom
) {
Image(
painter = painterResource(id = R.drawable.editplaceholder),
bitmap = cover.value.asImageBitmap(),
contentDescription = "editplaceholder",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(384.dp)
.padding(8.dp)
.align(Alignment.CenterHorizontally))
ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {})
PlaceholderInputField(label = "Название", true, onTextChanged = { newName ->
ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
launcher.launch("image/*")
})
PlaceholderInputField(label = "Описание", true, onTextChanged = { newDescription ->
PlaceholderInputField(label = "Название", isSingleLine = true,
startValue = title.value, onTextChanged = { newName ->
title.value = newName
})
PlaceholderInputField(label = "Описание", isSingleLine = true,
startValue = description.value, onTextChanged = { newDescription ->
description.value = newDescription
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
edit.value = !edit.value
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {})
NavigationButton(navController = navController, destination = "story", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White)
}
}
@Composable
fun EditMailScreen(navController: NavHostController, mailId: Int? = null) {
fun EditMailScreen(navController: NavHostController) {
val context = LocalContext.current
val message = remember { mutableStateOf("") }
val create = remember { mutableStateOf(false) }
if(create.value){
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
MobileAppDataBase.getInstance(context).mailDao()
.insert(Mail(message = message.value, userId = 2))
}
}
create.value = !create.value
navController.navigate("mail")
}
Column(
modifier = Modifier
.fillMaxSize()
@ -87,8 +172,12 @@ fun EditMailScreen(navController: NavHostController, mailId: Int? = null) {
.size(512.dp)
.padding(8.dp)
.align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Текс поста", false, onTextChanged = {})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {})
PlaceholderInputField(label = "Текс поста", isSingleLine = false, onTextChanged = { newmessage ->
message.value = newmessage
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
create.value = !create.value
})
NavigationButton(navController = navController, destination = "mail", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White)
}

View File

@ -37,8 +37,8 @@ fun Registration(navController: NavHostController){
.size(384.dp)
.padding(8.dp)
.align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Логин", true, onTextChanged = {})
PlaceholderInputField(label = "Email", true, onTextChanged = {})
PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {})
PlaceholderInputField(label = "Email", isSingleLine = true, onTextChanged = {})
PasswordInputField(label = "Пароль", onPasswordChanged = {})
PasswordInputField(label = "Пароль ещё раз", onPasswordChanged = {})
NavigationButton(navController = navController, destination = "main",