diff --git a/common/src/main/kotlin/us/wedemy/eggeum/android/common/ui/BaseRecyclerViewAdapter.kt b/common/src/main/kotlin/us/wedemy/eggeum/android/common/ui/BaseRecyclerViewAdapter.kt index 73e2ae32..cb7c71b0 100644 --- a/common/src/main/kotlin/us/wedemy/eggeum/android/common/ui/BaseRecyclerViewAdapter.kt +++ b/common/src/main/kotlin/us/wedemy/eggeum/android/common/ui/BaseRecyclerViewAdapter.kt @@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding abstract class BaseRecyclerViewAdapter : RecyclerView.Adapter>() { - private val items = mutableListOf() + protected val items = mutableListOf() override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { holder.bind(items[position]) diff --git a/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSource.kt b/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSource.kt index 133bc619..28f326ab 100644 --- a/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSource.kt +++ b/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSource.kt @@ -17,5 +17,5 @@ public interface PlaceLocalDataSource { public suspend fun deleteRecentSearchPlace(placeEntity: PlaceEntity) - public fun getRecentSearchPlaceList(name: String?): Flow> + public fun getRecentSearchPlaceList(): Flow> } diff --git a/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSourceImpl.kt b/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSourceImpl.kt index ded64728..09e89d8e 100644 --- a/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSourceImpl.kt +++ b/data/src/main/kotlin/us/wedemy/eggeum/android/data/datasource/place/local/PlaceLocalDataSourceImpl.kt @@ -29,7 +29,7 @@ public class PlaceLocalDataSourceImpl @Inject constructor( placeSearchDatabase.placeSearchDao().deleteRecentSearchPlace(placeEntity.toModel()) } - override fun getRecentSearchPlaceList(name: String?): Flow> { + override fun getRecentSearchPlaceList(): Flow> { val pagingSourceFactory = { placeSearchDatabase.placeSearchDao().getRecentSearchPlaceList() } diff --git a/data/src/main/kotlin/us/wedemy/eggeum/android/data/repository/PlaceRepositoryImpl.kt b/data/src/main/kotlin/us/wedemy/eggeum/android/data/repository/PlaceRepositoryImpl.kt index b5c85407..d30275f5 100644 --- a/data/src/main/kotlin/us/wedemy/eggeum/android/data/repository/PlaceRepositoryImpl.kt +++ b/data/src/main/kotlin/us/wedemy/eggeum/android/data/repository/PlaceRepositoryImpl.kt @@ -70,8 +70,8 @@ public class PlaceRepositoryImpl @Inject constructor( localDataSource.deleteRecentSearchPlace(placeEntity) } - override fun getRecentSearchPlaceList(name: String?): Flow> { - return localDataSource.getRecentSearchPlaceList(name).map { pagingData -> + override fun getRecentSearchPlaceList(): Flow> { + return localDataSource.getRecentSearchPlaceList().map { pagingData -> pagingData.map { place -> place.toEntity() } diff --git a/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/repository/PlaceRepository.kt b/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/repository/PlaceRepository.kt index c99a90bd..eb329556 100644 --- a/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/repository/PlaceRepository.kt +++ b/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/repository/PlaceRepository.kt @@ -73,8 +73,6 @@ public interface PlaceRepository { /** * 최근 검색 장소 조회 - * - * @param name 장소 이름 */ - public fun getRecentSearchPlaceList(name: String?): Flow> + public fun getRecentSearchPlaceList(): Flow> } diff --git a/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/usecase/PlaceUseCase.kt b/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/usecase/PlaceUseCase.kt index a96fa7df..cfd44736 100644 --- a/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/usecase/PlaceUseCase.kt +++ b/domain/src/main/kotlin/us/wedemy/eggeum/android/domain/usecase/PlaceUseCase.kt @@ -36,6 +36,28 @@ public class GetPlaceListUseCase @Inject constructor( } } +@Singleton +public class GetSearchPlaceListUseCase @Inject constructor( + private val repository: PlaceRepository, +) { + public operator fun invoke(query: String? = null): Flow> { + return if (query.isNullOrEmpty()) { + repository.getRecentSearchPlaceList() + } else { + repository.getPlaceList(search = query) + } + } +} + +@Singleton +public class GetRecentSearchPlaceListUseCase @Inject constructor( + private val repository: PlaceRepository, +) { + public operator fun invoke(): Flow> { + return repository.getRecentSearchPlaceList() + } +} + @Singleton public class UpsertPlaceUseCase @Inject constructor( private val repository: PlaceRepository, @@ -63,12 +85,3 @@ public class DeleteRecentSearchPlaceUseCase @Inject constructor( repository.deleteRecentSearchPlace(placeEntity) } } - -@Singleton -public class GetRecentSearchPlaceListUseCase @Inject constructor( - private val repository: PlaceRepository, -) { - public operator fun invoke(name: String? = null): Flow> { - return repository.getRecentSearchPlaceList(name) - } -} diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/NewCafeAdapter.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/NewCafeAdapter.kt index d3a80a8f..97c8e60f 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/NewCafeAdapter.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/NewCafeAdapter.kt @@ -10,6 +10,7 @@ package us.wedemy.eggeum.android.main.ui.adapter import android.view.ViewGroup import us.wedemy.eggeum.android.common.extension.layoutInflater import us.wedemy.eggeum.android.common.ui.BaseRecyclerViewAdapter +import us.wedemy.eggeum.android.common.ui.BaseViewHolder import us.wedemy.eggeum.android.domain.model.place.PlaceEntity import us.wedemy.eggeum.android.main.databinding.ItemNewCafeBinding import us.wedemy.eggeum.android.main.ui.adapter.listener.SearchCafeClickListener @@ -19,5 +20,13 @@ class NewCafeAdapter(private val clickListener: SearchCafeClickListener) : BaseRecyclerViewAdapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = - NewCafeViewHolder(ItemNewCafeBinding.inflate(parent.context.layoutInflater, parent, false), clickListener) + NewCafeViewHolder(ItemNewCafeBinding.inflate(parent.context.layoutInflater, parent, false)) + + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + super.onBindViewHolder(holder, position) + val cafeItem = items[position] + holder.itemView.setOnClickListener { + clickListener.onItemClick(cafeItem) + } + } } diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/SearchCafeAdapter.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/SearchCafeAdapter.kt index a79e3f1e..14f58c01 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/SearchCafeAdapter.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/SearchCafeAdapter.kt @@ -20,15 +20,15 @@ class SearchCafeAdapter(private val clickListener: SearchCafeClickListener? = nu PagingDataAdapter(PlaceEntityDiffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = - SearchCafeViewHolder( - ItemSearchCafeLocationBinding.inflate(LayoutInflater.from(parent.context), parent, false), - clickListener, - ) + SearchCafeViewHolder(ItemSearchCafeLocationBinding.inflate(LayoutInflater.from(parent.context), parent, false)) override fun onBindViewHolder(holder: SearchCafeViewHolder, position: Int) { val cafeItem = getItem(position) cafeItem?.let { cafe -> holder.bind(cafe) + holder.itemView.setOnClickListener { + clickListener?.onItemClick(cafeItem) + } } } diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/listener/SearchCafeClickListener.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/listener/SearchCafeClickListener.kt index 2ac3baf6..05e88d95 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/listener/SearchCafeClickListener.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/listener/SearchCafeClickListener.kt @@ -7,6 +7,8 @@ package us.wedemy.eggeum.android.main.ui.adapter.listener +import us.wedemy.eggeum.android.domain.model.place.PlaceEntity + interface SearchCafeClickListener { - fun onItemClick(position: Int) + fun onItemClick(item: PlaceEntity) } diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/NewCafeViewHolder.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/NewCafeViewHolder.kt index 00194238..837ec6b0 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/NewCafeViewHolder.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/NewCafeViewHolder.kt @@ -10,18 +10,8 @@ package us.wedemy.eggeum.android.main.ui.adapter.viewholder import us.wedemy.eggeum.android.common.ui.BaseViewHolder import us.wedemy.eggeum.android.domain.model.place.PlaceEntity import us.wedemy.eggeum.android.main.databinding.ItemNewCafeBinding -import us.wedemy.eggeum.android.main.ui.adapter.listener.SearchCafeClickListener -class NewCafeViewHolder( - binding: ItemNewCafeBinding, - clickListener: SearchCafeClickListener? = null, -) : BaseViewHolder(binding) { - - init { - binding.root.setOnClickListener { - clickListener?.onItemClick(adapterPosition) - } - } +class NewCafeViewHolder(binding: ItemNewCafeBinding) : BaseViewHolder(binding) { override fun bind(item: PlaceEntity) { binding.apply { diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/SearchCafeViewHolder.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/SearchCafeViewHolder.kt index 3148b3e3..b4d9fcd2 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/SearchCafeViewHolder.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/adapter/viewholder/SearchCafeViewHolder.kt @@ -10,18 +10,9 @@ package us.wedemy.eggeum.android.main.ui.adapter.viewholder import us.wedemy.eggeum.android.common.ui.BaseViewHolder import us.wedemy.eggeum.android.domain.model.place.PlaceEntity import us.wedemy.eggeum.android.main.databinding.ItemSearchCafeLocationBinding -import us.wedemy.eggeum.android.main.ui.adapter.listener.SearchCafeClickListener -class SearchCafeViewHolder( - binding: ItemSearchCafeLocationBinding, - clickListener: SearchCafeClickListener? = null, -) : BaseViewHolder(binding) { - - init { - binding.root.setOnClickListener { - clickListener?.onItemClick(adapterPosition) - } - } +class SearchCafeViewHolder(binding: ItemSearchCafeLocationBinding) : + BaseViewHolder(binding) { override fun bind(item: PlaceEntity) { binding.tvCafeSearchLocation.text = item.name diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/home/HomeFragment.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/home/HomeFragment.kt index 5d6b7077..a39c86fb 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/home/HomeFragment.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/home/HomeFragment.kt @@ -9,6 +9,7 @@ package us.wedemy.eggeum.android.main.ui.home import android.os.Bundle import android.view.View +import android.widget.Toast import androidx.fragment.app.viewModels import androidx.paging.LoadState import com.google.android.material.tabs.TabLayout @@ -21,6 +22,7 @@ import us.wedemy.eggeum.android.common.extension.repeatOnStarted import us.wedemy.eggeum.android.common.ui.BaseFragment import us.wedemy.eggeum.android.common.util.HorizontalSpacingItemDecoration import us.wedemy.eggeum.android.design.R +import us.wedemy.eggeum.android.domain.model.place.PlaceEntity import us.wedemy.eggeum.android.main.databinding.FragmentHomeBinding import us.wedemy.eggeum.android.main.ui.adapter.SearchCafeAdapter import us.wedemy.eggeum.android.main.ui.adapter.NewCafeAdapter @@ -40,8 +42,8 @@ class HomeFragment : BaseFragment() { private val newCafeAdapter by lazy { NewCafeAdapter( object : SearchCafeClickListener { - override fun onItemClick(position: Int) { - // TODO 화면 전환 클릭 이벤트 리스터 구현 + override fun onItemClick(item: PlaceEntity) { + Toast.makeText(requireContext(), "${item.name}을 선택했습니다.", Toast.LENGTH_SHORT).show() } }, ) diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/search/SearchCafeFragment.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/search/SearchCafeFragment.kt index 5453e03f..73e42312 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/search/SearchCafeFragment.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/ui/search/SearchCafeFragment.kt @@ -11,6 +11,7 @@ import android.os.Bundle import android.view.View import android.widget.Toast import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -19,6 +20,7 @@ import us.wedemy.eggeum.android.common.extension.repeatOnStarted import us.wedemy.eggeum.android.common.extension.textChangesAsFlow import us.wedemy.eggeum.android.common.ui.BaseFragment import us.wedemy.eggeum.android.design.R +import us.wedemy.eggeum.android.domain.model.place.PlaceEntity import us.wedemy.eggeum.android.main.databinding.FragmentSearchCafeBinding import us.wedemy.eggeum.android.main.ui.adapter.SearchCafeAdapter import us.wedemy.eggeum.android.main.ui.adapter.listener.SearchCafeClickListener @@ -33,8 +35,12 @@ class SearchCafeFragment : BaseFragment() { private val searchCafeAdapter by lazy { SearchCafeAdapter( object : SearchCafeClickListener { - override fun onItemClick(position: Int) { - Toast.makeText(requireContext(), "${position}번째 장소를 저장했습니다.", Toast.LENGTH_SHORT).show() + override fun onItemClick(item: PlaceEntity) { + Toast.makeText(requireContext(), "${item.name}을 저장했습니다.", Toast.LENGTH_SHORT).show() + viewModel.insertRecentSearchPlace(item) + +// val action = SearchCafeFragmentDirections.actionFragmentSearchCafeToFragmentCafeDetail() +// findNavController().safeNavigate(action) } }, ) @@ -43,10 +49,8 @@ class SearchCafeFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initView() + initListener() initObserver() - -// val action = SearchCafeFragmentDirections.actionFragmentSearchCafeToFragmentCafeDetail() -// findNavController().safeNavigate(action) } private fun initView() { @@ -57,6 +61,14 @@ class SearchCafeFragment : BaseFragment() { } } + private fun initListener() { + binding.tilSearchCafe.setStartIconOnClickListener { + if (!findNavController().navigateUp()) { + requireActivity().finish() + } + } + } + private fun initObserver() { repeatOnStarted { launch { diff --git a/main/src/main/kotlin/us/wedemy/eggeum/android/main/viewmodel/SearchCafeViewModel.kt b/main/src/main/kotlin/us/wedemy/eggeum/android/main/viewmodel/SearchCafeViewModel.kt index 349fd8ee..091b2a3d 100644 --- a/main/src/main/kotlin/us/wedemy/eggeum/android/main/viewmodel/SearchCafeViewModel.kt +++ b/main/src/main/kotlin/us/wedemy/eggeum/android/main/viewmodel/SearchCafeViewModel.kt @@ -19,28 +19,22 @@ import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch import us.wedemy.eggeum.android.common.util.SaveableMutableStateFlow import us.wedemy.eggeum.android.common.util.getMutableStateFlow import us.wedemy.eggeum.android.domain.model.place.PlaceEntity import us.wedemy.eggeum.android.domain.usecase.DeleteRecentSearchPlaceUseCase -import us.wedemy.eggeum.android.domain.usecase.GetPlaceListUseCase -import us.wedemy.eggeum.android.domain.usecase.GetRecentSearchPlaceListUseCase +import us.wedemy.eggeum.android.domain.usecase.GetSearchPlaceListUseCase import us.wedemy.eggeum.android.domain.usecase.InsertRecentSearchPlaceUseCase @HiltViewModel class SearchCafeViewModel @Inject constructor( - getPlaceListUseCase: GetPlaceListUseCase, - getRecentSearchPlaceListUseCase: GetRecentSearchPlaceListUseCase, + getSearchPlaceListUseCase: GetSearchPlaceListUseCase, private val insertRecentSearchPlaceUseCase: InsertRecentSearchPlaceUseCase, private val deleteRecentSearchPlaceUseCase: DeleteRecentSearchPlaceUseCase, savedStateHandle: SavedStateHandle, ) : ViewModel() { - val recentSearchPlaceList = getRecentSearchPlaceListUseCase().cachedIn(viewModelScope) - private val _searchQuery: SaveableMutableStateFlow = savedStateHandle.getMutableStateFlow(KEY_CAFE_NAME, "") val searchQuery = _searchQuery.asStateFlow() @@ -48,15 +42,13 @@ class SearchCafeViewModel @Inject constructor( @OptIn(FlowPreview::class) val debouncedSearchQuery: Flow = searchQuery .debounce(SEARCH_TIME_DELAY) - .filter { it.isNotEmpty() } .distinctUntilChanged() @OptIn(ExperimentalCoroutinesApi::class) val searchPlaceList: Flow> = - debouncedSearchQuery.filterNotNull() - .flatMapLatest { query -> - getPlaceListUseCase(query) - } + debouncedSearchQuery.flatMapLatest { query -> + getSearchPlaceListUseCase(query) + } .cachedIn(viewModelScope) fun setSearchQuery(query: String) {