mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 04:52:00 +03:00
Merge pull request #1630 from vector-im/feature/wellknown
Re-activate Wellknown support with updated UI (#1614)
This commit is contained in:
commit
98d56cb556
19 changed files with 172 additions and 124 deletions
|
@ -2,7 +2,7 @@ Changes in Riot.imX 0.91.4 (2020-XX-XX)
|
|||
===================================================
|
||||
|
||||
Features ✨:
|
||||
-
|
||||
- Re-activate Wellknown support with updated UI (#1614)
|
||||
|
||||
Improvements 🙌:
|
||||
- Upload device keys only once to the homeserver and fix crash when no network (#1629)
|
||||
|
@ -21,7 +21,7 @@ SDK API changes ⚠️:
|
|||
-
|
||||
|
||||
Build 🧱:
|
||||
- Fix lint false-positive about WorkManger (#1012)
|
||||
- Fix lint false-positive about WorkManager (#1012)
|
||||
- Upgrade build-tools from 3.5.3 to 3.6.6
|
||||
- Upgrade gradle from 5.4.1 to 5.6.4
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.auth.login
|
|||
import dagger.Lazy
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.internal.auth.AuthAPI
|
||||
import im.vector.matrix.android.internal.auth.SessionCreator
|
||||
|
@ -27,6 +28,7 @@ import im.vector.matrix.android.internal.di.Unauthenticated
|
|||
import im.vector.matrix.android.internal.network.RetrofitFactory
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.network.httpclient.addSocketFactory
|
||||
import im.vector.matrix.android.internal.network.ssl.UnrecognizedCertificateException
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import okhttp3.OkHttpClient
|
||||
import javax.inject.Inject
|
||||
|
@ -49,13 +51,28 @@ internal class DefaultDirectLoginTask @Inject constructor(
|
|||
|
||||
override suspend fun execute(params: DirectLoginTask.Params): Session {
|
||||
val client = buildClient(params.homeServerConnectionConfig)
|
||||
val authAPI = retrofitFactory.create(client, params.homeServerConnectionConfig.homeServerUri.toString())
|
||||
val homeServerUrl = params.homeServerConnectionConfig.homeServerUri.toString()
|
||||
|
||||
val authAPI = retrofitFactory.create(client, homeServerUrl)
|
||||
.create(AuthAPI::class.java)
|
||||
|
||||
val loginParams = PasswordLoginParams.userIdentifier(params.userId, params.password, params.deviceName)
|
||||
|
||||
val credentials = executeRequest<Credentials>(null) {
|
||||
apiCall = authAPI.login(loginParams)
|
||||
val credentials = try {
|
||||
executeRequest<Credentials>(null) {
|
||||
apiCall = authAPI.login(loginParams)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
when (throwable) {
|
||||
is UnrecognizedCertificateException -> {
|
||||
throw Failure.UnrecognizedCertificateFailure(
|
||||
homeServerUrl,
|
||||
throwable.fingerprint
|
||||
)
|
||||
}
|
||||
else ->
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
|
||||
return sessionCreator.createSession(credentials, params.homeServerConnectionConfig)
|
||||
|
|
|
@ -27,6 +27,7 @@ import im.vector.matrix.android.internal.di.Unauthenticated
|
|||
import im.vector.matrix.android.internal.network.RetrofitFactory
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.network.httpclient.addSocketFactory
|
||||
import im.vector.matrix.android.internal.network.ssl.UnrecognizedCertificateException
|
||||
import im.vector.matrix.android.internal.session.homeserver.CapabilitiesAPI
|
||||
import im.vector.matrix.android.internal.session.identity.IdentityAuthAPI
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
|
@ -106,6 +107,12 @@ internal class DefaultGetWellknownTask @Inject constructor(
|
|||
}
|
||||
} catch (throwable: Throwable) {
|
||||
when (throwable) {
|
||||
is UnrecognizedCertificateException -> {
|
||||
throw Failure.UnrecognizedCertificateFailure(
|
||||
"https://$domain",
|
||||
throwable.fingerprint
|
||||
)
|
||||
}
|
||||
is Failure.NetworkConnection -> {
|
||||
WellknownResult.Ignore
|
||||
}
|
||||
|
|
|
@ -37,3 +37,11 @@ internal fun String.ensureProtocol(): String {
|
|||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
internal fun String.ensureTrailingSlash(): String {
|
||||
return when {
|
||||
isEmpty() -> this
|
||||
!endsWith("/") -> "$this/"
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
|
|||
|
||||
override fun showFailure(throwable: Throwable) {
|
||||
when (throwable) {
|
||||
is Failure.Cancelled ->
|
||||
/* Ignore this error, user has cancelled the action */
|
||||
Unit
|
||||
is Failure.ServerError ->
|
||||
if (throwable.error.code == MatrixError.M_FORBIDDEN
|
||||
&& throwable.httpCode == HttpsURLConnection.HTTP_FORBIDDEN /* 403 */) {
|
||||
|
|
|
@ -151,8 +151,8 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
// TODO Disabled because it provokes a flickering
|
||||
// ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||
})
|
||||
is LoginViewEvents.OnServerSelectionDone -> onServerSelectionDone()
|
||||
is LoginViewEvents.OnSignModeSelected -> onSignModeSelected()
|
||||
is LoginViewEvents.OnServerSelectionDone -> onServerSelectionDone(loginViewEvents)
|
||||
is LoginViewEvents.OnSignModeSelected -> onSignModeSelected(loginViewEvents)
|
||||
is LoginViewEvents.OnLoginFlowRetrieved ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
if (loginViewEvents.isSso) {
|
||||
|
@ -228,18 +228,20 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
.show()
|
||||
}
|
||||
|
||||
private fun onServerSelectionDone() = withState(loginViewModel) { state ->
|
||||
when (state.serverType) {
|
||||
private fun onServerSelectionDone(loginViewEvents: LoginViewEvents.OnServerSelectionDone) {
|
||||
when (loginViewEvents.serverType) {
|
||||
ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow
|
||||
ServerType.Modular,
|
||||
ServerType.Other -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginServerUrlFormFragment::class.java,
|
||||
option = commonOption)
|
||||
ServerType.Unknown -> Unit /* Should not happen */
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSignModeSelected() = withState(loginViewModel) { state ->
|
||||
when (state.signMode) {
|
||||
private fun onSignModeSelected(loginViewEvents: LoginViewEvents.OnSignModeSelected) = withState(loginViewModel) { state ->
|
||||
// state.signMode could not be ready yet. So use value from the ViewEvent
|
||||
when (loginViewEvents.signMode) {
|
||||
SignMode.Unknown -> error("Sign mode has to be set before calling this method")
|
||||
SignMode.SignUp -> {
|
||||
// This is managed by the LoginViewEvents
|
||||
|
|
|
@ -54,6 +54,7 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
|||
|
||||
private var passwordShown = false
|
||||
private var isSignupMode = false
|
||||
|
||||
// Temporary patch for https://github.com/vector-im/riotX-android/issues/1410,
|
||||
// waiting for https://github.com/matrix-org/synapse/issues/7576
|
||||
private var isNumericOnlyUserIdForbidden = false
|
||||
|
@ -138,6 +139,7 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
|||
loginServerIcon.isVisible = false
|
||||
loginTitle.text = getString(R.string.login_signin_matrix_id_title)
|
||||
loginNotice.text = getString(R.string.login_signin_matrix_id_notice)
|
||||
loginPasswordNotice.isVisible = true
|
||||
} else {
|
||||
val resId = when (state.signMode) {
|
||||
SignMode.Unknown -> error("developer error")
|
||||
|
@ -164,7 +166,9 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
|||
loginTitle.text = getString(resId, state.homeServerUrl.toReducedUrl())
|
||||
loginNotice.text = getString(R.string.login_server_other_text)
|
||||
}
|
||||
ServerType.Unknown -> Unit /* Should not happen */
|
||||
}
|
||||
loginPasswordNotice.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.riotx.features.login
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import butterknife.OnClick
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.utils.openUrlInChromeCustomTab
|
||||
import kotlinx.android.synthetic.main.fragment_login_server_selection.*
|
||||
|
@ -40,11 +39,7 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
|
|||
}
|
||||
|
||||
private fun updateSelectedChoice(state: LoginViewState) {
|
||||
state.serverType.let {
|
||||
loginServerChoiceMatrixOrg.isChecked = it == ServerType.MatrixOrg
|
||||
loginServerChoiceModular.isChecked = it == ServerType.Modular
|
||||
loginServerChoiceOther.isChecked = it == ServerType.Other
|
||||
}
|
||||
loginServerChoiceMatrixOrg.isChecked = state.serverType == ServerType.MatrixOrg
|
||||
}
|
||||
|
||||
private fun initTextViews() {
|
||||
|
@ -61,42 +56,17 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
|
|||
|
||||
@OnClick(R.id.loginServerChoiceMatrixOrg)
|
||||
fun selectMatrixOrg() {
|
||||
if (loginServerChoiceMatrixOrg.isChecked) {
|
||||
// Consider this is a submit
|
||||
submit()
|
||||
} else {
|
||||
loginViewModel.handle(LoginAction.UpdateServerType(ServerType.MatrixOrg))
|
||||
}
|
||||
loginViewModel.handle(LoginAction.UpdateServerType(ServerType.MatrixOrg))
|
||||
}
|
||||
|
||||
@OnClick(R.id.loginServerChoiceModular)
|
||||
fun selectModular() {
|
||||
if (loginServerChoiceModular.isChecked) {
|
||||
// Consider this is a submit
|
||||
submit()
|
||||
} else {
|
||||
loginViewModel.handle(LoginAction.UpdateServerType(ServerType.Modular))
|
||||
}
|
||||
loginViewModel.handle(LoginAction.UpdateServerType(ServerType.Modular))
|
||||
}
|
||||
|
||||
@OnClick(R.id.loginServerChoiceOther)
|
||||
fun selectOther() {
|
||||
if (loginServerChoiceOther.isChecked) {
|
||||
// Consider this is a submit
|
||||
submit()
|
||||
} else {
|
||||
loginViewModel.handle(LoginAction.UpdateServerType(ServerType.Other))
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.loginServerSubmit)
|
||||
fun submit() = withState(loginViewModel) { state ->
|
||||
if (state.serverType == ServerType.MatrixOrg) {
|
||||
// Request login flow here
|
||||
loginViewModel.handle(LoginAction.UpdateHomeServer(getString(R.string.matrix_org_server_url)))
|
||||
} else {
|
||||
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnServerSelectionDone))
|
||||
}
|
||||
loginViewModel.handle(LoginAction.UpdateServerType(ServerType.Other))
|
||||
}
|
||||
|
||||
@OnClick(R.id.loginServerIKnowMyIdSubmit)
|
||||
|
|
|
@ -70,7 +70,7 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment()
|
|||
loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_modular_hint)
|
||||
loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_modular_notice)
|
||||
}
|
||||
ServerType.Other -> {
|
||||
else -> {
|
||||
loginServerUrlFormIcon.isVisible = false
|
||||
loginServerUrlFormTitle.text = getString(R.string.login_server_other_title)
|
||||
loginServerUrlFormText.text = getString(R.string.login_connect_to_a_custom_server)
|
||||
|
@ -78,7 +78,6 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment()
|
|||
loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_other_hint)
|
||||
loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_other_notice)
|
||||
}
|
||||
else -> error("This fragment should not be displayed in matrix.org mode")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ open class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractLo
|
|||
loginSignupSigninTitle.text = getString(R.string.login_server_other_title)
|
||||
loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
|
||||
}
|
||||
ServerType.Unknown -> Unit /* Should not happen */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ sealed class LoginViewEvents : VectorViewEvents {
|
|||
// Navigation event
|
||||
|
||||
object OpenServerSelection : LoginViewEvents()
|
||||
object OnServerSelectionDone : LoginViewEvents()
|
||||
data class OnServerSelectionDone(val serverType: ServerType) : LoginViewEvents()
|
||||
data class OnLoginFlowRetrieved(val isSso: Boolean) : LoginViewEvents()
|
||||
object OnSignModeSelected : LoginViewEvents()
|
||||
data class OnSignModeSelected(val signMode: SignMode) : LoginViewEvents()
|
||||
object OnForgetPasswordClicked : LoginViewEvents()
|
||||
object OnResetPasswordSendThreePidDone : LoginViewEvents()
|
||||
object OnResetPasswordMailConfirmationSuccess : LoginViewEvents()
|
||||
|
|
|
@ -39,6 +39,7 @@ import im.vector.matrix.android.api.auth.registration.RegistrationResult
|
|||
import im.vector.matrix.android.api.auth.registration.RegistrationWizard
|
||||
import im.vector.matrix.android.api.auth.registration.Stage
|
||||
import im.vector.matrix.android.api.auth.wellknown.WellknownResult
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.riotx.R
|
||||
|
@ -47,6 +48,7 @@ import im.vector.riotx.core.extensions.configureAndStart
|
|||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.core.utils.ensureTrailingSlash
|
||||
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
|
||||
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
||||
import im.vector.riotx.features.session.SessionListener
|
||||
|
@ -87,8 +89,12 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
// Store the last action, to redo it after user has trusted the untrusted certificate
|
||||
private var lastAction: LoginAction? = null
|
||||
private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null
|
||||
|
||||
private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
|
||||
|
||||
val currentThreePid: String?
|
||||
get() = registrationWizard?.currentThreePid
|
||||
|
||||
|
@ -111,8 +117,8 @@ class LoginViewModel @AssistedInject constructor(
|
|||
is LoginAction.UpdateServerType -> handleUpdateServerType(action)
|
||||
is LoginAction.UpdateSignMode -> handleUpdateSignMode(action)
|
||||
is LoginAction.InitWith -> handleInitWith(action)
|
||||
is LoginAction.UpdateHomeServer -> handleUpdateHomeserver(action)
|
||||
is LoginAction.LoginOrRegister -> handleLoginOrRegister(action)
|
||||
is LoginAction.UpdateHomeServer -> handleUpdateHomeserver(action).also { lastAction = action }
|
||||
is LoginAction.LoginOrRegister -> handleLoginOrRegister(action).also { lastAction = action }
|
||||
is LoginAction.LoginWithToken -> handleLoginWithToken(action)
|
||||
is LoginAction.WebLoginSuccess -> handleWebLoginSuccess(action)
|
||||
is LoginAction.ResetPassword -> handleResetPassword(action)
|
||||
|
@ -126,10 +132,23 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun handleUserAcceptCertificate(action: LoginAction.UserAcceptCertificate) {
|
||||
// It happen when we get the login flow, so alter the homeserver config and retrieve again the login flow
|
||||
currentHomeServerConnectionConfig
|
||||
?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) }
|
||||
?.let { getLoginFlow(it) }
|
||||
// It happen when we get the login flow, or during direct authentication.
|
||||
// So alter the homeserver config and retrieve again the login flow
|
||||
when (val finalLastAction = lastAction) {
|
||||
is LoginAction.UpdateHomeServer ->
|
||||
currentHomeServerConnectionConfig
|
||||
?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) }
|
||||
?.let { getLoginFlow(it) }
|
||||
is LoginAction.LoginOrRegister ->
|
||||
handleDirectLogin(
|
||||
finalLastAction,
|
||||
HomeServerConnectionConfig.Builder()
|
||||
// Will be replaced by the task
|
||||
.withHomeServerUri("https://dummy.org")
|
||||
.withAllowedFingerPrints(listOf(action.fingerprint))
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLoginWithToken(action: LoginAction.LoginWithToken) {
|
||||
|
@ -321,7 +340,7 @@ class LoginViewModel @AssistedInject constructor(
|
|||
LoginAction.ResetHomeServerType -> {
|
||||
setState {
|
||||
copy(
|
||||
serverType = ServerType.MatrixOrg
|
||||
serverType = ServerType.Unknown
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -333,6 +352,7 @@ class LoginViewModel @AssistedInject constructor(
|
|||
asyncHomeServerLoginFlowRequest = Uninitialized,
|
||||
homeServerUrl = null,
|
||||
loginMode = LoginMode.Unknown,
|
||||
serverType = ServerType.Unknown,
|
||||
loginModeSupportedTypes = emptyList()
|
||||
)
|
||||
}
|
||||
|
@ -379,9 +399,9 @@ class LoginViewModel @AssistedInject constructor(
|
|||
when (action.signMode) {
|
||||
SignMode.SignUp -> startRegistrationFlow()
|
||||
SignMode.SignIn -> startAuthenticationFlow()
|
||||
SignMode.SignInWithMatrixId -> _viewEvents.post(LoginViewEvents.OnSignModeSelected)
|
||||
SignMode.SignInWithMatrixId -> _viewEvents.post(LoginViewEvents.OnSignModeSelected(SignMode.SignInWithMatrixId))
|
||||
SignMode.Unknown -> Unit
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUpdateServerType(action: LoginAction.UpdateServerType) {
|
||||
|
@ -390,6 +410,15 @@ class LoginViewModel @AssistedInject constructor(
|
|||
serverType = action.serverType
|
||||
)
|
||||
}
|
||||
|
||||
when (action.serverType) {
|
||||
ServerType.Unknown -> Unit /* Should not happen */
|
||||
ServerType.MatrixOrg ->
|
||||
// Request login flow here
|
||||
handle(LoginAction.UpdateHomeServer(matrixOrgUrl))
|
||||
ServerType.Modular,
|
||||
ServerType.Other -> _viewEvents.post(LoginViewEvents.OnServerSelectionDone(action.serverType))
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleInitWith(action: LoginAction.InitWith) {
|
||||
|
@ -427,7 +456,6 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
// TODO Handled JobCancellationException
|
||||
setState {
|
||||
copy(
|
||||
asyncResetPassword = Fail(failure)
|
||||
|
@ -469,7 +497,6 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
// TODO Handled JobCancellationException
|
||||
setState {
|
||||
copy(
|
||||
asyncResetMailConfirmed = Fail(failure)
|
||||
|
@ -485,23 +512,22 @@ class LoginViewModel @AssistedInject constructor(
|
|||
SignMode.Unknown -> error("Developer error, invalid sign mode")
|
||||
SignMode.SignIn -> handleLogin(action)
|
||||
SignMode.SignUp -> handleRegisterWith(action)
|
||||
SignMode.SignInWithMatrixId -> handleDirectLogin(action)
|
||||
SignMode.SignInWithMatrixId -> handleDirectLogin(action, null)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleDirectLogin(action: LoginAction.LoginOrRegister) {
|
||||
private fun handleDirectLogin(action: LoginAction.LoginOrRegister, homeServerConnectionConfig: HomeServerConnectionConfig?) {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Loading()
|
||||
)
|
||||
}
|
||||
|
||||
// TODO Handle certificate error in this case. Direct login is deactivated now, so we will handle that later
|
||||
authenticationService.getWellKnownData(action.username, null, object : MatrixCallback<WellknownResult> {
|
||||
authenticationService.getWellKnownData(action.username, homeServerConnectionConfig, object : MatrixCallback<WellknownResult> {
|
||||
override fun onSuccess(data: WellknownResult) {
|
||||
when (data) {
|
||||
is WellknownResult.Prompt ->
|
||||
onWellknownSuccess(action, data)
|
||||
onWellknownSuccess(action, data, homeServerConnectionConfig)
|
||||
is WellknownResult.InvalidMatrixId -> {
|
||||
setState {
|
||||
copy(
|
||||
|
@ -522,23 +548,26 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Fail(failure)
|
||||
)
|
||||
}
|
||||
onDirectLoginError(failure)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun onWellknownSuccess(action: LoginAction.LoginOrRegister, wellKnownPrompt: WellknownResult.Prompt) {
|
||||
val homeServerConnectionConfig = HomeServerConnectionConfig(
|
||||
homeServerUri = Uri.parse(wellKnownPrompt.homeServerUrl),
|
||||
identityServerUri = wellKnownPrompt.identityServerUrl?.let { Uri.parse(it) }
|
||||
)
|
||||
private fun onWellknownSuccess(action: LoginAction.LoginOrRegister,
|
||||
wellKnownPrompt: WellknownResult.Prompt,
|
||||
homeServerConnectionConfig: HomeServerConnectionConfig?) {
|
||||
val alteredHomeServerConnectionConfig = homeServerConnectionConfig
|
||||
?.copy(
|
||||
homeServerUri = Uri.parse(wellKnownPrompt.homeServerUrl),
|
||||
identityServerUri = wellKnownPrompt.identityServerUrl?.let { Uri.parse(it) }
|
||||
)
|
||||
?: HomeServerConnectionConfig(
|
||||
homeServerUri = Uri.parse(wellKnownPrompt.homeServerUrl),
|
||||
identityServerUri = wellKnownPrompt.identityServerUrl?.let { Uri.parse(it) }
|
||||
)
|
||||
|
||||
authenticationService.directAuthentication(
|
||||
homeServerConnectionConfig,
|
||||
alteredHomeServerConnectionConfig,
|
||||
action.username,
|
||||
action.password,
|
||||
action.initialDeviceName,
|
||||
|
@ -548,15 +577,29 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Fail(failure)
|
||||
)
|
||||
}
|
||||
onDirectLoginError(failure)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun onDirectLoginError(failure: Throwable) {
|
||||
if (failure is Failure.UnrecognizedCertificateFailure) {
|
||||
// Display this error in a dialog
|
||||
_viewEvents.post(LoginViewEvents.Failure(failure))
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Uninitialized
|
||||
)
|
||||
}
|
||||
} else {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Fail(failure)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLogin(action: LoginAction.LoginOrRegister) {
|
||||
val safeLoginWizard = loginWizard
|
||||
|
||||
|
@ -584,7 +627,6 @@ class LoginViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
// TODO Handled JobCancellationException
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Fail(failure)
|
||||
|
@ -609,7 +651,7 @@ class LoginViewModel @AssistedInject constructor(
|
|||
// Ensure Wizard is ready
|
||||
loginWizard
|
||||
|
||||
_viewEvents.post(LoginViewEvents.OnSignModeSelected)
|
||||
_viewEvents.post(LoginViewEvents.OnSignModeSelected(SignMode.SignIn))
|
||||
}
|
||||
|
||||
private fun onFlowResponse(flowResult: FlowResult) {
|
||||
|
@ -673,7 +715,10 @@ class LoginViewModel @AssistedInject constructor(
|
|||
|
||||
setState {
|
||||
copy(
|
||||
asyncHomeServerLoginFlowRequest = Loading()
|
||||
asyncHomeServerLoginFlowRequest = Loading(),
|
||||
// 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 serverType
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -682,7 +727,9 @@ class LoginViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(LoginViewEvents.Failure(failure))
|
||||
setState {
|
||||
copy(
|
||||
asyncHomeServerLoginFlowRequest = Uninitialized
|
||||
asyncHomeServerLoginFlowRequest = Uninitialized,
|
||||
// If we were trying to retrieve matrix.org login flow, also reset the serverType
|
||||
serverType = if (serverType == ServerType.MatrixOrg) ServerType.Unknown else serverType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ data class LoginViewState(
|
|||
|
||||
// User choices
|
||||
@PersistState
|
||||
val serverType: ServerType = ServerType.MatrixOrg,
|
||||
val serverType: ServerType = ServerType.Unknown,
|
||||
@PersistState
|
||||
val signMode: SignMode = SignMode.Unknown,
|
||||
@PersistState
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.riotx.features.login
|
||||
|
||||
enum class ServerType {
|
||||
Unknown,
|
||||
MatrixOrg,
|
||||
Modular,
|
||||
Other
|
||||
|
|
|
@ -93,8 +93,9 @@ class SoftLogoutFragment @Inject constructor(
|
|||
softLogoutViewModel.handle(SoftLogoutAction.SignInAgain(password))
|
||||
}
|
||||
|
||||
override fun signinFallbackSubmit() {
|
||||
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSignModeSelected))
|
||||
override fun signinFallbackSubmit() = withState(loginViewModel) { state ->
|
||||
// The loginViewModel has been prepared for a SSO/login fallback recovery (above)
|
||||
loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSignModeSelected(state.signMode)))
|
||||
}
|
||||
|
||||
override fun clearData() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/bg_login_server_checked" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/bg_login_server_checked" android:state_pressed="true" />
|
||||
|
||||
<item android:drawable="@drawable/bg_login_server" />
|
||||
|
||||
|
|
|
@ -106,6 +106,16 @@
|
|||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginPasswordNotice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:text="@string/login_signin_matrix_id_password_notice"
|
||||
android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginServerTitle" />
|
||||
|
||||
<!-- Use a CheckableConstraintLayout to keep the pressed state when retrieving login flow -->
|
||||
<im.vector.riotx.core.platform.CheckableConstraintLayout
|
||||
android:id="@+id/loginServerChoiceMatrixOrg"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -84,7 +85,7 @@
|
|||
|
||||
</im.vector.riotx.core.platform.CheckableConstraintLayout>
|
||||
|
||||
<im.vector.riotx.core.platform.CheckableConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/loginServerChoiceModular"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -135,9 +136,9 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/loginServerChoiceModularText" />
|
||||
|
||||
</im.vector.riotx.core.platform.CheckableConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<im.vector.riotx.core.platform.CheckableConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/loginServerChoiceOther"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -178,45 +179,20 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginServerChoiceOtherTitle" />
|
||||
|
||||
</im.vector.riotx.core.platform.CheckableConstraintLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginServerSubmit"
|
||||
style="@style/Style.Vector.Login.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/login_continue"
|
||||
android:transitionName="loginSubmitTransition"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginServerIKnowMyIdNotice"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginServerChoiceOther" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginServerIKnowMyIdNotice"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="start"
|
||||
android:text="@string/login_connect_using_matrix_id_notice"
|
||||
android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginServerSubmit" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginServerIKnowMyIdSubmit"
|
||||
style="@style/Style.Vector.Login.Button.Text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/login_connect_using_matrix_id_submit"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginServerIKnowMyIdNotice" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginServerChoiceOther" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -1995,10 +1995,11 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming
|
|||
</plurals>
|
||||
|
||||
<string name="login_connect_using_matrix_id_notice">Alternatively, if you already have an account and you know your Matrix identifier and your password, you can use this method:</string>
|
||||
<string name="login_connect_using_matrix_id_submit">Sign in with my Matrix identifier</string>
|
||||
<string name="login_signin_matrix_id_title">Sign in</string>
|
||||
<string name="login_signin_matrix_id_notice">Enter your identifier and your password</string>
|
||||
<string name="login_signin_matrix_id_hint">User identifier</string>
|
||||
<string name="login_connect_using_matrix_id_submit">Sign in with Matrix ID</string>
|
||||
<string name="login_signin_matrix_id_title">Sign in with Matrix ID</string>
|
||||
<string name="login_signin_matrix_id_notice">If you set up an account on a homeserver, use your Matrix ID (e.g. @user:domain.com) and password below.</string>
|
||||
<string name="login_signin_matrix_id_hint">Matrix ID</string>
|
||||
<string name="login_signin_matrix_id_password_notice">If you don’t know your password, go back to reset it.</string>
|
||||
<string name="login_signin_matrix_id_error_invalid_matrix_id">This is not a valid user identifier. Expected format: \'@user:homeserver.org\'</string>
|
||||
<string name="autodiscover_well_known_error">Unable to find a valid homeserver. Please check your identifier</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue