Trim e-mail and username to ease the login process
Spaces aren't visible in EditText and it's possible to get authentication errors because of that invisible space.
This commit is contained in:
@@ -7,9 +7,11 @@ import android.view.WindowInsets
|
|||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.lifecycle.LifecycleCoroutineScope
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@@ -21,6 +23,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@@ -83,25 +86,24 @@ fun <T> ChannelResult<T>.logErrors(methodName: String): ChannelResult<T> {
|
|||||||
|
|
||||||
fun EditText.checkIfInputIsEmpty(
|
fun EditText.checkIfInputIsEmpty(
|
||||||
inputLayout: TextInputLayout,
|
inputLayout: TextInputLayout,
|
||||||
lifecycleCoroutineScope: LifecycleCoroutineScope,
|
lifecycleOwner: LifecycleOwner,
|
||||||
errorText: () -> String
|
@StringRes stringId: Int,
|
||||||
|
trim: Boolean = true,
|
||||||
): String? {
|
): String? {
|
||||||
Timber.v("checkIfInputIsEmpty() called with: input = $this, inputLayout = $inputLayout, errorText = $errorText")
|
val input = if (trim) text?.trim() else text
|
||||||
val text = text?.toString()
|
val text = input?.toString().orEmpty()
|
||||||
Timber.d("Input text is \"$text\"")
|
Timber.d("Input text is \"$text\"")
|
||||||
if (text.isNullOrEmpty()) {
|
return text.ifEmpty {
|
||||||
inputLayout.error = errorText()
|
inputLayout.error = resources.getString(stringId)
|
||||||
lifecycleCoroutineScope.launchWhenResumed {
|
lifecycleOwner.lifecycleScope.launch {
|
||||||
waitUntilNotEmpty()
|
waitUntilNotEmpty()
|
||||||
inputLayout.error = null
|
inputLayout.error = null
|
||||||
}
|
}
|
||||||
return null
|
null
|
||||||
}
|
}
|
||||||
return text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun EditText.waitUntilNotEmpty() {
|
suspend fun EditText.waitUntilNotEmpty() {
|
||||||
Timber.v("waitUntilNotEmpty() called with: input = $this")
|
|
||||||
textChangesFlow().filterNotNull().first { it.isNotEmpty() }
|
textChangesFlow().filterNotNull().first { it.isNotEmpty() }
|
||||||
Timber.v("waitUntilNotEmpty() returned")
|
Timber.v("waitUntilNotEmpty() returned")
|
||||||
}
|
}
|
||||||
@@ -39,13 +39,18 @@ class AuthenticationFragment : Fragment(R.layout.fragment_authentication) {
|
|||||||
private fun onLoginClicked(): Unit = with(binding) {
|
private fun onLoginClicked(): Unit = with(binding) {
|
||||||
Timber.v("onLoginClicked() called")
|
Timber.v("onLoginClicked() called")
|
||||||
|
|
||||||
val email: String = emailInput.checkIfInputIsEmpty(emailInputLayout, lifecycleScope) {
|
val email: String = emailInput.checkIfInputIsEmpty(
|
||||||
getString(R.string.fragment_authentication_email_input_empty)
|
inputLayout = emailInputLayout,
|
||||||
} ?: return
|
lifecycleOwner = viewLifecycleOwner,
|
||||||
|
stringId = R.string.fragment_authentication_email_input_empty,
|
||||||
|
) ?: return
|
||||||
|
|
||||||
val pass: String = passwordInput.checkIfInputIsEmpty(passwordInputLayout, lifecycleScope) {
|
val pass: String = passwordInput.checkIfInputIsEmpty(
|
||||||
getString(R.string.fragment_authentication_password_input_empty)
|
inputLayout = passwordInputLayout,
|
||||||
} ?: return
|
lifecycleOwner = viewLifecycleOwner,
|
||||||
|
stringId = R.string.fragment_authentication_password_input_empty,
|
||||||
|
trim = false,
|
||||||
|
) ?: return
|
||||||
|
|
||||||
button.isClickable = false
|
button.isClickable = false
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -29,9 +28,11 @@ class BaseURLFragment : Fragment(R.layout.fragment_base_url) {
|
|||||||
|
|
||||||
private fun onProceedClick(view: View) {
|
private fun onProceedClick(view: View) {
|
||||||
Timber.v("onProceedClick() called with: view = $view")
|
Timber.v("onProceedClick() called with: view = $view")
|
||||||
val url = binding.urlInput.checkIfInputIsEmpty(binding.urlInputLayout, lifecycleScope) {
|
val url = binding.urlInput.checkIfInputIsEmpty(
|
||||||
getString(R.string.fragment_baseurl_url_input_empty)
|
inputLayout = binding.urlInputLayout,
|
||||||
} ?: return
|
lifecycleOwner = viewLifecycleOwner,
|
||||||
|
stringId = R.string.fragment_baseurl_url_input_empty,
|
||||||
|
) ?: return
|
||||||
viewModel.saveBaseUrl(url)
|
viewModel.saveBaseUrl(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user