Login screens: persist login mode

This commit is contained in:
Benoit Marty 2019-11-27 10:04:41 +01:00
parent fbde8d7d18
commit e532d97ec1
7 changed files with 43 additions and 42 deletions

View File

@ -212,11 +212,11 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
}
SignMode.SignIn -> {
// It depends on the LoginMode
when (val loginMode = state.asyncHomeServerLoginFlowRequest.invoke()) {
null -> error("Developer error")
LoginMode.Password -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginFragment::class.java, tag = FRAGMENT_LOGIN_TAG)
LoginMode.Sso -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
is LoginMode.Unsupported -> onLoginModeNotSupported(loginMode)
when (state.loginMode) {
LoginMode.Unknown -> error("Developer error")
LoginMode.Password -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginFragment::class.java, tag = FRAGMENT_LOGIN_TAG)
LoginMode.Sso -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes)
}
}
}
@ -233,10 +233,10 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
.show()
}
private fun onLoginModeNotSupported(unsupportedLoginMode: LoginMode.Unsupported) {
private fun onLoginModeNotSupported(supportedTypes: List<String>) {
AlertDialog.Builder(this)
.setTitle(R.string.app_name)
.setMessage(getString(R.string.login_mode_not_supported, unsupportedLoginMode.types.joinToString { "'$it'" }))
.setMessage(getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" }))
.setPositiveButton(R.string.yes) { _, _ ->
addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
}

View File

@ -16,8 +16,9 @@
package im.vector.riotx.features.login
sealed class LoginMode {
object Password : LoginMode()
object Sso : LoginMode()
data class Unsupported(val types: List<String>) : LoginMode()
enum class LoginMode {
Unknown,
Password,
Sso,
Unsupported
}

View File

@ -22,7 +22,6 @@ import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.transition.TransitionInflater
import butterknife.OnClick
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.withState
import im.vector.riotx.R
import im.vector.riotx.core.error.ErrorFormatter
@ -129,11 +128,9 @@ class LoginServerSelectionFragment @Inject constructor(
override fun updateWithState(state: LoginViewState) {
updateSelectedChoice(state)
when (state.asyncHomeServerLoginFlowRequest) {
is Success -> {
// LoginFlow for matrix.org has been retrieved
loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved)
}
if (state.loginMode != LoginMode.Unknown) {
// LoginFlow for matrix.org has been retrieved
loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved)
}
}
}

View File

@ -22,7 +22,6 @@ import android.view.View
import android.view.inputmethod.EditorInfo
import androidx.core.view.isVisible
import butterknife.OnClick
import com.airbnb.mvrx.Success
import com.jakewharton.rxbinding3.widget.textChanges
import im.vector.riotx.R
import im.vector.riotx.core.error.ErrorFormatter
@ -128,11 +127,9 @@ class LoginServerUrlFormFragment @Inject constructor(
override fun updateWithState(state: LoginViewState) {
setupUi(state)
when (state.asyncHomeServerLoginFlowRequest) {
is Success -> {
// The home server url is valid
loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved)
}
if (state.loginMode != LoginMode.Unknown) {
// The home server url is valid
loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved)
}
}
}

View File

@ -59,7 +59,7 @@ class LoginSignUpSignInSelectionFragment @Inject constructor(
}
private fun setupButtons(state: LoginViewState) {
isSsoSignIn = state.asyncHomeServerLoginFlowRequest.invoke() == LoginMode.Sso
isSsoSignIn = state.loginMode == LoginMode.Sso
if (isSsoSignIn) {
loginSignupSigninSubmit.text = getString(R.string.login_signin_sso)

View File

@ -260,7 +260,9 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
setState {
copy(
asyncHomeServerLoginFlowRequest = Uninitialized,
homeServerUrl = null
homeServerUrl = null,
loginMode = LoginMode.Unknown,
loginModeSupportedTypes = emptyList()
)
}
}
@ -275,7 +277,9 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
setState {
copy(
asyncHomeServerLoginFlowRequest = Uninitialized,
signMode = SignMode.Unknown
signMode = SignMode.Unknown,
loginMode = LoginMode.Unknown,
loginModeSupportedTypes = emptyList()
)
}
}
@ -499,11 +503,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
if (homeServerConnectionConfig == null) {
// This is invalid
setState {
copy(
asyncHomeServerLoginFlowRequest = Fail(Throwable("Bad format"))
)
}
_viewEvents.post(LoginViewEvents.Error(Throwable("Unable to create a HomeServerConnectionConfig")))
} else {
currentTask?.cancel()
currentTask = null
@ -531,12 +531,9 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
is LoginFlowResult.Success -> {
val loginMode = when {
// SSO login is taken first
data.loginFlowResponse.flows.any { it.type == LoginFlowTypes.SSO } ->
LoginMode.Sso
data.loginFlowResponse.flows.any { it.type == LoginFlowTypes.PASSWORD } ->
LoginMode.Password
else ->
LoginMode.Unsupported(data.loginFlowResponse.flows.mapNotNull { it.type }.toList())
data.loginFlowResponse.flows.any { it.type == LoginFlowTypes.SSO } -> LoginMode.Sso
data.loginFlowResponse.flows.any { it.type == LoginFlowTypes.PASSWORD } -> LoginMode.Password
else -> LoginMode.Unsupported
}
if (loginMode == LoginMode.Password && !data.isLoginAndRegistrationSupported) {
@ -544,8 +541,10 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
} else {
setState {
copy(
asyncHomeServerLoginFlowRequest = Success(loginMode),
homeServerUrl = action.homeServerUrl
asyncHomeServerLoginFlowRequest = Uninitialized,
homeServerUrl = action.homeServerUrl,
loginMode = loginMode,
loginModeSupportedTypes = data.loginFlowResponse.flows.mapNotNull { it.type }.toList()
)
}
}

View File

@ -20,12 +20,12 @@ import com.airbnb.mvrx.*
data class LoginViewState(
val asyncLoginAction: Async<Unit> = Uninitialized,
val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized,
val asyncHomeServerLoginFlowRequest: Async<Unit> = Uninitialized,
val asyncResetPassword: Async<Unit> = Uninitialized,
val asyncResetMailConfirmed: Async<Unit> = Uninitialized,
val asyncRegistration: Async<Unit> = Uninitialized,
// User choice
// User choices
@PersistState
val serverType: ServerType = ServerType.MatrixOrg,
@PersistState
@ -33,7 +33,14 @@ data class LoginViewState(
@PersistState
val resetPasswordEmail: String? = null,
@PersistState
val homeServerUrl: String? = null
val homeServerUrl: String? = null,
// Network result
@PersistState
val loginMode: LoginMode = LoginMode.Unknown,
@PersistState
// Supported types for the login. We cannot use a sealed class for LoginType because it is not serializable
val loginModeSupportedTypes: List<String> = emptyList()
) : MvRxState {
fun isLoading(): Boolean {