Skip to content

Commit d3c325d

Browse files
committed
[Feat] 중복 스탭 리뷰반영
1 parent 5139123 commit d3c325d

File tree

1 file changed

+39
-168
lines changed
  • feature/onboarding/src/commonMain/kotlin/com/nexters/emotia/feature/onboarding

1 file changed

+39
-168
lines changed

feature/onboarding/src/commonMain/kotlin/com/nexters/emotia/feature/onboarding/OnBoardingScreen.kt

Lines changed: 39 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ import androidx.compose.foundation.layout.offset
2121
import androidx.compose.foundation.layout.padding
2222
import androidx.compose.foundation.layout.size
2323
import androidx.compose.foundation.shape.CircleShape
24-
import androidx.compose.foundation.shape.RoundedCornerShape
2524
import androidx.compose.material3.Button
2625
import androidx.compose.material3.CircularProgressIndicator
27-
import androidx.compose.material3.Surface
2826
import androidx.compose.material3.Text
2927
import androidx.compose.runtime.Composable
3028
import androidx.compose.runtime.LaunchedEffect
@@ -38,8 +36,6 @@ import androidx.compose.ui.Modifier
3836
import androidx.compose.ui.draw.clip
3937
import androidx.compose.ui.graphics.Color
4038
import androidx.compose.ui.layout.ContentScale
41-
import androidx.compose.ui.text.style.TextAlign
42-
import androidx.compose.ui.unit.IntOffset
4339
import androidx.compose.ui.unit.dp
4440
import androidx.compose.ui.unit.sp
4541
import com.nexters.emotia.core.designsystem.component.TypingAnimatedSpeechBubble
@@ -54,6 +50,7 @@ import emotia.core.designsystem.generated.resources.seven
5450
import emotia.core.designsystem.generated.resources.six
5551
import emotia.core.designsystem.generated.resources.ten
5652
import emotia.core.designsystem.generated.resources.third
53+
import org.jetbrains.compose.resources.DrawableResource
5754
import org.jetbrains.compose.resources.painterResource
5855
import org.koin.compose.viewmodel.koinViewModel
5956

