Skip the choose server screen when such URL are open when Element
This commit is contained in:
Benoit Marty 2021-10-25 19:18:14 +02:00 committed by Benoit Marty
parent dc5739c11d
commit 9f1efab18d
8 changed files with 60 additions and 17 deletions

2
changelog.d/2684.bugfix Normal file
View file

@ -0,0 +1,2 @@
Correctly handle url of type https://mobile.element.io/?hs_url=…&is_url=…
Skip the choose server screen when such URL are open when Element

View file

@ -23,6 +23,8 @@ import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
import org.matrix.android.sdk.internal.network.ssl.Fingerprint import org.matrix.android.sdk.internal.network.ssl.Fingerprint
sealed class LoginAction : VectorViewModelAction { sealed class LoginAction : VectorViewModelAction {
data class OnGetStarted(val resetLoginConfig: Boolean) : LoginAction()
data class UpdateServerType(val serverType: ServerType) : LoginAction() data class UpdateServerType(val serverType: ServerType) : LoginAction()
data class UpdateHomeServer(val homeServerUrl: String) : LoginAction() data class UpdateHomeServer(val homeServerUrl: String) : LoginAction()
data class UpdateSignMode(val signMode: SignMode) : LoginAction() data class UpdateSignMode(val signMode: SignMode) : LoginAction()

View file

@ -103,7 +103,6 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), ToolbarCo
// Get config extra // Get config extra
val loginConfig = intent.getParcelableExtra<LoginConfig?>(EXTRA_CONFIG) val loginConfig = intent.getParcelableExtra<LoginConfig?>(EXTRA_CONFIG)
if (isFirstCreation()) { if (isFirstCreation()) {
// TODO Check this
loginViewModel.handle(LoginAction.InitWith(loginConfig)) loginViewModel.handle(LoginAction.InitWith(loginConfig))
} }
} }

View file

@ -87,10 +87,5 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
override fun updateWithState(state: LoginViewState) { override fun updateWithState(state: LoginViewState) {
updateSelectedChoice(state) updateSelectedChoice(state)
if (state.loginMode != LoginMode.Unknown) {
// LoginFlow for matrix.org has been retrieved
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnLoginFlowRetrieved))
}
} }
} }

View file

@ -156,10 +156,5 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment<F
setupUi(state) setupUi(state)
views.loginServerUrlFormClearHistory.isInvisible = state.knownCustomHomeServersUrls.isEmpty() views.loginServerUrlFormClearHistory.isInvisible = state.knownCustomHomeServersUrls.isEmpty()
if (state.loginMode != LoginMode.Unknown) {
// The homeserver url is valid
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnLoginFlowRetrieved))
}
} }
} }

View file

