From da844b15f7f0c47fc1051dcec7e3c72745cd6e70 Mon Sep 17 00:00:00 2001 From: maxnes3 <112558334+maxnes3@users.noreply.github.com> Date: Sat, 25 Nov 2023 03:02:32 +0400 Subject: [PATCH] =?UTF-8?q?CRUD=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0?= =?UTF-8?q?=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/mobileapp/MainActivity.kt | 5 - .../mobileapp/components/InputContent.kt | 7 +- .../mobileapp/components/ListContent.kt | 87 +++++++++++++- .../mobileapp/components/NavigationBar.kt | 19 +-- .../mobileapp/database/MobileAppDataBase.kt | 10 +- .../mobileapp/screens/Authorization.kt | 2 +- .../example/mobileapp/screens/EditScreens.kt | 113 ++++++++++++++++-- .../example/mobileapp/screens/Registration.kt | 4 +- 8 files changed, 206 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/example/mobileapp/MainActivity.kt b/app/src/main/java/com/example/mobileapp/MainActivity.kt index 5cec01e..0b0ea0f 100644 --- a/app/src/main/java/com/example/mobileapp/MainActivity.kt +++ b/app/src/main/java/com/example/mobileapp/MainActivity.kt @@ -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 diff --git a/app/src/main/java/com/example/mobileapp/components/InputContent.kt b/app/src/main/java/com/example/mobileapp/components/InputContent.kt index 3d7d456..7af5b15 100644 --- a/app/src/main/java/com/example/mobileapp/components/InputContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/InputContent.kt @@ -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, { }) } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/components/ListContent.kt b/app/src/main/java/com/example/mobileapp/components/ListContent.kt index b3058b7..23e63e6 100644 --- a/app/src/main/java/com/example/mobileapp/components/ListContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/ListContent.kt @@ -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 DataListScroll(navController: NavHostController, dataList: List){ @@ -70,10 +79,20 @@ inline fun 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) + } + } + ) +} diff --git a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt index 94c812b..c259de7 100644 --- a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt +++ b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt @@ -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 - } } } } diff --git a/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt b/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt index a97d0d8..4e96fac 100644 --- a/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt +++ b/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt @@ -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) } } }) diff --git a/app/src/main/java/com/example/mobileapp/screens/Authorization.kt b/app/src/main/java/com/example/mobileapp/screens/Authorization.kt index af642f7..ec46274 100644 --- a/app/src/main/java/com/example/mobileapp/screens/Authorization.kt +++ b/app/src/main/java/com/example/mobileapp/screens/Authorization.kt @@ -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) diff --git a/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt b/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt index b477854..93b6b75 100644 --- a/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt +++ b/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt @@ -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(null) } + + val cover = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.editplaceholder)) } + val title = remember { mutableStateOf("") } + val description = remember { mutableStateOf("") } + + val imageData = remember { mutableStateOf(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) } diff --git a/app/src/main/java/com/example/mobileapp/screens/Registration.kt b/app/src/main/java/com/example/mobileapp/screens/Registration.kt index 7fb0552..4e124b8 100644 --- a/app/src/main/java/com/example/mobileapp/screens/Registration.kt +++ b/app/src/main/java/com/example/mobileapp/screens/Registration.kt @@ -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",