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:
parent
7c0d340bd0
commit
1361852721
|
@ -19,9 +19,13 @@ package im.vector.app.core.extensions
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import im.vector.app.core.platform.SimpleTextWatcher
|
import im.vector.app.core.platform.SimpleTextWatcher
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import reactivecircus.flowbinding.android.widget.textChanges
|
import reactivecircus.flowbinding.android.widget.textChanges
|
||||||
|
|
||||||
fun TextInputLayout.editText() = this.editText!!
|
fun TextInputLayout.editText() = this.editText!!
|
||||||
|
@ -37,11 +41,18 @@ fun TextInputLayout.content() = editText().text.toString()
|
||||||
|
|
||||||
fun TextInputLayout.hasContent() = !editText().text.isNullOrEmpty()
|
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() {
|
editText().addTextChangedListener(object : SimpleTextWatcher() {
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
val newContent = s.toString()
|
val newContent = s.toString()
|
||||||
button.isEnabled = newContent.isNotEmpty()
|
button.isEnabled = enabledPredicate(newContent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ 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 android.view.inputmethod.EditorInfo
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import im.vector.app.R
|
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.content
|
||||||
import im.vector.app.core.extensions.editText
|
import im.vector.app.core.extensions.editText
|
||||||
import im.vector.app.core.extensions.realignPercentagesToParent
|
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.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.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
||||||
import reactivecircus.flowbinding.android.widget.textChanges
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() {
|
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.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) }
|
||||||
views.chooseServerSubmit.debouncedClicks { updateServerUrl() }
|
views.chooseServerSubmit.debouncedClicks { updateServerUrl() }
|
||||||
views.chooseServerInput.editText().textChanges()
|
views.chooseServerInput.clearErrorOnChange(viewLifecycleOwner)
|
||||||
.onEach { views.chooseServerInput.error = null }
|
|
||||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateServerUrl() {
|
private fun updateServerUrl() {
|
||||||
|
|
|
@ -20,19 +20,15 @@ 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 androidx.lifecycle.lifecycleScope
|
|
||||||
import im.vector.app.core.extensions.associateContentStateWith
|
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.content
|
||||||
import im.vector.app.core.extensions.editText
|
|
||||||
import im.vector.app.core.extensions.isEmail
|
import im.vector.app.core.extensions.isEmail
|
||||||
import im.vector.app.core.extensions.setOnImeDoneListener
|
import im.vector.app.core.extensions.setOnImeDoneListener
|
||||||
import im.vector.app.databinding.FragmentFtueEmailInputBinding
|
import im.vector.app.databinding.FragmentFtueEmailInputBinding
|
||||||
import im.vector.app.features.onboarding.OnboardingAction
|
import im.vector.app.features.onboarding.OnboardingAction
|
||||||
import im.vector.app.features.onboarding.RegisterAction
|
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 org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||||
import reactivecircus.flowbinding.android.widget.textChanges
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class FtueAuthEmailEntryFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtueEmailInputBinding>() {
|
class FtueAuthEmailEntryFragment @Inject constructor() : AbstractFtueAuthFragment<FragmentFtueEmailInputBinding>() {
|
||||||
|
@ -47,16 +43,10 @@ class FtueAuthEmailEntryFragment @Inject constructor() : AbstractFtueAuthFragmen
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit)
|
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit, enabledPredicate = { it.isEmail() })
|
||||||
views.emailEntryInput.setOnImeDoneListener { updateEmail() }
|
views.emailEntryInput.setOnImeDoneListener { updateEmail() }
|
||||||
|
views.emailEntryInput.clearErrorOnChange(viewLifecycleOwner)
|
||||||
views.emailEntrySubmit.debouncedClicks { updateEmail() }
|
views.emailEntrySubmit.debouncedClicks { updateEmail() }
|
||||||
|
|
||||||
views.emailEntryInput.editText().textChanges()
|
|
||||||
.onEach {
|
|
||||||
views.emailEntryInput.error = null
|
|
||||||
views.emailEntrySubmit.isEnabled = it.isEmail()
|
|
||||||
}
|
|
||||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateEmail() {
|
private fun updateEmail() {
|
||||||
|
|
|
@ -20,18 +20,14 @@ 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 androidx.lifecycle.lifecycleScope
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.core.extensions.associateContentStateWith
|
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.content
|
||||||
import im.vector.app.core.extensions.editText
|
|
||||||
import im.vector.app.core.extensions.isEmail
|
import im.vector.app.core.extensions.isEmail
|
||||||
import im.vector.app.core.extensions.setOnImeDoneListener
|
import im.vector.app.core.extensions.setOnImeDoneListener
|
||||||
import im.vector.app.databinding.FragmentFtueResetPasswordEmailInputBinding
|
import im.vector.app.databinding.FragmentFtueResetPasswordEmailInputBinding
|
||||||
import im.vector.app.features.onboarding.OnboardingAction
|
import im.vector.app.features.onboarding.OnboardingAction
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import reactivecircus.flowbinding.android.widget.textChanges
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class FtueAuthResetPasswordEmailEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordEmailInputBinding>() {
|
class FtueAuthResetPasswordEmailEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordEmailInputBinding>() {
|
||||||
|
@ -46,14 +42,9 @@ class FtueAuthResetPasswordEmailEntryFragment : AbstractFtueAuthFragment<Fragmen
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit)
|
views.emailEntryInput.associateContentStateWith(button = views.emailEntrySubmit, enabledPredicate = { it.isEmail() })
|
||||||
views.emailEntryInput.setOnImeDoneListener { startPasswordReset() }
|
views.emailEntryInput.setOnImeDoneListener { startPasswordReset() }
|
||||||
views.emailEntryInput.editText().textChanges()
|
views.emailEntryInput.clearErrorOnChange(viewLifecycleOwner)
|
||||||
.onEach {
|
|
||||||
views.emailEntryInput.error = null
|
|
||||||
views.emailEntrySubmit.isEnabled = it.isEmail()
|
|
||||||
}
|
|
||||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
|
||||||
views.emailEntrySubmit.debouncedClicks { startPasswordReset() }
|
views.emailEntrySubmit.debouncedClicks { startPasswordReset() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,20 +21,16 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.core.extensions.associateContentStateWith
|
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.content
|
||||||
import im.vector.app.core.extensions.editText
|
import im.vector.app.core.extensions.editText
|
||||||
import im.vector.app.core.extensions.hidePassword
|
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.core.extensions.setOnImeDoneListener
|
||||||
import im.vector.app.databinding.FragmentFtueResetPasswordInputBinding
|
import im.vector.app.databinding.FragmentFtueResetPasswordInputBinding
|
||||||
import im.vector.app.features.onboarding.OnboardingAction
|
import im.vector.app.features.onboarding.OnboardingAction
|
||||||
import im.vector.app.features.onboarding.OnboardingViewState
|
import im.vector.app.features.onboarding.OnboardingViewState
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import reactivecircus.flowbinding.android.widget.textChanges
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordInputBinding>() {
|
class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtueResetPasswordInputBinding>() {
|
||||||
|
@ -51,9 +47,7 @@ class FtueAuthResetPasswordEntryFragment : AbstractFtueAuthFragment<FragmentFtue
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
views.newPasswordInput.associateContentStateWith(button = views.newPasswordSubmit)
|
views.newPasswordInput.associateContentStateWith(button = views.newPasswordSubmit)
|
||||||
views.newPasswordInput.setOnImeDoneListener { resetPassword() }
|
views.newPasswordInput.setOnImeDoneListener { resetPassword() }
|
||||||
views.newPasswordInput.editText().textChanges()
|
views.newPasswordInput.clearErrorOnChange(viewLifecycleOwner)
|
||||||
.onEach { views.newPasswordInput.error = null }
|
|
||||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
|
||||||
views.newPasswordSubmit.debouncedClicks { resetPassword() }
|
views.newPasswordSubmit.debouncedClicks { resetPassword() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue