extracting duplicated field resetting logic

This commit is contained in:
Adam Brown 2022-05-09 16:31:27 +01:00
parent fb1a686f90
commit d86c12dc7a
3 changed files with 33 additions and 57 deletions

View File

@ -21,17 +21,16 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.autofill.HintConstants import androidx.autofill.HintConstants
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.content import im.vector.app.core.extensions.content
import im.vector.app.core.extensions.editText import im.vector.app.core.extensions.editText
import im.vector.app.core.extensions.hasContentFlow
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.hidePassword import im.vector.app.core.extensions.hidePassword
import im.vector.app.core.extensions.realignPercentagesToParent import im.vector.app.core.extensions.realignPercentagesToParent
import im.vector.app.core.extensions.setOnImeDone
import im.vector.app.core.extensions.toReducedUrl import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.databinding.FragmentFtueCombinedLoginBinding import im.vector.app.databinding.FragmentFtueCombinedLoginBinding
import im.vector.app.features.login.LoginMode import im.vector.app.features.login.LoginMode
@ -40,9 +39,7 @@ import im.vector.app.features.login.SocialLoginButtonsView
import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewEvents
import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.OnboardingViewState
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn 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.auth.data.SsoIdentityProvider
import javax.inject.Inject import javax.inject.Inject
@ -59,36 +56,16 @@ class FtueAuthCombinedLoginFragment @Inject constructor(
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupSubmitButton() setupSubmitButton()
views.loginRoot.realignPercentagesToParent() views.loginRoot.realignPercentagesToParent()
views.editServerButton.debouncedClicks { views.editServerButton.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) }
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) views.loginPasswordInput.setOnImeDone { submit() }
}
views.loginPasswordInput.editText().setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
submit()
return@setOnEditorActionListener true
}
return@setOnEditorActionListener false
}
} }
private fun setupSubmitButton() { private fun setupSubmitButton() {
views.loginSubmit.setOnClickListener { submit() } views.loginSubmit.setOnClickListener { submit() }
observeInputFields() observeContentChangesAndResetErrors(views.loginInput, views.loginPasswordInput, views.loginSubmit)
.onEach {
views.loginPasswordInput.error = null
views.loginInput.error = null
views.loginSubmit.isEnabled = it
}
.launchIn(viewLifecycleOwner.lifecycleScope) .launchIn(viewLifecycleOwner.lifecycleScope)
} }
private fun observeInputFields() = combine(
views.loginInput.hasContentFlow { it.trim() },
views.loginPasswordInput.hasContentFlow(),
transform = { isLoginNotEmpty, isPasswordNotEmpty -> isLoginNotEmpty && isPasswordNotEmpty }
)
private fun submit() { private fun submit() {
cleanupUi() cleanupUi()
loginFieldsValidation.validate(views.loginInput.content(), views.loginPasswordInput.content()) loginFieldsValidation.validate(views.loginInput.content(), views.loginPasswordInput.content())

View File

@ -21,7 +21,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.autofill.HintConstants import androidx.autofill.HintConstants
import androidx.core.text.isDigitsOnly import androidx.core.text.isDigitsOnly
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -31,11 +30,11 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.content import im.vector.app.core.extensions.content
import im.vector.app.core.extensions.editText import im.vector.app.core.extensions.editText
import im.vector.app.core.extensions.hasContentFlow
import im.vector.app.core.extensions.hasSurroundingSpaces import im.vector.app.core.extensions.hasSurroundingSpaces
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.hidePassword import im.vector.app.core.extensions.hidePassword
import im.vector.app.core.extensions.realignPercentagesToParent import im.vector.app.core.extensions.realignPercentagesToParent
import im.vector.app.core.extensions.setOnImeDone
import im.vector.app.core.extensions.toReducedUrl import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.databinding.FragmentFtueCombinedRegisterBinding import im.vector.app.databinding.FragmentFtueCombinedRegisterBinding
import im.vector.app.features.login.LoginMode import im.vector.app.features.login.LoginMode
@ -45,9 +44,7 @@ import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction
import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewEvents
import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.OnboardingViewState
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn 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.auth.data.SsoIdentityProvider
import org.matrix.android.sdk.api.failure.isInvalidPassword import org.matrix.android.sdk.api.failure.isInvalidPassword
import org.matrix.android.sdk.api.failure.isInvalidUsername import org.matrix.android.sdk.api.failure.isInvalidUsername
@ -67,36 +64,16 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupSubmitButton() setupSubmitButton()
views.createAccountRoot.realignPercentagesToParent() views.createAccountRoot.realignPercentagesToParent()
views.editServerButton.debouncedClicks { views.editServerButton.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) }
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) views.createAccountPasswordInput.setOnImeDone { submit() }
}
views.createAccountPasswordInput.editText().setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
submit()
return@setOnEditorActionListener true
}
return@setOnEditorActionListener false
}
} }
private fun setupSubmitButton() { private fun setupSubmitButton() {
views.createAccountSubmit.setOnClickListener { submit() } views.createAccountSubmit.setOnClickListener { submit() }
observeInputFields() observeContentChangesAndResetErrors(views.createAccountInput, views.createAccountPasswordInput, views.createAccountSubmit)
.onEach {
views.createAccountPasswordInput.error = null
views.createAccountInput.error = null
views.createAccountSubmit.isEnabled = it
}
.launchIn(viewLifecycleOwner.lifecycleScope) .launchIn(viewLifecycleOwner.lifecycleScope)
} }
private fun observeInputFields() = combine(
views.createAccountInput.hasContentFlow { it.trim() },
views.createAccountPasswordInput.hasContentFlow(),
transform = { isLoginNotEmpty, isPasswordNotEmpty -> isLoginNotEmpty && isPasswordNotEmpty }
)
private fun submit() { private fun submit() {
withState(viewModel) { state -> withState(viewModel) { state ->
cleanupUi() cleanupUi()

View File

@ -16,14 +16,36 @@
package im.vector.app.features.onboarding.ftueauth package im.vector.app.features.onboarding.ftueauth
import android.widget.Button
import com.google.android.material.textfield.TextInputLayout
import im.vector.app.core.extensions.hasContentFlow
import im.vector.app.features.login.SignMode import im.vector.app.features.login.SignMode
import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingAction
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 { fun SignMode.toAuthenticateAction(login: String, password: String, initialDeviceName: String): OnboardingAction.AuthenticateAction {
return when (this) { return when (this) {
SignMode.Unknown -> error("developer error") SignMode.Unknown -> error("developer error")
SignMode.SignUp -> OnboardingAction.AuthenticateAction.Register(username = login, password, initialDeviceName) SignMode.SignUp -> OnboardingAction.AuthenticateAction.Register(username = login, password, initialDeviceName)
SignMode.SignIn -> OnboardingAction.AuthenticateAction.Login(username = login, password, initialDeviceName) SignMode.SignIn -> OnboardingAction.AuthenticateAction.Login(username = login, password, initialDeviceName)
SignMode.SignInWithMatrixId -> OnboardingAction.AuthenticateAction.LoginDirect(matrixId = login, password, initialDeviceName) SignMode.SignInWithMatrixId -> OnboardingAction.AuthenticateAction.LoginDirect(matrixId = login, password, initialDeviceName)
} }
} }
/**
* 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
password.error = null
submit.isEnabled = it
}
}