From 881f124a65de4423a662ea8d0a152d27d52eb298 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 17:27:17 +0900 Subject: [PATCH 01/13] =?UTF-8?q?[REFACTOR/#19]=20Onboarding=20Screen=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kms/onboarding/OnBoardingScreen.kt | 122 ------------------ .../OnboardingAlarmTimeSelectionScreen.kt | 57 ++++++++ .../kms/onboarding/OnboardingExplainScreen.kt | 54 ++++++++ .../navigation/OnboardingNavGraph.kt | 8 +- 4 files changed, 115 insertions(+), 126 deletions(-) create mode 100644 feature/onboarding/src/main/java/com/kms/onboarding/OnboardingAlarmTimeSelectionScreen.kt create mode 100644 feature/onboarding/src/main/java/com/kms/onboarding/OnboardingExplainScreen.kt diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt index 32c5511..20e87c6 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt @@ -1,22 +1,14 @@ package com.kms.onboarding import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.compose.NavHost @@ -25,9 +17,6 @@ import com.kms.onboarding.component.OnboardingBottomBar import com.kms.onboarding.navigation.onboardingNavGraph import com.kms.onboarding.navigation.rememberOnboardingAppState import com.yapp.designsystem.theme.OrbitTheme -import com.yapp.ui.component.timepicker.OrbitPicker -import com.yapp.ui.utils.heightForScreenPercentage -import feature.onboarding.R @Composable fun OnboardingRoute( @@ -105,114 +94,3 @@ fun OnboardingScreen( } } } - -@Composable -fun ExplainScreen( - state: OnboardingContract.State, - onNextClick: () -> Unit, -) { - OnboardingScreen( - currentStep = 0, - totalSteps = 0, - isButtonEnabled = true, - onNextClick = onNextClick, - onBackClick = null, - showTopAppBar = false, - ) { - Column(modifier = Modifier.fillMaxSize()) { - Spacer(modifier = Modifier.heightForScreenPercentage(0.105f)) - Text( - text = stringResource(id = R.string.onboarding_step1_text_title), - style = OrbitTheme.typography.body1Regular, - color = OrbitTheme.colors.gray_100, - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center, - ) - Text( - text = stringResource(id = R.string.onboarding_step1_text_subtitle), - style = OrbitTheme.typography.heading1SemiBold, - color = OrbitTheme.colors.white, - modifier = Modifier - .padding(horizontal = 20.dp) - .padding(top = 12.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center, - ) - } - } -} - -@Composable -fun AlarmTimeSelectionScreen( - state: OnboardingContract.State, - currentStep: Int, - totalSteps: Int, - onNextClick: () -> Unit, - onBackClick: () -> Unit, -) { - OnboardingScreen( - currentStep = currentStep, - totalSteps = totalSteps, - isButtonEnabled = true, - onNextClick = onNextClick, - onBackClick = onBackClick, - ) { - Column(modifier = Modifier.fillMaxSize()) { - Spacer(modifier = Modifier.heightForScreenPercentage(0.05f)) - Text( - text = stringResource(id = R.string.onboarding_step2_text_title), - style = OrbitTheme.typography.heading1SemiBold, - color = OrbitTheme.colors.white, - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - ) - Text( - text = stringResource(id = R.string.onboarding_step2_text_subtitle), - style = OrbitTheme.typography.body1Regular, - color = OrbitTheme.colors.gray_100, - modifier = Modifier - .padding(top = 4.dp) - .fillMaxWidth(), - textAlign = TextAlign.Center, - ) - OrbitPicker( - modifier = Modifier.padding(top = 90.dp), - ) - } - } -} - -@Composable -fun BirthdayScreen( - state: OnboardingContract.State, - currentStep: Int, - totalSteps: Int, - onNextClick: () -> Unit, - onBackClick: () -> Unit, -) { - OnboardingScreen( - currentStep = currentStep, - totalSteps = totalSteps, - isButtonEnabled = true, - onNextClick = onNextClick, - onBackClick = onBackClick, - ) { - Column { } - } -} - -@Composable -@Preview -fun OnboardingPreview() { - OrbitTheme { - AlarmTimeSelectionScreen( - state = OnboardingContract.State(), - currentStep = 1, - totalSteps = 2, - onNextClick = {}, - onBackClick = {}, - ) - } -} diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingAlarmTimeSelectionScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingAlarmTimeSelectionScreen.kt new file mode 100644 index 0000000..6a2aeab --- /dev/null +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingAlarmTimeSelectionScreen.kt @@ -0,0 +1,57 @@ +package com.kms.onboarding + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.yapp.designsystem.theme.OrbitTheme +import com.yapp.ui.component.timepicker.OrbitPicker +import com.yapp.ui.utils.heightForScreenPercentage +import feature.onboarding.R + +@Composable +fun OnboardingAlarmTimeSelectionScreen( + state: OnboardingContract.State, + currentStep: Int, + totalSteps: Int, + onNextClick: () -> Unit, + onBackClick: () -> Unit, +) { + OnboardingScreen( + currentStep = currentStep, + totalSteps = totalSteps, + isButtonEnabled = true, + onNextClick = onNextClick, + onBackClick = onBackClick, + ) { + Column(modifier = Modifier.fillMaxSize()) { + Spacer(modifier = Modifier.heightForScreenPercentage(0.05f)) + Text( + text = stringResource(id = R.string.onboarding_step2_text_title), + style = OrbitTheme.typography.heading1SemiBold, + color = OrbitTheme.colors.white, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + ) + Text( + text = stringResource(id = R.string.onboarding_step2_text_subtitle), + style = OrbitTheme.typography.body1Regular, + color = OrbitTheme.colors.gray_100, + modifier = Modifier + .padding(top = 4.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center, + ) + OrbitPicker( + modifier = Modifier.padding(top = 90.dp), + ) + } + } +} diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingExplainScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingExplainScreen.kt new file mode 100644 index 0000000..d3d737c --- /dev/null +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingExplainScreen.kt @@ -0,0 +1,54 @@ +package com.kms.onboarding + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.yapp.designsystem.theme.OrbitTheme +import com.yapp.ui.utils.heightForScreenPercentage +import feature.onboarding.R + +@Composable +fun OnboardingExplainScreen( + state: OnboardingContract.State, + onNextClick: () -> Unit, +) { + OnboardingScreen( + currentStep = 0, + totalSteps = 0, + isButtonEnabled = true, + onNextClick = onNextClick, + onBackClick = null, + showTopAppBar = false, + ) { + Column(modifier = Modifier.fillMaxSize()) { + Spacer(modifier = Modifier.heightForScreenPercentage(0.105f)) + Text( + text = stringResource(id = R.string.onboarding_step1_text_title), + style = OrbitTheme.typography.body1Regular, + color = OrbitTheme.colors.gray_100, + modifier = Modifier + .padding(horizontal = 20.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center, + ) + Text( + text = stringResource(id = R.string.onboarding_step1_text_subtitle), + style = OrbitTheme.typography.heading1SemiBold, + color = OrbitTheme.colors.white, + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 12.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center, + ) + } + } +} diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt index 54dc47f..d1e80b2 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt @@ -2,10 +2,10 @@ package com.kms.onboarding.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable -import com.kms.onboarding.AlarmTimeSelectionScreen import com.kms.onboarding.BirthdayScreen -import com.kms.onboarding.ExplainScreen +import com.kms.onboarding.OnboardingAlarmTimeSelectionScreen import com.kms.onboarding.OnboardingContract +import com.kms.onboarding.OnboardingExplainScreen fun NavGraphBuilder.onboardingNavGraph( stateProvider: () -> OnboardingContract.State, @@ -13,7 +13,7 @@ fun NavGraphBuilder.onboardingNavGraph( onFinishOnboarding: () -> Unit, ) { composable(OnboardingDestination.Explain.route) { - ExplainScreen( + OnboardingExplainScreen( state = stateProvider(), onNextClick = { eventDispatcher(OnboardingContract.Action.NextStep) @@ -22,7 +22,7 @@ fun NavGraphBuilder.onboardingNavGraph( } composable(OnboardingDestination.AlarmTimeSelection.route) { - AlarmTimeSelectionScreen( + OnboardingAlarmTimeSelectionScreen( state = stateProvider(), currentStep = 1, totalSteps = 2, From f75e295ddfd8ff985e8c82d08582e58570ce0ceb Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 17:27:44 +0900 Subject: [PATCH 02/13] =?UTF-8?q?[UI/#19]=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=83=9D=EB=85=84=EC=9B=94=EC=9D=BC=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kms/onboarding/BirthdayScreen.kt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 feature/onboarding/src/main/java/com/kms/onboarding/BirthdayScreen.kt diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/BirthdayScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/BirthdayScreen.kt new file mode 100644 index 0000000..4e827fb --- /dev/null +++ b/feature/onboarding/src/main/java/com/kms/onboarding/BirthdayScreen.kt @@ -0,0 +1,48 @@ +package com.kms.onboarding + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.yapp.designsystem.theme.OrbitTheme +import com.yapp.ui.component.timepicker.OrbitYearMonthPicker +import com.yapp.ui.utils.heightForScreenPercentage +import feature.onboarding.R + +@Composable +fun BirthdayScreen( + state: OnboardingContract.State, + currentStep: Int, + totalSteps: Int, + onNextClick: () -> Unit, + onBackClick: () -> Unit, +) { + OnboardingScreen( + currentStep = currentStep, + totalSteps = totalSteps, + isButtonEnabled = true, + onNextClick = onNextClick, + onBackClick = onBackClick, + ) { + Column(modifier = Modifier.fillMaxSize()) { + Spacer(modifier = Modifier.heightForScreenPercentage(0.05f)) + Text( + text = stringResource(id = R.string.onboarding_step3_text_title), + style = OrbitTheme.typography.heading1SemiBold, + color = OrbitTheme.colors.white, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + ) + OrbitYearMonthPicker( + modifier = Modifier.padding(top = 60.dp), + ) + } + } +} From a9d4c7510ff582016a01b5bee8fdcf532f72c900 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 21:42:58 +0900 Subject: [PATCH 03/13] =?UTF-8?q?[REFACTOR/#23]=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EB=B3=80=EA=B2=BD=20=EB=B0=98=EC=98=81=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B2=BD=EA=B3=A0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=8F=99?= =?UTF-8?q?=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/component/textfield/OrbitTextField.kt | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/core/ui/src/main/java/com/yapp/ui/component/textfield/OrbitTextField.kt b/core/ui/src/main/java/com/yapp/ui/component/textfield/OrbitTextField.kt index 06b6158..83ac88c 100644 --- a/core/ui/src/main/java/com/yapp/ui/component/textfield/OrbitTextField.kt +++ b/core/ui/src/main/java/com/yapp/ui/component/textfield/OrbitTextField.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource @@ -46,6 +45,7 @@ fun OrbitTextField( hint: String, modifier: Modifier = Modifier, showWarning: Boolean = false, + warningMessage: String, onFocusChanged: (Boolean) -> Unit = {}, ) { val focusRequester = remember { FocusRequester() } @@ -83,7 +83,7 @@ fun OrbitTextField( Spacer(modifier = Modifier.height(12.dp)) if (showWarning) { - WarningMessage() + WarningMessage(warningMessage) } } } @@ -91,7 +91,7 @@ fun OrbitTextField( } @Composable -private fun WarningMessage() { +private fun WarningMessage(message: String) { Box( modifier = Modifier .fillMaxWidth() @@ -99,7 +99,7 @@ private fun WarningMessage() { contentAlignment = Alignment.Center, ) { Text( - text = "입력한 숫자를 확인해 주세요", + text = message, color = OrbitTheme.colors.alert, style = OrbitTheme.typography.label1SemiBold, ) @@ -121,17 +121,17 @@ private fun TextFieldContainer( Box( modifier = Modifier .border( - width = 3.dp, + width = 1.dp, color = when { isFocused && showWarning -> OrbitTheme.colors.alert isFocused -> OrbitTheme.colors.main.copy(alpha = 0.2f) showWarning -> OrbitTheme.colors.alert - else -> Color.Transparent + else -> OrbitTheme.colors.gray_500 }, - shape = RoundedCornerShape(10.dp), + shape = RoundedCornerShape(16.dp), ) - .background(OrbitTheme.colors.gray_800, shape = RoundedCornerShape(10.dp)) - .height(52.dp) + .background(OrbitTheme.colors.gray_800, shape = RoundedCornerShape(16.dp)) + .height(54.dp) .fillMaxWidth() .focusRequester(focusRequester) .clickable( @@ -197,10 +197,11 @@ private fun TextFieldContainer( fun OrbitTextFieldPreview() { OrbitTheme { OrbitTextField( - text = "123", + text = "", onTextChange = {}, - showWarning = true, + showWarning = false, hint = "이름을 입력해주세요", + warningMessage = "이름을 입력해주세요", modifier = Modifier .fillMaxWidth(), ) From 3f520633a876f7db47a742dcca070ceef8558eb2 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 21:43:56 +0900 Subject: [PATCH 04/13] =?UTF-8?q?[FEAT/#23]=20=ED=83=9C=EC=96=B4=EB=82=9C?= =?UTF-8?q?=20=EC=8B=9C=EA=B0=84,=20=EC=9D=B4=EB=A6=84=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20Navigation=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../navigation/OnboardingDestination.kt | 4 +- .../navigation/OnboardingNavGraph.kt | 40 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingDestination.kt b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingDestination.kt index 80a9cb1..d33f5f9 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingDestination.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingDestination.kt @@ -4,9 +4,11 @@ sealed class OnboardingDestination(val route: String) { data object Explain : OnboardingDestination(Routes.EXPLAIN) data object AlarmTimeSelection : OnboardingDestination(Routes.ALARM_TIME_SELECTION) data object Birthday : OnboardingDestination(Routes.BIRTHDAY) + data object TimeOfBirth : OnboardingDestination(Routes.TIME_OF_BIRTH) + data object Name : OnboardingDestination(Routes.NAME) companion object { - private val routes = listOf(Explain, AlarmTimeSelection, Birthday) + private val routes = listOf(Explain, AlarmTimeSelection, Birthday, TimeOfBirth, Name) fun nextRoute(currentStep: Int): String? { return routes.getOrNull(currentStep)?.route diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt index d1e80b2..8bbb4ec 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt @@ -6,6 +6,8 @@ import com.kms.onboarding.BirthdayScreen import com.kms.onboarding.OnboardingAlarmTimeSelectionScreen import com.kms.onboarding.OnboardingContract import com.kms.onboarding.OnboardingExplainScreen +import com.kms.onboarding.OnboardingNameScreen +import com.kms.onboarding.OnboardingTimeOfBirthScreen fun NavGraphBuilder.onboardingNavGraph( stateProvider: () -> OnboardingContract.State, @@ -25,7 +27,7 @@ fun NavGraphBuilder.onboardingNavGraph( OnboardingAlarmTimeSelectionScreen( state = stateProvider(), currentStep = 1, - totalSteps = 2, + totalSteps = 4, onNextClick = { eventDispatcher(OnboardingContract.Action.NextStep) }, @@ -39,7 +41,7 @@ fun NavGraphBuilder.onboardingNavGraph( BirthdayScreen( state = stateProvider(), currentStep = 2, - totalSteps = 2, + totalSteps = 4, onNextClick = { eventDispatcher(OnboardingContract.Action.NextStep) }, @@ -48,4 +50,38 @@ fun NavGraphBuilder.onboardingNavGraph( }, ) } + + composable(OnboardingDestination.TimeOfBirth.route) { + OnboardingTimeOfBirthScreen( + state = stateProvider(), + currentStep = 3, + totalSteps = 4, + onNextClick = { + eventDispatcher(OnboardingContract.Action.NextStep) + eventDispatcher(OnboardingContract.Action.Reset) + }, + onBackClick = { + eventDispatcher(OnboardingContract.Action.PreviousStep) + }, + onTextChange = { value -> + eventDispatcher(OnboardingContract.Action.UpdateField(value, OnboardingContract.FieldType.TIME)) + }, + ) + } + composable(OnboardingDestination.Name.route) { + OnboardingNameScreen( + state = stateProvider(), + currentStep = 4, + totalSteps = 4, + onNextClick = { + eventDispatcher(OnboardingContract.Action.NextStep) + }, + onBackClick = { + eventDispatcher(OnboardingContract.Action.PreviousStep) + }, + onTextChange = { value -> + eventDispatcher(OnboardingContract.Action.UpdateField(value, OnboardingContract.FieldType.NAME)) + }, + ) + } } From b6573f462c7afa6805376c5b4856a467d701937b Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 21:44:34 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[ADD/#23]=20reset=20func=20Delay=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/kms/onboarding/OnboardingViewModel.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingViewModel.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingViewModel.kt index 8189610..27fd8e2 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingViewModel.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingViewModel.kt @@ -1,9 +1,12 @@ package com.kms.onboarding import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope import com.kms.onboarding.navigation.OnboardingDestination import com.yapp.ui.base.BaseViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -60,7 +63,10 @@ class OnboardingViewModel @Inject constructor( } private fun resetFields() { - updateState { copy(textFieldValue = "", showWarning = false, isButtonEnabled = false) } + viewModelScope.launch { + delay(150) + updateState { copy(textFieldValue = "", showWarning = false, isButtonEnabled = false) } + } } private fun handleSubmission(stepData: Map) { From 69058d576f7494142ff03738887f4479b9a864a6 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 21:44:58 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[UI/#23]=20=ED=83=9C=EC=96=B4=EB=82=9C=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onboarding/OnboardingTimeOfBirthScreen.kt | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt new file mode 100644 index 0000000..f7843cc --- /dev/null +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt @@ -0,0 +1,146 @@ +package com.kms.onboarding + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.pointer.pointerInteropFilter +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.yapp.designsystem.theme.OrbitTheme +import com.yapp.ui.component.textfield.OrbitTextField +import com.yapp.ui.extensions.customClickable +import com.yapp.ui.utils.heightForScreenPercentage +import com.yapp.ui.utils.paddingForScreenPercentage +import feature.onboarding.R + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun OnboardingTimeOfBirthScreen( + state: OnboardingContract.State, + currentStep: Int, + totalSteps: Int, + onNextClick: () -> Unit, + onBackClick: () -> Unit, + onTextChange: (String) -> Unit, +) { + val focusManager = LocalFocusManager.current + var isTextPressed by remember { mutableStateOf(false) } + + OnboardingScreen( + currentStep = currentStep, + totalSteps = totalSteps, + isButtonEnabled = state.isButtonEnabled, + onNextClick = onNextClick, + onBackClick = onBackClick, + ) { + Column( + modifier = Modifier + .fillMaxSize() + .customClickable( + rippleEnabled = false, + onClick = { focusManager.clearFocus() }, + ), + verticalArrangement = Arrangement.SpaceBetween, + ) { + Column( + modifier = Modifier.fillMaxWidth(), + ) { + Spacer(modifier = Modifier.heightForScreenPercentage(0.05f)) + Text( + text = stringResource(id = R.string.onboarding_step4_text_title), + style = OrbitTheme.typography.heading1SemiBold, + color = OrbitTheme.colors.white, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + ) + OrbitTextField( + text = state.textFieldValue, + onTextChange = { value -> + onTextChange(value) + }, + hint = "23:59", + showWarning = state.showWarning, + warningMessage = stringResource(id = R.string.onboarding_step4_textfield_warning), + modifier = Modifier + .fillMaxWidth() + .paddingForScreenPercentage(horizontalPercentage = 0.192f, verticalPercentage = 0.086f), + ) + } + + Row( + modifier = Modifier + .wrapContentWidth() + .paddingForScreenPercentage(verticalPercentage = 0.017f) + .align(Alignment.CenterHorizontally) + .pointerInteropFilter { event -> + when (event.action) { + android.view.MotionEvent.ACTION_DOWN -> { + isTextPressed = true + true + } + + android.view.MotionEvent.ACTION_UP, + android.view.MotionEvent.ACTION_CANCEL, + -> { + isTextPressed = false + true + } + + else -> false + } + }, + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + painter = painterResource(id = core.designsystem.R.drawable.ic_check), + contentDescription = "Check", + tint = if (isTextPressed) OrbitTheme.colors.main else OrbitTheme.colors.white, + ) + Text( + text = stringResource(id = R.string.onboarding_step4_text_check), + style = OrbitTheme.typography.body1Medium, + color = if (isTextPressed) OrbitTheme.colors.main else OrbitTheme.colors.white, + modifier = Modifier.padding(start = 4.dp), + textAlign = TextAlign.Center, + ) + } + } + } +} + +@Composable +@Preview +fun OnboardingTimeOfBirthScreenPreview() { + OnboardingTimeOfBirthScreen( + state = OnboardingContract.State( + textFieldValue = "23:59", + showWarning = false, + isButtonEnabled = true, + ), + currentStep = 4, + totalSteps = 4, + onNextClick = {}, + onBackClick = {}, + onTextChange = {}, + ) +} From 09bc9c9113accf5444af170d8659d9fe6d2812bd Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 21:45:15 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[UI/#23]=20=EC=9D=B4=EB=A6=84=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kms/onboarding/OnboardingNameScreen.kt | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt new file mode 100644 index 0000000..92ed7f1 --- /dev/null +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt @@ -0,0 +1,86 @@ +package com.kms.onboarding + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import com.yapp.designsystem.theme.OrbitTheme +import com.yapp.ui.component.textfield.OrbitTextField +import com.yapp.ui.extensions.customClickable +import com.yapp.ui.utils.heightForScreenPercentage +import com.yapp.ui.utils.paddingForScreenPercentage +import feature.onboarding.R + +@Composable +fun OnboardingNameScreen( + state: OnboardingContract.State, + currentStep: Int, + totalSteps: Int, + onNextClick: () -> Unit, + onBackClick: () -> Unit, + onTextChange: (String) -> Unit, +) { + val focusManager = LocalFocusManager.current + + OnboardingScreen( + currentStep = currentStep, + totalSteps = totalSteps, + isButtonEnabled = state.isButtonEnabled, + onNextClick = onNextClick, + onBackClick = onBackClick, + ) { + Column( + modifier = Modifier + .fillMaxSize() + .customClickable( + rippleEnabled = false, + onClick = { focusManager.clearFocus() }, + ), + ) { + Spacer(modifier = Modifier.heightForScreenPercentage(0.05f)) + Text( + text = stringResource(id = R.string.onboarding_step5_text_title), + style = OrbitTheme.typography.heading1SemiBold, + color = OrbitTheme.colors.white, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + ) + OrbitTextField( + text = state.textFieldValue, + onTextChange = { value -> + onTextChange(value) + }, + hint = "이름 입력", + showWarning = state.showWarning, + warningMessage = stringResource(id = R.string.onboarding_step5_textfield_warning), + modifier = Modifier + .fillMaxWidth() + .paddingForScreenPercentage(horizontalPercentage = 0.192f, verticalPercentage = 0.086f), + ) + } + } +} + +@Composable +@Preview +fun PreviewOnboardingNameScreen() { + OnboardingNameScreen( + state = OnboardingContract.State( + textFieldValue = "김민수", + isButtonEnabled = true, + showWarning = false, + ), + currentStep = 1, + totalSteps = 5, + onNextClick = {}, + onBackClick = {}, + onTextChange = {}, + ) +} From c6a21baa4266461eb3d16d887adc6a5e6e09e341 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sat, 11 Jan 2025 21:43:56 +0900 Subject: [PATCH 08/13] =?UTF-8?q?[FEAT/#23]=20=ED=83=9C=EC=96=B4=EB=82=9C?= =?UTF-8?q?=20=EC=8B=9C=EA=B0=84,=20=EC=9D=B4=EB=A6=84=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20Navigation=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kms/onboarding/navigation/OnboardingNavGraph.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt index bc089b8..9e6d9c8 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt @@ -12,6 +12,8 @@ import com.kms.onboarding.OnboardingAlarmTimeSelectionScreen import com.kms.onboarding.OnboardingBirthdayScreen import com.kms.onboarding.OnboardingContract import com.kms.onboarding.OnboardingExplainScreen +import com.kms.onboarding.OnboardingNameScreen +import com.kms.onboarding.OnboardingTimeOfBirthScreen fun NavGraphBuilder.onboardingNavGraph( stateProvider: () -> OnboardingContract.State, From b52bb73233d12a158c665ae2725c73a5f838a549 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sun, 12 Jan 2025 15:54:39 +0900 Subject: [PATCH 09/13] =?UTF-8?q?[FIX/#23]=20Conflict=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kms/onboarding/navigation/OnboardingNavGraph.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt index 9e6d9c8..11d7396 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt @@ -2,12 +2,6 @@ package com.kms.onboarding.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable -import com.kms.onboarding.BirthdayScreen -import com.kms.onboarding.OnboardingAlarmTimeSelectionScreen -import com.kms.onboarding.OnboardingContract -import com.kms.onboarding.OnboardingExplainScreen -import com.kms.onboarding.OnboardingNameScreen -import com.kms.onboarding.OnboardingTimeOfBirthScreen import com.kms.onboarding.OnboardingAlarmTimeSelectionScreen import com.kms.onboarding.OnboardingBirthdayScreen import com.kms.onboarding.OnboardingContract From 6bdc2989ebb1116318c7a8e654e767c7e8e10dad Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sun, 12 Jan 2025 17:18:39 +0900 Subject: [PATCH 10/13] =?UTF-8?q?[REFACTOR/#23]=20top,=20bottom=20percenta?= =?UTF-8?q?ge=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yapp/ui/utils/ScreenPercentage.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/ui/src/main/java/com/yapp/ui/utils/ScreenPercentage.kt b/core/ui/src/main/java/com/yapp/ui/utils/ScreenPercentage.kt index 6056a83..6956e81 100644 --- a/core/ui/src/main/java/com/yapp/ui/utils/ScreenPercentage.kt +++ b/core/ui/src/main/java/com/yapp/ui/utils/ScreenPercentage.kt @@ -21,13 +21,25 @@ fun Modifier.widthForScreenPercentage(percentage: Float): Modifier { } @Composable -fun Modifier.paddingForScreenPercentage(horizontalPercentage: Float = 0f, verticalPercentage: Float = 0f): Modifier { +fun Modifier.paddingForScreenPercentage( + horizontalPercentage: Float = 0f, + verticalPercentage: Float = 0f, + topPercentage: Float = 0f, + bottomPercentage: Float = 0f, +): Modifier { val configuration = LocalConfiguration.current val screenWidth = configuration.screenWidthDp.dp val screenHeight = configuration.screenHeightDp.dp val horizontalPadding = screenWidth * horizontalPercentage val verticalPadding = screenHeight * verticalPercentage + val topPadding = screenHeight * topPercentage + verticalPadding + val bottomPadding = screenHeight * bottomPercentage + verticalPadding - return this.padding(horizontal = horizontalPadding, vertical = verticalPadding) + return this.padding( + start = horizontalPadding, + top = topPadding, + end = horizontalPadding, + bottom = bottomPadding, + ) } From a4ac81e85e592b88dafc13385b1a522deb50cede Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sun, 12 Jan 2025 17:19:44 +0900 Subject: [PATCH 11/13] =?UTF-8?q?[REFACTOR/#23]=20keyboard=20hide=20option?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kms/onboarding/navigation/OnboardingNavGraph.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt index 11d7396..f685a2a 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/navigation/OnboardingNavGraph.kt @@ -1,5 +1,6 @@ package com.kms.onboarding.navigation +import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import com.kms.onboarding.OnboardingAlarmTimeSelectionScreen @@ -52,6 +53,7 @@ fun NavGraphBuilder.onboardingNavGraph( } composable(OnboardingDestination.TimeOfBirth.route) { + val keyboardContract = LocalSoftwareKeyboardController.current OnboardingTimeOfBirthScreen( state = stateProvider(), currentStep = 3, @@ -59,6 +61,7 @@ fun NavGraphBuilder.onboardingNavGraph( onNextClick = { eventDispatcher(OnboardingContract.Action.NextStep) eventDispatcher(OnboardingContract.Action.Reset) + keyboardContract?.hide() }, onBackClick = { eventDispatcher(OnboardingContract.Action.PreviousStep) From 6302f16107708bf3ad2c4d13469c9971ab6e552e Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sun, 12 Jan 2025 17:20:14 +0900 Subject: [PATCH 12/13] =?UTF-8?q?[REFACTOR/#23]=20vertical=20=ED=8C=A8?= =?UTF-8?q?=EB=94=A9=20=EC=A0=9C=EA=B1=B0=20=ED=9B=84=20top,=20bottom=20pa?= =?UTF-8?q?dding=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/kms/onboarding/OnboardingNameScreen.kt | 2 +- .../java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt index 92ed7f1..290309e 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingNameScreen.kt @@ -62,7 +62,7 @@ fun OnboardingNameScreen( warningMessage = stringResource(id = R.string.onboarding_step5_textfield_warning), modifier = Modifier .fillMaxWidth() - .paddingForScreenPercentage(horizontalPercentage = 0.192f, verticalPercentage = 0.086f), + .paddingForScreenPercentage(horizontalPercentage = 0.192f, topPercentage = 0.086f), ) } } diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt index f7843cc..6eb78d7 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnboardingTimeOfBirthScreen.kt @@ -82,14 +82,14 @@ fun OnboardingTimeOfBirthScreen( warningMessage = stringResource(id = R.string.onboarding_step4_textfield_warning), modifier = Modifier .fillMaxWidth() - .paddingForScreenPercentage(horizontalPercentage = 0.192f, verticalPercentage = 0.086f), + .paddingForScreenPercentage(horizontalPercentage = 0.192f, topPercentage = 0.086f), ) } Row( modifier = Modifier .wrapContentWidth() - .paddingForScreenPercentage(verticalPercentage = 0.017f) + .paddingForScreenPercentage(bottomPercentage = 0.017f) .align(Alignment.CenterHorizontally) .pointerInteropFilter { event -> when (event.action) { From 06d284e5215c8f53bc39a8c196e7768fe06b2cf9 Mon Sep 17 00:00:00 2001 From: Moonsu Kang Date: Sun, 12 Jan 2025 17:44:03 +0900 Subject: [PATCH 13/13] =?UTF-8?q?[REFACTOR/#23]=20Scaffold=20->=20Column(?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kms/onboarding/OnBoardingScreen.kt | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt b/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt index 20e87c6..80038d6 100644 --- a/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt +++ b/feature/onboarding/src/main/java/com/kms/onboarding/OnBoardingScreen.kt @@ -1,13 +1,15 @@ package com.kms.onboarding +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -66,31 +68,31 @@ fun OnboardingScreen( showTopAppBar: Boolean = true, content: @Composable () -> Unit, ) { - Scaffold( - topBar = { - if (showTopAppBar) { - OnBoardingTopAppBar( - currentStep = currentStep, - totalSteps = totalSteps, - onBackClick = onBackClick, - ) - } - }, - bottomBar = { - OnboardingBottomBar( - isButtonEnabled = isButtonEnabled, - onNextClick = onNextClick, + Column( + modifier = Modifier + .fillMaxSize() + .background(OrbitTheme.colors.gray_900) + .statusBarsPadding() + .navigationBarsPadding() + .imePadding(), + ) { + if (showTopAppBar) { + OnBoardingTopAppBar( + currentStep = currentStep, + totalSteps = totalSteps, + onBackClick = onBackClick, ) - }, - containerColor = OrbitTheme.colors.gray_900, - ) { innerPadding -> + } + Box( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), - contentAlignment = Alignment.TopCenter, + modifier = Modifier.weight(1f), ) { content() } + + OnboardingBottomBar( + isButtonEnabled = isButtonEnabled, + onNextClick = onNextClick, + ) } }