diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 73b632e351..b3bf87bab8 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -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(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) } } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt index 99a5c595e5..c9c5e05d57 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt @@ -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 = emptyList(), val knownCustomHomeServersUrls: List = 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 = emptyList(), ) : Parcelable @Parcelize diff --git a/vector/src/main/java/im/vector/app/features/onboarding/StartAuthenticationFlowUseCase.kt b/vector/src/main/java/im/vector/app/features/onboarding/StartAuthenticationFlowUseCase.kt new file mode 100644 index 0000000000..9c773923b4 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/StartAuthenticationFlowUseCase.kt @@ -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, + ) + + 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()) + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt index 2e9925516c..a032181e4d 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt @@ -37,7 +37,7 @@ abstract class AbstractSSOFtueAuthFragment : 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 : 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 : 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, diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt index f10ef68850..74c020223a 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt @@ -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() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt index 537adf977d..1f57c55206 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt @@ -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) +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt index f94a243cd9..f97470feb0 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt @@ -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) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt index e21210065b..a0b844f918 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt @@ -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( diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt index 67dafbd9c2..521dfe65cf 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt @@ -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() { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt index 74c98c0366..946f16a2e8 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt @@ -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, diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 104a37f256..c46d0ed5ee 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -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) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt index 7d8f19b1b0..853225b452 100755 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt @@ -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() } diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index a682d025b8..eee1a71d7e 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -392,6 +392,7 @@ class OnboardingViewModelTest { fakeUriFilenameResolver.instance, fakeRegisterActionHandler.instance, fakeDirectLoginUseCase.instance, + StartAuthenticationFlowUseCase(fakeAuthenticationService, FakeStringProvider().instance), FakeVectorOverrides() ) }