Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7346140
[ui]: 바텀 네비게이션 바 ui 수정 (#55)
rbqks529 Jul 24, 2025
f0b61fe
[feat]: 네비게이션 의존성 추가 및 기존 의존성 버전 수정 (#55)
rbqks529 Jul 24, 2025
d3519c6
[feat]: 타입 세이프 네비게이션으로 수정 (#55)
rbqks529 Jul 24, 2025
050f59f
[ui]: 아이콘 이름 변경 (#55)
rbqks529 Jul 24, 2025
47a7660
[feat]: GroupViewModel 위치 변경 (#55)
rbqks529 Jul 24, 2025
843327c
[feat]: 네비게이션 및 그룹 화면 임시 커밋 (#55)
rbqks529 Jul 24, 2025
f77ea31
Merge branch 'develop' of https://github.com/THIP-TextHip/THIP-Androi…
rbqks529 Jul 24, 2025
1fae915
[feat]: 네비게이션 이름 수정 및 파일 이동 (#55)
rbqks529 Jul 24, 2025
ab8640f
[feat]: 메인 화면에서 바텀 네비게이션 표시 로직 수정(#55)
rbqks529 Jul 24, 2025
fb21d79
[refactor]: 기존 코드 수정 (#55)
rbqks529 Jul 24, 2025
caa86c9
[feat]: 네비게이션 파일 분리 완료 (#55)
rbqks529 Jul 24, 2025
53b0e58
[feat]: 네비게이션 extensions(함수) 분리 (#55)
rbqks529 Jul 24, 2025
cc9c701
[feat]: 루트 분리 (#55)
rbqks529 Jul 24, 2025
e35062d
[feat]: 루트 분리 (#55)
rbqks529 Jul 24, 2025
e4b4a28
[feat]: 루트 분리 (#55)
rbqks529 Jul 24, 2025
d6ffedd
[feat]: 코드에서 사용하는 루트 이름 수정(리컴포지션 해도 다시 생성 안되게) (#55)
rbqks529 Jul 24, 2025
b16c04b
[feat]: 네비게이션 스트링 추출 (#55)
rbqks529 Jul 24, 2025
c4b2c8d
[feat]: 루트를 메인 탭 루트와 분리 (#55)
rbqks529 Jul 24, 2025
dd15818
[feat]: 메인 탭 이름 매칭 로직 수정 (#55)
rbqks529 Jul 24, 2025
14d5b7b
[ui]: 알림 페이지 QA 진행 (#55)
rbqks529 Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
}

android {
Expand Down Expand Up @@ -55,6 +56,7 @@ dependencies {
implementation(libs.androidx.foundation)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.navigation.runtime.android)
implementation(libs.kotlinx.serialization.json)
implementation(libs.accompanist.pager)
implementation(libs.accompanist.pager.indicators)
testImplementation(libs.junit)
Expand Down
13 changes: 8 additions & 5 deletions app/src/main/java/com/texthip/thip/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,29 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.texthip.thip.ui.navigator.BottomNavigationBar
import com.texthip.thip.ui.navigator.MainNavHost
import com.texthip.thip.ui.navigator.NavBarItems
import com.texthip.thip.ui.navigator.extensions.isMainTabRoute

@Composable
fun MainScreen() {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val showBottomBar = currentRoute in NavBarItems.BarItems.map { it.route }
val currentDestination = navBackStackEntry?.destination

val showBottomBar = currentDestination?.isMainTabRoute() ?: true

Scaffold(
bottomBar = {
if (showBottomBar) BottomNavigationBar(navController)
}
},
containerColor = Color.Transparent
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
MainNavHost (navController)
MainNavHost(navController)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,10 @@ fun AlarmScreen(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
painter = painterResource(R.drawable.ic_notification),
contentDescription = null,
tint = colors.Grey02,
)
Spacer(modifier = Modifier.height(12.dp))
Text(
text = stringResource(R.string.alarm_notification_comment),
style = typography.smalltitle_sb600_s16_h20,
color = colors.Grey01
style = typography.smalltitle_sb600_s18_h24,
color = colors.White
)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.texthip.thip.R
import com.texthip.thip.ui.common.buttons.GenreChipRow
import com.texthip.thip.ui.common.buttons.ToggleSwitchButton
Expand All @@ -36,13 +37,9 @@ import com.texthip.thip.ui.group.makeroom.component.GroupSelectBook
import com.texthip.thip.ui.group.makeroom.component.GroupMemberLimitPicker
import com.texthip.thip.ui.group.makeroom.component.SectionDivider
import com.texthip.thip.ui.group.makeroom.mock.BookData
import com.texthip.thip.ui.group.makeroom.mock.GroupMakeRoomRequest
import com.texthip.thip.ui.group.makeroom.mock.dummyGroupBooks
import com.texthip.thip.ui.group.makeroom.mock.dummySavedBooks
import com.texthip.thip.ui.group.makeroom.viewmodel.ApiResult
import com.texthip.thip.ui.group.makeroom.viewmodel.GroupCreateResponse
import com.texthip.thip.ui.group.makeroom.viewmodel.GroupMakeRoomViewModel
import com.texthip.thip.ui.group.makeroom.viewmodel.GroupRepository
import com.texthip.thip.ui.theme.ThipTheme
import com.texthip.thip.ui.theme.ThipTheme.colors
import com.texthip.thip.ui.theme.ThipTheme.typography
Expand Down Expand Up @@ -238,15 +235,7 @@ fun GroupMakeRoomScreen(
@Preview
@Composable
private fun GroupMakeRoomScreenPreview() {
// Preview용 MockViewModel 생성
val mockViewModel = object : GroupMakeRoomViewModel(MockGroupRepository()) {
// 필요한 경우 Preview용 초기 상태 설정
init {
// 예시: 미리 선택된 책이 있는 상태로 Preview
// selectBook(BookData(id = "1", title = "예시 책", author = "작가"))
// selectGenre(0)
}
}
val mockViewModel: GroupMakeRoomViewModel = viewModel()

ThipTheme {
GroupMakeRoomScreen(
Expand All @@ -256,16 +245,3 @@ private fun GroupMakeRoomScreenPreview() {
)
}
}

// Preview용 Mock Repository
class MockGroupRepository : GroupRepository {
override suspend fun createGroup(request: GroupMakeRoomRequest): ApiResult<GroupCreateResponse> {
return ApiResult(
isSuccess = true,
data = GroupCreateResponse(
groupId = "mock_group_id",
groupName = "Mock Group"
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import kotlinx.coroutines.launch
import java.time.LocalDate

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

Copilot AI Jul 25, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Production code should not have Mock implementations as default parameters. Consider using dependency injection or factory patterns to provide the appropriate repository implementation based on the environment.

Suggested change
private val groupRepository: GroupRepository = MockGroupRepository() // 기본값으로 Mock Repository 사용
private val groupRepository: GroupRepository // Dependency must be explicitly provided

Copilot uses AI. Check for mistakes.
) : ViewModel() {

private val _uiState = MutableStateFlow(GroupMakeRoomUiState())
Expand Down Expand Up @@ -122,4 +122,18 @@ data class ApiResult<T>(
data class GroupCreateResponse(
val groupId: String,
val groupName: String
)
)

// Mock Repository 구현
class MockGroupRepository : GroupRepository {
override suspend fun createGroup(request: GroupMakeRoomRequest): ApiResult<GroupCreateResponse> {
// 임시로 성공 응답 반환
return ApiResult(
isSuccess = true,
data = GroupCreateResponse(
groupId = "mock_group_${System.currentTimeMillis()}",
groupName = request.roomTitle
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,31 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import com.texthip.thip.R
import com.texthip.thip.ui.common.buttons.FloatingButton
import com.texthip.thip.ui.common.topappbar.LogoTopAppBar
import com.texthip.thip.ui.group.myroom.component.GroupMySectionHeader
import com.texthip.thip.ui.group.myroom.component.GroupPager
import com.texthip.thip.ui.group.myroom.component.GroupRoomDeadlineSection
import com.texthip.thip.ui.group.myroom.component.GroupSearchTextField
import com.texthip.thip.ui.group.myroom.mock.GroupViewModel
import com.texthip.thip.ui.group.viewmodel.GroupViewModel
import com.texthip.thip.ui.theme.ThipTheme
import com.texthip.thip.ui.theme.ThipTheme.colors

@Composable
fun GroupScreen(
navController: NavHostController? = null,
onNavigateToMakeRoom: () -> Unit = {},
viewModel: GroupViewModel = viewModel()
) {
val myGroups by viewModel.myGroups.collectAsState()
val roomSections by viewModel.roomSections.collectAsState()
val scrollState = rememberScrollState()
var searchText by remember { mutableStateOf("") }
val searchText by remember { mutableStateOf("") }

Copilot AI Jul 24, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The searchText variable is declared but never modified or used meaningfully. Consider removing this unused variable or implementing the search functionality if intended.

Suggested change
val searchText by remember { mutableStateOf("") }
val searchText = remember { mutableStateOf("") }
val filteredGroups = myGroups.filter { it.name.contains(searchText.value, ignoreCase = true) }

Copilot uses AI. Check for mistakes.
Comment thread
rbqks529 marked this conversation as resolved.

Box(
Modifier
Expand Down Expand Up @@ -99,7 +97,7 @@ fun GroupScreen(
// 오른쪽 하단 FAB
FloatingButton(
icon = painterResource(id = R.drawable.ic_makegroup),
onClick = { viewModel.onFabClick() }
onClick = onNavigateToMakeRoom
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.texthip.thip.ui.group.myroom.mock
package com.texthip.thip.ui.group.viewmodel

import androidx.lifecycle.ViewModel
import com.texthip.thip.R
import com.texthip.thip.ui.group.myroom.mock.GroupCardData
import com.texthip.thip.ui.group.myroom.mock.GroupCardItemRoomData
import com.texthip.thip.ui.group.myroom.mock.GroupRoomSectionData
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

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

fun onFabClick() {
// FAB 클릭(모임방 생성 등)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ fun MyPageScreen(
)
MenuItemButton(
text = stringResource(R.string.notification_settings),
icon = painterResource(R.drawable.ic_notification),
icon = painterResource(R.drawable.ic_notice),
contentColor = colors.White,
backgroundColor = colors.DarkGrey02,
hasRightIcon = true,
Expand Down
10 changes: 0 additions & 10 deletions app/src/main/java/com/texthip/thip/ui/navigator/BarItem.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,25 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.texthip.thip.ui.navigator.data.NavBarItems
import com.texthip.thip.ui.navigator.extensions.navigateToTab
import com.texthip.thip.ui.navigator.extensions.isRoute
import com.texthip.thip.ui.theme.ThipTheme.colors
import com.texthip.thip.ui.theme.ThipTheme.typography

@Composable
fun BottomNavigationBar(navController: NavController) {
val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route
fun BottomNavigationBar(navController: NavHostController) {
val currentDestination = navController.currentBackStackEntryAsState().value?.destination
val greyColor = colors.Grey02

Box(
modifier = Modifier
Expand All @@ -41,9 +49,48 @@ fun BottomNavigationBar(navController: NavController) {
bottomEnd = 0.dp
)
)
.background(colors.Black),
.background(colors.Black)
.drawBehind {
val cornerRadius = 12.dp.toPx()
val strokeWidth = 2.dp.toPx()

val path = Path().apply {

Copilot AI Jul 25, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a Path object in the drawBehind block will be executed on every recomposition. Consider moving this path creation outside the drawBehind or caching it.

Copilot uses AI. Check for mistakes.
// 좌상단 모서리부터 시작
moveTo(0f, cornerRadius)
arcTo(
rect = androidx.compose.ui.geometry.Rect(
left = 0f,
top = 0f,
right = cornerRadius * 2,
bottom = cornerRadius * 2
),
startAngleDegrees = 180f,
sweepAngleDegrees = 90f,
forceMoveTo = false
)
lineTo(size.width - cornerRadius, 0f)
arcTo(
rect = androidx.compose.ui.geometry.Rect(
left = size.width - cornerRadius * 2,
top = 0f,
right = size.width,
bottom = cornerRadius * 2
),
startAngleDegrees = 270f,
sweepAngleDegrees = 90f,
forceMoveTo = false
)
}

drawPath(
path = path,
color = greyColor,
style = Stroke(width = strokeWidth)
)
},
contentAlignment = Alignment.Center
) {

Row(
modifier = Modifier
.fillMaxSize()
Expand All @@ -52,39 +99,32 @@ fun BottomNavigationBar(navController: NavController) {
verticalAlignment = Alignment.CenterVertically
) {
NavBarItems.BarItems.forEach { item ->
val isSelected = currentRoute == item.route
val isSelected = currentDestination?.isRoute(item.route) == true
NavigationBarItem(
icon = {
Icon(
painter = painterResource(id = if (isSelected) item.SelectedIconRes else item.IconRes),
contentDescription = item.title,
painter = painterResource(id = if (isSelected) item.selectedIconRes else item.iconRes),
contentDescription = stringResource(item.titleRes),
)
},
label = {
Text(
text = item.title,
text = stringResource(item.titleRes),
style = typography.navi_m500_s10
)
},
selected = isSelected,
onClick = {
if (!isSelected) {
navController.navigate(item.route) {
popUpTo(navController.graph.startDestinationId) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
navController.navigateToTab(item.route)
}
},

colors = NavigationBarItemDefaults.colors(
indicatorColor = Color.Transparent,
selectedIconColor = colors.Purple,
unselectedIconColor = Color.Unspecified,
unselectedIconColor = colors.Grey02,
selectedTextColor = colors.Purple,
unselectedTextColor = Color.Unspecified
unselectedTextColor = colors.Grey02
)
)
}
Expand Down
Loading