Skip to content

Commit

Permalink
[Feature] LoginNavGraph & LoginMainDestination 만들기
Browse files Browse the repository at this point in the history
  • Loading branch information
ajou4095 committed Jan 23, 2024
1 parent f19e5fc commit 1dbed24
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ import ac.dnd.bookkeeping.android.presentation.ui.main.home.homeDestination
import ac.dnd.bookkeeping.android.presentation.ui.main.login.loginNavGraph
import ac.dnd.bookkeeping.android.presentation.ui.main.splash.SplashConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.splash.splashDestination
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost
Expand All @@ -20,24 +16,19 @@ fun MainScreen(
viewModel: MainViewModel = hiltViewModel()
) {
BookkeepingTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
val appState = rememberApplicationState()
ManageSystemUiState(appState = appState)
val appState = rememberApplicationState()
ManageSystemUiState(appState = appState)

NavHost(
navController = appState.navController,
startDestination = makeRoute(
SplashConstant.ROUTE,
listOf(SplashConstant.ROUTE_ARGUMENT_ENTRY_POINT_MAIN to SplashConstant.ROUTE_ARGUMENT_ENTRY_POINT_MAIN)
)
) {
loginNavGraph(appState = appState)
homeDestination(appState = appState)
splashDestination(appState = appState)
}
NavHost(
navController = appState.navController,
startDestination = makeRoute(
SplashConstant.ROUTE,
listOf(SplashConstant.ROUTE_ARGUMENT_ENTRY_POINT_MAIN to SplashConstant.ROUTE_ARGUMENT_ENTRY_POINT_MAIN)
)
) {
loginNavGraph(appState = appState)
homeDestination(appState = appState)
splashDestination(appState = appState)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@ package ac.dnd.bookkeeping.android.presentation.ui.main.login

object LoginConstant {
const val ROUTE = "/login"

const val ROUTE_STEP_1 = "$ROUTE/step1"
const val ROUTE_STEP_2 = "$ROUTE/step2"
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,18 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login

import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import androidx.compose.runtime.remember
import androidx.hilt.navigation.compose.hiltViewModel
import ac.dnd.bookkeeping.android.presentation.ui.main.login.main.LoginMainConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.login.main.loginMainDestination
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import androidx.navigation.navigation

fun NavGraphBuilder.loginNavGraph(
appState: ApplicationState
) {
navigation(
startDestination = LoginConstant.ROUTE_STEP_1,
startDestination = LoginMainConstant.ROUTE,
route = LoginConstant.ROUTE
) {
// TODO : 분리
composable(
route = LoginConstant.ROUTE_STEP_1
) {
val backStackEntry = remember(it) {
appState.navController.getBackStackEntry(LoginConstant.ROUTE_STEP_1)
}
val loginViewModel: LoginViewModel = hiltViewModel(backStackEntry)
LoginScreen(appState = appState, viewModel = loginViewModel)
}

// TODO : 분리
composable(
route = LoginConstant.ROUTE_STEP_2
) {
val backStackEntry = remember(it) {
appState.navController.getBackStackEntry(LoginConstant.ROUTE)
}
val loginViewModel: LoginViewModel = hiltViewModel(backStackEntry)
OnBoardScreen(appState = appState, viewModel = loginViewModel)
}
loginMainDestination(appState = appState)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.main

import ac.dnd.bookkeeping.android.presentation.ui.main.login.LoginConstant

object LoginMainConstant {
const val ROUTE: String = "${LoginConstant.ROUTE}/main"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.main

import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable

fun NavGraphBuilder.loginMainDestination(
appState: ApplicationState
) {
composable(
route = LoginMainConstant.ROUTE
) {
LoginMainScreen(
appState = appState
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.main

import ac.dnd.bookkeeping.android.domain.model.error.ServerException

sealed interface LoginMainEvent {
sealed interface Login : LoginMainEvent {
data object Success : Login
data class Failure(val exception: ServerException) : Login
data class Error(val exception: Throwable) : Login
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login
package ac.dnd.bookkeeping.android.presentation.ui.main.login.main

import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver
import ac.dnd.bookkeeping.android.presentation.common.util.LaunchedEffectWithLifecycle
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.eventObserve
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.home.HomeConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.login.LoginConstant
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
Expand All @@ -12,31 +16,45 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle

@Composable
fun LoginScreen(
fun LoginMainScreen(
appState: ApplicationState,
viewModel: LoginViewModel = hiltViewModel()
viewModel: LoginMainViewModel = hiltViewModel()
) {

Observer(
appState = appState,
viewModel = viewModel
)

val nextStageState = remember { mutableStateOf(false) }
if (nextStageState.value) {
appState.navController.navigate(LoginConstant.ROUTE_STEP_2)
nextStageState.value = false
Screen(
appState = appState,
viewModel = viewModel
)
}

@Composable
private fun Screen(
appState: ApplicationState,
viewModel: LoginMainViewModel
) {
val state by viewModel.state.collectAsStateWithLifecycle()

fun navigateToLogin() {
appState.navController.navigate(HomeConstant.ROUTE) {
popUpTo(LoginConstant.ROUTE) {
inclusive = true
}
}
}

Box(
Expand All @@ -45,7 +63,7 @@ fun LoginScreen(
.background(color = Color.Black),
) {
Text(
text = "Login Screen",
text = "OnBoard Screen",
fontSize = 20.sp,
color = Color.White,
modifier = Modifier.align(Alignment.Center)
Expand All @@ -57,7 +75,7 @@ fun LoginScreen(
.padding(30.dp)
.fillMaxWidth()
.clickable {
nextStageState.value = true
navigateToLogin()
},
shape = RoundedCornerShape(10.dp),
color = Color.White
Expand All @@ -76,7 +94,31 @@ fun LoginScreen(
@Composable
private fun Observer(
appState: ApplicationState,
viewModel: LoginViewModel
viewModel: LoginMainViewModel
) {
ErrorObserver(viewModel)

fun login(event: LoginMainEvent.Login) {
when (event) {
LoginMainEvent.Login.Success -> {
// TODO : Implement Success Case
}

is LoginMainEvent.Login.Error -> {
// TODO : Implement Request Error Case
}

is LoginMainEvent.Login.Failure -> {
// TODO : Implement Internal Server Error Case
}
}
}

LaunchedEffectWithLifecycle(viewModel.event, viewModel.handler) {
viewModel.event.eventObserve { event ->
when (event) {
is LoginMainEvent.Login -> login(event)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.main

sealed interface LoginMainState {
data object Init : LoginMainState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.main

import ac.dnd.bookkeeping.android.presentation.common.base.BaseViewModel
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.asEventFlow
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject

@HiltViewModel
class LoginMainViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : BaseViewModel() {

private val _state: MutableStateFlow<LoginMainState> = MutableStateFlow(LoginMainState.Init)
val state: StateFlow<LoginMainState> = _state.asStateFlow()

private val _event: MutableEventFlow<LoginMainEvent> = MutableEventFlow()
val event: EventFlow<LoginMainEvent> = _event.asEventFlow()
}

0 comments on commit 1dbed24

Please sign in to comment.