lab 4 complete(finally...)

This commit is contained in:
AnnZhimol 2023-11-23 19:40:59 +04:00
parent 41536e89d9
commit 5f4c36f00a
34 changed files with 936 additions and 658 deletions

View File

@ -1,3 +1,4 @@
plugins {
id("com.android.application")
id("com.google.devtools.ksp")
@ -39,6 +40,7 @@ android {
}
buildFeatures {
compose = true
viewBinding = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.5"
@ -81,4 +83,16 @@ dependencies {
ksp("androidx.room:room-compiler:$room_version")
implementation("androidx.room:room-ktx:$room_version")
implementation("androidx.room:room-paging:$room_version")
val paging_version = "3.1.1"
implementation ("androidx.paging:paging-runtime:$paging_version")
// alternatively - without Android dependencies for tests
testImplementation ("androidx.paging:paging-common:$paging_version")
// optional - RxJava2 support
implementation ("androidx.paging:paging-rxjava2:$paging_version")
// optional - RxJava3 support
implementation ("androidx.paging:paging-rxjava3:$paging_version")
// optional - Guava ListenableFuture support
implementation ("androidx.paging:paging-guava:$paging_version")
// optional - Jetpack Compose integration
implementation ("androidx.paging:paging-compose:1.0.0-alpha18")
}

View File

@ -60,7 +60,9 @@ 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
import com.example.pmulabs.room.models.Article
import com.example.pmulabs.room.models.Tag
import com.example.pmulabs.viewModels.AppViewModelProvider
@ -72,7 +74,7 @@ import java.text.SimpleDateFormat
@SuppressLint("UnrememberedMutableState", "CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick: () -> Unit, articleItemViewModel: ArticleItemViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
fun ArticleItem(navController: NavController,article: Article, modifier: Modifier = Modifier, onArticleClick: () -> Unit, articleItemViewModel: ArticleItemViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
val coroutineScope = rememberCoroutineScope()
articleItemViewModel.setTagList()
@ -360,6 +362,7 @@ fun ArticleItem(article: Article, modifier: Modifier = Modifier, onArticleClick:
coroutineScope.launch {
articleItemViewModel.deleteArticle(article)
}
navController.navigate(BottomBarScreen.Main.route)
},
imageVector = Icons.Filled.Close,
contentDescription = "Delete Icon",

View File

@ -39,6 +39,8 @@ import androidx.compose.ui.text.style.TextDecoration
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.room.models.Comment
import com.example.pmulabs.room.models.User
import com.example.pmulabs.viewModels.AppViewModelProvider
@ -49,7 +51,7 @@ import kotlinx.coroutines.launch
@SuppressLint("CoroutineCreationDuringComposition", "UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CommentItem(modifier: Modifier = Modifier, comm : Comment,commentItemViewModel: CommentItemViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
fun CommentItem(navController: NavController,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) }
@ -175,6 +177,7 @@ fun CommentItem(modifier: Modifier = Modifier, comm : Comment,commentItemViewMod
coroutineScope.launch {
commentItemViewModel.deleteComment(comm)
}
navController.navigate(BottomBarScreen.ArticlePage.passId(comm.articleId.toString()))
},
imageVector = Icons.Filled.Close,
contentDescription = "Delete Icon",

View File

@ -41,7 +41,9 @@ 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.R
import com.example.pmulabs.basecomponents.navigate.BottomBarScreen
import com.example.pmulabs.room.models.Tag
import com.example.pmulabs.viewModels.AppViewModelProvider
import com.example.pmulabs.viewModels.CurrentUserViewModel
@ -50,7 +52,7 @@ import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit, viewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory), tagViewModel: TagItemViewModel =viewModel(factory = AppViewModelProvider.Factory)) {
fun TagItem(navController: NavController,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) }
@ -197,6 +199,7 @@ fun TagItem(teg: Tag, modifier: Modifier = Modifier, onTagClick: () -> Unit, vie
coroutineScope.launch {
tagViewModel.deleteTag(teg)
}
navController.navigate(BottomBarScreen.Categories.route)
},
imageVector = Icons.Filled.Close,
contentDescription = "Delete Icon",

View File

@ -9,8 +9,10 @@ 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.CurrentUserViewModel
import com.example.pmulabs.viewModels.EntryScreenViewModel
import com.example.pmulabs.viewModels.RegisterScreenViewModel
fun NavGraphBuilder.authNavGraph(navController: NavHostController, currentUserViewModel: CurrentUserViewModel){
fun NavGraphBuilder.authNavGraph(navController: NavHostController,registerScreenViewModel: RegisterScreenViewModel,entryScreenViewModel: EntryScreenViewModel, currentUserViewModel: CurrentUserViewModel){
navigation(
route=Graph.AUTHENTICATION,
startDestination = AuthScreen.Splash.route
@ -19,10 +21,10 @@ fun NavGraphBuilder.authNavGraph(navController: NavHostController, currentUserVi
SplashScreen(navController = navController, Modifier)
}
composable(route=AuthScreen.Entry.route){
EntryScreen(navController = navController, Modifier,currentUserViewModel)
EntryScreen(navController = navController, Modifier,entryScreenViewModel,currentUserViewModel)
}
composable(route=AuthScreen.Register.route){
RegisterScreen(navController = navController, Modifier,currentUserViewModel)
RegisterScreen(navController = navController, Modifier,registerScreenViewModel,currentUserViewModel)
}
}
}

View File

@ -13,7 +13,6 @@ 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
@ -24,9 +23,13 @@ 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.AppViewModelProvider
import com.example.pmulabs.viewModels.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.viewModels.TagItemViewModel
@Composable
fun HomeNavGraph(navController: NavHostController, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
fun HomeNavGraph(navController: NavHostController,articlePageScreenViewModel: ArticlePageScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
NavHost(
navController = navController,
route = Graph.MAIN,
@ -35,7 +38,7 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
composable(
route=BottomBarScreen.Main.route
){
MainScreen(navController,Modifier,currentUserViewModel)
MainScreen(navController,Modifier,articleScreenViewModel,currentUserViewModel)
}
composable(
route=BottomBarScreen.SearchByTag.route,
@ -43,7 +46,7 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
type= NavType.StringType
})
){
SearchByTagScreen(navController,Modifier,currentUserViewModel)
SearchByTagScreen(navController,Modifier,articleScreenViewModel,currentUserViewModel)
}
composable(
route=BottomBarScreen.ArticlePage.route,
@ -51,7 +54,7 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
type= NavType.StringType
})
){
ArticlePageScreen(navController,Modifier,currentUserViewModel)
ArticlePageScreen(navController,Modifier,articlePageScreenViewModel,currentUserViewModel)
}
composable(
route=BottomBarScreen.Search.route,
@ -59,7 +62,7 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
type= NavType.StringType
})
){
SearchScreen(navController,Modifier,currentUserViewModel)
SearchScreen(navController,Modifier,articleScreenViewModel,currentUserViewModel)
}
composable(
route=BottomBarScreen.Calendar.route,
@ -67,10 +70,10 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
type= NavType.StringType
})
){
CalendarScreen(navController,Modifier,currentUserViewModel)
CalendarScreen(navController,articleScreenViewModel,Modifier,currentUserViewModel)
}
composable(route=BottomBarScreen.Profile.route){
ProfileScreen(navController,Modifier,currentUserViewModel)
ProfileScreen(navController,Modifier,articleScreenViewModel, tagItemViewModel, articlePageScreenViewModel,currentUserViewModel)
}
composable(route=BottomBarScreen.Info.route){
InfoScreen(navController,Modifier)
@ -79,7 +82,7 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
CoopScreen(navController,Modifier)
}
composable(route=BottomBarScreen.Categories.route){
TagsScreen(navController,Modifier,currentUserViewModel)
TagsScreen(navController,Modifier, tagItemViewModel, currentUserViewModel)
}
}
}

