Merge pull request #95 from kirmanak/bug-fix

Bugfix
This commit is contained in:
Kirill Kamakin
2022-11-17 22:29:40 +01:00
committed by GitHub
8 changed files with 55 additions and 22 deletions

View File

@@ -17,8 +17,8 @@ plugins {
android {
defaultConfig {
applicationId = "gq.kirmanak.mealient"
versionCode = 17
versionName = "0.3.2"
versionCode = 18
versionName = "0.3.3"
}
signingConfigs {

View File

@@ -2,10 +2,13 @@ package gq.kirmanak.mealient.extensions
import android.content.Context
import android.content.SharedPreferences
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.TextView
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
@@ -107,3 +110,8 @@ fun Context.showLongToast(@StringRes text: Int) = showLongToast(getString(text))
private fun Context.showToast(text: String, length: Int) {
Toast.makeText(this, text, length).show()
}
fun View.hideKeyboard() {
val imm = context.getSystemService<InputMethodManager>()
imm?.hideSoftInputFromWindow(windowToken, 0)
}

View File

@@ -123,7 +123,13 @@ class MainActivity : AppCompatActivity(R.layout.main_activity) {
logger.e { "setupSearchItem: search item's actionView is null or not SearchView" }
return
}
searchView.queryHint = getString(R.string.search_recipes_hint)
searchView.isSubmitButtonEnabled = false
searchView.setQuery(viewModel.lastSearchQuery, false)
searchView.isIconified = viewModel.lastSearchQuery.isNullOrBlank()
searchView.setOnCloseListener {
logger.v { "onClose() called" }
viewModel.onSearchQuery(null)

View File

@@ -32,6 +32,9 @@ class MainActivityViewModel @Inject constructor(
private val _startDestination = MutableLiveData<Int>()
val startDestination: LiveData<Int> = _startDestination
var lastSearchQuery: String? = null
private set
init {
authRepo.isAuthorizedFlow
.onEach { isAuthorized -> updateUiState { it.copy(isAuthorized = isAuthorized) } }
@@ -57,6 +60,9 @@ class MainActivityViewModel @Inject constructor(
fun onSearchQuery(query: String?) {
logger.v { "onSearchQuery() called with: query = $query" }
recipeRepo.updateNameQuery(query)
if (lastSearchQuery != query) {
lastSearchQuery = query
recipeRepo.updateNameQuery(query)
}
}
}

View File

@@ -127,9 +127,8 @@ class AddRecipeFragment : Fragment(R.layout.fragment_add_recipe) {
private fun saveValues() = with(binding) {
logger.v { "saveValues() called" }
val instructions =
parseInputRows(instructionsFlow).map { AddRecipeInstructionInfo(text = it) }
val ingredients = parseInputRows(ingredientsFlow).map { AddRecipeIngredientInfo(note = it) }
val instructions = parseInputRows(instructionsFlow).map { AddRecipeInstructionInfo(it) }
val ingredients = parseInputRows(ingredientsFlow).map { AddRecipeIngredientInfo(it) }
val settings = AddRecipeSettingsInfo(
public = publicRecipe.isChecked,
disableComments = disableComments.isChecked,
@@ -156,17 +155,18 @@ class AddRecipeFragment : Fragment(R.layout.fragment_add_recipe) {
private fun onSavedInputLoaded(request: AddRecipeInfo) = with(binding) {
logger.v { "onSavedInputLoaded() called with: request = $request" }
recipeNameInput.setText(request.name)
recipeDescriptionInput.setText(request.description)
recipeYieldInput.setText(request.recipeYield)
publicRecipe.isChecked = request.settings.public
disableComments.isChecked = request.settings.disableComments
request.recipeIngredient.map { it.note }
.showIn(ingredientsFlow, R.string.fragment_add_recipe_ingredient_hint)
request.recipeInstructions.map { it.text }
.showIn(instructionsFlow, R.string.fragment_add_recipe_instruction_hint)
recipeNameInput.setText(request.name)
recipeDescriptionInput.setText(request.description)
recipeYieldInput.setText(request.recipeYield)
publicRecipe.isChecked = request.settings.public
disableComments.isChecked = request.settings.disableComments
}
private fun Iterable<String>.showIn(flow: Flow, @StringRes hintId: Int) {

View File

@@ -1,5 +1,6 @@
package gq.kirmanak.mealient.ui.recipes
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import androidx.annotation.StringRes
@@ -17,10 +18,7 @@ import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.databinding.FragmentRecipesListBinding
import gq.kirmanak.mealient.datasource.NetworkError
import gq.kirmanak.mealient.extensions.collectWhenViewResumed
import gq.kirmanak.mealient.extensions.refreshRequestFlow
import gq.kirmanak.mealient.extensions.showLongToast
import gq.kirmanak.mealient.extensions.valueUpdatesOnly
import gq.kirmanak.mealient.extensions.*
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.ui.activity.MainActivityViewModel
import gq.kirmanak.mealient.ui.recipes.RecipesListFragmentDirections.Companion.actionRecipesFragmentToRecipeInfoFragment
@@ -59,6 +57,15 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
)
}
setupRecipeAdapter()
hideKeyboardOnScroll()
}
@SuppressLint("ClickableViewAccessibility")
private fun hideKeyboardOnScroll() {
binding.recipes.setOnTouchListener { view, _ ->
view?.hideKeyboard()
false
}
}
private fun navigateToRecipeInfo(id: String) {
@@ -70,11 +77,9 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
private fun onRecipeClicked(recipe: RecipeSummaryEntity) {
logger.v { "onRecipeClicked() called with: recipe = $recipe" }
binding.progress.isVisible = true
viewModel.refreshRecipeInfo(recipe.slug).observe(viewLifecycleOwner) { result ->
viewModel.refreshRecipeInfo(recipe.slug).observe(viewLifecycleOwner) {
binding.progress.isVisible = false
if (result.isSuccess && !isNavigatingSomewhere()) {
navigateToRecipeInfo(recipe.remoteId)
}
if (!isNavigatingSomewhere()) navigateToRecipeInfo(recipe.remoteId)
}
}

View File

@@ -63,7 +63,8 @@
<action
android:id="@+id/action_global_authenticationFragment"
app:destination="@id/authenticationFragment" />
app:destination="@id/authenticationFragment"
app:popUpTo="@id/recipesListFragment" />
<action
android:id="@+id/action_global_recipesListFragment"
@@ -71,9 +72,11 @@
<action
android:id="@+id/action_global_addRecipeFragment"
app:destination="@id/addRecipeFragment" />
app:destination="@id/addRecipeFragment"
app:popUpTo="@id/recipesListFragment" />
<action
android:id="@+id/action_global_baseURLFragment"
app:destination="@id/baseURLFragment" />
app:destination="@id/baseURLFragment"
app:popUpTo="@id/recipesListFragment" />
</navigation>

View File

@@ -4,7 +4,9 @@ import gq.kirmanak.mealient.data.auth.AuthRepo
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.test.AuthImplTestData.TEST_BASE_URL
import gq.kirmanak.mealient.test.BaseUnitTest
import io.mockk.coEvery
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.verify
@@ -32,6 +34,8 @@ class MainActivityViewModelTest : BaseUnitTest() {
override fun setUp() {
super.setUp()
every { authRepo.isAuthorizedFlow } returns emptyFlow()
coEvery { disclaimerStorage.isDisclaimerAccepted() } returns true
coEvery { serverInfoRepo.getUrl() } returns TEST_BASE_URL
subject = MainActivityViewModel(
authRepo = authRepo,
logger = logger,
@@ -49,6 +53,7 @@ class MainActivityViewModelTest : BaseUnitTest() {
@Test
fun `when onSearchQuery with null expect call to recipe repo`() {
subject.onSearchQuery("query")
subject.onSearchQuery(null)
verify { recipeRepo.updateNameQuery(null) }
}