Implement login/logout functionality

This commit is contained in:
Kirill Kamakin
2022-04-04 16:42:22 +05:00
parent f44f54522d
commit 468aa8c02a
26 changed files with 248 additions and 184 deletions

View File

@@ -4,8 +4,8 @@ import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import by.kirich1409.viewbindingdelegate.viewBinding
@@ -19,22 +19,15 @@ import timber.log.Timber
@AndroidEntryPoint
class AuthenticationFragment : Fragment(R.layout.fragment_authentication) {
private val binding by viewBinding(FragmentAuthenticationBinding::bind)
private val viewModel by viewModels<AuthenticationViewModel>()
private val viewModel by activityViewModels<AuthenticationViewModel>()
private val authStatuses by lazy { viewModel.authenticationStatuses() }
private val authStatusObserver = Observer<Boolean> { onAuthStatusChange(it) }
private fun onAuthStatusChange(isAuthenticated: Boolean) {
Timber.v("onAuthStatusChange() called with: isAuthenticated = $isAuthenticated")
if (isAuthenticated) {
authStatuses.removeObserver(authStatusObserver)
navigateToRecipes()
}
}
private val authStatuses: LiveData<AuthenticationState>
get() = viewModel.authenticationState
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Timber.v("onCreate() called with: savedInstanceState = $savedInstanceState")
authStatuses.observe(this, authStatusObserver)
authStatuses.observe(this, ::onAuthStatusChange)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -45,9 +38,11 @@ class AuthenticationFragment : Fragment(R.layout.fragment_authentication) {
getString(R.string.app_name)
}
private fun navigateToRecipes() {
Timber.v("navigateToRecipes() called")
findNavController().navigate(AuthenticationFragmentDirections.actionAuthenticationFragmentToRecipesFragment())
private fun onAuthStatusChange(isAuthenticated: AuthenticationState) {
Timber.v("onAuthStatusChange() called with: isAuthenticated = $isAuthenticated")
if (isAuthenticated == AuthenticationState.AUTHORIZED) {
findNavController().popBackStack()
}
}
private fun onLoginClicked(): Unit = with(binding) {

View File

@@ -0,0 +1,26 @@
package gq.kirmanak.mealient.ui.auth
import timber.log.Timber
enum class AuthenticationState {
AUTHORIZED,
AUTH_REQUESTED,
UNAUTHORIZED;
companion object {
fun determineState(
isLoginRequested: Boolean,
isAuthorized: Boolean,
): AuthenticationState {
Timber.v("determineState() called with: isLoginRequested = $isLoginRequested, isAuthorized = $isAuthorized")
val result = when {
isAuthorized -> AUTHORIZED
isLoginRequested -> AUTH_REQUESTED
else -> UNAUTHORIZED
}
Timber.v("determineState() returned: $result")
return result
}
}
}

View File

@@ -3,7 +3,8 @@ package gq.kirmanak.mealient.ui.auth
import androidx.lifecycle.*
import dagger.hilt.android.lifecycle.HiltViewModel
import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.recipes.RecipeRepo
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -11,9 +12,16 @@ import javax.inject.Inject
@HiltViewModel
class AuthenticationViewModel @Inject constructor(
private val authRepo: AuthRepo,
private val recipeRepo: RecipeRepo
) : ViewModel() {
private val loginRequestsFlow = MutableStateFlow(false)
val authenticationState: LiveData<AuthenticationState> = loginRequestsFlow.combine(
flow = authRepo.isAuthorizedFlow,
transform = AuthenticationState::determineState
).asLiveData()
val currentAuthenticationState: AuthenticationState
get() = checkNotNull(authenticationState.value) { "Auth state flow mustn't be null" }
fun authenticate(username: String, password: String): LiveData<Result<Unit>> {
Timber.v("authenticate() called with: username = $username, password = $password")
val result = MutableLiveData<Result<Unit>>()
@@ -31,16 +39,16 @@ class AuthenticationViewModel @Inject constructor(
return result
}
fun authenticationStatuses(): LiveData<Boolean> {
Timber.v("authenticationStatuses() called")
return authRepo.authenticationStatuses().asLiveData()
}
fun logout() {
Timber.v("logout() called")
viewModelScope.launch {
loginRequestsFlow.emit(false)
authRepo.logout()
recipeRepo.clearLocalData()
}
}
fun login() {
Timber.v("login() called")
viewModelScope.launch { loginRequestsFlow.emit(true) }
}
}