From 8a1c5d2c16464045af7169d2499610c20d27c8f6 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 02:26:59 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat:=20default=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/img_default_progile.xml | 45 +++++++++++++++++++ .../presentation/mypage/MyPageScreen.kt | 7 +-- 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 core/designsystem/src/main/res/drawable/img_default_progile.xml diff --git a/core/designsystem/src/main/res/drawable/img_default_progile.xml b/core/designsystem/src/main/res/drawable/img_default_progile.xml new file mode 100644 index 00000000..ec518560 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/img_default_progile.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt index bbe92722..165129f5 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt @@ -17,7 +17,8 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -77,10 +78,10 @@ private fun MyPageScreen( Spacer(modifier = Modifier.height(32.dp)) Image( - painter = ColorPainter(BitnagilTheme.colors.coolGray98), + imageVector = ImageVector.vectorResource(R.drawable.img_default_progile), contentDescription = null, modifier = Modifier - .size(80.dp) + .size(90.dp) .clip(shape = CircleShape), ) From dc3d6f96771b9a276b859356a064a683d9ca398d Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 04:11:48 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Feat:=20=EC=84=A4=EC=A0=95=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=EC=84=9C=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EB=B0=8F=20=ED=9A=8C=EC=9B=90=20=ED=83=88=ED=87=B4?= =?UTF-8?q?=20=EC=8B=9C=20ConfirmDialog=20=EB=85=B8=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/drawable/ic_warning.xml | 19 +++ .../presentation/setting/SettingScreen.kt | 14 ++- .../presentation/setting/SettingViewModel.kt | 50 ++++++-- .../setting/component/block/ConfirmDialog.kt | 115 ++++++++++++++++++ .../setting/model/ConfirmDialogType.kt | 18 +++ .../setting/model/mvi/SettingIntent.kt | 4 + .../setting/model/mvi/SettingState.kt | 3 + 7 files changed, 213 insertions(+), 10 deletions(-) create mode 100644 core/designsystem/src/main/res/drawable/ic_warning.xml create mode 100644 presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt create mode 100644 presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/ConfirmDialogType.kt diff --git a/core/designsystem/src/main/res/drawable/ic_warning.xml b/core/designsystem/src/main/res/drawable/ic_warning.xml new file mode 100644 index 00000000..fb6d8061 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_warning.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt index 068dd103..c3c1daf8 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt @@ -29,6 +29,7 @@ import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar import com.threegap.bitnagil.presentation.common.flow.collectAsEffect import com.threegap.bitnagil.presentation.setting.component.atom.settingtitle.SettingTitle import com.threegap.bitnagil.presentation.setting.component.atom.toggleswitch.ToggleSwitch +import com.threegap.bitnagil.presentation.setting.component.block.ConfirmDialog import com.threegap.bitnagil.presentation.setting.model.mvi.SettingSideEffect import com.threegap.bitnagil.presentation.setting.model.mvi.SettingState @@ -48,6 +49,14 @@ fun SettingScreenContainer( } } + state.showConfirmDialog?.let { dialogType -> + ConfirmDialog( + type = dialogType, + onDismiss = viewModel::hideConfirmDialog, + onConfirm = viewModel::confirmDialogAction, + ) + } + SettingScreen( state = state, toggleServiceAlarm = viewModel::toggleServiceAlarm, @@ -56,8 +65,8 @@ fun SettingScreenContainer( onClickBack = navigateToBack, onClickTermsOfService = navigateToTermsOfService, onClickPrivacyPolicy = navigateToPrivacyPolicy, - onClickLogout = viewModel::logout, - onClickWithdrawal = viewModel::withdrawal, + onClickLogout = viewModel::showLogoutDialog, + onClickWithdrawal = viewModel::showWithdrawalDialog, ) } @@ -213,6 +222,7 @@ fun SettingScreenPreview() { version = "1.0.1", latestVersion = "1.0.0", loading = false, + showConfirmDialog = null, ), toggleServiceAlarm = {}, togglePushAlarm = {}, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt index baa49ba5..90769786 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.threegap.bitnagil.domain.auth.usecase.LogoutUseCase import com.threegap.bitnagil.domain.auth.usecase.WithdrawalUseCase import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel +import com.threegap.bitnagil.presentation.setting.model.ConfirmDialogType import com.threegap.bitnagil.presentation.setting.model.mvi.SettingIntent import com.threegap.bitnagil.presentation.setting.model.mvi.SettingSideEffect import com.threegap.bitnagil.presentation.setting.model.mvi.SettingState @@ -41,15 +42,24 @@ class SettingViewModel @Inject constructor( ) } SettingIntent.TogglePushAlarm -> { - return state.copy( - usePushAlarm = !state.usePushAlarm, - ) + return state.copy(usePushAlarm = !state.usePushAlarm) } SettingIntent.ToggleServiceAlarm -> { - return state.copy( - useServiceAlarm = !state.useServiceAlarm, - ) + return state.copy(useServiceAlarm = !state.useServiceAlarm) + } + + is SettingIntent.ShowConfirmDialog -> { + return state.copy(showConfirmDialog = intent.type) } + + is SettingIntent.HideConfirmDialog -> { + return state.copy(showConfirmDialog = null) + } + + is SettingIntent.ConfirmDialogAction -> { + return state.copy(showConfirmDialog = null) + } + SettingIntent.LogoutSuccess -> { sendSideEffect(SettingSideEffect.NavigateToIntro) return null @@ -73,6 +83,30 @@ class SettingViewModel @Inject constructor( } } + fun showLogoutDialog() { + sendIntent(SettingIntent.ShowConfirmDialog(ConfirmDialogType.LOGOUT)) + } + + fun showWithdrawalDialog() { + sendIntent(SettingIntent.ShowConfirmDialog(ConfirmDialogType.WITHDRAW)) + } + + fun hideConfirmDialog() { + sendIntent(SettingIntent.HideConfirmDialog) + } + + fun confirmDialogAction() { + val currentDialogType = container.stateFlow.value.showConfirmDialog + + sendIntent(SettingIntent.ConfirmDialogAction) + + when (currentDialogType) { + ConfirmDialogType.LOGOUT -> executeLogout() + ConfirmDialogType.WITHDRAW -> executeWithdrawal() + null -> {} + } + } + fun toggleServiceAlarm() { sendIntent(SettingIntent.ToggleServiceAlarm) setServiceAlarmJob?.cancel() @@ -89,7 +123,7 @@ class SettingViewModel @Inject constructor( } } - fun logout() { + private fun executeLogout() { viewModelScope.launch { sendIntent(SettingIntent.LogoutLoading) logoutUseCase().onSuccess { @@ -100,7 +134,7 @@ class SettingViewModel @Inject constructor( } } - fun withdrawal() { + private fun executeWithdrawal() { viewModelScope.launch { sendIntent(SettingIntent.WithdrawalLoading) withdrawalUseCase().onSuccess { diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt new file mode 100644 index 00000000..83889373 --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt @@ -0,0 +1,115 @@ +package com.threegap.bitnagil.presentation.setting.component.block + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.DialogProperties +import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.R +import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon +import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButton +import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButtonColor +import com.threegap.bitnagil.presentation.setting.model.ConfirmDialogType + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ConfirmDialog( + type: ConfirmDialogType, + onDismiss: () -> Unit, + onConfirm: () -> Unit, + modifier: Modifier = Modifier, +) { + BasicAlertDialog( + modifier = modifier, + onDismissRequest = onDismiss, + properties = DialogProperties( + dismissOnBackPress = true, + dismissOnClickOutside = true, + ), + ) { + Column( + modifier = Modifier + .background( + color = BitnagilTheme.colors.white, + shape = RoundedCornerShape(20.dp), + ) + .padding(vertical = 24.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + BitnagilIcon( + id = R.drawable.ic_warning, + tint = null, + modifier = Modifier.size(55.dp), + ) + + Spacer(modifier = Modifier.height(18.dp)) + + Text( + text = type.titleText, + color = BitnagilTheme.colors.coolGray10, + style = BitnagilTheme.typography.title2Bold, + ) + + Spacer(modifier = Modifier.height(2.dp)) + + Text( + text = type.descriptionText, + color = BitnagilTheme.colors.coolGray10, + style = BitnagilTheme.typography.caption1Regular, + ) + + Spacer(modifier = Modifier.height(18.dp)) + + Row( + modifier = Modifier.height(44.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + BitnagilTextButton( + text = "취소", + onClick = onDismiss, + colors = BitnagilTextButtonColor.skip(), + modifier = Modifier + .weight(1f) + .border( + width = 1.dp, + color = BitnagilTheme.colors.navy500, + shape = RoundedCornerShape(8.dp), + ), + ) + + BitnagilTextButton( + text = type.confirmButtonText, + onClick = onConfirm, + shape = RoundedCornerShape(8.dp), + modifier = Modifier.weight(1f), + ) + } + } + } +} + +@Preview +@Composable +private fun ConfirmDialogPreview() { + ConfirmDialog( + type = ConfirmDialogType.LOGOUT, + onDismiss = {}, + onConfirm = {}, + ) +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/ConfirmDialogType.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/ConfirmDialogType.kt new file mode 100644 index 00000000..c26c4cbd --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/ConfirmDialogType.kt @@ -0,0 +1,18 @@ +package com.threegap.bitnagil.presentation.setting.model + +enum class ConfirmDialogType( + val titleText: String, + val descriptionText: String, + val confirmButtonText: String, +) { + LOGOUT( + titleText = "로그아웃 하시겠어요?", + descriptionText = "버튼을 누르면 로그인 페이지로 이동해요.", + confirmButtonText = "로그아웃", + ), + WITHDRAW( + titleText = "정말 탈퇴하시겠어요?", + descriptionText = "소중한 기록들이 모두 사라져요.", + confirmButtonText = "탈퇴하기", + ), +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt index 066691f3..b344863e 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt @@ -1,6 +1,7 @@ package com.threegap.bitnagil.presentation.setting.model.mvi import com.threegap.bitnagil.presentation.common.mviviewmodel.MviIntent +import com.threegap.bitnagil.presentation.setting.model.ConfirmDialogType sealed class SettingIntent : MviIntent { data class LoadSettingSuccess( @@ -10,6 +11,9 @@ sealed class SettingIntent : MviIntent { val latestVersion: String, ) : SettingIntent() + data class ShowConfirmDialog(val type: ConfirmDialogType) : SettingIntent() + data object HideConfirmDialog : SettingIntent() + data object ConfirmDialogAction : SettingIntent() data object ToggleServiceAlarm : SettingIntent() data object TogglePushAlarm : SettingIntent() data object LogoutLoading : SettingIntent() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingState.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingState.kt index e2382526..a0b7166b 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingState.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingState.kt @@ -1,6 +1,7 @@ package com.threegap.bitnagil.presentation.setting.model.mvi import com.threegap.bitnagil.presentation.common.mviviewmodel.MviState +import com.threegap.bitnagil.presentation.setting.model.ConfirmDialogType import kotlinx.parcelize.Parcelize @Parcelize @@ -10,6 +11,7 @@ data class SettingState( val version: String, val latestVersion: String, val loading: Boolean, + val showConfirmDialog: ConfirmDialogType?, ) : MviState { companion object { val Init = SettingState( @@ -18,6 +20,7 @@ data class SettingState( version = "", latestVersion = "", loading = false, + showConfirmDialog = null, ) } } From f8b7b9d6a9a26d1a1dde38211a94a03505a78d2b Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 09:58:50 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20Intent=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ConfirmDialogAction Intent 제거 --- .../bitnagil/presentation/setting/SettingViewModel.kt | 6 +----- .../presentation/setting/model/mvi/SettingIntent.kt | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt index 90769786..9b8c4e88 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingViewModel.kt @@ -56,10 +56,6 @@ class SettingViewModel @Inject constructor( return state.copy(showConfirmDialog = null) } - is SettingIntent.ConfirmDialogAction -> { - return state.copy(showConfirmDialog = null) - } - SettingIntent.LogoutSuccess -> { sendSideEffect(SettingSideEffect.NavigateToIntro) return null @@ -98,7 +94,7 @@ class SettingViewModel @Inject constructor( fun confirmDialogAction() { val currentDialogType = container.stateFlow.value.showConfirmDialog - sendIntent(SettingIntent.ConfirmDialogAction) + sendIntent(SettingIntent.HideConfirmDialog) when (currentDialogType) { ConfirmDialogType.LOGOUT -> executeLogout() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt index b344863e..9438f5d4 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/model/mvi/SettingIntent.kt @@ -13,7 +13,6 @@ sealed class SettingIntent : MviIntent { data class ShowConfirmDialog(val type: ConfirmDialogType) : SettingIntent() data object HideConfirmDialog : SettingIntent() - data object ConfirmDialogAction : SettingIntent() data object ToggleServiceAlarm : SettingIntent() data object TogglePushAlarm : SettingIntent() data object LogoutLoading : SettingIntent()