Skip to content
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: 약속 상세 화면 기능 개발 #961

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3cf91f0
feat: 약속 참여, 약속 아이템 클릭 시 약속 상세 화면으로 이동
kimhm0728 Jan 18, 2025
945537e
feat: 툴바 나가기 다이얼로그 연결
kimhm0728 Jan 18, 2025
c676620
feat: i 버튼 클릭 시 가이드 띄우는 기능 구현
kimhm0728 Jan 18, 2025
d321643
feat: 가운데 클릭 시 오디/로그 버튼 나오는 기능 구현
kimhm0728 Jan 19, 2025
69770f6
feat: 오디/로그 버튼 클릭 시 화면 이동 기능 구현
kimhm0728 Jan 19, 2025
1473fb6
feat: 30분 전에만 오디 버튼 클릭할 수 있도록 하는 기능 구현
kimhm0728 Jan 19, 2025
4cef0a6
style: ktLint 적용
kimhm0728 Jan 19, 2025
c5481e8
feat: 약속 참여자와 초대코드 복사 리스트 구현
kimhm0728 Jan 19, 2025
aa9b6b7
feat: 초대 코드 복사하는 기능 구현
kimhm0728 Jan 19, 2025
6e34390
style: ktLint 적용
kimhm0728 Jan 19, 2025
f62bff8
feat: meetingDetailUiModel 필드 추가
kimhm0728 Jan 20, 2025
8b09e38
feat: meetingDetailUiModel 화면에 띄우는 로직 추가
kimhm0728 Jan 20, 2025
e85c417
chore: MeetingDetailUiModel -> DetailMeetingUiModel 클래스명 변경
kimhm0728 Jan 20, 2025
7b774a5
fix: 초대코드 공유되지 않는 버그 수정
kimhm0728 Jan 20, 2025
3f261ce
style: ktLint 적용
kimhm0728 Jan 20, 2025
aaa54fb
refactor: isEtaAccessible 프로퍼티를 함수로 변경
kimhm0728 Jan 20, 2025
10e13d5
test: 테스트 픽스처 수정
kimhm0728 Jan 20, 2025
703f5d9
design: string 문구 띄어쓰기 수정
kimhm0728 Jan 21, 2025
ebbbce5
design: RecyclerView padding 옵션 추가
kimhm0728 Jan 21, 2025
e7d3b50
refactor: Point의 apply 제거
kimhm0728 Jan 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ fun MeetingResponse.toMeeting(): Meeting =
Meeting(
id = id,
name = name,
targetPosition = targetAddress,
meetingDate = date.parseToLocalDate(),
meetingTime = time.parseToLocalTime(),
date = date.toLocalDate(),
time = time.toLocalTime(),
destinationAddress = targetAddress,
departureAddress = departureAddress,
departureTime = departureTime.toLocalTime(),
routeTime = routeTime,
mates = mates.map { Mate(nickname = it.nickname, imageUrl = it.imageUrl) },
inviteCode = inviteCode,
)

