extracting the authentication start logic to a dedicated use case

- moves some of the homeserver specific state to the selectServer model
This commit is contained in:
Adam Brown 2022-04-01 15:21:04 +01:00
parent 51c294a6fc
commit f34df3997d
13 changed files with 150 additions and 129 deletions

View File

@ -47,7 +47,6 @@ import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import org.matrix.android.sdk.api.auth.login.LoginWizard
import org.matrix.android.sdk.api.auth.registration.FlowResult
import org.matrix.android.sdk.api.auth.registration.RegistrationResult
@ -75,6 +74,7 @@ class OnboardingViewModel @AssistedInject constructor(
private val uriFilenameResolver: UriFilenameResolver,
private val registrationActionHandler: RegistrationActionHandler,
private val directLoginUseCase: DirectLoginUseCase,
private val startAuthenticationFlowUseCase: StartAuthenticationFlowUseCase,
private val vectorOverrides: VectorOverrides
) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) {
@ -176,7 +176,7 @@ class OnboardingViewModel @AssistedInject constructor(
Timber.w("Url from config url was invalid: $configUrl")
continueToPageAfterSplash(onboardingFlow)
} else {
getLoginFlow(homeServerConnectionConfig, ServerType.Other)
startAuthenticationFlow(homeServerConnectionConfig, ServerType.Other)
}
} else {
continueToPageAfterSplash(onboardingFlow)
@ -203,7 +203,7 @@ class OnboardingViewModel @AssistedInject constructor(
is OnboardingAction.UpdateHomeServer -> {
currentHomeServerConnectionConfig
?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) }
?.let { getLoginFlow(it) }
?.let { startAuthenticationFlow(it) }
}
is OnboardingAction.LoginOrRegister ->
handleDirectLogin(
@ -292,11 +292,7 @@ class OnboardingViewModel @AssistedInject constructor(
when (action) {
OnboardingAction.ResetHomeServerType -> {
setState {
copy(
serverType = ServerType.Unknown
)
}
setState { copy(serverType = ServerType.Unknown) }
}
OnboardingAction.ResetHomeServerUrl -> {
viewModelScope.launch {
@ -304,10 +300,7 @@ class OnboardingViewModel @AssistedInject constructor(
setState {
copy(
isLoading = false,
serverSelectionState = ServerSelectionState(),
loginMode = LoginMode.Unknown,
serverType = ServerType.Unknown,
loginModeSupportedTypes = emptyList()
selectedHomeserver = SelectedHomeserverState(),
)
}
}
@ -317,8 +310,6 @@ class OnboardingViewModel @AssistedInject constructor(
copy(
isLoading = false,
signMode = SignMode.Unknown,
loginMode = LoginMode.Unknown,
loginModeSupportedTypes = emptyList()
)
}
}
@ -570,7 +561,7 @@ class OnboardingViewModel @AssistedInject constructor(
}
private fun handleWebLoginSuccess(action: OnboardingAction.WebLoginSuccess) = withState { state ->
val homeServerConnectionConfigFinal = homeServerConnectionConfigFactory.create(state.serverSelectionState.hostedUrl)
val homeServerConnectionConfigFinal = homeServerConnectionConfigFactory.create(state.selectedHomeserver.declaredUrl)
if (homeServerConnectionConfigFinal == null) {
// Should not happen
@ -593,93 +584,59 @@ class OnboardingViewModel @AssistedInject constructor(
// This is invalid
_viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig")))
} else {
getLoginFlow(homeServerConnectionConfig)
startAuthenticationFlow(homeServerConnectionConfig)
}
}
private fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig,
serverTypeOverride: ServerType? = null) {
private fun startAuthenticationFlow(homeServerConnectionConfig: HomeServerConnectionConfig, serverTypeOverride: ServerType? = null) {
currentHomeServerConnectionConfig = homeServerConnectionConfig
currentJob = viewModelScope.launch {
authenticationService.cancelPendingLoginOrRegistration()
setState { copy(isLoading = true) }
setState {
copy(
isLoading = true,
// If user has entered https://matrix.org, ensure that server type is ServerType.MatrixOrg
// It is also useful to set the value again in the case of a certificate error on matrix.org
serverType = if (homeServerConnectionConfig.homeServerUri.toString() == matrixOrgUrl) {
ServerType.MatrixOrg
} else {
serverTypeOverride ?: serverType
runCatching { startAuthenticationFlowUseCase.execute(homeServerConnectionConfig) }.fold(
onSuccess = {
rememberHomeServer(homeServerConnectionConfig.homeServerUri.toString())
if (it.isHomeserverOutdated) {
_viewEvents.post(OnboardingViewEvents.OutdatedHomeserver)
}
)
}
val data = try {
authenticationService.getLoginFlow(homeServerConnectionConfig)
} catch (failure: Throwable) {
setState {
copy(
isLoading = false,
// If we were trying to retrieve matrix.org login flow, also reset the serverType
serverType = if (serverType == ServerType.MatrixOrg) ServerType.Unknown else serverType
)
}
_viewEvents.post(OnboardingViewEvents.Failure(failure))
null
}
data ?: return@launch
// Valid Homeserver, add it to the history.
// Note: we add what the user has input, data.homeServerUrlBase can be different
rememberHomeServer(homeServerConnectionConfig.homeServerUri.toString())
val loginMode = when {
// SSO login is taken first
data.supportedLoginTypes.contains(LoginFlowTypes.SSO) &&
data.supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.SsoAndPassword(data.ssoIdentityProviders)
data.supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso(data.ssoIdentityProviders)
data.supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.Password
else -> LoginMode.Unsupported
}
setState {
copy(
serverSelectionState = serverSelectionState.copy(
description = when (data.homeServerUrl) {
matrixOrgUrl -> stringProvider.getString(R.string.ftue_auth_create_account_matrix_dot_org_server_description)
else -> null
},
userUrlInput = homeServerConnectionConfig.homeServerUri.toString(),
hostedUrl = data.homeServerUrl
),
isLoading = false,
loginMode = loginMode,
loginModeSupportedTypes = data.supportedLoginTypes.toList()
)
}
if ((loginMode == LoginMode.Password && !data.isLoginAndRegistrationSupported) ||
data.isOutdatedHomeserver) {
// Notify the UI
_viewEvents.post(OnboardingViewEvents.OutdatedHomeserver)
}
withState {
if (loginMode.supportsSignModeScreen()) {
when (it.onboardingFlow) {
OnboardingFlow.SignIn -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignIn))
OnboardingFlow.SignUp -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignUp))
OnboardingFlow.SignInSignUp,
null -> {
_viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved)
setState {
copy(
// If user has entered https://matrix.org, ensure that server type is ServerType.MatrixOrg
// It is also useful to set the value again in the case of a certificate error on matrix.org
serverType = if (homeServerConnectionConfig.homeServerUri.toString() == matrixOrgUrl) {
ServerType.MatrixOrg
} else {
serverTypeOverride ?: serverType
},
selectedHomeserver = it.serverSelectionState,
isLoading = false,
)
}
onAuthenticationStartedSuccess()
},
onFailure = {
setState { copy(isLoading = false) }
_viewEvents.post(OnboardingViewEvents.Failure(it))
}
)
}
}
private fun onAuthenticationStartedSuccess() {
withState {
if (it.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) {
when (it.onboardingFlow) {
OnboardingFlow.SignIn -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignIn))
OnboardingFlow.SignUp -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignUp))
OnboardingFlow.SignInSignUp,
null -> {
_viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved)
}
} else {
_viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved)
}
} else {
_viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved)
}
}
}