View File

@ -7,26 +7,31 @@ 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.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.viewModels.EntryScreenViewModel
import com.example.pmulabs.viewModels.RegisterScreenViewModel
import com.example.pmulabs.viewModels.SearchViewModel
import com.example.pmulabs.viewModels.TagItemViewModel
const val USERID_ARGUMENT="userId"
@Composable
fun RootNavigationGraph(navController: NavHostController, searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
fun RootNavigationGraph(navController: NavHostController, searchViewModel: SearchViewModel,articlePageScreenViewModel: ArticlePageScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), registerScreenViewModel: RegisterScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), entryScreenViewModel: EntryScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
NavHost(
navController=navController,
route = Graph.ROOT,
startDestination = Graph.AUTHENTICATION
){
authNavGraph(navController=navController,currentUserViewModel)
authNavGraph(navController=navController,registerScreenViewModel,entryScreenViewModel,currentUserViewModel)
composable(route=Graph.MAIN,
arguments = listOf(navArgument(USERID_ARGUMENT){
type= NavType.StringType
})){
LoadScreen(searchViewModel = searchViewModel, currentUserViewModel = currentUserViewModel)
LoadScreen(searchViewModel = searchViewModel, articleScreenViewModel = articleScreenViewModel, articlePageScreenViewModel = articlePageScreenViewModel, tagItemViewModel = tagItemViewModel,currentUserViewModel = currentUserViewModel)
}
}
}

View File

