triggering an initial enabled state when using associateContentStateWith and extracts the resetting of errors on content change to an extension

This commit is contained in:
Adam Brown 2022-06-29 14:11:39 +01:00
parent 7c0d340bd0
commit 1361852721
5 changed files with 23 additions and 42 deletions

View file

@ -19,9 +19,13 @@ package im.vector.app.core.extensions
import android.text.Editable
import android.view.View
import android.view.inputmethod.EditorInfo
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputLayout
import im.vector.app.core.platform.SimpleTextWatcher
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.widget.textChanges
fun TextInputLayout.editText() = this.editText!!
@ -37,11 +41,18 @@ fun TextInputLayout.content() = editText().text.toString()
fun TextInputLayout.hasContent() = !editText().text.isNullOrEmpty()
fun TextInputLayout.associateContentStateWith(button: View) {
fun TextInputLayout.clearErrorOnChange(lifecycleOwner: LifecycleOwner) {
editText().textChanges()
.onEach { error = null }
.launchIn(lifecycleOwner.lifecycleScope)
}
fun TextInputLayout.associateContentStateWith(button: View, enabledPredicate: (String) -> Boolean = { it.isNotEmpty() }) {
button.isEnabled = enabledPredicate(content())
editText().addTextChangedListener(object : SimpleTextWatcher() {
override fun afterTextChanged(s: Editable) {
val newContent = s.toString()
button.isEnabled = newContent.isNotEmpty()
button.isEnabled = enabledPredicate(newContent)
}
})
}

View file

@ -21,8 +21,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
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.realignPercentagesToParent
@ -34,10 +34,7 @@ import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding
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.launchIn
import kotlinx.coroutines.flow.onEach
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
import reactivecircus.flowbinding.android.widget.textChanges
import javax.inject.Inject
class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() {
@ -66,9 +63,7 @@ class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFt
}
views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) }
views.chooseServerSubmit.debouncedClicks { updateServerUrl() }
views.chooseServerInput.editText().textChanges()
.onEach { views.chooseServerInput.error = null }
.launchIn(viewLifecycleOwner.lifecycleScope)
views.chooseServerInput.clearErrorOnChange(viewLifecycleOwner)
}
private fun updateServerUrl() {

View file

@ -20,19 +20,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
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.isEmail
import im.vector.app.core.extensions.setOnImeDoneListener
import im.vector.app.databinding.FragmentFtueEmailInputBinding
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.RegisterAction
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
import reactivecircus.flowbinding.android.widget.textChanges
import javax.inject.Inject
class FtueAuthEmailEntryFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtueEmailInputBinding>() {
@ -47,16 +43,10 @@ class FtueAuthEmailEntryFragment @Inject constructor() : AbstractFtueAuthFragmen
}
private fun setupViews() {
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit)
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit, enabledPredicate = { it.isEmail() })
views.emailEntryInput.setOnImeDoneListener { updateEmail() }
views.emailEntryInput.clearErrorOnChange(viewLifecycleOwner)
views.emailEntrySubmit.debouncedClicks { updateEmail() }
views.emailEntryInput.editText().textChanges()
.onEach {
views.emailEntryInput.error = null
views.emailEntrySubmit.isEnabled = it.isEmail()
}
.launchIn(viewLifecycleOwner.lifecycleScope)
}
private fun updateEmail() {

View file

@ -20,18 +20,14 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
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.isEmail
import im.vector.app.core.extensions.setOnImeDoneListener
import im.vector.app.databinding.FragmentFtueResetPasswordEmailInputBinding
import im.vector.app.features.onboarding.OnboardingAction
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.widget.textChanges
@AndroidEntryPoint
class FtueAuthResetPasswordEmailEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordEmailInputBinding>() {
@ -46,14 +42,9 @@ class FtueAuthResetPasswordEmailEntryFragment : AbstractFtueAuthFragment<Fragmen
}
private fun setupViews() {
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit)
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit, enabledPredicate = { it.isEmail() })
views.emailEntryInput.setOnImeDoneListener { startPasswordReset() }
views.emailEntryInput.editText().textChanges()
.onEach {
views.emailEntryInput.error = null
views.emailEntrySubmit.isEnabled = it.isEmail()
}
.launchIn(viewLifecycleOwner.lifecycleScope)
views.emailEntryInput.clearErrorOnChange(viewLifecycleOwner)
views.emailEntrySubmit.debouncedClicks { startPasswordReset() }
}

View file

@ -21,20 +21,16 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
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.hidePassword
import im.vector.app.core.extensions.isEmail
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 kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.widget.textChanges
@AndroidEntryPoint
class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordInputBinding>() {
@ -51,9 +47,7 @@ class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtue
private fun setupViews() {
views.newPasswordInput.associateContentStateWith(button = views.newPasswordSubmit)
views.newPasswordInput.setOnImeDoneListener { resetPassword() }
views.newPasswordInput.editText().textChanges()
.onEach { views.newPasswordInput.error = null }
.launchIn(viewLifecycleOwner.lifecycleScope)
views.newPasswordInput.clearErrorOnChange(viewLifecycleOwner)
views.newPasswordSubmit.debouncedClicks { resetPassword() }
}