mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-30 17:41:52 +01:00
Replicate global search filters to migrate screen
Still needs better refactoring to dedupe all of this stuff though...
This commit is contained in:
parent
8b46e8edad
commit
dd3ca0c131
@ -1,45 +1,21 @@
|
||||
package eu.kanade.presentation.browse
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.DoneAll
|
||||
import androidx.compose.material.icons.outlined.FilterList
|
||||
import androidx.compose.material.icons.outlined.PushPin
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchCardRow
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchEmptyResultItem
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchResultItem
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchToolbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.presentation.core.components.material.Divider
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.VerticalDivider
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchScreen(
|
||||
@ -56,7 +32,6 @@ fun GlobalSearchScreen(
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
|
||||
GlobalSearchToolbar(
|
||||
searchQuery = state.searchQuery,
|
||||
progress = state.progress,
|
||||
@ -64,68 +39,12 @@ fun GlobalSearchScreen(
|
||||
navigateUp = navigateUp,
|
||||
onChangeSearchQuery = onChangeSearchQuery,
|
||||
onSearch = onSearch,
|
||||
sourceFilter = state.sourceFilter,
|
||||
onChangeSearchFilter = onChangeSearchFilter,
|
||||
onlyShowHasResults = state.onlyShowHasResults,
|
||||
onToggleResults = onToggleResults,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.horizontalScroll(rememberScrollState())
|
||||
.padding(horizontal = MaterialTheme.padding.small),
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
) {
|
||||
// TODO: make this UX better; it only applies when triggering a new search
|
||||
FilterChip(
|
||||
selected = state.sourceFilter == SourceFilter.PinnedOnly,
|
||||
onClick = { onChangeSearchFilter(SourceFilter.PinnedOnly) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.PushPin,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(FilterChipDefaults.IconSize),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.pinned_sources))
|
||||
},
|
||||
)
|
||||
FilterChip(
|
||||
selected = state.sourceFilter == SourceFilter.All,
|
||||
onClick = { onChangeSearchFilter(SourceFilter.All) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.DoneAll,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(FilterChipDefaults.IconSize),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.all))
|
||||
},
|
||||
)
|
||||
|
||||
VerticalDivider()
|
||||
|
||||
FilterChip(
|
||||
selected = state.onlyShowHasResults,
|
||||
onClick = { onToggleResults() },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.FilterList,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(FilterChipDefaults.IconSize),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.has_results))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Divider()
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
GlobalSearchContent(
|
||||
@ -141,7 +60,7 @@ fun GlobalSearchScreen(
|
||||
|
||||
@Composable
|
||||
internal fun GlobalSearchContent(
|
||||
sourceId: Long? = null,
|
||||
fromSourceId: Long? = null,
|
||||
items: Map<CatalogueSource, SearchItemResult>,
|
||||
contentPadding: PaddingValues,
|
||||
getManga: @Composable (Manga) -> State<Manga>,
|
||||
@ -155,7 +74,7 @@ internal fun GlobalSearchContent(
|
||||
items.forEach { (source, result) ->
|
||||
item(key = source.id) {
|
||||
GlobalSearchResultItem(
|
||||
title = sourceId?.let { "▶ ${source.name}".takeIf { source.id == sourceId } } ?: source.name,
|
||||
title = fromSourceId?.let { "▶ ${source.name}".takeIf { source.id == fromSourceId } } ?: source.name,
|
||||
subtitle = LocaleHelper.getDisplayName(source.lang),
|
||||
onClick = { onClickSource(source) },
|
||||
) {
|
||||
@ -164,11 +83,6 @@ internal fun GlobalSearchContent(
|
||||
GlobalSearchLoadingResultItem()
|
||||
}
|
||||
is SearchItemResult.Success -> {
|
||||
if (result.isEmpty) {
|
||||
GlobalSearchEmptyResultItem()
|
||||
return@GlobalSearchResultItem
|
||||
}
|
||||
|
||||
GlobalSearchCardRow(
|
||||
titles = result.result,
|
||||
getManga = getManga,
|
||||
|
@ -5,16 +5,19 @@ import androidx.compose.runtime.State
|
||||
import eu.kanade.presentation.browse.components.GlobalSearchToolbar
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateSearchScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
|
||||
@Composable
|
||||
fun MigrateSearchScreen(
|
||||
navigateUp: () -> Unit,
|
||||
state: MigrateSearchScreenModel.State,
|
||||
getManga: @Composable (Manga) -> State<Manga>,
|
||||
navigateUp: () -> Unit,
|
||||
onChangeSearchQuery: (String?) -> Unit,
|
||||
onSearch: (String) -> Unit,
|
||||
onChangeSearchFilter: (SourceFilter) -> Unit,
|
||||
onToggleResults: () -> Unit,
|
||||
getManga: @Composable (Manga) -> State<Manga>,
|
||||
onClickSource: (CatalogueSource) -> Unit,
|
||||
onClickItem: (Manga) -> Unit,
|
||||
onLongClickItem: (Manga) -> Unit,
|
||||
@ -28,13 +31,17 @@ fun MigrateSearchScreen(
|
||||
navigateUp = navigateUp,
|
||||
onChangeSearchQuery = onChangeSearchQuery,
|
||||
onSearch = onSearch,
|
||||
sourceFilter = state.sourceFilter,
|
||||
onChangeSearchFilter = onChangeSearchFilter,
|
||||
onlyShowHasResults = state.onlyShowHasResults,
|
||||
onToggleResults = onToggleResults,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
GlobalSearchContent(
|
||||
sourceId = state.manga?.source,
|
||||
items = state.items,
|
||||
fromSourceId = state.manga?.source,
|
||||
items = state.filteredItems,
|
||||
contentPadding = paddingValues,
|
||||
getManga = getManga,
|
||||
onClickSource = onClickSource,
|
||||
|
@ -3,17 +3,21 @@ package eu.kanade.presentation.browse.components
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.library.components.CommonMangaItemDefaults
|
||||
import eu.kanade.presentation.library.components.MangaComfortableGridItem
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
import tachiyomi.domain.manga.model.asMangaCover
|
||||
@ -26,13 +30,18 @@ fun GlobalSearchCardRow(
|
||||
onClick: (Manga) -> Unit,
|
||||
onLongClick: (Manga) -> Unit,
|
||||
) {
|
||||
if (titles.isEmpty()) {
|
||||
EmptyResultItem()
|
||||
return
|
||||
}
|
||||
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(MaterialTheme.padding.small),
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.tiny),
|
||||
) {
|
||||
items(titles) {
|
||||
val title by getManga(it)
|
||||
GlobalSearchCard(
|
||||
MangaItem(
|
||||
title = title.title,
|
||||
cover = title.asMangaCover(),
|
||||
isFavorite = title.favorite,
|
||||
@ -44,7 +53,7 @@ fun GlobalSearchCardRow(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun GlobalSearchCard(
|
||||
private fun MangaItem(
|
||||
title: String,
|
||||
cover: MangaCover,
|
||||
isFavorite: Boolean,
|
||||
@ -64,3 +73,15 @@ private fun GlobalSearchCard(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmptyResultItem() {
|
||||
Text(
|
||||
text = stringResource(R.string.no_results_found),
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
horizontal = MaterialTheme.padding.medium,
|
||||
vertical = MaterialTheme.padding.small,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -61,18 +61,6 @@ fun GlobalSearchResultItem(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchEmptyResultItem() {
|
||||
Text(
|
||||
text = stringResource(R.string.no_results_found),
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
horizontal = MaterialTheme.padding.medium,
|
||||
vertical = MaterialTheme.padding.small,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchLoadingResultItem() {
|
||||
Box(
|
||||
|
@ -1,13 +1,36 @@
|
||||
package eu.kanade.presentation.browse.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.DoneAll
|
||||
import androidx.compose.material.icons.outlined.FilterList
|
||||
import androidx.compose.material.icons.outlined.PushPin
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
||||
import tachiyomi.presentation.core.components.material.Divider
|
||||
import tachiyomi.presentation.core.components.material.VerticalDivider
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchToolbar(
|
||||
@ -17,8 +40,13 @@ fun GlobalSearchToolbar(
|
||||
navigateUp: () -> Unit,
|
||||
onChangeSearchQuery: (String?) -> Unit,
|
||||
onSearch: (String) -> Unit,
|
||||
sourceFilter: SourceFilter,
|
||||
onChangeSearchFilter: (SourceFilter) -> Unit,
|
||||
onlyShowHasResults: Boolean,
|
||||
onToggleResults: () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
) {
|
||||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
|
||||
Box {
|
||||
SearchToolbar(
|
||||
searchQuery = searchQuery,
|
||||
@ -37,4 +65,64 @@ fun GlobalSearchToolbar(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.horizontalScroll(rememberScrollState())
|
||||
.padding(horizontal = MaterialTheme.padding.small),
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
) {
|
||||
// TODO: make this UX better; it only applies when triggering a new search
|
||||
FilterChip(
|
||||
selected = sourceFilter == SourceFilter.PinnedOnly,
|
||||
onClick = { onChangeSearchFilter(SourceFilter.PinnedOnly) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.PushPin,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(FilterChipDefaults.IconSize),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.pinned_sources))
|
||||
},
|
||||
)
|
||||
FilterChip(
|
||||
selected = sourceFilter == SourceFilter.All,
|
||||
onClick = { onChangeSearchFilter(SourceFilter.All) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.DoneAll,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(FilterChipDefaults.IconSize),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.all))
|
||||
},
|
||||
)
|
||||
|
||||
VerticalDivider()
|
||||
|
||||
FilterChip(
|
||||
selected = onlyShowHasResults,
|
||||
onClick = { onToggleResults() },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.FilterList,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(FilterChipDefaults.IconSize),
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.has_results))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,13 @@ class MigrateSearchScreen(private val mangaId: Long) : Screen() {
|
||||
val state by screenModel.state.collectAsState()
|
||||
|
||||
MigrateSearchScreen(
|
||||
navigateUp = navigator::pop,
|
||||
state = state,
|
||||
getManga = { screenModel.getManga(it) },
|
||||
navigateUp = navigator::pop,
|
||||
onChangeSearchQuery = screenModel::updateSearchQuery,
|
||||
onSearch = screenModel::search,
|
||||
getManga = { screenModel.getManga(it) },
|
||||
onChangeSearchFilter = screenModel::setSourceFilter,
|
||||
onToggleResults = screenModel::toggleFilterResults,
|
||||
onClickSource = {
|
||||
if (!screenModel.incognitoMode.get()) {
|
||||
screenModel.lastUsedSourceId.set(it.id)
|
||||
|
@ -7,6 +7,7 @@ import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchScreenModel
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
@ -23,6 +24,9 @@ class MigrateSearchScreenModel(
|
||||
private val getManga: GetManga = Injekt.get(),
|
||||
) : SearchScreenModel<MigrateSearchScreenModel.State>(State()) {
|
||||
|
||||
val incognitoMode = preferences.incognitoMode()
|
||||
val lastUsedSourceId = sourcePreferences.lastUsedSource()
|
||||
|
||||
init {
|
||||
coroutineScope.launch {
|
||||
val manga = getManga.await(mangaId)!!
|
||||
@ -35,15 +39,13 @@ class MigrateSearchScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
val incognitoMode = preferences.incognitoMode()
|
||||
val lastUsedSourceId = sourcePreferences.lastUsedSource()
|
||||
|
||||
override fun getEnabledSources(): List<CatalogueSource> {
|
||||
val enabledLanguages = sourcePreferences.enabledLanguages().get()
|
||||
val disabledSources = sourcePreferences.disabledSources().get()
|
||||
val pinnedSources = sourcePreferences.pinnedSources().get()
|
||||
|
||||
return sourceManager.getCatalogueSources()
|
||||
.filter { mutableState.value.sourceFilter != SourceFilter.PinnedOnly || "${it.id}" in pinnedSources }
|
||||
.filter { it.lang in enabledLanguages }
|
||||
.filterNot { "${it.id}" in disabledSources }
|
||||
.sortedWith(compareBy({ "${it.id}" !in pinnedSources }, { "${it.name.lowercase()} (${it.lang})" }))
|
||||
@ -66,6 +68,16 @@ class MigrateSearchScreenModel(
|
||||
return mutableState.value.items
|
||||
}
|
||||
|
||||
fun setSourceFilter(filter: SourceFilter) {
|
||||
mutableState.update { it.copy(sourceFilter = filter) }
|
||||
}
|
||||
|
||||
fun toggleFilterResults() {
|
||||
mutableState.update {
|
||||
it.copy(onlyShowHasResults = !it.onlyShowHasResults)
|
||||
}
|
||||
}
|
||||
|
||||
fun setDialog(dialog: MigrateSearchDialog?) {
|
||||
mutableState.update {
|
||||
it.copy(dialog = dialog)
|
||||
@ -75,12 +87,16 @@ class MigrateSearchScreenModel(
|
||||
@Immutable
|
||||
data class State(
|
||||
val manga: Manga? = null,
|
||||
val searchQuery: String? = null,
|
||||
val items: Map<CatalogueSource, SearchItemResult> = emptyMap(),
|
||||
val dialog: MigrateSearchDialog? = null,
|
||||
|
||||
val searchQuery: String? = null,
|
||||
val sourceFilter: SourceFilter = SourceFilter.PinnedOnly,
|
||||
val onlyShowHasResults: Boolean = false,
|
||||
val items: Map<CatalogueSource, SearchItemResult> = emptyMap(),
|
||||
) {
|
||||
val progress: Int = items.count { it.value !is SearchItemResult.Loading }
|
||||
val total: Int = items.size
|
||||
val filteredItems = items.filter { (_, result) -> result.isVisible(onlyShowHasResults) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ class GlobalSearchScreenModel(
|
||||
|
||||
val incognitoMode = preferences.incognitoMode()
|
||||
val lastUsedSourceId = sourcePreferences.lastUsedSource()
|
||||
|
||||
init {
|
||||
extensionFilter = initialExtensionFilter
|
||||
if (initialQuery.isNotBlank() || !initialExtensionFilter.isNullOrBlank()) {
|
||||
@ -76,7 +77,3 @@ class GlobalSearchScreenModel(
|
||||
val filteredItems = items.filter { (_, result) -> result.isVisible(onlyShowHasResults) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun SearchItemResult.isVisible(onlyShowHasResults: Boolean): Boolean {
|
||||
return !onlyShowHasResults || (this is SearchItemResult.Success && !this.isEmpty)
|
||||
}
|
||||
|
@ -145,4 +145,8 @@ sealed class SearchItemResult {
|
||||
val isEmpty: Boolean
|
||||
get() = result.isEmpty()
|
||||
}
|
||||
|
||||
fun isVisible(onlyShowHasResults: Boolean): Boolean {
|
||||
return !onlyShowHasResults || (this is Success && !this.isEmpty)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user