Adds login type handling to SoftLogoutController

This commit is contained in:
ericdecanini 2022-03-04 14:51:39 +01:00
parent 2fda593c3c
commit 92f87a3a5a
3 changed files with 78 additions and 58 deletions

View file

@ -19,7 +19,9 @@ package im.vector.app.features.signout.soft
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Incomplete
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
@ -34,7 +36,7 @@ import im.vector.app.features.signout.soft.epoxy.loginRedButtonItem
import im.vector.app.features.signout.soft.epoxy.loginTextItem import im.vector.app.features.signout.soft.epoxy.loginTextItem
import im.vector.app.features.signout.soft.epoxy.loginTitleItem import im.vector.app.features.signout.soft.epoxy.loginTitleItem
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
import timber.log.Timber import org.matrix.android.sdk.internal.auth.login.LoginType
import javax.inject.Inject import javax.inject.Inject
class SoftLogoutController @Inject constructor( class SoftLogoutController @Inject constructor(
@ -87,61 +89,74 @@ class SoftLogoutController @Inject constructor(
} }
} }
private fun buildForm(state: SoftLogoutViewState) { private fun buildForm(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest) {
is Incomplete -> buildLoadingItem()
is Fail -> buildLoginErrorWithRetryItem(state.asyncHomeServerLoginFlowRequest.error)
is Success -> buildLoginSuccessItem(state)
is Loading, Uninitialized -> Unit
}
private fun buildLoadingItem() {
loadingItem {
id("loading")
}
}
private fun buildLoginErrorWithRetryItem(error: Throwable) {
val host = this val host = this
when (state.asyncHomeServerLoginFlowRequest) { loginErrorWithRetryItem {
is Incomplete -> { id("errorRetry")
loadingItem { text(host.errorFormatter.toHumanReadable(error))
id("loading") listener { host.listener?.retry() }
} }
} }
is Fail -> {
loginErrorWithRetryItem { private fun buildLoginSuccessItem(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest.invoke()) {
id("errorRetry") LoginMode.Password -> buildLoginPasswordForm(state)
text(host.errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error)) is LoginMode.Sso -> buildLoginSSOForm()
listener { host.listener?.retry() } is LoginMode.SsoAndPassword -> disambiguateLoginSSOAndPasswordForm(state)
} LoginMode.Unsupported -> buildLoginUnsupportedForm()
} LoginMode.Unknown, null -> Unit // Should not happen
is Success -> { }
val loginMode = state.asyncHomeServerLoginFlowRequest.invoke()
Timber.i("Login Mode: $loginMode") private fun buildLoginPasswordForm(state: SoftLogoutViewState) {
when (state.asyncHomeServerLoginFlowRequest.invoke()) { val host = this
LoginMode.Password -> { loginPasswordFormItem {
loginPasswordFormItem { id("passwordForm")
id("passwordForm") stringProvider(host.stringProvider)
stringProvider(host.stringProvider) passwordValue(state.enteredPassword)
passwordValue(state.enteredPassword) submitEnabled(state.enteredPassword.isNotEmpty())
submitEnabled(state.enteredPassword.isNotEmpty()) onPasswordEdited { host.listener?.passwordEdited(it) }
onPasswordEdited { host.listener?.passwordEdited(it) } errorText((state.asyncLoginAction as? Fail)?.error?.let { host.errorFormatter.toHumanReadable(it) })
errorText((state.asyncLoginAction as? Fail)?.error?.let { host.errorFormatter.toHumanReadable(it) }) forgetPasswordClickListener { host.listener?.forgetPasswordClicked() }
forgetPasswordClickListener { host.listener?.forgetPasswordClicked() } submitClickListener { host.listener?.submit() }
submitClickListener { host.listener?.submit() } }
} }
}
is LoginMode.Sso -> { private fun buildLoginSSOForm() {
loginCenterButtonItem { val host = this
id("sso") loginCenterButtonItem {
text(host.stringProvider.getString(R.string.login_signin_sso)) id("sso")
listener { host.listener?.signinFallbackSubmit() } text(host.stringProvider.getString(R.string.login_signin_sso))
} listener { host.listener?.signinFallbackSubmit() }
} }
is LoginMode.SsoAndPassword -> { }
loginCenterButtonItem {
id("sso") private fun disambiguateLoginSSOAndPasswordForm(state: SoftLogoutViewState) {
text(host.stringProvider.getString(R.string.login_signin_sso)) when (state.loginType) {
listener { host.listener?.signinFallbackSubmit() } LoginType.PASSWORD -> buildLoginPasswordForm(state)
} LoginType.SSO -> buildLoginSSOForm()
} LoginType.UNSUPPORTED -> buildLoginUnsupportedForm()
LoginMode.Unsupported -> { LoginType.UNKNOWN -> Unit
loginCenterButtonItem { }
id("fallback") }
text(host.stringProvider.getString(R.string.login_signin))
listener { host.listener?.signinFallbackSubmit() } private fun buildLoginUnsupportedForm() {
} val host = this
} loginCenterButtonItem {
LoginMode.Unknown -> Unit // Should not happen id("fallback")
} text(host.stringProvider.getString(R.string.login_signin))
} listener { host.listener?.signinFallbackSubmit() }
} }
} }

View file

@ -37,6 +37,7 @@ import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.auth.login.LoginType
import timber.log.Timber import timber.log.Timber
/** /**
@ -69,7 +70,8 @@ class SoftLogoutViewModel @AssistedInject constructor(
userId = userId, userId = userId,
deviceId = session.sessionParams.deviceId.orEmpty(), deviceId = session.sessionParams.deviceId.orEmpty(),
userDisplayName = session.getUser(userId)?.displayName ?: userId, userDisplayName = session.getUser(userId)?.displayName ?: userId,
hasUnsavedKeys = session.hasUnsavedKeys() hasUnsavedKeys = session.hasUnsavedKeys(),
loginType = session.sessionParams.loginType,
) )
} else { } else {
SoftLogoutViewState( SoftLogoutViewState(
@ -77,7 +79,8 @@ class SoftLogoutViewModel @AssistedInject constructor(
userId = "", userId = "",
deviceId = "", deviceId = "",
userDisplayName = "", userDisplayName = "",
hasUnsavedKeys = false hasUnsavedKeys = false,
loginType = LoginType.UNKNOWN,
) )
} }
} }

View file

@ -22,6 +22,7 @@ import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.login.LoginMode import im.vector.app.features.login.LoginMode
import org.matrix.android.sdk.internal.auth.login.LoginType
data class SoftLogoutViewState( data class SoftLogoutViewState(
val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized, val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized,
@ -31,7 +32,8 @@ data class SoftLogoutViewState(
val deviceId: String, val deviceId: String,
val userDisplayName: String, val userDisplayName: String,
val hasUnsavedKeys: Boolean, val hasUnsavedKeys: Boolean,
val enteredPassword: String = "" val loginType: LoginType,
val enteredPassword: String = "",
) : MavericksState { ) : MavericksState {
fun isLoading(): Boolean { fun isLoading(): Boolean {