From 907f2844ccfdbca02cd6f424f9cf2313e63367b1 Mon Sep 17 00:00:00 2001 From: jihyunniiii Date: Wed, 10 Jan 2024 21:22:36 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[feat]=20#94=20=ED=95=80=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20(=EC=A2=8C=ED=91=9C=20=ED=95=84=ED=84=B0=EB=A7=81?= =?UTF-8?q?=20x)=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datasource/remote/MapRemoteDataSource.kt | 8 ++++++ .../remote/MapRemoteDataSourceImpl.kt | 17 ++++++++++++ .../model/remote/request/RequestPinListDto.kt | 10 +++++++ .../remote/response/ResponsePinListDto.kt | 27 +++++++++++++++++++ .../data/repository/MapRepositoryImpl.kt | 27 +++++++++++++++++++ .../sopt/pingle/data/service/MapService.kt | 23 ++++++++++++++++ .../org/sopt/pingle/di/DataSourceModule.kt | 6 +++++ .../org/sopt/pingle/di/RepositoryModule.kt | 6 +++++ .../java/org/sopt/pingle/di/ServiceModule.kt | 7 +++++ .../java/org/sopt/pingle/di/UseCaseModule.kt | 7 +++++ .../pingle/domain/repository/MapRepository.kt | 8 ++++++ .../GetPinListWithoutFilteringUseCase.kt | 12 +++++++++ 12 files changed, 158 insertions(+) create mode 100644 app/src/main/java/org/sopt/pingle/data/datasource/remote/MapRemoteDataSource.kt create mode 100644 app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/MapRemoteDataSourceImpl.kt create mode 100644 app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPinListDto.kt create mode 100644 app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePinListDto.kt create mode 100644 app/src/main/java/org/sopt/pingle/data/repository/MapRepositoryImpl.kt create mode 100644 app/src/main/java/org/sopt/pingle/data/service/MapService.kt create mode 100644 app/src/main/java/org/sopt/pingle/domain/repository/MapRepository.kt create mode 100644 app/src/main/java/org/sopt/pingle/domain/usecase/GetPinListWithoutFilteringUseCase.kt diff --git a/app/src/main/java/org/sopt/pingle/data/datasource/remote/MapRemoteDataSource.kt b/app/src/main/java/org/sopt/pingle/data/datasource/remote/MapRemoteDataSource.kt new file mode 100644 index 00000000..30cefd5d --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/datasource/remote/MapRemoteDataSource.kt @@ -0,0 +1,8 @@ +package org.sopt.pingle.data.datasource.remote + +import org.sopt.pingle.data.model.remote.response.ResponsePinListDto +import org.sopt.pingle.util.base.BaseResponse + +interface MapRemoteDataSource { + suspend fun getPinListWithoutFiltering(teamId: Long, category: String?): BaseResponse> +} diff --git a/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/MapRemoteDataSourceImpl.kt b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/MapRemoteDataSourceImpl.kt new file mode 100644 index 00000000..90a81912 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/MapRemoteDataSourceImpl.kt @@ -0,0 +1,17 @@ +package org.sopt.pingle.data.datasourceimpl.remote + +import javax.inject.Inject +import org.sopt.pingle.data.datasource.remote.MapRemoteDataSource +import org.sopt.pingle.data.model.remote.response.ResponsePinListDto +import org.sopt.pingle.data.service.MapService +import org.sopt.pingle.util.base.BaseResponse + +class MapRemoteDataSourceImpl @Inject constructor( + private val mapService: MapService +) : MapRemoteDataSource { + override suspend fun getPinListWithoutFiltering( + teamId: Long, + category: String? + ): BaseResponse> = + mapService.getPinListWithoutFiltering(teamId = teamId, category = category) +} diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPinListDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPinListDto.kt new file mode 100644 index 00000000..ad936bd6 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPinListDto.kt @@ -0,0 +1,10 @@ +package org.sopt.pingle.data.model.remote.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RequestPinListDto( + @SerialName("category") + val category: String? +) diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePinListDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePinListDto.kt new file mode 100644 index 00000000..d7db3661 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePinListDto.kt @@ -0,0 +1,27 @@ +package org.sopt.pingle.data.model.remote.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.sopt.pingle.domain.model.PinEntity + +@Serializable +data class ResponsePinListDto( + @SerialName("id") + val id: Long, + @SerialName("x") + val x: Double, + @SerialName("y") + val y: Double, + @SerialName("category") + val category: String, + @SerialName("meetingCount") + val meetingCount: Int +) { + fun toPinEntity() = PinEntity( + id = this.id, + x = this.x, + y = this.y, + category = this.category, + meetingCount = this.meetingCount + ) +} diff --git a/app/src/main/java/org/sopt/pingle/data/repository/MapRepositoryImpl.kt b/app/src/main/java/org/sopt/pingle/data/repository/MapRepositoryImpl.kt new file mode 100644 index 00000000..1ab94186 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/repository/MapRepositoryImpl.kt @@ -0,0 +1,27 @@ +package org.sopt.pingle.data.repository + +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import org.sopt.pingle.data.datasource.remote.MapRemoteDataSource +import org.sopt.pingle.domain.model.PinEntity +import org.sopt.pingle.domain.repository.MapRepository + +class MapRepositoryImpl @Inject constructor( + private val mapDataSource: MapRemoteDataSource +) : MapRepository { + override suspend fun getPinListWithoutFiltering( + teamId: Long, + category: String? + ): Flow> = flow { + val result = runCatching { + mapDataSource.getPinListWithoutFiltering( + teamId = teamId, + category = category + ).data.map { pin -> + pin.toPinEntity() + } + } + emit(result.getOrThrow()) + } +} diff --git a/app/src/main/java/org/sopt/pingle/data/service/MapService.kt b/app/src/main/java/org/sopt/pingle/data/service/MapService.kt new file mode 100644 index 00000000..c3301035 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/service/MapService.kt @@ -0,0 +1,23 @@ +package org.sopt.pingle.data.service + +import org.sopt.pingle.data.model.remote.response.ResponsePinListDto +import org.sopt.pingle.util.base.BaseResponse +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Query + +interface MapService { + @GET("$VERSION/$TEAMS/{$TEAM_ID}/$PINS") + suspend fun getPinListWithoutFiltering( + @Path("$TEAM_ID") teamId: Long, + @Query(CATEGORY) category: String? + ): BaseResponse> + + companion object { + const val VERSION = "v1" + const val TEAMS = "teams" + const val PINS = "pins" + const val TEAM_ID = "teamId" + const val CATEGORY = "category" + } +} diff --git a/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt b/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt index e70e2adf..92780fcb 100644 --- a/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt @@ -7,8 +7,10 @@ import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.data.datasource.local.DummyLocalDataSource import org.sopt.pingle.data.datasource.remote.DummyRemoteDataSource +import org.sopt.pingle.data.datasource.remote.MapRemoteDataSource import org.sopt.pingle.data.datasourceimpl.local.DummyLocalDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.DummyRemoteDataSourceImpl +import org.sopt.pingle.data.datasourceimpl.remote.MapRemoteDataSourceImpl @Module @InstallIn(SingletonComponent::class) @@ -20,4 +22,8 @@ abstract class DataSourceModule { @Binds @Singleton abstract fun bindsDummyRemoteDataSource(dummyRemoteDataSourceImpl: DummyRemoteDataSourceImpl): DummyRemoteDataSource + + @Binds + @Singleton + abstract fun bindsMapRemoteDataSource(mapRemoteDataSourceImpl: MapRemoteDataSourceImpl): MapRemoteDataSource } diff --git a/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt b/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt index 310f22fc..81f14c1e 100644 --- a/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt @@ -6,7 +6,9 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.data.repository.DummyRepositoryImpl +import org.sopt.pingle.data.repository.MapRepositoryImpl import org.sopt.pingle.domain.repository.DummyRepository +import org.sopt.pingle.domain.repository.MapRepository @Module @InstallIn(SingletonComponent::class) @@ -14,4 +16,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindsDummyRepository(dummyRepositoryImpl: DummyRepositoryImpl): DummyRepository + + @Binds + @Singleton + abstract fun bindsMapRepository(mapRepositoryImpl: MapRepositoryImpl): MapRepository } diff --git a/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt b/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt index 498574a1..754022b6 100644 --- a/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt @@ -6,8 +6,10 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.data.service.DummyService +import org.sopt.pingle.data.service.MapService import org.sopt.pingle.di.qualifier.Pingle import retrofit2.Retrofit +import retrofit2.create @Module @InstallIn(SingletonComponent::class) @@ -16,4 +18,9 @@ object ServiceModule { @Singleton fun providesDummyService(@Pingle retrofit: Retrofit): DummyService = retrofit.create(DummyService::class.java) + + @Provides + @Singleton + fun providesMapService(@Pingle retrofit: Retrofit): MapService = + retrofit.create(MapService::class.java) } diff --git a/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt b/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt index a232e336..0c360644 100644 --- a/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt @@ -6,7 +6,9 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.domain.repository.DummyRepository +import org.sopt.pingle.domain.repository.MapRepository import org.sopt.pingle.domain.usecase.GetDummyUserListUseCase +import org.sopt.pingle.domain.usecase.GetPinListWithoutFilteringUseCase import org.sopt.pingle.domain.usecase.SetDummyDataUseCase @Module @@ -21,4 +23,9 @@ class UseCaseModule { @Singleton fun providesGetDummyUserListUseCase(dummyRepository: DummyRepository): GetDummyUserListUseCase = GetDummyUserListUseCase(dummyRepository) + + @Provides + @Singleton + fun providesGetPinListWithoutFilteringUseCase(mapRepository: MapRepository): GetPinListWithoutFilteringUseCase = + GetPinListWithoutFilteringUseCase(mapRepository = mapRepository) } diff --git a/app/src/main/java/org/sopt/pingle/domain/repository/MapRepository.kt b/app/src/main/java/org/sopt/pingle/domain/repository/MapRepository.kt new file mode 100644 index 00000000..69497652 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/repository/MapRepository.kt @@ -0,0 +1,8 @@ +package org.sopt.pingle.domain.repository + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.PinEntity + +interface MapRepository { + suspend fun getPinListWithoutFiltering(teamId: Long, category: String?): Flow> +} diff --git a/app/src/main/java/org/sopt/pingle/domain/usecase/GetPinListWithoutFilteringUseCase.kt b/app/src/main/java/org/sopt/pingle/domain/usecase/GetPinListWithoutFilteringUseCase.kt new file mode 100644 index 00000000..6028a387 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/usecase/GetPinListWithoutFilteringUseCase.kt @@ -0,0 +1,12 @@ +package org.sopt.pingle.domain.usecase + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.PinEntity +import org.sopt.pingle.domain.repository.MapRepository + +class GetPinListWithoutFilteringUseCase( + private val mapRepository: MapRepository +) { + suspend operator fun invoke(teamId: Long, category: String?): Flow> = + mapRepository.getPinListWithoutFiltering(teamId = teamId, category = category) +} From f5f4dcf00bc6ec4d42cdcbc2c3610df71e466915 Mon Sep 17 00:00:00 2001 From: jihyunniiii Date: Wed, 10 Jan 2024 21:23:10 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[chore]=20#94=20AuthInterceptor=20Authoriza?= =?UTF-8?q?tion=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/sopt/pingle/data/interceptor/AuthInterceptor.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/sopt/pingle/data/interceptor/AuthInterceptor.kt b/app/src/main/java/org/sopt/pingle/data/interceptor/AuthInterceptor.kt index 841aad0f..da86e200 100644 --- a/app/src/main/java/org/sopt/pingle/data/interceptor/AuthInterceptor.kt +++ b/app/src/main/java/org/sopt/pingle/data/interceptor/AuthInterceptor.kt @@ -9,7 +9,7 @@ class AuthInterceptor @Inject constructor() : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() val authRequest = - originalRequest.newBuilder().addHeader(ACCESS_TOKEN, BuildConfig.ACCESS_TOKEN).build() + originalRequest.newBuilder().addHeader(AUTHORIZATION, BuildConfig.ACCESS_TOKEN).build() val response = chain.proceed(authRequest) when (response.code) { @@ -21,6 +21,6 @@ class AuthInterceptor @Inject constructor() : Interceptor { } companion object { - const val ACCESS_TOKEN = "accessToken" + const val AUTHORIZATION = "Authorization" } } From 495882991799279a2da683433e237925340e3118 Mon Sep 17 00:00:00 2001 From: jihyunniiii Date: Wed, 10 Jan 2024 21:23:25 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[chore]=20#94=20pinMapper=20=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/pingle/presentation/mapper/PinMapper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/sopt/pingle/presentation/mapper/PinMapper.kt b/app/src/main/java/org/sopt/pingle/presentation/mapper/PinMapper.kt index fa47b035..ce5d8577 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/mapper/PinMapper.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/mapper/PinMapper.kt @@ -10,7 +10,7 @@ import org.sopt.pingle.presentation.type.CategoryType fun PinEntity.toMarkerModel(): MarkerModel { val markerModel = MarkerModel( Marker().apply { - position = LatLng(y, x) + position = LatLng(x, y) isHideCollidedMarkers = true icon = CategoryType.fromString(category).toMarkerIcon(false) } From 16862e137f489fd19573fcbdff09116a30226773 Mon Sep 17 00:00:00 2001 From: jihyunniiii Date: Wed, 10 Jan 2024 21:23:47 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[feat]=20#94=20=ED=95=80=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20(=EC=A2=8C=ED=91=9C=20=ED=95=84=ED=84=B0=EB=A7=81?= =?UTF-8?q?=20x)=20API=20=EC=97=B0=EB=8F=99=20=ED=9B=84=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/main/home/map/MapFragment.kt | 72 +++++----- .../ui/main/home/map/MapViewModel.kt | 136 ++++++------------ 2 files changed, 82 insertions(+), 126 deletions(-) diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt index fb335ffe..773aadb5 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapFragment.kt @@ -21,10 +21,12 @@ import com.naver.maps.map.NaverMap import com.naver.maps.map.OnMapReadyCallback import com.naver.maps.map.overlay.OverlayImage import com.naver.maps.map.util.FusedLocationSource +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentMapBinding +import org.sopt.pingle.presentation.model.MarkerModel import org.sopt.pingle.presentation.type.CategoryType import org.sopt.pingle.presentation.ui.main.home.mainlist.MainListFragment import org.sopt.pingle.util.base.BindingFragment @@ -32,10 +34,10 @@ import org.sopt.pingle.util.component.AllModalDialogFragment import org.sopt.pingle.util.component.OnPingleCardClickListener import org.sopt.pingle.util.component.PingleChip import org.sopt.pingle.util.fragment.navigateToFragment -import org.sopt.pingle.util.fragment.navigateToWebView -import org.sopt.pingle.util.fragment.showToast import org.sopt.pingle.util.fragment.stringOf +import org.sopt.pingle.util.view.UiState +@AndroidEntryPoint class MapFragment : BindingFragment(R.layout.fragment_map), OnMapReadyCallback { private val mapViewModel by viewModels() private lateinit var naverMap: NaverMap @@ -63,6 +65,7 @@ class MapFragment : BindingFragment(R.layout.fragment_map), this.naverMap = naverMap.apply { isNightModeEnabled = true mapType = NaverMap.MapType.Navi + minZoom = MIN_ZOOM with(uiSettings) { isZoomControlEnabled = false @@ -74,7 +77,7 @@ class MapFragment : BindingFragment(R.layout.fragment_map), } } - makeMarkers() + mapViewModel.getPinListWithoutFilter() setLocationTrackingMode() } @@ -99,14 +102,11 @@ class MapFragment : BindingFragment(R.layout.fragment_map), chipMapCategoryOthers.setChipCategoryType(CategoryType.OTHERS) cardMap.listener = object : OnPingleCardClickListener { override fun onPingleCardChatBtnClickListener() { - startActivity(navigateToWebView(mapViewModel.dummyPingle.chatLink)) + // TODO 선택된 마커로 웹뷰 연결 } override fun onPingleCardParticipateBtnClickListener() { - when (mapViewModel.dummyPingle.isParticipating) { - true -> showMapCancelModalDialogFragment() - false -> showMapModalDialogFragment() - } + // TODO 선택된 마커 참여 현황 여부에 따른 모달 로직 구현 } } } @@ -139,9 +139,20 @@ class MapFragment : BindingFragment(R.layout.fragment_map), } private fun collectData() { - mapViewModel.category.flowWithLifecycle(lifecycle).onEach { - // TODO 서버 통신 구현 시 삭제 예정 - showToast(it?.name ?: "null") + mapViewModel.category.flowWithLifecycle(lifecycle).onEach { category -> + mapViewModel.getPinListWithoutFilter() + }.launchIn(lifecycleScope) + + mapViewModel.markerListState.flowWithLifecycle(lifecycle).onEach { uiState -> + when (uiState) { + is UiState.Success -> { + if (::naverMap.isInitialized) { + makeMarkers(uiState.data) + } + } + + else -> Unit + } }.launchIn(lifecycleScope) mapViewModel.selectedMarkerPosition.flowWithLifecycle(lifecycle) @@ -192,17 +203,15 @@ class MapFragment : BindingFragment(R.layout.fragment_map), } } - private fun makeMarkers() { - mapViewModel.markerList.value.mapIndexed { index, markerModel -> + private fun makeMarkers(markerList: List) { + mapViewModel.clearMarkerList() + + markerList.mapIndexed { _, markerModel -> markerModel.marker.apply { + mapViewModel.addMarkerList(this) map = naverMap setOnClickListener { - with(mapViewModel) { - handleMarkerClick(index) - // TODO 마커 상세 정보 받아오는 로직 추가 - binding.cardMap.initLayout(dummyPingle) - moveMapCamera(position) - } + // TODO 마커 클릭 이벤트 수정 return@setOnClickListener true } } @@ -215,22 +224,14 @@ class MapFragment : BindingFragment(R.layout.fragment_map), detail = stringOf(R.string.map_cancel_modal_detail), buttonText = stringOf(R.string.map_cancel_modal_button_text), textButtonText = stringOf(R.string.map_cancel_modal_text_button_text), - clickBtn = { mapViewModel.cancelPingle() }, + clickBtn = { }, clickTextBtn = { }, - onDialogClosed = { binding.cardMap.initLayout(mapViewModel.dummyPingle) } + onDialogClosed = { } ).show(childFragmentManager, MAP_CANCEL_MODAL) } private fun showMapModalDialogFragment() { - with(mapViewModel.dummyPingle) { - MapModalDialogFragment( - category = CategoryType.fromString(categoryName = category), - name = name, - ownerName = ownerName, - clickBtn = { mapViewModel.joinPingle() }, - onDialogClosed = { binding.cardMap.initLayout(mapViewModel.dummyPingle) } - ).show(childFragmentManager, MAP_MODAL) - } + // TODO 취소 모달 구현 } companion object { @@ -252,8 +253,13 @@ class MapFragment : BindingFragment(R.layout.fragment_map), val OVERLAY_IMAGE_PIN_OTHERS_DEFAULT = OverlayImage.fromResource(R.drawable.ic_pin_others_default) val OVERLAY_IMAGE_PIN_PLAY_ACTIVE = OverlayImage.fromResource(R.drawable.ic_pin_play_active) - val OVERLAY_IMAGE_PIN_STUDY_ACTIVE = OverlayImage.fromResource(R.drawable.ic_pin_study_active) - val OVERLAY_IMAGE_PIN_MULTI_ACTIVE = OverlayImage.fromResource(R.drawable.ic_pin_multi_active) - val OVERLAY_IMAGE_PIN_OTHERS_ACTIVE = OverlayImage.fromResource(R.drawable.ic_pin_others_active) + val OVERLAY_IMAGE_PIN_STUDY_ACTIVE = + OverlayImage.fromResource(R.drawable.ic_pin_study_active) + val OVERLAY_IMAGE_PIN_MULTI_ACTIVE = + OverlayImage.fromResource(R.drawable.ic_pin_multi_active) + val OVERLAY_IMAGE_PIN_OTHERS_ACTIVE = + OverlayImage.fromResource(R.drawable.ic_pin_others_active) + + private const val MIN_ZOOM = 5.5 } } diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt index cd4d2ae5..8daead31 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/home/map/MapViewModel.kt @@ -1,82 +1,49 @@ package org.sopt.pingle.presentation.ui.main.home.map import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.naver.maps.map.overlay.Marker +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import org.sopt.pingle.domain.model.PinEntity -import org.sopt.pingle.domain.model.PingleEntity +import kotlinx.coroutines.launch +import org.sopt.pingle.domain.usecase.GetPinListWithoutFilteringUseCase import org.sopt.pingle.presentation.mapper.toMarkerModel import org.sopt.pingle.presentation.model.MarkerModel import org.sopt.pingle.presentation.type.CategoryType +import org.sopt.pingle.util.view.UiState -class MapViewModel() : ViewModel() { - val dummyPinList = listOf( - PinEntity( - id = 1, - x = 126.9275108, - y = 37.5262935, - category = "PLAY", - meetingCount = 1 - ), - PinEntity( - id = 2, - x = 126.9283122, - y = 37.5259168, - category = "STUDY", - meetingCount = 2 - ), - PinEntity( - id = 3, - x = 126.9276423, - y = 37.5258711, - category = "MULTI", - meetingCount = 1 - ), - PinEntity( - id = 4, - x = 126.9286719, - y = 37.5253629, - category = "OTHERS", - meetingCount = 2 - ) - ) - - var dummyPingle = PingleEntity( - id = 1, - category = "PLAY", - name = "핑글핑글핑글 ~", - ownerName = "배지현", - location = "길음역", - date = "2023-01-06", - startAt = "10:30:00", - endAt = "22:34:00", - maxParticipants = 5, - curParticipants = 4, - isParticipating = false, - chatLink = "https://github.com/TeamPINGLE/PINGLE-ANDROID" - ) - +@HiltViewModel +class MapViewModel @Inject constructor( + private val getPinListWithoutFilteringUseCase: GetPinListWithoutFilteringUseCase +) : ViewModel() { private val _category = MutableStateFlow(null) val category get() = _category.asStateFlow() - private var _markerList = MutableStateFlow>(emptyList()) - val markerList get() = _markerList.asStateFlow() + private val _markerListState = MutableStateFlow>>(UiState.Empty) + val markerListState get() = _markerListState.asStateFlow() + + private val _markerList = mutableListOf() private var _selectedMarkerPosition = MutableStateFlow(DEFAULT_SELECTED_MARKER_POSITION) val selectedMarkerPosition = _selectedMarkerPosition.asStateFlow() - init { - setMarkerList() + private fun setMarkerIsSelected(position: Int) { + // TODO 마커 선택값 재설정 } fun setCategory(category: CategoryType?) { _category.value = category } - fun setMarkerList() { - _markerList.value = dummyPinList.map { pinEntity -> - pinEntity.toMarkerModel() - } + fun clearMarkerList() { + _markerList.forEach { it.map = null } + _markerList.clear() + } + + fun addMarkerList(marker: Marker) { + _markerList.add(marker) } fun handleMarkerClick(position: Int) { @@ -96,45 +63,28 @@ class MapViewModel() : ViewModel() { } } - private fun setMarkerIsSelected(position: Int) { - markerList.value[position].isSelected.set(!markerList.value[position].isSelected.get()) - } - - fun cancelPingle() { - dummyPingle = PingleEntity( - id = 1, - category = "PLAY", - name = "핑글핑글핑글 ~", - ownerName = "배지현", - location = "길음역", - date = "2023-01-06", - startAt = "10:30:00", - endAt = "22:34:00", - maxParticipants = 5, - curParticipants = 4, - isParticipating = false, - chatLink = "https://github.com/TeamPINGLE/PINGLE-ANDROID" - ) - } - - fun joinPingle() { - dummyPingle = PingleEntity( - id = 1, - category = "PLAY", - name = "핑글핑글핑글 ~", - ownerName = "배지현", - location = "길음역", - date = "2023-01-06", - startAt = "10:30:00", - endAt = "22:34:00", - maxParticipants = 5, - curParticipants = 5, - isParticipating = true, - chatLink = "https://github.com/TeamPINGLE/PINGLE-ANDROID" - ) + fun getPinListWithoutFilter() { + viewModelScope.launch { + _markerListState.value = UiState.Loading + runCatching { + getPinListWithoutFilteringUseCase( + teamId = TEAM_ID, + category = category.value?.name + ).collect() { pinList -> + _markerListState.value = UiState.Success( + pinList.map { pinEntity -> + pinEntity.toMarkerModel() + } + ) + } + }.onFailure { exception: Throwable -> + _markerListState.value = UiState.Error(exception.message) + } + } } companion object { const val DEFAULT_SELECTED_MARKER_POSITION = -1 + const val TEAM_ID = 1L } }