diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0e06458..a349b4c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> List<*>.isListOf(): Boolean { } @Composable -fun StoryListItem(item: Story, navController: NavHostController){ - val context = LocalContext.current - +fun StoryListItem(item: Story, navController: NavHostController, + storyViewModel: StoryViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { val isExpanded = remember { mutableStateOf(false) } @@ -89,10 +93,6 @@ fun StoryListItem(item: Story, navController: NavHostController){ mutableStateOf(false) } - val delete = remember { - mutableStateOf(false) - } - Card( modifier = Modifier .fillMaxWidth() @@ -153,22 +153,12 @@ fun StoryListItem(item: Story, navController: NavHostController){ if(showDialog.value) { DialogWindow(label = "Подтверждение", message = "Вы уверены что хотите удалить запись?", onConfirmAction = { - delete.value = !delete.value + storyViewModel.deleteStory(item) 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 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 aa8b3a4..659e151 100644 --- a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt +++ b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt @@ -18,13 +18,17 @@ import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavHostController @@ -37,8 +41,8 @@ import com.example.mobileapp.screens.Authorization import com.example.mobileapp.screens.EditMailScreen import com.example.mobileapp.screens.EditStoryScreen import com.example.mobileapp.screens.EditUserScreen -import com.example.mobileapp.screens.ListDataScreen import com.example.mobileapp.screens.ListMailScreen +import com.example.mobileapp.screens.ListStoryScreen import com.example.mobileapp.screens.MainScreen import com.example.mobileapp.screens.Registration import com.example.mobileapp.screens.SettingsScreen @@ -53,9 +57,28 @@ val navBarItems = listOf( @OptIn(ExperimentalMaterial3Api::class) @Composable fun NavBar(navController: NavHostController) { + val topBarState = rememberSaveable { (mutableStateOf(false)) } val bottomBarState = rememberSaveable { (mutableStateOf(false)) } Scaffold( + topBar = { + AnimatedVisibility( + visible = topBarState.value, + enter = slideInVertically(initialOffsetY = { it }), + exit = slideOutVertically(targetOffsetY = { it }), + content = { + TopAppBar(title = { + Text( + text = "Storyteller", + textAlign = TextAlign.Center, + fontFamily = FontFamily(Font( + R.font.irishgrover_regular, FontWeight.Bold + )) + ) + }) + } + ) + }, bottomBar = { AnimatedVisibility( visible = bottomBarState.value, @@ -98,30 +121,37 @@ fun NavBar(navController: NavHostController) { modifier = Modifier.padding(innerPaddings) ) { composable("authorization"){ + topBarState.value = true bottomBarState.value = false Authorization(navController = navController) } composable("registration"){ + topBarState.value = true bottomBarState.value = false Registration(navController = navController) } composable("main"){ + topBarState.value = false bottomBarState.value = true MainScreen(navController = navController) } composable("story"){ + topBarState.value = false bottomBarState.value = true - ListDataScreen(navController = navController) + ListStoryScreen(navController = navController) } composable("mail"){ + topBarState.value = false bottomBarState.value = true ListMailScreen(navController = navController) } composable("settings"){ + topBarState.value = true bottomBarState.value = true SettingsScreen(navController = navController) } composable("editstory"){ // Без аргумента + topBarState.value = false bottomBarState.value = false EditStoryScreen(navController = navController) } @@ -130,15 +160,18 @@ fun NavBar(navController: NavHostController) { arguments = listOf(navArgument("id") { type = NavType.IntType }) //С аргументом ) { backStackEntry -> backStackEntry.arguments?.let { + topBarState.value = false bottomBarState.value = false EditStoryScreen(navController = navController, storyId = it.getInt("id")) } } composable("editmail"){ // Без аргумента + topBarState.value = false bottomBarState.value = false EditMailScreen(navController = navController) } composable("edituser"){ + topBarState.value = false bottomBarState.value = false EditUserScreen(navController = navController) } diff --git a/app/src/main/java/com/example/mobileapp/database/dao/MailDao.kt b/app/src/main/java/com/example/mobileapp/database/dao/MailDao.kt index bacf1a5..e8f2298 100644 --- a/app/src/main/java/com/example/mobileapp/database/dao/MailDao.kt +++ b/app/src/main/java/com/example/mobileapp/database/dao/MailDao.kt @@ -15,7 +15,7 @@ interface MailDao { fun getAll(): Flow> @Query("select * from mails where mails.id = :id") - fun getById(id: Int): Mail? + fun getById(id: Int): Flow @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(mail: Mail) diff --git a/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt b/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt index d6c2358..9955fe1 100644 --- a/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt +++ b/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt @@ -15,7 +15,7 @@ interface StoryDao { fun getAll(): Flow> @Query("select * from stories where stories.id = :id") - fun getById(id: Int): Story? + fun getById(id: Int): Flow @Query("select * from stories where stories.user_id = :userId") fun getByUserId(userId: Int): Flow> diff --git a/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt b/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt index 0de3004..18b46b3 100644 --- a/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt +++ b/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt @@ -15,7 +15,10 @@ interface UserDao { fun getAll():Flow> @Query("select * from users where users.id = :id") - fun getById(id: Int): User? + suspend fun getById(id: Int): User? + + @Query("select * from users where users.login = :login") + suspend fun getByLogin(login: String): User? @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(user: User) diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/MailRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/MailRepository.kt new file mode 100644 index 0000000..d7e36e0 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/repositories/MailRepository.kt @@ -0,0 +1,16 @@ +package com.example.mobileapp.database.repositories + +import com.example.mobileapp.database.entities.Mail +import kotlinx.coroutines.flow.Flow + +interface MailRepository { + fun getAllMails(): Flow> + + fun getMail(id: Int): Flow + + suspend fun insertMail(mail: Mail) + + suspend fun updateMail(mail: Mail) + + suspend fun deleteMail(mail: Mail) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/OfflineMailRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineMailRepository.kt new file mode 100644 index 0000000..50688f0 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineMailRepository.kt @@ -0,0 +1,17 @@ +package com.example.mobileapp.database.repositories + +import com.example.mobileapp.database.dao.MailDao +import com.example.mobileapp.database.entities.Mail +import kotlinx.coroutines.flow.Flow + +class OfflineMailRepository(private val mailDao: MailDao): MailRepository { + override fun getAllMails(): Flow> = mailDao.getAll() + + override fun getMail(id: Int): Flow = mailDao.getById(id) + + override suspend fun insertMail(mail: Mail) = mailDao.insert(mail) + + override suspend fun updateMail(mail: Mail) = mailDao.update(mail) + + override suspend fun deleteMail(mail: Mail) = mailDao.delete(mail) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/OfflineStoryRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineStoryRepository.kt new file mode 100644 index 0000000..dd3cea8 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineStoryRepository.kt @@ -0,0 +1,19 @@ +package com.example.mobileapp.database.repositories + +import com.example.mobileapp.database.dao.StoryDao +import com.example.mobileapp.database.entities.Story +import kotlinx.coroutines.flow.Flow + +class OfflineStoryRepository(private val storyDao: StoryDao): StoryRepository { + override fun getAllStories(): Flow> = storyDao.getAll() + + override fun getStoriesByUserId(userId: Int): Flow> = storyDao.getByUserId(userId) + + override fun getStoryById(id: Int): Flow = storyDao.getById(id) + + override suspend fun insertStory(story: Story) = storyDao.insert(story) + + override suspend fun updateStory(story: Story) = storyDao.update(story) + + override suspend fun deleteStory(story: Story) = storyDao.delete(story) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt new file mode 100644 index 0000000..c32ffb3 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt @@ -0,0 +1,19 @@ +package com.example.mobileapp.database.repositories + +import com.example.mobileapp.database.dao.UserDao +import com.example.mobileapp.database.entities.User +import kotlinx.coroutines.flow.Flow + +class OfflineUserRepository(private val userDao: UserDao): UserRepository { + override fun getAllUsers(): Flow> = userDao.getAll() + + override suspend fun getUser(id: Int): User? = userDao.getById(id) + + override suspend fun getUserByLogin(login: String): User? = userDao.getByLogin(login) + + override suspend fun insertUser(user: User) = userDao.insert(user) + + override suspend fun updateUser(user: User) = userDao.update(user) + + override suspend fun deleteUser(user: User) = userDao.delete(user) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/StoryRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/StoryRepository.kt new file mode 100644 index 0000000..f08d842 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/repositories/StoryRepository.kt @@ -0,0 +1,18 @@ +package com.example.mobileapp.database.repositories + +import com.example.mobileapp.database.entities.Story +import kotlinx.coroutines.flow.Flow + +interface StoryRepository { + fun getAllStories(): Flow> + + fun getStoriesByUserId(userId: Int): Flow> + + fun getStoryById(id: Int): Flow + + suspend fun insertStory(story: Story) + + suspend fun updateStory(story: Story) + + suspend fun deleteStory(story: Story) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt new file mode 100644 index 0000000..3be70c9 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt @@ -0,0 +1,18 @@ +package com.example.mobileapp.database.repositories + +import com.example.mobileapp.database.entities.User +import kotlinx.coroutines.flow.Flow + +interface UserRepository { + fun getAllUsers(): Flow> + + suspend fun getUser(id: Int): User? + + suspend fun getUserByLogin(login: String): User? + + suspend fun insertUser(user: User) + + suspend fun updateUser(user: User) + + suspend fun deleteUser(user: User) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/viewmodels/MailViewModel.kt b/app/src/main/java/com/example/mobileapp/database/viewmodels/MailViewModel.kt new file mode 100644 index 0000000..8bcd122 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/viewmodels/MailViewModel.kt @@ -0,0 +1,26 @@ +package com.example.mobileapp.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.mobileapp.database.entities.Mail +import com.example.mobileapp.database.repositories.MailRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch + +class MailViewModel(private val mailRepository: MailRepository): ViewModel() { + val getAllMails = mailRepository.getAllMails() + + fun getMail(id: Int): Flow = mailRepository.getMail(id) + + fun insertMail(mail: Mail) = viewModelScope.launch { + mailRepository.insertMail(mail) + } + + fun updateMail(mail: Mail) = viewModelScope.launch { + mailRepository.updateMail(mail) + } + + fun deleteMail(mail: Mail) = viewModelScope.launch { + mailRepository.deleteMail(mail) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/viewmodels/MobileAppViewModelProvider.kt b/app/src/main/java/com/example/mobileapp/database/viewmodels/MobileAppViewModelProvider.kt new file mode 100644 index 0000000..9d3554d --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/viewmodels/MobileAppViewModelProvider.kt @@ -0,0 +1,24 @@ +package com.example.mobileapp.database.viewmodels + +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.CreationExtras +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import com.example.mobileapp.MobileApp + +object MobileAppViewModelProvider { + val Factory = viewModelFactory { + initializer { + MailViewModel(app().container.mailRepository) + } + initializer { + StoryViewModel(app().container.storyRepository) + } + initializer { + UserViewModel(app().container.userRepository) + } + } +} + +fun CreationExtras.app(): MobileApp = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MobileApp) \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/viewmodels/StoryViewModel.kt b/app/src/main/java/com/example/mobileapp/database/viewmodels/StoryViewModel.kt new file mode 100644 index 0000000..5fd70af --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/viewmodels/StoryViewModel.kt @@ -0,0 +1,29 @@ +package com.example.mobileapp.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.mobileapp.database.entities.Story +import com.example.mobileapp.database.repositories.StoryRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch + +class StoryViewModel(private val storyRepository: StoryRepository): ViewModel() { + + val getAllStories = storyRepository.getAllStories() + + fun getStoryById(id: Int): Flow = storyRepository.getStoryById(id) + + fun getStoriesByUserId(userId: Int): Flow> = storyRepository.getStoriesByUserId(userId) + + fun insertStory(story: Story) = viewModelScope.launch { + storyRepository.insertStory(story) + } + + fun updateStory(story: Story) = viewModelScope.launch { + storyRepository.updateStory(story) + } + + fun deleteStory(story: Story) = viewModelScope.launch { + storyRepository.deleteStory(story) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt b/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt new file mode 100644 index 0000000..6b33556 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt @@ -0,0 +1,53 @@ +package com.example.mobileapp.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.mobileapp.GlobalUser +import com.example.mobileapp.database.entities.User +import com.example.mobileapp.database.repositories.UserRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch + +class UserViewModel(private val userRepository: UserRepository): ViewModel() { + val getAllUsers = userRepository.getAllUsers() + + suspend fun getUser(id: Int): User? = userRepository.getUser(id) + + fun updateUser(user: User) = viewModelScope.launch { + userRepository.updateUser(user) + } + + fun deleteUser(user: User) = viewModelScope.launch { + userRepository.deleteUser(user) + } + + fun regUser(user: User) = viewModelScope.launch { + val globalUser = userRepository.getUserByLogin(user.login) + globalUser?.let { + return@launch + } ?: run { + if(user.password.isEmpty()){ + return@launch + } + + if(user.email.isEmpty() || !isValidEmail(user.email)){ + return@launch + } + userRepository.insertUser(user) + GlobalUser.getInstance().setUser(userRepository.getUserByLogin(user.login)) + } + } + + fun authUser(user: User) = viewModelScope.launch { + val globalUser = userRepository.getUserByLogin(user.login) + globalUser?.let { + if (user.password.isNotEmpty() && user.password == globalUser.password){ + GlobalUser.getInstance().setUser(globalUser) + } + } + } + + private fun isValidEmail(email: String): Boolean { + return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches() + } +} \ No newline at end of file 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 ec46274..363aa9c 100644 --- a/app/src/main/java/com/example/mobileapp/screens/Authorization.kt +++ b/app/src/main/java/com/example/mobileapp/screens/Authorization.kt @@ -8,7 +8,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -17,31 +19,32 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import com.example.mobileapp.R +import com.example.mobileapp.components.ActiveButton 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.User +import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider +import com.example.mobileapp.database.viewmodels.UserViewModel import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor2 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun Authorization(navController: NavHostController){ - val context = LocalContext.current - val users = remember { mutableStateListOf() } +fun Authorization(navController: NavHostController, + userViewModel: UserViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { + val users = userViewModel.getAllUsers.collectAsState(emptyList()).value + + val login = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - MobileAppDataBase.getInstance(context).userDao().getAll().collect { data -> - users.clear() - users.addAll(data) - } - } - } Column( modifier = Modifier .fillMaxSize() @@ -53,13 +56,26 @@ fun Authorization(navController: NavHostController){ contentDescription = "login", contentScale = ContentScale.Crop, modifier = Modifier - .size(512.dp) + .size(448.dp) .padding(8.dp) .align(Alignment.CenterHorizontally)) - PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {}) - PasswordInputField(label = "Пароль", onPasswordChanged = {}) - NavigationButton(navController = navController, destination = "main", label = "Вход", - backgroundColor = ButtonColor2, textColor = Color.White) + PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {newlogin -> + login.value = newlogin + }) + PasswordInputField(label = "Пароль", onPasswordChanged = {newpassword -> + password.value = newpassword + }) + ActiveButton(label = "Вход", backgroundColor = ButtonColor2, + textColor = Color.White, onClickAction = { + userViewModel.authUser( + User( + login = login.value, + password = password.value, + email = String() + ) + ) + navController.navigate("main") + }) NavigationButton(navController = navController, destination = "registration", label = "Регистрация", backgroundColor = ButtonColor1, textColor = Color.Black) } 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 720efd8..f28342b 100644 --- a/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt +++ b/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt @@ -16,7 +16,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -27,22 +28,29 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController +import com.example.mobileapp.GlobalUser import com.example.mobileapp.R import com.example.mobileapp.components.ActiveButton 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.database.viewmodels.MailViewModel +import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider +import com.example.mobileapp.database.viewmodels.StoryViewModel import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor2 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { +fun EditStoryScreen(navController: NavHostController, storyId: Int? = null, + storyViewModel: StoryViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { val context = LocalContext.current val cover = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.editplaceholder)) } @@ -58,7 +66,6 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { 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!!) @@ -67,45 +74,10 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { } storyId?.let{ - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - 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") + val story by storyViewModel.getStoryById(storyId).collectAsState(null) + cover.value = story!!.cover + title.value = story!!.title + description.value = story!!.description } Column( @@ -134,7 +106,27 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { description.value = newDescription }) ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = { - edit.value = !edit.value + storyId?.let { + storyViewModel.updateStory( + Story( + id = storyId, + cover = cover.value, + title = title.value, + description = description.value, + userId = GlobalUser.getInstance().getUser()?.id!! + ) + ) + } ?: run { + storyViewModel.insertStory( + Story( + cover = cover.value, + title = title.value, + description = description.value, + userId = GlobalUser.getInstance().getUser()?.id!! + ) + ) + } + navController.navigate("story") }) NavigationButton(navController = navController, destination = "story", label = "Назад", backgroundColor = ButtonColor2, textColor = Color.White) @@ -142,22 +134,12 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { } @Composable -fun EditMailScreen(navController: NavHostController) { - val context = LocalContext.current - +fun EditMailScreen(navController: NavHostController, + mailViewModel: MailViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { 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() @@ -176,7 +158,13 @@ fun EditMailScreen(navController: NavHostController) { message.value = newmessage }) ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = { - create.value = !create.value + mailViewModel.insertMail( + Mail( + message = message.value, + userId = GlobalUser.getInstance().getUser()?.id!! + ) + ) + navController.navigate("mail") }) NavigationButton(navController = navController, destination = "mail", label = "Назад", backgroundColor = ButtonColor2, textColor = Color.White) diff --git a/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt index 10e279a..fd9d15f 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt @@ -5,32 +5,29 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import com.example.mobileapp.components.DataListScroll import com.example.mobileapp.database.MobileAppDataBase import com.example.mobileapp.database.entities.Mail +import com.example.mobileapp.database.viewmodels.MailViewModel +import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider import com.example.mobileapp.ui.theme.BackgroundItem1 import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.withContext @Composable -fun ListMailScreen(navController: NavHostController){ - - val context = LocalContext.current - val mails = remember { mutableStateListOf() } - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - MobileAppDataBase.getInstance(context).mailDao().getAll().collect { data -> - mails.clear() - mails.addAll(data) - } - } - } +fun ListMailScreen(navController: NavHostController, + mailViewModel: MailViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { + val mails = mailViewModel.getAllMails.collectAsState(emptyList()).value Column( modifier = Modifier diff --git a/app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ListStoryScreen.kt similarity index 57% rename from app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt rename to app/src/main/java/com/example/mobileapp/screens/ListStoryScreen.kt index 70680df..adc569c 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ListStoryScreen.kt @@ -1,42 +1,32 @@ package com.example.mobileapp.screens import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import com.example.mobileapp.components.DataListScroll -import com.example.mobileapp.components.NavBar import com.example.mobileapp.database.MobileAppDataBase import com.example.mobileapp.database.entities.Story +import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider +import com.example.mobileapp.database.viewmodels.StoryViewModel import com.example.mobileapp.ui.theme.BackgroundItem1 -import com.example.mobileapp.ui.theme.BackgroundItem2 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun ListDataScreen(navController: NavHostController){ - - val context = LocalContext.current - val stories = remember { mutableStateListOf() } - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - MobileAppDataBase.getInstance(context).storyDao().getAll().collect { data -> - stories.clear() - stories.addAll(data) - } - } - } +fun ListStoryScreen(navController: NavHostController, + storyViewModel: StoryViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { + val stories = storyViewModel.getAllStories.collectAsState(emptyList()).value Column( modifier = Modifier 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 4e124b8..f4fcfc9 100644 --- a/app/src/main/java/com/example/mobileapp/screens/Registration.kt +++ b/app/src/main/java/com/example/mobileapp/screens/Registration.kt @@ -7,22 +7,37 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +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.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import com.example.mobileapp.R +import com.example.mobileapp.components.ActiveButton import com.example.mobileapp.components.NavigationButton import com.example.mobileapp.components.PasswordInputField import com.example.mobileapp.components.PlaceholderInputField +import com.example.mobileapp.database.entities.User +import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider +import com.example.mobileapp.database.viewmodels.UserViewModel import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor2 @Composable -fun Registration(navController: NavHostController){ +fun Registration(navController: NavHostController, + userViewModel: UserViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { + val login = remember { mutableStateOf("") } + val email = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } + val repeatepassword = remember { mutableStateOf("") } + Column( modifier = Modifier .fillMaxSize() @@ -34,15 +49,34 @@ fun Registration(navController: NavHostController){ contentDescription = "registration", contentScale = ContentScale.Crop, modifier = Modifier - .size(384.dp) + .size(320.dp) .padding(8.dp) .align(Alignment.CenterHorizontally)) - PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {}) - PlaceholderInputField(label = "Email", isSingleLine = true, onTextChanged = {}) - PasswordInputField(label = "Пароль", onPasswordChanged = {}) - PasswordInputField(label = "Пароль ещё раз", onPasswordChanged = {}) - NavigationButton(navController = navController, destination = "main", - label = "Зарегистрироваться", backgroundColor = ButtonColor2, textColor = Color.White) + PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {newlogin -> + login.value = newlogin + }) + PlaceholderInputField(label = "Email", isSingleLine = true, onTextChanged = {newemail -> + email.value = newemail + }) + PasswordInputField(label = "Пароль", onPasswordChanged = {newpassword -> + password.value = newpassword + }) + PasswordInputField(label = "Пароль ещё раз", onPasswordChanged = {newpassword -> + repeatepassword.value = newpassword + }) + ActiveButton(label = "Зарегистрироваться", backgroundColor = ButtonColor2, + textColor = Color.White, onClickAction = { + if (password.value == repeatepassword.value){ + userViewModel.regUser( + User( + login = login.value, + password = password.value, + email = email.value + ) + ) + } + navController.navigate("main") + }) NavigationButton(navController = navController, destination = "authorization", label = "Назад", backgroundColor = ButtonColor1, textColor = Color.Black) }