private fun String.parseToLocalDate(): LocalDate {
private fun String.toLocalDate(): LocalDate {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
return LocalDate.parse(this, formatter)
}

private fun String.parseToLocalTime(): LocalTime {
private fun String.toLocalTime(): LocalTime {
val formatter = DateTimeFormatter.ofPattern("HH:mm")
return LocalTime.parse(this, formatter)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ data class MeetingResponse(
val date: String,
@Json(name = "time")
val time: String,
@Json(name = "departureAddress")
val departureAddress: String,
@Json(name = "departureTime")
val departureTime: String,
@Json(name = "routeTime")
val routeTime: Int,
@Json(name = "targetAddress")
val targetAddress: String,
@Json(name = "targetLatitude")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@ package com.mulberry.ody.data.remote.core.repository
import com.mulberry.ody.data.local.db.MateEtaInfoDao
import com.mulberry.ody.data.local.entity.eta.MateEtaInfoEntity
import com.mulberry.ody.data.remote.core.entity.meeting.mapper.toMateEtaInfo
import com.mulberry.ody.data.remote.core.entity.meeting.mapper.toMeeting
import com.mulberry.ody.data.remote.core.entity.meeting.mapper.toMeetingCatalogs
import com.mulberry.ody.data.remote.core.entity.meeting.mapper.toMeetingRequest
import com.mulberry.ody.data.remote.core.entity.meeting.mapper.toNudgeRequest
import com.mulberry.ody.data.remote.core.entity.meeting.request.MatesEtaRequest
import com.mulberry.ody.data.remote.core.service.MeetingService
import com.mulberry.ody.domain.apiresult.ApiResult
import com.mulberry.ody.domain.apiresult.map
import com.mulberry.ody.domain.model.Mate
import com.mulberry.ody.domain.model.MateEtaInfo
import com.mulberry.ody.domain.model.Meeting
import com.mulberry.ody.domain.model.MeetingCatalog
import com.mulberry.ody.domain.model.MeetingCreationInfo
import com.mulberry.ody.domain.model.Nudge
import com.mulberry.ody.domain.repository.ody.MeetingRepository
import java.time.LocalDate
import java.time.LocalTime
import javax.inject.Inject

class DefaultMeetingRepository
Expand All @@ -30,7 +32,21 @@ class DefaultMeetingRepository
}

override suspend fun fetchMeeting(meetingId: Long): ApiResult<Meeting> {
return service.fetchMeeting(meetingId).map { it.toMeeting() }
return ApiResult.Success(
Meeting(
id = 1,
name = "약속 이름",
date = LocalDate.of(2025, 2, 1),
time = LocalTime.of(11, 30),
destinationAddress = "서울특별시 강남구 테헤란로 411 (성담빌딩)",
departureAddress = "서울특별시 송파구 올림픽로 35다길 (한국루터회관)",
departureTime = LocalTime.of(10, 0),
routeTime = 70,
mates = listOf(Mate("올리브1", ""), Mate("올리브2", "")),
inviteCode = "12345",
),
)
// return service.fetchMeeting(meetingId).map { it.toMeeting() }
Comment on lines +35 to +49
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefaultMeetingRepository에서 임시 데이터 넣어두었어요 api merge되면 위 코드 삭제하고 아래 주석 추가할게요!

}

override suspend fun postNudge(nudge: Nudge): ApiResult<Unit> = service.postNudge(nudge.toNudgeRequest())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface MeetingService {
@GET("/v1/meetings/me")
suspend fun fetchMeetingCatalogs(): ApiResult<MeetingCatalogsResponse>

@GET("/v1/meetings/{meetingId}")
@GET("/v2/meetings/{meetingId}")
suspend fun fetchMeeting(
@Path(value = "meetingId") meetingId: Long,
): ApiResult<MeetingResponse>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import java.time.LocalTime
data class Meeting(
val id: Long,
val name: String,
val targetPosition: String,
val meetingDate: LocalDate,
val meetingTime: LocalTime,
val date: LocalDate,
val time: LocalTime,
val destinationAddress: String,
val departureAddress: String,
val departureTime: LocalTime,
val routeTime: Int,
val mates: List<Mate>,
val inviteCode: String,
)
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package com.mulberry.ody.presentation.common

import android.content.Context
import android.graphics.Point
import android.view.View

fun Int.toPixel(context: Context): Int {
val density = context.resources.displayMetrics.density
return (this * density).toInt()
}

fun View.getPointOnScreen(): Point {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply 쓴 이유가 궁금해요! Point(location[0], location[1]) 이렇게 사용하면 안되나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

참고한 코드에서 저렇게 작성했길래 당연히 Point의 생성자로 x, y를 받을 수 없다고 생각했어요 (ㅜㅜ)
그런데 해음이 말한 방법으로도 가능하네요!
수정했습니다 감사해요! e7d3b50

val location = IntArray(2)
this.getLocationOnScreen(location)
return Point(location[0], location[1])
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.mulberry.ody.presentation.common.listener.BackListener
import com.mulberry.ody.presentation.common.listener.NextListener
import com.mulberry.ody.presentation.join.complete.JoinCompleteActivity
import com.mulberry.ody.presentation.room.MeetingRoomActivity
import com.mulberry.ody.presentation.room.MeetingRoomActivity.Companion.NAVIGATE_TO_DETAIL_MEETING
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

Expand Down Expand Up @@ -90,7 +91,7 @@ class MeetingJoinActivity :
MeetingRoomActivity.getIntent(
this,
meetingId,
MeetingRoomActivity.NAVIGATE_TO_NOTIFICATION_LOG,
NAVIGATE_TO_DETAIL_MEETING,
)
startActivity(intent)
finish()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import com.mulberry.ody.presentation.login.LoginActivity
import com.mulberry.ody.presentation.meetings.adapter.MeetingsAdapter
import com.mulberry.ody.presentation.meetings.listener.MeetingsListener
import com.mulberry.ody.presentation.room.MeetingRoomActivity
import com.mulberry.ody.presentation.room.MeetingRoomActivity.Companion.NAVIGATE_TO_DETAIL_MEETING
import com.mulberry.ody.presentation.room.MeetingRoomActivity.Companion.NAVIGATE_TO_ETA_DASHBOARD
import com.mulberry.ody.presentation.setting.SettingActivity
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
Expand Down Expand Up @@ -116,7 +118,7 @@ class MeetingsActivity :
MeetingRoomActivity.getIntent(
this,
meetingId,
MeetingRoomActivity.NAVIGATE_TO_NOTIFICATION_LOG,
NAVIGATE_TO_DETAIL_MEETING,
)
startActivity(intent)
}
Expand All @@ -126,7 +128,7 @@ class MeetingsActivity :
MeetingRoomActivity.getIntent(
this,
meetingId,
MeetingRoomActivity.NAVIGATE_TO_ETA_DASHBOARD,
NAVIGATE_TO_ETA_DASHBOARD,
)
startActivity(intent)
}
Expand All @@ -137,7 +139,7 @@ class MeetingsActivity :
}

override fun guideItemDisabled() {
showSnackBar(R.string.meetings_entrance_unavailable_guide)
showSnackBar(R.string.inaccessible_eta_guide)
}

override fun onClickSetting() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import com.mulberry.ody.data.local.db.OdyDatastore
import com.mulberry.ody.domain.model.NotificationType
import com.mulberry.ody.presentation.meetings.MeetingsActivity
import com.mulberry.ody.presentation.room.MeetingRoomActivity
import com.mulberry.ody.presentation.room.MeetingRoomActivity.Companion.NAVIGATE_TO_DETAIL_MEETING
import com.mulberry.ody.presentation.room.MeetingRoomActivity.Companion.NAVIGATE_TO_ETA_DASHBOARD
import com.mulberry.ody.presentation.room.MeetingRoomActivity.Companion.NAVIGATE_TO_NOTIFICATION_LOG
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
Expand Down Expand Up @@ -93,7 +93,7 @@ class FCMNotification
): PendingIntent? {
val navigationTarget =
when (type) {
NotificationType.ENTRY, NotificationType.DEPARTURE_REMINDER -> NAVIGATE_TO_NOTIFICATION_LOG
NotificationType.ENTRY, NotificationType.DEPARTURE_REMINDER -> NAVIGATE_TO_DETAIL_MEETING
NotificationType.NUDGE, NotificationType.ETA_NOTICE -> NAVIGATE_TO_ETA_DASHBOARD
NotificationType.DEFAULT -> ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ import com.mulberry.ody.databinding.ActivityMeetingRoomBinding
import com.mulberry.ody.presentation.collectWhenStarted
import com.mulberry.ody.presentation.common.binding.BindingActivity
import com.mulberry.ody.presentation.common.listener.BackListener
import com.mulberry.ody.presentation.room.detail.DetailMeetingFragment
import com.mulberry.ody.presentation.room.etadashboard.EtaDashboardFragment
import com.mulberry.ody.presentation.room.listener.MeetingRoomListener
import com.mulberry.ody.presentation.room.log.ExitMeetingRoomDialog
import com.mulberry.ody.presentation.room.log.NotificationLogFragment
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class MeetingRoomActivity :
BindingActivity<ActivityMeetingRoomBinding>(R.layout.activity_meeting_room),
BackListener {
BackListener,
MeetingRoomListener {
@Inject
lateinit var viewModelFactory: MeetingRoomViewModel.MeetingViewModelFactory

Expand All @@ -30,6 +34,7 @@ class MeetingRoomActivity :

private val fragments: Map<String, Fragment> by lazy {
mapOf(
NAVIGATE_TO_DETAIL_MEETING to DetailMeetingFragment(),
NAVIGATE_TO_ETA_DASHBOARD to EtaDashboardFragment(),
NAVIGATE_TO_NOTIFICATION_LOG to NotificationLogFragment(),
)
Expand All @@ -54,8 +59,13 @@ class MeetingRoomActivity :

private fun initializeObserve() {
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
collectWhenStarted(viewModel.navigateToEtaDashboardEvent) {
addFragment(EtaDashboardFragment())
collectWhenStarted(viewModel.navigationEvent) {
val fragment =
when (it) {
MeetingRoomNavigateAction.NavigateToEtaDashboard -> fragments[NAVIGATE_TO_ETA_DASHBOARD]
MeetingRoomNavigateAction.NavigateToNotificationLog -> fragments[NAVIGATE_TO_NOTIFICATION_LOG]
} ?: return@collectWhenStarted
addFragment(fragment)
}
collectWhenStarted(viewModel.networkErrorEvent) {
showRetrySnackBar { viewModel.retryLastAction() }
Expand All @@ -73,6 +83,9 @@ class MeetingRoomActivity :
}
hideLoadingDialog()
}
collectWhenStarted(viewModel.inaccessibleEtaEvent) {
showSnackBar(R.string.inaccessible_eta_guide)
}
}

private fun initializeFragment() {
Expand Down Expand Up @@ -102,14 +115,22 @@ class MeetingRoomActivity :

private fun getMeetingId(): Long = intent.getLongExtra(MEETING_ID_KEY, MEETING_ID_DEFAULT_VALUE)

private fun getNavigateView(): String = intent.getStringExtra(NAVIGATE_VIEW_KEY) ?: NAVIGATE_TO_NOTIFICATION_LOG
private fun getNavigateView(): String = intent.getStringExtra(NAVIGATE_VIEW_KEY) ?: NAVIGATE_TO_DETAIL_MEETING

override fun onExitMeetingRoom() {
ExitMeetingRoomDialog().show(supportFragmentManager, EXIT_MEETING_ROOM_DIALOG_TAG)
}

companion object {
private const val EXIT_MEETING_ROOM_DIALOG_TAG = "exitMeetingRoomDialog"

private const val MEETING_ID_KEY = "meeting_id"
private const val MEETING_ID_DEFAULT_VALUE = -1L

private const val NAVIGATE_VIEW_KEY = "navigate_view"
const val NAVIGATE_TO_DETAIL_MEETING = "detail_meeting"
const val NAVIGATE_TO_ETA_DASHBOARD = "eta_dashboard"
const val NAVIGATE_TO_NOTIFICATION_LOG = "notification_log"
private const val NAVIGATE_TO_NOTIFICATION_LOG = "notification_log"

fun getIntent(
context: Context,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.mulberry.ody.presentation.room

sealed interface MeetingRoomNavigateAction {
data object NavigateToEtaDashboard : MeetingRoomNavigateAction

data object NavigateToNotificationLog : MeetingRoomNavigateAction
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ import com.mulberry.ody.presentation.common.analytics.logButtonClicked
import com.mulberry.ody.presentation.common.analytics.logNetworkErrorEvent
import com.mulberry.ody.presentation.common.image.ImageShareContent
import com.mulberry.ody.presentation.common.image.ImageShareHelper
import com.mulberry.ody.presentation.room.detail.model.DetailMeetingUiModel
import com.mulberry.ody.presentation.room.detail.model.InviteCodeCopyInfo
import com.mulberry.ody.presentation.room.detail.model.MateUiModel
import com.mulberry.ody.presentation.room.detail.model.toDetailMeetingUiModel
import com.mulberry.ody.presentation.room.detail.model.toMateUiModels
import com.mulberry.ody.presentation.room.etadashboard.listener.NudgeListener
import com.mulberry.ody.presentation.room.etadashboard.model.MateEtaUiModel
import com.mulberry.ody.presentation.room.etadashboard.model.toMateEtaUiModels
import com.mulberry.ody.presentation.room.log.model.InviteCodeCopyInfo
import com.mulberry.ody.presentation.room.log.model.MateUiModel
import com.mulberry.ody.presentation.room.log.model.MeetingDetailUiModel
import com.mulberry.ody.presentation.room.log.model.NotificationLogUiModel
import com.mulberry.ody.presentation.room.log.model.toMateUiModels
import com.mulberry.ody.presentation.room.log.model.toMeetingUiModel
import com.mulberry.ody.presentation.room.log.model.toNotificationUiModels
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
Expand Down Expand Up @@ -74,18 +74,17 @@ class MeetingRoomViewModel
initialValue = null,
)

private val _meeting: MutableStateFlow<MeetingDetailUiModel> =
MutableStateFlow(MeetingDetailUiModel.DEFAULT)
val meeting: StateFlow<MeetingDetailUiModel> = _meeting.asStateFlow()
private val _meeting: MutableStateFlow<DetailMeetingUiModel> = MutableStateFlow(DetailMeetingUiModel.DEFAULT)
val meeting: StateFlow<DetailMeetingUiModel> = _meeting.asStateFlow()

private val _mates: MutableStateFlow<List<MateUiModel>> = MutableStateFlow(listOf())
val mates: StateFlow<List<MateUiModel>> = _mates.asStateFlow()

private val _notificationLogs = MutableStateFlow<List<NotificationLogUiModel>>(listOf())
val notificationLogs: StateFlow<List<NotificationLogUiModel>> = _notificationLogs.asStateFlow()

private val _navigateToEtaDashboardEvent: MutableSharedFlow<Unit> = MutableSharedFlow()
val navigateToEtaDashboardEvent: SharedFlow<Unit> get() = _navigateToEtaDashboardEvent.asSharedFlow()
private val _navigationEvent: MutableSharedFlow<MeetingRoomNavigateAction> = MutableSharedFlow()
val navigationEvent: SharedFlow<MeetingRoomNavigateAction> get() = _navigationEvent.asSharedFlow()

private val _nudgeSuccessMate: MutableSharedFlow<String> = MutableSharedFlow()
val nudgeSuccessMate: SharedFlow<String> get() = _nudgeSuccessMate.asSharedFlow()
Expand All @@ -104,6 +103,12 @@ class MeetingRoomViewModel

private val matesNudgeTimes: MutableMap<Long, LocalDateTime> = mutableMapOf()

private val _isVisibleNavigation: MutableStateFlow<Boolean> = MutableStateFlow(false)
val isVisibleNavigation: StateFlow<Boolean> get() = _isVisibleNavigation

private val _inaccessibleEtaEvent: MutableSharedFlow<Unit> = MutableSharedFlow()
val inaccessibleEtaEvent: SharedFlow<Unit> get() = _inaccessibleEtaEvent

init {
fetchMeeting()
}
Expand Down Expand Up @@ -180,7 +185,7 @@ class MeetingRoomViewModel
startLoading()
meetingRepository.fetchMeeting(meetingId)
.onSuccess {
_meeting.value = it.toMeetingUiModel()
_meeting.value = it.toDetailMeetingUiModel()
_mates.value = it.toMateUiModels()
fetchNotificationLogs()
}.onFailure { code, errorMessage ->
Expand All @@ -196,12 +201,27 @@ class MeetingRoomViewModel
}

fun navigateToEtaDashboard() {
viewModelScope.launch {
if (!meeting.value.isEtaAccessible()) {
_inaccessibleEtaEvent.emit(Unit)
return@launch
}

analyticsHelper.logButtonClicked(
eventName = "navigate_to_eta_dashboard",
location = TAG,
)
_navigationEvent.emit(MeetingRoomNavigateAction.NavigateToEtaDashboard)
}
}

fun navigateToNotificationLog() {
viewModelScope.launch {
analyticsHelper.logButtonClicked(
eventName = "eta_button_from_notification_log",
eventName = "navigate_to_notification_log",
location = TAG,
)
_navigateToEtaDashboardEvent.emit(Unit)
_navigationEvent.emit(MeetingRoomNavigateAction.NavigateToNotificationLog)
}
}

Expand Down Expand Up @@ -288,6 +308,10 @@ class MeetingRoomViewModel
}
}

fun handleNavigationVisibility() {
_isVisibleNavigation.value = !_isVisibleNavigation.value
}

@AssistedFactory
interface MeetingViewModelFactory {
fun create(meetingId: Long): MeetingRoomViewModel
Expand Down
Loading
Loading