@ -16,6 +16,9 @@ interface ArticleDao {
@Query("select * from article where article.id = :idArticle")
fun getArticleById(idArticle: Int): Flow<Article>
@Query("SELECT * FROM article ORDER BY id DESC LIMIT :limit OFFSET :offset")
suspend fun getArticles(limit: Int, offset: Int): List<Article>
@Insert
suspend fun insert(article: Article)

View File

@ -16,6 +16,9 @@ interface CommentDao {
@Query("select COUNT(*) from comment WHERE comment.text!='' AND comment.article_id= :idArticle")
fun getCountComment(idArticle : Int?) : Int
@Query("SELECT * FROM comment ORDER BY id DESC LIMIT :limit OFFSET :offset")
suspend fun getComments(limit: Int, offset: Int): List<Comment>
@Insert
suspend fun insert(comment: Comment)

View File

@ -19,6 +19,9 @@ interface TagDao {
@Query("select * from tag where tag.title = :nameTag")
fun getTagByName(nameTag: String): Flow<Tag>
@Query("SELECT * FROM tag ORDER BY id ASC LIMIT :limit OFFSET :offset")
suspend fun getTags(limit: Int, offset: Int): List<Tag>
@Insert
suspend fun insert(tag: Tag)

View File

@ -0,0 +1,38 @@
package com.example.pmulabs.room.pagingSource
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.example.pmulabs.room.dao.ArticleDao
import com.example.pmulabs.room.models.Article
import kotlinx.coroutines.delay
class ArticlePagingSource(
private val dao: ArticleDao,
) : PagingSource<Int, Article>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Article> {
val page = params.key ?: 0
return try {
Log.d("MainPagingSource", "load: $page")
val entities = dao.getArticles(params.loadSize, page * params.loadSize)
if (page != 0) delay(1000)
LoadResult.Page(
data = entities,
prevKey = if (page == 0) null else page - 1,
nextKey = if (entities.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override val jumpingSupported: Boolean = true
override fun getRefreshKey(state: PagingState<Int, Article>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}

View File

@ -0,0 +1,38 @@
package com.example.pmulabs.room.pagingSource
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.example.pmulabs.room.dao.CommentDao
import com.example.pmulabs.room.models.Comment
import kotlinx.coroutines.delay
class CommentPagingSource(
private val dao: CommentDao,
) : PagingSource<Int, Comment>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Comment> {
val page = params.key ?: 0
return try {
Log.d("MainPagingSource", "load: $page")
val entities = dao.getComments(params.loadSize, page * params.loadSize)
if (page != 0) delay(1000)
LoadResult.Page(
data = entities,
prevKey = if (page == 0) null else page - 1,
nextKey = if (entities.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override val jumpingSupported: Boolean = true
override fun getRefreshKey(state: PagingState<Int, Comment>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}

View File

@ -0,0 +1,38 @@
package com.example.pmulabs.room.pagingSource
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.example.pmulabs.room.dao.TagDao
import com.example.pmulabs.room.models.Tag
import kotlinx.coroutines.delay
class TagPagingSource(
private val dao: TagDao,
) : PagingSource<Int, Tag>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Tag> {
val page = params.key ?: 0
return try {
Log.d("MainPagingSource", "load: $page")
val entities = dao.getTags(params.loadSize, page * params.loadSize)
if (page != 0) delay(1000)
LoadResult.Page(
data = entities,
prevKey = if (page == 0) null else page - 1,
nextKey = if (entities.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override val jumpingSupported: Boolean = true
override fun getRefreshKey(state: PagingState<Int, Tag>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.room.repository
import androidx.paging.PagingData
import com.example.pmulabs.room.models.Article
import kotlinx.coroutines.flow.Flow
@ -9,4 +10,5 @@ interface ArticleRepository {
suspend fun deleteArticle(article: Article)
fun getAllArticles(): Flow<List<Article>>
fun getArticleById(idArticle: Int): Flow<Article>
fun getArticles(): Flow<PagingData<Article>>
}

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.room.repository
import androidx.paging.PagingData
import com.example.pmulabs.room.models.Comment
import kotlinx.coroutines.flow.Flow
@ -9,4 +10,5 @@ interface CommentRepository {
suspend fun deleteComment(comment: Comment)
fun getAllComments(): Flow<List<Comment>>
fun getCountComment(idArticle : Int?) : Int
fun getComments(): Flow<PagingData<Comment>>
}

View File

@ -1,7 +1,11 @@
package com.example.pmulabs.room.repository
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.pmulabs.room.dao.ArticleDao
import com.example.pmulabs.room.models.Article
import com.example.pmulabs.room.pagingSource.ArticlePagingSource
import kotlinx.coroutines.flow.Flow
class OfflineArticleRepository(private val articleDao: ArticleDao) : ArticleRepository {
@ -10,4 +14,6 @@ class OfflineArticleRepository(private val articleDao: ArticleDao) : ArticleRepo
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)
override fun getArticles(): Flow<PagingData<Article>> = Pager(config = PagingConfig(pageSize = 4, jumpThreshold = 4, initialLoadSize = 4) ){ ArticlePagingSource(articleDao) }.flow
}

View File

@ -1,7 +1,11 @@
package com.example.pmulabs.room.repository
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.pmulabs.room.dao.CommentDao
import com.example.pmulabs.room.models.Comment
import com.example.pmulabs.room.pagingSource.CommentPagingSource
import kotlinx.coroutines.flow.Flow
class OfflineCommentRepository(private val commentDao: CommentDao) : CommentRepository {
@ -10,4 +14,6 @@ class OfflineCommentRepository(private val commentDao: CommentDao) : CommentRepo
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)
override fun getComments(): Flow<PagingData<Comment>> = Pager(config = PagingConfig(pageSize = 4, jumpThreshold = 4, initialLoadSize = 4) ){ CommentPagingSource(commentDao) }.flow
}

View File

@ -1,7 +1,11 @@
package com.example.pmulabs.room.repository
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.pmulabs.room.dao.TagDao
import com.example.pmulabs.room.models.Tag
import com.example.pmulabs.room.pagingSource.TagPagingSource
import kotlinx.coroutines.flow.Flow
class OfflineTagRepository(private val tagDao: TagDao) : TagRepository {
@ -11,4 +15,6 @@ class OfflineTagRepository(private val tagDao: TagDao) : TagRepository {
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)
override fun getTags(): Flow<PagingData<Tag>> = Pager(config = PagingConfig(pageSize = 4, jumpThreshold = 4, initialLoadSize = 4) ){ TagPagingSource(tagDao) }.flow
}

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.room.repository
import androidx.paging.PagingData
import com.example.pmulabs.room.models.Tag
import kotlinx.coroutines.flow.Flow
@ -10,4 +11,5 @@ interface TagRepository {
fun getAllTags(): Flow<List<Tag>>
fun getTagById(idTag: Int): Flow<Tag>
fun getTagByName(nameTag: String): Flow<Tag>
fun getTags(): Flow<PagingData<Tag>>
}

View File

@ -1,5 +1,7 @@
package com.example.pmulabs.screensMobile
import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@ -20,6 +22,7 @@ import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
@ -27,87 +30,68 @@ 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.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
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 androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.pmulabs.basecomponents.navigate.ARTICLE_ARGUMENT_KEY
import com.example.pmulabs.basecomponents.navigate.BottomBarScreen
import com.example.pmulabs.designElem.elem.BackButton
import com.example.pmulabs.designElem.items.CommentItem
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.AppViewModelProvider
import com.example.pmulabs.viewModels.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat
import java.util.Date
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
val argument = currentUserViewModel.argument.value
val context = LocalContext.current
fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifier,articlePageScreenViewModel: ArticlePageScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
var id=navController.currentBackStackEntry?.arguments?.getString(ARTICLE_ARGUMENT_KEY).toString()
var id =
navController.currentBackStackEntry?.arguments?.getString(ARTICLE_ARGUMENT_KEY).toString()
try {
articlePageScreenViewModel.getArticleById(id.toInt())
} catch (e: NumberFormatException) {
e.printStackTrace()
}
var textComm by rememberSaveable { mutableStateOf("") }
var article by remember { mutableStateOf<Article?>(null) }
var tag by remember { mutableStateOf<Tag?>(null) }
var tagId = 0
if (id.toString() != "null") {
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).articleDao().getArticleById(id.toInt()).collect { data ->
article=data
tagId=data.tagId
NewsPortalDatabase.getInstance(context).tagDao().getTagById(tagId).collect { data ->
tag=data
}
}
}
}
var article by mutableStateOf<Article?>(articlePageScreenViewModel.article)
try {
article?.tagId?.let { articlePageScreenViewModel.getTagById(it) }
} catch (e: Exception) {
e.printStackTrace()
}
var tag by mutableStateOf<Tag?>(articlePageScreenViewModel.tag)
Log.d("Tag:", tag.toString())
var tagId = articlePageScreenViewModel.tag?.id
val formatter = SimpleDateFormat("dd.MM.YY")
val publishDate = formatter.format(Date(article?.publishDate ?: 0))
val comms = remember { mutableStateListOf<Comment>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).commentDao().getAll().collect { data ->
comms.clear()
comms.addAll(data)
}
}
}
val comms = articlePageScreenViewModel.comments.collectAsLazyPagingItems()
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 coroutineScope = rememberCoroutineScope()
LazyColumn(
contentPadding = PaddingValues(top = 105.dp, bottom = 50.dp, start = 15.dp, end = 15.dp),
@ -116,11 +100,11 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
.requiredHeight(height = 915.dp)
.background(color = Color.White)
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(10.dp)
verticalArrangement = Arrangement.spacedBy(1.dp)
) {
item {
BackButton(modifier = Modifier
.clickable { navController.popBackStack()}
.clickable { navController.navigate(BottomBarScreen.Main.route) }
.offset(
y = 0.dp
))
@ -137,14 +121,18 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
Text(
text = "${publishDate}",
color = Color(0xff423a99),
style = MaterialTheme.typography.headlineMedium)
style = MaterialTheme.typography.headlineMedium
)
Text(
text = "#${tag?.title}",
color = Color(0xff423a99),
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier
.offset(x = 20.dp,
y = 0.dp))
.offset(
x = 20.dp,
y = 0.dp
)
)
}
}
item {
@ -153,11 +141,15 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
color = Color(0xff423a99),
style = TextStyle(
fontSize = 32.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.offset(x = 10.dp,
y = 0.dp)
.requiredWidth(width = 395.dp))
.offset(
x = 10.dp,
y = 0.dp
)
.requiredWidth(width = 395.dp)
)
}
item {
@ -166,9 +158,12 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
color = Color(0xff423a99),
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier
.offset(x = 5.dp,
y = 0.dp)
.requiredWidth(width = 375.dp))
.offset(
x = 5.dp,
y = 0.dp
)
.requiredWidth(width = 375.dp)
)
}
item {
Box(
@ -184,13 +179,17 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
color = Color(0xff423a99),
style = TextStyle(
fontSize = 32.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 15.dp,
y = 6.dp)
.offset(
x = 15.dp,
y = 6.dp
)
.requiredWidth(width = 395.dp)
.requiredHeight(height = 43.dp))
.requiredHeight(height = 43.dp)
)
HorizontalDivider(
thickness = 5.dp,
modifier = Modifier
@ -202,7 +201,8 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
.align(alignment = Alignment.TopStart)
.border(BorderStroke(3.dp, Color(0xff423a99)))
.offset(
y = 53.dp), color = Color(0xff423a99)
y = 53.dp
), color = Color(0xff423a99)
)
}
}
@ -239,10 +239,11 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
if (textComm.isNotEmpty()) {
var newComment =
Comment(null, textComm, getUser?.id.toString().toInt(), id.toInt())
CoroutineScope(Dispatchers.IO).launch {
NewsPortalDatabase.getInstance(context).commentDao().insert(newComment)
coroutineScope.launch {
articlePageScreenViewModel.insertComment(newComment)
}
textComm = ""
navController.navigate(BottomBarScreen.ArticlePage.passId(article?.id.toString()))
}
},
modifier = Modifier
@ -253,8 +254,10 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
Text(text = "Send", fontSize = 20.sp)
}
}
item{
comms.forEach{ comm ->
items(count = comms.itemCount) { index ->
val comm = comms[index]
if (comm != null) {
if (comm.articleId == article?.id && comm.text != "") {
Spacer(modifier = Modifier.padding(0.dp))
HorizontalDivider(
@ -262,10 +265,41 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
modifier = Modifier
.border(BorderStroke(3.dp, Color(0xff423a99))), color = Color(0xff423a99)
)
CommentItem(comm = comm, currentUserViewModel = currentUserViewModel)
CommentItem(navController,comm = comm, currentUserViewModel = currentUserViewModel)
}
}
}
comms.apply {
when {
loadState.refresh is LoadState.Loading -> {
item {
CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(),
color = Color(0xff423a99)
)
}
}
loadState.append is LoadState.Loading -> {
item {
CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(),
color = Color(0xff423a99)
)
}
}
loadState.refresh is LoadState.Error -> {
val err = comms.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = comms.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
}
}
}

