Skip to content

Commit e95b216

Browse files
authored
Merge pull request #57 from rbqks529/ui/#55_typesafe_navigation
[FEAT] 네비게이션 연결 기초 세팅 완료
2 parents c6c3bc1 + 14d5b7b commit e95b216

31 files changed

Lines changed: 407 additions & 144 deletions

app/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ plugins {
44
alias(libs.plugins.android.application)
55
alias(libs.plugins.kotlin.android)
66
alias(libs.plugins.kotlin.compose)
7+
alias(libs.plugins.kotlin.serialization)
78
}
89

910
android {
@@ -55,6 +56,7 @@ dependencies {
5556
implementation(libs.androidx.foundation)
5657
implementation(libs.androidx.lifecycle.viewmodel.compose)
5758
implementation(libs.androidx.navigation.runtime.android)
59+
implementation(libs.kotlinx.serialization.json)
5860
implementation(libs.accompanist.pager)
5961
implementation(libs.accompanist.pager.indicators)
6062
testImplementation(libs.junit)

app/src/main/java/com/texthip/thip/MainScreen.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,29 @@ import androidx.compose.material3.Scaffold
66
import androidx.compose.runtime.Composable
77
import androidx.compose.runtime.getValue
88
import androidx.compose.ui.Modifier
9+
import androidx.compose.ui.graphics.Color
910
import androidx.navigation.compose.currentBackStackEntryAsState
1011
import androidx.navigation.compose.rememberNavController
1112
import com.texthip.thip.ui.navigator.BottomNavigationBar
1213
import com.texthip.thip.ui.navigator.MainNavHost
13-
import com.texthip.thip.ui.navigator.NavBarItems
14+
import com.texthip.thip.ui.navigator.extensions.isMainTabRoute
1415

1516
@Composable
1617
fun MainScreen() {
1718
val navController = rememberNavController()
1819
val navBackStackEntry by navController.currentBackStackEntryAsState()
19-
val currentRoute = navBackStackEntry?.destination?.route
20-
val showBottomBar = currentRoute in NavBarItems.BarItems.map { it.route }
20+
val currentDestination = navBackStackEntry?.destination
21+
22+
val showBottomBar = currentDestination?.isMainTabRoute() ?: true
2123

2224
Scaffold(
2325
bottomBar = {
2426
if (showBottomBar) BottomNavigationBar(navController)
25-
}
27+
},
28+
containerColor = Color.Transparent
2629
) { innerPadding ->
2730
Box(modifier = Modifier.padding(innerPadding)) {
28-
MainNavHost (navController)
31+
MainNavHost(navController)
2932
}
3033
}
3134
}

app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,10 @@ fun AlarmScreen(
7272
verticalArrangement = Arrangement.Center,
7373
horizontalAlignment = Alignment.CenterHorizontally
7474
) {
75-
Icon(
76-
painter = painterResource(R.drawable.ic_notification),
77-
contentDescription = null,
78-
tint = colors.Grey02,
79-
)
80-
Spacer(modifier = Modifier.height(12.dp))
8175
Text(
8276
text = stringResource(R.string.alarm_notification_comment),
83-
style = typography.smalltitle_sb600_s16_h20,
84-
color = colors.Grey01
77+
style = typography.smalltitle_sb600_s18_h24,
78+
color = colors.White
8579
)
8680
}
8781
} else {

app/src/main/java/com/texthip/thip/ui/group/makeroom/screen/GroupMakeRoomScreen.kt

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import androidx.compose.ui.res.stringResource
2424
import androidx.compose.ui.text.input.KeyboardType
2525
import androidx.compose.ui.tooling.preview.Preview
2626
import androidx.compose.ui.unit.dp
27+
import androidx.lifecycle.viewmodel.compose.viewModel
2728
import com.texthip.thip.R
2829
import com.texthip.thip.ui.common.buttons.GenreChipRow
2930
import com.texthip.thip.ui.common.buttons.ToggleSwitchButton
@@ -36,13 +37,9 @@ import com.texthip.thip.ui.group.makeroom.component.GroupSelectBook
3637
import com.texthip.thip.ui.group.makeroom.component.GroupMemberLimitPicker
3738
import com.texthip.thip.ui.group.makeroom.component.SectionDivider
3839
import com.texthip.thip.ui.group.makeroom.mock.BookData
39-
import com.texthip.thip.ui.group.makeroom.mock.GroupMakeRoomRequest
4040
import com.texthip.thip.ui.group.makeroom.mock.dummyGroupBooks
4141
import com.texthip.thip.ui.group.makeroom.mock.dummySavedBooks
42-
import com.texthip.thip.ui.group.makeroom.viewmodel.ApiResult
43-
import com.texthip.thip.ui.group.makeroom.viewmodel.GroupCreateResponse
4442
import com.texthip.thip.ui.group.makeroom.viewmodel.GroupMakeRoomViewModel
45-
import com.texthip.thip.ui.group.makeroom.viewmodel.GroupRepository
4643
import com.texthip.thip.ui.theme.ThipTheme
4744
import com.texthip.thip.ui.theme.ThipTheme.colors
4845
import com.texthip.thip.ui.theme.ThipTheme.typography
@@ -238,15 +235,7 @@ fun GroupMakeRoomScreen(
238235
@Preview
239236
@Composable
240237
private fun GroupMakeRoomScreenPreview() {
241-
// Preview용 MockViewModel 생성
242-
val mockViewModel = object : GroupMakeRoomViewModel(MockGroupRepository()) {
243-
// 필요한 경우 Preview용 초기 상태 설정
244-
init {
245-
// 예시: 미리 선택된 책이 있는 상태로 Preview
246-
// selectBook(BookData(id = "1", title = "예시 책", author = "작가"))
247-
// selectGenre(0)
248-
}
249-
}
238+
val mockViewModel: GroupMakeRoomViewModel = viewModel()
250239

251240
ThipTheme {
252241
GroupMakeRoomScreen(
@@ -256,16 +245,3 @@ private fun GroupMakeRoomScreenPreview() {
256245
)
257246
}
258247
}
259-
260-
// Preview용 Mock Repository
261-
class MockGroupRepository : GroupRepository {
262-
override suspend fun createGroup(request: GroupMakeRoomRequest): ApiResult<GroupCreateResponse> {
263-
return ApiResult(
264-
isSuccess = true,
265-
data = GroupCreateResponse(
266-
groupId = "mock_group_id",
267-
groupName = "Mock Group"
268-
)
269-
)
270-
}
271-
}

app/src/main/java/com/texthip/thip/ui/group/makeroom/viewmodel/GroupMakeRoomViewModel.kt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import kotlinx.coroutines.launch
1212
import java.time.LocalDate
1313

1414
// 나중에 서버와 연동할 때 사용할 뷰모델 예시
15-
open class GroupMakeRoomViewModel(
16-
private val groupRepository: GroupRepository // 의존성 주입
15+
class GroupMakeRoomViewModel(
16+
private val groupRepository: GroupRepository = MockGroupRepository() // 기본값으로 Mock Repository 사용
1717
) : ViewModel() {
1818

1919
private val _uiState = MutableStateFlow(GroupMakeRoomUiState())
@@ -122,4 +122,18 @@ data class ApiResult<T>(
122122
data class GroupCreateResponse(
123123
val groupId: String,
124124
val groupName: String
125-
)
125+
)
126+
127+
// Mock Repository 구현
128+
class MockGroupRepository : GroupRepository {
129+
override suspend fun createGroup(request: GroupMakeRoomRequest): ApiResult<GroupCreateResponse> {
130+
// 임시로 성공 응답 반환
131+
return ApiResult(
132+
isSuccess = true,
133+
data = GroupCreateResponse(
134+
groupId = "mock_group_${System.currentTimeMillis()}",
135+
groupName = request.roomTitle
136+
)
137+
)
138+
}
139+
}

app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,31 @@ import androidx.compose.runtime.collectAsState
1515
import androidx.compose.runtime.getValue
1616
import androidx.compose.runtime.mutableStateOf
1717
import androidx.compose.runtime.remember
18-
import androidx.compose.runtime.setValue
1918
import androidx.compose.ui.Modifier
2019
import androidx.compose.ui.res.painterResource
2120
import androidx.compose.ui.tooling.preview.Preview
2221
import androidx.compose.ui.unit.dp
2322
import androidx.lifecycle.viewmodel.compose.viewModel
24-
import androidx.navigation.NavHostController
2523
import com.texthip.thip.R
2624
import com.texthip.thip.ui.common.buttons.FloatingButton
2725
import com.texthip.thip.ui.common.topappbar.LogoTopAppBar
2826
import com.texthip.thip.ui.group.myroom.component.GroupMySectionHeader
2927
import com.texthip.thip.ui.group.myroom.component.GroupPager
3028
import com.texthip.thip.ui.group.myroom.component.GroupRoomDeadlineSection
3129
import com.texthip.thip.ui.group.myroom.component.GroupSearchTextField
32-
import com.texthip.thip.ui.group.myroom.mock.GroupViewModel
30+
import com.texthip.thip.ui.group.viewmodel.GroupViewModel
3331
import com.texthip.thip.ui.theme.ThipTheme
3432
import com.texthip.thip.ui.theme.ThipTheme.colors
3533

3634
@Composable
3735
fun GroupScreen(
38-
navController: NavHostController? = null,
36+
onNavigateToMakeRoom: () -> Unit = {},
3937
viewModel: GroupViewModel = viewModel()
4038
) {
4139
val myGroups by viewModel.myGroups.collectAsState()
4240
val roomSections by viewModel.roomSections.collectAsState()
4341
val scrollState = rememberScrollState()
44-
var searchText by remember { mutableStateOf("") }
42+
val searchText by remember { mutableStateOf("") }
4543

4644
Box(
4745
Modifier
@@ -99,7 +97,7 @@ fun GroupScreen(
9997
// 오른쪽 하단 FAB
10098
FloatingButton(
10199
icon = painterResource(id = R.drawable.ic_makegroup),
102-
onClick = { viewModel.onFabClick() }
100+
onClick = onNavigateToMakeRoom
103101
)
104102
}
105103
}

app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupViewModel.kt renamed to app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
package com.texthip.thip.ui.group.myroom.mock
1+
package com.texthip.thip.ui.group.viewmodel
22

33
import androidx.lifecycle.ViewModel
44
import com.texthip.thip.R
5+
import com.texthip.thip.ui.group.myroom.mock.GroupCardData
6+
import com.texthip.thip.ui.group.myroom.mock.GroupCardItemRoomData
7+
import com.texthip.thip.ui.group.myroom.mock.GroupRoomSectionData
58
import kotlinx.coroutines.flow.MutableStateFlow
69
import kotlinx.coroutines.flow.StateFlow
710

@@ -84,7 +87,4 @@ class GroupViewModel : ViewModel() {
8487
// 방 카드 클릭 (상세 진입)
8588
}
8689

87-
fun onFabClick() {
88-
// FAB 클릭(모임방 생성 등)
89-
}
9090
}

app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ fun MyPageScreen(
109109
)
110110
MenuItemButton(
111111
text = stringResource(R.string.notification_settings),
112-
icon = painterResource(R.drawable.ic_notification),
112+
icon = painterResource(R.drawable.ic_notice),
113113
contentColor = colors.White,
114114
backgroundColor = colors.DarkGrey02,
115115
hasRightIcon = true,

app/src/main/java/com/texthip/thip/ui/navigator/BarItem.kt

Lines changed: 0 additions & 10 deletions
This file was deleted.

app/src/main/java/com/texthip/thip/ui/navigator/BottomNavigationBar.kt

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,25 @@ import androidx.compose.runtime.Composable
1717
import androidx.compose.ui.Alignment
1818
import androidx.compose.ui.Modifier
1919
import androidx.compose.ui.draw.clip
20+
import androidx.compose.ui.draw.drawBehind
2021
import androidx.compose.ui.graphics.Color
22+
import androidx.compose.ui.graphics.Path
23+
import androidx.compose.ui.graphics.drawscope.Stroke
2124
import androidx.compose.ui.res.painterResource
25+
import androidx.compose.ui.res.stringResource
2226
import androidx.compose.ui.unit.dp
23-
import androidx.navigation.NavController
27+
import androidx.navigation.NavHostController
2428
import androidx.navigation.compose.currentBackStackEntryAsState
29+
import com.texthip.thip.ui.navigator.data.NavBarItems
30+
import com.texthip.thip.ui.navigator.extensions.navigateToTab
31+
import com.texthip.thip.ui.navigator.extensions.isRoute
2532
import com.texthip.thip.ui.theme.ThipTheme.colors
2633
import com.texthip.thip.ui.theme.ThipTheme.typography
2734

2835
@Composable
29-
fun BottomNavigationBar(navController: NavController) {
30-
val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route
36+
fun BottomNavigationBar(navController: NavHostController) {
37+
val currentDestination = navController.currentBackStackEntryAsState().value?.destination
38+
val greyColor = colors.Grey02
3139

3240
Box(
3341
modifier = Modifier
@@ -41,9 +49,48 @@ fun BottomNavigationBar(navController: NavController) {
4149
bottomEnd = 0.dp
4250
)
4351
)
44-
.background(colors.Black),
52+
.background(colors.Black)
53+
.drawBehind {
54+
val cornerRadius = 12.dp.toPx()
55+
val strokeWidth = 2.dp.toPx()
56+
57+
val path = Path().apply {
58+
// 좌상단 모서리부터 시작
59+
moveTo(0f, cornerRadius)
60+
arcTo(
61+
rect = androidx.compose.ui.geometry.Rect(
62+
left = 0f,
63+
top = 0f,
64+
right = cornerRadius * 2,
65+
bottom = cornerRadius * 2
66+
),
67+
startAngleDegrees = 180f,
68+
sweepAngleDegrees = 90f,
69+
forceMoveTo = false
70+
)
71+
lineTo(size.width - cornerRadius, 0f)
72+
arcTo(
73+
rect = androidx.compose.ui.geometry.Rect(
74+
left = size.width - cornerRadius * 2,
75+
top = 0f,
76+
right = size.width,
77+
bottom = cornerRadius * 2
78+
),
79+
startAngleDegrees = 270f,
80+
sweepAngleDegrees = 90f,
81+
forceMoveTo = false
82+
)
83+
}
84+
85+
drawPath(
86+
path = path,
87+
color = greyColor,
88+
style = Stroke(width = strokeWidth)
89+
)
90+
},
4591
contentAlignment = Alignment.Center
4692
) {
93+
4794
Row(
4895
modifier = Modifier
4996
.fillMaxSize()
@@ -52,39 +99,32 @@ fun BottomNavigationBar(navController: NavController) {
5299
verticalAlignment = Alignment.CenterVertically
53100
) {
54101
NavBarItems.BarItems.forEach { item ->
55-
val isSelected = currentRoute == item.route
102+
val isSelected = currentDestination?.isRoute(item.route) == true
56103
NavigationBarItem(
57104
icon = {
58105
Icon(
59-
painter = painterResource(id = if (isSelected) item.SelectedIconRes else item.IconRes),
60-
contentDescription = item.title,
106+
painter = painterResource(id = if (isSelected) item.selectedIconRes else item.iconRes),
107+
contentDescription = stringResource(item.titleRes),
61108
)
62109
},
63110
label = {
64111
Text(
65-
text = item.title,
112+
text = stringResource(item.titleRes),
66113
style = typography.navi_m500_s10
67114
)
68115
},
69116
selected = isSelected,
70117
onClick = {
71118
if (!isSelected) {
72-
navController.navigate(item.route) {
73-
popUpTo(navController.graph.startDestinationId) {
74-
saveState = true
75-
}
76-
launchSingleTop = true
77-
restoreState = true
78-
}
119+
navController.navigateToTab(item.route)
79120
}
80121
},
81-
82122
colors = NavigationBarItemDefaults.colors(
83123
indicatorColor = Color.Transparent,
84124
selectedIconColor = colors.Purple,
85-
unselectedIconColor = Color.Unspecified,
125+
unselectedIconColor = colors.Grey02,
86126
selectedTextColor = colors.Purple,
87-
unselectedTextColor = Color.Unspecified
127+
unselectedTextColor = colors.Grey02
88128
)
89129
)
90130
}

0 commit comments

Comments
 (0)