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 import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
val database by lazy { MobileAppDataBase.getInstance(this) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
this.deleteDatabase("my-db")
CoroutineScope(Dispatchers.IO).launch {
MobileAppDataBase.initialDataBase()
}
setContent { setContent {
MobileAppTheme { MobileAppTheme {
// A surface container using the 'background' color from the theme // A surface container using the 'background' color from the theme

View File

@ -33,8 +33,11 @@ val buttonHeightStandard = 72.dp
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @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("") } var text = remember { mutableStateOf("") }
startValue?.let{
text.value = startValue
}
OutlinedTextField( OutlinedTextField(
value = text.value, value = text.value,
@ -161,7 +164,7 @@ fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClic
fun PlaceholderTextFieldPreview() { fun PlaceholderTextFieldPreview() {
MobileAppTheme { MobileAppTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { 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.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment 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.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.mobileapp.R import com.example.mobileapp.R
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Mail import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.database.entities.Story import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.ui.theme.BackgroundItem2 import com.example.mobileapp.ui.theme.BackgroundItem2
import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2 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 @Composable
fun <T : Any> DataListScroll(navController: NavHostController, dataList: List<T>){ fun <T : Any> DataListScroll(navController: NavHostController, dataList: List<T>){
@ -70,10 +79,20 @@ inline fun <reified T> List<*>.isListOf(): Boolean {
@Composable @Composable
fun StoryListItem(item: Story, navController: NavHostController){ fun StoryListItem(item: Story, navController: NavHostController){
val context = LocalContext.current
val isExpanded = remember { val isExpanded = remember {
mutableStateOf(false) mutableStateOf(false)
} }
val showDialog = remember {
mutableStateOf(false)
}
val delete = remember {
mutableStateOf(false)
}
Card( Card(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -105,7 +124,7 @@ fun StoryListItem(item: Story, navController: NavHostController){
modifier = Modifier.padding(8.dp) modifier = Modifier.padding(8.dp)
){ ){
Text( Text(
text = item.title, text = "${item.title} | ${dateFormat.format(Date(item.postdate!!))}",
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
@ -121,15 +140,35 @@ fun StoryListItem(item: Story, navController: NavHostController){
horizontalArrangement = Arrangement.End horizontalArrangement = Arrangement.End
){ ){
DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = { DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = {
navController.navigate("editstory/" + item.id) navController.navigate("editstory/${item.id}")
}) })
DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = { 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 @Composable
@ -187,7 +226,7 @@ fun MailListItem(item: Mail){
modifier = Modifier.padding(8.dp) modifier = Modifier.padding(8.dp)
){ ){
Text( Text(
text = "item.username", text = "item.username | ${dateFormat.format(Date(item.postdate!!))}",
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.Bold) fontWeight = FontWeight.Bold)
Text(text = item.message) 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.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.mobileapp.R import com.example.mobileapp.R
import com.example.mobileapp.screens.Authorization import com.example.mobileapp.screens.Authorization
import com.example.mobileapp.screens.EditMailScreen import com.example.mobileapp.screens.EditMailScreen
@ -122,20 +124,19 @@ fun NavBar(navController: NavHostController) {
EditStoryScreen(navController = navController) EditStoryScreen(navController = navController)
bottomBarState.value = false bottomBarState.value = false
} }
composable("editstory/{storyId}"){ navBackStackEntry -> composable(
val storyId = navBackStackEntry.arguments?.getInt("storyId") "editstory/{id}",
EditStoryScreen(navController = navController, storyId = storyId) arguments = listOf(navArgument("id") { type = NavType.IntType })
bottomBarState.value = false ) { backStackEntry ->
backStackEntry.arguments?.let {
EditStoryScreen(navController = navController, storyId = it.getInt("id"))
bottomBarState.value = false
}
} }
composable("editmail"){ // Без аргумента composable("editmail"){ // Без аргумента
EditMailScreen(navController = navController) EditMailScreen(navController = navController)
bottomBarState.value = false 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 @Volatile
private var INSTANCE: MobileAppDataBase? = null private var INSTANCE: MobileAppDataBase? = null
suspend fun initialDataBase(){ suspend fun initialDataBase(appContext: Context){
INSTANCE?.let { database -> INSTANCE?.let { database ->
val userDao = database.userDao() val userDao = database.userDao()
userDao.insert(User(id = 1, login = "Дзюнзи Ито", password = "1234", email = "ito@gmail.com")) userDao.insert(User(id = 1, login = "Дзюнзи Ито", password = "1234", email = "ito@gmail.com"))
userDao.insert(User(id = 2, login = "Стивен Кинг", password = "4321", email = "king@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 = "История ужасов от Дзюнзи Ито", 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 = "Знаменитая книга стивена кинга", 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() val mailDao = database.mailDao()
mailDao.insert(Mail(message = "Выложил новые страницы", userId = 1)) mailDao.insert(Mail(message = "Выложил новые страницы", userId = 1))
@ -61,7 +61,7 @@ abstract class MobileAppDataBase : RoomDatabase() {
override fun onCreate(db: SupportSQLiteDatabase) { override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db) super.onCreate(db)
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
initialDataBase() initialDataBase(appContext)
} }
} }
}) })

View File

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

View File

@ -1,5 +1,13 @@
package com.example.mobileapp.screens 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.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -14,6 +22,7 @@ import androidx.compose.runtime.remember
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.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource 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.PasswordInputField
import com.example.mobileapp.components.PlaceholderInputField import com.example.mobileapp.components.PlaceholderInputField
import com.example.mobileapp.database.MobileAppDataBase import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.database.entities.Story import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2 import com.example.mobileapp.ui.theme.ButtonColor2
@ -34,16 +44,70 @@ import kotlinx.coroutines.withContext
@Composable @Composable
fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) {
val context = LocalContext.current 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{ storyId?.let{
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
withContext(Dispatchers.IO) { 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( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -51,28 +115,49 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) {
verticalArrangement = Arrangement.Bottom verticalArrangement = Arrangement.Bottom
) { ) {
Image( Image(
painter = painterResource(id = R.drawable.editplaceholder), bitmap = cover.value.asImageBitmap(),
contentDescription = "editplaceholder", contentDescription = "editplaceholder",
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
.size(384.dp) .size(384.dp)
.padding(8.dp) .padding(8.dp)
.align(Alignment.CenterHorizontally)) .align(Alignment.CenterHorizontally))
ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {}) ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
PlaceholderInputField(label = "Название", true, onTextChanged = { newName -> 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 = "Назад", NavigationButton(navController = navController, destination = "story", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White) backgroundColor = ButtonColor2, textColor = Color.White)
} }
} }
@Composable @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( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -87,8 +172,12 @@ fun EditMailScreen(navController: NavHostController, mailId: Int? = null) {
.size(512.dp) .size(512.dp)
.padding(8.dp) .padding(8.dp)
.align(Alignment.CenterHorizontally)) .align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Текс поста", false, onTextChanged = {}) PlaceholderInputField(label = "Текс поста", isSingleLine = false, onTextChanged = { newmessage ->
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {}) message.value = newmessage
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
create.value = !create.value
})
NavigationButton(navController = navController, destination = "mail", label = "Назад", NavigationButton(navController = navController, destination = "mail", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White) backgroundColor = ButtonColor2, textColor = Color.White)
} }

View File

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