Merge pull request #6649 from vector-im/feature/adm/auth-testing-results
FTUE - Test session feedback
This commit is contained in:
commit
067a030f19
|
@ -0,0 +1 @@
|
|||
FTUE - Test session feedback
|
|
@ -0,0 +1 @@
|
|||
FTUE - Improved reset password error message
|
|
@ -86,6 +86,10 @@ fun Throwable.isInvalidUIAAuth() = this is Failure.ServerError &&
|
|||
fun Throwable.isHomeserverUnavailable() = this is Failure.NetworkConnection &&
|
||||
this.ioException is UnknownHostException
|
||||
|
||||
fun Throwable.isMissingEmailVerification() = this is Failure.ServerError &&
|
||||
error.code == MatrixError.M_UNAUTHORIZED &&
|
||||
error.message == "Unable to get validated threepid"
|
||||
|
||||
/**
|
||||
* Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible
|
||||
*/
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.failure.MatrixError
|
|||
import org.matrix.android.sdk.api.failure.MatrixIdFailure
|
||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||
import org.matrix.android.sdk.api.failure.isLimitExceededError
|
||||
import org.matrix.android.sdk.api.failure.isMissingEmailVerification
|
||||
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.SocketTimeoutException
|
||||
|
@ -105,6 +106,9 @@ class DefaultErrorFormatter @Inject constructor(
|
|||
throwable.error.message == "Not allowed to join this room" -> {
|
||||
stringProvider.getString(R.string.room_error_access_unauthorized)
|
||||
}
|
||||
throwable.isMissingEmailVerification() -> {
|
||||
stringProvider.getString(R.string.auth_reset_password_error_unverified)
|
||||
}
|
||||
else -> {
|
||||
throwable.error.message.takeIf { it.isNotEmpty() }
|
||||
?: throwable.error.code.takeIf { it.isNotEmpty() }
|
||||
|
|
|
@ -75,7 +75,11 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
|
|||
setupSubmitButton()
|
||||
views.createAccountRoot.realignPercentagesToParent()
|
||||
views.editServerButton.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) }
|
||||
views.createAccountPasswordInput.setOnImeDoneListener { submit() }
|
||||
views.createAccountPasswordInput.setOnImeDoneListener {
|
||||
if (canSubmit(views.createAccountInput.content(), views.createAccountPasswordInput.content())) {
|
||||
submit()
|
||||
}
|
||||
}
|
||||
|
||||
views.createAccountInput.onTextChange(viewLifecycleOwner) {
|
||||
viewModel.handle(OnboardingAction.ResetSelectedRegistrationUserName)
|
||||
|
@ -87,15 +91,19 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
|
|||
}
|
||||
}
|
||||
|
||||
private fun canSubmit(account: CharSequence, password: CharSequence): Boolean {
|
||||
val accountIsValid = account.isNotEmpty()
|
||||
val passwordIsValid = password.length >= MINIMUM_PASSWORD_LENGTH
|
||||
return accountIsValid && passwordIsValid
|
||||
}
|
||||
|
||||
private fun setupSubmitButton() {
|
||||
views.createAccountSubmit.setOnClickListener { submit() }
|
||||
views.createAccountInput.clearErrorOnChange(viewLifecycleOwner)
|
||||
views.createAccountPasswordInput.clearErrorOnChange(viewLifecycleOwner)
|
||||
|
||||
combine(views.createAccountInput.editText().textChanges(), views.createAccountPasswordInput.editText().textChanges()) { account, password ->
|
||||
val accountIsValid = account.isNotEmpty()
|
||||
val passwordIsValid = password.length >= MINIMUM_PASSWORD_LENGTH
|
||||
views.createAccountSubmit.isEnabled = accountIsValid && passwordIsValid
|
||||
views.createAccountSubmit.isEnabled = canSubmit(account, password)
|
||||
}.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,18 +20,20 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.associateContentStateWith
|
||||
import im.vector.app.core.extensions.clearErrorOnChange
|
||||
import im.vector.app.core.extensions.content
|
||||
import im.vector.app.core.extensions.editText
|
||||
import im.vector.app.core.extensions.realignPercentagesToParent
|
||||
import im.vector.app.core.extensions.setOnImeDoneListener
|
||||
import im.vector.app.core.extensions.toReducedUrl
|
||||
import im.vector.app.core.utils.ensureProtocol
|
||||
import im.vector.app.core.utils.ensureTrailingSlash
|
||||
import im.vector.app.core.utils.openUrlInExternalBrowser
|
||||
import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding
|
||||
import im.vector.app.features.onboarding.OnboardingAction
|
||||
import im.vector.app.features.onboarding.OnboardingFlow
|
||||
import im.vector.app.features.onboarding.OnboardingViewEvents
|
||||
import im.vector.app.features.onboarding.OnboardingViewState
|
||||
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
||||
|
@ -53,19 +55,19 @@ class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFt
|
|||
views.chooseServerToolbar.setNavigationOnClickListener {
|
||||
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnBack))
|
||||
}
|
||||
views.chooseServerInput.editText?.setOnEditorActionListener { _, actionId, _ ->
|
||||
when (actionId) {
|
||||
EditorInfo.IME_ACTION_DONE -> {
|
||||
updateServerUrl()
|
||||
}
|
||||
views.chooseServerInput.associateContentStateWith(button = views.chooseServerSubmit, enabledPredicate = { canSubmit(it) })
|
||||
views.chooseServerInput.setOnImeDoneListener {
|
||||
if (canSubmit(views.chooseServerInput.content())) {
|
||||
updateServerUrl()
|
||||
}
|
||||
false
|
||||
}
|
||||
views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) }
|
||||
views.chooseServerSubmit.debouncedClicks { updateServerUrl() }
|
||||
views.chooseServerInput.clearErrorOnChange(viewLifecycleOwner)
|
||||
}
|
||||
|
||||
private fun canSubmit(url: String) = url.isNotEmpty()
|
||||
|
||||
private fun updateServerUrl() {
|
||||
viewModel.handle(OnboardingAction.HomeServerChange.EditHomeServer(views.chooseServerInput.content().ensureProtocol().ensureTrailingSlash()))
|
||||
}
|
||||
|
@ -75,6 +77,14 @@ class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFt
|
|||
}
|
||||
|
||||
override fun updateWithState(state: OnboardingViewState) {
|
||||
views.chooseServerHeaderSubtitle.setText(
|
||||
when (state.onboardingFlow) {
|
||||
OnboardingFlow.SignIn -> R.string.ftue_auth_choose_server_sign_in_subtitle
|
||||
OnboardingFlow.SignUp -> R.string.ftue_auth_choose_server_subtitle
|
||||
else -> throw IllegalStateException("Invalid flow state")
|
||||
}
|
||||
)
|
||||
|
||||
if (views.chooseServerInput.content().isEmpty()) {
|
||||
val userUrlInput = state.selectedHomeserver.userFacingUrl?.toReducedUrlKeepingSchemaIfInsecure()
|
||||
views.chooseServerInput.editText().setText(userUrlInput)
|
||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.app.core.extensions.setOnImeDoneListener
|
|||
import im.vector.app.databinding.FragmentFtueResetPasswordInputBinding
|
||||
import im.vector.app.features.onboarding.OnboardingAction
|
||||
import im.vector.app.features.onboarding.OnboardingViewState
|
||||
import org.matrix.android.sdk.api.failure.isMissingEmailVerification
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordInputBinding>() {
|
||||
|
@ -61,7 +62,12 @@ class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtue
|
|||
}
|
||||
|
||||
override fun onError(throwable: Throwable) {
|
||||
views.newPasswordInput.error = errorFormatter.toHumanReadable(throwable)
|
||||
when {
|
||||
throwable.isMissingEmailVerification() -> super.onError(throwable)
|
||||
else -> {
|
||||
views.newPasswordInput.error = errorFormatter.toHumanReadable(throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateWithState(state: OnboardingViewState) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import android.os.Parcelable
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.isInvisible
|
||||
import com.airbnb.mvrx.args
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.utils.colorTerminatingFullStop
|
||||
|
@ -63,6 +63,7 @@ class FtueAuthWaitForEmailFragment @Inject constructor(
|
|||
.colorTerminatingFullStop(ThemeUtils.getColor(requireContext(), R.attr.colorSecondary))
|
||||
views.emailVerificationSubtitle.text = getString(R.string.ftue_auth_email_verification_subtitle, params.email)
|
||||
views.emailVerificationResendEmail.debouncedClicks {
|
||||
hideWaitingForVerificationLoading()
|
||||
viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.SendAgainThreePid))
|
||||
}
|
||||
}
|
||||
|
@ -75,13 +76,21 @@ class FtueAuthWaitForEmailFragment @Inject constructor(
|
|||
|
||||
private fun showLoadingIfReturningToScreen() {
|
||||
when (inferHasLeftAndReturnedToScreen) {
|
||||
true -> views.emailVerificationWaiting.isVisible = true
|
||||
true -> showWaitingForVerificationLoading()
|
||||
false -> {
|
||||
inferHasLeftAndReturnedToScreen = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideWaitingForVerificationLoading() {
|
||||
views.emailVerificationWaiting.isInvisible = true
|
||||
}
|
||||
|
||||
private fun showWaitingForVerificationLoading() {
|
||||
views.emailVerificationWaiting.isInvisible = false
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
viewModel.handle(OnboardingAction.StopEmailValidationCheck)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="71dp"
|
||||
android:height="70dp"
|
||||
android:viewportWidth="71"
|
||||
android:viewportHeight="70">
|
||||
<path
|
||||
android:pathData="M39,18C39,19.306 38.165,20.417 37,20.829V25H48C52.418,25 56,28.582 56,33V47C56,51.418 52.418,55 48,55H24C19.582,55 16,51.418 16,47V33C16,28.582 19.582,25 24,25H35V20.829C33.835,20.417 33,19.306 33,18C33,16.343 34.343,15 36,15C37.657,15 39,16.343 39,18ZM47,40C49.209,40 51,38.209 51,36C51,33.791 49.209,32 47,32C44.791,32 43,33.791 43,36C43,38.209 44.791,40 47,40ZM29,36C29,38.209 27.209,40 25,40C22.791,40 21,38.209 21,36C21,33.791 22.791,32 25,32C27.209,32 29,33.791 29,36ZM30.5,47C29.672,47 29,47.672 29,48.5C29,49.328 29.672,50 30.5,50H41.5C42.328,50 43,49.328 43,48.5C43,47.672 42.328,47 41.5,47H30.5Z"
|
||||
android:fillColor="#ff0000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -66,7 +66,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/ftue_auth_create_account_choose_server_header"
|
||||
android:text="@string/ftue_auth_sign_in_choose_server_header"
|
||||
android:textColor="?vctr_content_secondary"
|
||||
app:layout_constraintBottom_toTopOf="@id/selectedServerName"
|
||||
app:layout_constraintEnd_toStartOf="@id/editServerButton"
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
android:background="@drawable/circle"
|
||||
android:backgroundTint="?colorSecondary"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_user_fg"
|
||||
android:src="@drawable/ic_robot"
|
||||
app:layout_constraintBottom_toTopOf="@id/captchaHeaderTitle"
|
||||
app:layout_constraintEnd_toEndOf="@id/captchaGutterEnd"
|
||||
app:layout_constraintHeight_percent="0.10"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/LoginFormScrollView"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:colorBackground"
|
||||
|
@ -76,12 +77,12 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/ftue_auth_choose_server_subtitle"
|
||||
android:textColor="?vctr_content_secondary"
|
||||
app:layout_constraintBottom_toTopOf="@id/titleContentSpacing"
|
||||
app:layout_constraintEnd_toEndOf="@id/chooseServerGutterEnd"
|
||||
app:layout_constraintStart_toStartOf="@id/chooseServerGutterStart"
|
||||
app:layout_constraintTop_toBottomOf="@id/chooseServerHeaderTitle" />
|
||||
app:layout_constraintTop_toBottomOf="@id/chooseServerHeaderTitle"
|
||||
tools:text="@string/ftue_auth_choose_server_subtitle" />
|
||||
|
||||
<Space
|
||||
android:id="@+id/titleContentSpacing"
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
android:id="@+id/emailVerificationWaiting"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@id/emailVerificationSpace4"
|
||||
app:layout_constraintEnd_toEndOf="@id/ftueAuthGutterEnd"
|
||||
app:layout_constraintStart_toStartOf="@id/ftueAuthGutterStart"
|
||||
|
|
|
@ -524,6 +524,7 @@
|
|||
<string name="auth_recaptcha_message">This homeserver would like to make sure you are not a robot</string>
|
||||
<string name="auth_reset_password_missing_email">The email address linked to your account must be entered.</string>
|
||||
<string name="auth_reset_password_error_unauthorized">Failed to verify email address: make sure you clicked the link in the email</string>
|
||||
<string name="auth_reset_password_error_unverified">Email not verified, check your inbox</string>
|
||||
<string name="auth_accept_policies">"Please review and accept the policies of this homeserver:"</string>
|
||||
|
||||
<!-- Login Screen -->
|
||||
|
@ -1929,6 +1930,7 @@
|
|||
<string name="ftue_auth_create_account_username_entry_footer">Others can discover you %s</string>
|
||||
<string name="ftue_auth_create_account_password_entry_footer">Must be 8 characters or more</string>
|
||||
<string name="ftue_auth_create_account_choose_server_header">Where your conversations will live</string>
|
||||
<string name="ftue_auth_sign_in_choose_server_header">Where your conversations live</string>
|
||||
<string name="ftue_auth_create_account_sso_section_header">Or</string>
|
||||
<string name="ftue_auth_create_account_edit_server_selection">Edit</string>
|
||||
|
||||
|
@ -1936,6 +1938,7 @@
|
|||
|
||||
<string name="ftue_auth_choose_server_title">Select your server</string>
|
||||
<string name="ftue_auth_choose_server_subtitle">What is the address of your server? This is like a home for all your data</string>
|
||||
<string name="ftue_auth_choose_server_sign_in_subtitle">What is the address of your server?</string>
|
||||
<string name="ftue_auth_choose_server_entry_hint">Server URL</string>
|
||||
<string name="ftue_auth_choose_server_ems_title">Want to host your own server?</string>
|
||||
|
||||
|
@ -1970,9 +1973,9 @@
|
|||
<string name="ftue_auth_phone_confirmation_subtitle">A code was sent to %s</string>
|
||||
<string name="ftue_auth_phone_confirmation_resend_code">Resend code</string>
|
||||
|
||||
<string name="ftue_auth_email_verification_title">Check your email to verify.</string>
|
||||
<string name="ftue_auth_email_verification_title">Verify your email</string>
|
||||
<!-- Note for translators, %s is the users email address -->
|
||||
<string name="ftue_auth_email_verification_subtitle">To confirm your email, tap the button in the email we just sent to %s</string>
|
||||
<string name="ftue_auth_email_verification_subtitle">Follow the instructions sent to %s</string>
|
||||
<string name="ftue_auth_email_verification_footer">Did not receive an email?</string>
|
||||
<string name="ftue_auth_email_resend_email">Resend email</string>
|
||||
<string name="ftue_auth_forgot_password">Forgot password</string>
|
||||
|
|
Loading…
Reference in New Issue