diff --git a/.idea/misc.xml b/.idea/misc.xml index 40c82cb..3d1e84f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,6 @@ - - + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c303088..b8d8988 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.PMULabs" + android:name=".NewsPortalApplication" tools:targetApi="31"> Unit,sharedViewModel: SharedViewModel) { - - val context = LocalContext.current - +fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: () -> Unit, articleItemViewModel: ArticleItemViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) { + val coroutineScope = rememberCoroutineScope() + articleItemViewModel.setTagList() //список тэгов - val tags = remember { mutableStateListOf() } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).tagDao().getAll().collect { data -> - tags.clear() - tags.addAll(data) - } - } - } + val tags = mutableStateOf>(articleItemViewModel.tagList) //количество комментариев для статьи - var countComm by rememberSaveable { mutableStateOf(0) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - countComm = article.id?.let { - NewsPortalDatabase.getInstance(context).commentDao().getCountComment( - it - ) - }?.toInt() ?: 0 - } + var countComm = remember{mutableStateOf(0)} + coroutineScope.launch { + countComm.value = articleItemViewModel.getCount(article.id) } //текущий пользователь - val argument = sharedViewModel.argument.value - var getUser by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).userDao() - .getUserById(argument.toString().toInt()).collect { data -> - getUser=data - } - } - } + var getUser by remember { mutableStateOf(currentUserViewModel.user) } //формат даты val formatter = SimpleDateFormat("dd.MM.YY") @@ -122,7 +96,7 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: //список названий тэгов var tagName="" var tagsNames= remember { mutableStateListOf() } - tags.forEach{teg -> + tags.value.forEach{teg -> if(article.tagId == teg.id){ tagName=teg.title } @@ -148,14 +122,6 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: else Icons.Filled.ArrowDropDown - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).tagDao().getTagById(tagId).collect { data -> - selectedText=data.title - } - } - } - //диалоговое окно if (openDialog) { AlertDialog( @@ -211,11 +177,10 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: DropdownMenuItem( text= {Text(text=label)}, onClick = { selectedText = label - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).tagDao().getTagByName(selectedText).collect{ tag -> - tagId=tag?.id.toString().toInt() - } - }} + coroutineScope.launch { + tagId= articleItemViewModel.getTagByName(selectedText).id!! + } + } ) } } @@ -282,8 +247,8 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: if(tagId!=null) { article.tagId = tagId } - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).articleDao().update(article) + coroutineScope.launch { + articleItemViewModel.updateArticle(article) } }, modifier = Modifier @@ -392,8 +357,8 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: y = 0.dp) .requiredHeight(30.dp) .clickable { - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).articleDao().delete(article) + coroutineScope.launch { + articleItemViewModel.deleteArticle(article) } }, imageVector = Icons.Filled.Close, @@ -441,7 +406,7 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: .requiredWidth(width = 25.dp) .requiredHeight(height = 22.dp)) Text( - text = "${countComm}", + text = "${countComm.value}", color = Color(0xff423a99), style = TextStyle( fontSize = 17.sp), diff --git a/app/src/main/java/com/example/pmulabs/designElem/items/CommentItem.kt b/app/src/main/java/com/example/pmulabs/designElem/items/CommentItem.kt index 14e98af..310d83b 100644 --- a/app/src/main/java/com/example/pmulabs/designElem/items/CommentItem.kt +++ b/app/src/main/java/com/example/pmulabs/designElem/items/CommentItem.kt @@ -1,5 +1,6 @@ package com.example.pmulabs.designElem.items +import android.annotation.SuppressLint import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -24,57 +25,44 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.example.pmulabs.room.database.NewsPortalDatabase +import androidx.lifecycle.viewmodel.compose.viewModel import com.example.pmulabs.room.models.Comment import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers +import com.example.pmulabs.viewModels.AppViewModelProvider +import com.example.pmulabs.viewModels.CommentItemViewModel +import com.example.pmulabs.viewModels.CurrentUserViewModel import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +@SuppressLint("CoroutineCreationDuringComposition", "UnrememberedMutableState") @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CommentItem(modifier: Modifier = Modifier,comm : Comment,sharedViewModel: SharedViewModel) { - val context = LocalContext.current - - var user by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).userDao() - .getUserById(comm.userId).collect { data -> - user=data - } - } - } - - val argument = sharedViewModel.argument.value - var getUser by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).userDao() - .getUserById(argument.toString().toInt()).collect { data -> - getUser=data - } - } - } +fun CommentItem(modifier: Modifier = Modifier, comm : Comment,commentItemViewModel: CommentItemViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) { + var getUser by remember { mutableStateOf(currentUserViewModel.user) } var openDialog by remember { mutableStateOf(false) } var text by remember { mutableStateOf(comm.text) } + val coroutineScope = rememberCoroutineScope() + commentItemViewModel.getUsersByArticle(comm.articleId) + var users by mutableStateOf(commentItemViewModel.userListByArticle) + var user by mutableStateOf(null) + for(item in users){ + if(comm.userId==item.id){ + user=item + } + } if (openDialog) { AlertDialog( @@ -131,8 +119,8 @@ fun CommentItem(modifier: Modifier = Modifier,comm : Comment,sharedViewModel: Sh onClick = { openDialog = false comm.text=text - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).commentDao().update(comm) + coroutineScope.launch { + commentItemViewModel.updateComment(comm) } }, modifier = Modifier @@ -169,7 +157,6 @@ fun CommentItem(modifier: Modifier = Modifier,comm : Comment,sharedViewModel: Sh fontWeight = FontWeight.Bold ), ) - if(getUser?.id==comm.userId) { Icon( modifier=Modifier @@ -185,8 +172,8 @@ fun CommentItem(modifier: Modifier = Modifier,comm : Comment,sharedViewModel: Sh modifier=Modifier .requiredHeight(20.dp) .clickable { - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).commentDao().delete(comm) + coroutineScope.launch { + commentItemViewModel.deleteComment(comm) } }, imageVector = Icons.Filled.Close, diff --git a/app/src/main/java/com/example/pmulabs/designElem/items/TagItem.kt b/app/src/main/java/com/example/pmulabs/designElem/items/TagItem.kt index 57201a7..7c383ef 100644 --- a/app/src/main/java/com/example/pmulabs/designElem/items/TagItem.kt +++ b/app/src/main/java/com/example/pmulabs/designElem/items/TagItem.kt @@ -26,49 +26,36 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle 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.lifecycle.viewmodel.compose.viewModel import com.example.pmulabs.R -import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Tag -import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers +import com.example.pmulabs.viewModels.AppViewModelProvider +import com.example.pmulabs.viewModels.CurrentUserViewModel +import com.example.pmulabs.viewModels.TagItemViewModel import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext @OptIn(ExperimentalMaterial3Api::class) @Composable -fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit,sharedViewModel: SharedViewModel) { - val context = LocalContext.current - - val argument = sharedViewModel.argument.value - var getUser by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).userDao() - .getUserById(argument.toString().toInt()).collect { data -> - getUser = data - } - } - } +fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit, viewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory), tagViewModel: TagItemViewModel =viewModel(factory = AppViewModelProvider.Factory)) { + var getUser by remember { mutableStateOf(viewModel.user) } var openDialog by remember { mutableStateOf(false) } var text by remember { mutableStateOf(teg.title) } + val coroutineScope = rememberCoroutineScope() if (openDialog) { AlertDialog( @@ -125,8 +112,8 @@ fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit,shar onClick = { openDialog = false teg.title = text - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).tagDao().update(teg) + coroutineScope.launch { + tagViewModel.updateTag(teg) } }, modifier = Modifier @@ -207,8 +194,8 @@ fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit,shar y = 9.dp ) .clickable { - CoroutineScope(Dispatchers.IO).launch { - NewsPortalDatabase.getInstance(context).tagDao().delete(teg) + coroutineScope.launch { + tagViewModel.deleteTag(teg) } }, imageVector = Icons.Filled.Close, @@ -217,4 +204,5 @@ fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit,shar ) } } -} \ No newline at end of file +} + diff --git a/app/src/main/java/com/example/pmulabs/graphs/AuthNavGraph.kt b/app/src/main/java/com/example/pmulabs/graphs/AuthNavGraph.kt index 76fe102..a2d3bf2 100644 --- a/app/src/main/java/com/example/pmulabs/graphs/AuthNavGraph.kt +++ b/app/src/main/java/com/example/pmulabs/graphs/AuthNavGraph.kt @@ -8,9 +8,9 @@ import androidx.navigation.navigation import com.example.pmulabs.screensMobile.authScreens.EntryScreen import com.example.pmulabs.screensMobile.authScreens.RegisterScreen import com.example.pmulabs.screensMobile.authScreens.SplashScreen -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.CurrentUserViewModel -fun NavGraphBuilder.authNavGraph(navController: NavHostController,sharedViewModel: SharedViewModel){ +fun NavGraphBuilder.authNavGraph(navController: NavHostController, currentUserViewModel: CurrentUserViewModel){ navigation( route=Graph.AUTHENTICATION, startDestination = AuthScreen.Splash.route @@ -19,10 +19,10 @@ fun NavGraphBuilder.authNavGraph(navController: NavHostController,sharedViewMode SplashScreen(navController = navController, Modifier) } composable(route=AuthScreen.Entry.route){ - EntryScreen(navController = navController, Modifier,sharedViewModel) + EntryScreen(navController = navController, Modifier,currentUserViewModel) } composable(route=AuthScreen.Register.route){ - RegisterScreen(navController = navController, Modifier,sharedViewModel) + RegisterScreen(navController = navController, Modifier,currentUserViewModel) } } } diff --git a/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt b/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt index bb0ca3f..e5375aa 100644 --- a/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt +++ b/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt @@ -2,6 +2,7 @@ package com.example.pmulabs.graphs import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost @@ -12,6 +13,7 @@ import com.example.pmulabs.basecomponents.navigate.BottomBarScreen import com.example.pmulabs.basecomponents.navigate.CALENDAR_ARGUMENT_DATE import com.example.pmulabs.basecomponents.navigate.SEARCHBYTAG_ARGUMENT_KEY import com.example.pmulabs.basecomponents.navigate.SEARCH_ARGUMENT_TEXT +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.screensMobile.ArticlePageScreen import com.example.pmulabs.screensMobile.CoopScreen import com.example.pmulabs.screensMobile.InfoScreen @@ -21,10 +23,10 @@ import com.example.pmulabs.screensMobile.TagsScreen import com.example.pmulabs.screensMobile.filterScreens.CalendarScreen import com.example.pmulabs.screensMobile.filterScreens.SearchByTagScreen import com.example.pmulabs.screensMobile.filterScreens.SearchScreen -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider @Composable -fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewModel){ +fun HomeNavGraph(navController: NavHostController, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ NavHost( navController = navController, route = Graph.MAIN, @@ -33,7 +35,7 @@ fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewMod composable( route=BottomBarScreen.Main.route ){ - MainScreen(navController,Modifier,sharedViewModel) + MainScreen(navController,Modifier,currentUserViewModel) } composable( route=BottomBarScreen.SearchByTag.route, @@ -41,7 +43,7 @@ fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewMod type= NavType.StringType }) ){ - SearchByTagScreen(navController,Modifier,sharedViewModel) + SearchByTagScreen(navController,Modifier,currentUserViewModel) } composable( route=BottomBarScreen.ArticlePage.route, @@ -49,7 +51,7 @@ fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewMod type= NavType.StringType }) ){ - ArticlePageScreen(navController,Modifier,sharedViewModel) + ArticlePageScreen(navController,Modifier,currentUserViewModel) } composable( route=BottomBarScreen.Search.route, @@ -57,7 +59,7 @@ fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewMod type= NavType.StringType }) ){ - SearchScreen(navController,Modifier,sharedViewModel) + SearchScreen(navController,Modifier,currentUserViewModel) } composable( route=BottomBarScreen.Calendar.route, @@ -65,10 +67,10 @@ fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewMod type= NavType.StringType }) ){ - CalendarScreen(navController,Modifier,sharedViewModel) + CalendarScreen(navController,Modifier,currentUserViewModel) } composable(route=BottomBarScreen.Profile.route){ - ProfileScreen(navController,Modifier,sharedViewModel) + ProfileScreen(navController,Modifier,currentUserViewModel) } composable(route=BottomBarScreen.Info.route){ InfoScreen(navController,Modifier) @@ -77,7 +79,7 @@ fun HomeNavGraph(navController: NavHostController,sharedViewModel: SharedViewMod CoopScreen(navController,Modifier) } composable(route=BottomBarScreen.Categories.route){ - TagsScreen(navController,Modifier,sharedViewModel) + TagsScreen(navController,Modifier,currentUserViewModel) } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt b/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt index 1c672a4..bc79c50 100644 --- a/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt +++ b/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt @@ -1,30 +1,32 @@ package com.example.pmulabs.graphs import androidx.compose.runtime.Composable +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.screensMobile.LoadScreen +import com.example.pmulabs.viewModels.AppViewModelProvider import com.example.pmulabs.viewModels.SearchViewModel -import com.example.pmulabs.viewModels.SharedViewModel const val USERID_ARGUMENT="userId" @Composable -fun RootNavigationGraph(navController: NavHostController, searchViewModel: SearchViewModel, sharedViewModel: SharedViewModel){ +fun RootNavigationGraph(navController: NavHostController, searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ NavHost( navController=navController, route = Graph.ROOT, startDestination = Graph.AUTHENTICATION ){ - authNavGraph(navController=navController,sharedViewModel) + authNavGraph(navController=navController,currentUserViewModel) composable(route=Graph.MAIN, arguments = listOf(navArgument(USERID_ARGUMENT){ type= NavType.StringType })){ - LoadScreen(searchViewModel = searchViewModel, sharedViewModel = sharedViewModel) + LoadScreen(searchViewModel = searchViewModel, currentUserViewModel = currentUserViewModel) } } } diff --git a/app/src/main/java/com/example/pmulabs/room/AppContainer.kt b/app/src/main/java/com/example/pmulabs/room/AppContainer.kt new file mode 100644 index 0000000..99bd426 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/AppContainer.kt @@ -0,0 +1,38 @@ +package com.example.pmulabs.room + +import android.content.Context +import com.example.pmulabs.room.database.NewsPortalDatabase +import com.example.pmulabs.room.repository.ArticleRepository +import com.example.pmulabs.room.repository.CommentRepository +import com.example.pmulabs.room.repository.OfflineArticleRepository +import com.example.pmulabs.room.repository.OfflineCommentRepository +import com.example.pmulabs.room.repository.OfflineTagRepository +import com.example.pmulabs.room.repository.OfflineUserRepository +import com.example.pmulabs.room.repository.TagRepository +import com.example.pmulabs.room.repository.UserRepository + +interface AppContainer { + val userRepository: UserRepository + val articleRepository: ArticleRepository + val tagRepository: TagRepository + val commentRepository: CommentRepository +} + +class AppDataContainer(private val context: Context) : AppContainer { + override val userRepository: UserRepository by lazy { + OfflineUserRepository(NewsPortalDatabase.getInstance(context).userDao()) + } + override val articleRepository: ArticleRepository by lazy { + OfflineArticleRepository(NewsPortalDatabase.getInstance(context).articleDao()) + } + override val tagRepository: TagRepository by lazy { + OfflineTagRepository(NewsPortalDatabase.getInstance(context).tagDao()) + } + override val commentRepository: CommentRepository by lazy { + OfflineCommentRepository(NewsPortalDatabase.getInstance(context).commentDao()) + } + + companion object { + const val TIMEOUT = 5000L + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/dao/ArticleDao.kt b/app/src/main/java/com/example/pmulabs/room/dao/ArticleDao.kt index c8cfd88..cb4e423 100644 --- a/app/src/main/java/com/example/pmulabs/room/dao/ArticleDao.kt +++ b/app/src/main/java/com/example/pmulabs/room/dao/ArticleDao.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.Flow @Dao interface ArticleDao { - @Query("select * from article ORDER BY publish_date ASC") + @Query("select * from article") fun getAll(): Flow> @Query("select * from article where article.id = :idArticle") diff --git a/app/src/main/java/com/example/pmulabs/room/dao/CommentDao.kt b/app/src/main/java/com/example/pmulabs/room/dao/CommentDao.kt index 6071ef7..cec1325 100644 --- a/app/src/main/java/com/example/pmulabs/room/dao/CommentDao.kt +++ b/app/src/main/java/com/example/pmulabs/room/dao/CommentDao.kt @@ -10,11 +10,11 @@ import kotlinx.coroutines.flow.Flow @Dao interface CommentDao { - @Query("select * from comment ORDER BY id DESC") + @Query("select * from comment") fun getAll(): Flow> @Query("select COUNT(*) from comment WHERE comment.text!='' AND comment.article_id= :idArticle") - fun getCountComment(idArticle : Int) : Int + fun getCountComment(idArticle : Int?) : Int @Insert suspend fun insert(comment: Comment) diff --git a/app/src/main/java/com/example/pmulabs/room/dao/UserDao.kt b/app/src/main/java/com/example/pmulabs/room/dao/UserDao.kt index 0be1a9c..72327a6 100644 --- a/app/src/main/java/com/example/pmulabs/room/dao/UserDao.kt +++ b/app/src/main/java/com/example/pmulabs/room/dao/UserDao.kt @@ -17,7 +17,7 @@ interface UserDao { fun getAll(): Flow> @Query("select * from user where user.id = :idUser") - fun getUserById(idUser: Int): Flow + fun getUserById(idUser: Int?): Flow @Query("select * from comment WHERE comment.text!='' AND comment.user_id= :idUser") fun getUserComms(idUser: Int): Flow> diff --git a/app/src/main/java/com/example/pmulabs/room/repository/ArticleRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/ArticleRepository.kt new file mode 100644 index 0000000..069b149 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/ArticleRepository.kt @@ -0,0 +1,12 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.models.Article +import kotlinx.coroutines.flow.Flow + +interface ArticleRepository { + suspend fun insertArticle(article: Article) + suspend fun updateArticle(article: Article) + suspend fun deleteArticle(article: Article) + fun getAllArticles(): Flow> + fun getArticleById(idArticle: Int): Flow
+} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/CommentRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/CommentRepository.kt new file mode 100644 index 0000000..1d64968 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/CommentRepository.kt @@ -0,0 +1,12 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.models.Comment +import kotlinx.coroutines.flow.Flow + +interface CommentRepository { + suspend fun insertComment(comment: Comment) + suspend fun updateComment(comment: Comment) + suspend fun deleteComment(comment: Comment) + fun getAllComments(): Flow> + fun getCountComment(idArticle : Int?) : Int +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/OfflineArticleRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/OfflineArticleRepository.kt new file mode 100644 index 0000000..f31837b --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/OfflineArticleRepository.kt @@ -0,0 +1,13 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.dao.ArticleDao +import com.example.pmulabs.room.models.Article +import kotlinx.coroutines.flow.Flow + +class OfflineArticleRepository(private val articleDao: ArticleDao) : ArticleRepository { + override suspend fun insertArticle(article: Article) = articleDao.insert(article) + override suspend fun updateArticle(article: Article) = articleDao.update(article) + override suspend fun deleteArticle(article: Article) = articleDao.delete(article) + override fun getAllArticles(): Flow> = articleDao.getAll() + override fun getArticleById(idArticle: Int): Flow
= articleDao.getArticleById(idArticle) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/OfflineCommentRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/OfflineCommentRepository.kt new file mode 100644 index 0000000..0da976c --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/OfflineCommentRepository.kt @@ -0,0 +1,13 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.dao.CommentDao +import com.example.pmulabs.room.models.Comment +import kotlinx.coroutines.flow.Flow + +class OfflineCommentRepository(private val commentDao: CommentDao) : CommentRepository { + override suspend fun insertComment(comment: Comment) = commentDao.insert(comment) + override suspend fun updateComment(comment: Comment) = commentDao.update(comment) + override suspend fun deleteComment(comment: Comment) = commentDao.delete(comment) + override fun getAllComments(): Flow> = commentDao.getAll() + override fun getCountComment(idArticle : Int?) : Int = commentDao.getCountComment(idArticle) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/OfflineTagRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/OfflineTagRepository.kt new file mode 100644 index 0000000..c8dbc12 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/OfflineTagRepository.kt @@ -0,0 +1,14 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.dao.TagDao +import com.example.pmulabs.room.models.Tag +import kotlinx.coroutines.flow.Flow + +class OfflineTagRepository(private val tagDao: TagDao) : TagRepository { + override suspend fun insertTag(tag: Tag) = tagDao.insert(tag) + override suspend fun updateTag(tag: Tag) = tagDao.update(tag) + override suspend fun deleteTag(tag: Tag) = tagDao.delete(tag) + override fun getAllTags(): Flow> = tagDao.getAll() + override fun getTagById(idTag: Int): Flow = tagDao.getTagById(idTag) + override fun getTagByName(nameTag: String): Flow = tagDao.getTagByName(nameTag) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt new file mode 100644 index 0000000..eaa82e5 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt @@ -0,0 +1,19 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.dao.UserDao +import com.example.pmulabs.room.models.Article +import com.example.pmulabs.room.models.Comment +import com.example.pmulabs.room.models.Tag +import com.example.pmulabs.room.models.User +import kotlinx.coroutines.flow.Flow + +class OfflineUserRepository(private val userDao: UserDao) : UserRepository { + 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 fun getAllUsers(): Flow> = userDao.getAll() + override fun getUserById(idUser: Int?): Flow = userDao.getUserById(idUser) + override fun getUserComms(idUser: Int): Flow> = userDao.getUserComms(idUser) + override fun getUserArticles(idUser: Int): Flow> = userDao.getUserArticles(idUser) + override fun getUserTags(idUser: Int): Flow> = userDao.getUserTags(idUser) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/TagRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/TagRepository.kt new file mode 100644 index 0000000..a98af68 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/TagRepository.kt @@ -0,0 +1,13 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.models.Tag +import kotlinx.coroutines.flow.Flow + +interface TagRepository { + suspend fun insertTag(tag: Tag) + suspend fun updateTag(tag: Tag) + suspend fun deleteTag(tag: Tag) + fun getAllTags(): Flow> + fun getTagById(idTag: Int): Flow + fun getTagByName(nameTag: String): Flow +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt new file mode 100644 index 0000000..a9c1e6e --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt @@ -0,0 +1,18 @@ +package com.example.pmulabs.room.repository + +import com.example.pmulabs.room.models.Article +import com.example.pmulabs.room.models.Comment +import com.example.pmulabs.room.models.Tag +import com.example.pmulabs.room.models.User +import kotlinx.coroutines.flow.Flow + +interface UserRepository { + suspend fun insertUser(user: User) + suspend fun updateUser(user: User) + suspend fun deleteUser(user: User) + fun getAllUsers(): Flow> + fun getUserById(idUser: Int?): Flow + fun getUserComms(idUser: Int): Flow> + fun getUserArticles(idUser: Int): Flow> + fun getUserTags(idUser: Int): Flow> +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/ArticlePageScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/ArticlePageScreen.kt index fd70875..7ac2833 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/ArticlePageScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/ArticlePageScreen.kt @@ -42,6 +42,7 @@ import androidx.compose.ui.text.TextStyle 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 com.example.pmulabs.basecomponents.navigate.ARTICLE_ARGUMENT_KEY import com.example.pmulabs.designElem.elem.BackButton @@ -51,7 +52,8 @@ import com.example.pmulabs.room.models.Article import com.example.pmulabs.room.models.Comment import com.example.pmulabs.room.models.Tag import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider +import com.example.pmulabs.viewModels.CurrentUserViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -61,8 +63,8 @@ import java.util.Date @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ArticlePageScreen(navController: NavController,modifier: Modifier = Modifier,sharedViewModel: SharedViewModel) { - val argument = sharedViewModel.argument.value +fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) { + val argument = currentUserViewModel.argument.value val context = LocalContext.current var id=navController.currentBackStackEntry?.arguments?.getString(ARTICLE_ARGUMENT_KEY).toString() @@ -260,7 +262,7 @@ fun ArticlePageScreen(navController: NavController,modifier: Modifier = Modifier modifier = Modifier .border(BorderStroke(3.dp, Color(0xff423a99))), color = Color(0xff423a99) ) - CommentItem(comm = comm, sharedViewModel = sharedViewModel) + CommentItem(comm = comm, currentUserViewModel = currentUserViewModel) } } diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt index af3ba77..b24bf7e 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color 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 androidx.navigation.compose.rememberNavController @@ -41,12 +42,13 @@ import com.example.pmulabs.basecomponents.navigate.BottomBarScreen import com.example.pmulabs.basecomponents.navigate.SearchAppBar import com.example.pmulabs.basecomponents.navigate.TopBar import com.example.pmulabs.designElem.items.ArticleItem +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.graphs.HomeNavGraph import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Article +import com.example.pmulabs.viewModels.AppViewModelProvider import com.example.pmulabs.viewModels.SearchViewModel import com.example.pmulabs.viewModels.SearchWidget -import com.example.pmulabs.viewModels.SharedViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.text.SimpleDateFormat @@ -54,7 +56,7 @@ import java.util.Calendar import java.util.Date @Composable -fun MainScreen(navController: NavController, modifier: Modifier = Modifier,sharedViewModel: SharedViewModel){ +fun MainScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ val context = LocalContext.current val articles = remember { mutableStateListOf
() } @@ -73,7 +75,7 @@ fun MainScreen(navController: NavController, modifier: Modifier = Modifier,share contentPadding = PaddingValues(top=75.dp, bottom = 70.dp, start = 10.dp,end=10.dp), verticalArrangement = Arrangement.spacedBy(15.dp)){ items(items = articles){ article -> - ArticleItem(article = article, sharedViewModel = sharedViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}) + ArticleItem(article = article, currentUserViewModel = currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}) } } } @@ -81,7 +83,7 @@ fun MainScreen(navController: NavController, modifier: Modifier = Modifier,share @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @OptIn(ExperimentalMaterial3Api::class) @Composable -fun LoadScreen(navController: NavHostController=rememberNavController(), searchViewModel: SearchViewModel, sharedViewModel: SharedViewModel){ +fun LoadScreen(navController: NavHostController=rememberNavController(), searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel){ val searchWidgetState by searchViewModel.searchWidgetState val searchTextState by searchViewModel.searchTextState @@ -244,7 +246,7 @@ fun LoadScreen(navController: NavHostController=rememberNavController(), searchV ) { Modifier .padding(it) - HomeNavGraph(navController = navController,sharedViewModel) + HomeNavGraph(navController = navController,currentUserViewModel) } } diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt index 5b9f7e8..dd02f90 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt @@ -60,6 +60,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.toSize +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.R import com.example.pmulabs.basecomponents.navigate.BottomBarScreen @@ -69,8 +70,8 @@ import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Article import com.example.pmulabs.room.models.Comment import com.example.pmulabs.room.models.Tag -import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider +import com.example.pmulabs.viewModels.CurrentUserViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -79,34 +80,20 @@ import java.util.Date @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,sharedViewModel: SharedViewModel) { - val argument = sharedViewModel.argument.value - +fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) { val context = LocalContext.current - + var getUser by remember { mutableStateOf(currentUserViewModel.user) } var openDialogUser by remember { mutableStateOf(false) } - var email by remember { mutableStateOf("") } - var password by remember { mutableStateOf("") } - var nickname by remember { mutableStateOf("") } + var email by remember { mutableStateOf(getUser?.email) } + var password by remember { mutableStateOf(getUser?.password) } + var nickname by remember { mutableStateOf(getUser?.nickname) } - var getUser by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).userDao() - .getUserById(argument.toString().toInt()).collect { data -> - getUser = data - email=data.email - password=data.password - nickname=data.nickname - } - } - } val getComms = remember { mutableStateListOf() } LaunchedEffect(Unit) { withContext(Dispatchers.IO) { NewsPortalDatabase.getInstance(context).userDao() - .getUserComms(argument.toString().toInt()).collect { data -> + .getUserComms(getUser?.id.toString().toInt()).collect { data -> getComms.clear() getComms.addAll(data) } @@ -117,7 +104,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,sh LaunchedEffect(Unit) { withContext(Dispatchers.IO) { NewsPortalDatabase.getInstance(context).userDao() - .getUserArticles(argument.toString().toInt()).collect { data -> + .getUserArticles(getUser?.id.toString().toInt()).collect { data -> getArticles.clear() getArticles.addAll(data) } @@ -128,7 +115,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,sh LaunchedEffect(Unit) { withContext(Dispatchers.IO) { NewsPortalDatabase.getInstance(context).userDao() - .getUserTags(argument.toString().toInt()).collect { data -> + .getUserTags(getUser?.id.toString().toInt()).collect { data -> getTags.clear() getTags.addAll(data) } @@ -332,49 +319,53 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,sh fontSize = 20.sp, ), ) - ValidateEmail(email, {email=it} ) - OutlinedTextField( - value = password, - onValueChange = { - password=it - }, - colors = TextFieldDefaults.textFieldColors( - containerColor = Color.White, - focusedIndicatorColor = Color(0xff423a99), - focusedLabelColor = Color(0xff423a99), - unfocusedIndicatorColor = Color(0xff423a99), - unfocusedLabelColor = Color(0xff423a99) - ), - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(10.dp), - label = { Text("Password") }, - placeholder = { Text("Write password...") }, - minLines = 1, - maxLines = 1, - ) - OutlinedTextField( - value = nickname, - onValueChange = { - nickname=it - }, - colors = TextFieldDefaults.textFieldColors( - containerColor = Color.White, - focusedIndicatorColor = Color(0xff423a99), - focusedLabelColor = Color(0xff423a99), - unfocusedIndicatorColor = Color(0xff423a99), - unfocusedLabelColor = Color(0xff423a99) - ), - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(10.dp), - label = { Text("Nickname") }, - placeholder = { Text("Write nickname...") }, - minLines = 1, - maxLines = 1, - ) + email?.let { ValidateEmail(it, {email=it} ) } + password?.let { + OutlinedTextField( + value = it, + onValueChange = { + password=it + }, + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.White, + focusedIndicatorColor = Color(0xff423a99), + focusedLabelColor = Color(0xff423a99), + unfocusedIndicatorColor = Color(0xff423a99), + unfocusedLabelColor = Color(0xff423a99) + ), + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(10.dp), + label = { Text("Password") }, + placeholder = { Text("Write password...") }, + minLines = 1, + maxLines = 1, + ) + } + nickname?.let { + OutlinedTextField( + value = it, + onValueChange = { + nickname=it + }, + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.White, + focusedIndicatorColor = Color(0xff423a99), + focusedLabelColor = Color(0xff423a99), + unfocusedIndicatorColor = Color(0xff423a99), + unfocusedLabelColor = Color(0xff423a99) + ), + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(10.dp), + label = { Text("Nickname") }, + placeholder = { Text("Write nickname...") }, + minLines = 1, + maxLines = 1, + ) + } Row( modifier = Modifier.padding(all = 8.dp), horizontalArrangement = Arrangement.Center @@ -388,10 +379,13 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,sh ), onClick = { openDialogUser = false - if(password.isNotEmpty() && email.isNotEmpty() && isValidEmail(email) && nickname.isNotEmpty()) { - getUser?.password=password - getUser?.email=email - getUser?.nickname=nickname + if(password?.isNotEmpty() == true && email?.isNotEmpty() == true && isValidEmail( + email!! + ) && nickname?.isNotEmpty() == true + ) { + getUser?.password= password as String + getUser?.email= email as String + getUser?.nickname= nickname as String CoroutineScope(Dispatchers.IO).launch { getUser?.let { NewsPortalDatabase.getInstance(context).userDao() diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/TagsScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/TagsScreen.kt index edd0670..aff38e3 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/TagsScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/TagsScreen.kt @@ -41,13 +41,14 @@ 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.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.basecomponents.navigate.BottomBarScreen import com.example.pmulabs.designElem.items.TagItem import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Tag -import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider +import com.example.pmulabs.viewModels.CurrentUserViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -55,7 +56,7 @@ import kotlinx.coroutines.withContext @OptIn(ExperimentalMaterial3Api::class) @Composable -fun TagsScreen(navController: NavController, modifier: Modifier = Modifier,sharedViewModel: SharedViewModel){ +fun TagsScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ val context = LocalContext.current val tags = remember { mutableStateListOf() } @@ -68,17 +69,7 @@ fun TagsScreen(navController: NavController, modifier: Modifier = Modifier,share } } - val argument = sharedViewModel.argument.value - - var getUser by remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - NewsPortalDatabase.getInstance(context).userDao() - .getUserById(argument.toString().toInt()).collect { data -> - getUser=data - } - } - } + var getUser by remember { mutableStateOf(currentUserViewModel.user) } var openDialog by remember { mutableStateOf(false) } var text by remember { mutableStateOf("") } @@ -198,7 +189,7 @@ fun TagsScreen(navController: NavController, modifier: Modifier = Modifier,share items(items = tags){ tag -> TagItem( teg = tag, - sharedViewModel = sharedViewModel, + viewModel = currentUserViewModel, onTagClick = {navController.navigate(BottomBarScreen.SearchByTag.passId(tag.id.toString()))} ) } diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/EntryScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/EntryScreen.kt index 7a21144..08b8815 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/EntryScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/EntryScreen.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.designElem.elem.ValidateEmail import com.example.pmulabs.designElem.elem.isValidEmail @@ -59,13 +60,14 @@ import com.example.pmulabs.graphs.AuthScreen import com.example.pmulabs.graphs.Graph import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider +import com.example.pmulabs.viewModels.CurrentUserViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @OptIn(ExperimentalMaterial3Api::class) @Composable -fun EntryScreen(navController: NavController,modifier: Modifier = Modifier, sharedViewModel: SharedViewModel) { +fun EntryScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) { var emailValue by rememberSaveable { mutableStateOf("") } var passwordValue by rememberSaveable { mutableStateOf("") } @@ -79,7 +81,7 @@ fun EntryScreen(navController: NavController,modifier: Modifier = Modifier, shar } } } - val argument = sharedViewModel.argument.value + val argument = currentUserViewModel.argument.value var passwordVisibility by rememberSaveable { mutableStateOf(false) } val emailRegex = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+".toRegex() @@ -205,7 +207,7 @@ fun EntryScreen(navController: NavController,modifier: Modifier = Modifier, shar if (passwordValue.isNotEmpty() && isValidEmail(emailValue)) { users.forEach { user -> if (user.password == passwordValue && user.email == emailValue) { - sharedViewModel.setArgument(user.id.toString()) + currentUserViewModel.setArgument(user.id.toString()) navController.navigate(route = Graph.passUserId(user.id.toString())) { } } diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/RegisterScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/RegisterScreen.kt index 4e3da71..7001bdb 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/RegisterScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/authScreens/RegisterScreen.kt @@ -50,9 +50,11 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.designElem.elem.ValidateEmail import com.example.pmulabs.designElem.elem.isValidEmail +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.designElem.statDesign.LeftCircles import com.example.pmulabs.designElem.statDesign.LogoMobile import com.example.pmulabs.designElem.statDesign.RightCircles @@ -60,7 +62,7 @@ import com.example.pmulabs.graphs.AuthScreen import com.example.pmulabs.graphs.Graph import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.User -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -68,7 +70,7 @@ import kotlinx.coroutines.withContext @OptIn(ExperimentalMaterial3Api::class) @Composable -fun RegisterScreen(navController: NavController,modifier: Modifier = Modifier,sharedViewModel: SharedViewModel) { +fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) { var emailValue by rememberSaveable { mutableStateOf("") } var passwordValue by rememberSaveable { mutableStateOf("") } @@ -242,7 +244,7 @@ fun RegisterScreen(navController: NavController,modifier: Modifier = Modifier,sh data.forEach { user -> if (user.password == passwordValue && user.email == emailValue) { withContext(Dispatchers.Main) { - sharedViewModel.setArgument(user.id.toString()) + currentUserViewModel.setArgument(user.id.toString()) navController.navigate( route = Graph.passUserId( user.id.toString() diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/CalendarScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/CalendarScreen.kt index 3a05625..ba3f514 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/CalendarScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/CalendarScreen.kt @@ -16,20 +16,22 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.basecomponents.navigate.BottomBarScreen import com.example.pmulabs.basecomponents.navigate.CALENDAR_ARGUMENT_DATE import com.example.pmulabs.designElem.elem.BackButton import com.example.pmulabs.designElem.items.ArticleItem +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Article -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.text.SimpleDateFormat @Composable -fun CalendarScreen(navController: NavController, modifier: Modifier = Modifier,sharedViewModel: SharedViewModel){ +fun CalendarScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ val context = LocalContext.current val articles = remember { mutableStateListOf
() } LaunchedEffect(Unit) { @@ -59,7 +61,7 @@ fun CalendarScreen(navController: NavController, modifier: Modifier = Modifier, if(publishDate==date) { ArticleItem( article = article, - sharedViewModel=sharedViewModel, + currentUserViewModel=currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))} ) } diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchByTagScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchByTagScreen.kt index f6a09d9..2f9cd4c 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchByTagScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchByTagScreen.kt @@ -16,19 +16,21 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.basecomponents.navigate.BottomBarScreen import com.example.pmulabs.basecomponents.navigate.SEARCHBYTAG_ARGUMENT_KEY import com.example.pmulabs.designElem.elem.BackButton import com.example.pmulabs.designElem.items.ArticleItem +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Article -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun SearchByTagScreen(navController: NavController, modifier: Modifier = Modifier,sharedViewModel: SharedViewModel){ +fun SearchByTagScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ val context = LocalContext.current val articles = remember { mutableStateListOf
() } LaunchedEffect(Unit) { @@ -53,7 +55,7 @@ fun SearchByTagScreen(navController: NavController, modifier: Modifier = Modifie } items(items = articles){ article -> if(article.tagId.toString()==id) { - ArticleItem(article = article, sharedViewModel = sharedViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}) + ArticleItem(article = article, currentUserViewModel = currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}) } } } diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchScreen.kt index 93e1335..5d6e47f 100644 --- a/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchScreen.kt +++ b/app/src/main/java/com/example/pmulabs/screensMobile/filterScreens/SearchScreen.kt @@ -16,19 +16,21 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.pmulabs.basecomponents.navigate.BottomBarScreen import com.example.pmulabs.basecomponents.navigate.SEARCH_ARGUMENT_TEXT import com.example.pmulabs.designElem.elem.BackButton import com.example.pmulabs.designElem.items.ArticleItem +import com.example.pmulabs.viewModels.CurrentUserViewModel import com.example.pmulabs.room.database.NewsPortalDatabase import com.example.pmulabs.room.models.Article -import com.example.pmulabs.viewModels.SharedViewModel +import com.example.pmulabs.viewModels.AppViewModelProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun SearchScreen(navController: NavController, modifier: Modifier = Modifier,sharedViewModel: SharedViewModel){ +fun SearchScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){ val context = LocalContext.current val articles = remember { mutableStateListOf
() } LaunchedEffect(Unit) { @@ -54,7 +56,7 @@ fun SearchScreen(navController: NavController, modifier: Modifier = Modifier,sha } items(items = articles){ article -> if(article.title.contains(text)) { - ArticleItem(article = article,sharedViewModel=sharedViewModel,onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}) + ArticleItem(article = article,currentUserViewModel=currentUserViewModel,onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}) } } } diff --git a/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt b/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt new file mode 100644 index 0000000..a70ce10 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt @@ -0,0 +1,27 @@ +package com.example.pmulabs.viewModels + +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.CreationExtras +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import com.example.pmulabs.NewsPortalApplication + +object AppViewModelProvider { + val Factory = viewModelFactory { + initializer { + CurrentUserViewModel(newsPortalApplication().container.userRepository) + } + initializer { + TagItemViewModel(newsPortalApplication().container.tagRepository) + } + initializer { + CommentItemViewModel(newsPortalApplication().container.userRepository,newsPortalApplication().container.commentRepository) + } + initializer { + ArticleItemViewModel(newsPortalApplication().container.tagRepository,newsPortalApplication().container.commentRepository,newsPortalApplication().container.articleRepository) + } + } +} + +fun CreationExtras.newsPortalApplication(): NewsPortalApplication = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as NewsPortalApplication) \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/viewModels/ArticleItemViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/ArticleItemViewModel.kt new file mode 100644 index 0000000..93d611e --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/viewModels/ArticleItemViewModel.kt @@ -0,0 +1,46 @@ +package com.example.pmulabs.viewModels + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.pmulabs.room.models.Article +import com.example.pmulabs.room.models.Tag +import com.example.pmulabs.room.repository.ArticleRepository +import com.example.pmulabs.room.repository.CommentRepository +import com.example.pmulabs.room.repository.TagRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class ArticleItemViewModel( + private val tagRepository: TagRepository, + private val commentRepository: CommentRepository, + private val articleRepository: ArticleRepository +) : ViewModel() { + var tagList by mutableStateOf>(emptyList()) + fun setTagList() { + viewModelScope.launch { + tagList=tagRepository.getAllTags().first() + } + } + + suspend fun updateArticle(article: Article) { + articleRepository.updateArticle(article) + } + + suspend fun deleteArticle(article: Article) { + articleRepository.deleteArticle(article) + } + + suspend fun getTagByName(name: String) : Tag { + return tagRepository.getTagByName(name).first() + } + + suspend fun getCount(articleId: Int?): Int = withContext(Dispatchers.IO) { + commentRepository.getCountComment(articleId) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/viewModels/CommentItemViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/CommentItemViewModel.kt new file mode 100644 index 0000000..20e6506 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/viewModels/CommentItemViewModel.kt @@ -0,0 +1,57 @@ +package com.example.pmulabs.viewModels + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.pmulabs.room.models.Comment +import com.example.pmulabs.room.models.User +import com.example.pmulabs.room.repository.CommentRepository +import com.example.pmulabs.room.repository.UserRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class CommentItemViewModel( + private val userRepository: UserRepository, + private val commentRepository: CommentRepository +) : ViewModel() { + suspend fun updateComment(comment: Comment) { + commentRepository.updateComment(comment) + } + + var commentList by mutableStateOf>>(commentRepository.getAllComments()) + var commListByArticle by mutableStateOf>(emptyList()) + var userListByArticle by mutableStateOf>(emptyList()) + + suspend fun getCount(articleId: Int): Int = withContext(Dispatchers.IO) { + commentRepository.getCountComment(articleId) + } + + fun getUsersByArticle(articleId: Int) { + viewModelScope.launch { + val count=getCount(articleId) + for(item in commentList.first()){ + if(item.articleId==articleId){ + commListByArticle+=item + } + if(commListByArticle.size>count){ + commListByArticle -= commListByArticle[commListByArticle.size-1] + } + } + for(item in commListByArticle){ + userListByArticle+=userRepository.getUserById(item.userId).first() + if(userListByArticle.size>count){ + userListByArticle -= userListByArticle[userListByArticle.size-1] + } + } + } + } + + suspend fun deleteComment(comment: Comment) { + commentRepository.deleteComment(comment) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/viewModels/CurrentUserViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/CurrentUserViewModel.kt new file mode 100644 index 0000000..2bedddf --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/viewModels/CurrentUserViewModel.kt @@ -0,0 +1,28 @@ +package com.example.pmulabs.viewModels + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.pmulabs.room.models.User +import com.example.pmulabs.room.repository.UserRepository +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch + +class CurrentUserViewModel(private val userRepository: UserRepository) : ViewModel(){ + val argument = mutableStateOf(null) + private val userid = mutableStateOf(null) + var user by mutableStateOf(null) + + fun setArgument(arg: String) { + argument.value = arg + userid.value = arg.toInt() + viewModelScope.launch { + user = userRepository.getUserById(userid.value) + .filterNotNull() + .first() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/viewModels/SharedViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/SharedViewModel.kt deleted file mode 100644 index 64f7ba1..0000000 --- a/app/src/main/java/com/example/pmulabs/viewModels/SharedViewModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.pmulabs.viewModels - -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel - -class SharedViewModel : ViewModel() { - val argument = mutableStateOf(null) - - fun setArgument(arg: String) { - argument.value = arg - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/pmulabs/viewModels/TagItemViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/TagItemViewModel.kt new file mode 100644 index 0000000..2c7fcd5 --- /dev/null +++ b/app/src/main/java/com/example/pmulabs/viewModels/TagItemViewModel.kt @@ -0,0 +1,17 @@ +package com.example.pmulabs.viewModels + +import androidx.lifecycle.ViewModel +import com.example.pmulabs.room.models.Tag +import com.example.pmulabs.room.repository.TagRepository + +class TagItemViewModel( + private val tagRepository: TagRepository +) : ViewModel() { + suspend fun updateTag(tag: Tag) { + tagRepository.updateTag(tag) + } + + suspend fun deleteTag(tag: Tag) { + tagRepository.deleteTag(tag) + } +} \ No newline at end of file