Skip to content
Snippets Groups Projects
Commit ab4e2757 authored by Kamal Bramwell's avatar Kamal Bramwell
Browse files

Replaced LiveData with StateFlow

parent 10477513
No related branches found
No related tags found
No related merge requests found
package io.xxlabs.messenger.start.model
data class AppState(
val userState: UserState,
val versionState: VersionState
)
\ No newline at end of file
package io.xxlabs.messenger.start.model package io.xxlabs.messenger.start.model
enum class AppVersionStatus { enum class UserState {
Ok, UpdateRecommended, UpdateRequired NewUser, ExistingUser
} }
package io.xxlabs.messenger.start.model
import io.xxlabs.messenger.start.ui.VersionAlertUi
sealed class VersionState
class Checking: VersionState()
class VersionOk : VersionState()
class UpdateRecommended(val alertUi: VersionAlertUi) : VersionState()
class UpdateRequired(val alertUi: VersionAlertUi) : VersionState()
\ No newline at end of file
...@@ -9,6 +9,9 @@ import androidx.core.view.ViewCompat ...@@ -9,6 +9,9 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import io.elixxir.feature.home.MainActivity import io.elixxir.feature.home.MainActivity
import io.elixxir.feature.home.MainActivity.Companion.INTENT_INVITATION import io.elixxir.feature.home.MainActivity.Companion.INTENT_INVITATION
import io.elixxir.feature.home.MainActivity.Companion.INTENT_NOTIFICATION_CLICK import io.elixxir.feature.home.MainActivity.Companion.INTENT_NOTIFICATION_CLICK
...@@ -16,6 +19,8 @@ import io.xxlabs.messenger.R ...@@ -16,6 +19,8 @@ import io.xxlabs.messenger.R
import io.elixxir.feature.registration.registration.RegistrationFlowActivity import io.elixxir.feature.registration.registration.RegistrationFlowActivity
import io.elixxir.core.ui.util.getTransition import io.elixxir.core.ui.util.getTransition
import io.elixxir.core.ui.util.openLink import io.elixxir.core.ui.util.openLink
import io.xxlabs.messenger.start.model.*
import kotlinx.coroutines.launch
/** /**
* The app entry point when initially launched. Has no UI. * The app entry point when initially launched. Has no UI.
...@@ -29,6 +34,13 @@ class ColdStartActivity : AppCompatActivity() { ...@@ -29,6 +34,13 @@ class ColdStartActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
observeState()
}
}
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
hideSystemBars() hideSystemBars()
...@@ -83,44 +95,29 @@ class ColdStartActivity : AppCompatActivity() { ...@@ -83,44 +95,29 @@ class ColdStartActivity : AppCompatActivity() {
} }
} }
override fun onStart() { private fun observeState() {
super.onStart() lifecycleScope.launch {
observeUi() viewModel.appState.collect {
with(it) {
when (versionState) {
is VersionOk -> {
if (userState == UserState.NewUser) navigateToRegistration()
else navigateToMain()
} }
is UpdateRecommended -> showAlert(versionState.alertUi)
private fun observeUi() { is UpdateRequired -> showAlert(versionState.alertUi)
viewModel.navigateToRegistration.observe(this) { go -> else -> {}
if (go) {
navigateToRegistration()
viewModel.onNavigationHandled()
} }
} }
viewModel.navigateToMain.observe(this) { go ->
if (go) {
navigateToMain()
viewModel.onNavigationHandled()
} }
} }
viewModel.versionAlert.observe(this) { alert -> lifecycleScope.launch {
alert?.let { viewModel.launchUrl.collect {
showAlert(it) it?.let {
viewModel.onVersionAlertShown() openLink(it)
} }
} }
viewModel.error.observe(this) { error ->
error?.let {
showError(error)
}
}
viewModel.navigateToUrl.observe(this) { url ->
url?.let {
openLink(url)
viewModel.onUrlHandled()
}
} }
} }
...@@ -147,10 +144,10 @@ class ColdStartActivity : AppCompatActivity() { ...@@ -147,10 +144,10 @@ class ColdStartActivity : AppCompatActivity() {
} }
private fun showAlert(alertUi: VersionAlertUi) { private fun showAlert(alertUi: VersionAlertUi) {
TODO()
} }
private fun showError(error: String) { private fun showError(error: String) {
TODO()
} }
} }
\ No newline at end of file
...@@ -3,12 +3,16 @@ package io.xxlabs.messenger.start.ui ...@@ -3,12 +3,16 @@ package io.xxlabs.messenger.start.ui
import androidx.lifecycle.* import androidx.lifecycle.*
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import io.elixxir.core.logging.NotExposedYet
import io.elixxir.core.logging.log import io.elixxir.core.logging.log
import io.elixxir.core.preferences.PreferencesRepository import io.elixxir.core.preferences.PreferencesRepository
import io.xxlabs.messenger.start.model.VersionData import io.elixxir.core.ui.model.UiText
import io.xxlabs.messenger.R
import io.xxlabs.messenger.start.model.*
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
...@@ -19,20 +23,16 @@ class ColdStartViewModel( ...@@ -19,20 +23,16 @@ class ColdStartViewModel(
private val preferences: PreferencesRepository private val preferences: PreferencesRepository
) : ViewModel() { ) : ViewModel() {
val navigateToRegistration: LiveData<Boolean> by ::_navigateToRegistration private val _appState = MutableStateFlow(
private val _navigateToRegistration = MutableLiveData(false) AppState(userState, Checking())
)
val appState = _appState.asStateFlow()
val navigateToMain: LiveData<Boolean> by ::_navigateToMain private val _launchUrl = MutableSharedFlow<String?>()
private val _navigateToMain = MutableLiveData(false) val launchUrl = _launchUrl.asSharedFlow()
val versionAlert: LiveData<VersionAlertUi?> by ::_versionAlert private val userState: UserState
private val _versionAlert = MutableLiveData<VersionAlertUi?>(null) get() = if (userExists()) UserState.ExistingUser else UserState.NewUser
val error: LiveData<String?> by ::_error
private val _error = MutableLiveData<String?>(null)
val navigateToUrl: LiveData<String?> by ::_navigateToUrl
private val _navigateToUrl = MutableLiveData<String?>(null)
init { init {
initializeApp() initializeApp()
...@@ -43,18 +43,23 @@ class ColdStartViewModel( ...@@ -43,18 +43,23 @@ class ColdStartViewModel(
maybeClearData() maybeClearData()
// fetchCommonErrors() // fetchCommonErrors()
// parseJson(downloadRegistrationJson()) // parseJson(downloadRegistrationJson())
versionOk() _appState.emit(
AppState(
userState = userState,
versionState = VersionOk()
)
)
} }
} }
fun userExists(): Boolean = preferences.doesUserExist()
private suspend fun maybeClearData(): Boolean{ private suspend fun maybeClearData(): Boolean{
return if (!userExists()) { return if (!userExists()) {
clearAppDataAsync().await() clearAppDataAsync().await()
} else true } else true
} }
fun userExists(): Boolean = preferences.doesUserExist()
private fun clearAppDataAsync() : Deferred<Boolean> { private fun clearAppDataAsync() : Deferred<Boolean> {
return viewModelScope.async { return viewModelScope.async {
File("Session folder").apply { File("Session folder").apply {
...@@ -70,14 +75,14 @@ class ColdStartViewModel( ...@@ -70,14 +75,14 @@ class ColdStartViewModel(
} }
private fun fetchCommonErrors() { private fun fetchCommonErrors() {
TODO() NotExposedYet()
} }
private fun downloadRegistrationJson(): JsonObject { private fun downloadRegistrationJson(): JsonObject {
TODO() NotExposedYet()
} }
private fun parseJson(json: JsonElement) { private fun parseJson(json: JsonElement): VersionState {
val registrationWrapper = VersionData.from(json) val registrationWrapper = VersionData.from(json)
val appVersion = registrationWrapper.appVersion val appVersion = registrationWrapper.appVersion
val minVersion = registrationWrapper.minVersion val minVersion = registrationWrapper.minVersion
...@@ -85,61 +90,59 @@ class ColdStartViewModel( ...@@ -85,61 +90,59 @@ class ColdStartViewModel(
val downloadUrl = registrationWrapper.downloadUrl val downloadUrl = registrationWrapper.downloadUrl
val popupMessage = registrationWrapper.minPopupMessage val popupMessage = registrationWrapper.minPopupMessage
when { return when {
appVersion < minVersion -> updateRequiredAlert(popupMessage, downloadUrl) appVersion < minVersion -> updateRequired(popupMessage, downloadUrl)
appVersion >= minVersion && appVersion < recommendedVersion -> { appVersion >= minVersion && appVersion < recommendedVersion -> {
updateRecommendedAlert(downloadUrl) updateRecommended(downloadUrl)
} }
else -> versionOk() else -> VersionOk()
} }
} }
private fun updateRecommendedAlert(downloadUrl: String): VersionAlertUi { private fun updateRecommended(downloadUrl: String): VersionState {
TODO() return UpdateRecommended(
} VersionAlert(
title = UiText.StringResource(R.string.version_alert_update_recommended_title),
private fun updateRequiredAlert(message: String, downloadUrl: String): VersionAlertUi { body = UiText.StringResource(R.string.version_alert_update_recommended_subtitle),
TODO() positiveLabel = UiText.StringResource(R.string.version_alert_update_required_positive_label),
} negativeLabel = UiText.StringResource(R.string.version_alert_update_recommended_negative_label),
onPositiveClick = { onUpdateRequiredPositiveClick(downloadUrl) },
private fun versionOk() { onNegativeClick = ::onUpdateRecommendedNegativeClick,
_versionAlert.value = null onDismissed = ::onUpdateRecommendedDismissed,
determineNavigation() dismissable = true,
} downloadUrl = downloadUrl
)
private fun determineNavigation() { )
if (userExists()) { }
_navigateToMain.value = true
_navigateToRegistration.value = false private fun updateRequired(message: String, downloadUrl: String): VersionState {
} else { return UpdateRequired(
_navigateToRegistration.value = true VersionAlert(
_navigateToMain.value = false title = UiText.StringResource(R.string.version_alert_update_required_title),
} body = UiText.DynamicString(message),
} positiveLabel = UiText.StringResource(R.string.version_alert_update_required_positive_label),
negativeLabel = UiText.StringResource(R.string.version_alert_update_recommended_negative_label),
fun onNavigationHandled() { onPositiveClick = { onUpdateRequiredPositiveClick(downloadUrl) },
_navigateToMain.value = null onNegativeClick = { },
_navigateToRegistration.value = null onDismissed = { },
} dismissable = false,
downloadUrl = downloadUrl
fun onVersionAlertShown() { )
_versionAlert.value = null )
}
fun onUrlHandled() {
_navigateToUrl.value = null
} }
private fun onUpdateRecommendedPositiveClick(url: String) { private fun onUpdateRecommendedPositiveClick(url: String) {
_navigateToUrl.value = url viewModelScope.launch {
_launchUrl.emit(url)
}
} }
private fun onUpdateRecommendedNegativeClick() { private fun onUpdateRecommendedNegativeClick() {
determineNavigation() onUpdateRecommendedDismissed()
} }
private fun onUpdateRecommendedDismissed() { private fun onUpdateRecommendedDismissed() {
determineNavigation() _appState.value = AppState(userState, VersionOk())
} }
private fun onUpdateRequiredPositiveClick(url: String) { private fun onUpdateRequiredPositiveClick(url: String) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment