From 58a4faea4d8907e3fcd63b8ab6ddf5f246652d9e Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Wed, 4 Mar 2026 05:06:01 +0900 Subject: [PATCH 1/3] Merge branch 'feat/#112-task-certification-poke' into feat/#119-photolog-upload-modifiy --- .../components/photolog/BackgroundCard.kt | 22 +- .../src/main/res/drawable/ic_doubt.xml | 136 ++++------ .../src/main/res/drawable/ic_fuck.xml | 84 +++--- .../src/main/res/drawable/ic_happy.xml | 89 +++--- .../src/main/res/drawable/ic_keepi_angry.xml | 69 ----- .../src/main/res/drawable/ic_keepi_doubt.xml | 85 ------ .../src/main/res/drawable/ic_keepi_fuck.xml | 135 ---------- .../src/main/res/drawable/ic_keepi_happy.xml | 87 ------ .../src/main/res/drawable/ic_keepi_love.xml | 84 ------ .../src/main/res/drawable/ic_keepi_sting.xml | 118 -------- .../main/res/drawable/ic_keepi_trouble.xml | 125 --------- .../src/main/res/drawable/ic_love.xml | 89 +++--- .../res/drawable/ic_my_reaction_union.xml | 12 + .../res/drawable/ic_photolog_action_poke.xml | 139 ++++++++++ .../src/main/res/drawable/ic_trouble.xml | 253 ++++++++++-------- .../src/main/res/values/strings.xml | 4 +- .../java/com/twix/navigation/NavRoutes.kt | 6 +- .../twix/home/component/GoalVerifications.kt | 2 +- .../twix/stats/detail/StatsDetailScreen.kt | 3 +- .../twix/stats/detail/StatsDetailViewModel.kt | 1 + .../detail/contract/StatsDetailSideEffect.kt | 1 + .../detail/navigation/StatsDetailGraph.kt | 3 +- .../detail/TaskCertificationDetail.kt | 77 ++++-- .../TaskCertificationDetailViewModel.kt | 38 ++- .../component/TaskCertificationCardContent.kt | 77 +++++- .../component/reaction/ReactionEffect.kt | 6 + .../component/reaction/ReactionUiModel.kt | 10 +- .../contract/TaskCertificationDetailIntent.kt | 4 +- .../TaskCertificationDetailSideEffect.kt | 4 + .../TaskCertificationDetailUiState.kt | 96 ++++++- .../navigation/TaskCertificationGraph.kt | 4 + 31 files changed, 782 insertions(+), 1081 deletions(-) delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_angry.xml delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_doubt.xml delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_fuck.xml delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_happy.xml delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_love.xml delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_sting.xml delete mode 100644 core/design-system/src/main/res/drawable/ic_keepi_trouble.xml create mode 100644 core/design-system/src/main/res/drawable/ic_my_reaction_union.xml create mode 100644 core/design-system/src/main/res/drawable/ic_photolog_action_poke.xml diff --git a/core/design-system/src/main/java/com/twix/designsystem/components/photolog/BackgroundCard.kt b/core/design-system/src/main/java/com/twix/designsystem/components/photolog/BackgroundCard.kt index ab898f48..482eda29 100644 --- a/core/design-system/src/main/java/com/twix/designsystem/components/photolog/BackgroundCard.kt +++ b/core/design-system/src/main/java/com/twix/designsystem/components/photolog/BackgroundCard.kt @@ -27,11 +27,11 @@ import com.twix.ui.extension.noRippleClickable @Composable fun BackgroundCard( - isCertificated: Boolean, uploadedAt: String, - buttonTitle: String, - onClick: () -> Unit, + actionLabel: String, rotation: Float, + onClickAction: () -> Unit, + showActionButton: Boolean, ) { Column { PhotologCard( @@ -39,7 +39,7 @@ fun BackgroundCard( borderColor = GrayColor.C500, rotation = rotation, ) - if (isCertificated) { + if (!showActionButton) { AppText( text = uploadedAt, style = AppTextStyle.B4, @@ -60,19 +60,19 @@ fun BackgroundCard( Modifier .width(150.dp) .height(74.dp) - .noRippleClickable { onClick() }, - text = buttonTitle, + .noRippleClickable { onClickAction() }, + text = actionLabel, textColor = GrayColor.C500, backgroundColor = CommonColor.White, ) } Image( - imageVector = ImageVector.vectorResource(R.drawable.ic_keepi_sting), + imageVector = ImageVector.vectorResource(R.drawable.ic_photolog_action_poke), contentDescription = null, modifier = Modifier - .padding(end = 24.dp, top = 15.dp) + .padding(end = 16.dp, top = 15.dp) .align(Alignment.TopEnd), ) } @@ -85,10 +85,10 @@ fun BackgroundCard( fun PreviewBackgroundCard() { TwixTheme { BackgroundCard( - buttonTitle = stringResource(R.string.word_sting), + actionLabel = stringResource(R.string.word_sting), uploadedAt = "2023.10.31 23:59", - onClick = {}, - isCertificated = true, + onClickAction = {}, + showActionButton = true, rotation = -8f, ) } diff --git a/core/design-system/src/main/res/drawable/ic_doubt.xml b/core/design-system/src/main/res/drawable/ic_doubt.xml index bdf5ab45..ddbb2b7a 100644 --- a/core/design-system/src/main/res/drawable/ic_doubt.xml +++ b/core/design-system/src/main/res/drawable/ic_doubt.xml @@ -1,85 +1,67 @@ + android:width="52dp" + android:height="52dp" + android:viewportWidth="52" + android:viewportHeight="52"> + - + - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/core/design-system/src/main/res/drawable/ic_fuck.xml b/core/design-system/src/main/res/drawable/ic_fuck.xml index 97799f48..995c2f67 100644 --- a/core/design-system/src/main/res/drawable/ic_fuck.xml +++ b/core/design-system/src/main/res/drawable/ic_fuck.xml @@ -1,135 +1,135 @@ + android:width="52dp" + android:height="52dp" + android:viewportWidth="52" + android:viewportHeight="52"> + android:pathData="M3.043,3.047h46v46h-46z"/> diff --git a/core/design-system/src/main/res/drawable/ic_happy.xml b/core/design-system/src/main/res/drawable/ic_happy.xml index a15aeaf2..a0ae82a2 100644 --- a/core/design-system/src/main/res/drawable/ic_happy.xml +++ b/core/design-system/src/main/res/drawable/ic_happy.xml @@ -1,87 +1,102 @@ + android:width="52dp" + android:height="52dp" + android:viewportWidth="52" + android:viewportHeight="52"> + android:pathData="M1.93,4.719h49v44h-49z"/> + android:pathData="M16.897,35.942C18.989,34.838 19.789,32.248 18.685,30.157C17.582,28.065 14.991,27.265 12.9,28.368C10.809,29.472 10.008,32.063 11.112,34.154C12.216,36.245 14.806,37.046 16.897,35.942Z" + android:fillColor="#FDE0DF"/> + android:pathData="M38.389,28.387C40.481,27.284 41.281,24.693 40.178,22.602C39.074,20.511 36.484,19.71 34.392,20.814C32.301,21.918 31.5,24.508 32.604,26.599C33.708,28.691 36.298,29.491 38.389,28.387Z" + android:fillColor="#FDE0DF"/> - + android:pathData="M39.641,16.583C39.641,16.583 40.623,12.381 44.924,13.397C49.225,14.412 50.034,22.535 43.265,23.493" + android:fillColor="#ffffff"/> + android:pathData="M19.366,23.199C19.117,23.046 18.916,22.884 18.723,22.779C18.465,22.638 18.248,22.546 18.052,22.45C17.826,22.34 17.611,22.238 17.379,22.131C17.183,22.035 16.951,21.973 16.705,21.826C16.512,21.721 16.309,21.568 16.063,21.406" + android:strokeLineJoin="round" + android:strokeWidth="1.38" + android:fillColor="#00000000" + android:strokeColor="#181818" + android:strokeLineCap="round"/> + + diff --git a/core/design-system/src/main/res/drawable/ic_keepi_angry.xml b/core/design-system/src/main/res/drawable/ic_keepi_angry.xml deleted file mode 100644 index 1a396e8c..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_angry.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_keepi_doubt.xml b/core/design-system/src/main/res/drawable/ic_keepi_doubt.xml deleted file mode 100644 index 45601312..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_doubt.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_keepi_fuck.xml b/core/design-system/src/main/res/drawable/ic_keepi_fuck.xml deleted file mode 100644 index 22d0db5f..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_fuck.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_keepi_happy.xml b/core/design-system/src/main/res/drawable/ic_keepi_happy.xml deleted file mode 100644 index ce8d791d..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_happy.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_keepi_love.xml b/core/design-system/src/main/res/drawable/ic_keepi_love.xml deleted file mode 100644 index ef233362..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_love.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_keepi_sting.xml b/core/design-system/src/main/res/drawable/ic_keepi_sting.xml deleted file mode 100644 index ca28a97f..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_sting.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_keepi_trouble.xml b/core/design-system/src/main/res/drawable/ic_keepi_trouble.xml deleted file mode 100644 index 16ca9adf..00000000 --- a/core/design-system/src/main/res/drawable/ic_keepi_trouble.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/design-system/src/main/res/drawable/ic_love.xml b/core/design-system/src/main/res/drawable/ic_love.xml index 476ecc69..45b98ba7 100644 --- a/core/design-system/src/main/res/drawable/ic_love.xml +++ b/core/design-system/src/main/res/drawable/ic_love.xml @@ -1,84 +1,101 @@ + android:width="52dp" + android:height="52dp" + android:viewportWidth="52" + android:viewportHeight="52"> + android:pathData="M4.711,2.648h42v47h-42z"/> + android:pathData="M16.956,31.1C19.032,30.004 19.827,27.433 18.731,25.357C17.636,23.282 15.065,22.487 12.989,23.583C10.913,24.678 10.119,27.249 11.214,29.325C12.31,31.401 14.881,32.195 16.956,31.1Z" + android:fillColor="#FDE0DF"/> + android:pathData="M38.277,30.084C40.353,28.988 41.147,26.418 40.051,24.342C38.956,22.266 36.385,21.472 34.309,22.567C32.234,23.663 31.439,26.233 32.535,28.309C33.63,30.385 36.201,31.18 38.277,30.084Z" + android:fillColor="#FDE0DF"/> - + + android:pathData="M22.942,28.705L22.582,29.552L23.118,31.977L24.468,30.666L26.581,30.549L28.076,30.069L30.025,30.9L29.773,28.305L27.603,28.172L25.887,27.879L24.279,28.769L22.942,28.71V28.705Z" + android:fillColor="#BC6159"/> + + + diff --git a/core/design-system/src/main/res/drawable/ic_my_reaction_union.xml b/core/design-system/src/main/res/drawable/ic_my_reaction_union.xml new file mode 100644 index 00000000..e2133fff --- /dev/null +++ b/core/design-system/src/main/res/drawable/ic_my_reaction_union.xml @@ -0,0 +1,12 @@ + + + + diff --git a/core/design-system/src/main/res/drawable/ic_photolog_action_poke.xml b/core/design-system/src/main/res/drawable/ic_photolog_action_poke.xml new file mode 100644 index 00000000..2d58e737 --- /dev/null +++ b/core/design-system/src/main/res/drawable/ic_photolog_action_poke.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/design-system/src/main/res/drawable/ic_trouble.xml b/core/design-system/src/main/res/drawable/ic_trouble.xml index 35894ac5..37a013a9 100644 --- a/core/design-system/src/main/res/drawable/ic_trouble.xml +++ b/core/design-system/src/main/res/drawable/ic_trouble.xml @@ -1,125 +1,144 @@ + android:width="52dp" + android:height="52dp" + android:viewportWidth="52" + android:viewportHeight="52"> + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index f796c47b..67fdf85c 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -45,8 +45,8 @@ 끝내기 이뤘어요 탈퇴하기 - 찌르기 - 찌르기! + 찌르기 + 찌르기! 오늘 우리 목표 diff --git a/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt b/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt index 008c6412..b3139b1f 100644 --- a/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt +++ b/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt @@ -35,16 +35,18 @@ sealed class NavRoutes( object TaskCertificationGraph : NavRoutes("task_certification_graph") object TaskCertificationDetailRoute : - NavRoutes("task_certification_detail/{goalId}/{date}/{betweenUs}") { + NavRoutes("task_certification_detail/{goalId}/{date}/{betweenUs}?isCompleted={isCompleted}") { const val ARG_GOAL_ID = "goalId" const val ARG_DATE = "date" const val ARG_BETWEEN_US = "betweenUs" + const val ARG_IS_COMPLETED = "isCompleted" fun createRoute( goalId: Long, date: LocalDate, betweenUs: String, - ) = "task_certification_detail/$goalId/$date/$betweenUs" + isCompleted: Boolean = false, + ) = "task_certification_detail/$goalId/$date/$betweenUs?isCompleted=$isCompleted" } object TaskCertificationRoute : NavRoutes("task_certification/{data}") { diff --git a/feature/main/src/main/java/com/twix/home/component/GoalVerifications.kt b/feature/main/src/main/java/com/twix/home/component/GoalVerifications.kt index 8ff1f6d9..e1b25212 100644 --- a/feature/main/src/main/java/com/twix/home/component/GoalVerifications.kt +++ b/feature/main/src/main/java/com/twix/home/component/GoalVerifications.kt @@ -91,7 +91,7 @@ private fun EmptyContent( ) AppRoundButton( - text = stringResource(R.string.action_sting_emphasized), + text = stringResource(R.string.action_poke_emphasized), textColor = GrayColor.C500, textStyle = AppTextStyle.C2, backgroundColor = CommonColor.White, diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt index 8c1e4a39..35dd2e97 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt @@ -61,7 +61,7 @@ import java.time.LocalDate fun StatsDetailRoute( onBack: () -> Unit, navigateToGoalEditor: (Long) -> Unit, - navigateToTaskCertificationDetail: (Long, LocalDate, BetweenUs) -> Unit, + navigateToTaskCertificationDetail: (Long, LocalDate, BetweenUs, Boolean) -> Unit, toastManager: ToastManager = koinInject(), viewModel: StatsDetailViewModel = koinViewModel(), ) { @@ -79,6 +79,7 @@ fun StatsDetailRoute( sideEffect.goalId, sideEffect.date, sideEffect.betweenUs, + sideEffect.isCompleted, ) is StatsDetailSideEffect.ShowToast -> { toastManager.tryShow( diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt index b047036f..9e578d2e 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt @@ -211,6 +211,7 @@ class StatsDetailViewModel( goalId = argGoalId, date = selectedDate, betweenUs = determineDisplayBetweenUs(completedDate.date), + isCompleted = currentState.detail.isCompleted, ), ) } diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt index a8777465..d7c2d393 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt @@ -21,5 +21,6 @@ sealed interface StatsDetailSideEffect : SideEffect { val goalId: Long, val date: LocalDate, val betweenUs: BetweenUs, + val isCompleted: Boolean, ) : StatsDetailSideEffect } diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt index b2052d2c..ef12f777 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt @@ -36,12 +36,13 @@ object StatsDetailGraph : NavGraphContributor { launchSingleTop = true } }, - navigateToTaskCertificationDetail = { goalId, date, betweenUs -> + navigateToTaskCertificationDetail = { goalId, date, betweenUs, isCompleted -> val destination = NavRoutes.TaskCertificationDetailRoute.createRoute( goalId = goalId, date = date, betweenUs = betweenUs.name, + isCompleted = isCompleted, ) navController.navigate(destination) { launchSingleTop = true diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt index 21a8e50b..07770dc7 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt @@ -4,6 +4,7 @@ import android.Manifest import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -14,6 +15,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -30,6 +32,8 @@ import com.twix.domain.model.enums.GoalReactionType import com.twix.task_certification.detail.component.TaskCertificationCardContent import com.twix.task_certification.detail.component.TaskCertificationDetailTopBar import com.twix.task_certification.detail.component.reaction.ReactionContent +import com.twix.task_certification.detail.component.reaction.ReactionEffect +import com.twix.task_certification.detail.component.reaction.ReactionEffectSpec import com.twix.task_certification.detail.contract.TaskCertificationDetailIntent import com.twix.task_certification.detail.contract.TaskCertificationDetailSideEffect import com.twix.task_certification.detail.contract.TaskCertificationDetailUiState @@ -62,6 +66,12 @@ fun TaskCertificationDetailRoute( ToastData(currentContext.getString(sideEffect.message), sideEffect.type), ) } + + is TaskCertificationDetailSideEffect.ShowPokeToast -> { + toastManager.tryShow( + ToastData(sideEffect.message, ToastType.SUCCESS), + ) + } } } @@ -96,26 +106,49 @@ fun TaskCertificationDetailRoute( } } - TaskCertificationDetailScreen( - uiState = uiState, - onBack = navigateToBack, - onClickModify = { - navigateToEditor( - uiState.goalId, - uiState.selectedDate, - ) - }, - onClickReaction = { viewModel.dispatch(TaskCertificationDetailIntent.Reaction(it)) }, - onClickUpload = { - if (currentContext.hasCameraPermission()) { - navigateToCertification(uiState.goalId, uiState.selectedDate) - } else { - permissionLauncher.launch(Manifest.permission.CAMERA) + BoxWithConstraints { + val density = LocalDensity.current + val screenHeightPx = with(density) { maxHeight.toPx() } + + TaskCertificationDetailScreen( + uiState = uiState, + onBack = navigateToBack, + onClickModify = { + navigateToEditor( + uiState.goalId, + uiState.selectedDate, + ) + }, + onClickReaction = { viewModel.dispatch(TaskCertificationDetailIntent.Reaction(it)) }, + onClickUpload = { + if (currentContext.hasCameraPermission()) { + navigateToCertification(uiState.goalId, uiState.selectedDate) + } else { + permissionLauncher.launch(Manifest.permission.CAMERA) + } + }, + onPoke = { viewModel.dispatch(TaskCertificationDetailIntent.Poke) }, + onSwipe = { viewModel.dispatch(TaskCertificationDetailIntent.SwipeCard) }, + ) + if (!uiState.hasShownMyReaction && uiState.isDisplayedMyPhotolog) { + val model = uiState.myReaction + if (model != null) { + ReactionEffect( + targetReaction = model, + spec = + ReactionEffectSpec( + particleCount = 10, + durationRange = 500..800, + // 전체 화면 높이까지 퍼짐 + travelDistanceRange = 500..screenHeightPx.toInt(), + ), + onFinished = { + viewModel.dispatch(TaskCertificationDetailIntent.MyReactionEffected) + }, + ) } - }, - onClickSting = { viewModel.dispatch(TaskCertificationDetailIntent.Sting) }, - onSwipe = { viewModel.dispatch(TaskCertificationDetailIntent.SwipeCard) }, - ) + } + } } @Composable @@ -125,7 +158,7 @@ fun TaskCertificationDetailScreen( onClickModify: () -> Unit, onClickReaction: (GoalReactionType) -> Unit, onClickUpload: () -> Unit, - onClickSting: () -> Unit, + onPoke: () -> Unit, onSwipe: () -> Unit, ) { Column( @@ -146,7 +179,7 @@ fun TaskCertificationDetailScreen( uiState = uiState, onSwipe = onSwipe, onClickUpload = onClickUpload, - onClickSting = onClickSting, + onPoke = onPoke, ) if (uiState.canReaction) { @@ -172,7 +205,7 @@ private fun TaskCertificationDetailScreenPreview( onClickModify = {}, onClickReaction = {}, onClickUpload = {}, - onClickSting = {}, + onPoke = {}, onSwipe = {}, ) } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt index f24edb60..d24a1e96 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt @@ -7,6 +7,7 @@ import com.twix.designsystem.components.toast.model.ToastType import com.twix.domain.model.enums.BetweenUs import com.twix.domain.model.enums.GoalReactionType import com.twix.domain.repository.PhotoLogRepository +import com.twix.domain.repository.PokeRepository import com.twix.navigation.NavRoutes import com.twix.task_certification.detail.contract.TaskCertificationDetailIntent import com.twix.task_certification.detail.contract.TaskCertificationDetailSideEffect @@ -26,6 +27,7 @@ import java.time.LocalDate class TaskCertificationDetailViewModel( private val photologRepository: PhotoLogRepository, + private val pokeRepository: PokeRepository, private val detailRefreshBus: TaskCertificationRefreshBus, private val goalRefreshBus: GoalRefreshBus, savedStateHandle: SavedStateHandle, @@ -46,6 +48,9 @@ class TaskCertificationDetailViewModel( savedStateHandle[NavRoutes.TaskCertificationDetailRoute.ARG_BETWEEN_US] ?: error(BETWEEN_US_NOT_FOUND) + private val argIsCompleted: Boolean = + savedStateHandle[NavRoutes.TaskCertificationDetailRoute.ARG_IS_COMPLETED] ?: false + private var lastReaction: GoalReactionType? = null private val reactionFlow = @@ -63,7 +68,16 @@ class TaskCertificationDetailViewModel( private fun fetchPhotolog() { launchResult( block = { photologRepository.fetchPhotologs(argTargetDate, argGoalId) }, - onSuccess = { reduce { it.toUiState(argGoalId, argBetweenUs, argTargetDate) } }, + onSuccess = { + reduce { + it.toUiState( + argGoalId, + argBetweenUs, + argTargetDate, + argIsCompleted, + ) + } + }, onError = { showToast(R.string.task_certification_detail_fetch_photolog_fail, ToastType.ERROR) }, @@ -79,6 +93,7 @@ class TaskCertificationDetailViewModel( .debounce(DEBOUNCE_INTERVAL) .collectLatest { reaction -> reactToPhotolog(reaction) + goalRefreshBus.notifyGoalListChanged() } } } @@ -120,8 +135,9 @@ class TaskCertificationDetailViewModel( override suspend fun handleIntent(intent: TaskCertificationDetailIntent) { when (intent) { is TaskCertificationDetailIntent.Reaction -> reduceReaction(intent.type) - TaskCertificationDetailIntent.Sting -> TODO("찌르기 API 연동") + TaskCertificationDetailIntent.Poke -> pokeToPartner() TaskCertificationDetailIntent.SwipeCard -> reduceShownCard() + TaskCertificationDetailIntent.MyReactionEffected -> reduceMyReactionShown() } } @@ -131,6 +147,14 @@ class TaskCertificationDetailViewModel( reactionFlow.tryEmit(reaction) } + private fun pokeToPartner() { + launchResult( + block = { pokeRepository.pokeGoal(argGoalId) }, + onSuccess = { tryEmitSideEffect(TaskCertificationDetailSideEffect.ShowPokeToast(it.message)) }, + onError = { showToast(R.string.toast_poke_goal_failed, ToastType.ERROR) }, + ) + } + private fun reduceShownCard() { reduce { toggleBetweenUs() } } @@ -144,13 +168,15 @@ class TaskCertificationDetailViewModel( }, ) - private fun showToast( + private fun reduceMyReactionShown() { + reduce { copy(hasShownMyReaction = true) } + } + + private suspend fun showToast( message: Int, type: ToastType, ) { - viewModelScope.launch { - emitSideEffect(TaskCertificationDetailSideEffect.ShowToast(message, type)) - } + emitSideEffect(TaskCertificationDetailSideEffect.ShowToast(message, type)) } companion object { diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt index 836901c7..0f865749 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt @@ -1,41 +1,50 @@ package com.twix.task_certification.detail.component +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp import com.twix.designsystem.R import com.twix.designsystem.components.photolog.BackgroundCard import com.twix.designsystem.components.photolog.ForegroundCard +import com.twix.designsystem.theme.TwixTheme import com.twix.domain.model.enums.BetweenUs +import com.twix.task_certification.detail.component.reaction.ReactionUiModel import com.twix.task_certification.detail.component.swipe.SwipeableCard import com.twix.task_certification.detail.contract.TaskCertificationDetailUiState +import com.twix.task_certification.detail.preview.TaskCertificationDetailPreviewProvider @Composable internal fun TaskCertificationCardContent( uiState: TaskCertificationDetailUiState, onSwipe: () -> Unit, onClickUpload: () -> Unit, - onClickSting: () -> Unit, + onPoke: () -> Unit, ) { - Box(Modifier.fillMaxWidth()) { + Box { BackgroundCard( - isCertificated = uiState.isDisplayedGoalCertificated, uploadedAt = uiState.displayedGoalUpdateAt, - buttonTitle = + actionLabel = when (uiState.currentShow) { BetweenUs.ME -> stringResource(R.string.task_certification_take_picture) - BetweenUs.PARTNER -> stringResource(R.string.action_sting) + BetweenUs.PARTNER -> stringResource(R.string.action_poke) }, rotation = if (uiState.isDisplayedMyPhotolog) -8f else 0f, - onClick = if (uiState.isDisplayedMyPhotolog) onClickUpload else onClickSting, + onClickAction = if (uiState.isDisplayedMyPhotolog) onClickUpload else onPoke, + showActionButton = uiState.showActionButton, ) SwipeableCard( onSwipe = onSwipe, isDisplayingMyPhoto = uiState.isDisplayedMyPhotolog, - modifier = Modifier.fillMaxWidth(), ) { ForegroundCard( isCertificated = uiState.isDisplayedGoalCertificated, @@ -46,5 +55,57 @@ internal fun TaskCertificationCardContent( rotation = if (uiState.isDisplayedMyPhotolog) 0f else -8f, ) } + + MyReactionBadge( + visible = uiState.showMyPhotologReactionBadge, + reaction = uiState.myReaction, + modifier = + Modifier + .align(Alignment.TopEnd) + .offset(x = (-8).dp, y = (-13).dp), + ) + } +} + +@Composable +private fun MyReactionBadge( + visible: Boolean, + reaction: ReactionUiModel?, + modifier: Modifier = Modifier, +) { + if (!visible) return + + reaction?.let { + Box(modifier = modifier) { + Image( + painter = painterResource(R.drawable.ic_my_reaction_union), + contentDescription = null, + ) + + Image( + painter = painterResource(it.imageResources), + contentDescription = null, + modifier = + Modifier + .padding(bottom = 10.dp) + .align(Alignment.Center), + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun TaskCertificationCardContentPreview( + @PreviewParameter(TaskCertificationDetailPreviewProvider::class) + uiState: TaskCertificationDetailUiState, +) { + TwixTheme { + TaskCertificationCardContent( + uiState = uiState.copy(isLoading = true), + onSwipe = {}, + onClickUpload = {}, + onPoke = {}, + ) } } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt index 696eb339..95ecbf97 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt @@ -33,6 +33,7 @@ fun ReactionEffect( targetReaction: ReactionUiModel?, modifier: Modifier = Modifier, spec: ReactionEffectSpec = ReactionEffectSpec(), + onFinished: () -> Unit = {}, ) { if (targetReaction == null) return @@ -59,6 +60,8 @@ fun ReactionEffect( particles.addAll(newParticles) + var remaining = newParticles.size + // 2. 파티클 애니메이션 실행 newParticles.forEach { particle -> scope.launch { @@ -145,6 +148,9 @@ fun ReactionEffect( ) particles.remove(particle) + + remaining -= 1 + if (remaining == 0) onFinished() } } } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt index 6f68fd1a..2961c377 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt @@ -7,11 +7,11 @@ enum class ReactionUiModel( val type: GoalReactionType, val imageResources: Int, ) { - HAPPY(GoalReactionType.HAPPY, R.drawable.ic_keepi_happy), - TROUBLE(GoalReactionType.TROUBLE, R.drawable.ic_keepi_trouble), - LOVE(GoalReactionType.LOVE, R.drawable.ic_keepi_love), - DOUBT(GoalReactionType.DOUBT, R.drawable.ic_keepi_doubt), - FUCK(GoalReactionType.FUCK, R.drawable.ic_keepi_fuck), + HAPPY(GoalReactionType.HAPPY, R.drawable.ic_happy), + TROUBLE(GoalReactionType.TROUBLE, R.drawable.ic_trouble), + LOVE(GoalReactionType.LOVE, R.drawable.ic_love), + DOUBT(GoalReactionType.DOUBT, R.drawable.ic_doubt), + FUCK(GoalReactionType.FUCK, R.drawable.ic_fuck), ; companion object { diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt index 650100dd..00e57ece 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt @@ -8,7 +8,9 @@ sealed interface TaskCertificationDetailIntent : Intent { val type: GoalReactionType, ) : TaskCertificationDetailIntent - data object Sting : TaskCertificationDetailIntent + data object Poke : TaskCertificationDetailIntent data object SwipeCard : TaskCertificationDetailIntent + + data object MyReactionEffected : TaskCertificationDetailIntent } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt index 202348ef..92532bfb 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt @@ -8,4 +8,8 @@ sealed interface TaskCertificationDetailSideEffect : SideEffect { val message: Int, val type: ToastType, ) : TaskCertificationDetailSideEffect + + data class ShowPokeToast( + val message: String, + ) : TaskCertificationDetailSideEffect } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt index a907b700..f5d70449 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt @@ -5,6 +5,7 @@ import com.twix.domain.model.enums.BetweenUs import com.twix.domain.model.enums.GoalIconType import com.twix.domain.model.photolog.PhotoLogs import com.twix.domain.model.photolog.PhotologDetail +import com.twix.task_certification.detail.component.reaction.ReactionUiModel import com.twix.ui.base.State import com.twix.util.RelativeTimeFormatter import java.time.LocalDate @@ -20,11 +21,22 @@ data class TaskCertificationDetailUiState( val icon: GoalIconType = GoalIconType.DEFAULT, val myPhotolog: PhotologDetail? = null, val partnerPhotolog: PhotologDetail? = null, + val isCompletedGoal: Boolean = false, + /** + * 내 인증샷에 상대방이 리액션을 남겼을 경우 최초 1회 인터렉션 렌더링을 위한 변수 + */ + val hasShownMyReaction: Boolean = false, /** * 초기값으로 인해 찌르기/업로드 버튼이 렌더링 되는 것을 막기 위한 변수 - * */ + */ val isLoading: Boolean = false, ) : State { + /** + * 현재 [currentShow]에 해당하는 사용자의 인증샷 인증 여부 + * + * - [BetweenUs.ME]: 내 인증샷이 존재하면 `true` + * - [BetweenUs.PARTNER]: 파트너 인증샷이 존재하면 `true` + */ val isDisplayedGoalCertificated: Boolean get() = when (currentShow) { @@ -32,6 +44,12 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog != null } + /** + * 현재 [currentShow]에 해당하는 인증샷의 업로드 시간을 상대적 시간 문자열 + * + * - [BetweenUs.ME]: 내 인증샷 업로드 시간 + * - [BetweenUs.PARTNER]: 파트너 인증샷 업로드 시간 + */ val displayedGoalUpdateAt: String get() = when (currentShow) { @@ -42,12 +60,17 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog?.uploadedAt?.let { - RelativeTimeFormatter.format( - it, - ) + RelativeTimeFormatter.format(it) } ?: "" } + /** + * 현재 [currentShow]에 해당하는 인증샷 URL + * + * - [BetweenUs.ME]: 내 인증샷 이미지 URL + * - [BetweenUs.PARTNER]: 파트너 인증샷 이미지 URL + * + */ val displayedGoalImageUrl: String? get() = when (currentShow) { @@ -55,6 +78,13 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog?.imageUrl } + /** + * 현재 [currentShow]에 해당하는 인증샷의 코멘트 + * + * - [BetweenUs.ME]: 내 코멘트 + * - [BetweenUs.PARTNER]: 파트너 코멘트 + * + */ val displayedGoalComment: String? get() = when (currentShow) { @@ -62,6 +92,12 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog?.comment } + /** + * 현재 [currentShow]에 해당하는 사용자의 닉네임 + * + * - [BetweenUs.ME]: 내 닉네임 + * - [BetweenUs.PARTNER]: 파트너 닉네임 + */ val displayedNickname: String get() = when (currentShow) { @@ -69,23 +105,64 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerNickname } + /** + * 현재 화면이 내 인증샷을 표시하는 상태인지 여부 + * + * 내 인증샷일 때 `true` + */ val isDisplayedMyPhotolog: Boolean - get() = - currentShow == BetweenUs.ME + get() = currentShow == BetweenUs.ME + /** + * 내 인증샷를 수정할 수 있는지 여부 반환 + * + * 현재 내 인증샷를 보고 있고([isDisplayedMyPhotolog]), + * 인증이 완료된 상태([isDisplayedGoalCertificated])일 때 `true` + */ val canModify: Boolean - get() = - currentShow == BetweenUs.ME && isDisplayedGoalCertificated + get() = currentShow == BetweenUs.ME && isDisplayedGoalCertificated + /** + * 파트너 인증샷에 리액션을 남길 수 있는지 여부 + * + * 현재 파트너 인증샷을 보고 있고([BetweenUs.PARTNER]), + * 파트너의 인증이 완료된 상태([isDisplayedGoalCertificated])일 때 `true` + */ val canReaction: Boolean + get() = currentShow == BetweenUs.PARTNER && isDisplayedGoalCertificated + + /** + * 인증샷 업로드 또는 찌르기 액션 버튼을 표시할지 여부를 반환 + * + * 목표가 완료되지 않았고([isCompletedGoal]이 `false`), + * 현재 대상의 인증이 없는 상태([isDisplayedGoalCertificated]가 `false`)일 때 `true` + */ + val showActionButton: Boolean + get() = !isCompletedGoal && !isDisplayedGoalCertificated + + /** + * 내 인증샷에 달린 리액션 뱃지를 표시할지 여부를 반환 + * + * 내 인증샷을 보고 있고([isDisplayedMyPhotolog]), + * 리액션이 존재하며([myPhotolog]의 reaction이 non-null) 일 때 `true` + */ + val showMyPhotologReactionBadge: Boolean get() = - currentShow == BetweenUs.PARTNER && isDisplayedGoalCertificated + isDisplayedMyPhotolog && + myPhotolog?.reaction != null + + /** + * 내 인증샷의 리액션을 [ReactionUiModel]로 변환하여 반환 + */ + val myReaction: ReactionUiModel? + get() = myPhotolog?.reaction?.let { ReactionUiModel.find(it) } } fun PhotoLogs.toUiState( goalId: Long, betweenUs: String, selectedDate: LocalDate, + isCompletedGoal: Boolean, ): TaskCertificationDetailUiState { val currentGoalPhotolog = goals.firstOrNull { @@ -102,5 +179,6 @@ fun PhotoLogs.toUiState( icon = currentGoalPhotolog.icon, myPhotolog = currentGoalPhotolog.myPhotolog, partnerPhotolog = currentGoalPhotolog.partnerPhotolog, + isCompletedGoal = isCompletedGoal, ) } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt b/feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt index 8890a49f..30cb6ed1 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt +++ b/feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt @@ -37,6 +37,10 @@ object TaskCertificationGraph : NavGraphContributor { navArgument(NavRoutes.TaskCertificationDetailRoute.ARG_BETWEEN_US) { type = NavType.StringType }, + navArgument(NavRoutes.TaskCertificationDetailRoute.ARG_IS_COMPLETED) { + type = NavType.BoolType + defaultValue = false + }, ), ) { TaskCertificationDetailRoute( From 94c0294666422d96e3c741ba83b903fdef67a212 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Wed, 4 Mar 2026 05:23:00 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor:=20photolog?= =?UTF-8?q?=20=EB=AA=A8=EB=93=88=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- .../java/com/yapp/twix/di/FeatureModules.kt | 4 +- .../components/photolog/ForegroundCard.kt | 2 +- .../src/main/res/values/strings.xml | 34 ++++----- .../java/com/twix/navigation/AppNavHost.kt | 4 +- .../java/com/twix/navigation/NavRoutes.kt | 20 ++--- .../com/twix/navigation/args/DetailNavArgs.kt | 2 +- ...ionRefreshBus.kt => PhotologRefreshBus.kt} | 2 +- .../main/java/com/twix/util/di/UtilModule.kt | 4 +- .../com/twix/main/navigation/MainNavGraph.kt | 6 +- .../navigation/NotificationNavGraph.kt | 4 +- feature/photolog/capture/.gitignore | 1 + .../capture}/build.gradle.kts | 5 +- feature/photolog/capture/consumer-rules.pro | 1 + feature/photolog/capture/proguard-rules.pro | 1 + .../capture}/src/main/AndroidManifest.xml | 0 .../capture/PhotologCaptureScreen.kt} | 66 ++++++++-------- .../capture/PhotologCaptureViewModel.kt} | 76 +++++++++---------- .../capture}/component/CameraControlBar.kt | 6 +- .../capture}/component/CameraPreviewBox.kt | 8 +- .../capture}/component/CommentErrorText.kt | 2 +- .../capture}/component/LoadingContent.kt | 6 +- .../component/PhotologCaptureTopBar.kt} | 8 +- .../contract/PhotologCaptureIntent.kt} | 22 +++--- .../contract/PhotologCaptureSideEffect.kt} | 10 +-- .../contract/PhotologCaptureUiState.kt} | 18 ++--- .../capture/di/PhotologCaptureModule.kt | 13 ++++ .../photolog/capture}/model/CaptureStatus.kt | 2 +- .../photolog/capture}/model/TorchStatus.kt | 2 +- .../photolog/capture}/model/camera/Camera.kt | 4 +- .../capture}/model/camera/CameraPreview.kt | 2 +- .../capture}/model/camera/CaptureCamera.kt | 6 +- feature/photolog/detail/.gitignore | 1 + feature/photolog/detail/build.gradle.kts | 12 +++ feature/photolog/detail/consumer-rules.pro | 1 + feature/photolog/detail/proguard-rules.pro | 1 + .../detail/src/main/AndroidManifest.xml | 2 + .../twix/photolog/detail/PhotologDetail.kt} | 55 +++++++------- .../detail/PhotologDetailViewModel.kt} | 52 ++++++------- .../detail/component/PhotologCardContent.kt} | 24 +++--- .../detail/component/PhotologDetailTopBar.kt} | 10 +-- .../detail/component/reaction/ReactionBar.kt | 2 +- .../component/reaction/ReactionContent.kt | 2 +- .../component/reaction/ReactionEffect.kt | 2 +- .../component/reaction/ReactionEffectSpec.kt | 2 +- .../component/reaction/ReactionParticle.kt | 2 +- .../component/reaction/ReactionUiModel.kt | 2 +- .../detail/component/swipe/SwipeCardSpec.kt | 2 +- .../detail/component/swipe/SwipeableCard.kt | 2 +- .../detail/contract/PhotologDetailIntent.kt | 16 ++++ .../contract/PhotologDetailSideEffect.kt} | 8 +- .../detail/contract/PhotologDetailUiState.kt} | 76 ++----------------- .../detail/di/PhotologDetailModule.kt | 18 +++++ .../detail/navigation/PhotologGraph.kt} | 54 ++++++------- .../preview/PhotologDetailPreviewProvider.kt} | 10 +-- feature/photolog/editor/.gitignore | 1 + feature/photolog/editor/build.gradle.kts | 7 ++ feature/photolog/editor/consumer-rules.pro | 1 + feature/photolog/editor/proguard-rules.pro | 1 + .../editor/src/main/AndroidManifest.xml | 2 + .../photolog/editor/PhotologEditorRoute.kt} | 38 +++++----- .../editor/PhotologEditorViewModel.kt} | 44 +++++------ .../editor/component/PhotologEditorTopBar.kt} | 10 +-- .../editor/component/RetakeButton.kt | 4 +- .../editor/contract/PhotologEditorIntent.kt | 15 ++++ .../contract/PhotologEditorSideEffect.kt} | 6 +- .../editor/contract/PhotologEditorUiState.kt} | 8 +- .../editor/di/PhotologEditorModule.kt | 10 +++ .../twix/stats/detail/StatsDetailScreen.kt | 21 +++-- .../twix/stats/detail/StatsDetailViewModel.kt | 6 +- .../detail/contract/StatsDetailSideEffect.kt | 2 +- .../detail/navigation/StatsDetailGraph.kt | 4 +- feature/task-certification/.gitignore | 1 - feature/task-certification/consumer-rules.pro | 0 feature/task-certification/proguard-rules.pro | 21 ----- .../contract/TaskCertificationDetailIntent.kt | 16 ---- .../di/TaskCertificationModule.kt | 22 ------ .../contract/TaskCertificationEditorIntent.kt | 15 ---- settings.gradle.kts | 4 +- 79 files changed, 460 insertions(+), 498 deletions(-) rename core/util/src/main/java/com/twix/util/bus/{TaskCertificationRefreshBus.kt => PhotologRefreshBus.kt} (93%) create mode 100644 feature/photolog/capture/.gitignore rename feature/{task-certification => photolog/capture}/build.gradle.kts (70%) create mode 100644 feature/photolog/capture/consumer-rules.pro create mode 100644 feature/photolog/capture/proguard-rules.pro rename feature/{task-certification => photolog/capture}/src/main/AndroidManifest.xml (100%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationScreen.kt => photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureScreen.kt} (75%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationViewModel.kt => photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt} (67%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/component/CameraControlBar.kt (96%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/component/CameraPreviewBox.kt (92%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/component/CommentErrorText.kt (96%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/component/LoadingContent.kt (93%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification/component/TaskCertificationTopBar.kt => photolog/capture/src/main/java/com/twix/photolog/capture/component/PhotologCaptureTopBar.kt} (88%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationIntent.kt => photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureIntent.kt} (57%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationSideEffect.kt => photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureSideEffect.kt} (60%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationUiState.kt => photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureUiState.kt} (74%) create mode 100644 feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/model/CaptureStatus.kt (80%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/model/TorchStatus.kt (80%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/model/camera/Camera.kt (76%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/model/camera/CameraPreview.kt (71%) rename feature/{task-certification/src/main/java/com/twix/task_certification/certification => photolog/capture/src/main/java/com/twix/photolog/capture}/model/camera/CaptureCamera.kt (96%) create mode 100644 feature/photolog/detail/.gitignore create mode 100644 feature/photolog/detail/build.gradle.kts create mode 100644 feature/photolog/detail/consumer-rules.pro create mode 100644 feature/photolog/detail/proguard-rules.pro create mode 100644 feature/photolog/detail/src/main/AndroidManifest.xml rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt => photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetail.kt} (77%) rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt => photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetailViewModel.kt} (71%) rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt => photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologCardContent.kt} (80%) rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationDetailTopBar.kt => photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologDetailTopBar.kt} (92%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/reaction/ReactionBar.kt (98%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/reaction/ReactionContent.kt (96%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/reaction/ReactionEffect.kt (99%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/reaction/ReactionEffectSpec.kt (91%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/reaction/ReactionParticle.kt (87%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/reaction/ReactionUiModel.kt (92%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/swipe/SwipeCardSpec.kt (92%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/detail/src/main/java/com/twix/photolog}/detail/component/swipe/SwipeableCard.kt (99%) create mode 100644 feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailIntent.kt rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt => photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailSideEffect.kt} (54%) rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt => photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailUiState.kt} (58%) create mode 100644 feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt rename feature/{task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt => photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt} (65%) rename feature/{task-certification/src/main/java/com/twix/task_certification/detail/preview/TaskCertificationDetailPreviewProvider.kt => photolog/detail/src/main/java/com/twix/photolog/detail/preview/PhotologDetailPreviewProvider.kt} (85%) create mode 100644 feature/photolog/editor/.gitignore create mode 100644 feature/photolog/editor/build.gradle.kts create mode 100644 feature/photolog/editor/consumer-rules.pro create mode 100644 feature/photolog/editor/proguard-rules.pro create mode 100644 feature/photolog/editor/src/main/AndroidManifest.xml rename feature/{task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorRoute.kt => photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt} (85%) rename feature/{task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorViewModel.kt => photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt} (57%) rename feature/{task-certification/src/main/java/com/twix/task_certification/editor/component/TaskCertificationEditorTopBar.kt => photolog/editor/src/main/java/com/twix/photolog/editor/component/PhotologEditorTopBar.kt} (91%) rename feature/{task-certification/src/main/java/com/twix/task_certification => photolog/editor/src/main/java/com/twix/photolog}/editor/component/RetakeButton.kt (90%) create mode 100644 feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorIntent.kt rename feature/{task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorSideEffect.kt => photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorSideEffect.kt} (53%) rename feature/{task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorUiState.kt => photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorUiState.kt} (88%) create mode 100644 feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt delete mode 100644 feature/task-certification/.gitignore delete mode 100644 feature/task-certification/consumer-rules.pro delete mode 100644 feature/task-certification/proguard-rules.pro delete mode 100644 feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt delete mode 100644 feature/task-certification/src/main/java/com/twix/task_certification/di/TaskCertificationModule.kt delete mode 100644 feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorIntent.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef6623a7..8d477a58 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -60,7 +60,7 @@ dependencies { implementation(projects.domain) implementation(projects.feature.login) implementation(projects.feature.main) - implementation(projects.feature.taskCertification) + implementation(projects.feature.photolog.detail) implementation(projects.feature.onboarding) implementation(projects.feature.goalEditor) implementation(projects.feature.goalManage) diff --git a/app/src/main/java/com/yapp/twix/di/FeatureModules.kt b/app/src/main/java/com/yapp/twix/di/FeatureModules.kt index 04f67aa2..de6d20f0 100644 --- a/app/src/main/java/com/yapp/twix/di/FeatureModules.kt +++ b/app/src/main/java/com/yapp/twix/di/FeatureModules.kt @@ -7,11 +7,11 @@ import com.twix.login.di.loginModule import com.twix.main.di.mainModule import com.twix.notification.di.notificationFeatureModule import com.twix.onboarding.di.onBoardingModule +import com.twix.photolog.detail.di.photologDetailModule import com.twix.settings.di.settingsModule import com.twix.splash.di.splashModule import com.twix.stats.detail.di.statsDetailModule import com.twix.stats.di.statsModule -import com.twix.task_certification.di.taskCertificationModule import org.koin.core.module.Module val featureModules: List = @@ -19,7 +19,7 @@ val featureModules: List = loginModule, mainModule, homeModule, - taskCertificationModule, + photologDetailModule, goalEditorModule, goalManageModule, settingsModule, diff --git a/core/design-system/src/main/java/com/twix/designsystem/components/photolog/ForegroundCard.kt b/core/design-system/src/main/java/com/twix/designsystem/components/photolog/ForegroundCard.kt index 7bc42d08..38303e28 100644 --- a/core/design-system/src/main/java/com/twix/designsystem/components/photolog/ForegroundCard.kt +++ b/core/design-system/src/main/java/com/twix/designsystem/components/photolog/ForegroundCard.kt @@ -33,7 +33,7 @@ fun ForegroundCard( when (currentShow) { BetweenUs.ME -> stringResource(R.string.keep_it_up) BetweenUs.PARTNER -> - stringResource(R.string.partner_not_task_certification).format( + stringResource(R.string.partner_not_photolog).format( nickName, ) }, diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index 67fdf85c..abf6eb67 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -58,7 +58,7 @@ 5글자로 코멘트를 남길 수 있어요 - %s님은\n아직… + %s님은\n아직… 목표 직접 만들기 @@ -130,28 +130,28 @@ * 언제든지 설정 > 알림 설정에서 변경 가능해요 - 업로드 - 이미지 캡처에 실패했습니다. 다시 시도해 주세요. - 이미지를 불러오는 데 실패했습니다. 다시 시도해 주세요. - 인증샷 찍기 - 인증샷 등록에 실패했습니다. - 이미지 변환에 실패했습니다. - 인증샷 업로드 중... - 잠시만 기다려 주세요. + 업로드 + 이미지 캡처에 실패했습니다. 다시 시도해 주세요. + 이미지를 불러오는 데 실패했습니다. 다시 시도해 주세요. + 인증샷 찍기 + 인증샷 등록에 실패했습니다. + 이미지 변환에 실패했습니다. + 인증샷 업로드 중... + 잠시만 기다려 주세요. 코멘트는 5글자로 입력해주세요! - 인증샷 조회에 실패했습니다. - 인증샷 수정에 실패했어요. + 인증샷 조회에 실패했습니다. + 인증샷 수정에 실패했어요. - 다시 찍기 - 코멘트가 수정 되었어요. - 코멘트가 수정되지 않았어요. - 코멘트 수정에 실패했어요. - 리액션 요청에 실패했어요. + 다시 찍기 + 코멘트가 수정 되었어요. + 코멘트가 수정되지 않았어요. + 코멘트 수정에 실패했어요. + 리액션 요청에 실패했어요. - 인증샷 촬영을 위해서 카메라 권한이 필요해요. + 인증샷 촬영을 위해서 카메라 권한이 필요해요. Google로 시작하기 diff --git a/core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt b/core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt index 660c55b1..6269880e 100644 --- a/core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt +++ b/core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt @@ -63,7 +63,7 @@ fun AppNavHost( ) { ensureMainStack(navController) navController.navigate( - NavRoutes.TaskCertificationDetailRoute.createRoute( + NavRoutes.PhotologDetailRoute.createRoute( goalId = goalId, date = date, betweenUs = BetweenUs.ME.name, @@ -79,7 +79,7 @@ fun AppNavHost( ) { ensureMainStack(navController) navController.navigate( - NavRoutes.TaskCertificationDetailRoute.createRoute( + NavRoutes.PhotologDetailRoute.createRoute( goalId = goalId, date = date, betweenUs = BetweenUs.PARTNER.name, diff --git a/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt b/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt index b3139b1f..850eb91f 100644 --- a/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt +++ b/core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt @@ -30,12 +30,12 @@ sealed class NavRoutes( object MainRoute : NavRoutes("main") /** - * TaskCertificationGraph + * PhotologGraph * */ - object TaskCertificationGraph : NavRoutes("task_certification_graph") + object PhotologGraph : NavRoutes("photolog_graph") - object TaskCertificationDetailRoute : - NavRoutes("task_certification_detail/{goalId}/{date}/{betweenUs}?isCompleted={isCompleted}") { + object PhotologDetailRoute : + NavRoutes("photolog_detail/{goalId}/{date}/{betweenUs}?isCompleted={isCompleted}") { const val ARG_GOAL_ID = "goalId" const val ARG_DATE = "date" const val ARG_BETWEEN_US = "betweenUs" @@ -46,10 +46,10 @@ sealed class NavRoutes( date: LocalDate, betweenUs: String, isCompleted: Boolean = false, - ) = "task_certification_detail/$goalId/$date/$betweenUs?isCompleted=$isCompleted" + ) = "photolog_detail/$goalId/$date/$betweenUs?isCompleted=$isCompleted" } - object TaskCertificationRoute : NavRoutes("task_certification/{data}") { + object PhotologRoute : NavRoutes("photolog/{data}") { const val ARG_DATA = "data" enum class From { @@ -61,19 +61,19 @@ sealed class NavRoutes( fun createRoute(data: DetailNavArgs): String { val json = Json.encodeToString(data) val encoded = Uri.encode(json) - return "task_certification/$encoded" + return "photolog/$encoded" } } - object TaskCertificationEditorRoute : - NavRoutes("task_certification_editor/{goalId}/{date}") { + object PhotologEditorRoute : + NavRoutes("photolog_editor/{goalId}/{date}") { const val ARG_GOAL_ID = "goalId" const val ARG_DATE = "date" fun createRoute( goalId: Long, date: LocalDate, - ) = "task_certification_editor/$goalId/$date" + ) = "photolog_editor/$goalId/$date" } /** diff --git a/core/navigation/src/main/java/com/twix/navigation/args/DetailNavArgs.kt b/core/navigation/src/main/java/com/twix/navigation/args/DetailNavArgs.kt index b3824687..0bd01e02 100644 --- a/core/navigation/src/main/java/com/twix/navigation/args/DetailNavArgs.kt +++ b/core/navigation/src/main/java/com/twix/navigation/args/DetailNavArgs.kt @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable @Serializable data class DetailNavArgs( val goalId: Long, - val from: NavRoutes.TaskCertificationRoute.From, + val from: NavRoutes.PhotologRoute.From, val photologId: Long = -1, val selectedDate: String = "", val comment: String = "", diff --git a/core/util/src/main/java/com/twix/util/bus/TaskCertificationRefreshBus.kt b/core/util/src/main/java/com/twix/util/bus/PhotologRefreshBus.kt similarity index 93% rename from core/util/src/main/java/com/twix/util/bus/TaskCertificationRefreshBus.kt rename to core/util/src/main/java/com/twix/util/bus/PhotologRefreshBus.kt index 578d3a57..ebe91a64 100644 --- a/core/util/src/main/java/com/twix/util/bus/TaskCertificationRefreshBus.kt +++ b/core/util/src/main/java/com/twix/util/bus/PhotologRefreshBus.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow -class TaskCertificationRefreshBus { +class PhotologRefreshBus { enum class Publisher { PHOTOLOG, EDITOR, diff --git a/core/util/src/main/java/com/twix/util/di/UtilModule.kt b/core/util/src/main/java/com/twix/util/di/UtilModule.kt index b870083d..f651c1f4 100644 --- a/core/util/src/main/java/com/twix/util/di/UtilModule.kt +++ b/core/util/src/main/java/com/twix/util/di/UtilModule.kt @@ -3,13 +3,13 @@ package com.twix.util.di import com.twix.util.bus.GoalRefreshBus import com.twix.util.bus.StatsDetailRefreshBus import com.twix.util.bus.StatsRefreshBus -import com.twix.util.bus.TaskCertificationRefreshBus +import com.twix.util.bus.PhotologRefreshBus import org.koin.dsl.module val utilModule = module { single { GoalRefreshBus() } - single { TaskCertificationRefreshBus() } + single { PhotologRefreshBus() } single { StatsRefreshBus() } single { StatsDetailRefreshBus() } } diff --git a/feature/main/src/main/java/com/twix/main/navigation/MainNavGraph.kt b/feature/main/src/main/java/com/twix/main/navigation/MainNavGraph.kt index 8d53efe0..315404d6 100644 --- a/feature/main/src/main/java/com/twix/main/navigation/MainNavGraph.kt +++ b/feature/main/src/main/java/com/twix/main/navigation/MainNavGraph.kt @@ -39,10 +39,10 @@ object MainNavGraph : NavGraphContributor { }, navigateToCertification = { goalId, date -> val destination = - NavRoutes.TaskCertificationRoute.createRoute( + NavRoutes.PhotologRoute.createRoute( DetailNavArgs( goalId = goalId, - from = NavRoutes.TaskCertificationRoute.From.HOME, + from = NavRoutes.PhotologRoute.From.HOME, selectedDate = date.toString(), ), ) @@ -52,7 +52,7 @@ object MainNavGraph : NavGraphContributor { }, navigateToCertificationDetail = { goalId, date, betweenUs -> val destination = - NavRoutes.TaskCertificationDetailRoute.createRoute( + NavRoutes.PhotologDetailRoute.createRoute( goalId, date, betweenUs.name, diff --git a/feature/notification/src/main/java/com/twix/notification/navigation/NotificationNavGraph.kt b/feature/notification/src/main/java/com/twix/notification/navigation/NotificationNavGraph.kt index eb6477da..0690a2f3 100644 --- a/feature/notification/src/main/java/com/twix/notification/navigation/NotificationNavGraph.kt +++ b/feature/notification/src/main/java/com/twix/notification/navigation/NotificationNavGraph.kt @@ -24,13 +24,13 @@ object NotificationNavGraph : NavGraphContributor { NotificationRoute( popBackStack = { navController.popBackStack() }, navigateToMyPhotolog = { goalId, date -> - navController.navigate(NavRoutes.TaskCertificationDetailRoute.createRoute(goalId, date, BetweenUs.ME.name)) { + navController.navigate(NavRoutes.PhotologDetailRoute.createRoute(goalId, date, BetweenUs.ME.name)) { launchSingleTop = true } }, navigateToPartnerPhotolog = { goalId, date -> navController.navigate( - NavRoutes.TaskCertificationDetailRoute.createRoute( + NavRoutes.PhotologDetailRoute.createRoute( goalId, date, BetweenUs.PARTNER.name, diff --git a/feature/photolog/capture/.gitignore b/feature/photolog/capture/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/feature/photolog/capture/.gitignore @@ -0,0 +1 @@ +/build diff --git a/feature/task-certification/build.gradle.kts b/feature/photolog/capture/build.gradle.kts similarity index 70% rename from feature/task-certification/build.gradle.kts rename to feature/photolog/capture/build.gradle.kts index eb6da430..e6503c7c 100644 --- a/feature/task-certification/build.gradle.kts +++ b/feature/photolog/capture/build.gradle.kts @@ -3,11 +3,10 @@ plugins { } android { - namespace = "com.twix.task_certification" + namespace = "com.twix.photolog.capture" } -dependencies { - implementation(projects.core.util) +dependencies { implementation(libs.bundles.cameraX) implementation(libs.guava) implementation(libs.kotlinx.serialization.json) diff --git a/feature/photolog/capture/consumer-rules.pro b/feature/photolog/capture/consumer-rules.pro new file mode 100644 index 00000000..fb164d66 --- /dev/null +++ b/feature/photolog/capture/consumer-rules.pro @@ -0,0 +1 @@ +# Add project specific ProGuard rules here. diff --git a/feature/photolog/capture/proguard-rules.pro b/feature/photolog/capture/proguard-rules.pro new file mode 100644 index 00000000..fb164d66 --- /dev/null +++ b/feature/photolog/capture/proguard-rules.pro @@ -0,0 +1 @@ +# Add project specific ProGuard rules here. diff --git a/feature/task-certification/src/main/AndroidManifest.xml b/feature/photolog/capture/src/main/AndroidManifest.xml similarity index 100% rename from feature/task-certification/src/main/AndroidManifest.xml rename to feature/photolog/capture/src/main/AndroidManifest.xml diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationScreen.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureScreen.kt similarity index 75% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationScreen.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureScreen.kt index bc3a87ae..ef71b8fc 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationScreen.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureScreen.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification +package com.twix.photolog.capture import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.PickVisualMediaRequest @@ -37,16 +37,16 @@ import com.twix.designsystem.theme.GrayColor import com.twix.designsystem.theme.TwixTheme import com.twix.domain.model.enums.AppTextStyle import com.twix.domain.model.enums.BetweenUs -import com.twix.task_certification.certification.component.CameraControlBar -import com.twix.task_certification.certification.component.CameraPreviewBox -import com.twix.task_certification.certification.component.CommentErrorText -import com.twix.task_certification.certification.component.LoadingContent -import com.twix.task_certification.certification.component.TaskCertificationTopBar -import com.twix.task_certification.certification.contract.TaskCertificationIntent -import com.twix.task_certification.certification.contract.TaskCertificationSideEffect -import com.twix.task_certification.certification.contract.TaskCertificationUiState -import com.twix.task_certification.certification.model.camera.Camera -import com.twix.task_certification.certification.model.camera.CameraPreview +import com.twix.photolog.capture.component.CameraControlBar +import com.twix.photolog.capture.component.CameraPreviewBox +import com.twix.photolog.capture.component.CommentErrorText +import com.twix.photolog.capture.component.LoadingContent +import com.twix.photolog.capture.component.PhotologCaptureTopBar +import com.twix.photolog.capture.contract.PhotologCaptureIntent +import com.twix.photolog.capture.contract.PhotologCaptureSideEffect +import com.twix.photolog.capture.contract.PhotologCaptureUiState +import com.twix.photolog.capture.model.camera.Camera +import com.twix.photolog.capture.model.camera.CameraPreview import com.twix.ui.base.ObserveAsEvents import com.twix.ui.extension.noRippleClickable import kotlinx.coroutines.launch @@ -55,10 +55,10 @@ import org.koin.compose.koinInject import java.time.LocalDate @Composable -fun TaskCertificationRoute( +fun PhotologCaptureRoute( toastManager: ToastManager = koinInject(), camera: Camera = koinInject(), - viewModel: TaskCertificationViewModel = koinViewModel(), + viewModel: PhotologCaptureViewModel = koinViewModel(), navigateToBack: () -> Unit, navigateToDetail: (Long, LocalDate, BetweenUs) -> Unit, ) { @@ -71,7 +71,7 @@ fun TaskCertificationRoute( val pickMedia = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> - viewModel.dispatch(TaskCertificationIntent.PickPicture(uri)) + viewModel.dispatch(PhotologCaptureIntent.PickPicture(uri)) } LaunchedEffect(uiState.lens) { @@ -90,7 +90,7 @@ fun TaskCertificationRoute( ObserveAsEvents(viewModel.sideEffect) { event -> when (event) { - is TaskCertificationSideEffect.ShowToast -> { + is PhotologCaptureSideEffect.ShowToast -> { toastManager.tryShow( ToastData( message = currentContext.getString(event.message), @@ -99,8 +99,8 @@ fun TaskCertificationRoute( ) } - TaskCertificationSideEffect.NavigateToBack -> navigateToBack() - is TaskCertificationSideEffect.NavigateToDetail -> + PhotologCaptureSideEffect.NavigateToBack -> navigateToBack() + is PhotologCaptureSideEffect.NavigateToDetail -> navigateToDetail( event.goalId, event.date, @@ -112,7 +112,7 @@ fun TaskCertificationRoute( if (uiState.isLoading) { LoadingContent() } else { - TaskCertificationScreen( + PhotologCaptureScreen( uiState = uiState, cameraPreview = cameraPreview, onClickClose = navigateToBack, @@ -121,40 +121,40 @@ fun TaskCertificationRoute( camera .takePicture() .onSuccess { - viewModel.dispatch(TaskCertificationIntent.TakePicture(it)) + viewModel.dispatch(PhotologCaptureIntent.TakePicture(it)) }.onFailure { - viewModel.dispatch(TaskCertificationIntent.TakePicture(null)) + viewModel.dispatch(PhotologCaptureIntent.TakePicture(null)) } } }, onToggleCameraClick = { - viewModel.dispatch(TaskCertificationIntent.ToggleLens) + viewModel.dispatch(PhotologCaptureIntent.ToggleLens) }, onClickFlash = { - viewModel.dispatch(TaskCertificationIntent.ToggleTorch) + viewModel.dispatch(PhotologCaptureIntent.ToggleTorch) }, onClickGallery = { pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) }, onClickRefresh = { - viewModel.dispatch(TaskCertificationIntent.RetakePicture) + viewModel.dispatch(PhotologCaptureIntent.RetakePicture) }, onCommentChanged = { - viewModel.dispatch(TaskCertificationIntent.UpdateComment(it)) + viewModel.dispatch(PhotologCaptureIntent.UpdateComment(it)) }, onFocusChanged = { - viewModel.dispatch(TaskCertificationIntent.CommentFocusChanged(it)) + viewModel.dispatch(PhotologCaptureIntent.CommentFocusChanged(it)) }, onClickUpload = { - viewModel.dispatch(TaskCertificationIntent.TryUpload) + viewModel.dispatch(PhotologCaptureIntent.TryUpload) }, ) } } @Composable -private fun TaskCertificationScreen( - uiState: TaskCertificationUiState, +private fun PhotologCaptureScreen( + uiState: PhotologCaptureUiState, cameraPreview: CameraPreview?, onClickClose: () -> Unit, onCaptureClick: () -> Unit, @@ -177,7 +177,7 @@ private fun TaskCertificationScreen( .noRippleClickable { focusManager.clearFocus() }, ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { - TaskCertificationTopBar(onClickClose = onClickClose) + PhotologCaptureTopBar(onClickClose = onClickClose) Spacer(modifier = Modifier.height(24.26.dp)) @@ -186,7 +186,7 @@ private fun TaskCertificationScreen( CommentErrorText() } else { AppText( - text = stringResource(R.string.task_certification_take_picture), + text = stringResource(R.string.photolog_take_picture), style = AppTextStyle.H2, color = GrayColor.C100, ) @@ -227,10 +227,10 @@ private fun TaskCertificationScreen( @Preview @Composable -fun TaskCertificationScreenPreview() { +fun PhotologCaptureScreenPreview() { TwixTheme { - TaskCertificationScreen( - uiState = TaskCertificationUiState(), + PhotologCaptureScreen( + uiState = PhotologCaptureUiState(), cameraPreview = null, onClickClose = {}, onCaptureClick = {}, diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationViewModel.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt similarity index 67% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationViewModel.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt index 82ff30fe..2cd17655 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/TaskCertificationViewModel.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification +package com.twix.photolog.capture import android.net.Uri import androidx.lifecycle.SavedStateHandle @@ -11,57 +11,57 @@ import com.twix.domain.repository.PhotoLogRepository import com.twix.navigation.NavRoutes import com.twix.navigation.args.DetailNavArgs import com.twix.navigation.savedstate.decodeNavArgs -import com.twix.task_certification.certification.contract.TaskCertificationIntent -import com.twix.task_certification.certification.contract.TaskCertificationSideEffect -import com.twix.task_certification.certification.contract.TaskCertificationUiState -import com.twix.task_certification.certification.model.CaptureStatus +import com.twix.photolog.capture.contract.PhotologCaptureIntent +import com.twix.photolog.capture.contract.PhotologCaptureSideEffect +import com.twix.photolog.capture.contract.PhotologCaptureUiState +import com.twix.photolog.capture.model.CaptureStatus import com.twix.ui.base.BaseViewModel import com.twix.ui.image.ImageGenerator import com.twix.util.bus.GoalRefreshBus import com.twix.util.bus.StatsDetailRefreshBus -import com.twix.util.bus.TaskCertificationRefreshBus +import com.twix.util.bus.PhotologRefreshBus import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.time.LocalDate -class TaskCertificationViewModel( +class PhotologCaptureViewModel( private val imageGenerator: ImageGenerator, private val photologRepository: PhotoLogRepository, - private val detailRefreshBus: TaskCertificationRefreshBus, + private val detailRefreshBus: PhotologRefreshBus, private val goalRefreshBus: GoalRefreshBus, private val statsDetailRefreshBus: StatsDetailRefreshBus, savedStateHandle: SavedStateHandle, -) : BaseViewModel( - TaskCertificationUiState(), +) : BaseViewModel( + PhotologCaptureUiState(), ) { private val navArgs: DetailNavArgs = - savedStateHandle.decodeNavArgs(NavRoutes.TaskCertificationRoute.ARG_DATA) + savedStateHandle.decodeNavArgs(NavRoutes.PhotologRoute.ARG_DATA) init { - if (navArgs.from == NavRoutes.TaskCertificationRoute.From.EDITOR) { + if (navArgs.from == NavRoutes.PhotologRoute.From.EDITOR) { reduceComment(navArgs.comment) } } - override suspend fun handleIntent(intent: TaskCertificationIntent) { + override suspend fun handleIntent(intent: PhotologCaptureIntent) { when (intent) { - is TaskCertificationIntent.TakePicture -> takePicture(intent.uri) - is TaskCertificationIntent.PickPicture -> pickPicture(intent.uri) - is TaskCertificationIntent.ToggleLens -> reduceLens() - is TaskCertificationIntent.ToggleTorch -> reduceTorch() - is TaskCertificationIntent.RetakePicture -> setupRetake() - is TaskCertificationIntent.UpdateComment -> reduceComment(intent.value) - is TaskCertificationIntent.CommentFocusChanged -> reduceCommentFocus(intent.isFocused) - is TaskCertificationIntent.TryUpload -> handleUploadIntent() - is TaskCertificationIntent.Upload -> upload(intent.image) + is PhotologCaptureIntent.TakePicture -> takePicture(intent.uri) + is PhotologCaptureIntent.PickPicture -> pickPicture(intent.uri) + is PhotologCaptureIntent.ToggleLens -> reduceLens() + is PhotologCaptureIntent.ToggleTorch -> reduceTorch() + is PhotologCaptureIntent.RetakePicture -> setupRetake() + is PhotologCaptureIntent.UpdateComment -> reduceComment(intent.value) + is PhotologCaptureIntent.CommentFocusChanged -> reduceCommentFocus(intent.isFocused) + is PhotologCaptureIntent.TryUpload -> handleUploadIntent() + is PhotologCaptureIntent.Upload -> upload(intent.image) } } private fun takePicture(uri: Uri?) { uri?.let { reducePicture(it) } ?: showToast( - R.string.task_certification_image_capture_fail, + R.string.photolog_image_capture_fail, ToastType.ERROR, ) } @@ -112,7 +112,7 @@ class TaskCertificationViewModel( if (imageBytes != null) { upload(imageBytes) } else { - showToast(R.string.task_certification_image_translate_fail, ToastType.ERROR) + showToast(R.string.photolog_image_translate_fail, ToastType.ERROR) } } } @@ -140,18 +140,18 @@ class TaskCertificationViewModel( onSuccess = { fileName -> handleUploadPhotologSuccess(fileName) }, onError = { reduce { copy(isLoading = false) } - showToast(R.string.task_certification_upload_fail, ToastType.ERROR) + showToast(R.string.photolog_upload_fail, ToastType.ERROR) }, ) } private fun handleUploadPhotologSuccess(fileName: String) { when (navArgs.from) { - NavRoutes.TaskCertificationRoute.From.DETAIL, - NavRoutes.TaskCertificationRoute.From.HOME, + NavRoutes.PhotologRoute.From.DETAIL, + NavRoutes.PhotologRoute.From.HOME, -> uploadPhotolog(fileName) - NavRoutes.TaskCertificationRoute.From.EDITOR -> modifyPhotolog(fileName) + NavRoutes.PhotologRoute.From.EDITOR -> modifyPhotolog(fileName) } } @@ -169,22 +169,22 @@ class TaskCertificationViewModel( }, onSuccess = { handleUploadPhotologSuccess() }, onError = { - showToast(R.string.task_certification_upload_fail, ToastType.ERROR) + showToast(R.string.photolog_upload_fail, ToastType.ERROR) }, ) } private fun handleUploadPhotologSuccess() { when (navArgs.from) { - NavRoutes.TaskCertificationRoute.From.HOME -> + NavRoutes.PhotologRoute.From.HOME -> goalRefreshBus.notifyGoalListChanged() - NavRoutes.TaskCertificationRoute.From.DETAIL -> - detailRefreshBus.notifyChanged(TaskCertificationRefreshBus.Publisher.PHOTOLOG) + NavRoutes.PhotologRoute.From.DETAIL -> + detailRefreshBus.notifyChanged(PhotologRefreshBus.Publisher.PHOTOLOG) - NavRoutes.TaskCertificationRoute.From.EDITOR -> Unit + NavRoutes.PhotologRoute.From.EDITOR -> Unit } - tryEmitSideEffect(TaskCertificationSideEffect.NavigateToBack) + tryEmitSideEffect(PhotologCaptureSideEffect.NavigateToBack) } private fun modifyPhotolog(fileName: String) { @@ -198,18 +198,18 @@ class TaskCertificationViewModel( }, onSuccess = { handleModifyPhotologSuccess() }, onError = { - showToast(R.string.task_certification_modify_fail, ToastType.ERROR) + showToast(R.string.photolog_modify_fail, ToastType.ERROR) }, ) } private fun handleModifyPhotologSuccess() { - detailRefreshBus.notifyChanged(TaskCertificationRefreshBus.Publisher.PHOTOLOG) + detailRefreshBus.notifyChanged(PhotologRefreshBus.Publisher.PHOTOLOG) goalRefreshBus.notifyGoalListChanged() statsDetailRefreshBus.notifyChanged() val selectedDate = LocalDate.parse(navArgs.selectedDate) tryEmitSideEffect( - TaskCertificationSideEffect.NavigateToDetail( + PhotologCaptureSideEffect.NavigateToDetail( goalId = navArgs.goalId, date = selectedDate, betweenUs = BetweenUs.ME, @@ -222,7 +222,7 @@ class TaskCertificationViewModel( type: ToastType, ) { viewModelScope.launch { - emitSideEffect(TaskCertificationSideEffect.ShowToast(message, type)) + emitSideEffect(PhotologCaptureSideEffect.ShowToast(message, type)) } } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CameraControlBar.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CameraControlBar.kt similarity index 96% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CameraControlBar.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CameraControlBar.kt index c8020dc3..5b5b9deb 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CameraControlBar.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CameraControlBar.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.component +package com.twix.photolog.capture.component import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement @@ -31,7 +31,7 @@ import com.twix.designsystem.theme.CommonColor import com.twix.designsystem.theme.GrayColor import com.twix.designsystem.theme.TwixTheme import com.twix.domain.model.enums.AppTextStyle -import com.twix.task_certification.certification.model.CaptureStatus +import com.twix.photolog.capture.model.CaptureStatus import com.twix.ui.extension.noRippleClickable @Composable @@ -145,7 +145,7 @@ private fun ImageCapturedBar( AppRoundButton( borderColor = CommonColor.White, backgroundColor = GrayColor.C500, - text = stringResource(R.string.task_certification_upload), + text = stringResource(R.string.photolog_upload), textStyle = AppTextStyle.T2, textColor = CommonColor.White, modifier = diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CameraPreviewBox.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CameraPreviewBox.kt similarity index 92% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CameraPreviewBox.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CameraPreviewBox.kt index d97d5d57..68668ea2 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CameraPreviewBox.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CameraPreviewBox.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.component +package com.twix.photolog.capture.component import androidx.camera.compose.CameraXViewfinder import androidx.compose.foundation.Image @@ -22,9 +22,9 @@ import coil3.compose.AsyncImage import com.twix.designsystem.R import com.twix.designsystem.theme.GrayColor import com.twix.designsystem.theme.TwixTheme -import com.twix.task_certification.certification.model.CaptureStatus -import com.twix.task_certification.certification.model.TorchStatus -import com.twix.task_certification.certification.model.camera.CameraPreview +import com.twix.photolog.capture.model.CaptureStatus +import com.twix.photolog.capture.model.TorchStatus +import com.twix.photolog.capture.model.camera.CameraPreview import com.twix.ui.extension.noRippleClickable @Composable diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CommentErrorText.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CommentErrorText.kt similarity index 96% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CommentErrorText.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CommentErrorText.kt index 51bf8783..4d1bc90e 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/CommentErrorText.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/CommentErrorText.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.component +package com.twix.photolog.capture.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/LoadingContent.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/LoadingContent.kt similarity index 93% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/component/LoadingContent.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/LoadingContent.kt index a1d5e576..d4758a75 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/LoadingContent.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/LoadingContent.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.component +package com.twix.photolog.capture.component import androidx.compose.animation.core.EaseInOut import androidx.compose.animation.core.LinearEasing @@ -45,7 +45,7 @@ internal fun LoadingContent() { Spacer(Modifier.height(6.dp)) AppText( - text = stringResource(R.string.task_certification_loading), + text = stringResource(R.string.photolog_loading), style = AppTextStyle.H1, color = GrayColor.C500, ) @@ -53,7 +53,7 @@ internal fun LoadingContent() { Spacer(Modifier.height(10.dp)) AppText( - text = stringResource(R.string.task_certification_plz_waiting), + text = stringResource(R.string.photolog_plz_waiting), style = AppTextStyle.T2, color = GrayColor.C300, ) diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/TaskCertificationTopBar.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/PhotologCaptureTopBar.kt similarity index 88% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/component/TaskCertificationTopBar.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/PhotologCaptureTopBar.kt index e5b962d5..63d577a2 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/component/TaskCertificationTopBar.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/component/PhotologCaptureTopBar.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.component +package com.twix.photolog.capture.component import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -18,7 +18,7 @@ import com.twix.designsystem.theme.GrayColor import com.twix.ui.extension.noRippleClickable @Composable -internal fun TaskCertificationTopBar( +internal fun PhotologCaptureTopBar( onClickClose: () -> Unit, modifier: Modifier = Modifier, ) { @@ -43,6 +43,6 @@ internal fun TaskCertificationTopBar( @Preview(showBackground = true) @Composable -private fun TaskCertificationTopBarPreview() { - TaskCertificationTopBar({}) +private fun PhotologCaptureTopBarPreview() { + PhotologCaptureTopBar({}) } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationIntent.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureIntent.kt similarity index 57% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationIntent.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureIntent.kt index cbf40808..62772d75 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationIntent.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureIntent.kt @@ -1,36 +1,36 @@ -package com.twix.task_certification.certification.contract +package com.twix.photolog.capture.contract import android.net.Uri import com.twix.ui.base.Intent -sealed interface TaskCertificationIntent : Intent { +sealed interface PhotologCaptureIntent : Intent { data class TakePicture( val uri: Uri?, - ) : TaskCertificationIntent + ) : PhotologCaptureIntent data class PickPicture( val uri: Uri?, - ) : TaskCertificationIntent + ) : PhotologCaptureIntent - data object ToggleLens : TaskCertificationIntent + data object ToggleLens : PhotologCaptureIntent - data object ToggleTorch : TaskCertificationIntent + data object ToggleTorch : PhotologCaptureIntent - data object RetakePicture : TaskCertificationIntent + data object RetakePicture : PhotologCaptureIntent data class UpdateComment( val value: String, - ) : TaskCertificationIntent + ) : PhotologCaptureIntent data class CommentFocusChanged( val isFocused: Boolean, - ) : TaskCertificationIntent + ) : PhotologCaptureIntent - data object TryUpload : TaskCertificationIntent + data object TryUpload : PhotologCaptureIntent data class Upload( val image: ByteArray, - ) : TaskCertificationIntent { + ) : PhotologCaptureIntent { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationSideEffect.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureSideEffect.kt similarity index 60% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationSideEffect.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureSideEffect.kt index bd558670..a0d014d5 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationSideEffect.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureSideEffect.kt @@ -1,21 +1,21 @@ -package com.twix.task_certification.certification.contract +package com.twix.photolog.capture.contract import com.twix.designsystem.components.toast.model.ToastType import com.twix.domain.model.enums.BetweenUs import com.twix.ui.base.SideEffect import java.time.LocalDate -sealed interface TaskCertificationSideEffect : SideEffect { +sealed interface PhotologCaptureSideEffect : SideEffect { data class ShowToast( val message: Int, val type: ToastType, - ) : TaskCertificationSideEffect + ) : PhotologCaptureSideEffect - data object NavigateToBack : TaskCertificationSideEffect + data object NavigateToBack : PhotologCaptureSideEffect data class NavigateToDetail( val goalId: Long, val date: LocalDate, val betweenUs: BetweenUs, - ) : TaskCertificationSideEffect + ) : PhotologCaptureSideEffect } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationUiState.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureUiState.kt similarity index 74% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationUiState.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureUiState.kt index 54aa4eed..3b7dfd92 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/contract/TaskCertificationUiState.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/contract/PhotologCaptureUiState.kt @@ -1,16 +1,16 @@ -package com.twix.task_certification.certification.contract +package com.twix.photolog.capture.contract import android.net.Uri import androidx.camera.core.CameraSelector import androidx.compose.runtime.Immutable import com.twix.designsystem.components.comment.model.CommentUiModel -import com.twix.task_certification.certification.model.CaptureStatus -import com.twix.task_certification.certification.model.TorchStatus -import com.twix.task_certification.certification.model.camera.CameraPreview +import com.twix.photolog.capture.model.CaptureStatus +import com.twix.photolog.capture.model.TorchStatus +import com.twix.photolog.capture.model.camera.CameraPreview import com.twix.ui.base.State @Immutable -data class TaskCertificationUiState( +data class PhotologCaptureUiState( val capture: CaptureStatus = CaptureStatus.NotCaptured, val torch: TorchStatus = TorchStatus.Off, val lens: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA, @@ -25,7 +25,7 @@ data class TaskCertificationUiState( val showTorch: Boolean get() = capture is CaptureStatus.NotCaptured && lens == CameraSelector.DEFAULT_BACK_CAMERA - fun toggleLens(): TaskCertificationUiState { + fun toggleLens(): PhotologCaptureUiState { val newLens = if (lens == CameraSelector.DEFAULT_BACK_CAMERA) { CameraSelector.DEFAULT_FRONT_CAMERA @@ -38,18 +38,18 @@ data class TaskCertificationUiState( ) } - fun toggleTorch(): TaskCertificationUiState { + fun toggleTorch(): PhotologCaptureUiState { val newFlashMode = TorchStatus.Companion.toggle(torch) return copy(torch = newFlashMode) } - fun updatePicture(uri: Uri): TaskCertificationUiState = + fun updatePicture(uri: Uri): PhotologCaptureUiState = copy( capture = CaptureStatus.Captured(uri), torch = TorchStatus.Off, ) - fun removePicture(): TaskCertificationUiState = copy(capture = CaptureStatus.NotCaptured) + fun removePicture(): PhotologCaptureUiState = copy(capture = CaptureStatus.NotCaptured) fun updateComment(newComment: String) = copy(comment = comment.updateComment(newComment)) diff --git a/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt new file mode 100644 index 00000000..dc0a7f7d --- /dev/null +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt @@ -0,0 +1,13 @@ +package com.twix.photolog.capture.di + +import com.twix.photolog.capture.PhotologCaptureViewModel +import com.twix.photolog.capture.model.camera.Camera +import com.twix.photolog.capture.model.camera.CaptureCamera +import org.koin.core.module.dsl.viewModelOf +import org.koin.dsl.module + +val photologCaptureModule = + module { + viewModelOf(::PhotologCaptureViewModel) + factory { CaptureCamera(get()) } + } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/CaptureStatus.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/CaptureStatus.kt similarity index 80% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/model/CaptureStatus.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/CaptureStatus.kt index 3ad176f2..6d807aca 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/CaptureStatus.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/CaptureStatus.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.model +package com.twix.photolog.capture.model import android.net.Uri import androidx.compose.runtime.Immutable diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/TorchStatus.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/TorchStatus.kt similarity index 80% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/model/TorchStatus.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/TorchStatus.kt index e2ccd894..14b2ef6a 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/TorchStatus.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/TorchStatus.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.model +package com.twix.photolog.capture.model enum class TorchStatus { On, diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/Camera.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/Camera.kt similarity index 76% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/Camera.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/Camera.kt index bfd49e10..700328df 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/Camera.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/Camera.kt @@ -1,9 +1,9 @@ -package com.twix.task_certification.certification.model.camera +package com.twix.photolog.capture.model.camera import android.net.Uri import androidx.camera.core.CameraSelector import androidx.lifecycle.LifecycleOwner -import com.twix.task_certification.certification.model.TorchStatus +import com.twix.photolog.capture.model.TorchStatus import kotlinx.coroutines.flow.StateFlow interface Camera { diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/CameraPreview.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/CameraPreview.kt similarity index 71% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/CameraPreview.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/CameraPreview.kt index eca40459..169e077e 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/CameraPreview.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/CameraPreview.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.model.camera +package com.twix.photolog.capture.model.camera import androidx.camera.core.SurfaceRequest import androidx.compose.runtime.Immutable diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/CaptureCamera.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/CaptureCamera.kt similarity index 96% rename from feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/CaptureCamera.kt rename to feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/CaptureCamera.kt index 56f2a710..77b3c955 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/certification/model/camera/CaptureCamera.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/model/camera/CaptureCamera.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.certification.model.camera +package com.twix.photolog.capture.model.camera import android.content.ContentValues import android.content.Context @@ -15,7 +15,7 @@ import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.lifecycle.awaitInstance import androidx.core.content.ContextCompat import androidx.lifecycle.LifecycleOwner -import com.twix.task_certification.certification.model.TorchStatus +import com.twix.photolog.capture.model.TorchStatus import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -136,7 +136,7 @@ class CaptureCamera( private const val IMAGE_MIME_TYPE = "image/jpeg" private const val IMAGE_NAME = "task_%d" - private const val IMAGE_PATH = "Pictures/TaskCertification" + private const val IMAGE_PATH = "Pictures/Photolog" private const val URI_NOT_FOUND_EXCEPTION = "촬영한 이미지의 Uri를 찾을 수 없습니다" } diff --git a/feature/photolog/detail/.gitignore b/feature/photolog/detail/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/feature/photolog/detail/.gitignore @@ -0,0 +1 @@ +/build diff --git a/feature/photolog/detail/build.gradle.kts b/feature/photolog/detail/build.gradle.kts new file mode 100644 index 00000000..8bc0906a --- /dev/null +++ b/feature/photolog/detail/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + alias(libs.plugins.twix.feature) +} + +android { + namespace = "com.twix.photolog.detail" +} + +dependencies { + implementation(projects.feature.photolog.capture) + implementation(projects.feature.photolog.editor) +} diff --git a/feature/photolog/detail/consumer-rules.pro b/feature/photolog/detail/consumer-rules.pro new file mode 100644 index 00000000..fb164d66 --- /dev/null +++ b/feature/photolog/detail/consumer-rules.pro @@ -0,0 +1 @@ +# Add project specific ProGuard rules here. diff --git a/feature/photolog/detail/proguard-rules.pro b/feature/photolog/detail/proguard-rules.pro new file mode 100644 index 00000000..fb164d66 --- /dev/null +++ b/feature/photolog/detail/proguard-rules.pro @@ -0,0 +1 @@ +# Add project specific ProGuard rules here. diff --git a/feature/photolog/detail/src/main/AndroidManifest.xml b/feature/photolog/detail/src/main/AndroidManifest.xml new file mode 100644 index 00000000..8072ee00 --- /dev/null +++ b/feature/photolog/detail/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetail.kt similarity index 77% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetail.kt index 07770dc7..69dc9e70 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetail.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail +package com.twix.photolog.detail import android.Manifest import androidx.activity.compose.rememberLauncherForActivityResult @@ -29,15 +29,15 @@ import com.twix.designsystem.extension.showCameraPermissionToastWithNavigateToSe import com.twix.designsystem.theme.CommonColor import com.twix.designsystem.theme.TwixTheme import com.twix.domain.model.enums.GoalReactionType -import com.twix.task_certification.detail.component.TaskCertificationCardContent -import com.twix.task_certification.detail.component.TaskCertificationDetailTopBar -import com.twix.task_certification.detail.component.reaction.ReactionContent -import com.twix.task_certification.detail.component.reaction.ReactionEffect -import com.twix.task_certification.detail.component.reaction.ReactionEffectSpec -import com.twix.task_certification.detail.contract.TaskCertificationDetailIntent -import com.twix.task_certification.detail.contract.TaskCertificationDetailSideEffect -import com.twix.task_certification.detail.contract.TaskCertificationDetailUiState -import com.twix.task_certification.detail.preview.TaskCertificationDetailPreviewProvider +import com.twix.photolog.detail.component.PhotologCardContent +import com.twix.photolog.detail.component.PhotologDetailTopBar +import com.twix.photolog.detail.component.reaction.ReactionContent +import com.twix.photolog.detail.component.reaction.ReactionEffect +import com.twix.photolog.detail.component.reaction.ReactionEffectSpec +import com.twix.photolog.detail.contract.PhotologDetailIntent +import com.twix.photolog.detail.contract.PhotologDetailSideEffect +import com.twix.photolog.detail.contract.PhotologDetailUiState +import com.twix.photolog.detail.preview.PhotologDetailPreviewProvider import com.twix.ui.base.ObserveAsEvents import com.twix.ui.extension.findActivity import com.twix.ui.extension.hasCameraPermission @@ -47,12 +47,12 @@ import org.koin.compose.koinInject import java.time.LocalDate @Composable -fun TaskCertificationDetailRoute( +fun PhotologDetailRoute( navigateToBack: () -> Unit, navigateToCertification: (Long, LocalDate) -> Unit, navigateToEditor: (Long, LocalDate) -> Unit, toastManager: ToastManager = koinInject(), - viewModel: TaskCertificationDetailViewModel = koinViewModel(), + viewModel: PhotologDetailViewModel = koinViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() val context = LocalContext.current @@ -61,13 +61,13 @@ fun TaskCertificationDetailRoute( ObserveAsEvents(viewModel.sideEffect) { sideEffect -> when (sideEffect) { - is TaskCertificationDetailSideEffect.ShowToast -> { + is PhotologDetailSideEffect.ShowToast -> { toastManager.tryShow( ToastData(currentContext.getString(sideEffect.message), sideEffect.type), ) } - is TaskCertificationDetailSideEffect.ShowPokeToast -> { + is PhotologDetailSideEffect.ShowPokeToast -> { toastManager.tryShow( ToastData(sideEffect.message, ToastType.SUCCESS), ) @@ -110,7 +110,7 @@ fun TaskCertificationDetailRoute( val density = LocalDensity.current val screenHeightPx = with(density) { maxHeight.toPx() } - TaskCertificationDetailScreen( + PhotologDetailScreen( uiState = uiState, onBack = navigateToBack, onClickModify = { @@ -119,7 +119,7 @@ fun TaskCertificationDetailRoute( uiState.selectedDate, ) }, - onClickReaction = { viewModel.dispatch(TaskCertificationDetailIntent.Reaction(it)) }, + onClickReaction = { viewModel.dispatch(PhotologDetailIntent.Reaction(it)) }, onClickUpload = { if (currentContext.hasCameraPermission()) { navigateToCertification(uiState.goalId, uiState.selectedDate) @@ -127,8 +127,8 @@ fun TaskCertificationDetailRoute( permissionLauncher.launch(Manifest.permission.CAMERA) } }, - onPoke = { viewModel.dispatch(TaskCertificationDetailIntent.Poke) }, - onSwipe = { viewModel.dispatch(TaskCertificationDetailIntent.SwipeCard) }, + onPoke = { viewModel.dispatch(PhotologDetailIntent.Poke) }, + onSwipe = { viewModel.dispatch(PhotologDetailIntent.SwipeCard) }, ) if (!uiState.hasShownMyReaction && uiState.isDisplayedMyPhotolog) { val model = uiState.myReaction @@ -139,11 +139,10 @@ fun TaskCertificationDetailRoute( ReactionEffectSpec( particleCount = 10, durationRange = 500..800, - // 전체 화면 높이까지 퍼짐 travelDistanceRange = 500..screenHeightPx.toInt(), ), onFinished = { - viewModel.dispatch(TaskCertificationDetailIntent.MyReactionEffected) + viewModel.dispatch(PhotologDetailIntent.MyReactionEffected) }, ) } @@ -152,8 +151,8 @@ fun TaskCertificationDetailRoute( } @Composable -fun TaskCertificationDetailScreen( - uiState: TaskCertificationDetailUiState, +fun PhotologDetailScreen( + uiState: PhotologDetailUiState, onBack: () -> Unit, onClickModify: () -> Unit, onClickReaction: (GoalReactionType) -> Unit, @@ -166,7 +165,7 @@ fun TaskCertificationDetailScreen( .fillMaxSize() .background(color = CommonColor.White), ) { - TaskCertificationDetailTopBar( + PhotologDetailTopBar( title = uiState.goalName, canModify = uiState.canModify, onBack = onBack, @@ -175,7 +174,7 @@ fun TaskCertificationDetailScreen( Spacer(Modifier.height(103.dp)) if (uiState.isLoading) { - TaskCertificationCardContent( + PhotologCardContent( uiState = uiState, onSwipe = onSwipe, onClickUpload = onClickUpload, @@ -194,12 +193,12 @@ fun TaskCertificationDetailScreen( @Preview(showBackground = true) @Composable -private fun TaskCertificationDetailScreenPreview( - @PreviewParameter(TaskCertificationDetailPreviewProvider::class) - uiState: TaskCertificationDetailUiState, +private fun PhotologDetailScreenPreview( + @PreviewParameter(PhotologDetailPreviewProvider::class) + uiState: PhotologDetailUiState, ) { TwixTheme { - TaskCertificationDetailScreen( + PhotologDetailScreen( uiState = uiState, onBack = {}, onClickModify = {}, diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetailViewModel.kt similarity index 71% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetailViewModel.kt index d24a1e96..3c4cebdc 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/PhotologDetailViewModel.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail +package com.twix.photolog.detail import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope @@ -9,13 +9,13 @@ import com.twix.domain.model.enums.GoalReactionType import com.twix.domain.repository.PhotoLogRepository import com.twix.domain.repository.PokeRepository import com.twix.navigation.NavRoutes -import com.twix.task_certification.detail.contract.TaskCertificationDetailIntent -import com.twix.task_certification.detail.contract.TaskCertificationDetailSideEffect -import com.twix.task_certification.detail.contract.TaskCertificationDetailUiState -import com.twix.task_certification.detail.contract.toUiState +import com.twix.photolog.detail.contract.PhotologDetailIntent +import com.twix.photolog.detail.contract.PhotologDetailSideEffect +import com.twix.photolog.detail.contract.PhotologDetailUiState +import com.twix.photolog.detail.contract.toUiState import com.twix.ui.base.BaseViewModel import com.twix.util.bus.GoalRefreshBus -import com.twix.util.bus.TaskCertificationRefreshBus +import com.twix.util.bus.PhotologRefreshBus import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow @@ -25,31 +25,31 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch import java.time.LocalDate -class TaskCertificationDetailViewModel( +class PhotologDetailViewModel( private val photologRepository: PhotoLogRepository, private val pokeRepository: PokeRepository, - private val detailRefreshBus: TaskCertificationRefreshBus, + private val detailRefreshBus: PhotologRefreshBus, private val goalRefreshBus: GoalRefreshBus, savedStateHandle: SavedStateHandle, -) : BaseViewModel( - TaskCertificationDetailUiState(), +) : BaseViewModel( + PhotologDetailUiState(), ) { private val argGoalId: Long = - savedStateHandle[NavRoutes.TaskCertificationDetailRoute.ARG_GOAL_ID] + savedStateHandle[NavRoutes.PhotologDetailRoute.ARG_GOAL_ID] ?: error(GOAL_ID_NOT_FOUND) private val argTargetDate: LocalDate = LocalDate.parse( - savedStateHandle[NavRoutes.TaskCertificationDetailRoute.ARG_DATE] + savedStateHandle[NavRoutes.PhotologDetailRoute.ARG_DATE] ?: error(TARGET_DATE_NOT_FOUND), ) private val argBetweenUs: String = - savedStateHandle[NavRoutes.TaskCertificationDetailRoute.ARG_BETWEEN_US] + savedStateHandle[NavRoutes.PhotologDetailRoute.ARG_BETWEEN_US] ?: error(BETWEEN_US_NOT_FOUND) private val argIsCompleted: Boolean = - savedStateHandle[NavRoutes.TaskCertificationDetailRoute.ARG_IS_COMPLETED] ?: false + savedStateHandle[NavRoutes.PhotologDetailRoute.ARG_IS_COMPLETED] ?: false private var lastReaction: GoalReactionType? = null @@ -79,7 +79,7 @@ class TaskCertificationDetailViewModel( } }, onError = { - showToast(R.string.task_certification_detail_fetch_photolog_fail, ToastType.ERROR) + showToast(R.string.photolog_detail_fetch_photolog_fail, ToastType.ERROR) }, onFinally = { reduce { copy(isLoading = true) } }, ) @@ -106,7 +106,7 @@ class TaskCertificationDetailViewModel( onSuccess = {}, onError = { rollbackReaction() - showToast(R.string.task_certification_detail_reaction_fail, ToastType.ERROR) + showToast(R.string.photolog_detail_reaction_fail, ToastType.ERROR) }, ) } @@ -121,23 +121,23 @@ class TaskCertificationDetailViewModel( viewModelScope.launch { detailRefreshBus.events.collect { publisher -> when (publisher) { - TaskCertificationRefreshBus.Publisher.PHOTOLOG -> { + PhotologRefreshBus.Publisher.PHOTOLOG -> { fetchPhotolog() goalRefreshBus.notifyGoalListChanged() } - TaskCertificationRefreshBus.Publisher.EDITOR -> fetchPhotolog() + PhotologRefreshBus.Publisher.EDITOR -> fetchPhotolog() } } } } - override suspend fun handleIntent(intent: TaskCertificationDetailIntent) { + override suspend fun handleIntent(intent: PhotologDetailIntent) { when (intent) { - is TaskCertificationDetailIntent.Reaction -> reduceReaction(intent.type) - TaskCertificationDetailIntent.Poke -> pokeToPartner() - TaskCertificationDetailIntent.SwipeCard -> reduceShownCard() - TaskCertificationDetailIntent.MyReactionEffected -> reduceMyReactionShown() + is PhotologDetailIntent.Reaction -> reduceReaction(intent.type) + PhotologDetailIntent.Poke -> pokeToPartner() + PhotologDetailIntent.SwipeCard -> reduceShownCard() + PhotologDetailIntent.MyReactionEffected -> reduceMyReactionShown() } } @@ -150,7 +150,7 @@ class TaskCertificationDetailViewModel( private fun pokeToPartner() { launchResult( block = { pokeRepository.pokeGoal(argGoalId) }, - onSuccess = { tryEmitSideEffect(TaskCertificationDetailSideEffect.ShowPokeToast(it.message)) }, + onSuccess = { tryEmitSideEffect(PhotologDetailSideEffect.ShowPokeToast(it.message)) }, onError = { showToast(R.string.toast_poke_goal_failed, ToastType.ERROR) }, ) } @@ -159,7 +159,7 @@ class TaskCertificationDetailViewModel( reduce { toggleBetweenUs() } } - private fun toggleBetweenUs(): TaskCertificationDetailUiState = + private fun toggleBetweenUs(): PhotologDetailUiState = currentState.copy( currentShow = when (currentState.currentShow) { @@ -176,7 +176,7 @@ class TaskCertificationDetailViewModel( message: Int, type: ToastType, ) { - emitSideEffect(TaskCertificationDetailSideEffect.ShowToast(message, type)) + emitSideEffect(PhotologDetailSideEffect.ShowToast(message, type)) } companion object { diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologCardContent.kt similarity index 80% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologCardContent.kt index 0f865749..d8768c55 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationCardContent.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologCardContent.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component +package com.twix.photolog.detail.component import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box @@ -17,14 +17,14 @@ import com.twix.designsystem.components.photolog.BackgroundCard import com.twix.designsystem.components.photolog.ForegroundCard import com.twix.designsystem.theme.TwixTheme import com.twix.domain.model.enums.BetweenUs -import com.twix.task_certification.detail.component.reaction.ReactionUiModel -import com.twix.task_certification.detail.component.swipe.SwipeableCard -import com.twix.task_certification.detail.contract.TaskCertificationDetailUiState -import com.twix.task_certification.detail.preview.TaskCertificationDetailPreviewProvider +import com.twix.photolog.detail.component.reaction.ReactionUiModel +import com.twix.photolog.detail.component.swipe.SwipeableCard +import com.twix.photolog.detail.contract.PhotologDetailUiState +import com.twix.photolog.detail.preview.PhotologDetailPreviewProvider @Composable -internal fun TaskCertificationCardContent( - uiState: TaskCertificationDetailUiState, +internal fun PhotologCardContent( + uiState: PhotologDetailUiState, onSwipe: () -> Unit, onClickUpload: () -> Unit, onPoke: () -> Unit, @@ -34,7 +34,7 @@ internal fun TaskCertificationCardContent( uploadedAt = uiState.displayedGoalUpdateAt, actionLabel = when (uiState.currentShow) { - BetweenUs.ME -> stringResource(R.string.task_certification_take_picture) + BetweenUs.ME -> stringResource(R.string.photolog_take_picture) BetweenUs.PARTNER -> stringResource(R.string.action_poke) }, rotation = if (uiState.isDisplayedMyPhotolog) -8f else 0f, @@ -96,12 +96,12 @@ private fun MyReactionBadge( @Preview(showBackground = true) @Composable -private fun TaskCertificationCardContentPreview( - @PreviewParameter(TaskCertificationDetailPreviewProvider::class) - uiState: TaskCertificationDetailUiState, +private fun PhotologCardContentPreview( + @PreviewParameter(PhotologDetailPreviewProvider::class) + uiState: PhotologDetailUiState, ) { TwixTheme { - TaskCertificationCardContent( + PhotologCardContent( uiState = uiState.copy(isLoading = true), onSwipe = {}, onClickUpload = {}, diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationDetailTopBar.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologDetailTopBar.kt similarity index 92% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationDetailTopBar.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologDetailTopBar.kt index 4ee17ab4..4e14cc9c 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/TaskCertificationDetailTopBar.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/PhotologDetailTopBar.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component +package com.twix.photolog.detail.component import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -24,7 +24,7 @@ import com.twix.domain.model.enums.AppTextStyle import com.twix.ui.extension.noRippleClickable @Composable -internal fun TaskCertificationDetailTopBar( +internal fun PhotologDetailTopBar( title: String, canModify: Boolean, onBack: () -> Unit, @@ -67,17 +67,17 @@ internal fun TaskCertificationDetailTopBar( @Preview @Composable -fun TaskCertificationDetailTopBarPreview() { +fun PhotologDetailTopBarPreview() { TwixTheme { Column { - TaskCertificationDetailTopBar( + PhotologDetailTopBar( title = "목표 인증", canModify = true, onBack = {}, onClickModify = {}, ) - TaskCertificationDetailTopBar( + PhotologDetailTopBar( title = "목표 인증", canModify = false, onBack = {}, diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionBar.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionBar.kt similarity index 98% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionBar.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionBar.kt index cfdcf082..3d62265c 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionBar.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionBar.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.reaction +package com.twix.photolog.detail.component.reaction import androidx.compose.foundation.Image import androidx.compose.foundation.background diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionContent.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionContent.kt similarity index 96% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionContent.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionContent.kt index 75da1cad..c6f24ae1 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionContent.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionContent.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.reaction +package com.twix.photolog.detail.component.reaction import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionEffect.kt similarity index 99% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionEffect.kt index 95ecbf97..af7fb7f7 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffect.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionEffect.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.reaction +package com.twix.photolog.detail.component.reaction import androidx.compose.animation.core.FastOutLinearInEasing import androidx.compose.animation.core.LinearOutSlowInEasing diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffectSpec.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionEffectSpec.kt similarity index 91% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffectSpec.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionEffectSpec.kt index 455b1fdf..d0ceefbd 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionEffectSpec.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionEffectSpec.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.reaction +package com.twix.photolog.detail.component.reaction /** * ReactionEffect 애니메이션 설정 값 묶음. diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionParticle.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionParticle.kt similarity index 87% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionParticle.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionParticle.kt index 43b72f30..b9ca5557 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionParticle.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionParticle.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.reaction +package com.twix.photolog.detail.component.reaction import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.AnimationVector1D diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionUiModel.kt similarity index 92% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionUiModel.kt index 2961c377..72778711 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/reaction/ReactionUiModel.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/reaction/ReactionUiModel.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.reaction +package com.twix.photolog.detail.component.reaction import com.twix.designsystem.R import com.twix.domain.model.enums.GoalReactionType diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/swipe/SwipeCardSpec.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/swipe/SwipeCardSpec.kt similarity index 92% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/swipe/SwipeCardSpec.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/swipe/SwipeCardSpec.kt index 54a445bd..3ad087cd 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/swipe/SwipeCardSpec.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/swipe/SwipeCardSpec.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.swipe +package com.twix.photolog.detail.component.swipe import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/swipe/SwipeableCard.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/swipe/SwipeableCard.kt similarity index 99% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/component/swipe/SwipeableCard.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/swipe/SwipeableCard.kt index 90c4bd4b..f5483dca 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/component/swipe/SwipeableCard.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/component/swipe/SwipeableCard.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.detail.component.swipe +package com.twix.photolog.detail.component.swipe import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.spring diff --git a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailIntent.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailIntent.kt new file mode 100644 index 00000000..67ef0f5d --- /dev/null +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailIntent.kt @@ -0,0 +1,16 @@ +package com.twix.photolog.detail.contract + +import com.twix.domain.model.enums.GoalReactionType +import com.twix.ui.base.Intent + +sealed interface PhotologDetailIntent : Intent { + data class Reaction( + val type: GoalReactionType, + ) : PhotologDetailIntent + + data object Poke : PhotologDetailIntent + + data object SwipeCard : PhotologDetailIntent + + data object MyReactionEffected : PhotologDetailIntent +} diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailSideEffect.kt similarity index 54% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailSideEffect.kt index 92532bfb..ccb60416 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailSideEffect.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailSideEffect.kt @@ -1,15 +1,15 @@ -package com.twix.task_certification.detail.contract +package com.twix.photolog.detail.contract import com.twix.designsystem.components.toast.model.ToastType import com.twix.ui.base.SideEffect -sealed interface TaskCertificationDetailSideEffect : SideEffect { +sealed interface PhotologDetailSideEffect : SideEffect { data class ShowToast( val message: Int, val type: ToastType, - ) : TaskCertificationDetailSideEffect + ) : PhotologDetailSideEffect data class ShowPokeToast( val message: String, - ) : TaskCertificationDetailSideEffect + ) : PhotologDetailSideEffect } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailUiState.kt similarity index 58% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailUiState.kt index f5d70449..75c80280 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailUiState.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/contract/PhotologDetailUiState.kt @@ -1,17 +1,17 @@ -package com.twix.task_certification.detail.contract +package com.twix.photolog.detail.contract import androidx.compose.runtime.Immutable import com.twix.domain.model.enums.BetweenUs import com.twix.domain.model.enums.GoalIconType import com.twix.domain.model.photolog.PhotoLogs import com.twix.domain.model.photolog.PhotologDetail -import com.twix.task_certification.detail.component.reaction.ReactionUiModel +import com.twix.photolog.detail.component.reaction.ReactionUiModel import com.twix.ui.base.State import com.twix.util.RelativeTimeFormatter import java.time.LocalDate @Immutable -data class TaskCertificationDetailUiState( +data class PhotologDetailUiState( val goalId: Long = -1L, val currentShow: BetweenUs = BetweenUs.PARTNER, val selectedDate: LocalDate = LocalDate.now(), @@ -31,12 +31,6 @@ data class TaskCertificationDetailUiState( */ val isLoading: Boolean = false, ) : State { - /** - * 현재 [currentShow]에 해당하는 사용자의 인증샷 인증 여부 - * - * - [BetweenUs.ME]: 내 인증샷이 존재하면 `true` - * - [BetweenUs.PARTNER]: 파트너 인증샷이 존재하면 `true` - */ val isDisplayedGoalCertificated: Boolean get() = when (currentShow) { @@ -44,12 +38,6 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog != null } - /** - * 현재 [currentShow]에 해당하는 인증샷의 업로드 시간을 상대적 시간 문자열 - * - * - [BetweenUs.ME]: 내 인증샷 업로드 시간 - * - [BetweenUs.PARTNER]: 파트너 인증샷 업로드 시간 - */ val displayedGoalUpdateAt: String get() = when (currentShow) { @@ -64,13 +52,6 @@ data class TaskCertificationDetailUiState( } ?: "" } - /** - * 현재 [currentShow]에 해당하는 인증샷 URL - * - * - [BetweenUs.ME]: 내 인증샷 이미지 URL - * - [BetweenUs.PARTNER]: 파트너 인증샷 이미지 URL - * - */ val displayedGoalImageUrl: String? get() = when (currentShow) { @@ -78,13 +59,6 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog?.imageUrl } - /** - * 현재 [currentShow]에 해당하는 인증샷의 코멘트 - * - * - [BetweenUs.ME]: 내 코멘트 - * - [BetweenUs.PARTNER]: 파트너 코멘트 - * - */ val displayedGoalComment: String? get() = when (currentShow) { @@ -92,12 +66,6 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerPhotolog?.comment } - /** - * 현재 [currentShow]에 해당하는 사용자의 닉네임 - * - * - [BetweenUs.ME]: 내 닉네임 - * - [BetweenUs.PARTNER]: 파트너 닉네임 - */ val displayedNickname: String get() = when (currentShow) { @@ -105,55 +73,23 @@ data class TaskCertificationDetailUiState( BetweenUs.PARTNER -> partnerNickname } - /** - * 현재 화면이 내 인증샷을 표시하는 상태인지 여부 - * - * 내 인증샷일 때 `true` - */ val isDisplayedMyPhotolog: Boolean get() = currentShow == BetweenUs.ME - /** - * 내 인증샷를 수정할 수 있는지 여부 반환 - * - * 현재 내 인증샷를 보고 있고([isDisplayedMyPhotolog]), - * 인증이 완료된 상태([isDisplayedGoalCertificated])일 때 `true` - */ val canModify: Boolean get() = currentShow == BetweenUs.ME && isDisplayedGoalCertificated - /** - * 파트너 인증샷에 리액션을 남길 수 있는지 여부 - * - * 현재 파트너 인증샷을 보고 있고([BetweenUs.PARTNER]), - * 파트너의 인증이 완료된 상태([isDisplayedGoalCertificated])일 때 `true` - */ val canReaction: Boolean get() = currentShow == BetweenUs.PARTNER && isDisplayedGoalCertificated - /** - * 인증샷 업로드 또는 찌르기 액션 버튼을 표시할지 여부를 반환 - * - * 목표가 완료되지 않았고([isCompletedGoal]이 `false`), - * 현재 대상의 인증이 없는 상태([isDisplayedGoalCertificated]가 `false`)일 때 `true` - */ val showActionButton: Boolean get() = !isCompletedGoal && !isDisplayedGoalCertificated - /** - * 내 인증샷에 달린 리액션 뱃지를 표시할지 여부를 반환 - * - * 내 인증샷을 보고 있고([isDisplayedMyPhotolog]), - * 리액션이 존재하며([myPhotolog]의 reaction이 non-null) 일 때 `true` - */ val showMyPhotologReactionBadge: Boolean get() = isDisplayedMyPhotolog && myPhotolog?.reaction != null - /** - * 내 인증샷의 리액션을 [ReactionUiModel]로 변환하여 반환 - */ val myReaction: ReactionUiModel? get() = myPhotolog?.reaction?.let { ReactionUiModel.find(it) } } @@ -163,13 +99,13 @@ fun PhotoLogs.toUiState( betweenUs: String, selectedDate: LocalDate, isCompletedGoal: Boolean, -): TaskCertificationDetailUiState { +): PhotologDetailUiState { val currentGoalPhotolog = goals.firstOrNull { it.goalId == goalId - } ?: return TaskCertificationDetailUiState() + } ?: return PhotologDetailUiState() - return TaskCertificationDetailUiState( + return PhotologDetailUiState( goalId = goalId, currentShow = BetweenUs.valueOf(betweenUs), selectedDate = selectedDate, diff --git a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt new file mode 100644 index 00000000..673d01ac --- /dev/null +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt @@ -0,0 +1,18 @@ +package com.twix.photolog.detail.di + +import com.twix.navigation.NavRoutes +import com.twix.navigation.base.NavGraphContributor +import com.twix.photolog.capture.di.photologCaptureModule +import com.twix.photolog.detail.PhotologDetailViewModel +import com.twix.photolog.detail.navigation.PhotologGraph +import com.twix.photolog.editor.di.photologEditorModule +import org.koin.core.module.dsl.viewModelOf +import org.koin.core.qualifier.named +import org.koin.dsl.module + +val photologDetailModule = + module { + includes(photologCaptureModule, photologEditorModule) + viewModelOf(::PhotologDetailViewModel) + single(named(NavRoutes.PhotologRoute.route)) { PhotologGraph } + } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt similarity index 65% rename from feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt index 30cb6ed1..8a063438 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/navigation/TaskCertificationGraph.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.navigation +package com.twix.photolog.detail.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController @@ -9,15 +9,15 @@ import androidx.navigation.navigation import com.twix.navigation.NavRoutes import com.twix.navigation.args.DetailNavArgs import com.twix.navigation.base.NavGraphContributor -import com.twix.task_certification.certification.TaskCertificationRoute -import com.twix.task_certification.detail.TaskCertificationDetailRoute -import com.twix.task_certification.editor.TaskCertificationEditorRoute +import com.twix.photolog.capture.PhotologCaptureRoute +import com.twix.photolog.detail.PhotologDetailRoute +import com.twix.photolog.editor.PhotologEditorRoute -object TaskCertificationGraph : NavGraphContributor { +object PhotologGraph : NavGraphContributor { override val graphRoute: NavRoutes - get() = NavRoutes.TaskCertificationGraph + get() = NavRoutes.PhotologGraph override val startDestination: String - get() = NavRoutes.TaskCertificationDetailRoute.route + get() = NavRoutes.PhotologDetailRoute.route override fun NavGraphBuilder.registerGraph(navController: NavHostController) { navigation( @@ -25,32 +25,32 @@ object TaskCertificationGraph : NavGraphContributor { startDestination = startDestination, ) { composable( - route = NavRoutes.TaskCertificationDetailRoute.route, + route = NavRoutes.PhotologDetailRoute.route, arguments = listOf( - navArgument(NavRoutes.TaskCertificationDetailRoute.ARG_GOAL_ID) { + navArgument(NavRoutes.PhotologDetailRoute.ARG_GOAL_ID) { type = NavType.LongType }, - navArgument(NavRoutes.TaskCertificationDetailRoute.ARG_DATE) { + navArgument(NavRoutes.PhotologDetailRoute.ARG_DATE) { type = NavType.StringType }, - navArgument(NavRoutes.TaskCertificationDetailRoute.ARG_BETWEEN_US) { + navArgument(NavRoutes.PhotologDetailRoute.ARG_BETWEEN_US) { type = NavType.StringType }, - navArgument(NavRoutes.TaskCertificationDetailRoute.ARG_IS_COMPLETED) { + navArgument(NavRoutes.PhotologDetailRoute.ARG_IS_COMPLETED) { type = NavType.BoolType defaultValue = false }, ), ) { - TaskCertificationDetailRoute( + PhotologDetailRoute( navigateToBack = navController::popBackStack, navigateToCertification = { goalId, date -> val destination = - NavRoutes.TaskCertificationRoute.createRoute( + NavRoutes.PhotologRoute.createRoute( DetailNavArgs( goalId = goalId, - from = NavRoutes.TaskCertificationRoute.From.DETAIL, + from = NavRoutes.PhotologRoute.From.DETAIL, selectedDate = date.toString(), ), ) @@ -58,7 +58,7 @@ object TaskCertificationGraph : NavGraphContributor { }, navigateToEditor = { goalId, date -> navController.navigate( - NavRoutes.TaskCertificationEditorRoute.createRoute( + NavRoutes.PhotologEditorRoute.createRoute( goalId = goalId, date = date, ), @@ -68,25 +68,25 @@ object TaskCertificationGraph : NavGraphContributor { } composable( - route = NavRoutes.TaskCertificationEditorRoute.route, + route = NavRoutes.PhotologEditorRoute.route, arguments = listOf( - navArgument(NavRoutes.TaskCertificationEditorRoute.ARG_GOAL_ID) { + navArgument(NavRoutes.PhotologEditorRoute.ARG_GOAL_ID) { type = NavType.LongType }, - navArgument(NavRoutes.TaskCertificationEditorRoute.ARG_DATE) { + navArgument(NavRoutes.PhotologEditorRoute.ARG_DATE) { type = NavType.StringType }, ), ) { - TaskCertificationEditorRoute( + PhotologEditorRoute( navigateToBack = navController::popBackStack, navigateToCertification = { goalId, photologId, comment, selectedDate -> val destination = - NavRoutes.TaskCertificationRoute.createRoute( + NavRoutes.PhotologRoute.createRoute( DetailNavArgs( goalId = goalId, - from = NavRoutes.TaskCertificationRoute.From.EDITOR, + from = NavRoutes.PhotologRoute.From.EDITOR, photologId = photologId, selectedDate = selectedDate.toString(), comment = comment, @@ -98,25 +98,25 @@ object TaskCertificationGraph : NavGraphContributor { } composable( - route = NavRoutes.TaskCertificationRoute.route, + route = NavRoutes.PhotologRoute.route, arguments = listOf( - navArgument(NavRoutes.TaskCertificationRoute.ARG_DATA) { + navArgument(NavRoutes.PhotologRoute.ARG_DATA) { type = NavType.StringType }, ), ) { - TaskCertificationRoute( + PhotologCaptureRoute( navigateToBack = navController::popBackStack, navigateToDetail = { goalId, date, betweenUs -> navController.navigate( - NavRoutes.TaskCertificationDetailRoute.createRoute( + NavRoutes.PhotologDetailRoute.createRoute( goalId = goalId, date = date, betweenUs = betweenUs.name, ), ) { - popUpTo(NavRoutes.TaskCertificationDetailRoute.route) { + popUpTo(NavRoutes.PhotologDetailRoute.route) { inclusive = true } launchSingleTop = true diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/preview/TaskCertificationDetailPreviewProvider.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/preview/PhotologDetailPreviewProvider.kt similarity index 85% rename from feature/task-certification/src/main/java/com/twix/task_certification/detail/preview/TaskCertificationDetailPreviewProvider.kt rename to feature/photolog/detail/src/main/java/com/twix/photolog/detail/preview/PhotologDetailPreviewProvider.kt index 03eebdbf..a4d06649 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/preview/TaskCertificationDetailPreviewProvider.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/preview/PhotologDetailPreviewProvider.kt @@ -1,16 +1,16 @@ -package com.twix.task_certification.detail.preview +package com.twix.photolog.detail.preview import androidx.compose.ui.tooling.preview.PreviewParameterProvider import com.twix.domain.model.enums.BetweenUs import com.twix.domain.model.enums.GoalIconType import com.twix.domain.model.enums.GoalReactionType import com.twix.domain.model.photolog.PhotologDetail -import com.twix.task_certification.detail.contract.TaskCertificationDetailUiState +import com.twix.photolog.detail.contract.PhotologDetailUiState -class TaskCertificationDetailPreviewProvider : PreviewParameterProvider { +class PhotologDetailPreviewProvider : PreviewParameterProvider { override val values = sequenceOf( - TaskCertificationDetailUiState( + PhotologDetailUiState( goalId = 1, currentShow = BetweenUs.ME, myNickname = "나", @@ -30,7 +30,7 @@ class TaskCertificationDetailPreviewProvider : PreviewParameterProvider + diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorRoute.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt similarity index 85% rename from feature/task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorRoute.kt rename to feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt index 998be202..5d8f24c5 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorRoute.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.editor +package com.twix.photolog.editor import android.Manifest import androidx.activity.compose.rememberLauncherForActivityResult @@ -38,11 +38,11 @@ import com.twix.designsystem.components.toast.model.ToastType import com.twix.designsystem.extension.showCameraPermissionToastWithNavigateToSettingAction import com.twix.designsystem.theme.CommonColor import com.twix.designsystem.theme.TwixTheme -import com.twix.task_certification.editor.component.RetakeButton -import com.twix.task_certification.editor.component.TaskCertificationEditorTopBar -import com.twix.task_certification.editor.contract.TaskCertificationEditorIntent -import com.twix.task_certification.editor.contract.TaskCertificationEditorSideEffect -import com.twix.task_certification.editor.contract.TaskCertificationEditorUiState +import com.twix.photolog.editor.component.RetakeButton +import com.twix.photolog.editor.component.PhotologEditorTopBar +import com.twix.photolog.editor.contract.PhotologEditorIntent +import com.twix.photolog.editor.contract.PhotologEditorSideEffect +import com.twix.photolog.editor.contract.PhotologEditorUiState import com.twix.ui.base.ObserveAsEvents import com.twix.ui.extension.findActivity import com.twix.ui.extension.hasCameraPermission @@ -53,11 +53,11 @@ import org.koin.compose.koinInject import java.time.LocalDate @Composable -fun TaskCertificationEditorRoute( +fun PhotologEditorRoute( navigateToBack: () -> Unit, navigateToCertification: (Long, Long, String, LocalDate) -> Unit, toastManager: ToastManager = koinInject(), - viewModel: TaskCertificationEditorViewModel = koinViewModel(), + viewModel: PhotologEditorViewModel = koinViewModel(), ) { val context = LocalContext.current val currentContext by rememberUpdatedState(context) @@ -66,7 +66,7 @@ fun TaskCertificationEditorRoute( ObserveAsEvents(viewModel.sideEffect) { sideEffect -> when (sideEffect) { - is TaskCertificationEditorSideEffect.ShowToast -> + is PhotologEditorSideEffect.ShowToast -> toastManager.tryShow( ToastData( currentContext.getString(sideEffect.message), @@ -112,12 +112,12 @@ fun TaskCertificationEditorRoute( } } - TaskCertificationEditorScreen( + PhotologEditorScreen( uiState = uiState, onBack = navigateToBack, - onClickSave = { viewModel.dispatch(TaskCertificationEditorIntent.Save) }, - onFocusChanged = { viewModel.dispatch(TaskCertificationEditorIntent.CommentFocusChanged(it)) }, - onCommentChanged = { viewModel.dispatch(TaskCertificationEditorIntent.ModifyComment(it)) }, + onClickSave = { viewModel.dispatch(PhotologEditorIntent.Save) }, + onFocusChanged = { viewModel.dispatch(PhotologEditorIntent.CommentFocusChanged(it)) }, + onCommentChanged = { viewModel.dispatch(PhotologEditorIntent.ModifyComment(it)) }, onClickRetake = { if (currentContext.hasCameraPermission()) { navigateToCertification( @@ -134,8 +134,8 @@ fun TaskCertificationEditorRoute( } @Composable -fun TaskCertificationEditorScreen( - uiState: TaskCertificationEditorUiState, +fun PhotologEditorScreen( + uiState: PhotologEditorUiState, onBack: () -> Unit, onClickSave: () -> Unit, onCommentChanged: (String) -> Unit, @@ -153,7 +153,7 @@ fun TaskCertificationEditorScreen( .noRippleClickable { focusManager.clearFocus() }, ) { Column { - TaskCertificationEditorTopBar( + PhotologEditorTopBar( title = uiState.goalName, onBack = onBack, onClickSave = onClickSave, @@ -199,11 +199,11 @@ fun TaskCertificationEditorScreen( @Preview(showBackground = true) @Composable -private fun TaskCertificationEditorScreenPreview() { +private fun PhotologEditorScreenPreview() { TwixTheme { - TaskCertificationEditorScreen( + PhotologEditorScreen( uiState = - TaskCertificationEditorUiState( + PhotologEditorUiState( nickname = "페토", goalName = "아이스크림 먹기", ), diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorViewModel.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt similarity index 57% rename from feature/task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorViewModel.kt rename to feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt index 1f60f83b..368987b2 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/TaskCertificationEditorViewModel.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.editor +package com.twix.photolog.editor import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope @@ -7,41 +7,41 @@ import com.twix.designsystem.components.toast.model.ToastType import com.twix.domain.repository.PhotoLogRepository import com.twix.navigation.NavRoutes import com.twix.result.AppResult -import com.twix.task_certification.editor.contract.TaskCertificationEditorIntent -import com.twix.task_certification.editor.contract.TaskCertificationEditorSideEffect -import com.twix.task_certification.editor.contract.TaskCertificationEditorUiState -import com.twix.task_certification.editor.contract.toEditorUiState +import com.twix.photolog.editor.contract.PhotologEditorIntent +import com.twix.photolog.editor.contract.PhotologEditorSideEffect +import com.twix.photolog.editor.contract.PhotologEditorUiState +import com.twix.photolog.editor.contract.toEditorUiState import com.twix.ui.base.BaseViewModel import com.twix.util.bus.GoalRefreshBus -import com.twix.util.bus.TaskCertificationRefreshBus +import com.twix.util.bus.PhotologRefreshBus import kotlinx.coroutines.launch import java.time.LocalDate -class TaskCertificationEditorViewModel( +class PhotologEditorViewModel( private val photologRepository: PhotoLogRepository, - private val detailRefreshBus: TaskCertificationRefreshBus, + private val detailRefreshBus: PhotologRefreshBus, private val goalRefreshBus: GoalRefreshBus, savedStateHandle: SavedStateHandle, -) : BaseViewModel( - TaskCertificationEditorUiState(), +) : BaseViewModel( + PhotologEditorUiState(), ) { private val argGoalId: Long = - requireNotNull(savedStateHandle[NavRoutes.TaskCertificationEditorRoute.ARG_GOAL_ID]) { GOAL_ID_NOT_FOUND } + requireNotNull(savedStateHandle[NavRoutes.PhotologEditorRoute.ARG_GOAL_ID]) { GOAL_ID_NOT_FOUND } private val argTargetDate: LocalDate = LocalDate.parse( - requireNotNull(savedStateHandle[NavRoutes.TaskCertificationEditorRoute.ARG_DATE]) { TARGET_DATE_NOT_FOUND }, + requireNotNull(savedStateHandle[NavRoutes.PhotologEditorRoute.ARG_DATE]) { TARGET_DATE_NOT_FOUND }, ) init { fetchPhotolog() } - override suspend fun handleIntent(intent: TaskCertificationEditorIntent) { + override suspend fun handleIntent(intent: PhotologEditorIntent) { when (intent) { - is TaskCertificationEditorIntent.CommentFocusChanged -> reduceCommentFocus(intent.isFocused) - is TaskCertificationEditorIntent.ModifyComment -> reduceComment(intent.value) - TaskCertificationEditorIntent.Save -> modifyComment() + is PhotologEditorIntent.CommentFocusChanged -> reduceCommentFocus(intent.isFocused) + is PhotologEditorIntent.ModifyComment -> reduceComment(intent.value) + PhotologEditorIntent.Save -> modifyComment() } } @@ -57,17 +57,17 @@ class TaskCertificationEditorViewModel( if (currentState.comment.canUpload.not()) { showToast(R.string.comment_error_message, ToastType.ERROR) } else if (currentState.isCommentNotChanged) { - showToast(R.string.task_certification_editor_not_modified, ToastType.ERROR) + showToast(R.string.photolog_editor_not_modified, ToastType.ERROR) } else { launchResult( block = { launchModifyComment() }, onSuccess = { - detailRefreshBus.notifyChanged(TaskCertificationRefreshBus.Publisher.EDITOR) + detailRefreshBus.notifyChanged(PhotologRefreshBus.Publisher.EDITOR) goalRefreshBus.notifyGoalListChanged() - showToast(R.string.task_certification_editor_modify_success, ToastType.SUCCESS) + showToast(R.string.photolog_editor_modify_success, ToastType.SUCCESS) }, onError = { - showToast(R.string.task_certification_editor_modify_fail, ToastType.ERROR) + showToast(R.string.photolog_editor_modify_fail, ToastType.ERROR) }, ) } @@ -79,7 +79,7 @@ class TaskCertificationEditorViewModel( ) { viewModelScope.launch { emitSideEffect( - TaskCertificationEditorSideEffect.ShowToast(message, type), + PhotologEditorSideEffect.ShowToast(message, type), ) } } @@ -89,7 +89,7 @@ class TaskCertificationEditorViewModel( block = { photologRepository.fetchPhotologs(argTargetDate, argGoalId) }, onSuccess = { reduce { it.toEditorUiState(argGoalId, argTargetDate) } }, onError = { - showToast(R.string.task_certification_detail_fetch_photolog_fail, ToastType.ERROR) + showToast(R.string.photolog_detail_fetch_photolog_fail, ToastType.ERROR) }, ) } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/component/TaskCertificationEditorTopBar.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/component/PhotologEditorTopBar.kt similarity index 91% rename from feature/task-certification/src/main/java/com/twix/task_certification/editor/component/TaskCertificationEditorTopBar.kt rename to feature/photolog/editor/src/main/java/com/twix/photolog/editor/component/PhotologEditorTopBar.kt index bd3c2084..1f7f8ac8 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/component/TaskCertificationEditorTopBar.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/component/PhotologEditorTopBar.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.editor.component +package com.twix.photolog.editor.component import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -24,7 +24,7 @@ import com.twix.domain.model.enums.AppTextStyle import com.twix.ui.extension.noRippleClickable @Composable -internal fun TaskCertificationEditorTopBar( +internal fun PhotologEditorTopBar( title: String, onBack: () -> Unit, onClickSave: () -> Unit, @@ -64,16 +64,16 @@ internal fun TaskCertificationEditorTopBar( @Preview @Composable -fun TaskCertificationEditorTopBarPreview() { +fun PhotologEditorTopBarPreview() { TwixTheme { Column { - TaskCertificationEditorTopBar( + PhotologEditorTopBar( title = "목표 인증", onBack = {}, onClickSave = {}, ) - TaskCertificationEditorTopBar( + PhotologEditorTopBar( title = "목표 인증", onBack = {}, onClickSave = {}, diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/component/RetakeButton.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/component/RetakeButton.kt similarity index 90% rename from feature/task-certification/src/main/java/com/twix/task_certification/editor/component/RetakeButton.kt rename to feature/photolog/editor/src/main/java/com/twix/photolog/editor/component/RetakeButton.kt index c55390cb..7ea34426 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/component/RetakeButton.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/component/RetakeButton.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.editor.component +package com.twix.photolog.editor.component import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -21,7 +21,7 @@ internal fun RetakeButton( modifier: Modifier = Modifier, ) { AppRoundButton( - text = stringResource(R.string.task_certification_editor_retake), + text = stringResource(R.string.photolog_editor_retake), textColor = GrayColor.C500, backgroundColor = CommonColor.White, modifier = diff --git a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorIntent.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorIntent.kt new file mode 100644 index 00000000..b748f8ed --- /dev/null +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorIntent.kt @@ -0,0 +1,15 @@ +package com.twix.photolog.editor.contract + +import com.twix.ui.base.Intent + +sealed interface PhotologEditorIntent : Intent { + data object Save : PhotologEditorIntent + + data class CommentFocusChanged( + val isFocused: Boolean, + ) : PhotologEditorIntent + + data class ModifyComment( + val value: String, + ) : PhotologEditorIntent +} diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorSideEffect.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorSideEffect.kt similarity index 53% rename from feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorSideEffect.kt rename to feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorSideEffect.kt index f46c5660..868b471d 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorSideEffect.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorSideEffect.kt @@ -1,11 +1,11 @@ -package com.twix.task_certification.editor.contract +package com.twix.photolog.editor.contract import com.twix.designsystem.components.toast.model.ToastType import com.twix.ui.base.SideEffect -sealed interface TaskCertificationEditorSideEffect : SideEffect { +sealed interface PhotologEditorSideEffect : SideEffect { data class ShowToast( val message: Int, val type: ToastType, - ) : TaskCertificationEditorSideEffect + ) : PhotologEditorSideEffect } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorUiState.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorUiState.kt similarity index 88% rename from feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorUiState.kt rename to feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorUiState.kt index 9155c52c..22099d68 100644 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorUiState.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/contract/PhotologEditorUiState.kt @@ -1,4 +1,4 @@ -package com.twix.task_certification.editor.contract +package com.twix.photolog.editor.contract import androidx.compose.runtime.Immutable import com.twix.designsystem.components.comment.model.CommentUiModel @@ -7,7 +7,7 @@ import com.twix.ui.base.State import java.time.LocalDate @Immutable -data class TaskCertificationEditorUiState( +data class PhotologEditorUiState( val goalId: Long = -1, val photologId: Long = -1, val selectedDate: LocalDate = LocalDate.now(), @@ -31,11 +31,11 @@ data class TaskCertificationEditorUiState( internal fun PhotoLogs.toEditorUiState( goalId: Long, selectedDate: LocalDate, -): TaskCertificationEditorUiState { +): PhotologEditorUiState { val goalPhotolog = goals.firstOrNull { it.goalId == goalId } val myPhotolog = goalPhotolog?.myPhotolog - return TaskCertificationEditorUiState( + return PhotologEditorUiState( goalId = goalId, photologId = myPhotolog?.photologId ?: -1, selectedDate = selectedDate, diff --git a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt new file mode 100644 index 00000000..7fccc23a --- /dev/null +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt @@ -0,0 +1,10 @@ +package com.twix.photolog.editor.di + +import com.twix.photolog.editor.PhotologEditorViewModel +import org.koin.core.module.dsl.viewModelOf +import org.koin.dsl.module + +val photologEditorModule = + module { + viewModelOf(::PhotologEditorViewModel) + } diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt index 35dd2e97..105ba0e7 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailScreen.kt @@ -61,7 +61,7 @@ import java.time.LocalDate fun StatsDetailRoute( onBack: () -> Unit, navigateToGoalEditor: (Long) -> Unit, - navigateToTaskCertificationDetail: (Long, LocalDate, BetweenUs, Boolean) -> Unit, + navigateToPhotologDetail: (Long, LocalDate, BetweenUs, Boolean) -> Unit, toastManager: ToastManager = koinInject(), viewModel: StatsDetailViewModel = koinViewModel(), ) { @@ -74,8 +74,8 @@ fun StatsDetailRoute( when (sideEffect) { StatsDetailSideEffect.NavigateToBack -> onBack() is StatsDetailSideEffect.NavigateToGoalEditor -> navigateToGoalEditor(sideEffect.goalId) - is StatsDetailSideEffect.NavigateToTaskCertificationDetail -> - navigateToTaskCertificationDetail( + is StatsDetailSideEffect.NavigateToPhotologDetail -> + navigateToPhotologDetail( sideEffect.goalId, sideEffect.date, sideEffect.betweenUs, @@ -258,17 +258,15 @@ private fun StatsDeleteDialogContent( ) { Image( painter = painterResource(icon.toRes()), - contentDescription = "emoji", - modifier = - Modifier - .size(60.dp), + contentDescription = null, + modifier = Modifier.size(94.dp), ) - Spacer(Modifier.height(12.dp)) + Spacer(Modifier.height(16.dp)) AppText( text = title, - style = AppTextStyle.T1, + style = AppTextStyle.H2, color = GrayColor.C500, textAlign = TextAlign.Center, ) @@ -277,9 +275,8 @@ private fun StatsDeleteDialogContent( AppText( text = content, - style = AppTextStyle.B2, - color = GrayColor.C500, - textAlign = TextAlign.Center, + style = AppTextStyle.B3, + color = GrayColor.C300, ) } } diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt index 9e578d2e..aedbd4da 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/StatsDetailViewModel.kt @@ -193,7 +193,7 @@ class StatsDetailViewModel( override suspend fun handleIntent(intent: StatsDetailIntent) { when (intent) { - is StatsDetailIntent.SelectDate -> navigateToTaskCertificationDetail(intent.date) + is StatsDetailIntent.SelectDate -> navigateToPhotologDetail(intent.date) StatsDetailIntent.GoalEdit -> navigateToGoalEditor() StatsDetailIntent.PreviousMonth -> fetchPreviousMonth() StatsDetailIntent.NextMonth -> fetchNextMonth() @@ -202,12 +202,12 @@ class StatsDetailViewModel( } } - private suspend fun navigateToTaskCertificationDetail(selectedDate: LocalDate) { + private suspend fun navigateToPhotologDetail(selectedDate: LocalDate) { val completedDate = findCompletedDate(selectedDate) ?: return if (completedDate.myImageUrl == null && completedDate.partnerImageUrl == null) return emitSideEffect( - StatsDetailSideEffect.NavigateToTaskCertificationDetail( + StatsDetailSideEffect.NavigateToPhotologDetail( goalId = argGoalId, date = selectedDate, betweenUs = determineDisplayBetweenUs(completedDate.date), diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt index d7c2d393..767685e8 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/contract/StatsDetailSideEffect.kt @@ -17,7 +17,7 @@ sealed interface StatsDetailSideEffect : SideEffect { val goalId: Long, ) : StatsDetailSideEffect - data class NavigateToTaskCertificationDetail( + data class NavigateToPhotologDetail( val goalId: Long, val date: LocalDate, val betweenUs: BetweenUs, diff --git a/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt b/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt index ef12f777..e5b1f92b 100644 --- a/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt +++ b/feature/stats/detail/src/main/java/com/twix/stats/detail/navigation/StatsDetailGraph.kt @@ -36,9 +36,9 @@ object StatsDetailGraph : NavGraphContributor { launchSingleTop = true } }, - navigateToTaskCertificationDetail = { goalId, date, betweenUs, isCompleted -> + navigateToPhotologDetail = { goalId, date, betweenUs, isCompleted -> val destination = - NavRoutes.TaskCertificationDetailRoute.createRoute( + NavRoutes.PhotologDetailRoute.createRoute( goalId = goalId, date = date, betweenUs = betweenUs.name, diff --git a/feature/task-certification/.gitignore b/feature/task-certification/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/feature/task-certification/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/feature/task-certification/consumer-rules.pro b/feature/task-certification/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/feature/task-certification/proguard-rules.pro b/feature/task-certification/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/feature/task-certification/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt b/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt deleted file mode 100644 index 00e57ece..00000000 --- a/feature/task-certification/src/main/java/com/twix/task_certification/detail/contract/TaskCertificationDetailIntent.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.twix.task_certification.detail.contract - -import com.twix.domain.model.enums.GoalReactionType -import com.twix.ui.base.Intent - -sealed interface TaskCertificationDetailIntent : Intent { - data class Reaction( - val type: GoalReactionType, - ) : TaskCertificationDetailIntent - - data object Poke : TaskCertificationDetailIntent - - data object SwipeCard : TaskCertificationDetailIntent - - data object MyReactionEffected : TaskCertificationDetailIntent -} diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/di/TaskCertificationModule.kt b/feature/task-certification/src/main/java/com/twix/task_certification/di/TaskCertificationModule.kt deleted file mode 100644 index fddd2a5a..00000000 --- a/feature/task-certification/src/main/java/com/twix/task_certification/di/TaskCertificationModule.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.twix.task_certification.di - -import com.twix.navigation.NavRoutes -import com.twix.navigation.base.NavGraphContributor -import com.twix.task_certification.certification.TaskCertificationViewModel -import com.twix.task_certification.certification.model.camera.Camera -import com.twix.task_certification.certification.model.camera.CaptureCamera -import com.twix.task_certification.detail.TaskCertificationDetailViewModel -import com.twix.task_certification.editor.TaskCertificationEditorViewModel -import com.twix.task_certification.navigation.TaskCertificationGraph -import org.koin.core.module.dsl.viewModelOf -import org.koin.core.qualifier.named -import org.koin.dsl.module - -val taskCertificationModule = - module { - viewModelOf(::TaskCertificationDetailViewModel) - viewModelOf(::TaskCertificationViewModel) - viewModelOf(::TaskCertificationEditorViewModel) - factory { CaptureCamera(get()) } - single(named(NavRoutes.TaskCertificationRoute.route)) { TaskCertificationGraph } - } diff --git a/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorIntent.kt b/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorIntent.kt deleted file mode 100644 index 42bf9693..00000000 --- a/feature/task-certification/src/main/java/com/twix/task_certification/editor/contract/TaskCertificationEditorIntent.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.twix.task_certification.editor.contract - -import com.twix.ui.base.Intent - -sealed interface TaskCertificationEditorIntent : Intent { - data object Save : TaskCertificationEditorIntent - - data class CommentFocusChanged( - val isFocused: Boolean, - ) : TaskCertificationEditorIntent - - data class ModifyComment( - val value: String, - ) : TaskCertificationEditorIntent -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 5db1e85a..818491b2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,7 +40,9 @@ include(":core:design-system") include(":core:network") include(":core:analytics") include(":feature:main") -include(":feature:task-certification") +include(":feature:photolog:capture") +include(":feature:photolog:detail") +include(":feature:photolog:editor") include(":feature:goal-editor") include(":feature:goal-manage") include(":feature:settings") From 719151cdeeea44b49d3657d54398f9740809974a Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Fri, 6 Mar 2026 14:46:42 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor:=20photolog?= =?UTF-8?q?=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=EC=9D=84=20fea?= =?UTF-8?q?ture=20=EB=AA=A8=EB=93=88=EB=B3=84=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 + .../java/com/yapp/twix/di/FeatureModules.kt | 4 + .../main/java/com/twix/util/di/UtilModule.kt | 2 +- .../capture/PhotologCaptureViewModel.kt | 2 +- .../capture/di/PhotologCaptureModule.kt | 5 + .../navigation/PhotologCaptureNavGraph.kt | 47 +++++++ feature/photolog/detail/build.gradle.kts | 5 - .../detail/di/PhotologDetailModule.kt | 7 +- .../navigation/PhotologDetailNavGraph.kt | 63 +++++++++ .../detail/navigation/PhotologGraph.kt | 129 ------------------ .../photolog/editor/PhotologEditorRoute.kt | 2 +- .../editor/PhotologEditorViewModel.kt | 2 +- .../editor/di/PhotologEditorModule.kt | 5 + .../navigation/PhotologEditorNavGraph.kt | 50 +++++++ 14 files changed, 182 insertions(+), 143 deletions(-) create mode 100644 feature/photolog/capture/src/main/java/com/twix/photolog/capture/navigation/PhotologCaptureNavGraph.kt create mode 100644 feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologDetailNavGraph.kt delete mode 100644 feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt create mode 100644 feature/photolog/editor/src/main/java/com/twix/photolog/editor/navigation/PhotologEditorNavGraph.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8d477a58..bf21cfbf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -60,7 +60,9 @@ dependencies { implementation(projects.domain) implementation(projects.feature.login) implementation(projects.feature.main) + implementation(projects.feature.photolog.capture) implementation(projects.feature.photolog.detail) + implementation(projects.feature.photolog.editor) implementation(projects.feature.onboarding) implementation(projects.feature.goalEditor) implementation(projects.feature.goalManage) diff --git a/app/src/main/java/com/yapp/twix/di/FeatureModules.kt b/app/src/main/java/com/yapp/twix/di/FeatureModules.kt index de6d20f0..b63b5a5c 100644 --- a/app/src/main/java/com/yapp/twix/di/FeatureModules.kt +++ b/app/src/main/java/com/yapp/twix/di/FeatureModules.kt @@ -7,7 +7,9 @@ import com.twix.login.di.loginModule import com.twix.main.di.mainModule import com.twix.notification.di.notificationFeatureModule import com.twix.onboarding.di.onBoardingModule +import com.twix.photolog.capture.di.photologCaptureModule import com.twix.photolog.detail.di.photologDetailModule +import com.twix.photolog.editor.di.photologEditorModule import com.twix.settings.di.settingsModule import com.twix.splash.di.splashModule import com.twix.stats.detail.di.statsDetailModule @@ -19,7 +21,9 @@ val featureModules: List = loginModule, mainModule, homeModule, + photologCaptureModule, photologDetailModule, + photologEditorModule, goalEditorModule, goalManageModule, settingsModule, diff --git a/core/util/src/main/java/com/twix/util/di/UtilModule.kt b/core/util/src/main/java/com/twix/util/di/UtilModule.kt index f651c1f4..2516d112 100644 --- a/core/util/src/main/java/com/twix/util/di/UtilModule.kt +++ b/core/util/src/main/java/com/twix/util/di/UtilModule.kt @@ -1,9 +1,9 @@ package com.twix.util.di import com.twix.util.bus.GoalRefreshBus +import com.twix.util.bus.PhotologRefreshBus import com.twix.util.bus.StatsDetailRefreshBus import com.twix.util.bus.StatsRefreshBus -import com.twix.util.bus.PhotologRefreshBus import org.koin.dsl.module val utilModule = diff --git a/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt index 2cd17655..da1c8d1e 100644 --- a/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/PhotologCaptureViewModel.kt @@ -18,8 +18,8 @@ import com.twix.photolog.capture.model.CaptureStatus import com.twix.ui.base.BaseViewModel import com.twix.ui.image.ImageGenerator import com.twix.util.bus.GoalRefreshBus -import com.twix.util.bus.StatsDetailRefreshBus import com.twix.util.bus.PhotologRefreshBus +import com.twix.util.bus.StatsDetailRefreshBus import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch diff --git a/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt index dc0a7f7d..3ca797e1 100644 --- a/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/di/PhotologCaptureModule.kt @@ -1,13 +1,18 @@ package com.twix.photolog.capture.di +import com.twix.navigation.NavRoutes +import com.twix.navigation.base.NavGraphContributor import com.twix.photolog.capture.PhotologCaptureViewModel import com.twix.photolog.capture.model.camera.Camera import com.twix.photolog.capture.model.camera.CaptureCamera +import com.twix.photolog.capture.navigation.PhotologCaptureNavGraph import org.koin.core.module.dsl.viewModelOf +import org.koin.core.qualifier.named import org.koin.dsl.module val photologCaptureModule = module { viewModelOf(::PhotologCaptureViewModel) factory { CaptureCamera(get()) } + single(named(NavRoutes.PhotologRoute.route)) { PhotologCaptureNavGraph } } diff --git a/feature/photolog/capture/src/main/java/com/twix/photolog/capture/navigation/PhotologCaptureNavGraph.kt b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/navigation/PhotologCaptureNavGraph.kt new file mode 100644 index 00000000..5e7d8938 --- /dev/null +++ b/feature/photolog/capture/src/main/java/com/twix/photolog/capture/navigation/PhotologCaptureNavGraph.kt @@ -0,0 +1,47 @@ +package com.twix.photolog.capture.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import com.twix.navigation.NavRoutes +import com.twix.navigation.base.NavGraphContributor +import com.twix.photolog.capture.PhotologCaptureRoute + +object PhotologCaptureNavGraph : NavGraphContributor { + override val graphRoute: NavRoutes + get() = NavRoutes.PhotologRoute + override val startDestination: String + get() = NavRoutes.PhotologRoute.route + + override fun NavGraphBuilder.registerGraph(navController: NavHostController) { + composable( + route = NavRoutes.PhotologRoute.route, + arguments = + listOf( + navArgument(NavRoutes.PhotologRoute.ARG_DATA) { + type = NavType.StringType + }, + ), + ) { + PhotologCaptureRoute( + navigateToBack = navController::popBackStack, + navigateToDetail = { goalId, date, betweenUs -> + navController.navigate( + NavRoutes.PhotologDetailRoute.createRoute( + goalId = goalId, + date = date, + betweenUs = betweenUs.name, + ), + ) { + popUpTo(NavRoutes.PhotologDetailRoute.route) { + inclusive = true + } + launchSingleTop = true + } + }, + ) + } + } +} diff --git a/feature/photolog/detail/build.gradle.kts b/feature/photolog/detail/build.gradle.kts index 8bc0906a..7d3565cf 100644 --- a/feature/photolog/detail/build.gradle.kts +++ b/feature/photolog/detail/build.gradle.kts @@ -5,8 +5,3 @@ plugins { android { namespace = "com.twix.photolog.detail" } - -dependencies { - implementation(projects.feature.photolog.capture) - implementation(projects.feature.photolog.editor) -} diff --git a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt index 673d01ac..218f9c04 100644 --- a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/di/PhotologDetailModule.kt @@ -2,17 +2,14 @@ package com.twix.photolog.detail.di import com.twix.navigation.NavRoutes import com.twix.navigation.base.NavGraphContributor -import com.twix.photolog.capture.di.photologCaptureModule import com.twix.photolog.detail.PhotologDetailViewModel -import com.twix.photolog.detail.navigation.PhotologGraph -import com.twix.photolog.editor.di.photologEditorModule +import com.twix.photolog.detail.navigation.PhotologDetailNavGraph import org.koin.core.module.dsl.viewModelOf import org.koin.core.qualifier.named import org.koin.dsl.module val photologDetailModule = module { - includes(photologCaptureModule, photologEditorModule) viewModelOf(::PhotologDetailViewModel) - single(named(NavRoutes.PhotologRoute.route)) { PhotologGraph } + single(named(NavRoutes.PhotologDetailRoute.route)) { PhotologDetailNavGraph } } diff --git a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologDetailNavGraph.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologDetailNavGraph.kt new file mode 100644 index 00000000..a87681b1 --- /dev/null +++ b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologDetailNavGraph.kt @@ -0,0 +1,63 @@ +package com.twix.photolog.detail.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import com.twix.navigation.NavRoutes +import com.twix.navigation.args.DetailNavArgs +import com.twix.navigation.base.NavGraphContributor +import com.twix.photolog.detail.PhotologDetailRoute + +object PhotologDetailNavGraph : NavGraphContributor { + override val graphRoute: NavRoutes + get() = NavRoutes.PhotologGraph + override val startDestination: String + get() = NavRoutes.PhotologDetailRoute.route + + override fun NavGraphBuilder.registerGraph(navController: NavHostController) { + composable( + route = NavRoutes.PhotologDetailRoute.route, + arguments = + listOf( + navArgument(NavRoutes.PhotologDetailRoute.ARG_GOAL_ID) { + type = NavType.LongType + }, + navArgument(NavRoutes.PhotologDetailRoute.ARG_DATE) { + type = NavType.StringType + }, + navArgument(NavRoutes.PhotologDetailRoute.ARG_BETWEEN_US) { + type = NavType.StringType + }, + navArgument(NavRoutes.PhotologDetailRoute.ARG_IS_COMPLETED) { + type = NavType.BoolType + defaultValue = false + }, + ), + ) { + PhotologDetailRoute( + navigateToBack = navController::popBackStack, + navigateToCertification = { goalId, date -> + val destination = + NavRoutes.PhotologRoute.createRoute( + DetailNavArgs( + goalId = goalId, + from = NavRoutes.PhotologRoute.From.DETAIL, + selectedDate = date.toString(), + ), + ) + navController.navigate(destination) + }, + navigateToEditor = { goalId, date -> + navController.navigate( + NavRoutes.PhotologEditorRoute.createRoute( + goalId = goalId, + date = date, + ), + ) + }, + ) + } + } +} diff --git a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt b/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt deleted file mode 100644 index 8a063438..00000000 --- a/feature/photolog/detail/src/main/java/com/twix/photolog/detail/navigation/PhotologGraph.kt +++ /dev/null @@ -1,129 +0,0 @@ -package com.twix.photolog.detail.navigation - -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavHostController -import androidx.navigation.NavType -import androidx.navigation.compose.composable -import androidx.navigation.navArgument -import androidx.navigation.navigation -import com.twix.navigation.NavRoutes -import com.twix.navigation.args.DetailNavArgs -import com.twix.navigation.base.NavGraphContributor -import com.twix.photolog.capture.PhotologCaptureRoute -import com.twix.photolog.detail.PhotologDetailRoute -import com.twix.photolog.editor.PhotologEditorRoute - -object PhotologGraph : NavGraphContributor { - override val graphRoute: NavRoutes - get() = NavRoutes.PhotologGraph - override val startDestination: String - get() = NavRoutes.PhotologDetailRoute.route - - override fun NavGraphBuilder.registerGraph(navController: NavHostController) { - navigation( - route = graphRoute.route, - startDestination = startDestination, - ) { - composable( - route = NavRoutes.PhotologDetailRoute.route, - arguments = - listOf( - navArgument(NavRoutes.PhotologDetailRoute.ARG_GOAL_ID) { - type = NavType.LongType - }, - navArgument(NavRoutes.PhotologDetailRoute.ARG_DATE) { - type = NavType.StringType - }, - navArgument(NavRoutes.PhotologDetailRoute.ARG_BETWEEN_US) { - type = NavType.StringType - }, - navArgument(NavRoutes.PhotologDetailRoute.ARG_IS_COMPLETED) { - type = NavType.BoolType - defaultValue = false - }, - ), - ) { - PhotologDetailRoute( - navigateToBack = navController::popBackStack, - navigateToCertification = { goalId, date -> - val destination = - NavRoutes.PhotologRoute.createRoute( - DetailNavArgs( - goalId = goalId, - from = NavRoutes.PhotologRoute.From.DETAIL, - selectedDate = date.toString(), - ), - ) - navController.navigate(destination) - }, - navigateToEditor = { goalId, date -> - navController.navigate( - NavRoutes.PhotologEditorRoute.createRoute( - goalId = goalId, - date = date, - ), - ) - }, - ) - } - - composable( - route = NavRoutes.PhotologEditorRoute.route, - arguments = - listOf( - navArgument(NavRoutes.PhotologEditorRoute.ARG_GOAL_ID) { - type = NavType.LongType - }, - navArgument(NavRoutes.PhotologEditorRoute.ARG_DATE) { - type = NavType.StringType - }, - ), - ) { - PhotologEditorRoute( - navigateToBack = navController::popBackStack, - navigateToCertification = { goalId, photologId, comment, selectedDate -> - val destination = - NavRoutes.PhotologRoute.createRoute( - DetailNavArgs( - goalId = goalId, - from = NavRoutes.PhotologRoute.From.EDITOR, - photologId = photologId, - selectedDate = selectedDate.toString(), - comment = comment, - ), - ) - navController.navigate(destination) - }, - ) - } - - composable( - route = NavRoutes.PhotologRoute.route, - arguments = - listOf( - navArgument(NavRoutes.PhotologRoute.ARG_DATA) { - type = NavType.StringType - }, - ), - ) { - PhotologCaptureRoute( - navigateToBack = navController::popBackStack, - navigateToDetail = { goalId, date, betweenUs -> - navController.navigate( - NavRoutes.PhotologDetailRoute.createRoute( - goalId = goalId, - date = date, - betweenUs = betweenUs.name, - ), - ) { - popUpTo(NavRoutes.PhotologDetailRoute.route) { - inclusive = true - } - launchSingleTop = true - } - }, - ) - } - } - } -} diff --git a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt index 5d8f24c5..a1b45b6a 100644 --- a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorRoute.kt @@ -38,8 +38,8 @@ import com.twix.designsystem.components.toast.model.ToastType import com.twix.designsystem.extension.showCameraPermissionToastWithNavigateToSettingAction import com.twix.designsystem.theme.CommonColor import com.twix.designsystem.theme.TwixTheme -import com.twix.photolog.editor.component.RetakeButton import com.twix.photolog.editor.component.PhotologEditorTopBar +import com.twix.photolog.editor.component.RetakeButton import com.twix.photolog.editor.contract.PhotologEditorIntent import com.twix.photolog.editor.contract.PhotologEditorSideEffect import com.twix.photolog.editor.contract.PhotologEditorUiState diff --git a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt index 368987b2..b7f0002d 100644 --- a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/PhotologEditorViewModel.kt @@ -6,11 +6,11 @@ import com.twix.designsystem.R import com.twix.designsystem.components.toast.model.ToastType import com.twix.domain.repository.PhotoLogRepository import com.twix.navigation.NavRoutes -import com.twix.result.AppResult import com.twix.photolog.editor.contract.PhotologEditorIntent import com.twix.photolog.editor.contract.PhotologEditorSideEffect import com.twix.photolog.editor.contract.PhotologEditorUiState import com.twix.photolog.editor.contract.toEditorUiState +import com.twix.result.AppResult import com.twix.ui.base.BaseViewModel import com.twix.util.bus.GoalRefreshBus import com.twix.util.bus.PhotologRefreshBus diff --git a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt index 7fccc23a..0d6da520 100644 --- a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/di/PhotologEditorModule.kt @@ -1,10 +1,15 @@ package com.twix.photolog.editor.di +import com.twix.navigation.NavRoutes +import com.twix.navigation.base.NavGraphContributor import com.twix.photolog.editor.PhotologEditorViewModel +import com.twix.photolog.editor.navigation.PhotologEditorNavGraph import org.koin.core.module.dsl.viewModelOf +import org.koin.core.qualifier.named import org.koin.dsl.module val photologEditorModule = module { viewModelOf(::PhotologEditorViewModel) + single(named(NavRoutes.PhotologEditorRoute.route)) { PhotologEditorNavGraph } } diff --git a/feature/photolog/editor/src/main/java/com/twix/photolog/editor/navigation/PhotologEditorNavGraph.kt b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/navigation/PhotologEditorNavGraph.kt new file mode 100644 index 00000000..2233dda2 --- /dev/null +++ b/feature/photolog/editor/src/main/java/com/twix/photolog/editor/navigation/PhotologEditorNavGraph.kt @@ -0,0 +1,50 @@ +package com.twix.photolog.editor.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import com.twix.navigation.NavRoutes +import com.twix.navigation.args.DetailNavArgs +import com.twix.navigation.base.NavGraphContributor +import com.twix.photolog.editor.PhotologEditorRoute + +object PhotologEditorNavGraph : NavGraphContributor { + override val graphRoute: NavRoutes + get() = NavRoutes.PhotologEditorRoute + override val startDestination: String + get() = NavRoutes.PhotologEditorRoute.route + + override fun NavGraphBuilder.registerGraph(navController: NavHostController) { + composable( + route = NavRoutes.PhotologEditorRoute.route, + arguments = + listOf( + navArgument(NavRoutes.PhotologEditorRoute.ARG_GOAL_ID) { + type = NavType.LongType + }, + navArgument(NavRoutes.PhotologEditorRoute.ARG_DATE) { + type = NavType.StringType + }, + ), + ) { + PhotologEditorRoute( + navigateToBack = navController::popBackStack, + navigateToCertification = { goalId, photologId, comment, selectedDate -> + val destination = + NavRoutes.PhotologRoute.createRoute( + DetailNavArgs( + goalId = goalId, + from = NavRoutes.PhotologRoute.From.EDITOR, + photologId = photologId, + selectedDate = selectedDate.toString(), + comment = comment, + ), + ) + navController.navigate(destination) + }, + ) + } + } +}