diff --git a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/navigation/AppNavigation.kt b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/navigation/AppNavigation.kt index f3fd7800..b49053e5 100644 --- a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/navigation/AppNavigation.kt +++ b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/navigation/AppNavigation.kt @@ -17,7 +17,7 @@ fun AppNavigation( ) { composable(AppDestination.Login) { LoginScreen( - navigator = { destination -> navController.navigate(destination) } + navigator = { destination -> navController.navigate(destination) } ) } composable(AppDestination.Home) { @@ -45,6 +45,14 @@ private fun NavGraphBuilder.composable( private fun NavHostController.navigate(destination: AppDestination) { when (destination) { is AppDestination.Up -> popBackStack() + is AppDestination.Home -> navigate( + route = destination.destination, + navOptions { + popUpTo( + route = AppDestination.Login.route + ) { inclusive = true } + } + ) else -> navigate(route = destination.destination) } } diff --git a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/home/HomeScreen.kt b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/home/HomeScreen.kt index 9aa3241a..fdd0f796 100644 --- a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/home/HomeScreen.kt +++ b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/home/HomeScreen.kt @@ -1,24 +1,30 @@ package vn.luongvo.kmm.survey.android.ui.screens.home -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.* +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color.Companion.White import androidx.compose.ui.tooling.preview.Preview import vn.luongvo.kmm.survey.android.ui.theme.ComposeTheme @Composable fun HomeScreen() { - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colors.background + Column( + modifier = Modifier.fillMaxSize() ) { - Text(text = "Home") + Text( + text = "Home", + color = White, + modifier = Modifier + .fillMaxSize() + .wrapContentSize() + ) } } -@Preview @Composable +@Preview(showSystemUi = true) fun HomeScreenPreview() { ComposeTheme { HomeScreen() diff --git a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginScreen.kt b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginScreen.kt index e0544cef..b158cd81 100644 --- a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginScreen.kt +++ b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginScreen.kt @@ -43,6 +43,7 @@ fun LoginScreen( var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } val isLoading by viewModel.isLoading.collectAsState() + val isLoggedIn by viewModel.isLoggedIn.collectAsState() val context = LocalContext.current LaunchedEffect(viewModel.error) { @@ -53,14 +54,20 @@ fun LoginScreen( viewModel.navigator.collect { destination -> navigator(destination) } } - LoginScreenContent( - email = email, - password = password, - onEmailChange = { email = it }, - onPasswordChange = { password = it }, - onLogInClick = { viewModel.logIn(email, password) }, - isLoading = isLoading - ) + LaunchedEffect(Unit) { + viewModel.init() + } + + if (isLoggedIn == false) { + LoginScreenContent( + email = email, + password = password, + onEmailChange = { email = it }, + onPasswordChange = { password = it }, + onLogInClick = { viewModel.logIn(email, password) }, + isLoading = isLoading + ) + } } @Composable diff --git a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginViewModel.kt b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginViewModel.kt index 3f5428b1..3133e5cc 100644 --- a/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginViewModel.kt +++ b/android/src/main/java/vn/luongvo/kmm/survey/android/ui/screens/login/LoginViewModel.kt @@ -4,12 +4,28 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.* import vn.luongvo.kmm.survey.android.ui.base.BaseViewModel import vn.luongvo.kmm.survey.android.ui.navigation.AppDestination +import vn.luongvo.kmm.survey.domain.usecase.IsLoggedInUseCase import vn.luongvo.kmm.survey.domain.usecase.LogInUseCase class LoginViewModel( + private val isLoggedInUseCase: IsLoggedInUseCase, private val logInUseCase: LogInUseCase ) : BaseViewModel() { + private val _isLoggedIn = MutableStateFlow(null) + val isLoggedIn: StateFlow = _isLoggedIn.asStateFlow() + + fun init() { + isLoggedInUseCase() + .onEach { isLoggedIn -> + _isLoggedIn.emit(isLoggedIn) + if (isLoggedIn) { + navigateToHome() + } + } + .launchIn(viewModelScope) + } + fun logIn(email: String, password: String) { logInUseCase( email = email, @@ -18,8 +34,13 @@ class LoginViewModel( .injectLoading() .catch { e -> _error.emit(e) } .onEach { - _navigator.emit(AppDestination.Home) + _isLoggedIn.emit(true) + navigateToHome() } .launchIn(viewModelScope) } + + private suspend fun navigateToHome() { + _navigator.emit(AppDestination.Home) + } } diff --git a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/data/repository/AuthRepositoryImpl.kt b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/data/repository/AuthRepositoryImpl.kt index 1cb862c3..7fb25529 100644 --- a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/data/repository/AuthRepositoryImpl.kt +++ b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/data/repository/AuthRepositoryImpl.kt @@ -1,6 +1,7 @@ package vn.luongvo.kmm.survey.data.repository import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf import vn.luongvo.kmm.survey.data.extensions.flowTransform import vn.luongvo.kmm.survey.data.local.datasource.TokenLocalDataSource import vn.luongvo.kmm.survey.data.remote.datasource.AuthRemoteDataSource @@ -23,4 +24,9 @@ class AuthRepositoryImpl( override fun saveToken(token: Token) { tokenLocalDataSource.saveToken(token) } + + override val isLoggedIn: Flow + get() = flowOf( + tokenLocalDataSource.tokenType.isNotBlank() && tokenLocalDataSource.accessToken.isNotBlank() + ) } diff --git a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/di/module/UseCaseModule.kt b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/di/module/UseCaseModule.kt index 61794743..9a65fa2a 100644 --- a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/di/module/UseCaseModule.kt +++ b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/di/module/UseCaseModule.kt @@ -3,9 +3,9 @@ package vn.luongvo.kmm.survey.di.module import org.koin.core.module.dsl.singleOf import org.koin.dsl.bind import org.koin.dsl.module -import vn.luongvo.kmm.survey.domain.usecase.LogInUseCase -import vn.luongvo.kmm.survey.domain.usecase.LogInUseCaseImpl +import vn.luongvo.kmm.survey.domain.usecase.* val useCaseModule = module { singleOf(::LogInUseCaseImpl) bind LogInUseCase::class + singleOf(::IsLoggedInUseCaseImpl) bind IsLoggedInUseCase::class } diff --git a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/repository/AuthRepository.kt b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/repository/AuthRepository.kt index 5a1ab539..cae4d511 100644 --- a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/repository/AuthRepository.kt +++ b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/repository/AuthRepository.kt @@ -8,4 +8,6 @@ interface AuthRepository { fun logIn(email: String, password: String): Flow fun saveToken(token: Token) + + val isLoggedIn: Flow } diff --git a/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/usecase/IsLoggedInUseCase.kt b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/usecase/IsLoggedInUseCase.kt new file mode 100644 index 00000000..05544152 --- /dev/null +++ b/shared/src/commonMain/kotlin/vn/luongvo/kmm/survey/domain/usecase/IsLoggedInUseCase.kt @@ -0,0 +1,16 @@ +package vn.luongvo.kmm.survey.domain.usecase + +import kotlinx.coroutines.flow.Flow +import vn.luongvo.kmm.survey.domain.repository.AuthRepository + +interface IsLoggedInUseCase { + + operator fun invoke(): Flow +} + +class IsLoggedInUseCaseImpl(private val repository: AuthRepository) : IsLoggedInUseCase { + + override operator fun invoke(): Flow { + return repository.isLoggedIn + } +}