Hide error when text is entered (#14)

This commit is contained in:
Kirill Kamakin
2021-11-27 19:36:30 +03:00
committed by GitHub
parent 44458dd146
commit a15fac7c7e
2 changed files with 39 additions and 4 deletions

View File

@@ -4,12 +4,15 @@ import android.app.Activity
import android.os.Build
import android.view.View
import android.view.WindowInsets
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.ChannelResult
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.onClosed
import kotlinx.coroutines.channels.onFailure
@@ -22,9 +25,7 @@ fun SwipeRefreshLayout.refreshesLiveData(): LiveData<Unit> {
val callbackFlow: Flow<Unit> = callbackFlow {
val listener = SwipeRefreshLayout.OnRefreshListener {
Timber.v("Refresh requested")
trySend(Unit)
.onFailure { Timber.e(it, "refreshesFlow: can't send refresh callback") }
.onClosed { Timber.e(it, "refreshesFlow: flow has been closed") }
trySend(Unit).logErrors("refreshesFlow")
}
Timber.v("Adding refresh request listener")
setOnRefreshListener(listener)
@@ -60,4 +61,22 @@ fun AppCompatActivity.setActionBarVisibility(isVisible: Boolean) {
Timber.v("setActionBarVisibility() called with: isVisible = $isVisible")
supportActionBar?.apply { if (isVisible) show() else hide() }
?: Timber.w("setActionBarVisibility: action bar is null")
}
@ExperimentalCoroutinesApi
fun TextView.textChangesFlow(): Flow<CharSequence?> = callbackFlow {
Timber.v("textChangesFlow() called")
val textWatcher = doAfterTextChanged {
trySend(it).logErrors("textChangesFlow")
}
awaitClose {
Timber.d("textChangesFlow: flow is closing")
removeTextChangedListener(textWatcher)
}
}
fun <T> ChannelResult<T>.logErrors(methodName: String): ChannelResult<T> {
onFailure { Timber.e(it, "$methodName: can't send event") }
onClosed { Timber.e(it, "$methodName: flow has been closed") }
return this
}

View File

@@ -9,14 +9,20 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.google.android.material.textfield.TextInputLayout
import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.data.auth.impl.AuthenticationError.*
import gq.kirmanak.mealient.databinding.FragmentAuthenticationBinding
import gq.kirmanak.mealient.ui.textChangesFlow
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import timber.log.Timber
@ExperimentalCoroutinesApi
@AndroidEntryPoint
class AuthenticationFragment : Fragment() {
private var _binding: FragmentAuthenticationBinding? = null
@@ -107,13 +113,23 @@ class AuthenticationFragment : Fragment() {
Timber.v("checkIfInputIsEmpty() called with: input = $input, inputLayout = $inputLayout, errorText = $errorText")
val text = input.text?.toString()
Timber.d("Input text is \"$text\"")
if (text.isNullOrBlank()) {
if (text.isNullOrEmpty()) {
inputLayout.error = errorText()
viewLifecycleOwner.lifecycleScope.launchWhenResumed {
waitUntilNotEmpty(input)
inputLayout.error = null
}
return null
}
return text
}
private suspend fun waitUntilNotEmpty(input: EditText) {
Timber.v("waitUntilNotEmpty() called with: input = $input")
input.textChangesFlow().filterNotNull().first { it.isNotEmpty() }
Timber.v("waitUntilNotEmpty() returned")
}
override fun onDestroyView() {
super.onDestroyView()
Timber.v("onDestroyView() called")