diff --git a/app/src/main/java/com/hmoa/app/navigation/NavHost.kt b/app/src/main/java/com/hmoa/app/navigation/NavHost.kt index 8c5150be..3827b997 100644 --- a/app/src/main/java/com/hmoa/app/navigation/NavHost.kt +++ b/app/src/main/java/com/hmoa/app/navigation/NavHost.kt @@ -3,14 +3,61 @@ package com.hmoa.app.navigation import androidx.compose.runtime.Composable import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost -import com.hmoa.feature_authentication.navigation.* +import com.hmoa.feature_authentication.navigation.loginScreen +import com.hmoa.feature_authentication.navigation.navigateToLogin +import com.hmoa.feature_authentication.navigation.navigateToPickNickname +import com.hmoa.feature_authentication.navigation.navigateToPickPersonalInfo +import com.hmoa.feature_authentication.navigation.navigateToSignup +import com.hmoa.feature_authentication.navigation.pickNicknameScreen +import com.hmoa.feature_authentication.navigation.pickPersonalInfoScreen +import com.hmoa.feature_authentication.navigation.signupScreen import com.hmoa.feature_brand.navigation.brandScreen import com.hmoa.feature_brand.navigation.brandSearchScreen import com.hmoa.feature_brand.navigation.navigateToBrand -import com.hmoa.feature_community.Navigation.* +import com.hmoa.feature_community.Navigation.navigateToCommunityCommentEditRoute +import com.hmoa.feature_community.Navigation.navigateToCommunityDescriptionRoute +import com.hmoa.feature_community.Navigation.navigateToCommunityEditRoute +import com.hmoa.feature_community.Navigation.navigateToCommunityPage +import com.hmoa.feature_community.Navigation.navigateToCommunityPostRoute +import com.hmoa.feature_community.Navigation.navigateToCommunityRoute +import com.hmoa.feature_community.Navigation.navigateToCommunitySearchRoute +import com.hmoa.feature_community.Navigation.nestedCommunityGraph import com.hmoa.feature_fcm.alarmRoute -import com.hmoa.feature_hbti.navigation.* -import com.hmoa.feature_home.navigation.* +import com.hmoa.feature_hbti.navigation.addAddress +import com.hmoa.feature_hbti.navigation.editReview +import com.hmoa.feature_hbti.navigation.hbtiProcessScreen +import com.hmoa.feature_hbti.navigation.hbtiScreen +import com.hmoa.feature_hbti.navigation.hbtiSurveyLoadingScreen +import com.hmoa.feature_hbti.navigation.hbtiSurveyResultScreen +import com.hmoa.feature_hbti.navigation.hbtiSurveyScreen +import com.hmoa.feature_hbti.navigation.navigateToAddAddress +import com.hmoa.feature_hbti.navigation.navigateToEditReview +import com.hmoa.feature_hbti.navigation.navigateToHbti +import com.hmoa.feature_hbti.navigation.navigateToHbtiProcess +import com.hmoa.feature_hbti.navigation.navigateToHbtiSurvey +import com.hmoa.feature_hbti.navigation.navigateToHbtiSurveyLoading +import com.hmoa.feature_hbti.navigation.navigateToHbtiSurveyResult +import com.hmoa.feature_hbti.navigation.navigateToNotePick +import com.hmoa.feature_hbti.navigation.navigateToNotePickResult +import com.hmoa.feature_hbti.navigation.navigateToOrder +import com.hmoa.feature_hbti.navigation.navigateToOrderResult +import com.hmoa.feature_hbti.navigation.navigateToPerfumeRecommendation +import com.hmoa.feature_hbti.navigation.navigateToPerfumeRecommendationResult +import com.hmoa.feature_hbti.navigation.navigateToReview +import com.hmoa.feature_hbti.navigation.navigateToWriteReview +import com.hmoa.feature_hbti.navigation.notePickResult +import com.hmoa.feature_hbti.navigation.notePickScreen +import com.hmoa.feature_hbti.navigation.order +import com.hmoa.feature_hbti.navigation.orderResult +import com.hmoa.feature_hbti.navigation.perfumeRecommendationResultRoute +import com.hmoa.feature_hbti.navigation.perfumeRecommendationRoute +import com.hmoa.feature_hbti.navigation.review +import com.hmoa.feature_hbti.navigation.writeReview +import com.hmoa.feature_home.navigation.allPerfumeScreen +import com.hmoa.feature_home.navigation.homeScreen +import com.hmoa.feature_home.navigation.navigateToAllPerfume +import com.hmoa.feature_home.navigation.navigateToHome +import com.hmoa.feature_home.navigation.perfumeSearchScreen import com.hmoa.feature_hpedia.Navigation.navigateToHPedia import com.hmoa.feature_hpedia.Navigation.navigateToHPediaDescRoute import com.hmoa.feature_hpedia.Navigation.navigateToHPediaSearchRoute @@ -18,8 +65,30 @@ import com.hmoa.feature_hpedia.Navigation.nestedHPediaGraph import com.hmoa.feature_magazine.Navigation.magazineDesc import com.hmoa.feature_magazine.Navigation.magazineMain import com.hmoa.feature_magazine.Navigation.navigateToMagazineDesc -import com.hmoa.feature_perfume.navigation.* -import com.hmoa.feature_userinfo.navigation.* +import com.hmoa.feature_perfume.navigation.createNewPerfumeComment +import com.hmoa.feature_perfume.navigation.editMyPerfumeComment +import com.hmoa.feature_perfume.navigation.navigateToCreateNewperfumeComment +import com.hmoa.feature_perfume.navigation.navigateToPerfume +import com.hmoa.feature_perfume.navigation.navigateToPerfumeComment +import com.hmoa.feature_perfume.navigation.navigateToSpecificPerfumeComment +import com.hmoa.feature_perfume.navigation.perfumeComment +import com.hmoa.feature_perfume.navigation.perfumeScreen +import com.hmoa.feature_perfume.navigation.specificComment +import com.hmoa.feature_userinfo.navigation.navigateToBack +import com.hmoa.feature_userinfo.navigation.navigateToEditProfilePage +import com.hmoa.feature_userinfo.navigation.navigateToMyActivity +import com.hmoa.feature_userinfo.navigation.navigateToMyBirth +import com.hmoa.feature_userinfo.navigation.navigateToMyCommentPage +import com.hmoa.feature_userinfo.navigation.navigateToMyFavoriteCommentPage +import com.hmoa.feature_userinfo.navigation.navigateToMyFavoritePerfume +import com.hmoa.feature_userinfo.navigation.navigateToMyGenderPage +import com.hmoa.feature_userinfo.navigation.navigateToMyInfoPage +import com.hmoa.feature_userinfo.navigation.navigateToMyPostPage +import com.hmoa.feature_userinfo.navigation.navigateToMyReview +import com.hmoa.feature_userinfo.navigation.navigateToOrderRecord +import com.hmoa.feature_userinfo.navigation.navigateToRefund +import com.hmoa.feature_userinfo.navigation.navigateToRefundRecord +import com.hmoa.feature_userinfo.navigation.nestedUserInfoGraph @Composable fun SetUpNavGraph( @@ -110,9 +179,7 @@ fun SetUpNavGraph( navCommunityCommentEdit = navController::navigateToCommunityCommentEditRoute, onErrorHandleLoginAgain = navController::navigateToLogin, navLogin = navController::navigateToLogin, - navHome = navController::navigateToHome, - navHPedia = navController::navigateToHPedia, - popStack = { navController.popBackStack() } + navHPedia = navController::navigateToHPedia ) /** perfume 모듈 */ diff --git a/core-designsystem/src/main/java/com/hmoa/core_designsystem/component/MainBottomBar.kt b/core-designsystem/src/main/java/com/hmoa/core_designsystem/component/MainBottomBar.kt index 5a9267ff..21523c2c 100644 --- a/core-designsystem/src/main/java/com/hmoa/core_designsystem/component/MainBottomBar.kt +++ b/core-designsystem/src/main/java/com/hmoa/core_designsystem/component/MainBottomBar.kt @@ -1,5 +1,6 @@ package com.hmoa.core_designsystem.component +import android.util.Log import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -57,6 +58,7 @@ fun MainBottomBar( if (navBackStackEntry != null && navBackStackEntry!!.destination.route != null){ currentScreen = navBackStackEntry!!.destination.route!! } + Log.d("TAG TEST", "current route: ${currentScreen}") } val bottomNavItems = listOf( BottomNavItem( diff --git a/core-model/build.gradle.kts b/core-model/build.gradle.kts index 8f0bd237..700c5f7e 100644 --- a/core-model/build.gradle.kts +++ b/core-model/build.gradle.kts @@ -22,6 +22,7 @@ tasks { dependencies { val kotlinx_version = "1.5.0" + implementation(libs.kotlinx.collections.immutable) implementation("io.ktor:ktor-client-serialization:2.3.7") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinx_version") testImplementation("junit:junit:4.13.2") diff --git a/feature-community/build.gradle.kts b/feature-community/build.gradle.kts index 7d2990c4..13cc3835 100644 --- a/feature-community/build.gradle.kts +++ b/feature-community/build.gradle.kts @@ -1,8 +1,7 @@ plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("dagger.hilt.android.plugin") - id("com.google.dagger.hilt.android") + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.hilt.android) kotlin("kapt") } @@ -37,6 +36,18 @@ android { buildFeatures { compose = true } + tasks.withType() { + compilerOptions.freeCompilerArgs.addAll( + "-P", + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${project.buildDir.absolutePath}/compose_metrics", + ) + } + tasks.withType() { + compilerOptions.freeCompilerArgs.addAll( + "-P", + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${project.buildDir.absolutePath}/compose_reports", + ) + } } dependencies { @@ -50,6 +61,7 @@ dependencies { implementation(libs.bundles.lifecycle) implementation(libs.paging.compose) implementation(libs.bundles.basic) + implementation(libs.kotlinx.collections.immutable) implementation(libs.bundles.hilt) kapt(libs.hilt.android.compiler) diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Navigation/NavGraph.kt b/feature-community/src/main/java/com/hmoa/feature_community/Navigation/NavGraph.kt index c850ed68..687eb0da 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Navigation/NavGraph.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Navigation/NavGraph.kt @@ -1,10 +1,20 @@ package com.hmoa.feature_community.Navigation -import androidx.navigation.* +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.compose.navigation +import androidx.navigation.navArgument +import androidx.navigation.navDeepLink import com.hmoa.core_domain.entity.navigation.CommunityRoute -import com.hmoa.feature_community.Screen.* +import com.hmoa.feature_community.Screen.CommunityCommentEditRoute +import com.hmoa.feature_community.Screen.CommunityDescriptionRoute +import com.hmoa.feature_community.Screen.CommunityEditRoute +import com.hmoa.feature_community.Screen.CommunityHomeRoute +import com.hmoa.feature_community.Screen.CommunityPostRoute +import com.hmoa.feature_community.Screen.CommunityPreviewRoute +import com.hmoa.feature_community.Screen.CommunitySearchRoute //게시글 기본 화면 fun NavController.navigateToCommunityRoute() = navigate(CommunityRoute.CommunityGraphRoute.name) @@ -28,11 +38,16 @@ fun NavController.navigateToCommunityEditRoute(id: Int) = } //게시글 상세 화면 -fun NavController.navigateToCommunityDescriptionRoute(id: Int) = +fun NavController.navigateToCommunityDescriptionRoute(befScreen: CommunityRoute, id: Int) { navigate("${CommunityRoute.CommunityDescriptionRoute.name}/${id}") { - popUpTo("${CommunityRoute.CommunityDescriptionRoute.name}/{id}") { inclusive = true } + if (befScreen == CommunityRoute.CommunityEditRoute) { + popUpTo("${CommunityRoute.CommunityEditRoute.name}/{id}"){inclusive = true} + } else if (befScreen == CommunityRoute.CommunityPostRoute) { + popUpTo("${CommunityRoute.CommunityCommentEditRoute.name}/{type}"){inclusive = true} + } + launchSingleTop = true } - +} //게시글 검색 화면 fun NavController.navigateToCommunitySearchRoute() = navigate(CommunityRoute.CommunitySearchRoute.name) @@ -45,14 +60,12 @@ fun NavGraphBuilder.nestedCommunityGraph( navCommunityPage: () -> Unit, navCommunityPost: (String) -> Unit, navCommunityEdit: (Int) -> Unit, - navCommunityDescription: (Int) -> Unit, + navCommunityDescription: (befRoute: CommunityRoute, communityId: Int) -> Unit, navCommunitySearch: () -> Unit, navCommunityCommentEdit: (Int) -> Unit, onErrorHandleLoginAgain: () -> Unit, navLogin: () -> Unit, - navHome: () -> Unit, navHPedia: () -> Unit, - popStack: () -> Unit, ) { navigation( startDestination = CommunityRoute.CommunityPreviewRoute.name, @@ -63,7 +76,6 @@ fun NavGraphBuilder.nestedCommunityGraph( navCommunityDescription = navCommunityDescription, navCommunityGraph = navCommunityPage, onErrorHandleLoginAgain = onErrorHandleLoginAgain, - navHome = navHome ) } composable(route = CommunityRoute.CommunityPreviewRoute.name) { @@ -73,7 +85,6 @@ fun NavGraphBuilder.nestedCommunityGraph( navCommunityDescription = navCommunityDescription, navPost = navCommunityPost, navLogin = onErrorHandleLoginAgain, - navHPedia = navHPedia, ) } composable(route = "${CommunityRoute.CommunityPostRoute.name}/{type}") { @@ -90,7 +101,8 @@ fun NavGraphBuilder.nestedCommunityGraph( CommunityEditRoute( id = id?.toInt(), navBack = navBack, - navCommunityDesc = navCommunityDescription + navCommunityDesc = navCommunityDescription, + navLogin = navLogin ) } composable( @@ -102,12 +114,10 @@ fun NavGraphBuilder.nestedCommunityGraph( CommunityDescriptionRoute( id = id, - onNavCommunityEdit = navCommunityEdit, - onNavCommentEdit = navCommunityCommentEdit, - onNavLogin = navLogin, - onNavBack = navBack, - onNavHPedia = navHPedia, - onNavPopStack = popStack + navCommunityEdit = navCommunityEdit, + navCommentEdit = navCommunityCommentEdit, + navLogin = navLogin, + navBack = navBack ) } composable(route = CommunityRoute.CommunitySearchRoute.name) { @@ -120,7 +130,8 @@ fun NavGraphBuilder.nestedCommunityGraph( val id = it.arguments?.getString("commentId")?.toInt() CommunityCommentEditRoute( _commentId = id, - navBack = navBack + navBack = navBack, + navLogin = navLogin ) } } diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityCommentEditScreen.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityCommentEditScreen.kt index f18ecd93..248dc2eb 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityCommentEditScreen.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityCommentEditScreen.kt @@ -9,6 +9,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.BasicTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle @@ -18,7 +23,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.hmoa.core_common.ErrorUiState import com.hmoa.core_designsystem.component.AppLoadingScreen +import com.hmoa.core_designsystem.component.ErrorUiSetView import com.hmoa.core_designsystem.component.TopBarWithEvent import com.hmoa.feature_community.ViewModel.CommunityCommentEditUiState import com.hmoa.feature_community.ViewModel.CommunityCommentEditViewModel @@ -27,71 +34,85 @@ import com.hmoa.feature_community.ViewModel.CommunityCommentEditViewModel fun CommunityCommentEditRoute( _commentId : Int?, navBack : () -> Unit, + navLogin: () -> Unit, viewModel : CommunityCommentEditViewModel = hiltViewModel() ){ - viewModel.setId(_commentId) - - val comment = viewModel.comment.collectAsStateWithLifecycle() - val uiState = viewModel.uiState.collectAsStateWithLifecycle() + LaunchedEffect(Unit){ viewModel.setId(_commentId) } + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val errState by viewModel.errorUiState.collectAsStateWithLifecycle() CommunityCommentEditScreen( - uiState = uiState.value, - comment = comment.value, - onCommentChange = { - viewModel.updateComment(it) - }, - onEditDone = { - viewModel.editComment() - navBack() - }, - navBack = navBack + uiState = uiState, + errState = errState, + onEditDone = viewModel::editComment, + navBack = navBack, + navLogin = navLogin ) } @Composable fun CommunityCommentEditScreen( - uiState : CommunityCommentEditUiState, - comment : String, - onCommentChange : (String) -> Unit, - onEditDone : () -> Unit, - navBack : () -> Unit, + uiState: CommunityCommentEditUiState, + errState: ErrorUiState, + onEditDone: (newComment: String, onSuccess: () -> Unit) -> Unit, + navBack: () -> Unit, + navLogin: () -> Unit, ){ when(uiState){ CommunityCommentEditUiState.Loading -> { AppLoadingScreen() } - CommunityCommentEditUiState.Comment -> { - Column( - modifier = Modifier - .fillMaxSize() - .background(color = Color.White) - ){ - TopBarWithEvent( - onCancelClick = navBack, - onConfirmClick = onEditDone, - title = "댓글" - ) - - Spacer(Modifier.height(20.dp)) - - BasicTextField( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 32.dp), - value = comment, - onValueChange = { - onCommentChange(it) - }, - textStyle = TextStyle( - fontSize = 14.sp, - color = Color.Black, - fontFamily = FontFamily(Font(com.hmoa.core_designsystem.R.font.pretendard_regular)) - ) - ) - } + is CommunityCommentEditUiState.Comment -> { + CommunityCommentEditContent( + initComment = uiState.comment, + navBack = navBack, + onEditDone = onEditDone + ) } CommunityCommentEditUiState.Error -> { - Text("오류") + ErrorUiSetView( + onLoginClick = navLogin, + errorUiState = errState, + onCloseClick = navBack + ) } } +} + +@Composable +fun CommunityCommentEditContent( + initComment: String, + navBack: () -> Unit, + onEditDone: (newComment: String, onSuccess: () -> Unit) -> Unit, +){ + var comment by remember{mutableStateOf(initComment)} + + Column( + modifier = Modifier + .fillMaxSize() + .background(color = Color.White) + ){ + TopBarWithEvent( + onCancelClick = navBack, + onConfirmClick = { + onEditDone(comment, navBack) + }, + title = "댓글" + ) + + Spacer(Modifier.height(20.dp)) + + BasicTextField( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 32.dp), + value = comment, + onValueChange = {comment = it}, + textStyle = TextStyle( + fontSize = 14.sp, + color = Color.Black, + fontFamily = FontFamily(Font(com.hmoa.core_designsystem.R.font.pretendard_regular)) + ) + ) + } } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityDescriptionPage.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityDescriptionPage.kt index 79ca357b..533516b6 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityDescriptionPage.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityDescriptionPage.kt @@ -38,21 +38,18 @@ import kotlinx.coroutines.launch @Composable fun CommunityDescriptionRoute( id: Int?, - onNavCommunityEdit: (Int) -> Unit, - onNavCommentEdit: (Int) -> Unit, - onNavLogin: () -> Unit, - onNavBack: () -> Unit, - onNavHPedia: () -> Unit, - onNavPopStack: () -> Unit, + navCommunityEdit: (communityId: Int) -> Unit, + navCommentEdit: (communityId: Int) -> Unit, + navLogin: () -> Unit, + navBack: () -> Unit, viewModel: CommunityDescViewModel = hiltViewModel() ) { viewModel.setId(id) + val context = LocalContext.current val errState = viewModel.errorUiState.collectAsStateWithLifecycle() val uiState = viewModel.uiState.collectAsStateWithLifecycle() - val isLiked = viewModel.isLiked.collectAsStateWithLifecycle() val comments = viewModel.commentPagingSource().collectAsLazyPagingItems() - val reportState = viewModel.reportState.collectAsStateWithLifecycle() val onHeartClick = remember<(commentId: Int, isLiked: Boolean) -> Unit> { { commentId, isLiked -> viewModel.updateCommentLike( @@ -61,48 +58,44 @@ fun CommunityDescriptionRoute( ) } } - - val context = LocalContext.current + val onReportCommunityClick = remember<() -> Unit>{{ + viewModel.reportCommunity { Toast.makeText(context,"신고 완료",Toast.LENGTH_SHORT).show() } + }} + val onReportCommentClick = remember<(commentId: Int) -> Unit>{{ + viewModel.reportComment(it){ Toast.makeText(context, "신고 완료", Toast.LENGTH_SHORT).show() } + }} + val postComment = remember<(comment: String)-> Unit>{{ + viewModel.postComment(it) + comments.refresh() + }} + val deleteCommunity = remember<() -> Unit>{{ + viewModel.delCommunity{ + Toast.makeText(context, "게시글 삭제 완료", Toast.LENGTH_SHORT).show() + navBack() + } + }} + val deleteComment = remember<(commentId: Int) -> Unit>{{ + viewModel.delComment(it){ + comments.refresh() + Toast.makeText(context, "댓글 삭제", Toast.LENGTH_SHORT).show() + } + }} CommunityDescriptionPage( errState = errState.value, onChangeLike = viewModel::updateLike, uiState = uiState.value, commentList = comments, - onNavBack = onNavBack, - onReportCommunity = { - viewModel.reportCommunity() - if (reportState.value) { - Toast.makeText(context, "신고 완료", Toast.LENGTH_SHORT).show() - } - }, - onReportComment = { - viewModel.reportComment(it) - if (reportState.value) { - Toast.makeText(context, "신고 완료", Toast.LENGTH_SHORT).show() - } - }, - onPostComment = { - viewModel.postComment(it) - comments.refresh() - }, + navBack = navBack, + onReportCommunity = onReportCommunityClick, + onReportComment = onReportCommentClick, + onPostComment = postComment, onChangeCommentLike = onHeartClick, - onDeleteCommunity = { - viewModel.delCommunity() - onNavBack() - Toast.makeText(context, "게시글 삭제 완료", Toast.LENGTH_SHORT).show() - }, - onDeleteComment = { commentId -> - viewModel.delComment(commentId) - comments.refresh() - Toast.makeText(context, "댓글 삭제", Toast.LENGTH_SHORT).show() - }, - onNavCommunityEdit = { onNavCommunityEdit(id!!) }, - onNavCommentEdit = onNavCommentEdit, - onErrorHandleLoginAgain = { - onNavLogin() - }, - onNavPopStack = onNavPopStack + onDeleteCommunity = deleteCommunity, + onDeleteComment = deleteComment, + navCommunityEdit = { navCommunityEdit(id!!) }, + navCommentEdit = navCommentEdit, + onErrorHandleLoginAgain = navLogin ) } @@ -113,24 +106,22 @@ fun CommunityDescriptionPage( commentList: LazyPagingItems, onChangeLike: (isLiked: Boolean) -> Unit, onReportCommunity: () -> Unit, - onReportComment: (Int) -> Unit, - onPostComment: (String) -> Unit, - onChangeCommentLike: (Int, Boolean) -> Unit, + onReportComment: (commentId: Int) -> Unit, + onPostComment: (comment: String) -> Unit, + onChangeCommentLike: (commentId: Int, isLiked: Boolean) -> Unit, onDeleteCommunity: () -> Unit, - onDeleteComment: (Int) -> Unit, - onNavBack: () -> Unit, - onNavCommunityEdit: () -> Unit, - onNavCommentEdit: (Int) -> Unit, + onDeleteComment: (commentId: Int) -> Unit, + navBack: () -> Unit, + navCommunityEdit: () -> Unit, + navCommentEdit: (commentId: Int) -> Unit, onErrorHandleLoginAgain: () -> Unit, - onNavPopStack: () -> Unit, ) { when (uiState) { CommunityDescUiState.Loading -> AppLoadingScreen() is CommunityDescUiState.CommunityDesc -> { CommunityDescContent( - community = uiState.community, + community = uiState, commentList = commentList, - photoList = uiState.photoList, onChangeLike = onChangeLike, onReportCommunity = onReportCommunity, onReportComment = onReportComment, @@ -138,18 +129,16 @@ fun CommunityDescriptionPage( onChangeCommentLike = onChangeCommentLike, onDeleteCommunity = onDeleteCommunity, onDeleteComment = onDeleteComment, - onNavBack = onNavBack, - onNavCommunityEdit = onNavCommunityEdit, - onNavCommentEdit = onNavCommentEdit, - onNavPopStack = onNavPopStack + navBack = navBack, + navCommunityEdit = navCommunityEdit, + navCommentEdit = navCommentEdit, ) } - CommunityDescUiState.Error -> { ErrorUiSetView( onLoginClick = onErrorHandleLoginAgain, errorUiState = errState, - onCloseClick = onNavBack, + onCloseClick = navBack, ) } } @@ -158,9 +147,8 @@ fun CommunityDescriptionPage( @OptIn(ExperimentalMaterialApi::class) @Composable private fun CommunityDescContent( - community: CommunityDefaultResponseDto, + community: CommunityDescUiState.CommunityDesc, commentList: LazyPagingItems, - photoList: List, onChangeLike: (isLiked: Boolean) -> Unit, onReportCommunity: () -> Unit, onReportComment: (Int) -> Unit, @@ -168,10 +156,9 @@ private fun CommunityDescContent( onChangeCommentLike: (Int, Boolean) -> Unit, onDeleteCommunity: () -> Unit, onDeleteComment: (Int) -> Unit, - onNavBack: () -> Unit, - onNavCommunityEdit: () -> Unit, - onNavCommentEdit: (Int) -> Unit, - onNavPopStack: () -> Unit + navBack: () -> Unit, + navCommunityEdit: () -> Unit, + navCommentEdit: (Int) -> Unit, ) { var type by remember { mutableStateOf("post") } val onChangeType: (String) -> Unit = { type = it } @@ -183,7 +170,7 @@ private fun CommunityDescContent( val dialogOpen = { scope.launch { modalSheetState.show() } } val dialogClose = { scope.launch { modalSheetState.hide() } - onNavPopStack() + navBack() } ModalBottomSheetLayout( @@ -193,28 +180,23 @@ private fun CommunityDescContent( if (type == "post" && community.writed) { EditModal( onDeleteClick = onDeleteCommunity, - onEditClick = onNavCommunityEdit, - onCancelClick = { dialogClose() } + onEditClick = navCommunityEdit, + onCancelClick = dialogClose ) } else if (type == "comment" && comment != null && comment!!.writed) { EditModal( onDeleteClick = { onDeleteComment(comment!!.commentId) }, - onEditClick = { onNavCommentEdit(comment!!.commentId) }, - onCancelClick = { dialogClose() } + onEditClick = { navCommentEdit(comment!!.commentId) }, + onCancelClick = dialogClose ) } else { ReportModal( onOkClick = { - if (type == "post") { - onReportCommunity() - } else { - if (comment != null) { - onReportComment(comment!!.commentId) - } - } + if (type == "post") { onReportCommunity() } + else { if (comment != null) { onReportComment(comment!!.commentId) }} dialogClose() }, - onCancelClick = { dialogClose() }, + onCancelClick = dialogClose, ) } }, @@ -228,22 +210,20 @@ private fun CommunityDescContent( onChangeType("post") }, onChangeLike = onChangeLike, - photoList = photoList, commentList = commentList, onChangeCommentLike = onChangeCommentLike, onChangeType = onChangeType, onPostComment = onPostComment, setComment = { comment = it }, - onNavBack = onNavBack, + onNavBack = navBack, ) } } @Composable private fun CommunityDescMainContent( - community: CommunityDefaultResponseDto, + community: CommunityDescUiState.CommunityDesc, onChangeLike: (Boolean) -> Unit, - photoList: List, commentList: LazyPagingItems, onChangeType: (String) -> Unit, onChangeCommentLike: (Int, Boolean) -> Unit, @@ -294,7 +274,7 @@ private fun CommunityDescMainContent( heartCount = community.heartCount, isLiked = community.liked, onChangeLike = onChangeLike, - pictures = photoList + pictures = community.communityPhotos ) Column(modifier = Modifier.padding(16.dp)) { HorizontalDivider(thickness = 1.dp, color = CustomColor.gray2) diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityEditPage.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityEditPage.kt index f50a5975..234f9aef 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityEditPage.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityEditPage.kt @@ -1,5 +1,6 @@ package com.hmoa.feature_community.Screen +import android.content.Context import android.net.Uri import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background @@ -19,11 +20,16 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -31,12 +37,16 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.hmoa.core_common.ErrorUiState import com.hmoa.core_designsystem.R import com.hmoa.core_designsystem.component.AppLoadingScreen import com.hmoa.core_designsystem.component.BottomCameraBtn +import com.hmoa.core_designsystem.component.ErrorUiSetView import com.hmoa.core_designsystem.component.ImageView import com.hmoa.core_designsystem.component.TopBarWithEvent import com.hmoa.core_designsystem.theme.CustomColor +import com.hmoa.core_domain.entity.navigation.CommunityRoute +import com.hmoa.core_model.Category import com.hmoa.feature_community.ViewModel.CommunityEditUiState import com.hmoa.feature_community.ViewModel.CommunityEditViewModel @@ -44,116 +54,122 @@ import com.hmoa.feature_community.ViewModel.CommunityEditViewModel fun CommunityEditRoute( id: Int?, navBack: () -> Unit, - navCommunityDesc: (Int) -> Unit, + navCommunityDesc: (befRoute: CommunityRoute, communityId: Int) -> Unit, + navLogin: () -> Unit, viewModel: CommunityEditViewModel = hiltViewModel() ) { //id가 null이 아니면 view model에 setting viewModel.setId(id) - val uiState = viewModel.uiState.collectAsStateWithLifecycle() - val title = viewModel.title.collectAsStateWithLifecycle() - val content = viewModel.content.collectAsStateWithLifecycle() + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val errState by viewModel.errorUiState.collectAsStateWithLifecycle() val pictures = viewModel.newPictures.collectAsStateWithLifecycle() - val category = viewModel.category.collectAsStateWithLifecycle() + val onPostClick = remember{ { navCommunityDesc(CommunityRoute.CommunityEditRoute, id!!) }} CommunityEditPage( - uiState = uiState.value, - category = category.value?.name, - title = title.value, - onTitleChanged = { - viewModel.updateTitle(it) - }, - content = content.value, - onContentChanged = { - viewModel.updateContent(it) - }, + uiState = uiState, + errState = errState, pictures = pictures.value, - onUpdatePictures = { - viewModel.updatePictures(it) - }, - onDeletePictures = { - viewModel.deletePicture(it) - }, - onPostCommunity = { - //view model의 update community 사용 - viewModel.updateCommunity() - }, + onUpdatePictures = viewModel::updatePictures, + onDeletePictures = viewModel::deletePicture, + onPostCommunity = viewModel::updateCommunity, navBack = navBack, - navCommunityDesc = { navCommunityDesc(id!!) } + navCommunityDesc = onPostClick, + navLogin = navLogin ) } @Composable fun CommunityEditPage( uiState: CommunityEditUiState, - category: String?, - title: String, - onTitleChanged: (String) -> Unit, - content: String, - onContentChanged: (String) -> Unit, + errState: ErrorUiState, pictures: List, onUpdatePictures: (List) -> Unit, onDeletePictures: (Uri) -> Unit, - onPostCommunity: () -> Unit, + onPostCommunity: (context: Context, title: String, content: String, onSuccess: () -> Unit ) -> Unit, navBack: () -> Unit, - navCommunityDesc: () -> Unit + navCommunityDesc: () -> Unit, + navLogin: () -> Unit ) { when (uiState) { CommunityEditUiState.Loading -> AppLoadingScreen() - CommunityEditUiState.Success -> { - val scrollableState = rememberScrollState() - - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - TopBarWithEvent( - onCancelClick = navBack, - onConfirmClick = { - onPostCommunity() - navCommunityDesc() - }, - title = category!! - ) - HorizontalDivider(Modifier.fillMaxWidth(), thickness = 1.dp, color = Color.Black) - //title input - EditTitleTextField( - title = title, - onTitleChanged = onTitleChanged - ) - HorizontalDivider(Modifier.fillMaxWidth(), thickness = 1.dp, color = Color.Black) - Column( - modifier = Modifier - .fillMaxWidth() - .weight(1f) - .padding(horizontal = 33.dp, vertical = 27.dp) - .scrollable(state = scrollableState, orientation = Orientation.Vertical) - ) { - //content input - EditContentTextField( - content = content, - onContentChanged = onContentChanged - ) - } - - if (pictures.isNotEmpty()) { + is CommunityEditUiState.Success -> { + CommunityEditContent( + category = uiState.category, + initTitle = uiState.title, + initContent = uiState.content, + pictures = pictures, + onDeletePictures = onDeletePictures, + onUpdatePictures = onUpdatePictures, + onPostCommunity = onPostCommunity, + navCommunityDesc = navCommunityDesc, + navBack = navBack + ) + } - Spacer(Modifier.height(10.dp)) + CommunityEditUiState.Error -> { + ErrorUiSetView( + onLoginClick = navLogin, + errorUiState = errState, + onCloseClick = navBack + ) + } + } +} - EditImageViewPager( - pictures = pictures, - onDeletePictures = onDeletePictures - ) - } - BottomCameraBtn( - onUpdatePictures = onUpdatePictures - ) - } +@Composable +fun CommunityEditContent( + category: Category, + initTitle: String, + initContent: String, + pictures: List, + onDeletePictures: (Uri) -> Unit, + onUpdatePictures: (List) -> Unit, + onPostCommunity: (context: Context, title: String, content: String, onSuccess: () -> Unit) -> Unit, + navCommunityDesc: () -> Unit, + navBack: () -> Unit, +){ + var title by remember{mutableStateOf(initTitle)} + var content by remember{mutableStateOf(initContent)} + val context = LocalContext.current + val scrollableState = rememberScrollState() + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + TopBarWithEvent( + onCancelClick = navBack, + onConfirmClick = {onPostCommunity(context, title, content, navCommunityDesc)}, + title = category.name + ) + HorizontalDivider(Modifier.fillMaxWidth(), thickness = 1.dp, color = Color.Black) + //title input + EditTitleTextField( + title = title, + onTitleChanged = { title = it } + ) + HorizontalDivider(Modifier.fillMaxWidth(), thickness = 1.dp, color = Color.Black) + Column( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .padding(horizontal = 33.dp, vertical = 27.dp) + .scrollable(state = scrollableState, orientation = Orientation.Vertical) + ) { + EditContentTextField( + content = content, + onContentChanged = { content = it } + ) } - CommunityEditUiState.Error -> { - Text("Error") + if (pictures.isNotEmpty()) { + Spacer(Modifier.height(10.dp)) + EditImageViewPager( + pictures = pictures, + onDeletePictures = onDeletePictures + ) } + BottomCameraBtn(onUpdatePictures = onUpdatePictures) } } diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityHome.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityHome.kt index bab3bb3c..3d4696e4 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityHome.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityHome.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -25,6 +26,7 @@ import com.hmoa.core_designsystem.R import com.hmoa.core_designsystem.component.AppLoadingScreen import com.hmoa.core_designsystem.component.ErrorUiSetView import com.hmoa.core_designsystem.theme.CustomColor +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.response.CommunityByCategoryResponseDto import com.hmoa.feature_community.ViewModel.CommunityHomeUiState import com.hmoa.feature_community.ViewModel.CommunityHomeViewModel @@ -32,24 +34,20 @@ import com.hmoa.feature_community.ViewModel.CommunityHomeViewModel @Composable fun CommunityHomeRoute( navCommunityGraph: () -> Unit, - navCommunityDescription: (Int) -> Unit, + navCommunityDescription: (befRoute: CommunityRoute, communityId: Int) -> Unit, onErrorHandleLoginAgain: () -> Unit, - navHome: () -> Unit, viewModel: CommunityHomeViewModel = hiltViewModel(), ) { - - //ui state를 전달 >> 여기에 community list를 가지고 이를 통해 LazyColumn 이용 val uiState by viewModel.uiState.collectAsStateWithLifecycle() val errorUiState by viewModel.errorUiState.collectAsStateWithLifecycle() + val onPostClick = remember<(communityId: Int) -> Unit>{{navCommunityDescription(CommunityRoute.CommunityHomeRoute, it)}} CommunityHome( errorUiState = errorUiState, uiState = uiState, - onNavCommunityGraph = navCommunityGraph, - onNavCommunityDescription = navCommunityDescription, - onErrorHandleLoginAgain = { - onErrorHandleLoginAgain() - }, + navCommunityGraph = navCommunityGraph, + navCommunityDescription = onPostClick, + onErrorHandleLoginAgain = onErrorHandleLoginAgain, ) } @@ -57,40 +55,50 @@ fun CommunityHomeRoute( fun CommunityHome( errorUiState: ErrorUiState, uiState: CommunityHomeUiState, - onNavCommunityGraph: () -> Unit, - onNavCommunityDescription: (Int) -> Unit, + navCommunityGraph: () -> Unit, + navCommunityDescription: (communityId: Int) -> Unit, onErrorHandleLoginAgain: () -> Unit, +) { + when (uiState) { + is CommunityHomeUiState.Loading -> AppLoadingScreen() + is CommunityHomeUiState.Community -> { + CommunityHomeContent( + communities = uiState.communities, + navCommunityDescription = navCommunityDescription, + navCommunityByCategory = navCommunityGraph + ) + } + + is CommunityHomeUiState.Error -> { + ErrorUiSetView( + onLoginClick = onErrorHandleLoginAgain, + errorUiState = errorUiState, + onCloseClick = onErrorHandleLoginAgain + ) + } + } +} +@Composable +fun CommunityHomeContent( + communities: List, + navCommunityDescription: (communityId: Int) -> Unit, + navCommunityByCategory: () -> Unit, ) { Column( modifier = Modifier .padding(horizontal = 16.dp) .fillMaxSize() ) { - CommunityTitleBar(onNavCommunityByCategory = onNavCommunityGraph) - - when (uiState) { - is CommunityHomeUiState.Loading -> AppLoadingScreen() - is CommunityHomeUiState.Community -> { - CommunityHomeContent( - communities = uiState.communities, - onNavCommunityDescription = onNavCommunityDescription - ) - } - - is CommunityHomeUiState.Error -> { - ErrorUiSetView( - onLoginClick = onErrorHandleLoginAgain, - errorUiState = errorUiState, - onCloseClick = onErrorHandleLoginAgain - ) - } - } + CommunityTitleBar(navCommunityByCategory = navCommunityByCategory) + PostList( + communities = communities, + navCommunityDescription = navCommunityDescription + ) } } - @Composable fun CommunityTitleBar( - onNavCommunityByCategory: () -> Unit, + navCommunityByCategory: () -> Unit, ) { Row( modifier = Modifier @@ -107,7 +115,7 @@ fun CommunityTitleBar( ) Text( - modifier = Modifier.clickable { onNavCommunityByCategory() }, + modifier = Modifier.clickable { navCommunityByCategory() }, text = "전체보기", fontSize = 12.sp, fontFamily = FontFamily(Font(R.font.pretendard_regular)), @@ -117,21 +125,10 @@ fun CommunityTitleBar( Spacer(Modifier.height(16.dp)) } -@Composable -fun CommunityHomeContent( - communities: List, - onNavCommunityDescription: (Int) -> Unit, -) { - PostList( - communities = communities, - onNavCommunityDescription = onNavCommunityDescription - ) -} - @Composable fun PostList( communities: List, - onNavCommunityDescription: (Int) -> Unit + navCommunityDescription: (communityId: Int) -> Unit ) { LazyColumn( modifier = Modifier @@ -149,9 +146,7 @@ fun PostList( color = CustomColor.gray2, shape = RoundedCornerShape(10.dp) ), - onPostClick = { - onNavCommunityDescription(community.communityId) - }, + onPostClick = {navCommunityDescription(community.communityId)}, postType = community.category, postTitle = community.title, heartCount = community.heartCount, diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPostPage.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPostPage.kt index d5d27057..67468607 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPostPage.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPostPage.kt @@ -29,7 +29,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -60,7 +59,6 @@ fun CommunityPostRoute( navBack : () -> Unit, viewModel : CommunityPostViewModel = hiltViewModel() ){ - val isDone = viewModel.isDone.collectAsStateWithLifecycle() val category = when(category){ Category.추천.name -> Category.추천 Category.자유.name -> Category.자유 @@ -68,29 +66,26 @@ fun CommunityPostRoute( else -> Category.자유 } val pictures = viewModel.pictures.collectAsStateWithLifecycle() + val postCommunity = remember<(title: String, content: String) -> Unit>{{ title, content -> + viewModel.postCommunity(title, content, category, navBack) + }} PostCommunityPage( category = category, pictures = pictures.value, - onUpdatePictures = {viewModel.updatePictures(it)}, - onDeletePictures = {viewModel.deletePicture(it)}, + onUpdatePictures = viewModel::updatePictures, + onDeletePictures = viewModel::deletePicture, navBack = navBack, - onPostCommunity = { title, content -> - viewModel.postCommunity(title = title, content = content, category = category) - } + onPostCommunity = postCommunity ) - - LaunchedEffect(isDone.value){ - if(isDone.value){navBack()} - } } @Composable fun PostCommunityPage( category : Category, pictures : List, - onUpdatePictures : (List) -> Unit, - onDeletePictures : (Int) -> Unit, + onUpdatePictures : (pictureUris: List) -> Unit, + onDeletePictures : (delPictureId: Int) -> Unit, navBack: () -> Unit, onPostCommunity: (title: String, content: String) -> Unit, ) { diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPreview.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPreview.kt index c29689aa..820b107e 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPreview.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunityPreview.kt @@ -24,50 +24,39 @@ import com.hmoa.component.PostListItem import com.hmoa.core_common.ErrorUiState import com.hmoa.core_designsystem.component.* import com.hmoa.core_designsystem.theme.CustomColor +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.Category import com.hmoa.core_model.response.CommunityByCategoryResponseDto import com.hmoa.feature_community.ViewModel.CommunityMainUiState import com.hmoa.feature_community.ViewModel.CommunityMainViewModel - @Composable fun CommunityPreviewRoute( navBack: () -> Unit, navSearch: () -> Unit, - navCommunityDescription: (Int) -> Unit, + navCommunityDescription: (befRoute: CommunityRoute, communityId: Int) -> Unit, navPost: (String) -> Unit, navLogin: () -> Unit, - navHPedia: () -> Unit, viewModel: CommunityMainViewModel = hiltViewModel() ) { //view model의 ui state에서 type, list 를 받아서 사용하는 방식 val uiState = viewModel.uiState.collectAsStateWithLifecycle() val errState = viewModel.errorUiState.collectAsStateWithLifecycle() val type by viewModel.type.collectAsStateWithLifecycle() + val onPostClick = remember<(Int) -> Unit>{{navCommunityDescription(CommunityRoute.CommunityPreviewRoute, it)}} + val communities = viewModel.communityPagingSource().collectAsLazyPagingItems() CommunityPage( uiState = uiState.value, errState = errState.value, - communities = viewModel.communityPagingSource().collectAsLazyPagingItems(), + communities = communities, type = type, - onTypeChanged = { viewModel.updateCategory(it) }, + onTypeChanged = viewModel::updateCategory, navBack = navBack, navSearch = navSearch, - navCommunityDescription = navCommunityDescription, - navPost = { - if (viewModel.hasToken()) { - navPost(it) - } else { - viewModel.updateLoginError() - } - }, - onErrorHandleLoginAgain = { - if (viewModel.hasToken()) { - navHPedia() - } else { - navLogin() - } - } + navCommunityDescription = onPostClick, + navPost = navPost, + onErrorHandleLoginAgain = navLogin ) } @@ -77,79 +66,27 @@ fun CommunityPage( errState: ErrorUiState, communities: LazyPagingItems, type: Category, - onTypeChanged: (Category) -> Unit, + onTypeChanged: (newCategory: Category) -> Unit, navBack: () -> Unit, navSearch: () -> Unit, navCommunityDescription: (Int) -> Unit, navPost: (String) -> Unit, onErrorHandleLoginAgain: () -> Unit, ) { - var isOpen by remember { mutableStateOf(true) } - var isFabOpen by remember { mutableStateOf(false) } - val animatedAlpha by animateFloatAsState( - targetValue = if (isFabOpen) 0.8f else 0f, label = "fab alpha animation" - ) - when (uiState) { - is CommunityMainUiState.Loading -> AppLoadingScreen() - is CommunityMainUiState.Community -> { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.BottomEnd - ) { - Column( - modifier = Modifier.fillMaxSize() - ) { - TopBar( - title = "Community", - navIcon = painterResource(com.hmoa.core_designsystem.R.drawable.ic_back), - onNavClick = navBack, - menuIcon = painterResource(com.hmoa.core_designsystem.R.drawable.ic_search), - onMenuClick = navSearch - ) - ContentDivider() - CommunityMainTypes( - type = type, - onTypeChanged = onTypeChanged, - ) - ContentDivider() - CommunityPagePostList( - communities = communities.itemSnapshotList, - navCommunityDescription = navCommunityDescription - ) - } - Column( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(end = 8.dp), - horizontalAlignment = Alignment.End - ) { - FloatingActionBtn( - width = 135.dp, - fontSize = 16.sp, - options = listOf( - Category.추천.name, - Category.시향기.name, - Category.자유.name, - ), - events = listOf( - { navPost(Category.추천.name) }, - { navPost(Category.시향기.name) }, - { navPost(Category.자유.name) } - ), - isAvailable = true, - isFabOpen = isFabOpen, - onFabClick = { isFabOpen = it } - ) - } - } - - //fab 선택 시 화면 필터 - Box(modifier = Modifier.fillMaxSize().alpha(animatedAlpha).background(Color.Black)) + CommunityMainUiState.Loading -> AppLoadingScreen() + CommunityMainUiState.Community -> { + PreviewContent( + communities = communities, + type = type, + navBack = navBack, + navSearch = navSearch, + onTypeChanged = onTypeChanged, + navCommunityDescription = navCommunityDescription, + navPost = navPost + ) } - - is CommunityMainUiState.Error -> { + CommunityMainUiState.Error -> { ErrorUiSetView( onLoginClick = onErrorHandleLoginAgain, errorUiState = errState, @@ -159,6 +96,78 @@ fun CommunityPage( } } +@Composable +fun PreviewContent( + communities: LazyPagingItems, + type: Category, + onTypeChanged: (type: Category) -> Unit, + navBack: () -> Unit, + navSearch: () -> Unit, + navCommunityDescription: (communityId: Int) -> Unit, + navPost: (type: String) -> Unit, +){ + var isFabOpen by remember { mutableStateOf(false) } + val animatedAlpha by animateFloatAsState( targetValue = if (isFabOpen) 0.8f else 0f, label = "fab alpha animation" ) + + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.BottomEnd + ) { + Column( + modifier = Modifier.fillMaxSize() + ) { + TopBar( + title = "Community", + navIcon = painterResource(com.hmoa.core_designsystem.R.drawable.ic_back), + onNavClick = navBack, + menuIcon = painterResource(com.hmoa.core_designsystem.R.drawable.ic_search), + onMenuClick = navSearch + ) + ContentDivider() + CommunityMainTypes( + type = type, + onTypeChanged = onTypeChanged, + ) + ContentDivider() + CommunityPagePostList( + communities = communities.itemSnapshotList, + navCommunityDescription = navCommunityDescription + ) + } + Column( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(end = 8.dp), + horizontalAlignment = Alignment.End + ) { + FloatingActionBtn( + width = 135.dp, + fontSize = 16.sp, + options = listOf( + Category.추천.name, + Category.시향기.name, + Category.자유.name, + ), + events = listOf( + { navPost(Category.추천.name) }, + { navPost(Category.시향기.name) }, + { navPost(Category.자유.name) } + ), + isAvailable = true, + isFabOpen = isFabOpen, + onFabClick = { isFabOpen = it } + ) + } + } + + //fab 선택 시 화면 필터 + Box(modifier = Modifier + .fillMaxSize() + .alpha(animatedAlpha) + .background(Color.Black)) +} + @Composable fun CommunityMainTypes( type: Category, diff --git a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunitySearchPage.kt b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunitySearchPage.kt index 39192357..187ef4be 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunitySearchPage.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/Screen/CommunitySearchPage.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp @@ -20,6 +21,7 @@ import com.hmoa.core_designsystem.component.AppLoadingScreen import com.hmoa.core_designsystem.component.ErrorUiSetView import com.hmoa.core_designsystem.component.SearchTopBar import com.hmoa.core_designsystem.theme.CustomColor +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.response.CommunityByCategoryResponseDto import com.hmoa.feature_community.ViewModel.CommunitySearchUiState import com.hmoa.feature_community.ViewModel.CommunitySearchViewModel @@ -27,22 +29,23 @@ import com.hmoa.feature_community.ViewModel.CommunitySearchViewModel @Composable fun CommunitySearchRoute( navBack : () -> Unit, - navCommunityDesc: (Int) -> Unit, + navCommunityDesc: (befRoute: CommunityRoute, communityId: Int) -> Unit, viewModel : CommunitySearchViewModel = hiltViewModel() ){ val searchWord = viewModel.searchWord.collectAsStateWithLifecycle() val uiState = viewModel.uiState.collectAsStateWithLifecycle() val errState = viewModel.errorUiState.collectAsStateWithLifecycle() + val onPostClick = remember<(communityId: Int) -> Unit>{{navCommunityDesc(CommunityRoute.CommunitySearchRoute, it)}} CommunitySearchPage( uiState = uiState.value, errState = errState.value, searchWord = searchWord.value, - onSearchWordChanged = { viewModel.updateSearchWord(it) }, - onClearSearchWord = { viewModel.clearSearchWord() }, - onClickSearch = { viewModel.updateFlag() }, + onSearchWordChanged = viewModel::updateSearchWord, + onClearSearchWord = viewModel::clearSearchWord, + onClickSearch = viewModel::updateFlag, navBack = navBack, - navCommunityDesc = navCommunityDesc + navCommunityDesc = onPostClick ) } @@ -51,7 +54,7 @@ fun CommunitySearchPage( uiState : CommunitySearchUiState, errState: ErrorUiState, searchWord : String, - onSearchWordChanged : (String) -> Unit, + onSearchWordChanged : (newWord: String) -> Unit, onClearSearchWord : () -> Unit, onClickSearch : () -> Unit, navBack : () -> Unit, @@ -84,11 +87,11 @@ fun CommunitySearchPage( private fun SearchContent( communities: List, searchWord: String, - onSearchWordChanged: (String) -> Unit, + onSearchWordChanged: (newWord: String) -> Unit, onClearSearchWord: () -> Unit, onClickSearch: () -> Unit, navBack: () -> Unit, - navCommunityDesc: (Int) -> Unit + navCommunityDesc: (communityId: Int) -> Unit ){ Column( modifier = Modifier @@ -106,7 +109,10 @@ private fun SearchContent( LazyColumn( modifier = Modifier.weight(1f), ){ - items(communities){community -> + items( + items = communities, + key = {it.communityId} + ){community -> PostListItem( modifier = Modifier .fillMaxWidth() @@ -117,9 +123,7 @@ private fun SearchContent( heartCount = community.heartCount, commentCount = community.commentCount ) - if (communities.indexOf(community) != communities.lastIndex){ - HorizontalDivider(thickness = 1.dp, color = CustomColor.gray2) - } + if (communities.indexOf(community) != communities.lastIndex){ HorizontalDivider(thickness = 1.dp, color = CustomColor.gray2) } } } } diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityCommentEditViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityCommentEditViewModel.kt index 62c259ff..d21950aa 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityCommentEditViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityCommentEditViewModel.kt @@ -2,17 +2,17 @@ package com.hmoa.feature_community.ViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.hmoa.core_common.ErrorMessageType import com.hmoa.core_common.ErrorUiState import com.hmoa.core_common.Result import com.hmoa.core_common.asResult +import com.hmoa.core_common.handleErrorType import com.hmoa.core_domain.repository.CommunityCommentRepository -import com.hmoa.core_model.data.ErrorMessage import com.hmoa.core_model.request.CommunityCommentDefaultRequestDto import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -24,11 +24,7 @@ import javax.inject.Inject class CommunityCommentEditViewModel @Inject constructor( private val communityCommentRepository: CommunityCommentRepository ) : ViewModel() { - - private val commentId = MutableStateFlow(null) - - private val _comment = MutableStateFlow("") - val comment get() = _comment.asStateFlow() + private val commentId = MutableStateFlow(-1) private var expiredTokenErrorState = MutableStateFlow(false) private var wrongTypeTokenErrorState = MutableStateFlow(false) @@ -53,44 +49,60 @@ class CommunityCommentEditViewModel @Inject constructor( ) val uiState: StateFlow = combine(errorUiState, commentId) { errorState, id -> - if (id == null) throw NullPointerException("Id is NULL") - if (errorState is ErrorUiState.ErrorData) throw Exception(errorState.generalError.second) + if (errorState is ErrorUiState.ErrorData && errorState.isValidate()) throw Exception("") val response = communityCommentRepository.getCommunityComment(id) if (response.errorMessage != null) throw Exception(response.errorMessage!!.message) response.data!! - }.asResult() - .map { result -> - when (result) { - Result.Loading -> CommunityCommentEditUiState.Loading - is Result.Success -> { - val data = result.data - _comment.update { data.content } - CommunityCommentEditUiState.Comment - } - is Result.Error -> { - if (!generalErrorState.value.first) {generalErrorState.update{Pair(true, result.exception.message)}} - CommunityCommentEditUiState.Error + }.asResult().map { result -> + when (result) { + Result.Loading -> CommunityCommentEditUiState.Loading + is Result.Success -> CommunityCommentEditUiState.Comment(comment = result.data.content) + is Result.Error -> { + if (result.exception.message != "") { + handleErrorType( + error = result.exception, + onExpiredTokenError = {expiredTokenErrorState.update{true}}, + onWrongTypeTokenError = {wrongTypeTokenErrorState.update{true}}, + onUnknownError = {unLoginedErrorState.update{true}}, + onGeneralError = {generalErrorState.update{Pair(true, result.exception.message)}}, + ) } + CommunityCommentEditUiState.Error } - }.stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(3_000), - initialValue = CommunityCommentEditUiState.Loading - ) + } + }.stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(3_000), + initialValue = CommunityCommentEditUiState.Loading + ) + //comment id 설정 - fun setId(id: Int?) = commentId.update { id } - //comment 업데이트 - fun updateComment(newComment: String) = _comment.update { newComment } + fun setId(id: Int?) { + if (id == null) { + generalErrorState.update { Pair(true, "해당 댓글을 찾을 수 없습니다.") } + return + } + commentId.update { id } + } + //comment 수정 - fun editComment() { + fun editComment(newComment: String, onSuccess: () -> Unit) { viewModelScope.launch { - val id = commentId.value!! - val requestDto = CommunityCommentDefaultRequestDto(comment.value) + val requestDto = CommunityCommentDefaultRequestDto(newComment) val result = communityCommentRepository.putCommunityComment( - commentId = id, + commentId = commentId.value, dto = requestDto ) - if (result.errorMessage is ErrorMessage) generalErrorState.update{Pair(true, result.errorMessage!!.message)} + if (result.errorMessage != null) { + when(result.errorMessage!!.message){ + ErrorMessageType.UNKNOWN_ERROR.name -> unLoginedErrorState.update{true} + ErrorMessageType.WRONG_TYPE_TOKEN.name -> wrongTypeTokenErrorState.update{true} + ErrorMessageType.EXPIRED_TOKEN.name -> expiredTokenErrorState.update{true} + else -> generalErrorState.update{Pair(true, result.errorMessage!!.message)} + } + return@launch + } + onSuccess() } } @@ -98,6 +110,6 @@ class CommunityCommentEditViewModel @Inject constructor( sealed interface CommunityCommentEditUiState { data object Error : CommunityCommentEditUiState - data object Comment : CommunityCommentEditUiState + data class Comment(val comment: String) : CommunityCommentEditUiState data object Loading : CommunityCommentEditUiState } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityDescViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityDescViewModel.kt index b335b0f9..2b3ab3aa 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityDescViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityDescViewModel.kt @@ -10,15 +10,18 @@ import com.hmoa.core_common.ErrorMessageType import com.hmoa.core_common.ErrorUiState import com.hmoa.core_common.Result import com.hmoa.core_common.asResult +import com.hmoa.core_common.handleErrorType import com.hmoa.core_domain.repository.CommunityCommentRepository import com.hmoa.core_domain.repository.CommunityRepository import com.hmoa.core_domain.repository.ReportRepository import com.hmoa.core_model.request.CommunityCommentDefaultRequestDto import com.hmoa.core_model.request.TargetRequestDto import com.hmoa.core_model.response.CommunityCommentWithLikedResponseDto -import com.hmoa.core_model.response.CommunityDefaultResponseDto import com.hmoa.feature_community.CommunityCommentPagingSource import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -29,6 +32,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import javax.inject.Inject @HiltViewModel @@ -38,16 +42,11 @@ class CommunityDescViewModel @Inject constructor( private val reportRepository: ReportRepository, ) : ViewModel() { //community id - private val _id = MutableStateFlow(-1) - val id get() = _id.asStateFlow() + private val id = MutableStateFlow(-1) //like 여부 private val _isLiked = MutableStateFlow(false) val isLiked get() = _isLiked.asStateFlow() - private val _reportState = MutableStateFlow(false) - val reportState get() = _reportState.asStateFlow() - - private val flag = MutableStateFlow(false) private var expiredTokenErrorState = MutableStateFlow(false) private var wrongTypeTokenErrorState = MutableStateFlow(false) @@ -71,25 +70,41 @@ class CommunityDescViewModel @Inject constructor( initialValue = ErrorUiState.Loading ) //ui state - val uiState: StateFlow = combine(errorUiState, _id) { errState, id -> - if (errState is ErrorUiState.ErrorData && - (errState.expiredTokenError || errState.wrongTypeTokenError || errState.unknownError || errState.generalError.first)){ - throw Exception("") - } - val result = communityRepository.getCommunity(id) - result - }.asResult().map{ communityResult -> - when(communityResult) { + val uiState: StateFlow = combine(errorUiState, id) { errState, id -> + if (errState is ErrorUiState.ErrorData && errState.isValidate()){ throw Exception("") } + val response = communityRepository.getCommunity(id) + if (response.errorMessage != null) throw Exception(response.errorMessage!!.message) + response.data!! + }.asResult().map{ result -> + when(result) { is Result.Loading -> CommunityDescUiState.Loading - is Result.Success -> CommunityDescUiState.CommunityDesc((communityResult).data.data!!) + is Result.Success -> { + val data = result.data + val communityPhotos = data.communityPhotos.map{it.photoUrl} + CommunityDescUiState.CommunityDesc( + author = data.author, + category = data.category, + communityPhotos = communityPhotos.toImmutableList(), + content = data.content, + heartCount = data.heartCount, + imagesCount = data.imagesCount, + liked = data.liked, + myProfileImgUrl = data.myProfileImgUrl, + profileImgUrl = data.profileImgUrl, + time = data.time, + title = data.title, + writed = data.writed + ) + } is Result.Error -> { - if(communityResult.exception.message != "") { - when (communityResult.exception.message) { - ErrorMessageType.EXPIRED_TOKEN.message -> expiredTokenErrorState.update { true } - ErrorMessageType.WRONG_TYPE_TOKEN.message -> wrongTypeTokenErrorState.update { true } - ErrorMessageType.UNKNOWN_ERROR.message -> unLoginedErrorState.update { true } - else -> generalErrorState.update {Pair(true,communityResult.exception.message)} - } + if(result.exception.message != "") { + handleErrorType( + error = result.exception, + onExpiredTokenError = {expiredTokenErrorState.update{true}}, + onWrongTypeTokenError = {wrongTypeTokenErrorState.update { true }}, + onUnknownError = {unLoginedErrorState.update { true }}, + onGeneralError = {generalErrorState.update {Pair(true,result.exception.message)}} + ) } CommunityDescUiState.Error } @@ -101,17 +116,23 @@ class CommunityDescViewModel @Inject constructor( ) //커뮤니티 삭제 - fun delCommunity() { + fun delCommunity(onSuccess: () -> Unit) { viewModelScope.launch { - try { - communityRepository.deleteCommunity(id.value) - } catch (e: Exception) { - generalErrorState.update { Pair(true, e.message) } + val result = communityRepository.deleteCommunity(id.value) + if (result.errorMessage != null){ + when(result.errorMessage!!.message){ + ErrorMessageType.UNKNOWN_ERROR.name -> {unLoginedErrorState.update { true }} + ErrorMessageType.EXPIRED_TOKEN.name -> {expiredTokenErrorState.update { true }} + ErrorMessageType.WRONG_TYPE_TOKEN.name -> {wrongTypeTokenErrorState.update { true }} + else -> {generalErrorState.update { Pair(true, result.errorMessage!!.message) }} + } + return@launch } + withContext(Dispatchers.Main){ onSuccess() } } } //커뮤니티 신고하기 - fun reportCommunity() { + fun reportCommunity(onSuccess: () -> Unit) { viewModelScope.launch { val requestDto = TargetRequestDto(targetId = id.value.toString()) val result = reportRepository.reportCommunity(requestDto) @@ -122,6 +143,10 @@ class CommunityDescViewModel @Inject constructor( ErrorMessageType.EXPIRED_TOKEN.name -> {expiredTokenErrorState.update{true}} else -> {generalErrorState.update{Pair(true, result.errorMessage!!.message)}} } + return@launch + } + withContext(Dispatchers.Main){ + onSuccess() } } } @@ -160,11 +185,10 @@ class CommunityDescViewModel @Inject constructor( } return@launch } - flag.update{!flag.value} } } //댓글 삭제 - fun delComment(id: Int) { + fun delComment(id: Int, onSuccess: () -> Unit) { viewModelScope.launch { val result = communityCommentRepository.deleteCommunityComment(id) if (result.errorMessage != null){ @@ -176,11 +200,11 @@ class CommunityDescViewModel @Inject constructor( } return@launch } - flag.update{!flag.value} + withContext(Dispatchers.Main){ onSuccess() } } } //댓글 신고하기 - fun reportComment(id: Int) { + fun reportComment(id: Int, onSuccess: () -> Unit) { viewModelScope.launch { val requestDto = TargetRequestDto(id.toString()) val result = reportRepository.reportCommunityComment(requestDto) @@ -191,7 +215,9 @@ class CommunityDescViewModel @Inject constructor( ErrorMessageType.EXPIRED_TOKEN.name -> {expiredTokenErrorState.update{true}} else -> {generalErrorState.update{Pair(true, result.errorMessage!!.message)}} } + return@launch } + withContext(Dispatchers.Main){ onSuccess() } } } //댓글 좋아요 @@ -212,15 +238,12 @@ class CommunityDescViewModel @Inject constructor( } } //id 설정 - fun setId(id: Int?) { - if (id == null) { + fun setId(newId: Int?) { + if (newId == null) { generalErrorState.update { Pair(true, "해당 글을 찾을 수 없습니다.") } return - } else if (id == -1) { - generalErrorState.update { Pair(true, "이미 삭제된 게시글 입니다.") } - return } - _id.update { id } + id.update { newId } } private fun getCommentPaging(id: Int) : CommunityCommentPagingSource { return CommunityCommentPagingSource( @@ -233,9 +256,18 @@ class CommunityDescViewModel @Inject constructor( sealed interface CommunityDescUiState { data object Loading : CommunityDescUiState data class CommunityDesc( - val community: CommunityDefaultResponseDto, - ) : CommunityDescUiState { - val photoList = community.communityPhotos.map {it.photoUrl} - } + val author: String, + val category: String, + val communityPhotos: ImmutableList, + val content: String, + val heartCount: Int, + val imagesCount: Int, + val liked: Boolean, + val myProfileImgUrl: String?, + val profileImgUrl: String?, + val time: String, + val title: String, + val writed: Boolean, + ) : CommunityDescUiState data object Error : CommunityDescUiState } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityEditViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityEditViewModel.kt index 25d1dafb..3f953300 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityEditViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityEditViewModel.kt @@ -1,6 +1,6 @@ package com.hmoa.feature_community.ViewModel -import android.app.Application +import android.content.Context import android.net.Uri import androidx.core.net.toUri import androidx.lifecycle.ViewModel @@ -8,7 +8,9 @@ import androidx.lifecycle.viewModelScope import com.hmoa.core_common.ErrorMessageType import com.hmoa.core_common.ErrorUiState import com.hmoa.core_common.Result +import com.hmoa.core_common.absolutePath import com.hmoa.core_common.asResult +import com.hmoa.core_common.handleErrorType import com.hmoa.core_domain.repository.CommunityRepository import com.hmoa.core_model.Category import com.hmoa.core_model.data.ErrorMessage @@ -24,31 +26,14 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import java.io.File -import java.io.FileOutputStream import javax.inject.Inject @HiltViewModel class CommunityEditViewModel @Inject constructor( - private val application: Application, private val repository: CommunityRepository, ) : ViewModel() { - private val context = application.applicationContext - //가져올 게시글 id - private val _id = MutableStateFlow(null) - val id get() = _id.asStateFlow() - - //title - private val _title = MutableStateFlow("") - val title get() = _title.asStateFlow() - - //content - private val _content = MutableStateFlow("") - val content get() = _content.asStateFlow() - - //category - private val _category = MutableStateFlow(null) - val category get() = _category.asStateFlow() + private val id = MutableStateFlow(-1) //pictures private val _pictures = MutableStateFlow>(listOf()) @@ -82,39 +67,37 @@ class CommunityEditViewModel @Inject constructor( ) val uiState: StateFlow = combine(id, errorUiState) { communityId, errorState -> + if (errorState is ErrorUiState.ErrorData && errorState.isValidate()) throw Exception("") val result = repository.getCommunity(communityId!!) - if (errorState is ErrorUiState.ErrorData && errorState.generalError.first) throw Exception(errorState.generalError.second) if (result.errorMessage is ErrorMessage) throw Exception(result.errorMessage!!.message) result.data!! - }.asResult() - .map { result -> + }.asResult().map { result -> when (result) { Result.Loading -> CommunityEditUiState.Loading is Result.Success -> { - val data = result.data - _title.update { data.title } - _content.update { data.content } - _category.update { - val category = when (data.category) { - "시향기" -> Category.시향기 - "추천" -> Category.추천 - "자유" -> Category.자유 - else -> throw IllegalArgumentException("올바르지 않은 Category") - } - category + val category = when(result.data.category){ + "시향기" -> Category.시향기 + "추천" -> Category.추천 + "자유" -> Category.자유 + else -> throw IllegalArgumentException("올바르지 않은 Category") } - _pictures.update { data.communityPhotos } - _newPictures.update { data.communityPhotos.map { it.photoUrl.toUri() } } - CommunityEditUiState.Success + _pictures.update { result.data.communityPhotos } + _newPictures.update { result.data.communityPhotos.map { it.photoUrl.toUri() } } + CommunityEditUiState.Success( + title = result.data.title, + content = result.data.content, + category = category + ) } is Result.Error -> { - if (!generalErrorState.value.first) { - when (result.exception.message) { - ErrorMessageType.EXPIRED_TOKEN.message -> expiredTokenErrorState.update { true } - ErrorMessageType.WRONG_TYPE_TOKEN.message -> wrongTypeTokenErrorState.update { true } - ErrorMessageType.UNKNOWN_ERROR.message -> unLoginedErrorState.update { true } - else -> generalErrorState.update { Pair(true, result.exception.message) } - } + if (result.exception.message != "") { + handleErrorType( + error = result.exception, + onExpiredTokenError = { expiredTokenErrorState.update { true } }, + onWrongTypeTokenError = { wrongTypeTokenErrorState.update { true } }, + onUnknownError = { unLoginedErrorState.update { true } }, + onGeneralError = {generalErrorState.update { Pair(true, result.exception.message) }} + ) } CommunityEditUiState.Error } @@ -126,16 +109,14 @@ class CommunityEditViewModel @Inject constructor( ) //id setting - fun setId(id: Int?) { - _id.update { - if (id == null) generalErrorState.update{Pair(true, "Not Found ID")} - id + fun setId(newId: Int?) { + if (newId == null) { + generalErrorState.update { Pair(true, "해당 게시글을 찾을 수 없습니다.") } + return } + id.update {newId} } - //title update - fun updateTitle(title: String) = _title.update { title } - //content update - fun updateContent(content: String) = _content.update { content } + //사진 추가 fun updatePictures(newPictures: List) = _newPictures.update { it.plus(newPictures) } //사진 삭제 @@ -143,8 +124,9 @@ class CommunityEditViewModel @Inject constructor( _newPictures.update { it.minus(uri) } delPicture.add(uri) } + //게시글 수정 POST - fun updateCommunity() { + fun updateCommunity(context: Context, title: String, content: String, onSuccess: () -> Unit) { viewModelScope.launch { val pictureUris = _pictures.value.map { it.photoUrl.toUri() } val addPictures = mutableListOf() @@ -154,25 +136,32 @@ class CommunityEditViewModel @Inject constructor( } } val images = addPictures.map { - val uri = absolutePath(it) + val uri = absolutePath(context, it) if (uri == null) generalErrorState.update { Pair(true, "파일 경로가 NULL 입니다.") } File(uri!!) } val delPictureId = getDeletePictureId(delPicture) - if (id.value != null) { - val result = repository.postCommunityUpdate( - images = images.toTypedArray(), - title = title.value, - content = content.value, - communityId = id.value!!, - deleteCommunityPhotoIds = delPictureId.toTypedArray() - ) - if (result.errorMessage is ErrorMessage) {generalErrorState.update { Pair(true, result.errorMessage!!.message) }} - } else { - generalErrorState.update { Pair(true,"id is null") } + val response = repository.postCommunityUpdate( + images = images.toTypedArray(), + title = title, + content = content, + communityId = id.value, + deleteCommunityPhotoIds = delPictureId.toTypedArray() + ) + + if (response.errorMessage != null) { + when(response.errorMessage!!.message){ + ErrorMessageType.UNKNOWN_ERROR.name -> unLoginedErrorState.update{true} + ErrorMessageType.WRONG_TYPE_TOKEN.name -> wrongTypeTokenErrorState.update{true} + ErrorMessageType.EXPIRED_TOKEN.name -> expiredTokenErrorState.update{true} + else -> generalErrorState.update{Pair(true, response.errorMessage!!.message)} + } + return@launch } + onSuccess() } } + //삭제할 사진 id 계산 private fun getDeletePictureId(pictures: List): ArrayList { val ids = arrayListOf() @@ -184,27 +173,14 @@ class CommunityEditViewModel @Inject constructor( } return ids } - private fun absolutePath(uri: Uri): String? { - val contentResolver = context.contentResolver - val filePath = (context.applicationInfo.dataDir + File.separator + System.currentTimeMillis()) - val file = File(filePath) - try { - val inputStream = contentResolver.openInputStream(uri) ?: return null - val outputStream = FileOutputStream(file) - val buf = ByteArray(1024) - var len: Int - while (inputStream.read(buf).also { len = it } > 0) outputStream.write(buf, 0, len) - outputStream.close() - inputStream.close() - } catch (ignore: Exception) { - return null - } - return file.absolutePath - } } sealed interface CommunityEditUiState { data object Loading : CommunityEditUiState - data object Success : CommunityEditUiState + data class Success( + val title: String, + val content: String, + val category: Category + ) : CommunityEditUiState data object Error : CommunityEditUiState } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityHomeViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityHomeViewModel.kt index fad85ff0..e3109e71 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityHomeViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityHomeViewModel.kt @@ -2,45 +2,42 @@ package com.hmoa.feature_community.ViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.hmoa.core_common.ErrorMessageType import com.hmoa.core_common.ErrorUiState import com.hmoa.core_common.Result import com.hmoa.core_common.asResult +import com.hmoa.core_common.handleErrorType import com.hmoa.core_domain.repository.CommunityRepository -import com.hmoa.core_domain.repository.LoginRepository import com.hmoa.core_model.response.CommunityByCategoryResponseDto import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update import javax.inject.Inject @HiltViewModel class CommunityHomeViewModel @Inject constructor( - private val communityRepository: CommunityRepository, - private val loginRepository: LoginRepository, + private val communityRepository: CommunityRepository ) : ViewModel() { - private val authToken = MutableStateFlow(null) - - private val _community = MutableStateFlow(emptyList()) - val community get() = _community.asStateFlow() - private var expiredTokenErrorState = MutableStateFlow(false) private var wrongTypeTokenErrorState = MutableStateFlow(false) private var unLoginedErrorState = MutableStateFlow(false) - private var memberNotFoundErrorState = MutableStateFlow(false) private var generalErrorState = MutableStateFlow>(Pair(false, null)) val errorUiState: StateFlow = combine( expiredTokenErrorState, wrongTypeTokenErrorState, unLoginedErrorState, - memberNotFoundErrorState, generalErrorState - ) { expiredTokenError, wrongTypeTokenError, unknownError, memberNotFoundError, generalError -> + ) { expiredTokenError, wrongTypeTokenError, unknownError, generalError -> ErrorUiState.ErrorData( expiredTokenError = expiredTokenError, wrongTypeTokenError = wrongTypeTokenError, unknownError = unknownError, - memberNotFoundError = memberNotFoundError, generalError = generalError ) }.stateIn( @@ -49,55 +46,36 @@ class CommunityHomeViewModel @Inject constructor( initialValue = ErrorUiState.Loading ) - init { - getAuthToken() - } - val uiState: StateFlow = flow { val result = communityRepository.getCommunitiesHome() - if (result.errorMessage != null) { - throw Exception(result.errorMessage!!.message) - } + if (result.errorMessage != null) throw Exception(result.errorMessage!!.message) emit(result.data!!) - }.asResult() - .map { result -> - when (result) { - is Result.Loading -> CommunityHomeUiState.Loading - is Result.Success -> CommunityHomeUiState.Community(result.data) - is Result.Error -> { - when (result.exception.message) { - ErrorMessageType.EXPIRED_TOKEN.message -> expiredTokenErrorState.update { true } - ErrorMessageType.WRONG_TYPE_TOKEN.message -> wrongTypeTokenErrorState.update { true } - ErrorMessageType.UNKNOWN_ERROR.message -> unLoginedErrorState.update { true } - ErrorMessageType.MEMBER_NOT_FOUND.message -> memberNotFoundErrorState.update { true } - else -> generalErrorState.update { Pair(true, result.exception.message) } - } - CommunityHomeUiState.Error - } - } - }.stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(1_000), - initialValue = CommunityHomeUiState.Loading - ) - - fun hasToken(): Boolean = authToken.value != null - - // get token - private fun getAuthToken() { - viewModelScope.launch { - loginRepository.getAuthToken().onEmpty { }.collectLatest { - authToken.value = it + }.asResult().map { result -> + when (result) { + Result.Loading -> CommunityHomeUiState.Loading + is Result.Success -> CommunityHomeUiState.Community(result.data.toImmutableList()) + is Result.Error -> { + handleErrorType( + error = result.exception, + onExpiredTokenError = {expiredTokenErrorState.update { true }}, + onWrongTypeTokenError = {wrongTypeTokenErrorState.update { true }}, + onUnknownError = {unLoginedErrorState.update { true }}, + onGeneralError = {generalErrorState.update { Pair(true, result.exception.message) }} + ) + CommunityHomeUiState.Error } } - } + }.stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(3_000), + initialValue = CommunityHomeUiState.Loading + ) } sealed interface CommunityHomeUiState { data object Loading : CommunityHomeUiState data class Community( - val communities: List + val communities: kotlinx.collections.immutable.ImmutableList ) : CommunityHomeUiState - data object Error : CommunityHomeUiState } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityMainViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityMainViewModel.kt index 4cdd9919..a02ca278 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityMainViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityMainViewModel.kt @@ -8,29 +8,31 @@ import androidx.paging.PagingData import androidx.paging.cachedIn import com.hmoa.core_common.ErrorUiState import com.hmoa.core_domain.repository.CommunityRepository -import com.hmoa.core_domain.repository.LoginRepository import com.hmoa.core_model.Category import com.hmoa.core_model.response.CommunityByCategoryResponseDto import com.hmoa.feature_community.CommunityPagingSource import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update import javax.inject.Inject const val PAGE_SIZE = 10 @HiltViewModel class CommunityMainViewModel @Inject constructor( - private val communityRepository: CommunityRepository, - private val loginRepository: LoginRepository + private val communityRepository: CommunityRepository ) : ViewModel() { - private val authToken = MutableStateFlow(null) - //type 정보 private val _type = MutableStateFlow(Category.추천) val type get() = _type.asStateFlow() private var _communities = MutableStateFlow?>(null) - val _enableLoginErrorDialog = MutableStateFlow(false) private var expiredTokenErrorState = MutableStateFlow(false) private var wrongTypeTokenErrorState = MutableStateFlow(false) @@ -54,28 +56,17 @@ class CommunityMainViewModel @Inject constructor( initialValue = ErrorUiState.Loading ) - val uiState: StateFlow = combine( - _communities, - _enableLoginErrorDialog - ) { communities, isLoginUser -> - CommunityMainUiState.Community( - communities, isLoginUser - ) + val uiState: StateFlow = errorUiState.map{ errState -> + CommunityMainUiState.Community }.stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(3_000), initialValue = CommunityMainUiState.Loading ) - init { - getAuthToken() - } - fun communityPagingSource(): Flow> = Pager( config = PagingConfig(pageSize = PAGE_SIZE), - pagingSourceFactory = { - getCommunityPaging(type.value.name) - } + pagingSourceFactory = { getCommunityPaging(type.value.name) } ).flow.cachedIn(viewModelScope) //category 정보 변경 @@ -88,28 +79,10 @@ class CommunityMainViewModel @Inject constructor( communityRepository = communityRepository, category = category ) - - //err state update - fun updateLoginError() { - unLoginedErrorState.update { true } - } - - fun hasToken() = authToken.value != null - - //get token - private fun getAuthToken() { - viewModelScope.launch { - loginRepository.getAuthToken().onEmpty { }.collectLatest { authToken.value = it } - } - } } sealed interface CommunityMainUiState { data object Loading : CommunityMainUiState - data class Community( - val communities: PagingData?, - val enableLoginErrorDialog: Boolean - ) : CommunityMainUiState - + data object Community : CommunityMainUiState data object Error : CommunityMainUiState } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityPostViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityPostViewModel.kt index 60296600..f72585be 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityPostViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunityPostViewModel.kt @@ -4,7 +4,9 @@ import android.app.Application import android.net.Uri import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.hmoa.core_common.ErrorMessageType import com.hmoa.core_common.ErrorUiState +import com.hmoa.core_common.absolutePath import com.hmoa.core_domain.repository.CommunityRepository import com.hmoa.core_model.Category import dagger.hilt.android.lifecycle.HiltViewModel @@ -17,7 +19,6 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import java.io.File -import java.io.FileOutputStream import javax.inject.Inject @HiltViewModel @@ -75,10 +76,10 @@ class CommunityPostViewModel @Inject constructor( } //게시글 게시 - fun postCommunity(title: String, content: String, category: Category) { + fun postCommunity(title: String, content: String, category: Category, onSuccess: () -> Unit,) { val images = arrayListOf() pictures.value.map { picture -> - val path = absolutePath(picture) ?: throw NullPointerException("file path is NULL") + val path = absolutePath(context, picture) ?: throw NullPointerException("file path is NULL") images.add(File(path)) } viewModelScope.launch { @@ -89,32 +90,15 @@ class CommunityPostViewModel @Inject constructor( content = content ) if (result.errorMessage != null) { - _generalErrorState.update { Pair(true, result.errorMessage!!.message) } + when(result.errorMessage!!.message){ + ErrorMessageType.UNKNOWN_ERROR.name -> _unLoginedErrorState.update{true} + ErrorMessageType.WRONG_TYPE_TOKEN.name -> _wrongTypeTokenErrorState.update{true} + ErrorMessageType.EXPIRED_TOKEN.name -> _expiredTokenErrorState.update{true} + else -> _generalErrorState.update{Pair(true, result.errorMessage!!.message)} + } return@launch } - isDone.update{true} + onSuccess() } } - - private fun absolutePath(uri: Uri): String? { - val contentResolver = context.contentResolver - - val filePath = (context.applicationInfo.dataDir + File.separator + System.currentTimeMillis()) - val file = File(filePath) - - try { - val inputStream = contentResolver.openInputStream(uri) ?: return null - - val outputStream = FileOutputStream(file) - - val buf = ByteArray(1024) - var len: Int - while (inputStream.read(buf).also { len = it } > 0) outputStream.write(buf, 0, len) - outputStream.close() - inputStream.close() - } catch (ignore: Exception) { - return null - } - return file.absolutePath - } } \ No newline at end of file diff --git a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunitySearchViewModel.kt b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunitySearchViewModel.kt index 94ada361..c9231957 100644 --- a/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunitySearchViewModel.kt +++ b/feature-community/src/main/java/com/hmoa/feature_community/ViewModel/CommunitySearchViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.hmoa.core_common.ErrorUiState import com.hmoa.core_common.Result import com.hmoa.core_common.asResult +import com.hmoa.core_common.handleErrorType import com.hmoa.core_domain.repository.SearchRepository import com.hmoa.core_model.response.CommunityByCategoryResponseDto import dagger.hilt.android.lifecycle.HiltViewModel @@ -13,6 +14,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update @@ -56,20 +58,22 @@ class CommunitySearchViewModel @Inject constructor( _searchWord, _flag ) { word, flag -> - if (_searchWord.value.isEmpty()) { - return@combine emptyList() - } + if (_searchWord.value.isEmpty()) { return@combine emptyList() } val result = searchRepository.getCommunity(0, word) - if (result.errorMessage != null) { - throw Exception(result.errorMessage!!.message) - } + if (result.errorMessage != null) { throw Exception(result.errorMessage!!.message) } result.data!! - }.asResult().map { result -> + }.debounce(500).asResult().map { result -> when (result) { is Result.Loading -> CommunitySearchUiState.Loading is Result.Success -> CommunitySearchUiState.SearchResult(result.data) is Result.Error -> { - generalErrorState.update{ Pair(true, result.exception.message)} + handleErrorType( + error = result.exception, + onExpiredTokenError = {expiredTokenErrorState.update{true}}, + onUnknownError = {unLoginedErrorState.update{true}}, + onWrongTypeTokenError = {wrongTypeTokenErrorState.update{true}}, + onGeneralError = {generalErrorState.update{Pair(true, result.exception.message)}}, + ) CommunitySearchUiState.Error } } diff --git a/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmNavigation.kt b/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmNavigation.kt index a349c496..696bd2c1 100644 --- a/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmNavigation.kt +++ b/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmNavigation.kt @@ -3,6 +3,7 @@ package com.hmoa.feature_fcm import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import com.hmoa.core_domain.entity.navigation.CommunityRoute const val ALARM_ROUTE = "ALARM_ROUTE" @@ -10,7 +11,7 @@ fun NavController.navigateToAlarmScreen() = navigate(ALARM_ROUTE) fun NavGraphBuilder.alarmRoute( onNavBack : () -> Unit, - onNavCommunityDesc : (Int) -> Unit, + onNavCommunityDesc : (befRoute: CommunityRoute, communityId: Int) -> Unit, onNavPerfumeComment : (Int) -> Unit, ){ composable(route = ALARM_ROUTE){ diff --git a/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmScreen.kt b/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmScreen.kt index 8eee0569..b2ddf909 100644 --- a/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmScreen.kt +++ b/feature-fcm/src/main/java/com/hmoa/feature_fcm/AlarmScreen.kt @@ -3,12 +3,18 @@ package com.hmoa.feature_fcm import android.net.Uri import android.util.Log import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -24,17 +30,19 @@ import com.hmoa.core_designsystem.component.AlarmItem import com.hmoa.core_designsystem.component.AppLoadingScreen import com.hmoa.core_designsystem.component.ErrorUiSetView import com.hmoa.core_designsystem.component.TopBar +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.response.AlarmResponse @Composable fun AlarmScreenRoute( onNavBack: () -> Unit, - onNavCommunityDesc: (Int) -> Unit, - onNavPerfumeComment: (Int) -> Unit, + onNavCommunityDesc: (befRoute: CommunityRoute, communityId: Int) -> Unit, + onNavPerfumeComment: (perfumeId: Int) -> Unit, viewModel: AlarmViewModel = hiltViewModel() ) { val uiState = viewModel.uiState.collectAsStateWithLifecycle() val errorState = viewModel.errorUiState.collectAsStateWithLifecycle() + val onPostClick = remember<(Int) -> Unit>{{onNavCommunityDesc(CommunityRoute.CommunityHomeRoute, it)}} AlarmScreen( uiState = uiState.value, errState = errorState.value, @@ -42,7 +50,7 @@ fun AlarmScreenRoute( val uri = Uri.parse(type) val type = uri.host when (type) { - "community" -> onNavCommunityDesc(id) + "community" -> onPostClick(id) "perfume_comment" -> onNavPerfumeComment(id) else -> { Log.d("NAVIGATION TEST", "type : ${type}") diff --git a/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Navigation/NavGraph.kt b/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Navigation/NavGraph.kt index cfc00d2d..24bcba1b 100644 --- a/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Navigation/NavGraph.kt +++ b/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Navigation/NavGraph.kt @@ -6,6 +6,7 @@ import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.compose.navigation import androidx.navigation.navArgument +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.feature_hpedia.Screen.HPediaDescRoute import com.hmoa.feature_hpedia.Screen.HPediaRoute import com.hmoa.feature_hpedia.Screen.HPediaSearchRoute @@ -21,7 +22,7 @@ fun NavController.navigateToHPediaSearchRoute(type: String) = navigate("${com.hm fun NavGraphBuilder.nestedHPediaGraph( navBack: () -> Unit, - navCommunityDesc: (Int) -> Unit, + navCommunityDesc: (befRoute: CommunityRoute, community: Int) -> Unit, navCommunityGraph: () -> Unit, navHPediaSearch: (String) -> Unit, navHPediaDesc: (Int, String) -> Unit, @@ -64,7 +65,6 @@ fun NavGraphBuilder.nestedHPediaGraph( navCommunityDesc = navCommunityDesc, navCommunityGraph = navCommunityGraph, navLogin = navLogin, - navHome = navHome, ) } } diff --git a/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Screen/HPediaScreen.kt b/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Screen/HPediaScreen.kt index b14948fe..be5fc762 100644 --- a/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Screen/HPediaScreen.kt +++ b/feature-hpedia/src/main/java/com/hmoa/feature_hpedia/Screen/HPediaScreen.kt @@ -24,22 +24,21 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.hmoa.core_designsystem.R +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.feature_community.Screen.CommunityHomeRoute @Composable fun HPediaRoute( navHPediaSearch: (String) -> Unit, - navCommunityDesc: (Int) -> Unit, + navCommunityDesc: (befRoute: CommunityRoute, communityId: Int) -> Unit, navCommunityGraph: () -> Unit, - navLogin: () -> Unit, - navHome : () -> Unit, + navLogin: () -> Unit ) { HPediaScreen( navHPediaSearch = navHPediaSearch, navCommunityDesc = navCommunityDesc, navCommunityGraph = navCommunityGraph, - onErrorHandleLoginAgain = navLogin, - navHome = navHome + onErrorHandleLoginAgain = navLogin ) } @@ -47,10 +46,9 @@ fun HPediaRoute( @Composable fun HPediaScreen( navHPediaSearch: (String) -> Unit, - navCommunityDesc: (Int) -> Unit, + navCommunityDesc: (communityRoute: CommunityRoute, communityId: Int) -> Unit, navCommunityGraph: () -> Unit, onErrorHandleLoginAgain: () -> Unit, - navHome : () -> Unit ) { Column( modifier = Modifier @@ -72,7 +70,6 @@ fun HPediaScreen( navCommunityGraph = navCommunityGraph, navCommunityDescription = navCommunityDesc, onErrorHandleLoginAgain = onErrorHandleLoginAgain, - navHome = navHome ) } } diff --git a/feature-magazine/src/main/java/com/hmoa/feature_magazine/Navigation/MagazineNavigation.kt b/feature-magazine/src/main/java/com/hmoa/feature_magazine/Navigation/MagazineNavigation.kt index f052c536..828bca77 100644 --- a/feature-magazine/src/main/java/com/hmoa/feature_magazine/Navigation/MagazineNavigation.kt +++ b/feature-magazine/src/main/java/com/hmoa/feature_magazine/Navigation/MagazineNavigation.kt @@ -3,6 +3,7 @@ package com.hmoa.feature_magazine.Navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_domain.entity.navigation.MagazineRoute import com.hmoa.feature_magazine.Screen.MagazineDescRoute import com.hmoa.feature_magazine.Screen.MagazineMainRoute @@ -14,7 +15,7 @@ fun NavHostController.navigateToMagazineDesc(magazineId : Int) = navigate("${Mag fun NavGraphBuilder.magazineMain( onNavHome : () -> Unit, onNavPerfumeDesc : (Int) -> Unit, - onNavCommunityDesc : (Int) -> Unit, + onNavCommunityDesc : (befRoute: CommunityRoute, communityId: Int) -> Unit, onNavMagazineDesc : (Int) -> Unit, ){ composable(MagazineRoute.Magazine.name){ diff --git a/feature-magazine/src/main/java/com/hmoa/feature_magazine/Screen/MagazineMain.kt b/feature-magazine/src/main/java/com/hmoa/feature_magazine/Screen/MagazineMain.kt index 6ebca983..bf615497 100644 --- a/feature-magazine/src/main/java/com/hmoa/feature_magazine/Screen/MagazineMain.kt +++ b/feature-magazine/src/main/java/com/hmoa/feature_magazine/Screen/MagazineMain.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -32,6 +33,7 @@ import com.hmoa.core_common.ErrorUiState import com.hmoa.core_designsystem.R import com.hmoa.core_designsystem.component.* import com.hmoa.core_designsystem.theme.CustomColor +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.response.MagazineSummaryResponseDto import com.hmoa.core_model.response.MagazineTastingCommentResponseDto import com.hmoa.core_model.response.RecentPerfumeResponseDto @@ -42,13 +44,14 @@ import com.hmoa.feature_magazine.ViewModel.MagazineMainViewModel fun MagazineMainRoute( onNavHome: () -> Unit, onNavPerfumeDesc: (Int) -> Unit, - onNavCommunityDesc: (Int) -> Unit, + onNavCommunityDesc: (befRoute: CommunityRoute, communityId: Int) -> Unit, onNavMagazineDesc: (Int) -> Unit, viewModel: MagazineMainViewModel = hiltViewModel() ) { val uiState = viewModel.uiState.collectAsStateWithLifecycle() val errorState = viewModel.errorUiState.collectAsStateWithLifecycle() val magazineList = viewModel.magazinePagingSource().collectAsLazyPagingItems() + val onPostClick = remember<(Int) -> Unit>{{onNavCommunityDesc(CommunityRoute.CommunityHomeRoute, it)}} MagazineMainScreen( uiState = uiState.value, @@ -56,7 +59,7 @@ fun MagazineMainRoute( magazineList = magazineList, onNavHome = onNavHome, onNavPerfumeDesc = onNavPerfumeDesc, - onNavCommunityDesc = onNavCommunityDesc, + onNavCommunityDesc = onPostClick, onNavMagazineDesc = onNavMagazineDesc ) } diff --git a/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyCommentPage.kt b/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyCommentPage.kt index 3a494088..a0b93064 100644 --- a/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyCommentPage.kt +++ b/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyCommentPage.kt @@ -1,10 +1,17 @@ package com.hmoa.feature_userinfo.screen import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -21,9 +28,15 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.ItemSnapshotList import androidx.paging.compose.collectAsLazyPagingItems import com.hmoa.core_common.ErrorUiState -import com.hmoa.core_designsystem.component.* +import com.hmoa.core_designsystem.component.AppLoadingScreen +import com.hmoa.core_designsystem.component.Comment +import com.hmoa.core_designsystem.component.EmptyDataPage +import com.hmoa.core_designsystem.component.ErrorUiSetView +import com.hmoa.core_designsystem.component.TopBar +import com.hmoa.core_designsystem.component.TypeBadge import com.hmoa.core_designsystem.theme.CustomColor import com.hmoa.core_domain.entity.data.MyPageCategory +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.response.CommunityCommentDefaultResponseDto import com.hmoa.feature_userinfo.viewModel.CommentUiState import com.hmoa.feature_userinfo.viewModel.CommentViewModel @@ -31,7 +44,7 @@ import com.hmoa.feature_userinfo.viewModel.CommentViewModel @Composable fun MyCommentRoute( navBack: () -> Unit, - navCommunity: (communityId: Int) -> Unit, + navCommunity: (befRoute: CommunityRoute, communityId: Int) -> Unit, navPerfume : (perfumeId: Int) -> Unit, navLogin: () -> Unit, viewModel: CommentViewModel = hiltViewModel() @@ -39,13 +52,14 @@ fun MyCommentRoute( //comment list val commentUiState = viewModel.uiState.collectAsStateWithLifecycle() val errState = viewModel.errorUiState.collectAsStateWithLifecycle() + val onCommentClick = remember<(Int) -> Unit>{{navCommunity(CommunityRoute.CommunityHomeRoute, it)}} MyCommentPage( uiState = commentUiState.value, errState = errState.value, navBack = navBack, navPerfume = navPerfume, - navCommunity = navCommunity, + navCommunity = onCommentClick, onTypeChanged = viewModel::changeType, navLogin = navLogin ) diff --git a/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyFavoriteCommentPage.kt b/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyFavoriteCommentPage.kt index 48a33a3c..ee714cfd 100644 --- a/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyFavoriteCommentPage.kt +++ b/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/Screen/MyFavoriteCommentPage.kt @@ -1,11 +1,20 @@ package com.hmoa.feature_userinfo import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource @@ -16,9 +25,15 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.ItemSnapshotList import androidx.paging.compose.collectAsLazyPagingItems import com.hmoa.core_common.ErrorUiState -import com.hmoa.core_designsystem.component.* +import com.hmoa.core_designsystem.component.AppLoadingScreen +import com.hmoa.core_designsystem.component.Comment +import com.hmoa.core_designsystem.component.EmptyDataPage +import com.hmoa.core_designsystem.component.ErrorUiSetView +import com.hmoa.core_designsystem.component.TopBar +import com.hmoa.core_designsystem.component.TypeBadge import com.hmoa.core_designsystem.theme.CustomColor import com.hmoa.core_domain.entity.data.MyPageCategory +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_model.response.CommunityCommentDefaultResponseDto import com.hmoa.feature_userinfo.viewModel.FavoriteCommentUiState import com.hmoa.feature_userinfo.viewModel.FavoriteCommentViewModel @@ -26,7 +41,7 @@ import com.hmoa.feature_userinfo.viewModel.FavoriteCommentViewModel @Composable fun MyFavoriteCommentRoute( navBack: () -> Unit, - navCommunity: (communityId: Int) -> Unit, + navCommunity: (befRoute: CommunityRoute, communityId: Int) -> Unit, navPerfume: (perfumeId: Int) -> Unit, viewModel: FavoriteCommentViewModel = hiltViewModel() ) { @@ -34,6 +49,7 @@ fun MyFavoriteCommentRoute( val uiState = viewModel.uiState.collectAsStateWithLifecycle() val errState = viewModel.errorUiState.collectAsStateWithLifecycle() val type by viewModel.type.collectAsStateWithLifecycle() + val onCommentClick = remember<(Int) -> Unit>{{navCommunity(CommunityRoute.CommunityHomeRoute, it)}} MyFavoriteCommentPage( uiState = uiState.value, @@ -42,7 +58,7 @@ fun MyFavoriteCommentRoute( onTypeChanged = viewModel::changeType, navBack = navBack, navPerfume = navPerfume, - navCommunity = navCommunity, + navCommunity = onCommentClick, ) } diff --git a/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/navigation/NavGraph.kt b/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/navigation/NavGraph.kt index 4a6b3fa2..489cc12f 100644 --- a/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/navigation/NavGraph.kt +++ b/feature-userInfo/src/main/java/com/hmoa/feature_userinfo/navigation/NavGraph.kt @@ -7,6 +7,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.navigation import androidx.navigation.navArgument import com.example.userinfo.MyPageRoute +import com.hmoa.core_domain.entity.navigation.CommunityRoute import com.hmoa.core_domain.entity.navigation.HbtiRoute import com.hmoa.core_domain.entity.navigation.UserInfoRoute import com.hmoa.feature_userinfo.MyFavoriteCommentRoute @@ -72,7 +73,7 @@ fun NavGraphBuilder.nestedUserInfoGraph( navLogin: () -> Unit, navReview: (befRoute: HbtiRoute) -> Unit, navBack: () -> Unit, - navCommunity: (Int) -> Unit, + navCommunity: (befRoute: CommunityRoute, communityId: Int) -> Unit, navEditPost: (Int) -> Unit, navEditProfile: () -> Unit, navManageMyInfo: () -> Unit,