Use single UI state for activity

This commit is contained in:
Kirill Kamakin
2022-04-09 00:47:50 +05:00
parent 536c9765cb
commit e7620400b8
8 changed files with 56 additions and 45 deletions

View File

@@ -12,16 +12,14 @@ import com.google.android.material.shape.MaterialShapeDrawable
import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.databinding.MainActivityBinding
import gq.kirmanak.mealient.ui.auth.AuthenticationState
import gq.kirmanak.mealient.ui.auth.AuthenticationState.AUTHORIZED
import gq.kirmanak.mealient.ui.auth.AuthenticationState.UNAUTHORIZED
import timber.log.Timber
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: MainActivityBinding
private val viewModel by viewModels<MainActivityViewModel>()
private var lastAuthenticationState: AuthenticationState? = null
private val title: String by lazy { getString(R.string.app_name) }
private val uiState: MainActivityUiState get() = viewModel.uiState
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -31,7 +29,13 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(binding.toolbar)
supportActionBar?.setIcon(R.drawable.ic_toolbar)
setToolbarRoundCorner()
listenToAuthStatuses()
viewModel.uiStateLive.observe(this, ::onUiStateChange)
}
private fun onUiStateChange(uiState: MainActivityUiState) {
Timber.v("onUiStateChange() called with: uiState = $uiState")
supportActionBar?.title = if (uiState.titleVisible) title else null
invalidateOptionsMenu()
}
private fun setToolbarRoundCorner() {
@@ -51,22 +55,11 @@ class MainActivity : AppCompatActivity() {
}
}
private fun listenToAuthStatuses() {
Timber.v("listenToAuthStatuses() called")
viewModel.authenticationStateLive.observe(this, ::onAuthStateUpdate)
}
private fun onAuthStateUpdate(authState: AuthenticationState) {
Timber.v("onAuthStateUpdate() called with: it = $authState")
lastAuthenticationState = authState
invalidateOptionsMenu()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
Timber.v("onCreateOptionsMenu() called with: menu = $menu")
menuInflater.inflate(R.menu.main_toolbar, menu)
menu.findItem(R.id.logout).isVisible = lastAuthenticationState == AUTHORIZED
menu.findItem(R.id.login).isVisible = lastAuthenticationState == UNAUTHORIZED
menu.findItem(R.id.logout).isVisible = uiState.canShowLogout
menu.findItem(R.id.login).isVisible = uiState.canShowLogin
return true
}

View File

@@ -0,0 +1,13 @@
package gq.kirmanak.mealient.ui.activity
data class MainActivityUiState(
val loginButtonVisible: Boolean = false,
val titleVisible: Boolean = true,
val isAuthorized: Boolean = false,
) {
val canShowLogin: Boolean
get() = !isAuthorized && loginButtonVisible
val canShowLogout: Boolean
get() = isAuthorized && loginButtonVisible
}

View File

@@ -1,14 +1,10 @@
package gq.kirmanak.mealient.ui.activity
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.*
import dagger.hilt.android.lifecycle.HiltViewModel
import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.ui.auth.AuthenticationState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -18,16 +14,22 @@ class MainActivityViewModel @Inject constructor(
private val authRepo: AuthRepo,
) : ViewModel() {
private val showLoginButtonFlow = MutableStateFlow(false)
var showLoginButton: Boolean by showLoginButtonFlow::value
private val _uiState = MutableLiveData(MainActivityUiState())
val uiStateLive: LiveData<MainActivityUiState>
get() = _uiState.distinctUntilChanged()
var uiState: MainActivityUiState
get() = checkNotNull(_uiState.value) { "UiState must not be null" }
private set(value) = _uiState.postValue(value)
private val authenticationStateFlow = combine(
showLoginButtonFlow,
authRepo.isAuthorizedFlow,
AuthenticationState::determineState
)
val authenticationStateLive: LiveData<AuthenticationState>
get() = authenticationStateFlow.asLiveData()
init {
authRepo.isAuthorizedFlow
.onEach { isAuthorized -> updateUiState { it.copy(isAuthorized = isAuthorized) } }
.launchIn(viewModelScope)
}
fun updateUiState(updater: (MainActivityUiState) -> MainActivityUiState) {
uiState = updater(uiState)
}
fun logout() {
Timber.v("logout() called")