diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt b/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt index 30b033b0cf..4739840f01 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt @@ -46,6 +46,7 @@ fun TextInputLayout.hasContent() = !editText().text.isNullOrEmpty() fun TextInputLayout.clearErrorOnChange(lifecycleOwner: LifecycleOwner) { onTextChange(lifecycleOwner) { error = null + isErrorEnabled = false } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt index 63a8c9069b..58b1edddf8 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt @@ -25,6 +25,7 @@ import androidx.autofill.HintConstants import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import im.vector.app.R +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.hideKeyboard @@ -41,8 +42,10 @@ import im.vector.app.features.login.render import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider +import reactivecircus.flowbinding.android.widget.textChanges import javax.inject.Inject class FtueAuthCombinedLoginFragment @Inject constructor( @@ -66,8 +69,12 @@ class FtueAuthCombinedLoginFragment @Inject constructor( private fun setupSubmitButton() { views.loginSubmit.setOnClickListener { submit() } - observeContentChangesAndResetErrors(views.loginInput, views.loginPasswordInput, views.loginSubmit) - .launchIn(viewLifecycleOwner.lifecycleScope) + views.loginInput.clearErrorOnChange(viewLifecycleOwner) + views.loginPasswordInput.clearErrorOnChange(viewLifecycleOwner) + + combine(views.loginInput.editText().textChanges(), views.loginPasswordInput.editText().textChanges()) { account, password -> + views.loginSubmit.isEnabled = account.isNotEmpty() && password.isNotEmpty() + }.launchIn(viewLifecycleOwner.lifecycleScope) } private fun submit() { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt index 0f7d15db0d..639045b5c0 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt @@ -28,6 +28,7 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R +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.hasSurroundingSpaces @@ -48,8 +49,8 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import org.matrix.android.sdk.api.failure.isInvalidPassword @@ -61,6 +62,8 @@ import org.matrix.android.sdk.api.failure.isWeakPassword import reactivecircus.flowbinding.android.widget.textChanges import javax.inject.Inject +private const val MINIMUM_PASSWORD_LENGTH = 8 + class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAuthFragment() { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueCombinedRegisterBinding { @@ -86,8 +89,14 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu private fun setupSubmitButton() { views.createAccountSubmit.setOnClickListener { submit() } - observeContentChangesAndResetErrors(views.createAccountInput, views.createAccountPasswordInput, views.createAccountSubmit) - .launchIn(viewLifecycleOwner.lifecycleScope) + 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 + }.launchIn(viewLifecycleOwner.lifecycleScope) } private fun submit() { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt index 6ca6d80fcb..ea25d8ebcd 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt @@ -16,16 +16,10 @@ package im.vector.app.features.onboarding.ftueauth -import android.widget.Button -import com.google.android.material.textfield.TextInputLayout import im.vector.app.R -import im.vector.app.core.extensions.hasContentFlow import im.vector.app.features.login.SignMode import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.themes.ThemeProvider -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.onEach fun SignMode.toAuthenticateAction(login: String, password: String, initialDeviceName: String): OnboardingAction.AuthenticateAction { return when (this) { @@ -36,24 +30,6 @@ fun SignMode.toAuthenticateAction(login: String, password: String, initialDevice } } -/** - * A flow to monitor content changes from both username/id and password fields, - * clearing errors and enabling/disabling the submission button on non empty content changes. - */ -fun observeContentChangesAndResetErrors(username: TextInputLayout, password: TextInputLayout, submit: Button): Flow<*> { - return combine( - username.hasContentFlow { it.trim() }, - password.hasContentFlow(), - transform = { usernameHasContent, passwordHasContent -> usernameHasContent && passwordHasContent } - ).onEach { - username.error = null - username.isErrorEnabled = false - password.error = null - username.isErrorEnabled = false - submit.isEnabled = it - } -} - fun ThemeProvider.ftueBreakerBackground() = when (isLightTheme()) { true -> R.drawable.bg_gradient_ftue_breaker false -> R.drawable.bg_color_background