AuthViewModel: Switch from livedata to stateflow
* Also make authdata init private Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -33,6 +33,7 @@ sealed class ViewState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class AuthState {
|
sealed class AuthState {
|
||||||
|
data object Init: AuthState()
|
||||||
data object Available : AuthState()
|
data object Available : AuthState()
|
||||||
data object Unavailable : AuthState()
|
data object Unavailable : AuthState()
|
||||||
data object SignedIn : AuthState()
|
data object SignedIn : AuthState()
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.net.UrlQuerySanitizer
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.aurora.extensions.hide
|
import com.aurora.extensions.hide
|
||||||
import com.aurora.extensions.show
|
import com.aurora.extensions.show
|
||||||
@@ -36,6 +37,8 @@ import com.aurora.store.util.Preferences.PREFERENCE_INTRO
|
|||||||
import com.aurora.store.view.ui.commons.BaseFragment
|
import com.aurora.store.view.ui.commons.BaseFragment
|
||||||
import com.aurora.store.viewmodel.auth.AuthViewModel
|
import com.aurora.store.viewmodel.auth.AuthViewModel
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class SplashFragment : BaseFragment<FragmentSplashBinding>() {
|
class SplashFragment : BaseFragment<FragmentSplashBinding>() {
|
||||||
@@ -83,72 +86,70 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>() {
|
|||||||
binding.btnAnonymous.visibility = View.VISIBLE
|
binding.btnAnonymous.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initial status
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
updateStatus(getString(R.string.session_init))
|
viewModel.authState.collectLatest {
|
||||||
|
when (it) {
|
||||||
|
AuthState.Init -> updateStatus(getString(R.string.session_init))
|
||||||
|
|
||||||
viewModel.liveData.observe(viewLifecycleOwner) {
|
AuthState.Fetching -> {
|
||||||
when (it) {
|
updateStatus(getString(R.string.requesting_new_session))
|
||||||
AuthState.Fetching -> {
|
|
||||||
updateStatus(getString(R.string.requesting_new_session))
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthState.Valid -> {
|
|
||||||
val packageName = getPackageName()
|
|
||||||
if (packageName.isBlank()) {
|
|
||||||
navigateToDefaultTab()
|
|
||||||
} else {
|
|
||||||
requireArguments().remove("packageName")
|
|
||||||
findNavController().navigate(
|
|
||||||
SplashFragmentDirections.actionSplashFragmentToAppDetailsFragment(
|
|
||||||
packageName
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
AuthState.Available -> {
|
AuthState.Valid -> {
|
||||||
updateStatus(getString(R.string.session_verifying))
|
val packageName = getPackageName()
|
||||||
updateActionLayout(false)
|
if (packageName.isBlank()) {
|
||||||
}
|
navigateToDefaultTab()
|
||||||
|
} else {
|
||||||
AuthState.Unavailable -> {
|
requireArguments().remove("packageName")
|
||||||
updateStatus(getString(R.string.session_login))
|
findNavController().navigate(
|
||||||
updateActionLayout(true)
|
SplashFragmentDirections.actionSplashFragmentToAppDetailsFragment(
|
||||||
}
|
packageName
|
||||||
|
)
|
||||||
AuthState.SignedIn -> {
|
|
||||||
val packageName = getPackageName()
|
|
||||||
if (packageName.isBlank()) {
|
|
||||||
navigateToDefaultTab()
|
|
||||||
} else {
|
|
||||||
requireArguments().remove("packageName")
|
|
||||||
findNavController().navigate(
|
|
||||||
SplashFragmentDirections.actionSplashFragmentToAppDetailsFragment(
|
|
||||||
packageName
|
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
AuthState.SignedOut -> {
|
AuthState.Available -> {
|
||||||
updateStatus(getString(R.string.session_scrapped))
|
updateStatus(getString(R.string.session_verifying))
|
||||||
updateActionLayout(true)
|
updateActionLayout(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthState.Verifying -> {
|
AuthState.Unavailable -> {
|
||||||
updateStatus(getString(R.string.verifying_new_session))
|
updateStatus(getString(R.string.session_login))
|
||||||
}
|
updateActionLayout(true)
|
||||||
|
}
|
||||||
|
|
||||||
is AuthState.Failed -> {
|
AuthState.SignedIn -> {
|
||||||
updateStatus(it.status)
|
val packageName = getPackageName()
|
||||||
updateActionLayout(true)
|
if (packageName.isBlank()) {
|
||||||
resetActions()
|
navigateToDefaultTab()
|
||||||
|
} else {
|
||||||
|
requireArguments().remove("packageName")
|
||||||
|
findNavController().navigate(
|
||||||
|
SplashFragmentDirections.actionSplashFragmentToAppDetailsFragment(
|
||||||
|
packageName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthState.SignedOut -> {
|
||||||
|
updateStatus(getString(R.string.session_scrapped))
|
||||||
|
updateActionLayout(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthState.Verifying -> {
|
||||||
|
updateStatus(getString(R.string.verifying_new_session))
|
||||||
|
}
|
||||||
|
|
||||||
|
is AuthState.Failed -> {
|
||||||
|
updateStatus(it.status)
|
||||||
|
updateActionLayout(true)
|
||||||
|
resetActions()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check authentication status
|
|
||||||
viewModel.observe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateStatus(string: String?) {
|
private fun updateStatus(string: String?) {
|
||||||
@@ -167,14 +168,14 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>() {
|
|||||||
|
|
||||||
private fun attachActions() {
|
private fun attachActions() {
|
||||||
binding.btnAnonymous.addOnClickListener {
|
binding.btnAnonymous.addOnClickListener {
|
||||||
if (viewModel.liveData.value != AuthState.Fetching) {
|
if (viewModel.authState.value != AuthState.Fetching) {
|
||||||
binding.btnAnonymous.updateProgress(true)
|
binding.btnAnonymous.updateProgress(true)
|
||||||
viewModel.buildAnonymousAuthData()
|
viewModel.buildAnonymousAuthData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.btnGoogle.addOnClickListener {
|
binding.btnGoogle.addOnClickListener {
|
||||||
if (viewModel.liveData.value != AuthState.Fetching) {
|
if (viewModel.authState.value != AuthState.Fetching) {
|
||||||
binding.btnGoogle.updateProgress(true)
|
binding.btnGoogle.updateProgress(true)
|
||||||
findNavController().navigate(R.id.googleFragment)
|
findNavController().navigate(R.id.googleFragment)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ package com.aurora.store.viewmodel.auth
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.aurora.Constants
|
import com.aurora.Constants
|
||||||
@@ -40,6 +39,8 @@ import com.aurora.store.util.Preferences
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.net.ConnectException
|
import java.net.ConnectException
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
@@ -55,21 +56,15 @@ class AuthViewModel @Inject constructor(
|
|||||||
|
|
||||||
private val TAG = AuthViewModel::class.java.simpleName
|
private val TAG = AuthViewModel::class.java.simpleName
|
||||||
|
|
||||||
val liveData: MutableLiveData<AuthState> = MutableLiveData()
|
private val _authState: MutableStateFlow<AuthState> = MutableStateFlow(AuthState.Init)
|
||||||
|
val authState = _authState.asStateFlow()
|
||||||
|
|
||||||
fun observe() {
|
init {
|
||||||
if (liveData.value != AuthState.Fetching) {
|
updateAuthState()
|
||||||
if (AccountProvider.isLoggedIn(context)) {
|
|
||||||
liveData.postValue(AuthState.Available)
|
|
||||||
buildSavedAuthData()
|
|
||||||
} else {
|
|
||||||
liveData.postValue(AuthState.Unavailable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildGoogleAuthData(email: String, token: String, tokenType: AuthHelper.Token) {
|
fun buildGoogleAuthData(email: String, token: String, tokenType: AuthHelper.Token) {
|
||||||
liveData.postValue(AuthState.Fetching)
|
_authState.value = AuthState.Fetching
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
verifyAndSaveAuth(
|
verifyAndSaveAuth(
|
||||||
@@ -77,16 +72,15 @@ class AuthViewModel @Inject constructor(
|
|||||||
AccountType.GOOGLE
|
AccountType.GOOGLE
|
||||||
)
|
)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
liveData.postValue(
|
_authState.value =
|
||||||
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
||||||
)
|
|
||||||
Log.e(TAG, "Failed to generate Session", exception)
|
Log.e(TAG, "Failed to generate Session", exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildAnonymousAuthData() {
|
fun buildAnonymousAuthData() {
|
||||||
liveData.postValue(AuthState.Fetching)
|
_authState.value = AuthState.Fetching
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
verifyAndSaveAuth(
|
verifyAndSaveAuth(
|
||||||
@@ -95,7 +89,7 @@ class AuthViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.e(TAG, "Failed to generate Session", exception)
|
Log.e(TAG, "Failed to generate Session", exception)
|
||||||
liveData.postValue(AuthState.Failed(exception.message.toString()))
|
_authState.value = AuthState.Failed(exception.message.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,11 +119,22 @@ class AuthViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateAuthState() {
|
||||||
|
if (_authState.value != AuthState.Fetching) {
|
||||||
|
if (AccountProvider.isLoggedIn(context)) {
|
||||||
|
_authState.value = AuthState.Available
|
||||||
|
buildSavedAuthData()
|
||||||
|
} else {
|
||||||
|
_authState.value = AuthState.Unavailable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildSavedAuthData() {
|
private fun buildSavedAuthData() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
if (authProvider.isSavedAuthDataValid()) {
|
if (authProvider.isSavedAuthDataValid()) {
|
||||||
liveData.postValue(AuthState.Valid)
|
_authState.value = AuthState.Valid
|
||||||
} else {
|
} else {
|
||||||
// Generate and validate new auth
|
// Generate and validate new auth
|
||||||
when (AccountProvider.getAccountType(context)) {
|
when (AccountProvider.getAccountType(context)) {
|
||||||
@@ -152,13 +157,13 @@ class AuthViewModel @Inject constructor(
|
|||||||
is ConnectException -> context.getString(R.string.server_unreachable)
|
is ConnectException -> context.getString(R.string.server_unreachable)
|
||||||
else -> context.getString(R.string.bad_request)
|
else -> context.getString(R.string.bad_request)
|
||||||
}
|
}
|
||||||
liveData.postValue(AuthState.Failed(error))
|
_authState.value = AuthState.Failed(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyAndSaveAuth(authData: AuthData, accountType: AccountType) {
|
private fun verifyAndSaveAuth(authData: AuthData, accountType: AccountType) {
|
||||||
liveData.postValue(AuthState.Verifying)
|
_authState.value = AuthState.Verifying
|
||||||
if (authData.authToken.isNotEmpty() && authData.deviceConfigToken.isNotEmpty()) {
|
if (authData.authToken.isNotEmpty() && authData.deviceConfigToken.isNotEmpty()) {
|
||||||
authProvider.saveAuthData(authData)
|
authProvider.saveAuthData(authData)
|
||||||
AccountProvider.login(
|
AccountProvider.login(
|
||||||
@@ -168,13 +173,12 @@ class AuthViewModel @Inject constructor(
|
|||||||
if (authData.aasToken.isBlank()) AuthHelper.Token.AUTH else AuthHelper.Token.AAS,
|
if (authData.aasToken.isBlank()) AuthHelper.Token.AUTH else AuthHelper.Token.AAS,
|
||||||
accountType
|
accountType
|
||||||
)
|
)
|
||||||
liveData.postValue(AuthState.SignedIn)
|
_authState.value = AuthState.SignedIn
|
||||||
} else {
|
} else {
|
||||||
authProvider.removeAuthData(context)
|
authProvider.removeAuthData(context)
|
||||||
AccountProvider.logout(context)
|
AccountProvider.logout(context)
|
||||||
liveData.postValue(
|
_authState.value =
|
||||||
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user