Show progress when parsing recipe

This commit is contained in:
Kirill Kamakin
2022-11-29 19:42:07 +01:00
parent 0c41aac9b7
commit 4a68916433
10 changed files with 135 additions and 41 deletions

View File

@@ -1,26 +1,31 @@
package gq.kirmanak.mealient.ui.share
import android.content.Intent
import android.graphics.drawable.Animatable2
import android.graphics.drawable.AnimatedVectorDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isInvisible
import androidx.core.view.postDelayed
import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.databinding.ActivityShareRecipeBinding
import gq.kirmanak.mealient.extensions.showLongToast
import gq.kirmanak.mealient.logging.Logger
import javax.inject.Inject
import gq.kirmanak.mealient.ui.BaseActivity
import gq.kirmanak.mealient.ui.OperationUiState
@AndroidEntryPoint
class ShareRecipeActivity : AppCompatActivity() {
class ShareRecipeActivity : BaseActivity<ActivityShareRecipeBinding>(
binder = ActivityShareRecipeBinding::bind,
containerId = R.id.root,
layoutRes = R.layout.activity_share_recipe,
) {
private val viewModel: ShareRecipeViewModel by viewModels()
@Inject
lateinit var logger: Logger
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
logger.v { "onCreate() called with: savedInstanceState = $savedInstanceState" }
if (intent.action != Intent.ACTION_SEND || intent.type != "text/plain") {
logger.w { "onCreate: intent.action = ${intent.action}, intent.type = ${intent.type}" }
@@ -35,14 +40,54 @@ class ShareRecipeActivity : AppCompatActivity() {
return
}
viewModel.saveOperationResult.observe(this) {
restartAnimationOnEnd()
viewModel.saveResult.observe(this, ::onStateUpdate)
viewModel.saveRecipeByURL(url)
}
private fun onStateUpdate(state: OperationUiState<String>) {
binding.progress.isInvisible = !state.isProgress
withAnimatedDrawable {
if (state.isProgress) start() else stop()
}
if (state.isSuccess || state.isFailure) {
showLongToast(
if (it.isSuccess) R.string.activity_share_recipe_success_toast
if (state.isSuccess) R.string.activity_share_recipe_success_toast
else R.string.activity_share_recipe_failure_toast
)
finish()
}
viewModel.saveRecipeByURL(url)
}
private fun restartAnimationOnEnd() {
withAnimatedDrawable {
onAnimationEnd {
if (viewModel.saveResult.value?.isProgress == true) {
binding.progress.postDelayed(250) { start() }
}
}
}
}
private inline fun withAnimatedDrawable(block: AnimatedVectorDrawable.() -> Unit) {
binding.progress.drawable.let { drawable ->
if (drawable is AnimatedVectorDrawable) {
drawable.block()
} else {
logger.w { "withAnimatedDrawable: progress's drawable is not AnimatedVectorDrawable" }
}
}
}
}
private inline fun AnimatedVectorDrawable.onAnimationEnd(
crossinline block: AnimatedVectorDrawable.() -> Unit,
): Animatable2.AnimationCallback {
val callback = object : Animatable2.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
block()
}
}
registerAnimationCallback(callback)
return callback
}

View File

@@ -8,6 +8,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import gq.kirmanak.mealient.data.share.ShareRecipeRepo
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.ui.OperationUiState
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -17,21 +18,17 @@ class ShareRecipeViewModel @Inject constructor(
private val logger: Logger,
) : ViewModel() {
private val _saveOperationResult = MutableLiveData<Result<String>>()
val saveOperationResult: LiveData<Result<String>> get() = _saveOperationResult
private val _saveResult = MutableLiveData<OperationUiState<String>>(OperationUiState.Initial())
val saveResult: LiveData<OperationUiState<String>> get() = _saveResult
fun saveRecipeByURL(url: CharSequence) {
logger.v { "saveRecipeByURL() called with: url = $url" }
_saveResult.postValue(OperationUiState.Progress())
viewModelScope.launch {
runCatchingExceptCancel {
shareRecipeRepo.saveRecipeByURL(url)
}.onSuccess {
logger.d { "Successfully saved recipe by URL" }
_saveOperationResult.postValue(Result.success(it))
}.onFailure {
logger.e(it) { "Can't save recipe by URL" }
_saveOperationResult.postValue(Result.failure(it))
}
val result = runCatchingExceptCancel { shareRecipeRepo.saveRecipeByURL(url) }
.onSuccess { logger.d { "Successfully saved recipe by URL" } }
.onFailure { logger.e(it) { "Can't save recipe by URL" } }
_saveResult.postValue(OperationUiState.fromResult(result))
}
}
}