Skip to content

Commit

Permalink
Merge branch 'feat/naver_map_marker' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim-swit committed Mar 14, 2024
2 parents d253bfc + 1ffd643 commit d0dafd3
Show file tree
Hide file tree
Showing 21 changed files with 408 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import androidx.paging.PagingSource
import androidx.paging.PagingState
import org.gdsc.data.model.RegisteredRestaurantResponse
import org.gdsc.data.network.RestaurantAPI
import org.gdsc.domain.SortType
import org.gdsc.domain.model.request.RestaurantSearchRequest

class RestaurantByMapPagingSource(
private val api: RestaurantAPI,
private val sortType: SortType,
private val restaurantSearchRequest: RestaurantSearchRequest,
): PagingSource<Int, RegisteredRestaurantResponse>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, RegisteredRestaurantResponse> {
Expand All @@ -16,6 +18,7 @@ class RestaurantByMapPagingSource(
val items = api.getRestaurantLocationInfoByMap(
page = page,
size = params.loadSize,
sort = sortType.key,
restaurantSearchRequest = restaurantSearchRequest
)
LoadResult.Page(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ class RestaurantDataSourceImpl @Inject constructor(
) {
RestaurantByMapPagingSource(
restaurantAPI,
sortType,
restaurantSearchRequest
)
}.flow.cachedIn(coroutineScope)
Expand Down
2 changes: 1 addition & 1 deletion data/src/main/java/org/gdsc/data/network/RestaurantAPI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ interface RestaurantAPI {
suspend fun getRestaurantLocationInfoByMap(
@Query("page") page: Int? = null,
@Query("size") size: Int? = null,
@Query("sort") sort: Array<String>? = null,
@Query("sort") sort: String? = null,
@Body restaurantSearchRequest: RestaurantSearchRequest,
): Response<RegisteredRestaurantPaging>

Expand Down
8 changes: 4 additions & 4 deletions domain/src/main/java/org/gdsc/domain/SortType.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.gdsc.domain

enum class SortType(val text: String) {
DISTANCE("가까운 순"),
LIKED("좋아요 순"),
RECENCY("최신 순");
enum class SortType(val text: String, val key: String) {
DISTANCE("가까운 순", "distance,asc"),
LIKED("좋아요 순", ""),
RECENCY("최신 순", "");


companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,18 @@ data class FoodCategoryItem(
else -> R.drawable.ic_etc
}
}

@DrawableRes fun getMarkerIcon(): Int {
return when(this.categoryItem) {
FoodCategory.KOREAN -> R.drawable.ic_marker_korea
FoodCategory.JAPANESE -> R.drawable.ic_marker_japan
FoodCategory.CHINESE -> R.drawable.ic_marker_china
FoodCategory.WESTERN -> R.drawable.ic_marker_foreign
FoodCategory.FUSION -> R.drawable.ic_marker_fusion
FoodCategory.CAFE -> R.drawable.ic_marker_cafe
FoodCategory.BAR -> R.drawable.ic_marker_bar
FoodCategory.ETC -> R.drawable.ic_marker_etc
else -> R.drawable.ic_marker_etc
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import com.naver.maps.geometry.LatLng
import com.naver.maps.map.CameraUpdate
import com.naver.maps.map.MapView
import com.naver.maps.map.Projection
import com.naver.maps.map.overlay.Marker
import com.naver.maps.map.overlay.OverlayImage
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -37,7 +35,6 @@ import org.gdsc.presentation.base.BaseViewHolder
import org.gdsc.presentation.base.ViewHolderBindListener
import org.gdsc.presentation.databinding.FragmentHomeBinding
import org.gdsc.presentation.utils.repeatWhenUiStarted
import org.gdsc.presentation.utils.toDp
import org.gdsc.presentation.view.custom.JmtSpinner


Expand All @@ -55,6 +52,7 @@ class HomeFragment : Fragment(), ViewHolderBindListener {
private val recommendPopularRestaurantTitleAdapter by lazy { RecommendPopularRestaurantTitleAdapter("그룹에서 인기가 많아요") }
private val recommendPopularRestaurantWrapperAdapter by lazy { RecommendPopularRestaurantWrapperAdapter(recommendPopularRestaurantList)}
private val restaurantFilterAdapter by lazy { RestaurantFilterAdapter(this) }
private val restaurantListAdapter by lazy { MapMarkerWithRestaurantsAdatper() }
private val mapMarkerAdapter by lazy { MapMarkerWithRestaurantsAdatper() }
private val emptyAdapter by lazy { EmptyAdapter() }
private lateinit var concatAdapter: ConcatAdapter
Expand All @@ -76,68 +74,27 @@ class HomeFragment : Fragment(), ViewHolderBindListener {
recommendPopularRestaurantTitleAdapter,
recommendPopularRestaurantWrapperAdapter,
restaurantFilterAdapter,
mapMarkerAdapter
restaurantListAdapter
)
} else {
ConcatAdapter(
restaurantFilterAdapter,
mapMarkerAdapter
restaurantListAdapter
)
}
setRecyclerView()
return binding.root
}

fun setRecyclerView() {
private fun setRecyclerView() {
binding.recyclerView.adapter = concatAdapter
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
standardBottomSheetBehavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
fun setBottomSheetRelatedView(isVisible: Boolean) {
binding.bottomSheetHandle.isVisible = isVisible
binding.bottomSheetHandleSpace.isVisible = isVisible
binding.mapOptionContainer.isVisible = isVisible
}

override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_EXPANDED -> {
binding.groupHeader.elevation = 10F
setBottomSheetRelatedView(false)
binding.bottomSheet.background = ResourcesCompat.getDrawable(
resources,
R.color.white,
null
)
}
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
binding.mapOptionContainer.isVisible = true
}

BottomSheetBehavior.STATE_DRAGGING -> {
binding.groupHeader.elevation = 0F
setBottomSheetRelatedView(true)
binding.bottomSheet.background = ResourcesCompat.getDrawable(
resources,
R.drawable.bg_bottom_sheet_top_round,
null
)
}
}
}

override fun onSlide(bottomSheet: View, slideOffset: Float) { }
})

CoroutineScope(Dispatchers.Main).launch {
delay(1000)
if (standardBottomSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED)
standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
}
setRestaurantListBottomSheet()
}

override fun onViewHolderBind(holder: BaseViewHolder<out ViewBinding>, _item: Any) {
Expand Down Expand Up @@ -182,9 +139,19 @@ class HomeFragment : Fragment(), ViewHolderBindListener {
mapView.onCreate(savedInstanceState)

mapView.getMapAsync { naverMap ->

val markerManager = MarkerManager(naverMap)

naverMap.uiSettings.isZoomControlEnabled = false
naverMap.uiSettings.isScaleBarEnabled = false

repeatWhenUiStarted {

viewModel.registeredPagingDataByMap().collect {
mapMarkerAdapter.submitData(it)
}
}

repeatWhenUiStarted {
val location = viewModel.getCurrentLocation()
location?.let {
Expand All @@ -196,43 +163,25 @@ class HomeFragment : Fragment(), ViewHolderBindListener {
naverMap.moveCamera(zoom)
}

mapMarkerAdapter.addLoadStateListener { loadState ->
if (loadState.append.endOfPaginationReached) {
if (mapMarkerAdapter.itemCount < 1) {
concatAdapter.addAdapter(emptyAdapter)
standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
} else {
concatAdapter.removeAdapter(emptyAdapter)
}
setRecyclerView()
}
}
mapMarkerAdapter.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver() {
fun setMark() {
CoroutineScope(Dispatchers.Main).launch {
mapMarkerAdapter.snapshot().items.forEach { data ->
Marker().apply {
position = LatLng(data.y, data.x)
icon = OverlayImage.fromResource(R.drawable.jmt_marker)
map = naverMap
}
}
}
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount)
setMark()
markerManager.updateDataList(mapMarkerAdapter.snapshot().items)
}

override fun onChanged() {
super.onChanged()
setMark()
markerManager.updateDataList(mapMarkerAdapter.snapshot().items)
}

override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount)
markerManager.updateDataList(mapMarkerAdapter.snapshot().items)
}
})
}

binding.mapRefreshBtn.setOnClickListener {

val projection: Projection = naverMap.projection

val topLeft: LatLng = projection.fromScreenLocation(PointF(0F, 0F))
Expand All @@ -242,13 +191,84 @@ class HomeFragment : Fragment(), ViewHolderBindListener {
viewModel.setEndLocation(Location(bottomRight.longitude.toString(), bottomRight.latitude.toString()))
}
}
}


private fun setRestaurantListBottomSheet() {

binding.scrollUpButton.setOnClickListener {
binding.recyclerView.scrollToPosition(0)
}

binding.registRestaurantButton.setOnClickListener {
// TODO : 식당 등록 버튼 클릭 시 동작 정의 필요
Log.d("testLog", "식당 등록 버튼 클릭")
}

restaurantListAdapter.addLoadStateListener { loadState ->
if (loadState.append.endOfPaginationReached) {
if (restaurantListAdapter.itemCount < 1) {
concatAdapter.addAdapter(emptyAdapter)
standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
} else {
concatAdapter.removeAdapter(emptyAdapter)
}
setRecyclerView()
}
}

standardBottomSheetBehavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
fun setBottomSheetRelatedView(isVisible: Boolean) {
binding.bottomSheetHandle.isVisible = isVisible
binding.bottomSheetHandleSpace.isVisible = isVisible
binding.mapOptionContainer.isVisible = isVisible
}

override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_EXPANDED -> {
binding.groupHeader.elevation = 10F
binding.bottomSheetActionButtons.isVisible = true

setBottomSheetRelatedView(false)
binding.bottomSheet.background = ResourcesCompat.getDrawable(
resources,
R.color.white,
null
)
}
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
binding.mapOptionContainer.isVisible = true
}

BottomSheetBehavior.STATE_DRAGGING -> {
binding.groupHeader.elevation = 0F
setBottomSheetRelatedView(true)
binding.bottomSheet.background = ResourcesCompat.getDrawable(
resources,
R.drawable.bg_bottom_sheet_top_round,
null
)
}
}
}

