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.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.GlobalSearchFilter import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchState import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult 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.padding @Composable fun GlobalSearchScreen( state: GlobalSearchState, items: Map, navigateUp: () -> Unit, onChangeSearchQuery: (String?) -> Unit, onSearch: (String) -> Unit, onChangeFilter: (GlobalSearchFilter) -> Unit, getManga: @Composable (Manga) -> State, onClickSource: (CatalogueSource) -> Unit, onClickItem: (Manga) -> Unit, onLongClickItem: (Manga) -> Unit, ) { Scaffold( topBar = { scrollBehavior -> Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) { GlobalSearchToolbar( searchQuery = state.searchQuery, progress = state.progress, total = state.total, navigateUp = navigateUp, onChangeSearchQuery = onChangeSearchQuery, onSearch = onSearch, scrollBehavior = scrollBehavior, ) Row( modifier = Modifier .horizontalScroll(rememberScrollState()) .padding(horizontal = MaterialTheme.padding.small), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), ) { FilterChip( selected = state.searchFilter == GlobalSearchFilter.All, onClick = { onChangeFilter(GlobalSearchFilter.All) }, leadingIcon = { Icon( imageVector = Icons.Outlined.DoneAll, contentDescription = "", modifier = Modifier .size(FilterChipDefaults.IconSize), ) }, label = { Text(text = stringResource(id = R.string.all)) }, ) FilterChip( selected = state.searchFilter == GlobalSearchFilter.PinnedOnly, onClick = { onChangeFilter(GlobalSearchFilter.PinnedOnly) }, leadingIcon = { Icon( imageVector = Icons.Outlined.PushPin, contentDescription = "", modifier = Modifier .size(FilterChipDefaults.IconSize), ) }, label = { Text(text = stringResource(id = R.string.pinned_sources)) }, ) FilterChip( selected = state.searchFilter == GlobalSearchFilter.AvailableOnly, onClick = { onChangeFilter(GlobalSearchFilter.AvailableOnly) }, leadingIcon = { Icon( imageVector = Icons.Outlined.FilterList, contentDescription = "", modifier = Modifier .size(FilterChipDefaults.IconSize), ) }, label = { Text(text = stringResource(id = R.string.has_results)) }, ) } Divider() } }, ) { paddingValues -> GlobalSearchContent( items = items, contentPadding = paddingValues, getManga = getManga, onClickSource = onClickSource, onClickItem = onClickItem, onLongClickItem = onLongClickItem, ) } } @Composable private fun GlobalSearchContent( items: Map, contentPadding: PaddingValues, getManga: @Composable (Manga) -> State, onClickSource: (CatalogueSource) -> Unit, onClickItem: (Manga) -> Unit, onLongClickItem: (Manga) -> Unit, ) { LazyColumn( contentPadding = contentPadding, ) { items.forEach { (source, result) -> item(key = source.id) { GlobalSearchResultItem( title = source.name, subtitle = LocaleHelper.getDisplayName(source.lang), onClick = { onClickSource(source) }, ) { when (result) { SearchItemResult.Loading -> { GlobalSearchLoadingResultItem() } is SearchItemResult.Success -> { if (result.isEmpty) { Text( text = stringResource(R.string.no_results_found), modifier = Modifier .padding( horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small, ), ) return@GlobalSearchResultItem } GlobalSearchCardRow( titles = result.result, getManga = getManga, onClick = onClickItem, onLongClick = onLongClickItem, ) } is SearchItemResult.Error -> { GlobalSearchErrorResultItem(message = result.throwable.message) } } } } } } }