@ -22,9 +22,13 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.databinding.FragmentLoginSplashBinding import im.vector.app.databinding.FragmentLoginSplashBinding
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.failure.Failure
import java.net.UnknownHostException
import javax.inject.Inject import javax.inject.Inject
/** /**
@ -45,7 +49,7 @@ class LoginSplashFragment @Inject constructor(
} }
private fun setupViews() { private fun setupViews() {
views.loginSplashSubmit.setOnClickListener { getStarted() } views.loginSplashSubmit.debouncedClicks { getStarted() }
if (BuildConfig.DEBUG || vectorPreferences.developerMode()) { if (BuildConfig.DEBUG || vectorPreferences.developerMode()) {
views.loginSplashVersion.isVisible = true views.loginSplashVersion.isVisible = true
@ -57,10 +61,28 @@ class LoginSplashFragment @Inject constructor(
} }
private fun getStarted() { private fun getStarted() {
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OpenServerSelection)) loginViewModel.handle(LoginAction.OnGetStarted(false))
} }
override fun resetViewModel() { override fun resetViewModel() {
// Nothing to do // Nothing to do
} }
override fun onError(throwable: Throwable) {
if (throwable is Failure.NetworkConnection &&
throwable.ioException is UnknownHostException) {
// Invalid homeserver from URL config
val url = loginViewModel.getInitialHomeServerUrl().orEmpty()
MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error)
.setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url))
.setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ ->
loginViewModel.handle(LoginAction.OnGetStarted(true))
}
.setNegativeButton(R.string.cancel, null)
.show()
} else {
super.onError(throwable)
}
}
} }

View file

@ -19,7 +19,6 @@ package im.vector.app.features.login
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
@ -128,6 +127,7 @@ class LoginViewModel @AssistedInject constructor(
override fun handle(action: LoginAction) { override fun handle(action: LoginAction) {
when (action) { when (action) {
is LoginAction.OnGetStarted -> handleOnGetStarted(action)
is LoginAction.UpdateServerType -> handleUpdateServerType(action) is LoginAction.UpdateServerType -> handleUpdateServerType(action)
is LoginAction.UpdateSignMode -> handleUpdateSignMode(action) is LoginAction.UpdateSignMode -> handleUpdateSignMode(action)
is LoginAction.InitWith -> handleInitWith(action) is LoginAction.InitWith -> handleInitWith(action)
@ -146,6 +146,27 @@ class LoginViewModel @AssistedInject constructor(
}.exhaustive }.exhaustive
} }
private fun handleOnGetStarted(action: LoginAction.OnGetStarted) {
if (action.resetLoginConfig) {
loginConfig = null
}
val configUrl = loginConfig?.homeServerUrl?.takeIf { it.isNotEmpty() }
if (configUrl != null) {
// Use config from uri
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")
_viewEvents.post(LoginViewEvents.OpenServerSelection)
} else {
getLoginFlow(homeServerConnectionConfig, ServerType.Other)
}
} else {
_viewEvents.post(LoginViewEvents.OpenServerSelection)
}
}
private fun handleUserAcceptCertificate(action: LoginAction.UserAcceptCertificate) { private fun handleUserAcceptCertificate(action: LoginAction.UserAcceptCertificate) {
// 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
@ -744,7 +765,8 @@ class LoginViewModel @AssistedInject constructor(
} }
} }
private fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig) { private fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig,
serverTypeOverride: ServerType? = null) {
currentHomeServerConnectionConfig = homeServerConnectionConfig currentHomeServerConnectionConfig = homeServerConnectionConfig
currentJob = viewModelScope.launch { currentJob = viewModelScope.launch {
@ -755,7 +777,11 @@ class LoginViewModel @AssistedInject constructor(
asyncHomeServerLoginFlowRequest = Loading(), asyncHomeServerLoginFlowRequest = Loading(),
// If user has entered https://matrix.org, ensure that server type is ServerType.MatrixOrg // 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 // 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 serverType serverType = if (homeServerConnectionConfig.homeServerUri.toString() == matrixOrgUrl) {
ServerType.MatrixOrg
} else {
serverTypeOverride ?: serverType
}
) )
} }
@ -788,7 +814,6 @@ class LoginViewModel @AssistedInject constructor(
else -> LoginMode.Unsupported else -> LoginMode.Unsupported
} }
// FIXME We should post a view event here normally?
setState { setState {
copy( copy(
asyncHomeServerLoginFlowRequest = Uninitialized, asyncHomeServerLoginFlowRequest = Uninitialized,
@ -803,6 +828,7 @@ class LoginViewModel @AssistedInject constructor(
// Notify the UI // Notify the UI
_viewEvents.post(LoginViewEvents.OutdatedHomeserver) _viewEvents.post(LoginViewEvents.OutdatedHomeserver)
} }
_viewEvents.post(LoginViewEvents.OnLoginFlowRetrieved)
} }
} }

View file

@ -657,6 +657,8 @@
<string name="login_error_unknown_host">This URL is not reachable, please check it</string> <string name="login_error_unknown_host">This URL is not reachable, please check it</string>
<string name="login_error_no_homeserver_found">This is not a valid Matrix server address</string> <string name="login_error_no_homeserver_found">This is not a valid Matrix server address</string>
<string name="login_error_homeserver_not_found">Cannot reach a homeserver at this URL, please check it</string> <string name="login_error_homeserver_not_found">Cannot reach a homeserver at this URL, please check it</string>
<string name="login_error_homeserver_from_url_not_found">Cannot reach a homeserver at the URL %s. Please check your link or choose a homeserver manually.</string>
<string name="login_error_homeserver_from_url_not_found_enter_manual">Choose homeserver</string>
<string name="login_error_ssl_peer_unverified">"SSL Error: the peer's identity has not been verified."</string> <string name="login_error_ssl_peer_unverified">"SSL Error: the peer's identity has not been verified."</string>
<string name="login_error_ssl_other">"SSL Error."</string> <string name="login_error_ssl_other">"SSL Error."</string>
<string name="login_error_ssl_handshake">Your device is using an outdated TLS security protocol, vulnerable to attack, for your security you will not be able to connect</string> <string name="login_error_ssl_handshake">Your device is using an outdated TLS security protocol, vulnerable to attack, for your security you will not be able to connect</string>