Replicate global search filters to migrate screen

Still needs better refactoring to dedupe all of this stuff though...
This commit is contained in:
arkon 2023-07-16 17:09:59 -04:00
parent 8b46e8edad
commit dd3ca0c131
9 changed files with 182 additions and 145 deletions

View File

@ -1,45 +1,21 @@
package eu.kanade.presentation.browse 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.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.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.Composable
import androidx.compose.runtime.State 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.GlobalSearchCardRow
import eu.kanade.presentation.browse.components.GlobalSearchEmptyResultItem
import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem
import eu.kanade.presentation.browse.components.GlobalSearchResultItem import eu.kanade.presentation.browse.components.GlobalSearchResultItem
import eu.kanade.presentation.browse.components.GlobalSearchToolbar import eu.kanade.presentation.browse.components.GlobalSearchToolbar
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreenModel 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.SearchItemResult
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.domain.manga.model.Manga 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.Scaffold
import tachiyomi.presentation.core.components.material.VerticalDivider
import tachiyomi.presentation.core.components.material.padding
@Composable @Composable
fun GlobalSearchScreen( fun GlobalSearchScreen(
@ -56,76 +32,19 @@ fun GlobalSearchScreen(
) { ) {
Scaffold( Scaffold(
topBar = { scrollBehavior -> topBar = { scrollBehavior ->
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) { GlobalSearchToolbar(
GlobalSearchToolbar( searchQuery = state.searchQuery,
searchQuery = state.searchQuery, progress = state.progress,
progress = state.progress, total = state.total,
total = state.total, navigateUp = navigateUp,
navigateUp = navigateUp, onChangeSearchQuery = onChangeSearchQuery,
onChangeSearchQuery = onChangeSearchQuery, onSearch = onSearch,
onSearch = onSearch, sourceFilter = state.sourceFilter,
scrollBehavior = scrollBehavior, onChangeSearchFilter = onChangeSearchFilter,
) onlyShowHasResults = state.onlyShowHasResults,
onToggleResults = onToggleResults,
Row( scrollBehavior = scrollBehavior,
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 -> ) { paddingValues ->
GlobalSearchContent( GlobalSearchContent(
@ -141,7 +60,7 @@ fun GlobalSearchScreen(
@Composable @Composable
internal fun GlobalSearchContent( internal fun GlobalSearchContent(
sourceId: Long? = null, fromSourceId: Long? = null,
items: Map<CatalogueSource, SearchItemResult>, items: Map<CatalogueSource, SearchItemResult>,
contentPadding: PaddingValues, contentPadding: PaddingValues,
getManga: @Composable (Manga) -> State<Manga>, getManga: @Composable (Manga) -> State<Manga>,
@ -155,7 +74,7 @@ internal fun GlobalSearchContent(
items.forEach { (source, result) -> items.forEach { (source, result) ->
item(key = source.id) { item(key = source.id) {
GlobalSearchResultItem( 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), subtitle = LocaleHelper.getDisplayName(source.lang),
onClick = { onClickSource(source) }, onClick = { onClickSource(source) },
) { ) {
@ -164,11 +83,6 @@ internal fun GlobalSearchContent(
GlobalSearchLoadingResultItem() GlobalSearchLoadingResultItem()
} }
is SearchItemResult.Success -> { is SearchItemResult.Success -> {
if (result.isEmpty) {
GlobalSearchEmptyResultItem()
return@GlobalSearchResultItem
}
GlobalSearchCardRow( GlobalSearchCardRow(
titles = result.result, titles = result.result,
getManga = getManga, getManga = getManga,

View File

@ -5,16 +5,19 @@ import androidx.compose.runtime.State
import eu.kanade.presentation.browse.components.GlobalSearchToolbar import eu.kanade.presentation.browse.components.GlobalSearchToolbar
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateSearchScreenModel 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.domain.manga.model.Manga
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
@Composable @Composable
fun MigrateSearchScreen( fun MigrateSearchScreen(
navigateUp: () -> Unit,
state: MigrateSearchScreenModel.State, state: MigrateSearchScreenModel.State,
getManga: @Composable (Manga) -> State<Manga>, navigateUp: () -> Unit,
onChangeSearchQuery: (String?) -> Unit, onChangeSearchQuery: (String?) -> Unit,
onSearch: (String) -> Unit, onSearch: (String) -> Unit,
onChangeSearchFilter: (SourceFilter) -> Unit,
onToggleResults: () -> Unit,
getManga: @Composable (Manga) -> State<Manga>,
onClickSource: (CatalogueSource) -> Unit, onClickSource: (CatalogueSource) -> Unit,
onClickItem: (Manga) -> Unit, onClickItem: (Manga) -> Unit,
onLongClickItem: (Manga) -> Unit, onLongClickItem: (Manga) -> Unit,
@ -28,13 +31,17 @@ fun MigrateSearchScreen(
navigateUp = navigateUp, navigateUp = navigateUp,
onChangeSearchQuery = onChangeSearchQuery, onChangeSearchQuery = onChangeSearchQuery,
onSearch = onSearch, onSearch = onSearch,
sourceFilter = state.sourceFilter,
onChangeSearchFilter = onChangeSearchFilter,
onlyShowHasResults = state.onlyShowHasResults,
onToggleResults = onToggleResults,
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
) )
}, },
) { paddingValues -> ) { paddingValues ->
GlobalSearchContent( GlobalSearchContent(
sourceId = state.manga?.source, fromSourceId = state.manga?.source,
items = state.items, items = state.filteredItems,
contentPadding = paddingValues, contentPadding = paddingValues,
getManga = getManga, getManga = getManga,
onClickSource = onClickSource, onClickSource = onClickSource,

View File

@ -3,17 +3,21 @@ package eu.kanade.presentation.browse.components
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.library.components.CommonMangaItemDefaults import eu.kanade.presentation.library.components.CommonMangaItemDefaults
import eu.kanade.presentation.library.components.MangaComfortableGridItem import eu.kanade.presentation.library.components.MangaComfortableGridItem
import eu.kanade.tachiyomi.R
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaCover import tachiyomi.domain.manga.model.MangaCover
import tachiyomi.domain.manga.model.asMangaCover import tachiyomi.domain.manga.model.asMangaCover
@ -26,13 +30,18 @@ fun GlobalSearchCardRow(
onClick: (Manga) -> Unit, onClick: (Manga) -> Unit,
onLongClick: (Manga) -> Unit, onLongClick: (Manga) -> Unit,
) { ) {
if (titles.isEmpty()) {
EmptyResultItem()
return
}
LazyRow( LazyRow(
contentPadding = PaddingValues(MaterialTheme.padding.small), contentPadding = PaddingValues(MaterialTheme.padding.small),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.tiny), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.tiny),
) { ) {
items(titles) { items(titles) {
val title by getManga(it) val title by getManga(it)
GlobalSearchCard( MangaItem(
title = title.title, title = title.title,
cover = title.asMangaCover(), cover = title.asMangaCover(),
isFavorite = title.favorite, isFavorite = title.favorite,
@ -44,7 +53,7 @@ fun GlobalSearchCardRow(
} }
@Composable @Composable
private fun GlobalSearchCard( private fun MangaItem(
title: String, title: String,
cover: MangaCover, cover: MangaCover,
isFavorite: Boolean, 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,
),
)
}

View File

@ -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 @Composable
fun GlobalSearchLoadingResultItem() { fun GlobalSearchLoadingResultItem() {
Box( Box(

View File

@ -1,13 +1,36 @@
package eu.kanade.presentation.browse.components 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.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth 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.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import eu.kanade.presentation.components.SearchToolbar 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 @Composable
fun GlobalSearchToolbar( fun GlobalSearchToolbar(
@ -17,24 +40,89 @@ fun GlobalSearchToolbar(
navigateUp: () -> Unit, navigateUp: () -> Unit,
onChangeSearchQuery: (String?) -> Unit, onChangeSearchQuery: (String?) -> Unit,
onSearch: (String) -> Unit, onSearch: (String) -> Unit,
sourceFilter: SourceFilter,
onChangeSearchFilter: (SourceFilter) -> Unit,
onlyShowHasResults: Boolean,
onToggleResults: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior, scrollBehavior: TopAppBarScrollBehavior,
) { ) {
Box { Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
SearchToolbar( Box {
searchQuery = searchQuery, SearchToolbar(
onChangeSearchQuery = onChangeSearchQuery, searchQuery = searchQuery,
onSearch = onSearch, onChangeSearchQuery = onChangeSearchQuery,
onClickCloseSearch = navigateUp, onSearch = onSearch,
navigateUp = navigateUp, onClickCloseSearch = navigateUp,
scrollBehavior = scrollBehavior, navigateUp = navigateUp,
) scrollBehavior = scrollBehavior,
if (progress in 1 until total) { )
LinearProgressIndicator( if (progress in 1 until total) {
progress = progress / total.toFloat(), LinearProgressIndicator(
modifier = Modifier progress = progress / total.toFloat(),
.align(Alignment.BottomStart) modifier = Modifier
.fillMaxWidth(), .align(Alignment.BottomStart)
.fillMaxWidth(),
)
}
}
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()
} }
} }

View File

@ -21,11 +21,13 @@ class MigrateSearchScreen(private val mangaId: Long) : Screen() {
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()
MigrateSearchScreen( MigrateSearchScreen(
navigateUp = navigator::pop,
state = state, state = state,
getManga = { screenModel.getManga(it) }, navigateUp = navigator::pop,
onChangeSearchQuery = screenModel::updateSearchQuery, onChangeSearchQuery = screenModel::updateSearchQuery,
onSearch = screenModel::search, onSearch = screenModel::search,
getManga = { screenModel.getManga(it) },
onChangeSearchFilter = screenModel::setSourceFilter,
onToggleResults = screenModel::toggleFilterResults,
onClickSource = { onClickSource = {
if (!screenModel.incognitoMode.get()) { if (!screenModel.incognitoMode.get()) {
screenModel.lastUsedSourceId.set(it.id) screenModel.lastUsedSourceId.set(it.id)

View File

@ -7,6 +7,7 @@ import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult 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.SearchScreenModel
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.interactor.GetManga
@ -23,6 +24,9 @@ class MigrateSearchScreenModel(
private val getManga: GetManga = Injekt.get(), private val getManga: GetManga = Injekt.get(),
) : SearchScreenModel<MigrateSearchScreenModel.State>(State()) { ) : SearchScreenModel<MigrateSearchScreenModel.State>(State()) {
val incognitoMode = preferences.incognitoMode()
val lastUsedSourceId = sourcePreferences.lastUsedSource()
init { init {
coroutineScope.launch { coroutineScope.launch {
val manga = getManga.await(mangaId)!! val manga = getManga.await(mangaId)!!
@ -35,15 +39,13 @@ class MigrateSearchScreenModel(
} }
} }
val incognitoMode = preferences.incognitoMode()
val lastUsedSourceId = sourcePreferences.lastUsedSource()
override fun getEnabledSources(): List<CatalogueSource> { override fun getEnabledSources(): List<CatalogueSource> {
val enabledLanguages = sourcePreferences.enabledLanguages().get() val enabledLanguages = sourcePreferences.enabledLanguages().get()
val disabledSources = sourcePreferences.disabledSources().get() val disabledSources = sourcePreferences.disabledSources().get()
val pinnedSources = sourcePreferences.pinnedSources().get() val pinnedSources = sourcePreferences.pinnedSources().get()
return sourceManager.getCatalogueSources() return sourceManager.getCatalogueSources()
.filter { mutableState.value.sourceFilter != SourceFilter.PinnedOnly || "${it.id}" in pinnedSources }
.filter { it.lang in enabledLanguages } .filter { it.lang in enabledLanguages }
.filterNot { "${it.id}" in disabledSources } .filterNot { "${it.id}" in disabledSources }
.sortedWith(compareBy({ "${it.id}" !in pinnedSources }, { "${it.name.lowercase()} (${it.lang})" })) .sortedWith(compareBy({ "${it.id}" !in pinnedSources }, { "${it.name.lowercase()} (${it.lang})" }))
@ -66,6 +68,16 @@ class MigrateSearchScreenModel(
return mutableState.value.items 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?) { fun setDialog(dialog: MigrateSearchDialog?) {
mutableState.update { mutableState.update {
it.copy(dialog = dialog) it.copy(dialog = dialog)
@ -75,12 +87,16 @@ class MigrateSearchScreenModel(
@Immutable @Immutable
data class State( data class State(
val manga: Manga? = null, val manga: Manga? = null,
val searchQuery: String? = null,
val items: Map<CatalogueSource, SearchItemResult> = emptyMap(),
val dialog: MigrateSearchDialog? = null, 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 progress: Int = items.count { it.value !is SearchItemResult.Loading }
val total: Int = items.size val total: Int = items.size
val filteredItems = items.filter { (_, result) -> result.isVisible(onlyShowHasResults) }
} }
} }

View File

@ -19,6 +19,7 @@ class GlobalSearchScreenModel(
val incognitoMode = preferences.incognitoMode() val incognitoMode = preferences.incognitoMode()
val lastUsedSourceId = sourcePreferences.lastUsedSource() val lastUsedSourceId = sourcePreferences.lastUsedSource()
init { init {
extensionFilter = initialExtensionFilter extensionFilter = initialExtensionFilter
if (initialQuery.isNotBlank() || !initialExtensionFilter.isNullOrBlank()) { if (initialQuery.isNotBlank() || !initialExtensionFilter.isNullOrBlank()) {
@ -76,7 +77,3 @@ class GlobalSearchScreenModel(
val filteredItems = items.filter { (_, result) -> result.isVisible(onlyShowHasResults) } val filteredItems = items.filter { (_, result) -> result.isVisible(onlyShowHasResults) }
} }
} }
private fun SearchItemResult.isVisible(onlyShowHasResults: Boolean): Boolean {
return !onlyShowHasResults || (this is SearchItemResult.Success && !this.isEmpty)
}

View File

@ -145,4 +145,8 @@ sealed class SearchItemResult {
val isEmpty: Boolean val isEmpty: Boolean
get() = result.isEmpty() get() = result.isEmpty()
} }
fun isVisible(onlyShowHasResults: Boolean): Boolean {
return !onlyShowHasResults || (this is Success && !this.isEmpty)
}
} }