Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide error when text is entered #14

Merged
merged 1 commit into from
Nov 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions app/src/main/java/gq/kirmanak/mealient/ui/ViewExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down