From e9326c1d1e46d742f8115f204d524635700dbfbd Mon Sep 17 00:00:00 2001 From: eshc123 <> Date: Tue, 19 Nov 2024 00:57:16 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20=EC=9D=98=EC=A1=B4=EC=84=B1=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/missionmate.android.feature.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build-logic/src/main/kotlin/missionmate.android.feature.gradle.kts b/build-logic/src/main/kotlin/missionmate.android.feature.gradle.kts index 9f74ffe..0942695 100644 --- a/build-logic/src/main/kotlin/missionmate.android.feature.gradle.kts +++ b/build-logic/src/main/kotlin/missionmate.android.feature.gradle.kts @@ -28,6 +28,7 @@ dependencies { implementation(project(":core:domain:mission")) implementation(project(":core:domain:common")) implementation(project(":core:domain:auth")) + implementation(project(":core:domain:onboarding")) implementation(project(":core:ui")) -} \ No newline at end of file +} From f099d3bb2ffb0627fb9b1f2a7411d5fb75da93ae Mon Sep 17 00:00:00 2001 From: eshc123 <> Date: Tue, 19 Nov 2024 00:57:20 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EC=8B=9C=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A4=91=EC=9D=B8=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=EA=B3=BC=20=EB=B3=B4=EB=93=9C=20=ED=99=94=EB=A9=B4=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=B9=84=EA=B5=90=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/board/screen/BoardViewModel.kt | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt index e35552c..99d9411 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt @@ -4,14 +4,15 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.goalpanzi.mission_mate.core.domain.common.DomainResult +import com.goalpanzi.mission_mate.core.domain.common.model.mission.MissionStatus.Companion.statusString import com.goalpanzi.mission_mate.core.domain.mission.model.BoardReward import com.goalpanzi.mission_mate.core.domain.mission.usecase.DeleteMissionUseCase import com.goalpanzi.mission_mate.core.domain.mission.usecase.GetMissionBoardsUseCase import com.goalpanzi.mission_mate.core.domain.mission.usecase.GetMissionUseCase import com.goalpanzi.mission_mate.core.domain.mission.usecase.GetMissionVerificationsUseCase import com.goalpanzi.mission_mate.core.domain.mission.usecase.GetMyMissionVerificationUseCase -import com.goalpanzi.mission_mate.core.domain.mission.usecase.VerifyMissionUseCase import com.goalpanzi.mission_mate.core.domain.mission.usecase.ViewVerificationUseCase +import com.goalpanzi.mission_mate.core.domain.onboarding.usecase.GetJoinedMissionsUseCase import com.goalpanzi.mission_mate.core.domain.setting.usecase.GetViewedTooltipUseCase import com.goalpanzi.mission_mate.core.domain.setting.usecase.SetViewedTooltipUseCase import com.goalpanzi.mission_mate.core.domain.user.usecase.GetCachedMemberIdUseCase @@ -43,6 +44,7 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch @@ -59,8 +61,8 @@ class BoardViewModel @Inject constructor( private val deleteMissionUseCase: DeleteMissionUseCase, private val profileUseCase: ProfileUseCase, private val setViewedTooltipUseCase: SetViewedTooltipUseCase, - private val verifyMissionUseCase: VerifyMissionUseCase, - private val getMyMissionVerificationUseCase : GetMyMissionVerificationUseCase, + private val getJoinedMissionsUseCase: GetJoinedMissionsUseCase, + private val getMyMissionVerificationUseCase: GetMyMissionVerificationUseCase, private val viewVerificationUseCase: ViewVerificationUseCase ) : ViewModel() { @@ -157,7 +159,13 @@ class BoardViewModel @Inject constructor( is DomainResult.Success -> { val myMemberId = getCachedMemberIdUseCase().first() - _missionBoardUiModel.emit(MissionBoardUiModel.Success(it.data.toUiModel(myMemberId))) + _missionBoardUiModel.emit( + MissionBoardUiModel.Success( + it.data.toUiModel( + myMemberId + ) + ) + ) val boardPieceList = it.data.toUiModel(myMemberId).toBoardPieces(profileUseCase.getProfile()) @@ -166,7 +174,7 @@ class BoardViewModel @Inject constructor( _boardPieces.emit(boardPieceList) } else { val isMoved = - boardPieces.value.find { it.isMe }?.index?.plus(1) == boardPieceList.find { it.isMe }?.index + boardPieces.value.find { it.isMe }?.index?.plus(1) == boardPieceList.find { it.isMe }?.index val newList = PieceManager.getBoardPieces( boardPieces.value, @@ -175,7 +183,7 @@ class BoardViewModel @Inject constructor( _boardPieces.emit( newList ) - if(isMoved){ + if (isMoved) { delay(550) _boardRewardEvent.emit( it.data.missionBoards.find { it.isMyPosition }?.reward @@ -186,7 +194,7 @@ class BoardViewModel @Inject constructor( else -> { _missionBoardUiModel.emit(MissionBoardUiModel.Error) - _missionError.emit(MissionError.NOT_EXIST) + if(!isSameAsLastMission()) _missionError.emit(MissionError.NOT_EXIST) } } } @@ -203,7 +211,7 @@ class BoardViewModel @Inject constructor( else -> { _missionUiModel.emit(MissionUiModel.Error) - _missionError.emit(MissionError.NOT_EXIST) + if(!isSameAsLastMission()) _missionError.emit(MissionError.NOT_EXIST) } } } @@ -220,7 +228,7 @@ class BoardViewModel @Inject constructor( else -> { _missionVerificationUiModel.emit(MissionVerificationUiModel.Error) - _missionError.emit(MissionError.NOT_EXIST) + if(!isSameAsLastMission()) _missionError.emit(MissionError.NOT_EXIST) } } } @@ -275,13 +283,23 @@ class BoardViewModel @Inject constructor( } } } - - fun viewVerification(missionVerificationId : Long){ + + fun viewVerification(missionVerificationId: Long) { viewModelScope.launch { viewVerificationUseCase(missionVerificationId) - .collectLatest { - getMissionVerification() + .collectLatest { + getMissionVerification() } } } + + private suspend fun isSameAsLastMission(): Boolean { + return when (val result = getJoinedMissionsUseCase(filter = statusString).firstOrNull()) { + is DomainResult.Success -> { + result.data.missions.lastOrNull()?.missionId == missionId + } + + else -> false + } + } } From 750c24a9692e74f5783f273703f098490fdeea4f Mon Sep 17 00:00:00 2001 From: eshc123 <> Date: Tue, 19 Nov 2024 01:29:36 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EB=AF=B8=EC=85=98=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=A4=ED=8C=A8=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dialog/InvalidMissionErrorDialog.kt | 26 +++++++++++++++ .../feature/board/model/MissionError.kt | 4 +-- .../feature/board/screen/BoardScreen.kt | 33 ++++++++++++++++--- .../feature/board/screen/BoardViewModel.kt | 21 ++++++++---- feature/board/src/main/res/values/strings.xml | 4 ++- 5 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/component/dialog/InvalidMissionErrorDialog.kt diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/component/dialog/InvalidMissionErrorDialog.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/component/dialog/InvalidMissionErrorDialog.kt new file mode 100644 index 0000000..cb3227a --- /dev/null +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/component/dialog/InvalidMissionErrorDialog.kt @@ -0,0 +1,26 @@ +package com.goalpanzi.mission_mate.feature.board.component.dialog + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.DialogProperties +import com.goalpanzi.mission_mate.core.designsystem.component.MissionMateDialog +import com.goalpanzi.mission_mate.feature.board.R + +@Composable +fun InvalidMissionErrorDialog( + onDismissRequest: () -> Unit, + onClickOk: () -> Unit, + modifier: Modifier = Modifier +) { + MissionMateDialog( + titleId = R.string.board_mission_not_exist, + onDismissRequest = onDismissRequest, + onClickOk = onClickOk, + okTextId = R.string.retry, + dialogProperties = DialogProperties( + usePlatformDefaultWidth = false, + dismissOnBackPress = false, + dismissOnClickOutside = false + ) + ) +} diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/model/MissionError.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/model/MissionError.kt index 2d8e7bd..1b1c46b 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/model/MissionError.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/model/MissionError.kt @@ -1,5 +1,5 @@ package com.goalpanzi.mission_mate.feature.board.model enum class MissionError { - NOT_EXIST, -} \ No newline at end of file + NOT_EXIST, INVALID_MISSION +} diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardScreen.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardScreen.kt index a849244..05eeab6 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardScreen.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardScreen.kt @@ -51,6 +51,8 @@ import com.goalpanzi.mission_mate.feature.board.model.uimodel.MissionBoardUiMode import com.goalpanzi.mission_mate.feature.board.model.uimodel.MissionUiModel import com.goalpanzi.mission_mate.feature.board.model.uimodel.MissionVerificationUiModel import com.goalpanzi.mission_mate.core.designsystem.component.StableImage +import com.goalpanzi.mission_mate.feature.board.component.dialog.InvalidMissionErrorDialog +import com.goalpanzi.mission_mate.feature.board.model.MissionError import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -83,6 +85,7 @@ fun BoardRoute( onRefresh = viewModel::refreshMissionData ) var isShownDeleteMissionDialog by remember { mutableStateOf(false) } + var isShownNotLoadedErrorDialog by remember { mutableStateOf(false) } var isShownBoardRewardDialog by remember { mutableStateOf(null) } var isShownInvitationCodeDialog by remember { mutableStateOf(false) } @@ -123,11 +126,19 @@ fun BoardRoute( } } launch { - viewModel.missionError.collect { - if(it != null){ - Toast.makeText(context,context.getString(R.string.board_mission_not_exist), Toast.LENGTH_SHORT).show() - onNavigateOnboarding() - return@collect + viewModel.missionError.collect { error -> + when(error){ + MissionError.INVALID_MISSION -> { + isShownNotLoadedErrorDialog = true + viewModel.resetMissionError() + } + MissionError.NOT_EXIST -> { + Toast.makeText(context,context.getString(R.string.board_mission_not_exist), Toast.LENGTH_SHORT).show() + viewModel.resetMissionError() + onNavigateOnboarding() + return@collect + } + else -> { } } } } @@ -141,6 +152,18 @@ fun BoardRoute( } } + if (isShownNotLoadedErrorDialog) { + InvalidMissionErrorDialog( + onDismissRequest = { + isShownNotLoadedErrorDialog = false + }, + onClickOk = { + isShownNotLoadedErrorDialog = false + viewModel.fetchMissionData() + } + ) + } + if (isShownDeleteMissionDialog) { DeleteMissionDialog( onDismissRequest = { diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt index 99d9411..3c08007 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/BoardViewModel.kt @@ -70,7 +70,7 @@ class BoardViewModel @Inject constructor( val viewedToolTip: StateFlow = getViewedTooltipUseCase().stateIn( viewModelScope, - started = SharingStarted.WhileSubscribed(500), + started = SharingStarted.WhileSubscribed(5_000), initialValue = true ) @@ -108,7 +108,7 @@ class BoardViewModel @Inject constructor( memberId == mission.missionDetail.hostMemberId }.stateIn( viewModelScope, - started = SharingStarted.WhileSubscribed(500), + started = SharingStarted.WhileSubscribed(5_000), initialValue = false ) @@ -121,7 +121,7 @@ class BoardViewModel @Inject constructor( getMissionState(missionBoard, mission, missionVerification) }.stateIn( scope = viewModelScope, - started = SharingStarted.WhileSubscribed(500), + started = SharingStarted.WhileSubscribed(5_000), initialValue = MissionState.LOADING ) private val _boardRewardEvent = MutableSharedFlow() @@ -194,7 +194,7 @@ class BoardViewModel @Inject constructor( else -> { _missionBoardUiModel.emit(MissionBoardUiModel.Error) - if(!isSameAsLastMission()) _missionError.emit(MissionError.NOT_EXIST) + handleMissionError(isSameAsLastMission()) } } } @@ -211,7 +211,7 @@ class BoardViewModel @Inject constructor( else -> { _missionUiModel.emit(MissionUiModel.Error) - if(!isSameAsLastMission()) _missionError.emit(MissionError.NOT_EXIST) + handleMissionError(isSameAsLastMission()) } } } @@ -228,7 +228,7 @@ class BoardViewModel @Inject constructor( else -> { _missionVerificationUiModel.emit(MissionVerificationUiModel.Error) - if(!isSameAsLastMission()) _missionError.emit(MissionError.NOT_EXIST) + handleMissionError(isSameAsLastMission()) } } } @@ -293,6 +293,15 @@ class BoardViewModel @Inject constructor( } } + fun resetMissionError() { + _missionError.value = null + } + + private suspend fun handleMissionError(isSameAsLastMission : Boolean){ + if(isSameAsLastMission) _missionError.emit(MissionError.INVALID_MISSION) + else _missionError.emit(MissionError.NOT_EXIST) + } + private suspend fun isSameAsLastMission(): Boolean { return when (val result = getJoinedMissionsUseCase(filter = statusString).firstOrNull()) { is DomainResult.Success -> { diff --git a/feature/board/src/main/res/values/strings.xml b/feature/board/src/main/res/values/strings.xml index 7d45613..e62eb5b 100644 --- a/feature/board/src/main/res/values/strings.xml +++ b/feature/board/src/main/res/values/strings.xml @@ -53,11 +53,13 @@ 인증횟수(보드판 수)는 총 %d개 삭제하기 - 미션을 불러올 수 없습니다. + 미션을 불러올 수 없어요. 에러가 발생하였습니다. 확인 취소 닫기 업로드 + + 재시도