diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt index 3af68c0f4..19b3f11f7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt @@ -10,4 +10,5 @@ class FilterAdapter( filterTagDelegate(listener), filterHeaderDelegate(), filterLoadingDelegate(), + filterErrorDelegate(), ) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt index 10a6cafd8..073de2c9d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt @@ -1,10 +1,12 @@ package org.koitharu.kotatsu.list.ui.filter +import android.widget.TextView +import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.R import org.koitharu.kotatsu.databinding.ItemCheckableMultipleBinding import org.koitharu.kotatsu.databinding.ItemCheckableSingleBinding import org.koitharu.kotatsu.databinding.ItemFilterHeaderBinding -import org.koitharu.kotatsu.databinding.ItemLoadingFooterBinding fun filterSortDelegate( listener: OnFilterChangedListener, @@ -47,6 +49,11 @@ fun filterHeaderDelegate() = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemLoadingFooterBinding.inflate(layoutInflater, parent, false) } -) { } \ No newline at end of file +fun filterLoadingDelegate() = adapterDelegate(R.layout.item_loading_footer) {} + +fun filterErrorDelegate() = adapterDelegate(R.layout.item_sources_empty) { + + bind { + (itemView as TextView).setText(item.textResId) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt index d72cadf7c..73e3db315 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt @@ -17,14 +17,18 @@ class FilterDiffCallback : DiffUtil.ItemCallback() { oldItem is FilterItem.Sort && newItem is FilterItem.Sort -> { oldItem.order == newItem.order } + oldItem is FilterItem.Error && newItem is FilterItem.Error -> { + oldItem.textResId == newItem.textResId + } else -> false } } override fun areContentsTheSame(oldItem: FilterItem, newItem: FilterItem): Boolean { return when { - oldItem === newItem -> true + oldItem == FilterItem.Loading && newItem == FilterItem.Loading -> true oldItem is FilterItem.Header && newItem is FilterItem.Header -> true + oldItem is FilterItem.Error && newItem is FilterItem.Error -> true oldItem is FilterItem.Tag && newItem is FilterItem.Tag -> { oldItem.isChecked == newItem.isChecked } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt index 8117f5afd..75b29e60d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt @@ -21,4 +21,8 @@ sealed interface FilterItem { ) : FilterItem object Loading : FilterItem + + class Error( + @StringRes val textResId: Int, + ) : FilterItem } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterViewModel.kt index 0942ef35d..06c4b029e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterViewModel.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.* import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.model.MangaTag import org.koitharu.kotatsu.core.model.SortOrder import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import java.util.* @@ -21,12 +22,10 @@ class FilterViewModel( private var job: Job? = null private var selectedSortOrder: SortOrder? = state.sortOrder private val selectedTags = HashSet(state.tags) - private val availableTagsDeferred = viewModelScope.async(Dispatchers.Default + createErrorHandler()) { - repository.getTags() - } - private val localTagsDeferred = viewModelScope.async(Dispatchers.Default + createErrorHandler()) { + private val localTagsDeferred = viewModelScope.async(Dispatchers.Default) { dataRepository.findTags(repository.source) } + private var availableTagsDeferred = loadTagsAsync() init { showFilter() @@ -52,21 +51,24 @@ class FilterViewModel( val previousJob = job job = launchJob(Dispatchers.Default) { previousJob?.cancelAndJoin() - val tags = availableTagsDeferred.await() + val tags = tryLoadTags() val localTags = localTagsDeferred.await() val sortOrders = repository.sortOrders - val list = ArrayList(sortOrders.size + tags.size + 2) + val list = ArrayList(sortOrders.size + (tags?.size ?: 1) + 2) list.add(FilterItem.Header(R.string.sort_order)) sortOrders.sortedBy { it.ordinal }.mapTo(list) { FilterItem.Sort(it, isSelected = it == selectedSortOrder) } - if (tags.isNotEmpty() || selectedTags.isNotEmpty()) { + if (tags == null || tags.isNotEmpty() || selectedTags.isNotEmpty()) { list.add(FilterItem.Header(R.string.genres)) val mappedTags = TreeSet(compareBy({ !it.isChecked }, { it.tag.title })) localTags.mapTo(mappedTags) { FilterItem.Tag(it, isChecked = it in selectedTags) } - tags.mapTo(mappedTags) { FilterItem.Tag(it, isChecked = it in selectedTags) } + tags?.mapTo(mappedTags) { FilterItem.Tag(it, isChecked = it in selectedTags) } selectedTags.mapTo(mappedTags) { FilterItem.Tag(it, isChecked = true) } list.addAll(mappedTags) + if (tags == null) { + list.add(FilterItem.Error(R.string.filter_load_error)) + } } ensureActive() filter.postValue(list) @@ -93,4 +95,20 @@ class FilterViewModel( updateFilters() } } + + private suspend fun tryLoadTags(): Set? { + val shouldRetryOnError = availableTagsDeferred.isCompleted + val result = availableTagsDeferred.await() + if (result == null && shouldRetryOnError) { + availableTagsDeferred = loadTagsAsync() + return availableTagsDeferred.await() + } + return result + } + + private fun loadTagsAsync() = viewModelScope.async(Dispatchers.Default) { + kotlin.runCatching { + repository.getTags() + }.getOrNull() + } } \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3155e92f0..3966f6c81 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -253,4 +253,5 @@ Разрешить Запретить для NSFW Запретить всегда + Не удалось загрузить список жанров \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6adb549de..bd5d42803 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -255,4 +255,5 @@ Allow Block on NSFW Block always + Unable to load genres list \ No newline at end of file