CRUD почти есть, также работает регистрация и вход

This commit is contained in:
maxnes3 2023-12-08 18:04:05 +04:00
parent 69175e82f0
commit 2c1100863b
23 changed files with 475 additions and 138 deletions

View File

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".MobileApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"

View File

@ -0,0 +1,12 @@
package com.example.mobileapp
import android.app.Application
class MobileApp: Application() {
lateinit var container: MobileAppContainer
override fun onCreate() {
super.onCreate()
container = MobileAppDataContainer(this)
}
}

View File

@ -0,0 +1,34 @@
package com.example.mobileapp
import android.content.Context
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.repositories.MailRepository
import com.example.mobileapp.database.repositories.OfflineMailRepository
import com.example.mobileapp.database.repositories.OfflineStoryRepository
import com.example.mobileapp.database.repositories.OfflineUserRepository
import com.example.mobileapp.database.repositories.StoryRepository
import com.example.mobileapp.database.repositories.UserRepository
interface MobileAppContainer {
val mailRepository: MailRepository
val storyRepository: StoryRepository
val userRepository: UserRepository
}
class MobileAppDataContainer(private val context: Context): MobileAppContainer {
override val mailRepository: MailRepository by lazy {
OfflineMailRepository(MobileAppDataBase.getInstance(context).mailDao())
}
override val storyRepository: StoryRepository by lazy {
OfflineStoryRepository(MobileAppDataBase.getInstance(context).storyDao())
}
override val userRepository: UserRepository by lazy {
OfflineUserRepository(MobileAppDataBase.getInstance(context).userDao())
}
companion object{
const val TIMEOUT = 5000L
}
}

View File

@ -36,11 +36,14 @@ 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.lifecycle.viewmodel.compose.viewModel
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.database.viewmodels.MobileAppViewModelProvider
import com.example.mobileapp.database.viewmodels.StoryViewModel
import com.example.mobileapp.ui.theme.BackgroundItem2
import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2
@ -78,9 +81,10 @@ inline fun <reified T> 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

View File

@ -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)
}

View File

@ -15,7 +15,7 @@ interface MailDao {
fun getAll(): Flow<List<Mail>>
@Query("select * from mails where mails.id = :id")
fun getById(id: Int): Mail?
fun getById(id: Int): Flow<Mail?>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(mail: Mail)

View File

@ -15,7 +15,7 @@ interface StoryDao {
fun getAll(): Flow<List<Story>>
@Query("select * from stories where stories.id = :id")
fun getById(id: Int): Story?
fun getById(id: Int): Flow<Story?>
@Query("select * from stories where stories.user_id = :userId")
fun getByUserId(userId: Int): Flow<List<Story>>

View File

@ -15,7 +15,10 @@ interface UserDao {
fun getAll():Flow<List<User>>
@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)

View File

@ -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<List<Mail>>
fun getMail(id: Int): Flow<Mail?>
suspend fun insertMail(mail: Mail)
suspend fun updateMail(mail: Mail)
suspend fun deleteMail(mail: Mail)
}

View File

@ -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<List<Mail>> = mailDao.getAll()
override fun getMail(id: Int): Flow<Mail?> = 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)
}

View File

@ -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<List<Story>> = storyDao.getAll()
override fun getStoriesByUserId(userId: Int): Flow<List<Story>> = storyDao.getByUserId(userId)
override fun getStoryById(id: Int): Flow<Story?> = 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)
}

View File

@ -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<List<User>> = 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)
}

View File

@ -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<List<Story>>
fun getStoriesByUserId(userId: Int): Flow<List<Story>>
fun getStoryById(id: Int): Flow<Story?>
suspend fun insertStory(story: Story)
suspend fun updateStory(story: Story)
suspend fun deleteStory(story: Story)
}

View File

@ -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<List<User>>
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)
}

View File

@ -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<Mail?> = 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)
}
}

View File

@ -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)

View File

@ -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<Story?> = storyRepository.getStoryById(id)
fun getStoriesByUserId(userId: Int): Flow<List<Story>> = 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)
}
}

View File

@ -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()
}
}

View File

@ -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<User>() }
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)
}

View File

@ -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<Bitmap>(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)

View File

@ -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<Mail>() }
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

View File

@ -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<Story>() }
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

View File

@ -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)
}