override fun onSlide(bottomSheet: View, slideOffset: Float) { }
})

CoroutineScope(Dispatchers.Main).launch {
delay(1000)
if (standardBottomSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED)
standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
}
}

private fun observeState() {

repeatWhenUiStarted {
viewModel.registeredPagingData().collect {
mapMarkerAdapter.submitData(it)
viewModel.registeredPagingDataByGroup().collect {
restaurantListAdapter.submitData(it)
}
}

Expand All @@ -261,5 +281,4 @@ class HomeFragment : Fragment(), ViewHolderBindListener {
_binding = null
super.onDestroyView()
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package org.gdsc.presentation.view.home

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.map
import com.google.gson.Gson
import com.naver.maps.geometry.LatLng
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand All @@ -21,10 +18,8 @@ import org.gdsc.domain.DrinkPossibility
import org.gdsc.domain.FoodCategory
import org.gdsc.domain.SortType
import org.gdsc.domain.model.Location
import org.gdsc.domain.model.PagingResult
import org.gdsc.domain.model.RegisteredRestaurant
import org.gdsc.domain.usecase.GetRestaurantsByMapUseCase
import org.gdsc.domain.usecase.token.GetAccessTokenUseCase
import org.gdsc.presentation.JmtLocationManager
import javax.inject.Inject

Expand Down Expand Up @@ -96,7 +91,7 @@ class HomeViewModel @Inject constructor(


@OptIn(ExperimentalCoroutinesApi::class)
suspend fun registeredPagingData(): Flow<PagingData<RegisteredRestaurant>> {
suspend fun registeredPagingDataByMap(): Flow<PagingData<RegisteredRestaurant>> {
val location = locationManager.getCurrentLocation() ?: return flowOf(PagingData.empty())
val userLoc = Location(location.longitude.toString(), location.latitude.toString())

Expand All @@ -113,4 +108,20 @@ class HomeViewModel @Inject constructor(
.flatMapLatest { it }
}.cachedIn(viewModelScope)
}

@OptIn(ExperimentalCoroutinesApi::class)
suspend fun registeredPagingDataByGroup(): Flow<PagingData<RegisteredRestaurant>> {

return run {
return@run combine(
userLocationState,
sortTypeState,
foodCategoryState,
drinkPossibilityState
) { userLoc, sortType, foodCategory, drinkPossibility ->
getRestaurantsByMapUseCase(sortType, foodCategory, drinkPossibility, userLoc, null, null)
}.distinctUntilChanged()
.flatMapLatest { it }
}.cachedIn(viewModelScope)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class MapMarkerWithRestaurantsAdatper
oldItem: RegisteredRestaurant,
newItem: RegisteredRestaurant
): Boolean {
return oldItem == newItem
return oldItem.id == newItem.id
}
}
}
Expand Down
Loading

0 comments on commit d0dafd3

Please sign in to comment.