@@ -2,26 +2,15 @@ package com.puzzle.onboarding
22
33import android.app.Activity
44import androidx.activity.compose.BackHandler
5- import androidx.compose.animation.AnimatedVisibility
6- import androidx.compose.animation.fadeIn
7- import androidx.compose.animation.fadeOut
8- import androidx.compose.foundation.Image
95import androidx.compose.foundation.background
10- import androidx.compose.foundation.clickable
116import androidx.compose.foundation.layout.Arrangement
127import androidx.compose.foundation.layout.Column
138import androidx.compose.foundation.layout.Row
14- import androidx.compose.foundation.layout.Spacer
159import androidx.compose.foundation.layout.fillMaxSize
1610import androidx.compose.foundation.layout.fillMaxWidth
17- import androidx.compose.foundation.layout.height
1811import androidx.compose.foundation.layout.padding
19- import androidx.compose.foundation.layout.size
2012import androidx.compose.foundation.pager.HorizontalPager
2113import androidx.compose.foundation.pager.rememberPagerState
22- import androidx.compose.foundation.shape.CircleShape
23- import androidx.compose.material3.Surface
24- import androidx.compose.material3.Text
2514import androidx.compose.runtime.Composable
2615import androidx.compose.runtime.getValue
2716import androidx.compose.runtime.mutableLongStateOf
@@ -30,22 +19,22 @@ import androidx.compose.runtime.rememberCoroutineScope
3019import androidx.compose.runtime.setValue
3120import androidx.compose.ui.Alignment
3221import androidx.compose.ui.Modifier
33- import androidx.compose.ui.draw.clip
3422import androidx.compose.ui.platform.LocalContext
35- import androidx.compose.ui.res.painterResource
3623import androidx.compose.ui.res.stringResource
37- import androidx.compose.ui.text.style.TextAlign
38- import androidx.compose.ui.text.style.TextDecoration
39- import androidx.compose.ui.tooling.preview.Preview
4024import androidx.compose.ui.unit.dp
4125import androidx.hilt.navigation.compose.hiltViewModel
4226import com.puzzle.analytics.TrackScreenViewEvent
4327import com.puzzle.common.event.PieceEvent
4428import com.puzzle.common.ui.SnackBarState
4529import com.puzzle.designsystem.R
30+ import com.puzzle.designsystem.component.PieceOutlinedButton
4631import com.puzzle.designsystem.component.PieceSolidButton
32+ import com.puzzle.designsystem.component.PieceSubCloseTopBar
4733import com.puzzle.designsystem.foundation.PieceTheme
4834import com.puzzle.onboarding.contract.OnboardingIntent
35+ import com.puzzle.onboarding.model.OnboardingPageData
36+ import com.puzzle.onboarding.model.onboardingPages
37+ import com.puzzle.onboarding.ui.PageContent
4938import kotlinx.coroutines.launch
5039
5140@Composable
@@ -59,7 +48,7 @@ internal fun OnboardingRoute(viewModel: OnboardingViewModel = hiltViewModel()) {
5948 } else {
6049 viewModel.eventHelper.sendEvent(
6150 PieceEvent .ShowSnackBar (
62- SnackBarState .TextOnly (context.getString(com.puzzle.designsystem. R .string.back_description))
51+ SnackBarState .TextOnly (context.getString(R .string.back_description))
6352 )
6453 )
6554 }
@@ -70,211 +59,104 @@ internal fun OnboardingRoute(viewModel: OnboardingViewModel = hiltViewModel()) {
7059}
7160
7261@Composable
73- internal fun OnboardingScreen (onStartButtonClick : () -> Unit ) {
62+ private fun OnboardingScreen (onStartButtonClick : () -> Unit ) {
7463 val scope = rememberCoroutineScope()
64+ val pageCount = onboardingPages.size
65+
7566 val pagerState = rememberPagerState(
7667 initialPage = 0 ,
77- pageCount = { 2 },
68+ pageCount = { pageCount },
7869 )
70+ val currentPage = pagerState.currentPage
71+ val currentPageData = onboardingPages.getOrNull(currentPage)
7972
80- TrackScreenViewEvent (
81- key = pagerState.currentPage,
82- screenName = when (pagerState.currentPage) {
83- 0 -> " onboarding_dailymatch"
84- 1 -> " onboarding_safetynotice"
85- else -> null
86- }
87- )
73+ currentPageData?.screenName?.let { screenName ->
74+ TrackScreenViewEvent (
75+ key = currentPage,
76+ screenName = screenName
77+ )
78+ }
8879
8980 Column (
9081 horizontalAlignment = Alignment .CenterHorizontally ,
9182 modifier = Modifier
9283 .fillMaxSize()
93- .padding(horizontal = 20 .dp )
84+ .background( PieceTheme .colors.light3 )
9485 ) {
95- OnboardingTopBar (
96- currentPage = pagerState.currentPage,
97- onSkipButtonClick = onStartButtonClick,
98- modifier = Modifier .padding(bottom = 49 .dp),
86+
87+ PieceSubCloseTopBar (
88+ title = " " ,
89+ contentColor = PieceTheme .colors.black,
90+ onCloseClick = onStartButtonClick,
91+ modifier = Modifier .padding(horizontal = 20 .dp)
9992 )
10093
10194 HorizontalPager (
10295 state = pagerState,
103- modifier = Modifier
104- .weight(1f )
105- .padding(bottom = 40 .dp)
106- ) { page ->
107- Column (modifier = Modifier .fillMaxSize()) {
108- when (page) {
109- 0 -> OnboardingPageContent (
110- imageRes = R .drawable.ic_onboarding_matching,
111- title = stringResource(R .string.one_day_one_matching_title),
112- description = stringResource(R .string.one_day_one_matching_description),
113- )
96+ userScrollEnabled = false ,
97+ modifier = Modifier .weight(1f )
98+ ) { pageIndex ->
99+
100+ val isCurrentPage = pageIndex == currentPage
114101
115- 1 -> OnboardingPageContent (
116- imageRes = R .drawable.ic_onboarding_camera,
117- title = stringResource( R .string.camera_block_title) ,
118- description = stringResource( R .string.camera_block_description) ,
119- )
120- }
102+ onboardingPages.getOrNull(pageIndex)?. let { data ->
103+ PageContent (
104+ titleRes = data.titleRes ,
105+ pageContentType = data.contentType ,
106+ isPageActive = isCurrentPage
107+ )
121108 }
122109 }
123110
124- OnboardingIndicator (
125- total = 2 ,
126- current = pagerState.currentPage,
127- modifier = Modifier
128- .align(Alignment .CenterHorizontally )
129- .padding(bottom = 30 .dp),
130- )
131-
132- PieceSolidButton (
133- label = when (pagerState.currentPage) {
134- 1 -> stringResource(R .string.start)
135- else -> stringResource(R .string.next)
136- },
137- onClick = {
138- when (pagerState.currentPage) {
139- 1 -> onStartButtonClick()
140- else -> scope.launch { pagerState.animateScrollToPage(1 ) }
141- }
142- },
143- modifier = Modifier
144- .padding(bottom = 10 .dp, top = 12 .dp)
145- .fillMaxWidth(),
111+ OnboardingBottomButton (
112+ currentPage = currentPage,
113+ pageCount = pageCount,
114+ currentPageData = currentPageData,
115+ onNextClick = { scope.launch { pagerState.scrollToPage(currentPage + 1 ) } },
116+ onStartClick = onStartButtonClick,
117+ onRestartClick = { scope.launch { pagerState.scrollToPage(0 ) } }
146118 )
147119 }
148120}
149121
150122@Composable
151- private fun OnboardingTopBar (
123+ private fun OnboardingBottomButton (
152124 currentPage : Int ,
153- onSkipButtonClick : () -> Unit ,
154- modifier : Modifier = Modifier ,
125+ pageCount : Int ,
126+ currentPageData : OnboardingPageData ? ,
127+ onNextClick : () -> Unit ,
128+ onStartClick : () -> Unit ,
129+ onRestartClick : () -> Unit
155130) {
156- Row (
157- verticalAlignment = Alignment .CenterVertically ,
158- modifier = modifier
159- .fillMaxWidth()
160- .height(64 .dp),
161- ) {
162- Image (
163- painter = painterResource(R .drawable.ic_onboarding_logo),
164- contentDescription = null ,
165- )
166-
167- Spacer (modifier = Modifier .weight(1f ))
168-
169- AnimatedVisibility (
170- visible = currentPage == 0 ,
171- enter = fadeIn(),
172- exit = fadeOut(),
131+ if (currentPage == pageCount - 1 ) {
132+ Row (
133+ modifier = Modifier
134+ .padding(horizontal = 20 .dp)
135+ .padding(bottom = 10 .dp, top = 12 .dp)
136+ .fillMaxWidth(),
137+ horizontalArrangement = Arrangement .spacedBy(8 .dp)
173138 ) {
174- Text (
175- text = stringResource(R .string.skip),
176- style = PieceTheme .typography.bodyMM.copy(
177- textDecoration = TextDecoration .Underline
178- ),
179- color = PieceTheme .colors.dark3,
180- modifier = Modifier .clickable { onSkipButtonClick() }
139+ PieceOutlinedButton (
140+ label = stringResource(R .string.onboarding_camera_block_button1),
141+ onClick = onRestartClick,
142+ modifier = Modifier .weight(1f )
143+ )
144+ PieceSolidButton (
145+ label = stringResource(R .string.onboarding_camera_block_button2),
146+ onClick = onStartClick,
147+ modifier = Modifier .weight(1f )
181148 )
182149 }
183- }
184- }
150+ } else {
151+ val labelRes = currentPageData?.buttonLabelRes ? : return
185152
186- @Composable
187- private fun OnboardingPageContent (
188- imageRes : Int ,
189- title : String ,
190- description : String
191- ) {
192- Column (modifier = Modifier .fillMaxSize()) {
193- Image (
194- painter = painterResource(imageRes),
195- contentDescription = null ,
153+ PieceSolidButton (
154+ label = stringResource(labelRes),
155+ onClick = onNextClick,
196156 modifier = Modifier
197- .align(Alignment .CenterHorizontally )
198- .padding(bottom = 66 .dp),
199- )
200-
201- Text (
202- text = title,
203- textAlign = TextAlign .Start ,
204- style = PieceTheme .typography.headingLSB,
205- color = PieceTheme .colors.black,
206- modifier = Modifier .padding(bottom = 12 .dp),
207- )
208-
209- Text (
210- text = description,
211- textAlign = TextAlign .Start ,
212- style = PieceTheme .typography.bodySM,
213- color = PieceTheme .colors.dark3,
214- )
215- }
216- }
217-
218- @Composable
219- private fun OnboardingIndicator (
220- total : Int ,
221- current : Int ,
222- modifier : Modifier = Modifier ,
223- ) {
224- Row (
225- horizontalArrangement = Arrangement .spacedBy(8 .dp),
226- verticalAlignment = Alignment .CenterVertically ,
227- modifier = modifier
228- ) {
229- (0 until total).forEachIndexed { index, _ ->
230- if (index == current) {
231- Spacer (
232- modifier = Modifier
233- .size(width = 20 .dp, height = 8 .dp)
234- .clip(CircleShape )
235- .background(PieceTheme .colors.dark2)
236- )
237- } else {
238- Spacer (
239- modifier = Modifier
240- .size(8 .dp)
241- .clip(CircleShape )
242- .background(PieceTheme .colors.light1)
243- )
244- }
245- }
246- }
247- }
248-
249- @Preview
250- @Composable
251- private fun OnboardingScreenPreview () {
252- PieceTheme {
253- Surface (
254- color = PieceTheme .colors.white,
255- modifier = Modifier .fillMaxSize(),
256- ) {
257- OnboardingScreen {}
258- }
259- }
260- }
261-
262- @Preview
263- @Composable
264- private fun OnboardingTopBarPreview () {
265- PieceTheme {
266- OnboardingTopBar (
267- currentPage = 0 ,
268- onSkipButtonClick = {}
157+ .padding(horizontal = 20 .dp)
158+ .padding(bottom = 10 .dp, top = 12 .dp)
159+ .fillMaxWidth(),
269160 )
270161 }
271- }
272-
273-
274- @Preview
275- @Composable
276- private fun OnboardingIndicatorPreview () {
277- PieceTheme {
278- OnboardingIndicator (total = 2 , current = 0 )
279- }
280- }
162+ }
0 commit comments