diff --git a/app/src/main/java/gq/kirmanak/mealient/extensions/FragmentExtensions.kt b/app/src/main/java/gq/kirmanak/mealient/extensions/FragmentExtensions.kt index f6ffa7c..0ab4993 100644 --- a/app/src/main/java/gq/kirmanak/mealient/extensions/FragmentExtensions.kt +++ b/app/src/main/java/gq/kirmanak/mealient/extensions/FragmentExtensions.kt @@ -2,19 +2,11 @@ package gq.kirmanak.mealient.extensions import androidx.annotation.StringRes import androidx.fragment.app.Fragment -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.launch fun Fragment.collectWhenViewResumed(flow: Flow, collector: FlowCollector) { - viewLifecycleOwner.lifecycleScope.launch { - viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) { - flow.collect(collector) - } - } + viewLifecycleOwner.collectWhenResumed(flow, collector) } fun Fragment.showLongToast(@StringRes text: Int) = context?.showLongToast(text) != null diff --git a/app/src/main/java/gq/kirmanak/mealient/extensions/ViewExtensions.kt b/app/src/main/java/gq/kirmanak/mealient/extensions/ViewExtensions.kt index 3e3d779..08ede24 100644 --- a/app/src/main/java/gq/kirmanak/mealient/extensions/ViewExtensions.kt +++ b/app/src/main/java/gq/kirmanak/mealient/extensions/ViewExtensions.kt @@ -13,10 +13,7 @@ import android.widget.Toast import androidx.annotation.StringRes import androidx.core.content.getSystemService import androidx.core.widget.doAfterTextChanged -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData -import androidx.lifecycle.Observer -import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.* import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.google.android.material.textfield.TextInputLayout import gq.kirmanak.mealient.logging.Logger @@ -24,10 +21,7 @@ import kotlinx.coroutines.channels.ChannelResult import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.onClosed import kotlinx.coroutines.channels.onFailure -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.filterNotNull -import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch fun SwipeRefreshLayout.refreshRequestFlow(logger: Logger): Flow = callbackFlow { @@ -124,4 +118,12 @@ fun Context.isDarkThemeOn(): Boolean { resources.configuration.isNightModeActive else resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES +} + +fun LifecycleOwner.collectWhenResumed(flow: Flow, collector: FlowCollector) { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + flow.collect(collector) + } + } } \ No newline at end of file diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivity.kt b/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivity.kt index d8870fa..a0ae607 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivity.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivity.kt @@ -20,6 +20,7 @@ import gq.kirmanak.mealient.NavGraphDirections.Companion.actionGlobalBaseURLFrag import gq.kirmanak.mealient.NavGraphDirections.Companion.actionGlobalRecipesListFragment import gq.kirmanak.mealient.R import gq.kirmanak.mealient.databinding.MainActivityBinding +import gq.kirmanak.mealient.extensions.collectWhenResumed import gq.kirmanak.mealient.extensions.isDarkThemeOn import gq.kirmanak.mealient.extensions.observeOnce import gq.kirmanak.mealient.logging.Logger @@ -69,6 +70,10 @@ class MainActivity : AppCompatActivity(R.layout.main_activity) { isAppearanceLightStatusBars = isAppearanceLightBars } viewModel.uiStateLive.observe(this, ::onUiStateChange) + collectWhenResumed(viewModel.clearSearchViewFocus) { + logger.d { "clearSearchViewFocus(): received event" } + binding.toolbar.clearSearchFocus() + } } private fun onNavigationItemSelected(menuItem: MenuItem): Boolean { diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivityViewModel.kt b/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivityViewModel.kt index 73ab467..8022d30 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivityViewModel.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/activity/MainActivityViewModel.kt @@ -8,8 +8,11 @@ import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo import gq.kirmanak.mealient.data.disclaimer.DisclaimerStorage import gq.kirmanak.mealient.data.recipes.RecipeRepo import gq.kirmanak.mealient.logging.Logger +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import javax.inject.Inject @@ -32,6 +35,9 @@ class MainActivityViewModel @Inject constructor( private val _startDestination = MutableLiveData() val startDestination: LiveData = _startDestination + private val _clearSearchViewFocusChannel = Channel() + val clearSearchViewFocus: Flow = _clearSearchViewFocusChannel.receiveAsFlow() + init { authRepo.isAuthorizedFlow .onEach { isAuthorized -> updateUiState { it.copy(isAuthorized = isAuthorized) } } @@ -59,4 +65,9 @@ class MainActivityViewModel @Inject constructor( logger.v { "onSearchQuery() called with: query = $query" } recipeRepo.updateNameQuery(query) } + + fun clearSearchViewFocus() { + logger.v { "clearSearchViewFocus() called" } + _clearSearchViewFocusChannel.trySend(Unit) + } } \ No newline at end of file diff --git a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/RecipesListFragment.kt b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/RecipesListFragment.kt index 9618bd7..79d1452 100644 --- a/app/src/main/java/gq/kirmanak/mealient/ui/recipes/RecipesListFragment.kt +++ b/app/src/main/java/gq/kirmanak/mealient/ui/recipes/RecipesListFragment.kt @@ -61,8 +61,8 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) { @SuppressLint("ClickableViewAccessibility") private fun hideKeyboardOnScroll() { - binding.recipes.setOnTouchListener { view, _ -> - view?.hideKeyboard() + binding.recipes.setOnTouchListener { _, _ -> + activityViewModel.clearSearchViewFocus() false } } @@ -155,18 +155,12 @@ private fun Throwable.toLoadErrorReasonText(): Int? = when (this) { } private fun PagingDataAdapter.refreshErrors(): Flow { - return loadStateFlow - .map { it.refresh } - .valueUpdatesOnly() - .filterIsInstance() + return loadStateFlow.map { it.refresh }.valueUpdatesOnly().filterIsInstance() .map { it.error } } private fun PagingDataAdapter.appendPaginationEnd(): Flow { - return loadStateFlow - .map { it.append.endOfPaginationReached } - .valueUpdatesOnly() - .filter { it } + return loadStateFlow.map { it.append.endOfPaginationReached }.valueUpdatesOnly().filter { it } .map { } }