Always suggest available tags in manga list header
This commit is contained in:
@@ -29,7 +29,7 @@ fun listHeader2AD(
|
|||||||
binding.scrollView.smoothScrollTo(0, 0)
|
binding.scrollView.smoothScrollTo(0, 0)
|
||||||
}
|
}
|
||||||
ignoreChecking = true
|
ignoreChecking = true
|
||||||
binding.chipsTags.setChips(item.chips)
|
binding.chipsTags.setChips(item.chips) // TODO use recyclerview
|
||||||
ignoreChecking = false
|
ignoreChecking = false
|
||||||
binding.textViewFilter.setTextAndVisible(item.sortOrder?.titleRes ?: 0)
|
binding.textViewFilter.setTextAndVisible(item.sortOrder?.titleRes ?: 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class FilterCoordinator(
|
|||||||
private var availableTagsDeferred = loadTagsAsync()
|
private var availableTagsDeferred = loadTagsAsync()
|
||||||
|
|
||||||
val items: LiveData<List<FilterItem>> = getItemsFlow()
|
val items: LiveData<List<FilterItem>> = getItemsFlow()
|
||||||
.asLiveDataDistinct(coroutineScope.coroutineContext + Dispatchers.Default)
|
.asLiveDataDistinct(coroutineScope.coroutineContext + Dispatchers.Default, listOf(FilterItem.Loading))
|
||||||
|
|
||||||
init {
|
init {
|
||||||
observeState()
|
observeState()
|
||||||
@@ -54,6 +54,13 @@ class FilterCoordinator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun observeAvailableTags(): Flow<Set<MangaTag>?> = flow {
|
||||||
|
if (!availableTagsDeferred.isCompleted) {
|
||||||
|
emit(emptySet())
|
||||||
|
}
|
||||||
|
emit(availableTagsDeferred.await())
|
||||||
|
}
|
||||||
|
|
||||||
fun observeState() = currentState.asStateFlow()
|
fun observeState() = currentState.asStateFlow()
|
||||||
|
|
||||||
fun setTags(tags: Set<MangaTag>) {
|
fun setTags(tags: Set<MangaTag>) {
|
||||||
|
|||||||
@@ -3,7 +3,28 @@ package org.koitharu.kotatsu.list.ui.model
|
|||||||
import org.koitharu.kotatsu.base.ui.widgets.ChipsView
|
import org.koitharu.kotatsu.base.ui.widgets.ChipsView
|
||||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||||
|
|
||||||
data class ListHeader2(
|
class ListHeader2(
|
||||||
val chips: Collection<ChipsView.ChipModel>,
|
val chips: Collection<ChipsView.ChipModel>,
|
||||||
val sortOrder: SortOrder?,
|
val sortOrder: SortOrder?,
|
||||||
) : ListModel
|
val hasSelectedTags: Boolean,
|
||||||
|
) : ListModel {
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as ListHeader2
|
||||||
|
|
||||||
|
if (chips != other.chips) return false
|
||||||
|
if (sortOrder != other.sortOrder) return false
|
||||||
|
// Not need to check hasSelectedTags
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = chips.hashCode()
|
||||||
|
result = 31 * result + (sortOrder?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,16 +45,16 @@ class RemoteListViewModel(
|
|||||||
override val content = combine(
|
override val content = combine(
|
||||||
mangaList,
|
mangaList,
|
||||||
createListModeFlow(),
|
createListModeFlow(),
|
||||||
filter.observeState(),
|
createHeaderFlow(),
|
||||||
listError,
|
listError,
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
) { list, mode, filterState, error, hasNext ->
|
) { list, mode, header, error, hasNext ->
|
||||||
buildList(list?.size?.plus(2) ?: 2) {
|
buildList(list?.size?.plus(2) ?: 2) {
|
||||||
add(ListHeader2(createChipsList(filterState), filterState.sortOrder))
|
add(header)
|
||||||
when {
|
when {
|
||||||
list.isNullOrEmpty() && error != null -> add(error.toErrorState(canRetry = true))
|
list.isNullOrEmpty() && error != null -> add(error.toErrorState(canRetry = true))
|
||||||
list == null -> add(LoadingState)
|
list == null -> add(LoadingState)
|
||||||
list.isEmpty() -> add(createEmptyState(filterState))
|
list.isEmpty() -> add(createEmptyState(header.hasSelectedTags))
|
||||||
else -> {
|
else -> {
|
||||||
list.toUi(this, mode)
|
list.toUi(this, mode)
|
||||||
when {
|
when {
|
||||||
@@ -64,10 +64,7 @@ class RemoteListViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.asLiveDataDistinct(
|
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
|
||||||
viewModelScope.coroutineContext + Dispatchers.Default,
|
|
||||||
listOf(ListHeader(repository.source.title, 0, null), LoadingState),
|
|
||||||
)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
filter.observeState()
|
filter.observeState()
|
||||||
@@ -144,16 +141,33 @@ class RemoteListViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createEmptyState(filterState: FilterState) = EmptyState(
|
private fun createEmptyState(canResetFilter: Boolean) = EmptyState(
|
||||||
icon = R.drawable.ic_empty_search,
|
icon = R.drawable.ic_empty_search,
|
||||||
textPrimary = R.string.nothing_found,
|
textPrimary = R.string.nothing_found,
|
||||||
textSecondary = 0,
|
textSecondary = 0,
|
||||||
actionStringRes = if (filterState.tags.isEmpty()) 0 else R.string.reset_filter,
|
actionStringRes = if (canResetFilter) R.string.reset_filter else 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
private suspend fun createChipsList(filterState: FilterState): List<ChipsView.ChipModel> {
|
private fun createHeaderFlow() = combine(
|
||||||
|
filter.observeState(),
|
||||||
|
filter.observeAvailableTags(),
|
||||||
|
) { state, available ->
|
||||||
|
val chips = createChipsList(state, available.orEmpty())
|
||||||
|
ListHeader2(chips, state.sortOrder, state.tags.isNotEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun createChipsList(
|
||||||
|
filterState: FilterState,
|
||||||
|
availableTags: Set<MangaTag>
|
||||||
|
): List<ChipsView.ChipModel> {
|
||||||
val selectedTags = filterState.tags.toMutableSet()
|
val selectedTags = filterState.tags.toMutableSet()
|
||||||
val tags = searchRepository.getTagsSuggestion("", 6, repository.source)
|
var tags = searchRepository.getTagsSuggestion("", 6, repository.source)
|
||||||
|
if (tags.isEmpty()) {
|
||||||
|
tags = availableTags.take(6)
|
||||||
|
}
|
||||||
|
if (tags.isEmpty() && selectedTags.isEmpty()) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
val result = LinkedList<ChipsView.ChipModel>()
|
val result = LinkedList<ChipsView.ChipModel>()
|
||||||
for (tag in tags) {
|
for (tag in tags) {
|
||||||
val model = ChipsView.ChipModel(
|
val model = ChipsView.ChipModel(
|
||||||
|
|||||||
Reference in New Issue
Block a user