-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feat] 핀 클릭 시 번개 목록 API 연동 #101
Changes from all commits
2b38ee7
7a45b5a
dcb3f2b
1150fcb
fd93cfd
c87b1ed
a307b43
72e386e
4bd4e48
7524dd2
567e5ab
e85cef1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,14 @@ | ||
package org.sopt.pingle.data.datasource.remote | ||
|
||
import org.sopt.pingle.data.model.remote.response.ResponsePinListDto | ||
import org.sopt.pingle.data.model.remote.response.ResponsePingleListDto | ||
import org.sopt.pingle.util.base.BaseResponse | ||
|
||
interface MapRemoteDataSource { | ||
suspend fun getPinListWithoutFiltering(teamId: Long, category: String?): BaseResponse<List<ResponsePinListDto>> | ||
suspend fun getPinListWithoutFiltering( | ||
teamId: Long, | ||
category: String? | ||
): BaseResponse<List<ResponsePinListDto>> | ||
|
||
suspend fun getPingleList(teamId: Long, pinId: Long): BaseResponse<List<ResponsePingleListDto>> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.sopt.pingle.data.model.remote.response | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
import org.sopt.pingle.domain.model.PingleEntity | ||
|
||
@Serializable | ||
data class ResponsePingleListDto( | ||
@SerialName("id") | ||
val id: Long, | ||
@SerialName("category") | ||
val category: String, | ||
@SerialName("name") | ||
val name: String, | ||
@SerialName("ownerName") | ||
val ownerName: String, | ||
@SerialName("location") | ||
val location: String, | ||
@SerialName("date") | ||
val date: String, | ||
@SerialName("startAt") | ||
val startAt: String, | ||
@SerialName("endAt") | ||
val endAt: String, | ||
@SerialName("maxParticipants") | ||
val maxParticipants: Int, | ||
@SerialName("curParticipants") | ||
val curParticipants: Int, | ||
@SerialName("isParticipating") | ||
val isParticipating: Boolean, | ||
@SerialName("chatLink") | ||
val chatLink: String | ||
) { | ||
fun toPingleEntity() = PingleEntity( | ||
id = this.id, | ||
category = this.category, | ||
name = this.name, | ||
ownerName = this.ownerName, | ||
location = this.location, | ||
date = this.date, | ||
startAt = this.startAt, | ||
endAt = this.endAt, | ||
maxParticipants = this.maxParticipants, | ||
curParticipants = this.curParticipants, | ||
isParticipating = this.isParticipating, | ||
chatLink = this.chatLink | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ 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.model.PingleEntity | ||
import org.sopt.pingle.domain.repository.MapRepository | ||
|
||
class MapRepositoryImpl @Inject constructor( | ||
|
@@ -24,4 +25,16 @@ class MapRepositoryImpl @Inject constructor( | |
} | ||
emit(result.getOrThrow()) | ||
} | ||
|
||
override suspend fun getPingleList(teamId: Long, pinId: Long): Flow<List<PingleEntity>> = flow { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flow로 한 이유가 있나용?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. flow로 방출한다면 이 루틴은 죽는 시점이 언제인가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기서 반환되는 플로우는 viewModelScope.launch 블록 내부에서 수집되게 됩니당. 그렇기 때문에 뷰모델이 소멸될 때 코루틴도 함께 취소되고 코루틴이 취소되면서 그 안에서 실행되고 있는 플로우도 자동으로 취소됩니다 즉, 뷰모델이 죽으면 플로우도 같이 죽어용 ㅋ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 근데 이 루틴이 해당 블록 내에서 수행되는게 아니지 않나용?? 방출된게 수집되는 것이지 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 음,, 제가 질문을 제대로 이해한 게 맞는지 모르겠지만,, 이 함수의 결과값으로 플로우를 반환해주는 것이기 때문에 뷰모델 스코프 내부에서 플로우가 생성되고 종료되는 거라구 생각했습니당,,, |
||
val result = runCatching { | ||
mapDataSource.getPingleList( | ||
teamId = teamId, | ||
pinId = pinId | ||
).data.map { pingle -> | ||
pingle.toPingleEntity() | ||
} | ||
} | ||
emit(result.getOrThrow()) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.sopt.pingle.domain.usecase | ||
|
||
import kotlinx.coroutines.flow.Flow | ||
import org.sopt.pingle.domain.model.PingleEntity | ||
import org.sopt.pingle.domain.repository.MapRepository | ||
|
||
class GetPingleListUseCase( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거랑 withOut..UseCase를 나눈 이유가 뭘까요?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 유즈케이스가 하나의 책임을 가지는 것이 좋다고 생각해서 나누었습니다 |
||
private val mapRepository: MapRepository | ||
) { | ||
suspend operator fun invoke(teamId: Long, pinId: Long): Flow<List<PingleEntity>> = | ||
mapRepository.getPingleList(teamId = teamId, pinId = pinId) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,14 +26,15 @@ 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.domain.model.PinEntity | ||
import org.sopt.pingle.presentation.mapper.toMarkerModel | ||
import org.sopt.pingle.presentation.type.CategoryType | ||
import org.sopt.pingle.presentation.ui.main.home.mainlist.MainListFragment | ||
import org.sopt.pingle.util.base.BindingFragment | ||
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.stringOf | ||
import org.sopt.pingle.util.view.UiState | ||
|
||
|
@@ -70,6 +71,7 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), | |
with(uiSettings) { | ||
isZoomControlEnabled = false | ||
isScaleBarEnabled = false | ||
isCompassEnabled = false | ||
} | ||
|
||
setOnMapClickListener { _, _ -> | ||
|
@@ -100,15 +102,6 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), | |
chipMapCategoryStudy.setChipCategoryType(CategoryType.STUDY) | ||
chipMapCategoryMulti.setChipCategoryType(CategoryType.MULTI) | ||
chipMapCategoryOthers.setChipCategoryType(CategoryType.OTHERS) | ||
cardMap.listener = object : OnPingleCardClickListener { | ||
override fun onPingleCardChatBtnClickListener() { | ||
// TODO 선택된 마커로 웹뷰 연결 | ||
} | ||
|
||
override fun onPingleCardParticipateBtnClickListener() { | ||
// TODO 선택된 마커 참여 현황 여부에 따른 모달 로직 구현 | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
@@ -143,11 +136,18 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), | |
mapViewModel.getPinListWithoutFilter() | ||
}.launchIn(lifecycleScope) | ||
|
||
mapViewModel.markerListState.flowWithLifecycle(lifecycle).onEach { uiState -> | ||
mapViewModel.pinEntityListState.flowWithLifecycle(lifecycle).onEach { uiState -> | ||
when (uiState) { | ||
is UiState.Success -> { | ||
if (::naverMap.isInitialized) { | ||
makeMarkers(uiState.data) | ||
with(binding) { | ||
fabMapHere.visibility = View.VISIBLE | ||
fabMapList.visibility = View.VISIBLE | ||
cardMap.visibility = View.INVISIBLE | ||
} | ||
|
||
mapViewModel.clearSelectedMarkerPosition() | ||
} | ||
} | ||
|
||
|
@@ -165,6 +165,21 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), | |
} | ||
} | ||
}.launchIn(lifecycleScope) | ||
|
||
mapViewModel.pingleListState.flowWithLifecycle(lifecycle).onEach { uiState -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 emit 방식으로 한거면 flowWithLifeCylce 한 번 확인해보는게 좋을거 같습니당!! 물론 저희는 여러개의 루틴이 생길일이 있을 거 같진 않지만... 여러개의 루틴이 생기게 됐을때 최신값을 우선적으로 방출하는 아이가 맞는지 한 번 확인해주세용 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 확인안해도 될 거 같습니다 그대로 stateFLow군요 ㅋㅋ |
||
when (uiState) { | ||
is UiState.Success -> { | ||
with(binding.cardMap) { | ||
initLayout(uiState.data[SINGLE_SELECTION]) | ||
setOnChatButtonClick { | ||
startActivity(navigateToWebView(uiState.data[SINGLE_SELECTION].chatLink)) | ||
} | ||
} | ||
} | ||
|
||
else -> Unit | ||
} | ||
}.launchIn(lifecycleScope) | ||
} | ||
|
||
private fun setLocationTrackingMode() { | ||
|
@@ -203,17 +218,21 @@ class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), | |
} | ||
} | ||
|
||
private fun makeMarkers(markerList: List<MarkerModel>) { | ||
private fun makeMarkers(pinEntityList: List<PinEntity>) { | ||
mapViewModel.clearMarkerList() | ||
|
||
markerList.mapIndexed { _, markerModel -> | ||
markerModel.marker.apply { | ||
mapViewModel.addMarkerList(this) | ||
map = naverMap | ||
setOnClickListener { | ||
// TODO 마커 클릭 이벤트 수정 | ||
return@setOnClickListener true | ||
pinEntityList.mapIndexed { index, pinEntity -> | ||
pinEntity.toMarkerModel().apply { | ||
this.marker.apply { | ||
map = naverMap | ||
setOnClickListener { | ||
mapViewModel.updateMarkerModelListSelectedValue(index) | ||
mapViewModel.getPingleList(pinEntity.id) | ||
moveMapCamera(position) | ||
return@setOnClickListener true | ||
} | ||
} | ||
mapViewModel.addMarkerList(this) | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
근데 생각해보니까 아요가 Long 타입 없다고 하지 않았었나..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오잉 이거 서버에서 long으로 넘어오던뎅,, 그리고 아요 이미 서버 다 붙이긴 함요,,, 지도 부분