renaming update homeserver to select homeserver

- should better reflect this steps mvoes the onboarding process forwards
This commit is contained in:
Adam Brown 2022-04-01 16:13:33 +01:00
parent f34df3997d
commit 1e520121ce
7 changed files with 66 additions and 57 deletions

View File

@ -29,7 +29,7 @@ sealed interface OnboardingAction : VectorViewModelAction {
data class OnIAlreadyHaveAnAccount(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction data class OnIAlreadyHaveAnAccount(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction
data class UpdateServerType(val serverType: ServerType) : OnboardingAction data class UpdateServerType(val serverType: ServerType) : OnboardingAction
data class UpdateHomeServer(val homeServerUrl: String) : OnboardingAction data class SelectHomeServer(val homeServerUrl: String) : OnboardingAction
data class UpdateUseCase(val useCase: FtueUseCase) : OnboardingAction data class UpdateUseCase(val useCase: FtueUseCase) : OnboardingAction
object ResetUseCase : OnboardingAction object ResetUseCase : OnboardingAction
data class UpdateSignMode(val signMode: SignMode) : OnboardingAction data class UpdateSignMode(val signMode: SignMode) : OnboardingAction

View File

@ -107,6 +107,7 @@ class OnboardingViewModel @AssistedInject constructor(
private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null
private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
private val defaultHomeserverUrl = matrixOrgUrl
private val registrationWizard: RegistrationWizard private val registrationWizard: RegistrationWizard
get() = authenticationService.getRegistrationWizard() get() = authenticationService.getRegistrationWizard()
@ -139,7 +140,7 @@ class OnboardingViewModel @AssistedInject constructor(
is OnboardingAction.UpdateServerType -> handleUpdateServerType(action) is OnboardingAction.UpdateServerType -> handleUpdateServerType(action)
is OnboardingAction.UpdateSignMode -> handleUpdateSignMode(action) is OnboardingAction.UpdateSignMode -> handleUpdateSignMode(action)
is OnboardingAction.InitWith -> handleInitWith(action) is OnboardingAction.InitWith -> handleInitWith(action)
is OnboardingAction.UpdateHomeServer -> handleUpdateHomeserver(action).also { lastAction = action } is OnboardingAction.SelectHomeServer -> handleSelectHomeserver(action).also { lastAction = action }
is OnboardingAction.LoginOrRegister -> handleLoginOrRegister(action).also { lastAction = action } is OnboardingAction.LoginOrRegister -> handleLoginOrRegister(action).also { lastAction = action }
is OnboardingAction.Register -> handleRegisterWith(action).also { lastAction = action } is OnboardingAction.Register -> handleRegisterWith(action).also { lastAction = action }
is OnboardingAction.LoginWithToken -> handleLoginWithToken(action) is OnboardingAction.LoginWithToken -> handleLoginWithToken(action)
@ -167,19 +168,19 @@ class OnboardingViewModel @AssistedInject constructor(
} }
setState { copy(onboardingFlow = onboardingFlow) } setState { copy(onboardingFlow = onboardingFlow) }
val configUrl = loginConfig?.homeServerUrl?.takeIf { it.isNotEmpty() } return when (val config = loginConfig.toHomeserverConfig()) {
if (configUrl != null) { null -> continueToPageAfterSplash(onboardingFlow)
// Use config from uri else -> startAuthenticationFlow(config, ServerType.Other)
val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(configUrl) }
if (homeServerConnectionConfig == null) { }
// Url is invalid, in this case, just use the regular flow
Timber.w("Url from config url was invalid: $configUrl") private fun LoginConfig?.toHomeserverConfig(): HomeServerConnectionConfig? {
continueToPageAfterSplash(onboardingFlow) return this?.homeServerUrl?.takeIf { it.isNotEmpty() }?.let { url ->
} else { homeServerConnectionConfigFactory.create(url).also {
startAuthenticationFlow(homeServerConnectionConfig, ServerType.Other) if (it == null) {
Timber.w("Url from config url was invalid: $url")
}
} }
} else {
continueToPageAfterSplash(onboardingFlow)
} }
} }
@ -200,7 +201,7 @@ class OnboardingViewModel @AssistedInject constructor(
// It happens when we get the login flow, or during direct authentication. // It happens when we get the login flow, or during direct authentication.
// So alter the homeserver config and retrieve again the login flow // So alter the homeserver config and retrieve again the login flow
when (val finalLastAction = lastAction) { when (val finalLastAction = lastAction) {
is OnboardingAction.UpdateHomeServer -> { is OnboardingAction.SelectHomeServer -> {
currentHomeServerConnectionConfig currentHomeServerConnectionConfig
?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) } ?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) }
?.let { startAuthenticationFlow(it) } ?.let { startAuthenticationFlow(it) }
@ -348,10 +349,7 @@ class OnboardingViewModel @AssistedInject constructor(
private fun handleUpdateUseCase(action: OnboardingAction.UpdateUseCase) { private fun handleUpdateUseCase(action: OnboardingAction.UpdateUseCase) {
setState { copy(useCase = action.useCase) } setState { copy(useCase = action.useCase) }
when (vectorFeatures.isOnboardingCombinedRegisterEnabled()) { when (vectorFeatures.isOnboardingCombinedRegisterEnabled()) {
true -> { true -> handle(OnboardingAction.SelectHomeServer(defaultHomeserverUrl))
handle(OnboardingAction.UpdateHomeServer(matrixOrgUrl))
OnboardingViewEvents.OpenCombinedRegister
}
false -> _viewEvents.post(OnboardingViewEvents.OpenServerSelection) false -> _viewEvents.post(OnboardingViewEvents.OpenServerSelection)
} }
} }
@ -371,7 +369,7 @@ class OnboardingViewModel @AssistedInject constructor(
ServerType.Unknown -> Unit /* Should not happen */ ServerType.Unknown -> Unit /* Should not happen */
ServerType.MatrixOrg -> ServerType.MatrixOrg ->
// Request login flow here // Request login flow here
handle(OnboardingAction.UpdateHomeServer(matrixOrgUrl)) handle(OnboardingAction.SelectHomeServer(matrixOrgUrl))
ServerType.EMS, ServerType.EMS,
ServerType.Other -> _viewEvents.post(OnboardingViewEvents.OnServerSelectionDone(action.serverType)) ServerType.Other -> _viewEvents.post(OnboardingViewEvents.OnServerSelectionDone(action.serverType))
} }
@ -578,7 +576,7 @@ class OnboardingViewModel @AssistedInject constructor(
} }
} }
private fun handleUpdateHomeserver(action: OnboardingAction.UpdateHomeServer) { private fun handleSelectHomeserver(action: OnboardingAction.SelectHomeServer) {
val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl) val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl)
if (homeServerConnectionConfig == null) { if (homeServerConnectionConfig == null) {
// This is invalid // This is invalid
@ -603,14 +601,8 @@ class OnboardingViewModel @AssistedInject constructor(
setState { setState {
copy( copy(
// If user has entered https://matrix.org, ensure that server type is ServerType.MatrixOrg serverType = alignServerTypeAfterSubmission(homeServerConnectionConfig, serverTypeOverride),
// It is also useful to set the value again in the case of a certificate error on matrix.org selectedHomeserver = it.selectedHomeserverState,
serverType = if (homeServerConnectionConfig.homeServerUri.toString() == matrixOrgUrl) {
ServerType.MatrixOrg
} else {
serverTypeOverride ?: serverType
},
selectedHomeserver = it.serverSelectionState,
isLoading = false, isLoading = false,
) )
} }
@ -624,6 +616,18 @@ class OnboardingViewModel @AssistedInject constructor(
} }
} }
/**
* 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
**/
private fun OnboardingViewState.alignServerTypeAfterSubmission(config: HomeServerConnectionConfig, serverTypeOverride: ServerType?): ServerType {
return if (config.homeServerUri.toString() == matrixOrgUrl) {
ServerType.MatrixOrg
} else {
serverTypeOverride ?: serverType
}
}
private fun onAuthenticationStartedSuccess() { private fun onAuthenticationStartedSuccess() {
withState { withState {
if (it.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) { if (it.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) {

View File

@ -68,7 +68,7 @@ data class SelectedHomeserverState(
val declaredUrl: String? = null, val declaredUrl: String? = null,
val preferredLoginMode: LoginMode = LoginMode.Unknown, val preferredLoginMode: LoginMode = LoginMode.Unknown,
// Supported types for the login. We cannot use a sealed class for LoginType because it is not serializable // Supported types for the login. We cannot use a sealed class for LoginType because it is not serializable
val loginModeSupportedTypes: List<String> = emptyList(), val supportedLoginTypes: List<String> = emptyList(),
) : Parcelable ) : Parcelable
@Parcelize @Parcelize

View File

@ -22,6 +22,7 @@ import im.vector.app.core.utils.ensureTrailingSlash
import im.vector.app.features.login.LoginMode import im.vector.app.features.login.LoginMode
import org.matrix.android.sdk.api.auth.AuthenticationService 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.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.LoginFlowResult
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import javax.inject.Inject import javax.inject.Inject
@ -30,38 +31,42 @@ class StartAuthenticationFlowUseCase @Inject constructor(
private val stringProvider: StringProvider private val stringProvider: StringProvider
) { ) {
data class Bar( suspend fun execute(config: HomeServerConnectionConfig): StartAuthenticationResult {
val isHomeserverOutdated: Boolean,
val serverSelectionState: SelectedHomeserverState,
val loginMode: LoginMode,
val supportedLoginTypes: List<String>,
)
suspend fun execute(config: HomeServerConnectionConfig): Bar {
authenticationService.cancelPendingLoginOrRegistration() authenticationService.cancelPendingLoginOrRegistration()
val authFlow = authenticationService.getLoginFlow(config) val authFlow = authenticationService.getLoginFlow(config)
val preferredLoginMode = authFlow.findPreferredLoginMode()
val loginMode = when { val selection = createSelectedHomeserverState(authFlow, config, preferredLoginMode)
// SSO login is taken first val isOutdated = (preferredLoginMode == LoginMode.Password && !authFlow.isLoginAndRegistrationSupported) || authFlow.isOutdatedHomeserver
authFlow.supportedLoginTypes.contains(LoginFlowTypes.SSO) && return StartAuthenticationResult(isOutdated, selection, preferredLoginMode, authFlow.supportedLoginTypes.toList())
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
} }
private fun createSelectedHomeserverState(authFlow: LoginFlowResult, config: HomeServerConnectionConfig, preferredLoginMode: LoginMode): SelectedHomeserverState {
val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
val selection = SelectedHomeserverState( return SelectedHomeserverState(
description = when (authFlow.homeServerUrl) { description = when (authFlow.homeServerUrl) {
matrixOrgUrl -> stringProvider.getString(R.string.ftue_auth_create_account_matrix_dot_org_server_description) matrixOrgUrl -> stringProvider.getString(R.string.ftue_auth_create_account_matrix_dot_org_server_description)
else -> null else -> null
}, },
sourceUrl = config.homeServerUri.toString(), sourceUrl = config.homeServerUri.toString(),
declaredUrl = authFlow.homeServerUrl, declaredUrl = authFlow.homeServerUrl,
preferredLoginMode = loginMode, preferredLoginMode = preferredLoginMode,
loginModeSupportedTypes = authFlow.supportedLoginTypes supportedLoginTypes = authFlow.supportedLoginTypes
) )
val isOutdated = (loginMode == LoginMode.Password && !authFlow.isLoginAndRegistrationSupported) || authFlow.isOutdatedHomeserver
return Bar(isOutdated, selection, loginMode, authFlow.supportedLoginTypes.toList())
} }
private fun LoginFlowResult.findPreferredLoginMode() = when {
// SSO login is taken first
supportedLoginTypes.contains(LoginFlowTypes.SSO) &&
supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.SsoAndPassword(ssoIdentityProviders)
supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso(ssoIdentityProviders)
supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.Password
else -> LoginMode.Unsupported
}
data class StartAuthenticationResult(
val isHomeserverOutdated: Boolean,
val selectedHomeserverState: SelectedHomeserverState,
val loginMode: LoginMode,
val supportedLoginTypes: List<String>,
)
} }

View File

@ -45,7 +45,7 @@ class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFt
} }
views.chooseServerSubmit.debouncedClicks { views.chooseServerSubmit.debouncedClicks {
viewModel.handle(OnboardingAction.UpdateHomeServer(views.chooseServerInput.content())) viewModel.handle(OnboardingAction.SelectHomeServer(views.chooseServerInput.content()))
} }
} }

View File

@ -139,7 +139,7 @@ class FtueAuthServerUrlFormFragment @Inject constructor() : AbstractFtueAuthFrag
} }
else -> { else -> {
views.loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/) views.loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/)
viewModel.handle(OnboardingAction.UpdateHomeServer(serverUrl)) viewModel.handle(OnboardingAction.SelectHomeServer(serverUrl))
} }
} }
} }

View File

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