View File

@ -45,17 +45,11 @@ data class OnboardingViewState(
@PersistState
val deviceId: String? = null,
// Network result
@PersistState
val loginMode: LoginMode = LoginMode.Unknown,
// Supported types for the login. We cannot use a sealed class for LoginType because it is not serializable
@PersistState
val loginModeSupportedTypes: List<String> = emptyList(),
val knownCustomHomeServersUrls: List<String> = emptyList(),
val isForceLoginFallbackEnabled: Boolean = false,
@PersistState
val serverSelectionState: ServerSelectionState = ServerSelectionState(),
val selectedHomeserver: SelectedHomeserverState = SelectedHomeserverState(),
@PersistState
val personalizationState: PersonalizationState = PersonalizationState()
@ -68,10 +62,13 @@ enum class OnboardingFlow {
}
@Parcelize
data class ServerSelectionState(
data class SelectedHomeserverState(
val description: String? = null,
val userUrlInput: String? = null,
val hostedUrl: String? = null,
val sourceUrl: String? = null,
val declaredUrl: String? = null,
val preferredLoginMode: LoginMode = LoginMode.Unknown,
// Supported types for the login. We cannot use a sealed class for LoginType because it is not serializable
val loginModeSupportedTypes: List<String> = emptyList(),
) : Parcelable
@Parcelize

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.onboarding
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ensureTrailingSlash
import im.vector.app.features.login.LoginMode
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import javax.inject.Inject
class StartAuthenticationFlowUseCase @Inject constructor(
private val authenticationService: AuthenticationService,
private val stringProvider: StringProvider
) {
data class Bar(
val isHomeserverOutdated: Boolean,
val serverSelectionState: SelectedHomeserverState,
val loginMode: LoginMode,
val supportedLoginTypes: List<String>,
)
suspend fun execute(config: HomeServerConnectionConfig): Bar {
authenticationService.cancelPendingLoginOrRegistration()
val authFlow = authenticationService.getLoginFlow(config)
val loginMode = when {
// SSO login is taken first
authFlow.supportedLoginTypes.contains(LoginFlowTypes.SSO) &&
authFlow.supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.SsoAndPassword(authFlow.ssoIdentityProviders)
authFlow.supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso(authFlow.ssoIdentityProviders)
authFlow.supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.Password
else -> LoginMode.Unsupported
}
val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
val selection = SelectedHomeserverState(
description = when (authFlow.homeServerUrl) {
matrixOrgUrl -> stringProvider.getString(R.string.ftue_auth_create_account_matrix_dot_org_server_description)
else -> null
},
sourceUrl = config.homeServerUri.toString(),
declaredUrl = authFlow.homeServerUrl,
preferredLoginMode = loginMode,
loginModeSupportedTypes = authFlow.supportedLoginTypes
)
val isOutdated = (loginMode == LoginMode.Password && !authFlow.isLoginAndRegistrationSupported) || authFlow.isOutdatedHomeserver
return Bar(isOutdated, selection, loginMode, authFlow.supportedLoginTypes.toList())
}
}

View File

@ -37,7 +37,7 @@ abstract class AbstractSSOFtueAuthFragment<VB : ViewBinding> : AbstractFtueAuthF
override fun onStart() {
super.onStart()
val hasSSO = withState(viewModel) { it.loginMode.hasSso() }
val hasSSO = withState(viewModel) { it.selectedHomeserver.preferredLoginMode.hasSso() }
if (hasSSO) {
val packageName = CustomTabsClient.getPackageName(requireContext(), null)
@ -67,7 +67,7 @@ abstract class AbstractSSOFtueAuthFragment<VB : ViewBinding> : AbstractFtueAuthF
override fun onStop() {
super.onStop()
val hasSSO = withState(viewModel) { it.loginMode.hasSso() }
val hasSSO = withState(viewModel) { it.selectedHomeserver.preferredLoginMode.hasSso() }
if (hasSSO) {
customTabsServiceConnection?.let { requireContext().unbindService(it) }
customTabsServiceConnection = null
@ -88,7 +88,7 @@ abstract class AbstractSSOFtueAuthFragment<VB : ViewBinding> : AbstractFtueAuthF
private fun prefetchIfNeeded() {
withState(viewModel) { state ->
if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) {
if (state.selectedHomeserver.preferredLoginMode.hasSso() && state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders().isNullOrEmpty()) {
// in this case we can prefetch (not other cases for privacy concerns)
viewModel.getSsoUrl(
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,

View File

@ -77,7 +77,7 @@ class FtueAuthCaptchaFragment @Inject constructor(
val mime = "text/html"
val encoding = "utf-8"
val homeServerUrl = state.serverSelectionState.hostedUrl ?: error("missing url of homeserver")
val homeServerUrl = state.selectedHomeserver.declaredUrl ?: error("missing url of homeserver")
views.loginCaptchaWevView.loadDataWithBaseURL(homeServerUrl, html, mime, encoding, null)
views.loginCaptchaWevView.requestLayout()

View File

@ -40,7 +40,6 @@ import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.databinding.FragmentFtueSignUpCombinedBinding
import im.vector.app.features.login.LoginMode
import im.vector.app.features.login.SSORedirectRouterActivity
import im.vector.app.features.login.ServerType
import im.vector.app.features.login.SocialLoginButtonsView
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewEvents
@ -168,8 +167,8 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
setupUi(state)
setupAutoFill()
views.selectedServerName.text = state.serverSelectionState.userUrlInput.toReducedUrl()
views.selectedServerDescription.text = state.serverSelectionState.description
views.selectedServerName.text = state.selectedHomeserver.sourceUrl.toReducedUrl()
views.selectedServerDescription.text = state.selectedHomeserver.description
if (state.isLoading) {
// Ensure password is hidden
@ -178,8 +177,8 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
}
private fun setupUi(state: OnboardingViewState) {
when (state.loginMode) {
is LoginMode.SsoAndPassword -> renderSsoProviders(state.deviceId, state.loginMode.ssoIdentityProviders)
when (state.selectedHomeserver.preferredLoginMode) {
is LoginMode.SsoAndPassword -> renderSsoProviders(state.deviceId, state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders)
else -> hideSsoProviders()
}
}
@ -208,6 +207,6 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
views.createAccountPasswordInput.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
}
}
}
private fun OnboardingViewState.isNumericOnlyUserIdForbidden() = serverType == ServerType.MatrixOrg
private fun OnboardingViewState.isNumericOnlyUserIdForbidden() = selectedHomeserver.sourceUrl == getString(R.string.matrix_org_server_url)
}

View File

@ -54,7 +54,7 @@ class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFt
}
override fun updateWithState(state: OnboardingViewState) {
val userUrlInput = state.serverSelectionState.userUrlInput?.toReducedUrlKeepingSchemaIfInsecure()
val userUrlInput = state.selectedHomeserver.sourceUrl?.toReducedUrlKeepingSchemaIfInsecure()
views.chooseServerInput.editText().setText(userUrlInput)
}

View File

@ -184,7 +184,7 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment<
ServerType.MatrixOrg -> {
views.loginServerIcon.isVisible = true
views.loginServerIcon.setImageResource(R.drawable.ic_logo_matrix_org)
views.loginTitle.text = getString(resId, state.serverSelectionState.userUrlInput.toReducedUrl())
views.loginTitle.text = getString(resId, state.selectedHomeserver.sourceUrl.toReducedUrl())
views.loginNotice.text = getString(R.string.login_server_matrix_org_text)
}
ServerType.EMS -> {
@ -195,16 +195,16 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment<
}
ServerType.Other -> {
views.loginServerIcon.isVisible = false
views.loginTitle.text = getString(resId, state.serverSelectionState.userUrlInput.toReducedUrl())
views.loginTitle.text = getString(resId, state.selectedHomeserver.sourceUrl.toReducedUrl())
views.loginNotice.text = getString(R.string.login_server_other_text)
}
ServerType.Unknown -> Unit /* Should not happen */
}
views.loginPasswordNotice.isVisible = false
if (state.loginMode is LoginMode.SsoAndPassword) {
if (state.selectedHomeserver.preferredLoginMode is LoginMode.SsoAndPassword) {
views.loginSocialLoginContainer.isVisible = true
views.loginSocialLoginButtons.ssoIdentityProviders = state.loginMode.ssoIdentityProviders?.sorted()
views.loginSocialLoginButtons.ssoIdentityProviders = state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders?.sorted()
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
override fun onProviderSelected(id: String?) {
viewModel.getSsoUrl(

View File

@ -59,7 +59,7 @@ class FtueAuthResetPasswordFragment @Inject constructor() : AbstractFtueAuthFrag
}
private fun setupUi(state: OnboardingViewState) {
views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.serverSelectionState.userUrlInput.toReducedUrl())
views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.selectedHomeserver.sourceUrl.toReducedUrl())
}
private fun setupSubmitButton() {

View File

@ -60,27 +60,27 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF
ServerType.MatrixOrg -> {
views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org)
views.loginSignupSigninServerIcon.isVisible = true
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.serverSelectionState.userUrlInput.toReducedUrl())
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.selectedHomeserver.sourceUrl.toReducedUrl())
views.loginSignupSigninText.text = getString(R.string.login_server_matrix_org_text)
}
ServerType.EMS -> {
views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services)
views.loginSignupSigninServerIcon.isVisible = true
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to_modular)
views.loginSignupSigninText.text = state.serverSelectionState.userUrlInput.toReducedUrl()
views.loginSignupSigninText.text = state.selectedHomeserver.sourceUrl.toReducedUrl()
}
ServerType.Other -> {
views.loginSignupSigninServerIcon.isVisible = false
views.loginSignupSigninTitle.text = getString(R.string.login_server_other_title)
views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.serverSelectionState.userUrlInput.toReducedUrl())
views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.selectedHomeserver.sourceUrl.toReducedUrl())
}
ServerType.Unknown -> Unit /* Should not happen */
}
when (state.loginMode) {
when (state.selectedHomeserver.preferredLoginMode) {
is LoginMode.SsoAndPassword -> {
views.loginSignupSigninSignInSocialLoginContainer.isVisible = true
views.loginSignupSigninSocialLoginButtons.ssoIdentityProviders = state.loginMode.ssoIdentityProviders()?.sorted()
views.loginSignupSigninSocialLoginButtons.ssoIdentityProviders = state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders()?.sorted()
views.loginSignupSigninSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
override fun onProviderSelected(id: String?) {
viewModel.getSsoUrl(
@ -101,7 +101,7 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF
}
private fun setupButtons(state: OnboardingViewState) {
when (state.loginMode) {
when (state.selectedHomeserver.preferredLoginMode) {
is LoginMode.Sso -> {
// change to only one button that is sign in with sso
views.loginSignupSigninSubmit.text = getString(R.string.login_signin_sso)
@ -115,7 +115,7 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF
}
private fun submit() = withState(viewModel) { state ->
if (state.loginMode is LoginMode.Sso) {
if (state.selectedHomeserver.preferredLoginMode is LoginMode.Sso) {
viewModel.getSsoUrl(
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
deviceId = state.deviceId,

View File

@ -306,18 +306,18 @@ class FtueAuthVariant(
private fun handleSignInSelected(state: OnboardingViewState) {
if (isForceLoginFallbackEnabled) {
onLoginModeNotSupported(state.loginModeSupportedTypes)
onLoginModeNotSupported(state.selectedHomeserver.loginModeSupportedTypes)
} else {
disambiguateLoginMode(state)
}
}
private fun disambiguateLoginMode(state: OnboardingViewState) = when (state.loginMode) {
private fun disambiguateLoginMode(state: OnboardingViewState) = when (state.selectedHomeserver.preferredLoginMode) {
LoginMode.Unknown,
is LoginMode.Sso -> error("Developer error")
is LoginMode.SsoAndPassword,
LoginMode.Password -> openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG)
LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes)
LoginMode.Unsupported -> onLoginModeNotSupported(state.selectedHomeserver.loginModeSupportedTypes)
}
private fun openAuthLoginFragmentWithTag(tag: String) {
@ -338,7 +338,7 @@ class FtueAuthVariant(
private fun handleSignInWithMatrixId(state: OnboardingViewState) {
if (isForceLoginFallbackEnabled) {
onLoginModeNotSupported(state.loginModeSupportedTypes)
onLoginModeNotSupported(state.selectedHomeserver.loginModeSupportedTypes)
} else {
openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG)
}

View File

@ -116,7 +116,7 @@ class FtueAuthTermsFragment @Inject constructor(
}
override fun updateWithState(state: OnboardingViewState) {
policyController.homeServer = state.serverSelectionState.userUrlInput.toReducedUrl()
policyController.homeServer = state.selectedHomeserver.sourceUrl.toReducedUrl()
renderState()
}

View File

@ -392,6 +392,7 @@ class OnboardingViewModelTest {
fakeUriFilenameResolver.instance,
fakeRegisterActionHandler.instance,
fakeDirectLoginUseCase.instance,
StartAuthenticationFlowUseCase(fakeAuthenticationService, FakeStringProvider().instance),
FakeVectorOverrides()
)
}