Skip to content

Commit f975884

Browse files
authored
Merge pull request #54 from YAPP-Github/feat/#50-random-pose
[Feat] #50 랜덤 포즈 추천 기능 구현
2 parents b49d93e + e9a20c8 commit f975884

35 files changed

Lines changed: 1346 additions & 274 deletions

File tree

app/src/main/java/com/neki/android/app/navigation/TopLevelNavItem.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ enum class TopLevelNavItem(
2525
selectedIconRes = R.drawable.ic_nav_pose_selected,
2626
unselectedIconRes = R.drawable.ic_nav_pose_unselected,
2727
iconStringRes = R.string.top_level_nav_pose,
28-
navKey = PoseNavKey.Pose,
28+
navKey = PoseNavKey.PoseMain,
2929
),
3030
MAP(
3131
selectedIconRes = R.drawable.ic_nav_map_selected,

core/designsystem/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ android {
99

1010
dependencies {
1111
implementation(libs.androidx.core.ktx)
12+
api(libs.haze)
13+
api(libs.haze.materials)
1214
}

core/designsystem/src/main/java/com/neki/android/core/designsystem/modifier/Background.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ package com.neki.android.core.designsystem.modifier
22

33
import androidx.compose.foundation.background
44
import androidx.compose.foundation.shape.RoundedCornerShape
5+
import androidx.compose.runtime.Composable
56
import androidx.compose.ui.Modifier
67
import androidx.compose.ui.geometry.Offset
78
import androidx.compose.ui.graphics.Brush
89
import androidx.compose.ui.graphics.Color
910
import androidx.compose.ui.graphics.Shape
11+
import androidx.compose.ui.graphics.luminance
12+
import androidx.compose.ui.unit.Dp
1013
import androidx.compose.ui.unit.dp
14+
import dev.chrisbanes.haze.HazeState
15+
import dev.chrisbanes.haze.HazeStyle
16+
import dev.chrisbanes.haze.HazeTint
17+
import dev.chrisbanes.haze.hazeEffect
1118

1219
/**
1320
* 사진 컴포넌트에 적용되는 그라데이션 배경
@@ -27,3 +34,33 @@ fun Modifier.photoBackground(
2734
),
2835
shape = shape,
2936
)
37+
38+
/**
39+
* 블러 효과가 적용된 배경을 설정하는 Modifier 확장 함수
40+
*
41+
* @param hazeState Haze 블러 효과를 관리하는 상태 객체
42+
* @param enabled 블러 효과 활성화 여부 (false일 경우 단색 배경 적용)
43+
* @param color 블러 효과에 적용될 배경 색상
44+
* @param defaultBackgroundColor 블러 비활성화 시 적용될 기본 배경 색상
45+
* @param blurRadius 블러 효과의 반경
46+
*/
47+
@Composable
48+
fun Modifier.backgroundHazeBlur(
49+
hazeState: HazeState,
50+
enabled: Boolean = true,
51+
color: Color = Color(0xFF202227).copy(alpha = 0.9f),
52+
defaultBackgroundColor: Color = color,
53+
blurRadius: Dp = 12.dp,
54+
): Modifier =
55+
if (enabled) {
56+
this.hazeEffect(
57+
state = hazeState,
58+
style = HazeStyle(
59+
backgroundColor = color,
60+
tint = HazeTint(
61+
color.copy(alpha = if (color.luminance() >= 0.5) 0.6f else 0.65f),
62+
),
63+
blurRadius = blurRadius,
64+
),
65+
)
66+
} else this.background(color = defaultBackgroundColor)
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.neki.android.core.model
22

3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
36
data class Pose(
47
val id: Long = 0L,
58
val poseImageUrl: String = "",
69
val isScrapped: Boolean = false,
7-
val numberOfPeople: Int = 0,
10+
val peopleCount: Int = 0,
811
)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.neki.android.core.model
2+
3+
import kotlinx.collections.immutable.ImmutableList
4+
import kotlinx.collections.immutable.persistentListOf
5+
import kotlinx.serialization.Serializable
6+
7+
private val dummyPoseList = persistentListOf(
8+
Pose(id = 1, poseImageUrl = "https://picsum.photos/seed/poseA/400/520", peopleCount = 1),
9+
Pose(id = 2, poseImageUrl = "https://picsum.photos/seed/poseB/400/680", peopleCount = 2),
10+
Pose(id = 3, poseImageUrl = "https://picsum.photos/seed/poseC/400/450", peopleCount = 1),
11+
Pose(id = 4, poseImageUrl = "https://picsum.photos/seed/poseD/400/600", peopleCount = 3),
12+
Pose(id = 5, poseImageUrl = "https://picsum.photos/seed/poseE/400/550", peopleCount = 2),
13+
Pose(id = 6, poseImageUrl = "https://picsum.photos/seed/poseF/400/720", peopleCount = 4),
14+
Pose(id = 7, poseImageUrl = "https://picsum.photos/seed/poseG/400/480", peopleCount = 1),
15+
Pose(id = 8, poseImageUrl = "https://picsum.photos/seed/poseH/400/650", peopleCount = 2),
16+
Pose(id = 9, poseImageUrl = "https://picsum.photos/seed/poseI/400/500", peopleCount = 3),
17+
Pose(id = 10, poseImageUrl = "https://picsum.photos/seed/poseJ/400/580", peopleCount = 1),
18+
Pose(id = 11, poseImageUrl = "https://picsum.photos/seed/poseK/400/700", peopleCount = 5),
19+
Pose(id = 12, poseImageUrl = "https://picsum.photos/seed/poseL/400/460", peopleCount = 2),
20+
Pose(id = 13, poseImageUrl = "https://picsum.photos/seed/poseM/400/620", peopleCount = 1),
21+
Pose(id = 14, poseImageUrl = "https://picsum.photos/seed/poseN/400/540", peopleCount = 4),
22+
Pose(id = 15, poseImageUrl = "https://picsum.photos/seed/poseO/400/690", peopleCount = 2),
23+
Pose(id = 16, poseImageUrl = "https://picsum.photos/seed/poseP/400/470", peopleCount = 3),
24+
Pose(id = 17, poseImageUrl = "https://picsum.photos/seed/poseQ/400/610", peopleCount = 1),
25+
Pose(id = 18, poseImageUrl = "https://picsum.photos/seed/poseR/400/530", peopleCount = 2),
26+
Pose(id = 19, poseImageUrl = "https://picsum.photos/seed/poseS/400/670", peopleCount = 5),
27+
Pose(id = 20, poseImageUrl = "https://picsum.photos/seed/poseT/400/490", peopleCount = 1),
28+
Pose(id = 21, poseImageUrl = "https://picsum.photos/seed/poseU/400/640", peopleCount = 2),
29+
Pose(id = 22, poseImageUrl = "https://picsum.photos/seed/poseV/400/560", peopleCount = 3),
30+
)
31+
32+
private val scrappedDummyList = persistentListOf(
33+
Pose(
34+
id = 101,
35+
poseImageUrl = "https://picsum.photos/seed/scrapA/400/520",
36+
isScrapped = true,
37+
peopleCount = 1,
38+
),
39+
Pose(
40+
id = 102,
41+
poseImageUrl = "https://picsum.photos/seed/scrapB/400/680",
42+
isScrapped = true,
43+
peopleCount = 2,
44+
),
45+
Pose(
46+
id = 103,
47+
poseImageUrl = "https://picsum.photos/seed/scrapC/400/450",
48+
isScrapped = true,
49+
peopleCount = 1,
50+
),
51+
Pose(
52+
id = 104,
53+
poseImageUrl = "https://picsum.photos/seed/scrapD/400/600",
54+
isScrapped = true,
55+
peopleCount = 3,
56+
),
57+
Pose(
58+
id = 105,
59+
poseImageUrl = "https://picsum.photos/seed/scrapE/400/550",
60+
isScrapped = true,
61+
peopleCount = 2,
62+
),
63+
Pose(
64+
id = 106,
65+
poseImageUrl = "https://picsum.photos/seed/scrapF/400/720",
66+
isScrapped = true,
67+
peopleCount = 4,
68+
),
69+
Pose(
70+
id = 107,
71+
poseImageUrl = "https://picsum.photos/seed/scrapG/400/480",
72+
isScrapped = true,
73+
peopleCount = 1,
74+
),
75+
)
76+
77+
data class PoseState(
78+
val isLoading: Boolean = false,
79+
val selectedPeopleCount: PeopleCount? = null,
80+
val selectedRandomPosePeopleCount: PeopleCount? = null,
81+
val isShowScrappedPose: Boolean = false,
82+
val randomPoseList: ImmutableList<Pose> = dummyPoseList,
83+
val scrappedPoseList: ImmutableList<Pose> = scrappedDummyList,
84+
val isShowPeopleCountBottomSheet: Boolean = false,
85+
val isShowRandomPosePeopleCountBottomSheet: Boolean = false,
86+
)
87+
88+
sealed interface PoseIntent {
89+
data object EnterPoseScreen : PoseIntent
90+
data object ClickAlarmIcon : PoseIntent
91+
data object ClickPeopleCountChip : PoseIntent
92+
data object DismissPeopleCountBottomSheet : PoseIntent
93+
data object DismissRandomPosePeopleCountBottomSheet : PoseIntent
94+
data object ClickScrapChip : PoseIntent
95+
data class ClickPoseItem(val item: Pose) : PoseIntent
96+
data class ClickPeopleCountSheetItem(val peopleCount: PeopleCount) : PoseIntent
97+
data object ClickRandomPoseRecommendation : PoseIntent
98+
data class ClickRandomPosePeopleCountSheetItem(val peopleCount: PeopleCount) : PoseIntent
99+
data object ClickRandomPoseBottomSheetSelectButton : PoseIntent
100+
}
101+
102+
sealed interface PoseEffect {
103+
data object NavigateToNotification : PoseEffect
104+
data class NavigateToRandomPose(val peopleCount: PeopleCount) : PoseEffect
105+
data class NavigateToPoseDetail(val pose: Pose) : PoseEffect
106+
data class ShowToast(val message: String) : PoseEffect
107+
}
108+
109+
@Serializable
110+
enum class PeopleCount(val displayText: String, val value: Int) {
111+
ONE("1인", 1),
112+
TWO("2인", 2),
113+
THREE("3인", 3),
114+
FOUR("4인", 4),
115+
FIVE_OR_MORE("5인 이상", 5),
116+
;
117+
118+
override fun toString(): String = displayText
119+
}

core/ui/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
implementation(libs.androidx.activity.compose)
1717
implementation(libs.androidx.lifecycle.viewmodel.ktx)
1818
implementation(libs.androidx.lifecycle.viewmodel.compose)
19+
implementation(libs.kotlinx.collections.immutable)
1920

2021
api(libs.coil.compose)
2122
api(libs.coil.network.okhttp)

0 commit comments

Comments
 (0)