lab 4 complete(finally...)
This commit is contained in:
parent
41536e89d9
commit
5f4c36f00a
@ -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")
|
||||
}
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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>>
|
||||
}
|
@ -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>>
|
||||
}
|
@ -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
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
}
|
@ -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>>
|
||||
}
|
@ -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,102 +30,83 @@ 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 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 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 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 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),
|
||||
contentPadding = PaddingValues(top = 105.dp, bottom = 50.dp, start = 15.dp, end = 15.dp),
|
||||
modifier = modifier
|
||||
.requiredWidth(width = 412.dp)
|
||||
.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()}
|
||||
item {
|
||||
BackButton(modifier = Modifier
|
||||
.clickable { navController.navigate(BottomBarScreen.Main.route) }
|
||||
.offset(
|
||||
y=0.dp
|
||||
y = 0.dp
|
||||
))
|
||||
}
|
||||
item {
|
||||
@ -131,20 +115,24 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
|
||||
.requiredWidth(width = 350.dp)
|
||||
.requiredHeight(height = 33.dp)
|
||||
.offset(
|
||||
y=0.dp
|
||||
y = 0.dp
|
||||
)
|
||||
) {
|
||||
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(
|
||||
@ -176,7 +171,7 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
|
||||
.requiredWidth(width = 412.dp)
|
||||
.requiredHeight(height = 53.dp)
|
||||
.offset(
|
||||
y=0.dp
|
||||
y = 0.dp
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
@ -184,33 +179,38 @@ 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,
|
||||
thickness = 5.dp,
|
||||
modifier = Modifier
|
||||
.border(BorderStroke(3.dp, Color(0xff423a99))), color = Color(0xff423a99)
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness=5.dp,
|
||||
thickness = 5.dp,
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.border(BorderStroke(3.dp, Color(0xff423a99)))
|
||||
.offset(
|
||||
y = 53.dp), color = Color(0xff423a99)
|
||||
y = 53.dp
|
||||
), color = Color(0xff423a99)
|
||||
)
|
||||
}
|
||||
}
|
||||
item{
|
||||
item {
|
||||
OutlinedTextField(
|
||||
value = textComm,
|
||||
onValueChange = {
|
||||
textComm=it
|
||||
textComm = it
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White,
|
||||
@ -236,13 +236,14 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
|
||||
disabledContentColor = Color.White
|
||||
),
|
||||
onClick = {
|
||||
if(textComm.isNotEmpty()) {
|
||||
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,19 +254,52 @@ fun ArticlePageScreen(navController: NavController, modifier: Modifier = Modifie
|
||||
Text(text = "Send", fontSize = 20.sp)
|
||||
}
|
||||
}
|
||||
item{
|
||||
comms.forEach{ comm ->
|
||||
if(comm.articleId==article?.id && comm.text!="") {
|
||||
|
||||
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(
|
||||
thickness=3.dp,
|
||||
thickness = 3.dp,
|
||||
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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,80 +63,45 @@ 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 ->
|
||||
if(!tagsNames.contains(teg.title)) {
|
||||
var tagsNames = remember { mutableStateListOf<String>() }
|
||||
tags.value.forEach { teg ->
|
||||
if (!tagsNames.contains(teg.title)) {
|
||||
tagsNames.add(teg.title)
|
||||
}
|
||||
}
|
||||
@ -149,7 +115,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val suggestions = tagsNames
|
||||
var selectedText by remember { mutableStateOf("") }
|
||||
var textfieldSize by remember { mutableStateOf(Size.Zero)}
|
||||
var textfieldSize by remember { mutableStateOf(Size.Zero) }
|
||||
val icon = if (expanded)
|
||||
Icons.Filled.ArrowDropUp
|
||||
else
|
||||
@ -159,8 +125,8 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
openDialog = false
|
||||
text=""
|
||||
title=""
|
||||
text = ""
|
||||
title = ""
|
||||
},
|
||||
content = {
|
||||
Column(
|
||||
@ -186,7 +152,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
.onGloballyPositioned { coordinates ->
|
||||
textfieldSize = coordinates.size.toSize()
|
||||
},
|
||||
label = {Text("Select Tag")},
|
||||
label = { Text("Select Tag") },
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White,
|
||||
focusedIndicatorColor = Color(0xff423a99),
|
||||
@ -195,7 +161,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
unfocusedLabelColor = Color(0xff423a99)
|
||||
),
|
||||
trailingIcon = {
|
||||
Icon(icon,"List of tags",
|
||||
Icon(icon, "List of tags",
|
||||
Modifier.clickable { expanded = !expanded })
|
||||
}
|
||||
)
|
||||
@ -203,17 +169,18 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
modifier = Modifier
|
||||
.width(with(LocalDensity.current){textfieldSize.width.toDp()})
|
||||
.width(with(LocalDensity.current) { textfieldSize.width.toDp() })
|
||||
) {
|
||||
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()
|
||||
}
|
||||
}}
|
||||
text = { Text(text = label) },
|
||||
onClick = {
|
||||
selectedText = label
|
||||
coroutineScope.launch {
|
||||
tagId =
|
||||
articlePageScreenViewModel.getTagByName(selectedText).id!!
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -221,7 +188,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
OutlinedTextField(
|
||||
value = title,
|
||||
onValueChange = {
|
||||
title=it
|
||||
title = it
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White,
|
||||
@ -242,7 +209,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
OutlinedTextField(
|
||||
value = text,
|
||||
onValueChange = {
|
||||
text=it
|
||||
text = it
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White,
|
||||
@ -273,14 +240,13 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
),
|
||||
onClick = {
|
||||
openDialog = false
|
||||
if(title.isNotEmpty() && text.isNotEmpty() && tagId!=null) {
|
||||
if (title.isNotEmpty() && text.isNotEmpty() && tagId != null) {
|
||||
val newArticle = Article(
|
||||
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)
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -301,9 +267,9 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
openDialogUser = false
|
||||
email=getUser?.email.toString()
|
||||
password=getUser?.password.toString()
|
||||
nickname=getUser?.nickname.toString()
|
||||
email = getUser?.email.toString()
|
||||
password = getUser?.password.toString()
|
||||
nickname = getUser?.nickname.toString()
|
||||
},
|
||||
content = {
|
||||
Column(
|
||||
@ -319,12 +285,12 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
fontSize = 20.sp,
|
||||
),
|
||||
)
|
||||
email?.let { ValidateEmail(it, {email=it} ) }
|
||||
email?.let { ValidateEmail(it, { email = it }) }
|
||||
password?.let {
|
||||
OutlinedTextField(
|
||||
value = it,
|
||||
onValueChange = {
|
||||
password=it
|
||||
password = it
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White,
|
||||
@ -347,7 +313,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
OutlinedTextField(
|
||||
value = it,
|
||||
onValueChange = {
|
||||
nickname=it
|
||||
nickname = it
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White,
|
||||
@ -379,17 +345,16 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
),
|
||||
onClick = {
|
||||
openDialogUser = false
|
||||
if(password?.isNotEmpty() == true && email?.isNotEmpty() == true && isValidEmail(
|
||||
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?.password = password as String
|
||||
getUser?.email = email as String
|
||||
getUser?.nickname = nickname as String
|
||||
coroutineScope.launch {
|
||||
getUser?.let {
|
||||
NewsPortalDatabase.getInstance(context).userDao()
|
||||
.update(it)
|
||||
articlePageScreenViewModel.updateUser(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -409,7 +374,7 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
|
||||
|
||||
LazyColumn(
|
||||
contentPadding= PaddingValues(top=5.dp, bottom = 320.dp),
|
||||
contentPadding = PaddingValues(top = 5.dp, bottom = 320.dp),
|
||||
modifier = modifier
|
||||
.requiredWidth(width = 412.dp)
|
||||
.requiredHeight(height = 915.dp)
|
||||
@ -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,35 +564,69 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp)
|
||||
) {
|
||||
if (!getComms.isEmpty()) {
|
||||
items(items = getComms) { comment ->
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
Text(
|
||||
text = "${comment.text}",
|
||||
color = Color(0xff423a99),
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.clickable {
|
||||
navController.navigate(
|
||||
BottomBarScreen.ArticlePage.passId(
|
||||
comment.articleId.toString()
|
||||
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}",
|
||||
color = Color(0xff423a99),
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.clickable {
|
||||
navController.navigate(
|
||||
BottomBarScreen.ArticlePage.passId(
|
||||
comment?.articleId.toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
HorizontalDivider(
|
||||
thickness = 3.dp,
|
||||
modifier = Modifier
|
||||
.border(BorderStroke(3.dp, Color(0xffdbdbf1))),
|
||||
color = Color(0xffdbdbf1)
|
||||
)
|
||||
}
|
||||
}
|
||||
getComms.apply {
|
||||
when {
|
||||
loadState.refresh is LoadState.Loading -> {
|
||||
item {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.fillParentMaxSize(),
|
||||
color = Color(0xff423a99)
|
||||
)
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
HorizontalDivider(
|
||||
thickness=3.dp,
|
||||
modifier = Modifier
|
||||
.border(BorderStroke(3.dp, Color(0xffdbdbf1))), color = Color(0xffdbdbf1)
|
||||
)
|
||||
}
|
||||
|
||||
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{
|
||||
} 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,35 +718,69 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp)
|
||||
) {
|
||||
if (!getArticles.isEmpty()) {
|
||||
items(items = getArticles) { article ->
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
Text(
|
||||
text = "${article.title}",
|
||||
color = Color(0xff423a99),
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.clickable {
|
||||
navController.navigate(
|
||||
BottomBarScreen.ArticlePage.passId(
|
||||
article.id.toString()
|
||||
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}",
|
||||
color = Color(0xff423a99),
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.clickable {
|
||||
navController.navigate(
|
||||
BottomBarScreen.ArticlePage.passId(
|
||||
article?.id.toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
HorizontalDivider(
|
||||
thickness = 3.dp,
|
||||
modifier = Modifier
|
||||
.border(BorderStroke(3.dp, Color(0xffdbdbf1))),
|
||||
color = Color(0xffdbdbf1)
|
||||
)
|
||||
}
|
||||
}
|
||||
getArticles.apply {
|
||||
when {
|
||||
loadState.refresh is LoadState.Loading -> {
|
||||
item {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.fillParentMaxSize(),
|
||||
color = Color(0xff423a99)
|
||||
)
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
HorizontalDivider(
|
||||
thickness=3.dp,
|
||||
modifier = Modifier
|
||||
.border(BorderStroke(3.dp, Color(0xffdbdbf1))), color = Color(0xffdbdbf1)
|
||||
)
|
||||
}
|
||||
|
||||
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{
|
||||
} 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,29 +872,38 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier, c
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp)
|
||||
) {
|
||||
if (!getTags.isEmpty()) {
|
||||
items(items = getTags) { tag ->
|
||||
Spacer(modifier = Modifier.padding(5.dp))
|
||||
Text(
|
||||
text = "${tag.title}",
|
||||
color = Color(0xff423a99),
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.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)
|
||||
)
|
||||
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}",
|
||||
color = Color(0xff423a99),
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopStart)
|
||||
.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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 ->
|
||||
TagItem(
|
||||
teg = tag,
|
||||
viewModel = currentUserViewModel,
|
||||
onTagClick = {navController.navigate(BottomBarScreen.SearchByTag.passId(tag.id.toString()))}
|
||||
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()))}
|
||||
)
|
||||
}
|
||||
}
|
||||
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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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())) {
|
||||
|
@ -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) }
|
||||
@ -169,7 +162,7 @@ fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier,
|
||||
TextField(
|
||||
value = nicknameValue,
|
||||
onValueChange = {
|
||||
nicknameValue=it
|
||||
nicknameValue = it
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.White
|
||||
@ -185,7 +178,7 @@ fun RegisterScreen(navController: NavController, modifier: Modifier = Modifier,
|
||||
singleLine = true,
|
||||
)
|
||||
Spacer(modifier = Modifier.padding(3.dp))
|
||||
ValidateEmail(emailValue, {emailValue=it} )
|
||||
ValidateEmail(emailValue, { emailValue = it })
|
||||
Spacer(modifier = Modifier.padding(3.dp))
|
||||
TextField(
|
||||
value = passwordValue,
|
||||
@ -228,32 +221,32 @@ 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))
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
@ -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,14 +45,43 @@ 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) {
|
||||
ArticleItem(
|
||||
article = article,
|
||||
currentUserViewModel=currentUserViewModel,
|
||||
onArticleClick = {navController.navigate(BottomBarScreen.ArticlePage.passId(article.id.toString()))}
|
||||
)
|
||||
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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user