Skip to content

Commit

Permalink
[Feature] Home item 연결 (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajou4095 authored Feb 6, 2024
1 parent db79812 commit ce0fb75
Show file tree
Hide file tree
Showing 20 changed files with 402 additions and 131 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ac.dnd.bookkeeping.android.presentation.model.main

import androidx.annotation.DrawableRes

data class MainBottomBarItem(
val route: String,
val name: String,
@DrawableRes val icon: Int
)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.home

import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable

Expand All @@ -10,6 +15,24 @@ fun NavGraphBuilder.homeDestination(
composable(
route = HomeConstant.ROUTE
) {
HomeScreen(appState)
val viewModel: HomeViewModel = hiltViewModel()

val model: HomeModel = let {
val state by viewModel.state.collectAsStateWithLifecycle()

HomeModel(
state = state
)
}

ErrorObserver(viewModel)

HomeScreen(
appState = appState,
model = model,
event = viewModel.event,
intent = viewModel::onIntent,
handler = viewModel.handler
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.home

sealed interface HomeEvent {
data class ShowSnackBar(val message: String) : HomeEvent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.home

sealed interface HomeIntent
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.home

data class HomeModel(
val state: HomeState,
)
Original file line number Diff line number Diff line change
@@ -1,46 +1,97 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.home

import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver
import ac.dnd.bookkeeping.android.presentation.R
import ac.dnd.bookkeeping.android.presentation.common.theme.Caption4
import ac.dnd.bookkeeping.android.presentation.common.theme.Icon24
import ac.dnd.bookkeeping.android.presentation.common.util.LaunchedEffectWithLifecycle
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.EventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.MutableEventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.eventObserve
import ac.dnd.bookkeeping.android.presentation.common.view.CustomSnackBarHost
import ac.dnd.bookkeeping.android.presentation.model.main.MainBottomBarItem
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.common.gallery.GalleryScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.home.history.HistoryConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.home.history.HistoryScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.home.setting.SettingScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.home.mypage.MyPageConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.home.mypage.MyPageScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.ScheduleConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.ScheduleScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.home.statistics.StatisticsConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.home.statistics.StatisticsScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.home.test.TestConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.home.test.TestScreen
import ac.dnd.bookkeeping.android.presentation.ui.main.rememberApplicationState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.BottomNavigation
import androidx.compose.material.BottomNavigationItem
import androidx.compose.material.Icon
import androidx.compose.material.Scaffold
import androidx.compose.material.SnackbarResult
import androidx.compose.material.Text
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun HomeScreen(
appState: ApplicationState,
viewModel: HomeViewModel = hiltViewModel()
model: HomeModel,
event: EventFlow<HomeEvent>,
intent: (HomeIntent) -> Unit,
handler: CoroutineExceptionHandler
) {
Observer(
appState = appState,
viewModel = viewModel
)
val scope = rememberCoroutineScope()

val bottomBarItemList: List<MainBottomBarItem> = listOf(
MainBottomBarItem(
route = HistoryConstant.ROUTE,
name = "내역",
icon = R.drawable.ic_launcher
),
MainBottomBarItem(
route = ScheduleConstant.ROUTE,
name = "통계",
icon = R.drawable.ic_launcher
),
MainBottomBarItem(
route = StatisticsConstant.ROUTE,
name = "일정",
icon = R.drawable.ic_launcher
),
MainBottomBarItem(
route = MyPageConstant.ROUTE,
name = "마이페이지",
icon = R.drawable.ic_launcher
),
MainBottomBarItem(
route = TestConstant.ROUTE,
name = "Test Page",
icon = R.drawable.ic_warning
)
)
val scaffoldState = rememberScaffoldState()
var selectedItem by rememberSaveable { mutableIntStateOf(0) }
var snackBarIsShowingState by remember { mutableStateOf(false) }
val pagerState = rememberPagerState(
pageCount = { 2 }
pageCount = { bottomBarItemList.size }
)

LaunchedEffect(selectedItem) {
Expand All @@ -53,57 +104,117 @@ fun HomeScreen(
snackbarHost = CustomSnackBarHost,
bottomBar = {
HomeBottomBarScreen(
itemList = bottomBarItemList,
selectedItem = selectedItem,
onClick = {
selectedItem = it
}
)
}
) { innerPadding ->

HorizontalPager(
state = pagerState,
modifier = Modifier.padding(innerPadding),
userScrollEnabled = false
) { page ->
when (page) {
0 -> {
when (bottomBarItemList[page].route) {
HistoryConstant.ROUTE -> {
HistoryScreen(
appState = appState
)
GalleryScreen(
}
ScheduleConstant.ROUTE -> {
ScheduleScreen(
appState = appState
)
}
StatisticsConstant.ROUTE -> {
StatisticsScreen(
appState = appState
)
}

MyPageConstant.ROUTE -> {
MyPageScreen(
appState = appState
)
}

1 -> {
SettingScreen(
appState = appState,
onShowSnackBar = {
snackBarIsShowingState = true
}
TestConstant.ROUTE -> {
TestScreen(
appState = appState
)
}
}
}
}

if (snackBarIsShowingState) {
LaunchedEffect(Unit) {
scaffoldState.snackbarHostState.showSnackbar("show snackBar")
.let {
if (it == SnackbarResult.Dismissed) {
snackBarIsShowingState = false
}
fun showSnackBar(message: String) {
scope.launch(handler) {
scaffoldState.snackbarHostState.showSnackbar(message)
}
}

LaunchedEffectWithLifecycle(event, handler) {
event.eventObserve { event ->
when (event) {
is HomeEvent.ShowSnackBar -> {
showSnackBar(event.message)
}
}
}
}
}

@Composable
private fun Observer(
appState: ApplicationState,
viewModel: HomeViewModel
private fun HomeBottomBarScreen(
itemList: List<MainBottomBarItem>,
selectedItem: Int,
onClick: (Int) -> Unit
) {
ErrorObserver(viewModel)
BottomNavigation(
elevation = 0.dp,
backgroundColor = Color.LightGray,
modifier = Modifier
.fillMaxWidth()
.height(55.dp)
) {
itemList.forEachIndexed { index, item ->
BottomNavigationItem(
selected = index == selectedItem,
icon = {
Icon(
modifier = Modifier.size(Icon24),
painter = painterResource(id = item.icon),
contentDescription = "bottom icon"
)
},
label = {
Text(
text = item.name,
style = Caption4
)
},
selectedContentColor = Color.Black,
unselectedContentColor = Color.Gray,
onClick = {
onClick(index)
}
)
}
}
}

@Preview
@Composable
private fun HomeScreenPreview() {
HomeScreen(
appState = rememberApplicationState(),
model = HomeModel(
state = HomeState.Init
),
event = MutableEventFlow(),
intent = {},
handler = CoroutineExceptionHandler { _, _ -> }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.home

sealed interface HomeState {
data object Init : HomeState
}
Loading

0 comments on commit ce0fb75

Please sign in to comment.