added repositories, partial transfer of business logic to ViewModel files.

This commit is contained in:
AnnZhimol 2023-11-21 15:43:03 +04:00
parent a2add02c8d
commit 41536e89d9
37 changed files with 544 additions and 270 deletions

3
.idea/misc.xml generated
View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -11,6 +11,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PMULabs"
android:name=".NewsPortalApplication"
tools:targetApi="31">
<activity
android:name=".MainActivity"

View File

@ -4,20 +4,22 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.rememberNavController
import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.graphs.RootNavigationGraph
import com.example.pmulabs.ui.theme.PMULabsTheme
import com.example.pmulabs.viewModels.AppViewModelProvider
import com.example.pmulabs.viewModels.SearchViewModel
import com.example.pmulabs.viewModels.SharedViewModel
class MainActivity : ComponentActivity() {
private val searchViewModel: SearchViewModel by viewModels()
private val sharedViewModel: SharedViewModel by viewModels()
private val currentUserViewModel: CurrentUserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PMULabsTheme {
RootNavigationGraph(navController = rememberNavController(),searchViewModel, sharedViewModel = sharedViewModel)
RootNavigationGraph(navController = rememberNavController(),searchViewModel, currentUserViewModel = viewModel(factory = AppViewModelProvider.Factory))
}
}
}

View File

@ -0,0 +1,14 @@
package com.example.pmulabs
import android.app.Application
import com.example.pmulabs.room.AppContainer
import com.example.pmulabs.room.AppDataContainer
class NewsPortalApplication : Application() {
lateinit var container: AppContainer
override fun onCreate() {
super.onCreate()
container = AppDataContainer(this)
}
}

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.designElem.items
import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
@ -39,12 +40,11 @@ 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.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -52,7 +52,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
@ -60,60 +59,35 @@ import androidx.compose.ui.text.font.FontWeight
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 com.example.pmulabs.R
import com.example.pmulabs.room.database.NewsPortalDatabase
import com.example.pmulabs.room.models.Article
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.ArticleItemViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat
@SuppressLint("UnrememberedMutableState", "CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: () -> 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<Tag>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).tagDao().getAll().collect { data ->
tags.clear()
tags.addAll(data)
}
}
}
val tags = mutableStateOf<List<Tag>>(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<Int?>(0)}
coroutineScope.launch {
countComm.value = articleItemViewModel.getCount(article.id)
}
//текущий пользователь
val argument = sharedViewModel.argument.value
var getUser by remember { mutableStateOf<User?>(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<String>() }
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),

View File

@ -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<User?>(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<User?>(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<User?>(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,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<List<Article>>
@Query("select * from article where article.id = :idArticle")

View File

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

View File

@ -17,7 +17,7 @@ interface UserDao {
fun getAll(): Flow<List<User>>
@Query("select * from user where user.id = :idUser")
fun getUserById(idUser: Int): Flow<User>
fun getUserById(idUser: Int?): Flow<User>
@Query("select * from comment WHERE comment.text!='' AND comment.user_id= :idUser")
fun getUserComms(idUser: Int): Flow<List<Comment>>

View File

@ -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<List<Article>>
fun getArticleById(idArticle: Int): Flow<Article>
}

View File

@ -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<List<Comment>>
fun getCountComment(idArticle : Int?) : Int
}

View File

@ -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<List<Article>> = articleDao.getAll()
override fun getArticleById(idArticle: Int): Flow<Article> = articleDao.getArticleById(idArticle)
}

View File

@ -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<List<Comment>> = commentDao.getAll()
override fun getCountComment(idArticle : Int?) : Int = commentDao.getCountComment(idArticle)
}

View File

@ -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<List<Tag>> = tagDao.getAll()
override fun getTagById(idTag: Int): Flow<Tag> = tagDao.getTagById(idTag)
override fun getTagByName(nameTag: String): Flow<Tag> = tagDao.getTagByName(nameTag)
}

View File

@ -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<List<User>> = userDao.getAll()
override fun getUserById(idUser: Int?): Flow<User> = userDao.getUserById(idUser)
override fun getUserComms(idUser: Int): Flow<List<Comment>> = userDao.getUserComms(idUser)
override fun getUserArticles(idUser: Int): Flow<List<Article>> = userDao.getUserArticles(idUser)
override fun getUserTags(idUser: Int): Flow<List<Tag>> = userDao.getUserTags(idUser)
}

View File

@ -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<List<Tag>>
fun getTagById(idTag: Int): Flow<Tag>
fun getTagByName(nameTag: String): Flow<Tag>
}

View File

@ -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<List<User>>
fun getUserById(idUser: Int?): Flow<User>
fun getUserComms(idUser: Int): Flow<List<Comment>>
fun getUserArticles(idUser: Int): Flow<List<Article>>
fun getUserTags(idUser: Int): Flow<List<Tag>>
}

View File

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

View File

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

View File

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

View File

@ -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<Tag>() }
@ -68,17 +69,7 @@ fun TagsScreen(navController: NavController, modifier: Modifier = Modifier,share
}
}
val argument = sharedViewModel.argument.value
var getUser by remember { mutableStateOf<User?>(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()))}
)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Flow<List<Comment>>>(commentRepository.getAllComments())
var commListByArticle by mutableStateOf<List<Comment>>(emptyList())
var userListByArticle by mutableStateOf<List<User>>(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)
}
}

View File

@ -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<String?>(null)
private val userid = mutableStateOf<Int?>(null)
var user by mutableStateOf<User?>(null)
fun setArgument(arg: String) {
argument.value = arg
userid.value = arg.toInt()
viewModelScope.launch {
user = userRepository.getUserById(userid.value)
.filterNotNull()
.first()
}
}
}

View File

@ -1,12 +0,0 @@
package com.example.pmulabs.viewModels
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class SharedViewModel : ViewModel() {
val argument = mutableStateOf<String?>(null)
fun setArgument(arg: String) {
argument.value = arg
}
}

View File

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