diff --git a/app/build.gradle b/app/build.gradle index 5014b672..826a20fa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { applicationId "com.sopt.geonppang" minSdk 28 targetSdk 34 - versionCode 1 + versionCode 5 versionName "1.0.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/sopt/geonppang/data/repository/BakeryListPagingRepository.kt b/app/src/main/java/com/sopt/geonppang/data/repository/BakeryListPagingRepository.kt index 96df0f13..0f4557a5 100644 --- a/app/src/main/java/com/sopt/geonppang/data/repository/BakeryListPagingRepository.kt +++ b/app/src/main/java/com/sopt/geonppang/data/repository/BakeryListPagingRepository.kt @@ -16,11 +16,12 @@ class BakeryListPagingRepository @Inject constructor( config = PagingConfig( pageSize = PAGE_SIZE, enablePlaceholders = false, + initialLoadSize = PAGE_SIZE ), pagingSourceFactory = { BakeryListPagingSource( bakeryService = bakeryService, - sort = bakeryListFilterType.sortType.sortName, + sort = bakeryListFilterType.sortType.sortType, personal = bakeryListFilterType.isPersonalFilterApplied == true, isHard = bakeryListFilterType.isHard, isBrunch = bakeryListFilterType.isBrunch, diff --git a/app/src/main/java/com/sopt/geonppang/domain/model/Profile.kt b/app/src/main/java/com/sopt/geonppang/domain/model/Profile.kt index bb0e8da7..ec65011b 100644 --- a/app/src/main/java/com/sopt/geonppang/domain/model/Profile.kt +++ b/app/src/main/java/com/sopt/geonppang/domain/model/Profile.kt @@ -3,7 +3,7 @@ package com.sopt.geonppang.domain.model import com.sopt.geonppang.presentation.type.BreadFilterType data class Profile( - var memberNickname: String, - var mainPurpose: String, - var breadTypeList: List + var memberNickname: String = "", + var mainPurpose: String = "", + var breadTypeList: List = listOf() ) diff --git a/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListFragment.kt b/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListFragment.kt index fbc6d321..5ab5d2f4 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListFragment.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListFragment.kt @@ -39,12 +39,12 @@ import kotlinx.coroutines.launch class BakeryListFragment : BindingFragment(R.layout.fragment_bakery_list), BakerySortTypeListener { - private val viewModel: BakeryListViewModel by viewModels() + private val bakeryListViewModel: BakeryListViewModel by viewModels() private lateinit var bakeryAdapter: BakeryListPagingDataAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.viewModel = viewModel + binding.viewModel = bakeryListViewModel binding.lifecycleOwner = this.viewLifecycleOwner initLayout() @@ -53,14 +53,21 @@ class BakeryListFragment : } private fun initLayout() { - val getUserRole = viewModel.userRoleType.value == UserRoleType.NONE_MEMBER.name - if (!getUserRole) - viewModel.getUserFilter() bakeryAdapter = BakeryListPagingDataAdapter(::moveToDetail, ::initBreadTypeChips) binding.rvBakeryList.apply { adapter = bakeryAdapter addItemDecoration(CustomItemDecoration(requireContext())) } + + val isFilterSelectedMember = + bakeryListViewModel.userRoleType.value == UserRoleType.FILTER_SELECTED_MEMBER.name + + with(binding) { + includeHomeSpeechBubble.root.setVisibility(bakeryListViewModel.userRoleType.value == UserRoleType.FILTER_UNSELECTED_MEMBER.name) + checkBakeryListMyFilter.isEnabled = isFilterSelectedMember + checkBakeryListMyFilter.isChecked = isFilterSelectedMember + layoutBakeryListMyFiltaerApply.isEnabled = isFilterSelectedMember + } } private fun addListeners() { @@ -84,25 +91,28 @@ class BakeryListFragment : // 비회원, 회원 분기처리 binding.ivBakeryListFilter.setOnClickListener { - val getUserRole = viewModel.userRoleType.value == UserRoleType.NONE_MEMBER.name - AmplitudeUtils.trackEvent(START_FILTER_LIST) - if (getUserRole) + val isMember = bakeryListViewModel.userRoleType.value == UserRoleType.NONE_MEMBER.name + + if (isMember) { showLoginNeedDialog() - else + } else { moveToFilter() + AmplitudeUtils.trackEvent(START_FILTER_LIST) + } } } private fun collectData() { - viewModel.bakeryListFilterType.flowWithLifecycle(viewLifecycleOwner.lifecycle).onEach { - lifecycleScope.launch { - viewModel.fetchBakeryListPagingData().collectLatest { - bakeryAdapter.submitData(it) + bakeryListViewModel.bakeryListFilterType.flowWithLifecycle(viewLifecycleOwner.lifecycle) + .onEach { + lifecycleScope.launch { + bakeryListViewModel.fetchBakeryListPagingData().collectLatest { + bakeryAdapter.submitData(it) + } } - } - }.launchIn(viewLifecycleOwner.lifecycleScope) + }.launchIn(viewLifecycleOwner.lifecycleScope) - viewModel.bakeryListFilterType + bakeryListViewModel.bakeryListFilterType .map { it.isPersonalFilterApplied } .distinctUntilChanged() .flowWithLifecycle(viewLifecycleOwner.lifecycle).onEach { isPersonalFilterApplied -> @@ -111,7 +121,7 @@ class BakeryListFragment : } }.launchIn(viewLifecycleOwner.lifecycleScope) - viewModel.bakeryListFilterType + bakeryListViewModel.bakeryListFilterType .map { listOfNotNull( if (it.isHard) BakeryCategoryType.HARD.titleString else null, @@ -131,17 +141,6 @@ class BakeryListFragment : } } .launchIn(viewLifecycleOwner.lifecycleScope) - - viewModel.isFilterSelected.flowWithLifecycle(lifecycle).onEach { isFilterSelected -> - binding.includeHomeSpeechBubble.root.setVisibility(!isFilterSelected) - binding.checkBakeryListMyFilter.isEnabled = isFilterSelected - binding.layoutBakeryListMyFiltaerApply.isEnabled = isFilterSelected - }.launchIn(viewLifecycleOwner.lifecycleScope) - - viewModel.userRoleType.flowWithLifecycle(viewLifecycleOwner.lifecycle).onEach { - if (it == UserRoleType.NONE_MEMBER.name) - binding.checkBakeryListMyFilter.isEnabled = false - }.launchIn(viewLifecycleOwner.lifecycleScope) } private fun initBreadTypeChips(chipGroup: ChipGroup, breadFilterList: List) { @@ -180,7 +179,10 @@ class BakeryListFragment : // BakeryListSortDialog로 현재 정렬 정보 전달 bakeryListSortBottomSheetDialog.arguments = Bundle().apply { - putString("bakerySortType", viewModel.bakeryListFilterType.value.sortType.sortType) + putString( + "bakerySortType", + bakeryListViewModel.bakeryListFilterType.value.sortType.sortType + ) } bakeryListSortBottomSheetDialog.setDataListener(this) bakeryListSortBottomSheetDialog.show(parentFragmentManager, "bakeryListSortDialog") @@ -195,7 +197,7 @@ class BakeryListFragment : // BakeryListDialog에서 부터 받아온 데이터를 처리 override fun onBakerySortTypeSelected(bakerySortType: BakerySortType) { - viewModel.setBakerySortType(bakerySortType) + bakeryListViewModel.setBakerySortType(bakerySortType) } companion object { diff --git a/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListViewModel.kt b/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListViewModel.kt index ab71b59f..e4e7a901 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListViewModel.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/bakeryList/BakeryListViewModel.kt @@ -8,7 +8,6 @@ import com.sopt.geonppang.data.datasource.local.GPDataSource import com.sopt.geonppang.data.repository.BakeryListPagingRepository import com.sopt.geonppang.domain.model.BakeryInformation import com.sopt.geonppang.domain.model.BakeryListFilterType -import com.sopt.geonppang.domain.repository.GetUserFilterRepository import com.sopt.geonppang.presentation.type.BakeryCategoryType import com.sopt.geonppang.presentation.type.BakerySortType import dagger.hilt.android.lifecycle.HiltViewModel @@ -16,21 +15,16 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject @HiltViewModel class BakeryListViewModel @Inject constructor( private val bakeryListPagingRepository: BakeryListPagingRepository, - private val getUserFilterRepository: GetUserFilterRepository, private val gpDataSource: GPDataSource ) : ViewModel() { private var _bakeryListFilterState = MutableStateFlow(BakeryListFilterType()) val bakeryListFilterType get() = _bakeryListFilterState.asStateFlow() - private val _isFilterSelected = MutableStateFlow(true) - val isFilterSelected get() = _isFilterSelected.asStateFlow() private val _userRoleType = MutableStateFlow(gpDataSource.userRoleType) val userRoleType get() = _userRoleType @@ -57,32 +51,12 @@ class BakeryListViewModel @Inject constructor( } } - // TODO: dana 필터 적용 상태(앱 내 유저 상태) 어떻게 관리할 건지 고민 - private fun setInitPersonalFilterState() { - _bakeryListFilterState.update { - it.copy(isPersonalFilterApplied = _isFilterSelected.value) - } - } - fun fetchBakeryListPagingData(): Flow> { return bakeryListPagingRepository.fetchBakeryList( bakeryListFilterType = bakeryListFilterType.value ).cachedIn(viewModelScope) } - fun getUserFilter() { - viewModelScope.launch { - getUserFilterRepository.getUserFilter() - .onSuccess { userFilterInfo -> - _isFilterSelected.value = (userFilterInfo.mainPurpose != NONE) - setInitPersonalFilterState() - } - .onFailure { throwable -> - Timber.e(throwable.message) - } - } - } - companion object { const val NONE = "NONE" } diff --git a/app/src/main/java/com/sopt/geonppang/presentation/home/HomeFragment.kt b/app/src/main/java/com/sopt/geonppang/presentation/home/HomeFragment.kt index 2b69b4bd..3b2f005d 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/home/HomeFragment.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/home/HomeFragment.kt @@ -94,7 +94,7 @@ class HomeFragment : BindingFragment(R.layout.fragment_home viewModel.userRoleType.flowWithLifecycle(lifecycle).onEach { when (it) { UserRoleType.NONE_MEMBER.name -> { - viewModel.setNickName("별사탕") + viewModel.setNickName(getString(R.string.user_role_type_member_none_title)) } UserRoleType.FILTER_SELECTED_MEMBER.name -> { diff --git a/app/src/main/java/com/sopt/geonppang/presentation/home/HomeViewModel.kt b/app/src/main/java/com/sopt/geonppang/presentation/home/HomeViewModel.kt index 842b8178..85aa728f 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/home/HomeViewModel.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/home/HomeViewModel.kt @@ -34,7 +34,7 @@ class HomeViewModel @Inject constructor( private val _userRoleType = MutableStateFlow(gpDataSource.userRoleType) val userRoleType get() = _userRoleType.asStateFlow() - // TODO: 무슨 회원인지 로컬 에서 관리 + // TODO: 무슨 회원인지 로컬에서 관리 init { // 비회원이 아닌 경우에만 호출 되도록 if (_userRoleType.value != UserRoleType.NONE_MEMBER.name) { diff --git a/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageFragment.kt b/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageFragment.kt index fbf21d6f..6254a49b 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageFragment.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageFragment.kt @@ -47,7 +47,7 @@ class MyPageFragment : BindingFragment(R.layout.fragment_ private fun initLayout() { if (viewModel.userRoleType.value == UserRoleType.NONE_MEMBER.name) - viewModel.fetchNoneMemberProfileInfo() + viewModel.setNoneMemberNickname(getString(R.string.user_role_type_member_none_title)) else viewModel.fetchProfileInfo() binding.includeMyPageSpeechBubble.ivSpeechBubble.setBackgroundResource(R.drawable.background_left_speech_bubble) diff --git a/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageViewModel.kt b/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageViewModel.kt index 6c51a5f9..fb8d7d23 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageViewModel.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/myPage/MyPageViewModel.kt @@ -12,6 +12,7 @@ import com.sopt.geonppang.util.UiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -20,7 +21,7 @@ class MyPageViewModel @Inject constructor( private val gpDataSource: GPDataSource, private val myPageRepository: MyPageRepository, ) : ViewModel() { - private var _profileInfo = MutableStateFlow(null) + private var _profileInfo = MutableStateFlow(Profile()) val profileInfo get() = _profileInfo.asStateFlow() private var _isFilterSelected = MutableStateFlow(true) val isFilterSelected = _isFilterSelected.asStateFlow() @@ -47,8 +48,12 @@ class MyPageViewModel @Inject constructor( } } - fun fetchNoneMemberProfileInfo() { - _profileInfo.value = Profile("별사탕", "", listOf()) + fun setNoneMemberNickname(defaultNoneMemberNickName: String) { + _profileInfo.update { + it.copy( + memberNickname = defaultNoneMemberNickName + ) + } } fun fetchMyPageReviewList() { @@ -74,7 +79,7 @@ class MyPageViewModel @Inject constructor( } fun setMainPurposeTitle(): Int? { - return when (profileInfo.value?.mainPurpose) { + return when (profileInfo.value.mainPurpose) { MainPurposeFilterType.DIET.name -> MainPurposeFilterType.DIET.titleRes MainPurposeFilterType.HEALTH.name -> MainPurposeFilterType.HEALTH.titleRes MainPurposeFilterType.VEGAN.name -> MainPurposeFilterType.VEGAN.titleRes diff --git a/app/src/main/res/layout/fragment_bakery_list.xml b/app/src/main/res/layout/fragment_bakery_list.xml index d60c4bf7..bc680647 100644 --- a/app/src/main/res/layout/fragment_bakery_list.xml +++ b/app/src/main/res/layout/fragment_bakery_list.xml @@ -163,7 +163,6 @@ style="@style/Style.CheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:checked="@{viewModel.bakeryListFilterType.isPersonalFilterApplied()}" android:onClick="@{() -> viewModel.setIsPersonalFilterAppliedState()}" /> 신고하기 - 신고가 완료됐어요! + 신고가 완료됐어요!탕 + + + 별사탕 \ No newline at end of file diff --git a/build.gradle b/build.gradle index c6c6a9c5..739f4b66 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" - classpath 'com.google.gms:google-services:4.3.15' + classpath 'com.google.gms:google-services:4.4.1' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9' } }