@@ -134,6 +131,23 @@ private fun StoryContent(
134131
val totalSteps = 12
135132
var currentStep by remember { mutableStateOf(0) }
136133

134+
// --- 리팩토링된 부분: 각 스텝에 해당하는 이미지를 리스트로 관리 ---
135+
val storyImages: List<DrawableResource> = remember {
136+
listOf(
137+
// 0~2단계는 애니메이션이 복잡하여 별도 처리
138+
Res.drawable.four, // 3단계 (인덱스 0)
139+
Res.drawable.five, // 4단계 (인덱스 1)
140+
Res.drawable.six, // 5단계 (인덱스 2)
141+
Res.drawable.six, // 6단계 (인덱스 3)
142+
Res.drawable.seven, // 7단계 (인덱스 4)
143+
Res.drawable.eight, // 8단계 (인덱스 5)
144+
Res.drawable.nine, // 9단계 (인덱스 6)
145+
Res.drawable.ten, // 10단계 (인덱스 7)
146+
)
147+
}
148+
// 단순 이미지 전환이 일어나는 스텝의 범위
149+
val simpleImageTransitionSteps = 3..10
150+
137151
BoxWithConstraints(
138152
modifier = Modifier
139153
.fillMaxSize()
@@ -152,9 +166,10 @@ private fun StoryContent(
152166

153167
// --- 애니메이션 상태 값 정의 ---
154168
val animationSpecFloat = tween<Float>(durationMillis = 600)
155-
val animationSpecIntOffset = tween<IntOffset>(durationMillis = 600)
156169

157-
// first 이미지 애니메이션 (위로 이동 및 크기 축소)
170+
// --- 각 스텝 별 UI 구성 (복잡한 애니메이션은 기존 로직 유지) ---
171+
172+
// Step 1 & 2: first 이미지 (위로 이동 및 크기 축소)
158173
val firstImageOffsetY by animateDpAsState(
159174
targetValue = if (currentStep >= 1) -(screenHeight / 4) else 0.dp,
160175
animationSpec = tween(600)
@@ -164,17 +179,8 @@ private fun StoryContent(
164179
animationSpec = tween(600)
165180
)
166181

167-
// second 이미지 애니메이션 (위로 이동)
168-
val secondImageOffsetY by animateDpAsState(
169-
targetValue = if (currentStep == 2) -(screenHeight / 2) else 0.dp,
170-
animationSpec = tween(600)
171-
)
172-
173-
// --- 각 스텝 별 UI 구성 ---
174-
175-
// Step 1 & 2: first 이미지
176182
AnimatedVisibility(
177-
visible = currentStep <= 1, // Step 1과 2에서만 보임
183+
visible = currentStep <= 1,
178184
exit = fadeOut(animationSpecFloat)
179185
) {
180186
Image(
@@ -191,8 +197,8 @@ private fun StoryContent(
191197

192198
// Step 2: second 이미지 (하단)
193199
AnimatedVisibility(
194-
visible = currentStep == 1, // Step 2에서만 보임
195-
enter = slideInVertically(animationSpecIntOffset) { it / 2 } + fadeIn(animationSpecFloat),
200+
visible = currentStep == 1,
201+
enter = slideInVertically(tween(600)) { it / 2 } + fadeIn(animationSpecFloat),
196202
exit = fadeOut(animationSpecFloat)
197203
) {
198204
Image(
@@ -206,157 +212,44 @@ private fun StoryContent(
206212
)
207213
}
208214

209-
// Step 3: third(하단) + second(상단) 스택
215+
// Step 3: third(하단) + second(상단) 스택
210216
AnimatedVisibility(
211-
visible = currentStep == 2, // Step 3에서만 보임
217+
visible = currentStep == 2,
212218
enter = fadeIn(animationSpecFloat),
213219
exit = fadeOut(animationSpecFloat)
214220
) {
215221
Column(modifier = Modifier.fillMaxSize()) {
216-
// 상단 절반 - second 이미지 (투명도 50%)
217222
Image(
218223
painter = painterResource(Res.drawable.second),
219224
contentDescription = "Second screen (top half)",
220-
modifier = Modifier
221-
.fillMaxWidth()
222-
.weight(1f), // 절반 차지
225+
modifier = Modifier.fillMaxWidth().weight(1f),
223226
contentScale = ContentScale.Crop,
224227
alpha = 0.5f
225228
)
226-
227-
// 하단 절반 - third 이미지
228229
Image(
229230
painter = painterResource(Res.drawable.third),
230231
contentDescription = "Third screen (bottom half)",
231-
modifier = Modifier
232-
.fillMaxWidth()
233-
.weight(1f), // 절반 차지
232+
modifier = Modifier.fillMaxWidth().weight(1f),
234233
contentScale = ContentScale.Crop
235234
)
236235
}
237236
}
238237

239-
240-
// Step 4: four 이미지로 전환
241-
AnimatedVisibility(
242-
visible = currentStep == 3,
243-
enter = fadeIn(animationSpecFloat),
244-
exit = fadeOut(animationSpecFloat)
245-
) {
246-
Image(
247-
painter = painterResource(Res.drawable.four),
248-
contentDescription = "Fourth screen",
249-
modifier = Modifier.fillMaxSize(),
250-
contentScale = ContentScale.Crop
251-
)
252-
}
253-
254-
// Step 4
255-
AnimatedVisibility(
256-
visible = currentStep == 4,
257-
enter = fadeIn(animationSpecFloat),
258-
exit = fadeOut(animationSpecFloat)
259-
) {
260-
Image(
261-
painter = painterResource(Res.drawable.five),
262-
contentDescription = "Fifth screen",
263-
modifier = Modifier.fillMaxSize(),
264-
contentScale = ContentScale.Crop
265-
)
266-
}
267-
268-
// Step 5
238+
// --- 리팩토링된 부분: 3~10단계의 단순 이미지 전환을 하나의 블록으로 처리 ---
269239
AnimatedVisibility(
270-
visible = currentStep == 5,
240+
visible = currentStep in simpleImageTransitionSteps,
271241
enter = fadeIn(animationSpecFloat),
272242
exit = fadeOut(animationSpecFloat)
273243
) {
244+
val imageIndex = (currentStep - simpleImageTransitionSteps.first).coerceIn(storyImages.indices)
274245
Image(
275-
painter = painterResource(Res.drawable.six),
276-
contentDescription = "Fifth screen",
277-
modifier = Modifier.fillMaxSize(),
278-
contentScale = ContentScale.Crop
279-
)
280-
}
281-
// Step 6
282-
AnimatedVisibility(
283-
visible = currentStep == 6,
284-
enter = fadeIn(animationSpecFloat),
285-
exit = fadeOut(animationSpecFloat)
286-
) {
287-
Image(
288-
painter = painterResource(Res.drawable.six),
289-
contentDescription = "Fifth screen",
246+
painter = painterResource(storyImages[imageIndex]),
247+
contentDescription = "Story image for step ${currentStep + 1}",
290248
modifier = Modifier.fillMaxSize(),
291249
contentScale = ContentScale.Crop
292250
)
293251
}
294252

295-
// Step 7
296-
AnimatedVisibility(
297-
visible = currentStep == 7,
298-
enter = fadeIn(animationSpecFloat),
299-
exit = fadeOut(animationSpecFloat)
300-
) {
301-
Image(
302-
painter = painterResource(Res.drawable.seven),
303-
contentDescription = "Fifth screen",
304-
modifier = Modifier.fillMaxSize(),
305-
contentScale = ContentScale.Crop
306-
)
307-
}
308-
309-
AnimatedVisibility(
310-
visible = currentStep == 8,
311-
enter = fadeIn(animationSpecFloat),
312-
exit = fadeOut(animationSpecFloat)
313-
) {
314-
Image(
315-
painter = painterResource(Res.drawable.eight),
316-
contentDescription = "Sixth screen",
317-
modifier = Modifier.fillMaxSize(),
318-
contentScale = ContentScale.Crop
319-
)
320-
}
321-
322-
AnimatedVisibility(
323-
visible = currentStep == 9,
324-
enter = fadeIn(animationSpecFloat),
325-
exit = fadeOut(animationSpecFloat)
326-
) {
327-
Image(
328-
painter = painterResource(Res.drawable.nine),
329-
contentDescription = "Sixth screen",
330-
modifier = Modifier.fillMaxSize(),
331-
contentScale = ContentScale.Crop
332-
)
333-
}
334-
335-
AnimatedVisibility(
336-
visible = currentStep == 10,
337-
enter = fadeIn(animationSpecFloat),
338-
exit = fadeOut(animationSpecFloat)
339-
) {
340-
Image(
341-
painter = painterResource(Res.drawable.ten),
342-
contentDescription = "Sixth screen",
343-
modifier = Modifier.fillMaxSize(),
344-
contentScale = ContentScale.Crop
345-
)
346-
}
347-
348-
AnimatedVisibility(
349-
visible = currentStep == 11,
350-
enter = fadeIn(animationSpecFloat),
351-
exit = fadeOut(animationSpecFloat)
352-
) {
353-
Image(
354-
painter = painterResource(Res.drawable.ten),
355-
contentDescription = "Sixth screen",
356-
modifier = Modifier.fillMaxSize(),
357-
contentScale = ContentScale.Crop
358-
)
359-
}
360253

361254
// 말풍선
362255
val (speechBubbleText, useAlternativeBackground) = when (currentStep) {
@@ -380,7 +273,6 @@ private fun StoryContent(
380273
exit = fadeOut(tween(300)),
381274
modifier = Modifier.align(Alignment.BottomCenter)
382275
) {
383-
// 커스텀 말풍선 컴포넌트 호출 및 파라미터 전달
384276
TypingAnimatedSpeechBubble(
385277
fullText = speechBubbleText,
386278
useAlternativeBackground = useAlternativeBackground
@@ -396,18 +288,18 @@ private fun StoryContent(
396288
Box(
397289
modifier = Modifier
398290
.fillMaxSize()
399-
.background(Color.Black), // 전체 배경 어둡게
291+
.background(Color.Black),
400292
contentAlignment = Alignment.Center
401293
) {
402294
// 원형 뷰포트
403295
Box(
404296
modifier = Modifier
405-
.size(150.dp) // 원 크기
406-
.clip(CircleShape) // 동그랗게 자름
407-
.background(Color.Transparent) // 원 안은 배경이 그대로 보이도록
297+
.size(150.dp)
298+
.clip(CircleShape)
299+
.background(Color.Transparent)
408300
) {
409301
Image(
410-
painter = painterResource(Res.drawable.ten), // 보여줄 이미지
302+
painter = painterResource(Res.drawable.ten),
411303
contentDescription = "마지막 배경",
412304
modifier = Modifier.fillMaxSize(),
413305
contentScale = ContentScale.Crop
@@ -439,25 +331,4 @@ private fun StoryContent(
439331
)
440332
}
441333
}
442-
}
443-
444-
@Composable
445-
private fun SpeechBubble(
446-
text: String,
447-
modifier: Modifier = Modifier
448-
) {
449-
Surface(
450-
modifier = modifier.padding(start = 24.dp, end = 24.dp, bottom = 100.dp),
451-
color = Color.Black.copy(alpha = 0.7f),
452-
shape = RoundedCornerShape(16.dp)
453-
) {
454-
Text(
455-
text = text,
456-
color = Color.White,
457-
fontSize = 16.sp,
458-
textAlign = TextAlign.Center,
459-
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
460-
lineHeight = 24.sp
461-
)
462-
}
463-
}
334+
}

0 commit comments

Comments
 (0)