View File

@ -8,9 +8,9 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerColors
import androidx.compose.material3.DatePickerDialog
@ -21,61 +21,70 @@ import androidx.compose.material3.TextButton
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.pmulabs.basecomponents.navigate.BottomBar
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.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.viewModels.SearchViewModel
import com.example.pmulabs.viewModels.SearchWidget
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.pmulabs.viewModels.TagItemViewModel
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
@Composable
fun MainScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val context = LocalContext.current
val articles = remember { mutableStateListOf<Article>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).articleDao().getAll().collect { data ->
articles.clear()
articles.addAll(data)
}
}
}
fun MainScreen(navController: NavController, modifier: Modifier = Modifier, articleScreenViewModel: ArticleScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val articles = articleScreenViewModel.articles.collectAsLazyPagingItems()
LazyColumn(
modifier=Modifier
.background(Color.White)
.fillMaxSize(),
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, currentUserViewModel = currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))})
items(count = articles.itemCount) { index ->
val article = articles[index]
if (article != null) {
ArticleItem(navController=navController,article = article, currentUserViewModel = currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))})
}
}
articles.apply {
when {
loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.refresh is LoadState.Error -> {
val err = articles.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = articles.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
}
}
@ -83,14 +92,14 @@ fun MainScreen(navController: NavController, modifier: Modifier = Modifier, curr
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoadScreen(navController: NavHostController=rememberNavController(), searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel){
fun LoadScreen(navController: NavHostController=rememberNavController(),articlePageScreenViewModel: ArticlePageScreenViewModel, tagItemViewModel: TagItemViewModel, articleScreenViewModel: ArticleScreenViewModel, searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel){
val searchWidgetState by searchViewModel.searchWidgetState
val searchTextState by searchViewModel.searchTextState
val formatter = SimpleDateFormat("dd-MMMM-YY")
val calendar = Calendar.getInstance()
calendar.set(2023, 0, 1) // add year, month (Jan), date
calendar.set(2023,10,23)
// set the initial date
val datePickerState = rememberDatePickerState(initialSelectedDateMillis = calendar.timeInMillis)
@ -133,7 +142,7 @@ fun LoadScreen(navController: NavHostController=rememberNavController(), searchV
selectedYearContentColor=Color.White,
subheadContentColor=Color(0xff423a99),
titleContentColor=Color(0xff423a99),
todayContentColor=Color.White,
todayContentColor=Color(0xff423a99),
todayDateBorderColor=Color(0xff423a99),
weekdayContentColor=Color(0xff423a99),
yearContentColor=Color(0xff423a99)
@ -212,7 +221,7 @@ fun LoadScreen(navController: NavHostController=rememberNavController(), searchV
selectedYearContentColor=Color.White,
subheadContentColor=Color(0xff423a99),
titleContentColor=Color(0xff423a99),
todayContentColor=Color.White,
todayContentColor=Color(0xff423a99),
todayDateBorderColor=Color(0xff423a99),
weekdayContentColor=Color(0xff423a99),
yearContentColor=Color(0xff423a99)
@ -246,7 +255,7 @@ fun LoadScreen(navController: NavHostController=rememberNavController(), searchV
) {
Modifier
.padding(it)
HomeNavGraph(navController = navController,currentUserViewModel)
HomeNavGraph(navController = navController,articlePageScreenViewModel, tagItemViewModel,articleScreenViewModel,currentUserViewModel)
}
}

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.screensMobile
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@ -21,7 +22,6 @@ import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
@ -30,6 +30,7 @@ import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
@ -39,11 +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.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -62,79 +63,44 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.toSize
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.pmulabs.R
import com.example.pmulabs.basecomponents.navigate.BottomBarScreen
import com.example.pmulabs.designElem.elem.ValidateEmail
import com.example.pmulabs.designElem.elem.isValidEmail
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.viewModels.AppViewModelProvider
import com.example.pmulabs.viewModels.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import com.example.pmulabs.viewModels.TagItemViewModel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Date
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory),tagItemViewModel: TagItemViewModel= viewModel(factory = AppViewModelProvider.Factory),articlePageScreenViewModel: ArticlePageScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), 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(getUser?.email) }
var password by remember { mutableStateOf(getUser?.password) }
var nickname by remember { mutableStateOf(getUser?.nickname) }
val getArticles = articleScreenViewModel.articles.collectAsLazyPagingItems()
val getComms = articlePageScreenViewModel.comments.collectAsLazyPagingItems()
val getTags = tagItemViewModel.tags.collectAsLazyPagingItems()
val coroutineScope = rememberCoroutineScope()
articlePageScreenViewModel.setTagList()
val getComms = remember { mutableStateListOf<Comment>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).userDao()
.getUserComms(getUser?.id.toString().toInt()).collect { data ->
getComms.clear()
getComms.addAll(data)
}
}
}
val tags = mutableStateOf<List<Tag>>(articlePageScreenViewModel.tagList)
val getArticles = remember { mutableStateListOf<Article>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).userDao()
.getUserArticles(getUser?.id.toString().toInt()).collect { data ->
getArticles.clear()
getArticles.addAll(data)
}
}
}
val getTags = remember { mutableStateListOf<Tag>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).userDao()
.getUserTags(getUser?.id.toString().toInt()).collect { data ->
getTags.clear()
getTags.addAll(data)
}
}
}
//список тэгов
val tags = remember { mutableStateListOf<Tag>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).tagDao().getAll().collect { data ->
tags.clear()
tags.addAll(data)
}
}
}
//список названий тэгов
var tagsNames = remember { mutableStateListOf<String>() }
tags.forEach{teg ->
tags.value.forEach { teg ->
if (!tagsNames.contains(teg.title)) {
tagsNames.add(teg.title)
}
@ -208,12 +174,13 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
suggestions.forEach { label ->
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()
onClick = {
selectedText = label
coroutineScope.launch {
tagId =
articlePageScreenViewModel.getTagByName(selectedText).id!!
}
}
}}
)
}
}
@ -278,9 +245,8 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
null, title, text,
Date().time, getUser?.id.toString().toInt(), tagId
)
CoroutineScope(Dispatchers.IO).launch {
NewsPortalDatabase.getInstance(context).articleDao()
.insert(newArticle)
coroutineScope.launch {
articlePageScreenViewModel.insertArticle(newArticle)
}
}
},
@ -386,10 +352,9 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
getUser?.password = password as String
getUser?.email = email as String
getUser?.nickname = nickname as String
CoroutineScope(Dispatchers.IO).launch {
coroutineScope.launch {
getUser?.let {
NewsPortalDatabase.getInstance(context).userDao()
.update(it)
articlePageScreenViewModel.updateUser(it)
}
}
}
@ -430,7 +395,8 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
contentDescription = "Ellipse 8",
modifier = Modifier
.requiredSize(size = 200.dp)
.clip(shape = CircleShape))
.clip(shape = CircleShape)
)
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
@ -446,18 +412,21 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xffdbdbf1)))
.background(color = Color(0xffdbdbf1))
)
Text(
text = "${getUser?.nickname}",
color = Color(0xff423a99),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
Box(
modifier = Modifier
@ -474,18 +443,21 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xffdbdbf1)))
.background(color = Color(0xffdbdbf1))
)
Text(
text = "${getUser?.email}",
color = Color(0xff423a99),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
Box(
modifier = Modifier
@ -502,14 +474,16 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xff423a99)))
.background(color = Color(0xff423a99))
)
Text(
text = "Add Article!",
color = Color(0xffdbdbf1),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
@ -531,14 +505,16 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xff423a99)))
.background(color = Color(0xff423a99))
)
Text(
text = "Edit my Data",
color = Color(0xffdbdbf1),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.requiredWidth(width = 200.dp)
.requiredHeight(height = 44.dp)
@ -588,11 +564,13 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
),
verticalArrangement = Arrangement.spacedBy(1.dp)
) {
if (!getComms.isEmpty()) {
items(items = getComms) { comment ->
if (getComms.itemCount != 0) {
items(count = getComms.itemCount) { index ->
val comment = getComms[index]
if (comment?.userId == getUser?.id) {
Spacer(modifier = Modifier.padding(5.dp))
Text(
text = "${comment.text}",
text = "${comment?.text}",
color = Color(0xff423a99),
style = TextStyle(
fontSize = 15.sp,
@ -603,7 +581,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.clickable {
navController.navigate(
BottomBarScreen.ArticlePage.passId(
comment.articleId.toString()
comment?.articleId.toString()
)
)
}
@ -612,11 +590,43 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
HorizontalDivider(
thickness = 3.dp,
modifier = Modifier
.border(BorderStroke(3.dp, Color(0xffdbdbf1))), color = Color(0xffdbdbf1)
.border(BorderStroke(3.dp, Color(0xffdbdbf1))),
color = Color(0xffdbdbf1)
)
}
}
else{
getComms.apply {
when {
loadState.refresh is LoadState.Loading -> {
item {
CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(),
color = Color(0xff423a99)
)
}
}
loadState.append is LoadState.Loading -> {
item {
CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(),
color = Color(0xff423a99)
)
}
}
loadState.refresh is LoadState.Error -> {
val err = getComms.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = getComms.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
} else {
item {
Text(
text = "Комментариев пока нет!",
@ -644,13 +654,15 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 393.dp)
.requiredHeight(height = 54.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xff423a99)))
.background(color = Color(0xff423a99))
)
Text(
text = "Comments:",
color = Color.White,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
@ -659,7 +671,8 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
)
.requiredWidth(width = 210.dp)
.requiredHeight(height = 54.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
}
@ -705,11 +718,13 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
),
verticalArrangement = Arrangement.spacedBy(1.dp)
) {
if (!getArticles.isEmpty()) {
items(items = getArticles) { article ->
if (getArticles.itemCount != 0) {
items(count = getArticles.itemCount) { index ->
val article = getArticles[index]
if (article?.userId == getUser?.id) {
Spacer(modifier = Modifier.padding(5.dp))
Text(
text = "${article.title}",
text = "${article?.title}",
color = Color(0xff423a99),
style = TextStyle(
fontSize = 15.sp,
@ -720,7 +735,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.clickable {
navController.navigate(
BottomBarScreen.ArticlePage.passId(
article.id.toString()
article?.id.toString()
)
)
}
@ -729,11 +744,43 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
HorizontalDivider(
thickness = 3.dp,
modifier = Modifier
.border(BorderStroke(3.dp, Color(0xffdbdbf1))), color = Color(0xffdbdbf1)
.border(BorderStroke(3.dp, Color(0xffdbdbf1))),
color = Color(0xffdbdbf1)
)
}
}
else{
getArticles.apply {
when {
loadState.refresh is LoadState.Loading -> {
item {
CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(),
color = Color(0xff423a99)
)
}
}
loadState.append is LoadState.Loading -> {
item {
CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(),
color = Color(0xff423a99)
)
}
}
loadState.refresh is LoadState.Error -> {
val err = getArticles.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = getArticles.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
} else {
item {
Text(
text = "Статей пока нет!",
@ -761,13 +808,15 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 393.dp)
.requiredHeight(height = 54.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xff423a99)))
.background(color = Color(0xff423a99))
)
Text(
text = "Articles:",
color = Color.White,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
@ -776,7 +825,8 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
)
.requiredWidth(width = 210.dp)
.requiredHeight(height = 54.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
}
@ -822,11 +872,13 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
),
verticalArrangement = Arrangement.spacedBy(1.dp)
) {
if (!getTags.isEmpty()) {
items(items = getTags) { tag ->
if (getTags.itemCount != 0) {
items(count = getTags.itemCount) { index ->
val tag = getTags[index]
if (tag?.userId == getUser?.id) {
Spacer(modifier = Modifier.padding(5.dp))
Text(
text = "${tag.title}",
text = "${tag?.title}",
color = Color(0xff423a99),
style = TextStyle(
fontSize = 15.sp,
@ -834,17 +886,24 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.clickable {navController.navigate(BottomBarScreen.SearchByTag.passId(tag.id.toString()))}
.clickable {
navController.navigate(
BottomBarScreen.SearchByTag.passId(
tag?.id.toString()
)
)
}
)
Spacer(modifier = Modifier.padding(5.dp))
HorizontalDivider(
thickness = 3.dp,
modifier = Modifier
.border(BorderStroke(3.dp, Color(0xffdbdbf1))), color = Color(0xffdbdbf1)
.border(BorderStroke(3.dp, Color(0xffdbdbf1))),
color = Color(0xffdbdbf1)
)
}
}
else{
} else {
item {
Text(
text = "Тэгов пока нет!",
@ -872,13 +931,15 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
.requiredWidth(width = 393.dp)
.requiredHeight(height = 54.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xff423a99)))
.background(color = Color(0xff423a99))
)
Text(
text = "Tags:",
color = Color.White,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold),
fontWeight = FontWeight.Bold
),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
@ -887,9 +948,11 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
)
.requiredWidth(width = 210.dp)
.requiredHeight(height = 54.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
}
}
}

View File

@ -16,26 +16,24 @@ import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
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.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.TextAlign
@ -43,34 +41,24 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
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.viewModels.AppViewModelProvider
import com.example.pmulabs.viewModels.CurrentUserViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import com.example.pmulabs.viewModels.TagItemViewModel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TagsScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
fun TagsScreen(navController: NavController, modifier: Modifier = Modifier, tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val context = LocalContext.current
val tags = remember { mutableStateListOf<Tag>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).tagDao().getAll().collect { data ->
tags.clear()
tags.addAll(data)
}
}
}
var tags = tagItemViewModel.tags.collectAsLazyPagingItems()
var getUser by remember { mutableStateOf(currentUserViewModel.user) }
val coroutineScope = rememberCoroutineScope()
var openDialog by remember { mutableStateOf(false) }
var text by remember { mutableStateOf("") }
@ -130,10 +118,10 @@ fun TagsScreen(navController: NavController, modifier: Modifier = Modifier, curr
openDialog = false
if(text.isNotEmpty()) {
val newTag = Tag(null, text, getUser?.id.toString().toInt())
CoroutineScope(Dispatchers.IO).launch {
NewsPortalDatabase.getInstance(context).tagDao()
.insert(newTag)
coroutineScope.launch {
tagItemViewModel.insertTag(newTag)
}
navController.navigate(BottomBarScreen.Categories.route)
}
},
modifier = Modifier
@ -186,12 +174,34 @@ fun TagsScreen(navController: NavController, modifier: Modifier = Modifier, curr
)
}
}
items(items = tags){ tag ->
items(count = tags.itemCount) { index ->
val tag = tags[index]
if (tag != null) {
TagItem(
navController=navController,
teg = tag,
viewModel = currentUserViewModel,
onTagClick = {navController.navigate(BottomBarScreen.SearchByTag.passId(tag.id.toString()))}
onTagClick = {navController.navigate(BottomBarScreen.SearchByTag.passId(tag?.id.toString()))}
)
}
}
tags.apply {
when {
loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.refresh is LoadState.Error -> {
val err = tags.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = tags.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
}
}

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.screensMobile.authScreens
import android.annotation.SuppressLint
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@ -28,11 +29,9 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@ -41,7 +40,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
@ -58,33 +56,24 @@ import com.example.pmulabs.designElem.statDesign.LogoMobile
import com.example.pmulabs.designElem.statDesign.RightCircles
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.AppViewModelProvider
import com.example.pmulabs.viewModels.CurrentUserViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.pmulabs.viewModels.EntryScreenViewModel
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EntryScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
fun EntryScreen(navController: NavController, modifier: Modifier = Modifier,entryScreenViewModel: EntryScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
var emailValue by rememberSaveable { mutableStateOf("") }
var passwordValue by rememberSaveable { mutableStateOf("") }
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).userDao().getAll().collect { data ->
users.clear()
users.addAll(data)
}
}
}
entryScreenViewModel.setUserList()
val users = mutableStateOf<List<User>>(entryScreenViewModel.userList)
val argument = currentUserViewModel.argument.value
var passwordVisibility by rememberSaveable { mutableStateOf(false) }
val emailRegex = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+".toRegex()
val coroutineScope = rememberCoroutineScope()
Box(
modifier = modifier
@ -205,7 +194,7 @@ fun EntryScreen(navController: NavController, modifier: Modifier = Modifier, cur
),
onClick = {
if (passwordValue.isNotEmpty() && isValidEmail(emailValue)) {
users.forEach { user ->
users.value.forEach { user ->
if (user.password == passwordValue && user.email == emailValue) {
currentUserViewModel.setArgument(user.id.toString())
navController.navigate(route = Graph.passUserId(user.id.toString())) {

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.screensMobile.authScreens
import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@ -29,11 +30,9 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@ -42,7 +41,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
@ -54,36 +52,31 @@ 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
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.AppViewModelProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.viewModels.RegisterScreenViewModel
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier,registerScreenViewModel: RegisterScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
var emailValue by rememberSaveable { mutableStateOf("") }
var passwordValue by rememberSaveable { mutableStateOf("") }
var nicknameValue by rememberSaveable { mutableStateOf("") }
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).userDao().getAll().collect { data ->
users.clear()
users.addAll(data)
}
}
val coroutineScope = rememberCoroutineScope()
registerScreenViewModel.setUserList()
var users = mutableStateOf<List<User>>(emptyList())
registerScreenViewModel.users.observeForever { userList ->
users.value = userList
}
var passwordVisibility by rememberSaveable { mutableStateOf(false) }
@ -228,29 +221,29 @@ fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier,
onClick = {
var isExist = false;
if (passwordValue.isNotEmpty() && isValidEmail(emailValue) && nicknameValue.isNotEmpty()) {
users.forEach { user ->
users.value.forEach { user ->
if (user.email == emailValue || user.nickname == nicknameValue) {
Log.d("User already exist. User id: ", user.id.toString())
isExist = true
}
}
if (!isExist) {
var newUser = User(null, nicknameValue, emailValue, passwordValue, "user")
CoroutineScope(Dispatchers.IO).launch {
NewsPortalDatabase.getInstance(context).userDao().insert(newUser)
NewsPortalDatabase.getInstance(context).userDao().getAll()
.collect { data ->
data.forEach { user ->
if (user.password == passwordValue && user.email == emailValue) {
withContext(Dispatchers.Main) {
currentUserViewModel.setArgument(user.id.toString())
navController.navigate(
route = Graph.passUserId(
user.id.toString()
)
)
val newUser = User(null, nicknameValue, emailValue, passwordValue, "user")
coroutineScope.launch {
val insertResult = async {
registerScreenViewModel.insertUser(newUser)
}
insertResult.await()
registerScreenViewModel.setUserList()
registerScreenViewModel.users.observeForever { userList ->
users.value = userList
Log.println(Log.ASSERT, "UsersList", users.value.toString())
users.value?.forEach { user ->
if (user.password == passwordValue && user.email == emailValue) {
currentUserViewModel.setArgument(user.id.toString())
navController.navigate(route = Graph.passUserId(user.id.toString()))
}
}
}
@ -288,195 +281,9 @@ fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier,
}
)
Spacer(modifier = Modifier.padding(20.dp))
}
}
}
}
}
/*
@Composable
fun RegisterScreen(navController: NavController,modifier: Modifier = Modifier) {
Box(
modifier = modifier
.requiredWidth(width = 412.dp)
.requiredHeight(height = 915.dp)
.background(color = Color.White)
) {
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = (-17).dp,
y = 329.dp
)
.requiredWidth(width = 436.dp)
.requiredHeight(height = 325.dp)
) {
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 69.1444091796875.dp,
y = 122.9124755859375.dp
)
.requiredWidth(width = 308.dp)
.requiredHeight(height = 61.dp)
) {
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 69.1444091796875.dp,
y = 193.824951171875.dp
)
.requiredWidth(width = 308.dp)
.requiredHeight(height = 61.dp)
) {
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 68.dp,
y = 52.dp
)
.requiredWidth(width = 308.dp)
.requiredHeight(height = 61.dp)
) {
}
Text(
textAlign = TextAlign.Center,
text = buildAnnotatedString {
withStyle(style = SpanStyle(
color = Color(0xff7d7dbd),
fontSize = 20.sp)) {append("Please, ")}
withStyle(style = SpanStyle(
color = Color(0xff7d7dbd),
fontSize = 20.sp,
fontWeight = FontWeight.Bold)) {append("Sign Up")}},
modifier = Modifier
.fillMaxSize())
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 128.dp,
y = 730.dp
)
.requiredWidth(width = 381.dp)
.requiredHeight(height = 268.dp)
.rotate(degrees = 8.33f)
) {
RightCircles()
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = (-111.28436279296875).dp,
y = (-96.86965942382812).dp
)
.requiredWidth(width = 250.dp)
.requiredHeight(height = 290.dp)
) {
Box(
modifier = Modifier
.rotate(degrees = 12.96f)
) {
LeftCircles()
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 140.35101318359375.dp,
y = 152.06341552734375.dp
)
.requiredWidth(width = 66.dp)
.requiredHeight(height = 27.dp)
) {
BackButton(modifier=Modifier
.clickable { navController.navigate(route = AuthScreen.Entry.route){
popUpTo(AuthScreen.Splash.route)
} })}
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 50.dp,
y = 681.dp
)
.requiredWidth(width = 308.dp)
.requiredHeight(height = 127.dp)
) {
Text(
text = "Do you have an account? ",
color = Color(0xff7d7dbd),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 20.sp),
modifier = Modifier
.fillMaxSize()
.offset(
x = 0.dp,
y = 75.dp
))
Text(
text = "Sign In",
color = Color(0xff7d7dbd),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 20.sp,
fontWeight = FontWeight.Bold),
modifier = Modifier
.fillMaxSize()
.offset(
x = 0.dp,
y = 95.dp
)
.clickable { navController.navigate(route = AuthScreen.Entry.route)
{
popUpTo(AuthScreen.Splash.route)
}})
Box(
modifier = Modifier
.requiredWidth(width = 308.dp)
.requiredHeight(height = 82.dp)
) {
ButtonCustom(name = "Sign Up",modifier = Modifier
.fillMaxSize()
.clickable { navController.navigate(route = Graph.MAIN){
popUpTo(Graph.MAIN)
} }
)
}
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 57.dp,
y = 165.dp
)
.requiredWidth(width = 302.dp)
.requiredHeight(height = 140.dp)
) {
LogoMobile(modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 9.dp
)
.fillMaxWidth()
.requiredHeight(height = 131.dp))
}
}
}*/

View File

@ -1,5 +1,6 @@
package com.example.pmulabs.screensMobile.filterScreens
import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@ -7,41 +8,29 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
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 androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
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.AppViewModelProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import java.text.SimpleDateFormat
@SuppressLint("UnrememberedMutableState")
@Composable
fun CalendarScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val context = LocalContext.current
val articles = remember { mutableStateListOf<Article>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).articleDao().getAll().collect { data ->
articles.clear()
articles.addAll(data)
}
}
}
fun CalendarScreen(navController: NavController, articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val articles = articleScreenViewModel.articles.collectAsLazyPagingItems()
var date=navController.currentBackStackEntry?.arguments?.getString(CALENDAR_ARGUMENT_DATE).toString()
Log.d("date: ",date)
val formatter = SimpleDateFormat("dd-MMMM-YY")
@ -56,15 +45,44 @@ fun CalendarScreen(navController: NavController, modifier: Modifier = Modifier,
BackButton(modifier=Modifier
.clickable { navController.popBackStack()})
}
items(items = articles){ article ->
val publishDate=formatter.format(article.publishDate)
items(count = articles.itemCount) { index ->
val article = articles[index]
val publishDate=formatter.format(article?.publishDate)
if(publishDate==date) {
if (article != null) {
ArticleItem(
navController=navController,
article = article,
currentUserViewModel = currentUserViewModel,
onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}
onArticleClick = {
navController.navigate(
BottomBarScreen.ArticlePage.passId(
article?.id.toString()
)
)
}
)
}
}
}
articles.apply {
when {
loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.refresh is LoadState.Error -> {
val err = articles.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = articles.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
}
}

View File

@ -7,40 +7,28 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
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 androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
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.AppViewModelProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
@Composable
fun SearchByTagScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val context = LocalContext.current
val articles = remember { mutableStateListOf<Article>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).articleDao().getAll().collect { data ->
articles.clear()
articles.addAll(data)
}
}
}
fun SearchByTagScreen(navController: NavController, modifier: Modifier = Modifier, articleScreenViewModel: ArticleScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val articles = articleScreenViewModel.articles.collectAsLazyPagingItems()
var id=navController.currentBackStackEntry?.arguments?.getString(SEARCHBYTAG_ARGUMENT_KEY).toString()
Log.d("id: ",id)
@ -53,9 +41,30 @@ fun SearchByTagScreen(navController: NavController, modifier: Modifier = Modifie
BackButton(modifier=Modifier
.clickable { navController.popBackStack()})
}
items(items = articles){ article ->
if(article.tagId.toString()==id) {
ArticleItem(article = article, currentUserViewModel = currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))})
items(count = articles.itemCount) { index ->
val article = articles[index]
if(article?.tagId.toString()==id) {
if (article != null) {
ArticleItem(navController=navController,article = article, currentUserViewModel = currentUserViewModel, onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))})
}
}
}
articles.apply {
when {
loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.refresh is LoadState.Error -> {
val err = articles.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = articles.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
}

View File

@ -7,40 +7,27 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
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 androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
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.AppViewModelProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
@Composable
fun SearchScreen(navController: NavController, modifier: Modifier = Modifier, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val context = LocalContext.current
val articles = remember { mutableStateListOf<Article>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
NewsPortalDatabase.getInstance(context).articleDao().getAll().collect { data ->
articles.clear()
articles.addAll(data)
}
}
}
fun SearchScreen(navController: NavController, modifier: Modifier = Modifier, articleScreenViewModel: ArticleScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val articles = articleScreenViewModel.articles.collectAsLazyPagingItems()
var text=navController.currentBackStackEntry?.arguments?.getString(SEARCH_ARGUMENT_TEXT).toString()
Log.d("text: ",text)
@ -54,9 +41,30 @@ fun SearchScreen(navController: NavController, modifier: Modifier = Modifier, cu
BackButton(modifier=Modifier
.clickable { navController.popBackStack()})
}
items(items = articles){ article ->
if(article.title.contains(text)) {
ArticleItem(article = article,currentUserViewModel=currentUserViewModel,onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))})
items(count = articles.itemCount) { index ->
val article = articles[index]
if(article?.title?.contains(text)==true) {
if (article != null) {
ArticleItem(navController=navController,article = article,currentUserViewModel=currentUserViewModel,onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))})
}
}
}
articles.apply {
when {
loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator(modifier = Modifier.fillParentMaxSize(), color = Color(0xff423a99)) }
}
loadState.refresh is LoadState.Error -> {
val err = articles.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) }
}
loadState.append is LoadState.Error -> {
val err = articles.loadState.append as LoadState.Error
item { Text(err.error.localizedMessage) }
}
}
}
}

View File

@ -20,6 +20,18 @@ object AppViewModelProvider {
initializer {
ArticleItemViewModel(newsPortalApplication().container.tagRepository,newsPortalApplication().container.commentRepository,newsPortalApplication().container.articleRepository)
}
initializer {
EntryScreenViewModel(newsPortalApplication().container.userRepository)
}
initializer {
RegisterScreenViewModel(newsPortalApplication().container.userRepository)
}
initializer {
ArticleScreenViewModel(newsPortalApplication().container.articleRepository)
}
initializer {
ArticlePageScreenViewModel(newsPortalApplication().container.tagRepository,newsPortalApplication().container.commentRepository,newsPortalApplication().container.articleRepository,newsPortalApplication().container.userRepository)
}
}
}

View File

@ -0,0 +1,74 @@
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 androidx.paging.PagingData
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.room.repository.ArticleRepository
import com.example.pmulabs.room.repository.CommentRepository
import com.example.pmulabs.room.repository.TagRepository
import com.example.pmulabs.room.repository.UserRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class ArticlePageScreenViewModel(
private val tagRepository: TagRepository,
private val commentRepository: CommentRepository,
private val articleRepository: ArticleRepository,
private val userRepository: UserRepository
) : ViewModel() {
private val articleid = mutableStateOf<Int?>(null)
private val tagid = mutableStateOf<Int?>(null)
var article by mutableStateOf<Article?>(null)
var tag by mutableStateOf<Tag?>(null)
val comments: Flow<PagingData<Comment>> = commentRepository.getComments()
fun getArticleById(articleId:Int) {
articleid.value = articleId
viewModelScope.launch {
article = articleRepository.getArticleById(articleid.value!!)
.filterNotNull()
.first()
}
}
var tagList by mutableStateOf<List<Tag>>(emptyList())
fun setTagList() {
viewModelScope.launch {
tagList=tagRepository.getAllTags().first()
}
}
suspend fun insertComment(comment: Comment) {
commentRepository.insertComment(comment)
}
suspend fun updateUser(user: User) {
userRepository.updateUser(user)
}
suspend fun insertArticle(article: Article) {
articleRepository.insertArticle(article)
}
suspend fun getTagByName(name: String) : Tag {
return tagRepository.getTagByName(name).first()
}
fun getTagById(tagId:Int) {
tagid.value = tagId
viewModelScope.launch {
tag = tagRepository.getTagById(tagid.value!!)
.filterNotNull()
.first()
}
}
}

View File

@ -0,0 +1,11 @@
package com.example.pmulabs.viewModels
import androidx.lifecycle.ViewModel
import androidx.paging.PagingData
import com.example.pmulabs.room.models.Article
import com.example.pmulabs.room.repository.ArticleRepository
import kotlinx.coroutines.flow.Flow
class ArticleScreenViewModel(private val articleRepository: ArticleRepository) : ViewModel() {
val articles: Flow<PagingData<Article>> = articleRepository.getArticles()
}

View File

@ -0,0 +1,21 @@
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.first
import kotlinx.coroutines.launch
class EntryScreenViewModel(private val userRepository: UserRepository) : ViewModel() {
var userList by mutableStateOf<List<User>>(emptyList())
fun setUserList() {
viewModelScope.launch {
userList=userRepository.getAllUsers().first()
}
}
}

View File

@ -0,0 +1,26 @@
package com.example.pmulabs.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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.first
import kotlinx.coroutines.launch
class RegisterScreenViewModel(private val userRepository: UserRepository) : ViewModel() {
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> get() = _users
fun setUserList() {
viewModelScope.launch {
_users.value = userRepository.getAllUsers().first()
}
}
suspend fun insertUser(user: User) {
userRepository.insertUser(user)
}
}

View File

@ -1,12 +1,19 @@
package com.example.pmulabs.viewModels
import androidx.lifecycle.ViewModel
import androidx.paging.PagingData
import com.example.pmulabs.room.models.Tag
import com.example.pmulabs.room.repository.TagRepository
import kotlinx.coroutines.flow.Flow
class TagItemViewModel(
private val tagRepository: TagRepository
) : ViewModel() {
var tags: Flow<PagingData<Tag>> = tagRepository.getTags()
suspend fun insertTag(tag: Tag) {
tagRepository.insertTag(tag)
}
suspend fun updateTag(tag: Tag) {
tagRepository.updateTag(tag)
}