diff --git a/app/src/main/java/com/withpeace/withpeace/navigation/NavHost.kt b/app/src/main/java/com/withpeace/withpeace/navigation/NavHost.kt index d2a20f3c..350b5761 100644 --- a/app/src/main/java/com/withpeace/withpeace/navigation/NavHost.kt +++ b/app/src/main/java/com/withpeace/withpeace/navigation/NavHost.kt @@ -5,6 +5,7 @@ import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.navOptions @@ -13,12 +14,10 @@ import com.app.profileeditor.navigation.navigateProfileEditor import com.app.profileeditor.navigation.profileEditorNavGraph import com.withpeace.withpeace.core.designsystem.ui.snackbar.SnackbarState import com.withpeace.withpeace.core.designsystem.ui.snackbar.SnackbarType -import com.withpeace.withpeace.feature.disablepolicy.navigation.DISABLE_POLICY_ID_ARGUMENT import com.withpeace.withpeace.feature.disablepolicy.navigation.disabledPolicyNavGraph import com.withpeace.withpeace.feature.disablepolicy.navigation.navigateDisabledPolicy import com.withpeace.withpeace.feature.gallery.navigation.galleryNavGraph import com.withpeace.withpeace.feature.gallery.navigation.navigateToGallery -import com.withpeace.withpeace.feature.home.navigation.HOME_ROUTE import com.withpeace.withpeace.feature.home.navigation.homeNavGraph import com.withpeace.withpeace.feature.home.navigation.navigateHome import com.withpeace.withpeace.feature.login.navigation.LOGIN_ROUTE @@ -193,11 +192,22 @@ fun WithpeaceNavHost( ) }, onPolicyClick = { - navController.navigateToPolicyDetail(policyId = it) + navController.navigateToPolicyDetail( + policyId = it, + ) + }, + onPostClick = { // TODO 인스턴스가 존재할 때, argument 로딩안됨 + navController.navigateToPostList( + it.name, + navOptions = navOptions { + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + }, + ) }, - onPostClick = { - navController.navigateToPostList(it.name) - } ) policyDetailNavGraph( onShowSnackBar = { onShowSnackBar(SnackbarState(it)) }, diff --git a/core/domain/src/main/java/com/withpeace/withpeace/core/domain/usecase/GetPolicyFilterUseCase.kt b/core/domain/src/main/java/com/withpeace/withpeace/core/domain/usecase/GetPolicyFilterUseCase.kt new file mode 100644 index 00000000..2e83088b --- /dev/null +++ b/core/domain/src/main/java/com/withpeace/withpeace/core/domain/usecase/GetPolicyFilterUseCase.kt @@ -0,0 +1,14 @@ +package com.withpeace.withpeace.core.domain.usecase + +import com.withpeace.withpeace.core.domain.model.error.CheonghaError +import com.withpeace.withpeace.core.domain.model.policy.PolicyFilters +import com.withpeace.withpeace.core.domain.repository.UserRepository +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetPolicyFilterUseCase @Inject constructor( + private val userRepository: UserRepository, +) { + operator fun invoke(onError: suspend (CheonghaError) -> Unit): Flow = + userRepository.getPolicyFilter(onError) +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/withpeace/withpeace/core/domain/usecase/UpdatePolicyFilterUseCase.kt b/core/domain/src/main/java/com/withpeace/withpeace/core/domain/usecase/UpdatePolicyFilterUseCase.kt new file mode 100644 index 00000000..a1e6af73 --- /dev/null +++ b/core/domain/src/main/java/com/withpeace/withpeace/core/domain/usecase/UpdatePolicyFilterUseCase.kt @@ -0,0 +1,18 @@ +package com.withpeace.withpeace.core.domain.usecase + +import com.withpeace.withpeace.core.domain.model.error.CheonghaError +import com.withpeace.withpeace.core.domain.model.policy.PolicyFilters +import com.withpeace.withpeace.core.domain.repository.UserRepository +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class UpdatePolicyFilterUseCase @Inject constructor( + private val userRepository: UserRepository, +) { + operator fun invoke( + policyFilters: PolicyFilters, + onError: (CheonghaError) -> Unit, + ): Flow { + return userRepository.updatePolicyFilter(policyFilters = policyFilters, onError = onError) + } +} \ No newline at end of file diff --git a/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeScreen.kt b/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeScreen.kt index 140fcfb3..8fc7b70d 100644 --- a/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeScreen.kt +++ b/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeScreen.kt @@ -71,12 +71,13 @@ fun HomeRoute( onPolicyClick: (String) -> Unit, onPostClick: (PostTopicUiModel) -> Unit, ) { - val selectedFilterUiState = viewModel.selectingFilters.collectAsStateWithLifecycle() + val selectingFilterUiState = viewModel.selectingFilters.collectAsStateWithLifecycle() val recentPosts = viewModel.recentPostsUiState.collectAsStateWithLifecycle() val hotPolicies = viewModel.hotPolicyUiState.collectAsStateWithLifecycle() val recommendPolicies = viewModel.recommendPolicyUiState.collectAsStateWithLifecycle() + val completedFilterUiState = viewModel.completedFilters.collectAsStateWithLifecycle() HomeScreen( - selectedFilterUiState = selectedFilterUiState.value, + selectedFilterUiState = selectingFilterUiState.value, onClassificationCheckChanged = viewModel::onCheckClassification, onRegionCheckChanged = viewModel::onCheckRegion, onFilterAllOff = viewModel::onFilterAllOff, @@ -88,6 +89,7 @@ fun HomeRoute( onPolicyClick = onPolicyClick, hotPolicyUiState = hotPolicies.value, recommendPolicyUiState = recommendPolicies.value, + completedFilterState = completedFilterUiState.value, ) } @@ -106,6 +108,7 @@ fun HomeScreen( onCloseFilter: () -> Unit, onPostClick: (PostTopicUiModel) -> Unit, onPolicyClick: (String) -> Unit, + completedFilterState: PolicyFiltersUiModel, ) { Column(modifier = modifier.fillMaxSize()) { HomeHeader( @@ -128,7 +131,7 @@ fun HomeScreen( onPolicyClick = onPolicyClick, hotPolicyUiState = hotPolicyUiState, recommendPolicyUiState = recommendPolicyUiState, - + completedFilterState = completedFilterState, ) } @@ -151,6 +154,7 @@ private fun ScrollSection( onPostClick: (PostTopicUiModel) -> Unit, hotPolicyUiState: HotPolicyUiState, recommendPolicyUiState: RecommendPolicyUiState, + completedFilterState: PolicyFiltersUiModel, ) { val builder = rememberBalloonBuilder { setIsVisibleArrow(false) @@ -249,7 +253,7 @@ private fun ScrollSection( } Spacer(modifier = modifier.height(8.dp)) - FlowRow { + FlowRow(verticalArrangement = Arrangement.spacedBy(8.dp)) { Image( painter = painterResource(id = R.drawable.ic_filter), modifier = modifier @@ -264,20 +268,34 @@ private fun ScrollSection( }, contentDescription = "", ) - // List(5) { //TODO("데이터 변경") - // Spacer(modifier = modifier.width(8.dp)) - // Text( - // text = "#부산", - // style = WithpeaceTheme.typography.Tag, - // color = WithpeaceTheme.colors.MainPurple, - // modifier = modifier - // .background( - // color = WithpeaceTheme.colors.SubPurple, - // shape = RoundedCornerShape(7.dp), - // ) - // .padding(6.dp), - // ) - // } + List(completedFilterState.classifications.size) { //TODO("데이터 변경") + Spacer(modifier = modifier.width(8.dp)) + Text( + text = "#${stringResource(id = completedFilterState.classifications[it].stringResId)}", + style = WithpeaceTheme.typography.Tag, + color = WithpeaceTheme.colors.MainPurple, + modifier = modifier + .background( + color = WithpeaceTheme.colors.SubPurple, + shape = RoundedCornerShape(7.dp), + ) + .padding(6.dp), + ) + } + List(completedFilterState.regions.size) { //TODO("데이터 변경") + Spacer(modifier = modifier.width(8.dp)) + Text( + text = "#${completedFilterState.regions[it].name}", + style = WithpeaceTheme.typography.Tag, + color = WithpeaceTheme.colors.MainPurple, + modifier = modifier + .background( + color = WithpeaceTheme.colors.SubPurple, + shape = RoundedCornerShape(7.dp), + ) + .padding(6.dp), + ) + } } } Spacer(modifier = modifier.height(16.dp)) @@ -319,6 +337,7 @@ private fun ScrollSection( } } } else { + //TODO 실패 UI items(6) { Column( modifier.clickable { @@ -389,6 +408,7 @@ private fun ScrollSection( } } } else { + //TODO 실패 UI items(6) { Column( modifier.clickable { diff --git a/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeViewModel.kt b/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeViewModel.kt index 7dd18756..55794f2b 100644 --- a/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeViewModel.kt +++ b/feature/home/src/main/java/com/withpeace/withpeace/feature/home/HomeViewModel.kt @@ -4,8 +4,10 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.withpeace.withpeace.core.domain.model.policy.PolicyFilters import com.withpeace.withpeace.core.domain.usecase.GetHotPoliciesUseCase +import com.withpeace.withpeace.core.domain.usecase.GetPolicyFilterUseCase import com.withpeace.withpeace.core.domain.usecase.GetRecentPostUseCase import com.withpeace.withpeace.core.domain.usecase.GetRecommendPoliciesUseCase +import com.withpeace.withpeace.core.domain.usecase.UpdatePolicyFilterUseCase import com.withpeace.withpeace.core.ui.policy.ClassificationUiModel import com.withpeace.withpeace.core.ui.policy.RegionUiModel import com.withpeace.withpeace.core.ui.policy.filtersetting.PolicyFiltersUiModel @@ -17,6 +19,7 @@ import com.withpeace.withpeace.feature.home.uistate.RecentPostsUiState import com.withpeace.withpeace.feature.home.uistate.RecommendPolicyUiState import com.withpeace.withpeace.feature.home.uistate.toUiModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -32,6 +35,8 @@ class HomeViewModel @Inject constructor( private val getRecentPostUseCase: GetRecentPostUseCase, private val getRecommendPoliciesUseCase: GetRecommendPoliciesUseCase, private val getHotPoliciesUseCase: GetHotPoliciesUseCase, + private val getPolicyFilterUseCase: GetPolicyFilterUseCase, + private val updatePolicyFilterUseCase: UpdatePolicyFilterUseCase, ) : ViewModel() { private val _recentPostsUiState: MutableStateFlow = MutableStateFlow(RecentPostsUiState.Loading) @@ -53,7 +58,14 @@ class HomeViewModel @Inject constructor( PolicyFiltersUiModel(), ) - private var completedFilters = PolicyFilters() + private val _completedFilters = MutableStateFlow(PolicyFilters()) + val completedFilters: StateFlow = + _completedFilters.map { it.toUiModel() }.stateIn( + scope = viewModelScope, + SharingStarted.WhileSubscribed(), + PolicyFiltersUiModel(), + ) + init { viewModelScope.launch { @@ -70,30 +82,47 @@ class HomeViewModel @Inject constructor( } } } + getRecommendPolicy() + getHotPolicy() launch { - getRecommendPoliciesUseCase( + getPolicyFilterUseCase( onError = { - _recommendPolicyUiState.update { - RecommendPolicyUiState.Failure - } }, ).collect { data -> - _recommendPolicyUiState.update { - RecommendPolicyUiState.Success(data.map { it.toUiModel() }) - } + _selectingFilters.update { data } + _completedFilters.update { data } } } - launch { - getHotPoliciesUseCase( - onError = { - _hotPolicyUiState.update { - HotPolicyUiState.Failure - } - }, - ).collect { data -> + } + } + + private fun CoroutineScope.getHotPolicy() { + launch { + getHotPoliciesUseCase( + onError = { _hotPolicyUiState.update { - HotPolicyUiState.Success(data.map { it.toUiModel() }) + HotPolicyUiState.Failure + } + }, + ).collect { data -> + _hotPolicyUiState.update { + HotPolicyUiState.Success(data.map { it.toUiModel() }) + } + } + } + } + + private fun CoroutineScope.getRecommendPolicy() { + launch { + getRecommendPoliciesUseCase( + onError = { + _recommendPolicyUiState.update { + RecommendPolicyUiState.Failure } + }, + ).collect { data -> + _recommendPolicyUiState.update { + RecommendPolicyUiState.Success(data.map { it.toUiModel() }) } } } @@ -112,12 +141,20 @@ class HomeViewModel @Inject constructor( } fun onCompleteFilter() { - completedFilters = selectingFilters.value.toDomain() - // api + viewModelScope.launch { + updatePolicyFilterUseCase( + policyFilters = selectingFilters.value.toDomain(), + onError = {}, + ).collect { + _completedFilters.update { selectingFilters.value.toDomain() } + this.launch { getHotPolicy() } + this.launch { getRecommendPolicy() } + } + } } fun onCancelFilter() { - _selectingFilters.update { completedFilters } + _selectingFilters.update { completedFilters.value.toDomain() } } fun onFilterAllOff() { diff --git a/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/PostListViewModel.kt b/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/PostListViewModel.kt index eaae2753..25f61017 100644 --- a/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/PostListViewModel.kt +++ b/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/PostListViewModel.kt @@ -34,9 +34,7 @@ class PostListViewModel @Inject constructor( private val _uiEvent = Channel() val uiEvent = _uiEvent.receiveAsFlow() - private val _currentTopic = MutableStateFlow(PostTopicUiModel.entries.find { - it.name == savedStateHandle.get(POST_TYPE_ARGUMENT) - } ?: PostTopicUiModel.FREEDOM) + private val _currentTopic = MutableStateFlow(PostTopicUiModel.FREEDOM) val currentTopic = _currentTopic.asStateFlow() private val _postListPagingFlow = MutableStateFlow(PagingData.empty()) diff --git a/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/navigation/PostListNavigation.kt b/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/navigation/PostListNavigation.kt index 6f2fe952..328ec835 100644 --- a/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/navigation/PostListNavigation.kt +++ b/feature/postlist/src/main/java/com/withpeace/withpeace/feature/postlist/navigation/PostListNavigation.kt @@ -1,5 +1,6 @@ package com.withpeace.withpeace.feature.postlist.navigation +import android.util.Log import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.hilt.navigation.compose.hiltViewModel @@ -39,8 +40,17 @@ fun NavGraphBuilder.postListGraph( enterTransition = { EnterTransition.None }, exitTransition = { ExitTransition.None }, ) { - val deletedId = it.savedStateHandle.get(POST_LIST_DELETED_POST_ID_ARGUMENT) val viewModel: PostListViewModel = hiltViewModel() + val deletedId = it.savedStateHandle.get(POST_LIST_DELETED_POST_ID_ARGUMENT) + + val postType = it.savedStateHandle.get(POST_TYPE_ARGUMENT) + // postType?.let { // recomposition이 안되는건가 + // viewModel.onTopicChanged( + // PostTopicUiModel.entries.find { + // it.name == postType + // } ?: PostTopicUiModel.FREEDOM, + // ) + // } deletedId?.let { id -> viewModel.updateDeletedId(id) }