mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
Login screens: ensure homeserver version is supported
This commit is contained in:
parent
3f1540b54e
commit
9b207dd5dc
24 changed files with 228 additions and 58 deletions
|
@ -19,12 +19,12 @@ package im.vector.matrix.android.api.auth
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.auth.data.LoginFlowResult
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.api.auth.login.LoginWizard
|
||||
import im.vector.matrix.android.api.auth.registration.RegistrationWizard
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
||||
|
||||
/**
|
||||
* This interface defines methods to authenticate or to create an account to a matrix server.
|
||||
|
@ -35,7 +35,7 @@ interface AuthenticationService {
|
|||
* Request the supported login flows for this homeserver.
|
||||
* This is the first method to call to be able to get a wizard to login or the create an account
|
||||
*/
|
||||
fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResponse>): Cancelable
|
||||
fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResult>): Cancelable
|
||||
|
||||
/**
|
||||
* Return a LoginWizard, to login to the homeserver
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2019 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.matrix.android.api.auth.data
|
||||
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
||||
|
||||
// Either a LoginFlowResponse, or an error if the homeserver is outdated
|
||||
sealed class LoginFlowResult {
|
||||
data class Success(val loginFlowResponse: LoginFlowResponse) : LoginFlowResult()
|
||||
object OutdatedHomeserver : LoginFlowResult()
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 2018 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.matrix.android.api.auth.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Model for https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions
|
||||
*
|
||||
* Ex:
|
||||
* <pre>
|
||||
* {
|
||||
* "unstable_features": {
|
||||
* "m.lazy_load_members": true
|
||||
* },
|
||||
* "versions": [
|
||||
* "r0.0.1",
|
||||
* "r0.1.0",
|
||||
* "r0.2.0",
|
||||
* "r0.3.0"
|
||||
* ]
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Versions(
|
||||
@Json(name = "versions")
|
||||
val supportedVersions: List<String>? = null,
|
||||
|
||||
@Json(name = "unstable_features")
|
||||
val unstableFeatures: Map<String, Boolean>? = null
|
||||
)
|
||||
|
||||
// MatrixClientServerAPIVersion
|
||||
private const val r0_0_1 = "r0_0_1"
|
||||
private const val r0_1_0 = "r0_1_0"
|
||||
private const val r0_2_0 = "r0_2_0"
|
||||
private const val r0_3_0 = "r0_3_0"
|
||||
private const val r0_4_0 = "r0_4_0"
|
||||
private const val r0_5_0 = "r0_5_0"
|
||||
private const val r0_6_0 = "r0_6_0"
|
||||
|
||||
// MatrixVersionsFeature
|
||||
private const val FEATURE_LAZY_LOAD_MEMBERS = "m.lazy_load_members"
|
||||
private const val FEATURE_REQUIRE_IDENTITY_SERVER = "m.require_identity_server"
|
||||
private const val FEATURE_ID_ACCESS_TOKEN = "m.id_access_token"
|
||||
private const val FEATURE_SEPARATE_ADD_AND_BIND = "m.separate_add_and_bind"
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the SDK supports this homeserver version
|
||||
*/
|
||||
fun Versions.isSupportedBySdk(): Boolean {
|
||||
return supportLazyLoadMembers()
|
||||
&& !doesServerRequireIdentityServerParam()
|
||||
&& doesServerAcceptIdentityAccessToken()
|
||||
&& doesServerSeparatesAddAndBind()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the server support the lazy loading of room members
|
||||
*
|
||||
* @return true if the server support the lazy loading of room members
|
||||
*/
|
||||
private fun Versions.supportLazyLoadMembers(): Boolean {
|
||||
return supportedVersions?.contains(r0_5_0) == true
|
||||
|| unstableFeatures?.get(FEATURE_LAZY_LOAD_MEMBERS) == true
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if the `id_server` parameter is required when registering with an 3pid,
|
||||
* adding a 3pid or resetting password.
|
||||
*/
|
||||
private fun Versions.doesServerRequireIdentityServerParam(): Boolean {
|
||||
if (supportedVersions?.contains(r0_6_0) == true) return false
|
||||
return unstableFeatures?.get(FEATURE_REQUIRE_IDENTITY_SERVER) ?: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if the `id_access_token` parameter can be safely passed to the homeserver.
|
||||
* Some homeservers may trigger errors if they are not prepared for the new parameter.
|
||||
*/
|
||||
private fun Versions.doesServerAcceptIdentityAccessToken(): Boolean {
|
||||
return supportedVersions?.contains(r0_6_0) == true
|
||||
|| unstableFeatures?.get(FEATURE_ID_ACCESS_TOKEN) ?: false
|
||||
}
|
||||
|
||||
private fun Versions.doesServerSeparatesAddAndBind(): Boolean {
|
||||
return supportedVersions?.contains(r0_6_0) == true
|
||||
|| unstableFeatures?.get(FEATURE_SEPARATE_ADD_AND_BIND) ?: false
|
||||
}
|
|
@ -17,10 +17,11 @@
|
|||
package im.vector.matrix.android.internal.auth
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.auth.data.Versions
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
||||
import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
|
||||
import im.vector.matrix.android.internal.auth.registration.*
|
||||
import im.vector.matrix.android.internal.auth.login.ResetPasswordMailConfirmed
|
||||
import im.vector.matrix.android.internal.auth.registration.*
|
||||
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.*
|
||||
|
@ -30,6 +31,12 @@ import retrofit2.http.*
|
|||
*/
|
||||
internal interface AuthAPI {
|
||||
|
||||
/**
|
||||
* Get the version information of the homeserver
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_ + "versions")
|
||||
fun versions(): Call<Versions>
|
||||
|
||||
/**
|
||||
* Register to the homeserver
|
||||
* Ref: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management
|
||||
|
|
|
@ -19,9 +19,7 @@ package im.vector.matrix.android.internal.auth
|
|||
import dagger.Lazy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.AuthenticationService
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.api.auth.data.*
|
||||
import im.vector.matrix.android.api.auth.login.LoginWizard
|
||||
import im.vector.matrix.android.api.auth.registration.RegistrationWizard
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
|
@ -68,7 +66,7 @@ internal class DefaultAuthenticationService @Inject constructor(@Unauthenticated
|
|||
return sessionManager.getOrCreateSession(sessionParams)
|
||||
}
|
||||
|
||||
override fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResponse>): Cancelable {
|
||||
override fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResult>): Cancelable {
|
||||
currentHomeServerConnectionConfig = null
|
||||
|
||||
return GlobalScope.launch(coroutineDispatchers.main) {
|
||||
|
@ -77,8 +75,10 @@ internal class DefaultAuthenticationService @Inject constructor(@Unauthenticated
|
|||
}
|
||||
result.fold(
|
||||
{
|
||||
// The homeserver exists, keep the config
|
||||
if (it is LoginFlowResult.Success) {
|
||||
// The homeserver exists and up to date, keep the config
|
||||
currentHomeServerConnectionConfig = homeServerConnectionConfig
|
||||
}
|
||||
callback.onSuccess(it)
|
||||
},
|
||||
{
|
||||
|
@ -92,9 +92,21 @@ internal class DefaultAuthenticationService @Inject constructor(@Unauthenticated
|
|||
private suspend fun getLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig) = withContext(coroutineDispatchers.io) {
|
||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||
|
||||
executeRequest<LoginFlowResponse> {
|
||||
// First check the homeserver version
|
||||
val versions = executeRequest<Versions> {
|
||||
apiCall = authAPI.versions()
|
||||
}
|
||||
|
||||
if (versions.isSupportedBySdk()) {
|
||||
// Get the login flow
|
||||
val loginFlowResponse = executeRequest<LoginFlowResponse> {
|
||||
apiCall = authAPI.getLoginFlows()
|
||||
}
|
||||
LoginFlowResult.Success(loginFlowResponse)
|
||||
} else {
|
||||
// Not supported
|
||||
LoginFlowResult.OutdatedHomeserver
|
||||
}
|
||||
}
|
||||
|
||||
override fun getOrCreateRegistrationWizard(): RegistrationWizard {
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.network
|
|||
internal object NetworkConstants {
|
||||
|
||||
private const val URI_API_PREFIX_PATH = "_matrix/client"
|
||||
const val URI_API_PREFIX_PATH_ = "$URI_API_PREFIX_PATH/"
|
||||
const val URI_API_PREFIX_PATH_R0 = "$URI_API_PREFIX_PATH/r0/"
|
||||
const val URI_API_PREFIX_PATH_UNSTABLE = "$URI_API_PREFIX_PATH/unstable/"
|
||||
|
||||
|
|
|
@ -52,14 +52,14 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
|
|||
|
||||
private fun handleLoginViewEvents(loginViewEvents: LoginViewEvents) {
|
||||
when (loginViewEvents) {
|
||||
is LoginViewEvents.RegistrationFlowResult ->
|
||||
is LoginViewEvents.Error -> showError(loginViewEvents.throwable)
|
||||
else ->
|
||||
// This is handled by the Activity
|
||||
Unit
|
||||
is LoginViewEvents.RegistrationError -> displayRegistrationError(loginViewEvents.throwable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayRegistrationError(throwable: Throwable) {
|
||||
private fun showError(throwable: Throwable) {
|
||||
when (throwable) {
|
||||
is Failure.ServerError -> {
|
||||
if (throwable.error.code == MatrixError.FORBIDDEN
|
||||
|
@ -70,14 +70,14 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
|
|||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
} else {
|
||||
onRegistrationError(throwable)
|
||||
onError(throwable)
|
||||
}
|
||||
}
|
||||
else -> onRegistrationError(throwable)
|
||||
else -> onError(throwable)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun onRegistrationError(throwable: Throwable)
|
||||
abstract fun onError(throwable: Throwable)
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
return when {
|
||||
|
|
|
@ -160,7 +160,13 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
}
|
||||
}
|
||||
}
|
||||
is LoginViewEvents.RegistrationError ->
|
||||
is LoginViewEvents.OutdatedHomeserver ->
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(R.string.login_error_outdated_homeserver)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
is LoginViewEvents.Error ->
|
||||
// This is handled by the Fragments
|
||||
Unit
|
||||
}
|
||||
|
|
|
@ -178,8 +178,7 @@ class LoginCaptchaFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -189,7 +189,7 @@ class LoginFragment @Inject constructor(
|
|||
loginViewModel.handle(LoginAction.ResetLogin)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
override fun onError(throwable: Throwable) {
|
||||
loginFieldTil.error = errorFormatter.toHumanReadable(throwable)
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ class LoginGenericTextInputFormFragment @Inject constructor(private val errorFor
|
|||
}
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
override fun onError(throwable: Throwable) {
|
||||
when (params.mode) {
|
||||
TextInputFormFragmentMode.SetEmail -> {
|
||||
if (throwable.is401()) {
|
||||
|
|
|
@ -140,8 +140,7 @@ class LoginResetPasswordFragment @Inject constructor(
|
|||
loginViewModel.handle(LoginAction.ResetResetPassword)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// TODO
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -53,8 +53,12 @@ class LoginResetPasswordMailConfirmationFragment @Inject constructor(
|
|||
loginViewModel.handle(LoginAction.ResetPasswordMailConfirmed)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// No op
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
|
|
|
@ -36,8 +36,7 @@ class LoginResetPasswordSuccessFragment @Inject constructor(
|
|||
loginSharedActionViewModel.post(LoginNavigation.OnResetPasswordMailConfirmationSuccessDone)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -123,8 +123,7 @@ class LoginServerSelectionFragment @Inject constructor(
|
|||
loginViewModel.handle(LoginAction.ResetHomeServerType)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -125,8 +125,7 @@ class LoginServerUrlFormFragment @Inject constructor(
|
|||
loginServerUrlFormHomeServerUrlTil.error = null
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -95,8 +95,7 @@ class LoginSignUpSignInSelectionFragment @Inject constructor(
|
|||
loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -36,8 +36,7 @@ class LoginSplashFragment @Inject constructor(
|
|||
loginSharedActionViewModel.post(LoginNavigation.OpenServerSelection)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -24,5 +24,6 @@ import im.vector.matrix.android.api.auth.registration.FlowResult
|
|||
*/
|
||||
sealed class LoginViewEvents {
|
||||
data class RegistrationFlowResult(val flowResult: FlowResult) : LoginViewEvents()
|
||||
data class RegistrationError(val throwable: Throwable) : LoginViewEvents()
|
||||
data class Error(val throwable: Throwable) : LoginViewEvents()
|
||||
object OutdatedHomeserver : LoginViewEvents()
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.squareup.inject.assisted.AssistedInject
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.AuthenticationService
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.auth.data.LoginFlowResult
|
||||
import im.vector.matrix.android.api.auth.login.LoginWizard
|
||||
import im.vector.matrix.android.api.auth.registration.FlowResult
|
||||
import im.vector.matrix.android.api.auth.registration.RegistrationResult
|
||||
|
@ -31,7 +32,6 @@ import im.vector.matrix.android.api.auth.registration.Stage
|
|||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.MatrixCallbackDelegate
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||
import im.vector.riotx.core.extensions.configureAndStart
|
||||
|
@ -166,7 +166,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
if (failure !is CancellationException) {
|
||||
_viewEvents.post(LoginViewEvents.RegistrationError(failure))
|
||||
_viewEvents.post(LoginViewEvents.Error(failure))
|
||||
}
|
||||
setState {
|
||||
copy(
|
||||
|
@ -188,7 +188,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
_viewEvents.post(LoginViewEvents.RegistrationError(failure))
|
||||
_viewEvents.post(LoginViewEvents.Error(failure))
|
||||
setState {
|
||||
copy(
|
||||
asyncRegistration = Uninitialized
|
||||
|
@ -210,7 +210,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
_viewEvents.post(LoginViewEvents.RegistrationError(failure))
|
||||
_viewEvents.post(LoginViewEvents.Error(failure))
|
||||
setState {
|
||||
copy(
|
||||
asyncRegistration = Uninitialized
|
||||
|
@ -525,8 +525,9 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
)
|
||||
}
|
||||
|
||||
currentTask = authenticationService.getLoginFlow(homeServerConnectionConfigFinal, object : MatrixCallback<LoginFlowResponse> {
|
||||
currentTask = authenticationService.getLoginFlow(homeServerConnectionConfigFinal, object : MatrixCallback<LoginFlowResult> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
_viewEvents.post(LoginViewEvents.Error(failure))
|
||||
setState {
|
||||
copy(
|
||||
asyncHomeServerLoginFlowRequest = Fail(failure)
|
||||
|
@ -534,12 +535,14 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
}
|
||||
}
|
||||
|
||||
override fun onSuccess(data: LoginFlowResponse) {
|
||||
override fun onSuccess(data: LoginFlowResult) {
|
||||
when (data) {
|
||||
is LoginFlowResult.Success -> {
|
||||
val loginMode = when {
|
||||
// SSO login is taken first
|
||||
data.flows.any { it.type == LoginFlowTypes.SSO } -> LoginMode.Sso
|
||||
data.flows.any { it.type == LoginFlowTypes.PASSWORD } -> LoginMode.Password
|
||||
else -> LoginMode.Unsupported(data.flows.mapNotNull { it.type }.toList())
|
||||
data.loginFlowResponse.flows.any { it.type == LoginFlowTypes.SSO } -> LoginMode.Sso
|
||||
data.loginFlowResponse.flows.any { it.type == LoginFlowTypes.PASSWORD } -> LoginMode.Password
|
||||
else -> LoginMode.Unsupported(data.loginFlowResponse.flows.mapNotNull { it.type }.toList())
|
||||
}
|
||||
|
||||
setState {
|
||||
|
@ -548,6 +551,18 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
)
|
||||
}
|
||||
}
|
||||
is LoginFlowResult.OutdatedHomeserver -> {
|
||||
// Notify the UI
|
||||
_viewEvents.post(LoginViewEvents.OutdatedHomeserver)
|
||||
|
||||
setState {
|
||||
copy(
|
||||
asyncHomeServerLoginFlowRequest = Uninitialized
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class LoginWaitForEmailFragment @Inject constructor(private val errorFormatter:
|
|||
loginWaitForEmailNotice.text = getString(R.string.login_wait_for_email_notice, params.email)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
override fun onError(throwable: Throwable) {
|
||||
if (throwable.is401()) {
|
||||
// Try again, with a delay
|
||||
loginViewModel.handle(LoginAction.CheckIfEmailHasBeenValidated(10_000))
|
||||
|
|
|
@ -245,8 +245,7 @@ class LoginWebFragment @Inject constructor(
|
|||
loginViewModel.handle(LoginAction.ResetLogin)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
// Cannot happen here, but just in case
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -101,7 +101,7 @@ class LoginTermsFragment @Inject constructor(
|
|||
loginViewModel.handle(LoginAction.AcceptTerms)
|
||||
}
|
||||
|
||||
override fun onRegistrationError(throwable: Throwable) {
|
||||
override fun onError(throwable: Throwable) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(throwable))
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
<string name="login_wait_for_email_title">Please check your email</string>
|
||||
<string name="login_wait_for_email_notice">We just sent an email to %1$s.\nPlease click on the link it contains to continue the account creation.</string>
|
||||
<string name="login_validation_code_is_not_correct">The entered code is not correct. Please check.</string>
|
||||
<string name="login_error_outdated_homeserver">The homeserver version is outdated, RiotX supports only recent versions of homeserver.\n\nYou may contact the administrator of the homeserver to request for an upgrade of the homeserver.</string>
|
||||
|
||||
<plurals name="login_error_limit_exceeded_retry_after">
|
||||
<item quantity="one">Too many requests have been sent. You can retry in %1$d second…</item>
|
||||
|
|
Loading…
Reference in a new issue