Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] OnBoardingDestination 만들기 #13

Merged
merged 6 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ac.dnd.bookkeeping.android.presentation.ui.main.login
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.login.main.LoginMainConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.login.main.loginMainDestination
import ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding.loginOnBoardingDestination
import androidx.navigation.NavGraphBuilder
import androidx.navigation.navigation

Expand All @@ -13,6 +14,7 @@ fun NavGraphBuilder.loginNavGraph(
startDestination = LoginMainConstant.ROUTE,
route = LoginConstant.ROUTE
) {
loginOnBoardingDestination(appState = appState)
loginMainDestination(appState = appState)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

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

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

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.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable

fun NavGraphBuilder.loginOnBoardingDestination(
appState: ApplicationState
) {
composable(
route = LoginOnBoardingConstant.ROUTE
) {

val viewModel: LoginOnBoardingViewModel = hiltViewModel()

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

ErrorObserver(viewModel)

LoginOnBoardingScreen(
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.login.onboarding

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

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

class LoginOnBoardingModel(
val state: LoginOnBoardingState
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

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.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.home.HomeConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.login.LoginConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.rememberApplicationState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.CoroutineExceptionHandler

@Composable
fun LoginOnBoardingScreen(
appState: ApplicationState,
model: LoginOnBoardingModel,
event: EventFlow<LoginOnBoardingEvent>,
intent: (LoginOnBoardingIntent) -> Unit,
handler: CoroutineExceptionHandler
) {

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

Box(
modifier = Modifier
.fillMaxSize()
.background(color = Color.Black),
) {
Text(
text = "OnBoard Screen",
fontSize = 20.sp,
color = Color.White,
modifier = Modifier.align(Alignment.Center)
)

Surface(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(30.dp)
.fillMaxWidth()
.clickable {
intent(LoginOnBoardingIntent.OnClickNextStep)
},
shape = RoundedCornerShape(10.dp),
color = Color.White
) {
Text(
text = "next",
fontSize = 20.sp,
color = Color.Black,
textAlign = TextAlign.Center,
modifier = Modifier.padding(5.dp)
)
}
}

LaunchedEffectWithLifecycle(event, handler) {
event.eventObserve { event ->
when (event){
is LoginOnBoardingEvent.GoToNextStep ->{

}
else -> {

}
}
}
}
}

@Preview
@Composable
fun LoginOnBoardingScreenPreview() {
LoginOnBoardingScreen(
appState = rememberApplicationState(),
model = LoginOnBoardingModel(
state = LoginOnBoardingState.Init
),
event = MutableEventFlow(),
intent = {},
handler = CoroutineExceptionHandler { _, _ -> }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

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

sealed interface LoginOnBoardingState {
data object Init : LoginOnBoardingState
sealed interface Loading : LoginOnBoardingEvent {
data object Success : Loading
data class Failure(val exception: ServerException) : Loading
data class Error(val exception: Throwable) : Loading
}
Comment on lines +7 to +11
Copy link
Collaborator

Choose a reason for hiding this comment

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

State 는 Init Loading 으로 충분할 것 같아요. 이거 아마 실제 사용해보시면 감이 오실 것 같아요

나중에 제가 state, event, intent 사용하는 샘플코드를 하나 작성해서 보여드릴게요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

호옹 감사합니다

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

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 LoginOnBoardingViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : BaseViewModel() {

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

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

fun onIntent(intent: LoginOnBoardingIntent) {
when (intent) {
is LoginOnBoardingIntent.OnClickNextStep -> {
launch {
_event.emit(LoginOnBoardingEvent.GoToNextStep)
}
}
}
}
}
Loading