From db3bf44b273ccb2439303598f8b46b7fa8fcc36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=90=D0=BB=D0=B5=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=D0=BD?= Date: Sat, 23 Dec 2023 03:01:16 +0400 Subject: [PATCH] =?UTF-8?q?4-=D1=83=D1=8E=20=D0=BF=D0=BE=D1=87=D1=82=D0=B8?= =?UTF-8?q?=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++ app/src/main/AndroidManifest.xml | 1 + .../com/example/myapplication/MainActivity.kt | 23 ++++++++ .../com/example/myapplication/MobileApp.kt | 12 +++++ .../myapplication/MobileAppContainer.kt | 27 ++++++++++ .../myapplication/components/InputContent.kt | 50 +++++++++++++++++ .../myapplication/database/MobileDatabase.kt | 4 +- .../myapplication/database/dao/CardDao.kt | 7 +-- .../myapplication/database/dao/UserDao.kt | 9 ++-- .../database/repositories/CardRepository.kt | 19 +++++++ .../repositories/OfflineCardRepository.kt | 49 +++++++++++++++++ .../repositories/OfflineUserRepository.kt | 21 ++++++++ .../database/repositories/UserRepository.kt | 22 ++++++++ .../database/viewmodels/CardViewModel.kt | 25 +++++++++ .../viewmodels/MobileAppViewModelProvider.kt | 21 ++++++++ .../database/viewmodels/UserViewModel.kt | 53 +++++++++++++++++++ .../myapplication/screens/authorization.kt | 52 ++++++++++++------ .../example/myapplication/screens/editcard.kt | 34 ++++++++---- .../myapplication/screens/mainScreen.kt | 41 +++++++++----- .../myapplication/screens/registration.kt | 52 ++++++++++++++---- .../com/example/myapplication/screens/user.kt | 47 +++++++++++----- 21 files changed, 500 insertions(+), 73 deletions(-) create mode 100644 app/src/main/java/com/example/myapplication/MobileApp.kt create mode 100644 app/src/main/java/com/example/myapplication/MobileAppContainer.kt create mode 100644 app/src/main/java/com/example/myapplication/database/repositories/CardRepository.kt create mode 100644 app/src/main/java/com/example/myapplication/database/repositories/OfflineCardRepository.kt create mode 100644 app/src/main/java/com/example/myapplication/database/repositories/OfflineUserRepository.kt create mode 100644 app/src/main/java/com/example/myapplication/database/repositories/UserRepository.kt create mode 100644 app/src/main/java/com/example/myapplication/database/viewmodels/CardViewModel.kt create mode 100644 app/src/main/java/com/example/myapplication/database/viewmodels/MobileAppViewModelProvider.kt create mode 100644 app/src/main/java/com/example/myapplication/database/viewmodels/UserViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3659f9a..27972c2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -80,4 +80,8 @@ dependencies { ksp("androidx.room:room-compiler:$room_version") implementation("androidx.room:room-ktx:$room_version") implementation("androidx.room:room-paging:$room_version") + + //Paging + implementation ("androidx.paging:paging-compose:3.2.1") + implementation ("androidx.paging:paging-runtime:3.2.1") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e013846..80e213c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> Unit){ + var text = remember { mutableStateOf("") } + startValue?.let{ + text.value = startValue + } + OutlinedTextField( + value = text.value, + onValueChange = { + text.value = it + onTextChanged(it) + }, + placeholder = { + Text(label) + }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), + shape = RoundedCornerShape(10.dp), + singleLine = isSingleLine + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PasswordInputField(label: String, startValue: String? = null, onPasswordChanged: (String) -> Unit){ + var text = remember { mutableStateOf("") } + startValue?.let{ + text.value = startValue + } + + OutlinedTextField( + value = text.value, + onValueChange = { + text.value = it + onPasswordChanged(it) + }, + placeholder = { + Text(label) + }, + visualTransformation = PasswordVisualTransformation(), + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), + shape = RoundedCornerShape(10.dp)) } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt b/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt index 5a38fa0..93430b2 100644 --- a/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt +++ b/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt @@ -53,8 +53,8 @@ abstract class MobileAppDataBase : RoomDatabase() { private suspend fun initialDataBase(appContext: Context) { INSTANCE?.let { database -> val userDao = database.userDao() - userDao.insert(User(id = 1, login = "Иван", password = "1234",)) - userDao.insert(User(id = 2, login = "Леонель Месси", password = "4321",)) + userDao.insert(User(id = 1, login = "Margen", password = "1234",)) + userDao.insert(User(id = 2, login = "Leonel Messi", password = "4321",)) val cardDao = database.cardDao() cardDao.insert( diff --git a/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt b/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt index dd3ff98..2ee9591 100644 --- a/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt +++ b/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt @@ -1,5 +1,6 @@ package com.example.myapplication.database.dao +import androidx.paging.PagingSource import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert @@ -12,13 +13,13 @@ import kotlinx.coroutines.flow.Flow @Dao interface CardDao { @Query("select * from cards") - fun getAll(): Flow> + fun getAll(): PagingSource @Query("select * from cards where cards.id = :id") - fun getById(id: Int): Card? + fun getById(id: Int): Flow @Query("select * from cards where cards.user_id = :userId") - fun getByUserId(userId: Int): Flow> + fun getByUserId(userId: Int): PagingSource @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(card: Card) diff --git a/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt b/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt index ea7fa1d..c518f94 100644 --- a/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt +++ b/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt @@ -19,7 +19,10 @@ interface UserDao { fun getAll(): Flow> @Query("select * from users where users.id = :id") - fun getById(id: Int): User? + fun getById(id: Int): Flow + + @Query("select * from users where users.login = :login") + suspend fun getByLogin(login: String): User? @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(user: User) @@ -30,6 +33,6 @@ interface UserDao { @Delete suspend fun delete(user: User) - @Query("select count(*) from cards where user_id = :userId") - fun getAdsCount(userId: Int): Int? + @Query("SELECT * FROM users WHERE login = :login AND password = :password") + fun getUserByLoginAndPassword(login: String, password: String): User? } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/repositories/CardRepository.kt b/app/src/main/java/com/example/myapplication/database/repositories/CardRepository.kt new file mode 100644 index 0000000..565bb9f --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/repositories/CardRepository.kt @@ -0,0 +1,19 @@ +package com.example.myapplication.database.repositories + +import androidx.paging.PagingData +import com.example.myapplication.database.entities.Card +import kotlinx.coroutines.flow.Flow + +interface CardRepository { + fun getAllCards(): Flow> + + fun getCardsByUserId(userId: Int): Flow> + + fun getCardById(id: Int): Flow + + suspend fun insertCard(card: Card) + + suspend fun updateCard(card: Card) + + suspend fun deleteCard(card: Card) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/repositories/OfflineCardRepository.kt b/app/src/main/java/com/example/myapplication/database/repositories/OfflineCardRepository.kt new file mode 100644 index 0000000..fa4ba14 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/repositories/OfflineCardRepository.kt @@ -0,0 +1,49 @@ +package com.example.myapplication.database.repositories + +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import com.example.myapplication.database.dao.CardDao +import com.example.myapplication.database.entities.Card +import kotlinx.coroutines.flow.Flow + +class OfflineCardRepository(private val cardDao: CardDao): CardRepository { + override fun getAllCards(): Flow> { + return Pager( + config = PagingConfig( + pageSize = 5, + prefetchDistance = 1, + enablePlaceholders = true, + initialLoadSize = 10, + maxSize = 15 + ), + pagingSourceFactory = { + cardDao.getAll() + } + ).flow + } + + override fun getCardsByUserId(UserId: Int):Flow> { + return Pager( + config = PagingConfig( + pageSize = 5, + prefetchDistance = 1, + enablePlaceholders = true, + initialLoadSize = 10, + maxSize = 15 + ), + pagingSourceFactory = { + cardDao.getByUserId(UserId) + } + ).flow + } + + override fun getCardById(id: Int): Flow = cardDao.getById(id) + + override suspend fun insertCard(card: Card) = cardDao.insert(card) + + override suspend fun updateCard(card: Card) = cardDao.update(card) + + override suspend fun deleteCard(card: Card) = cardDao.delete(card) + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/repositories/OfflineUserRepository.kt b/app/src/main/java/com/example/myapplication/database/repositories/OfflineUserRepository.kt new file mode 100644 index 0000000..0d8d3ee --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/repositories/OfflineUserRepository.kt @@ -0,0 +1,21 @@ +package com.example.myapplication.database.repositories + +import com.example.myapplication.database.dao.UserDao +import com.example.myapplication.database.entities.User +import kotlinx.coroutines.flow.Flow + +class OfflineUserRepository(private val userDao: UserDao): UserRepository { + override fun getAllUsers(): Flow> = userDao.getAll() + + override suspend fun getUserById(id: Int): Flow = 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) + + override suspend fun getUserByLoginAndPassword(login: String, password: String): User? = userDao.getUserByLoginAndPassword(login, password) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/repositories/UserRepository.kt b/app/src/main/java/com/example/myapplication/database/repositories/UserRepository.kt new file mode 100644 index 0000000..3a97f54 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/repositories/UserRepository.kt @@ -0,0 +1,22 @@ +package com.example.myapplication.database.repositories + +import androidx.room.Query +import com.example.myapplication.database.entities.User +import kotlinx.coroutines.flow.Flow + +interface UserRepository { + fun getAllUsers(): Flow> + + suspend fun getUserById(id: Int): Flow + + suspend fun getUserByLogin(login: String): User? + + suspend fun insertUser(user: User) + + suspend fun updateUser(user: User) + + suspend fun deleteUser(user: User) + + suspend fun getUserByLoginAndPassword(login: String, password: String): User? + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/viewmodels/CardViewModel.kt b/app/src/main/java/com/example/myapplication/database/viewmodels/CardViewModel.kt new file mode 100644 index 0000000..6360ce2 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/viewmodels/CardViewModel.kt @@ -0,0 +1,25 @@ +package com.example.myapplication.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import androidx.paging.PagingData +import androidx.paging.cachedIn +import com.example.myapplication.database.dao.CardDao +import com.example.myapplication.database.entities.Card +import com.example.myapplication.database.repositories.CardRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch + +class CardViewModel(private val cardRepository : CardRepository):ViewModel() { + val getAllCards: Flow> = cardRepository.getAllCards().cachedIn(viewModelScope) + + fun getCardById(id: Int): Flow = cardRepository.getCardById(id) + + fun getCardByUserId(userId: Int): Flow> = cardRepository.getCardsByUserId(userId).cachedIn(viewModelScope) + + fun insertCard(card: Card) = viewModelScope.launch { cardRepository.insertCard(card) } + + fun updateCard(card: Card) = viewModelScope.launch { cardRepository.updateCard(card) } + + fun deleteCard(card: Card) = viewModelScope.launch { cardRepository.deleteCard(card) } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/viewmodels/MobileAppViewModelProvider.kt b/app/src/main/java/com/example/myapplication/database/viewmodels/MobileAppViewModelProvider.kt new file mode 100644 index 0000000..83397cb --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/viewmodels/MobileAppViewModelProvider.kt @@ -0,0 +1,21 @@ +package com.example.myapplication.database.viewmodels + +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.CreationExtras +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import com.example.myapplication.MobileApp + +object MobileAppViewModelProvider { + val Factory = viewModelFactory { + initializer { + CardViewModel(app().container.cardRepository) + } + 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/myapplication/database/viewmodels/UserViewModel.kt b/app/src/main/java/com/example/myapplication/database/viewmodels/UserViewModel.kt new file mode 100644 index 0000000..3bafbc3 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/viewmodels/UserViewModel.kt @@ -0,0 +1,53 @@ +package com.example.myapplication.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.myapplication.GlobalUser +import com.example.myapplication.database.entities.User +import com.example.myapplication.database.repositories.UserRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking + +class UserViewModel(private val userRepository: UserRepository): ViewModel() { + val getAllUsers = userRepository.getAllUsers() + + suspend fun getUser(id: Int): Flow = userRepository.getUserById(id) + + fun updateUser(user: User) = viewModelScope.launch { + userRepository.updateUser(user) + } + + fun deleteUser(user: User) = viewModelScope.launch { + userRepository.deleteUser(user) + } + + suspend fun getUserByLogin(login: String): User? = userRepository.getUserByLogin(login) + + fun regUser(user: User) = viewModelScope.launch { + val globalUser = userRepository.getUserByLogin(user.login) + globalUser?.let { + return@launch + } ?: run { + if(user.password.isEmpty()){ + 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/myapplication/screens/authorization.kt b/app/src/main/java/com/example/myapplication/screens/authorization.kt index f220213..472278a 100644 --- a/app/src/main/java/com/example/myapplication/screens/authorization.kt +++ b/app/src/main/java/com/example/myapplication/screens/authorization.kt @@ -14,7 +14,9 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text 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 @@ -25,32 +27,33 @@ 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.NavController import androidx.navigation.NavHostController import com.example.myapplication.R +import com.example.myapplication.components.ActiveButton import com.example.myapplication.components.LoginField import com.example.myapplication.components.PasswordField +import com.example.myapplication.components.PasswordInputField +import com.example.myapplication.components.PlaceholderInputField +import com.example.myapplication.components.PlaceholderInputFieldAuth import com.example.myapplication.components.navButton import com.example.myapplication.database.MobileAppDataBase import com.example.myapplication.database.entities.Card import com.example.myapplication.database.entities.User +import com.example.myapplication.database.viewmodels.MobileAppViewModelProvider +import com.example.myapplication.database.viewmodels.UserViewModel +import com.example.myapplication.ui.theme.SkyBlue import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun Authorization(navController: NavHostController){ +fun Authorization(navController: NavHostController, + userViewModel: UserViewModel = viewModel( factory = MobileAppViewModelProvider.Factory )){ val context = LocalContext.current - val users = remember { mutableStateListOf() } - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - val database = MobileAppDataBase.getInstance(context) - database.userDao().getAll().collect { data -> - users.clear() - data.forEach { users.add(it) } - } - } - } + val users = userViewModel.getAllUsers.collectAsState(emptyList()).value + val login = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } Column ( modifier = Modifier @@ -73,11 +76,26 @@ fun Authorization(navController: NavHostController){ fontSize = 20.sp ) } - LoginField(text = "Логин") - PasswordField(text = "Пароль") - navButton(navController = navController, destination = "mainScreen", label = "Вход", - backgroundColor = Color.Cyan, textColor = Color.Black) + PlaceholderInputFieldAuth(label = "Логин", isSingleLine = true, onTextChanged = { newlogin -> + login.value = newlogin + }) + PasswordInputField(label = "Пароль", onPasswordChanged = { newpassword -> + password.value = newpassword + }) + + ActiveButton(label = "Вход", backgroundColor = SkyBlue, + textColor = Color.Black, onClickAction = { + if (login.value.isNotEmpty() && password.value.isNotEmpty()) { + userViewModel.authUser( + User( + login = login.value, + password = password.value, + ) + ) + navController.navigate("mainScreen") + } + }) navButton(navController = navController, destination = "registration", label = "Регистрация", - backgroundColor = Color.Cyan, textColor = Color.Black) + backgroundColor = SkyBlue, textColor = Color.Black) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/screens/editcard.kt b/app/src/main/java/com/example/myapplication/screens/editcard.kt index 149f697..6cbafe7 100644 --- a/app/src/main/java/com/example/myapplication/screens/editcard.kt +++ b/app/src/main/java/com/example/myapplication/screens/editcard.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import androidx.navigation.NavHostController import com.example.myapplication.R @@ -45,12 +46,16 @@ import com.example.myapplication.components.navBar import com.example.myapplication.components.navButton import com.example.myapplication.database.MobileAppDataBase import com.example.myapplication.database.entities.Card +import com.example.myapplication.database.viewmodels.CardViewModel +import com.example.myapplication.database.viewmodels.MobileAppViewModelProvider import com.example.myapplication.ui.theme.SkyBlue import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun EditCardScreen(navController: NavHostController, cardId: Int? = null) { +fun EditCardScreen(navController: NavHostController, + cardViewModel: CardViewModel = viewModel( factory = MobileAppViewModelProvider.Factory), + cardId: Int? = null) { val context = LocalContext.current val image = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.ferrari_laferrari_car2)) } @@ -76,15 +81,24 @@ fun EditCardScreen(navController: NavHostController, cardId: Int? = null) { } } - cardId?.let{ - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - val card = MobileAppDataBase.getInstance(context).cardDao().getById(cardId!!) - image.value = card!!.image - name.value = card!!.name - location.value = card!!.location - price.value = card!!.price - mileage.value = card!!.mileage + LaunchedEffect(Unit) { + cardId?.let { + cardViewModel.getCardById(cardId).collect { + if (it != null) { + image.value = it.image + } + if (it != null) { + name.value = it.name + } + if (it != null) { + location.value = it.location + } + if (it != null) { + mileage.value = it.mileage + } + if (it != null) { + price.value = it.price + } } } } diff --git a/app/src/main/java/com/example/myapplication/screens/mainScreen.kt b/app/src/main/java/com/example/myapplication/screens/mainScreen.kt index ede4d2f..9ea65af 100644 --- a/app/src/main/java/com/example/myapplication/screens/mainScreen.kt +++ b/app/src/main/java/com/example/myapplication/screens/mainScreen.kt @@ -37,6 +37,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog @@ -49,35 +51,48 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateListOf import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey +import com.example.myapplication.GlobalUser import com.example.myapplication.R import com.example.myapplication.database.MobileAppDataBase +import com.example.myapplication.database.viewmodels.CardViewModel +import com.example.myapplication.database.viewmodels.MobileAppViewModelProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @Composable -fun MainScreen(navController: NavHostController) { +fun MainScreen(navController: NavHostController, + cardViewModel: CardViewModel = viewModel(factory = MobileAppViewModelProvider.Factory)) { val context = LocalContext.current - val cards = remember { mutableStateListOf() } + val cards = cardViewModel.getAllCards.collectAsLazyPagingItems() + //val cards = cardViewModel.getCardByUserId(GlobalUser.getInstance().getUser()?.id!!).collectAsLazyPagingItems() - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - val database = MobileAppDataBase.getInstance(context) - database.cardDao().getAll().collect { data -> - cards.clear() - data.forEach { cards.add(it) } - } - } - } - Column { Box(modifier = Modifier .padding(horizontal = 10.dp) .fillMaxHeight(0.9f)) { Column() { - DataListScroll(navController, cards) + LazyColumn( + modifier = Modifier.weight(1f) + ) { + item { + addNewListItem(navController, "editcard") + } + items( + count = cards.itemCount, + key = cards.itemKey { item -> item.id!! } + ) { index: Int -> + val card: Card? = cards[index] + if (card != null) { + CardListItem(item = card, navController = navController) + } + } + } } } Column( diff --git a/app/src/main/java/com/example/myapplication/screens/registration.kt b/app/src/main/java/com/example/myapplication/screens/registration.kt index 2be06c7..a04c872 100644 --- a/app/src/main/java/com/example/myapplication/screens/registration.kt +++ b/app/src/main/java/com/example/myapplication/screens/registration.kt @@ -4,31 +4,61 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.Text 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.ModifierInfo import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import androidx.navigation.NavHostController +import com.example.myapplication.components.ActiveButton import com.example.myapplication.components.LoginField import com.example.myapplication.components.PasswordField +import com.example.myapplication.components.PasswordInputField +import com.example.myapplication.components.PlaceholderInputField +import com.example.myapplication.components.PlaceholderInputFieldAuth import com.example.myapplication.components.navButton +import com.example.myapplication.database.entities.User +import com.example.myapplication.database.viewmodels.MobileAppViewModelProvider +import com.example.myapplication.database.viewmodels.UserViewModel +import com.example.myapplication.ui.theme.SkyBlue @Composable -fun Registration(navController: NavHostController) { +fun Registration(navController: NavHostController, + userViewModel: UserViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory)) { + val login = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } + val repeatepassword = remember { mutableStateOf("") } + Column (modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Text(text = "Привет!", - fontSize = 20.sp, - fontWeight = FontWeight.Bold) - Text(text = "Зарегистрируйся, чтобы начать!", - fontSize = 20.sp, - fontWeight = FontWeight.Bold) - LoginField(text = "Логин") - PasswordField(text = "Пароль") - PasswordField(text = "Повторите пароль") - navButton(navController = navController, destination = "authorization", label = "Зарегистрироваться", backgroundColor = Color.Cyan, textColor = Color.Black) + PlaceholderInputFieldAuth(label = "Логин", isSingleLine = true, onTextChanged = {newlogin -> + login.value = newlogin + }) + PasswordInputField(label = "Пароль", onPasswordChanged = {newpassword -> + password.value = newpassword + }) + PasswordInputField(label = "Повторите пароль", onPasswordChanged = {newpassword -> + repeatepassword.value = newpassword + }) + ActiveButton(label = "Зарегистрироваться", backgroundColor = SkyBlue, + textColor = Color.Black, onClickAction = { + if (password.value == repeatepassword.value){ + userViewModel.regUser( + User( + login = login.value, + password = password.value, + ) + ) + } + navController.navigate("authorization") + }) + navButton(navController = navController, destination = "authorization", + label = "Назад", backgroundColor = SkyBlue, textColor = Color.Black) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/screens/user.kt b/app/src/main/java/com/example/myapplication/screens/user.kt index fa326e6..513ded3 100644 --- a/app/src/main/java/com/example/myapplication/screens/user.kt +++ b/app/src/main/java/com/example/myapplication/screens/user.kt @@ -19,37 +19,48 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue 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.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import androidx.navigation.NavHostController +import com.example.myapplication.GlobalUser +import com.example.myapplication.MobileApp import com.example.myapplication.R +import com.example.myapplication.components.ActiveButton import com.example.myapplication.components.LoginField +import com.example.myapplication.components.PlaceholderInputField import com.example.myapplication.components.navBar import com.example.myapplication.database.MobileAppDataBase +import com.example.myapplication.database.entities.Card import com.example.myapplication.database.entities.User +import com.example.myapplication.database.viewmodels.MobileAppViewModelProvider +import com.example.myapplication.database.viewmodels.UserViewModel import com.example.myapplication.ui.theme.SkyBlue import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun UserSettings(navController: NavHostController) { +fun UserSettings(navController: NavHostController, + userViewModel: UserViewModel = viewModel(factory = MobileAppViewModelProvider.Factory)) { val context = LocalContext.current - val login = remember { mutableStateOf("") } val password = remember { mutableStateOf("") } val adsCount = remember { mutableStateOf(0) } - val userId = 1 + val userId = GlobalUser.getInstance().getUser()?.id!! - userId?.let { - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - val user = MobileAppDataBase.getInstance(context).userDao().getById(userId!!) - login.value = user!!.login - password.value = user!!.password - adsCount.value = MobileAppDataBase.getInstance(context).userDao().getAdsCount(userId)?: 0 + LaunchedEffect(Unit) { + userId?.let { + userViewModel.getUser(userId).collect { + if (it != null) { + login.value = it.login + } + if (it != null) { + password.value = it.password + } } } } @@ -59,7 +70,7 @@ fun UserSettings(navController: NavHostController) { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally - ) { + ) { Image( painter = painterResource(id = R.drawable.user), contentDescription = "login", @@ -67,9 +78,17 @@ fun UserSettings(navController: NavHostController) { modifier = Modifier .size(300.dp) ) - LoginField(text = "Логин пользователя: ${login.value}") - LoginField(text = "Пароль пользователя: ${password.value}") - LoginField(text = "Количество объявлений пользователя: ${adsCount.value}") + PlaceholderInputField(label = "Логин пользователя: ${login.value}", isSingleLine = true, onTextChanged = {newlogin -> + login.value = newlogin}) + PlaceholderInputField(label = "Пароль пользователя: ${password.value}", isSingleLine = true, onTextChanged = {newpassword -> + password.value = newpassword}) + ActiveButton(label = "Сохранить изменения", backgroundColor = SkyBlue, textColor = Color.Black, onClickAction = + { + userViewModel.updateUser(User( + login = login.value, + password = password.value + )) + }) } } Column(modifier = Modifier