123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package eu.kanade.presentation.browse
- import androidx.compose.foundation.layout.PaddingValues
- import androidx.compose.foundation.layout.padding
- import androidx.compose.foundation.lazy.grid.GridCells
- import androidx.compose.material.icons.Icons
- import androidx.compose.material.icons.outlined.HelpOutline
- import androidx.compose.material.icons.outlined.Public
- import androidx.compose.material.icons.outlined.Refresh
- import androidx.compose.material3.SnackbarDuration
- import androidx.compose.material3.SnackbarHostState
- import androidx.compose.material3.SnackbarResult
- import androidx.compose.runtime.Composable
- import androidx.compose.runtime.LaunchedEffect
- import androidx.compose.ui.Modifier
- import androidx.compose.ui.platform.LocalContext
- import androidx.compose.ui.res.stringResource
- import androidx.paging.LoadState
- import androidx.paging.compose.LazyPagingItems
- import eu.kanade.presentation.browse.components.BrowseSourceComfortableGrid
- import eu.kanade.presentation.browse.components.BrowseSourceCompactGrid
- import eu.kanade.presentation.browse.components.BrowseSourceList
- import eu.kanade.presentation.components.AppBar
- import eu.kanade.presentation.util.formattedMessage
- import eu.kanade.tachiyomi.R
- import eu.kanade.tachiyomi.source.Source
- import kotlinx.collections.immutable.persistentListOf
- import kotlinx.coroutines.flow.StateFlow
- import tachiyomi.domain.library.model.LibraryDisplayMode
- import tachiyomi.domain.manga.model.Manga
- import tachiyomi.domain.source.model.StubSource
- import tachiyomi.presentation.core.components.material.Scaffold
- import tachiyomi.presentation.core.screens.EmptyScreen
- import tachiyomi.presentation.core.screens.EmptyScreenAction
- import tachiyomi.presentation.core.screens.LoadingScreen
- import tachiyomi.source.local.LocalSource
- @Composable
- fun BrowseSourceContent(
- source: Source?,
- mangaList: LazyPagingItems<StateFlow<Manga>>,
- columns: GridCells,
- displayMode: LibraryDisplayMode,
- snackbarHostState: SnackbarHostState,
- contentPadding: PaddingValues,
- onWebViewClick: () -> Unit,
- onHelpClick: () -> Unit,
- onLocalSourceHelpClick: () -> Unit,
- onMangaClick: (Manga) -> Unit,
- onMangaLongClick: (Manga) -> Unit,
- ) {
- val context = LocalContext.current
- val errorState = mangaList.loadState.refresh.takeIf { it is LoadState.Error }
- ?: mangaList.loadState.append.takeIf { it is LoadState.Error }
- val getErrorMessage: (LoadState.Error) -> String = { state ->
- with(context) { state.error.formattedMessage }
- }
- LaunchedEffect(errorState) {
- if (mangaList.itemCount > 0 && errorState != null && errorState is LoadState.Error) {
- val result = snackbarHostState.showSnackbar(
- message = getErrorMessage(errorState),
- actionLabel = context.getString(R.string.action_retry),
- duration = SnackbarDuration.Indefinite,
- )
- when (result) {
- SnackbarResult.Dismissed -> snackbarHostState.currentSnackbarData?.dismiss()
- SnackbarResult.ActionPerformed -> mangaList.retry()
- }
- }
- }
- if (mangaList.itemCount <= 0 && errorState != null && errorState is LoadState.Error) {
- EmptyScreen(
- modifier = Modifier.padding(contentPadding),
- message = getErrorMessage(errorState),
- actions = if (source is LocalSource) {
- persistentListOf(
- EmptyScreenAction(
- stringResId = R.string.local_source_help_guide,
- icon = Icons.Outlined.HelpOutline,
- onClick = onLocalSourceHelpClick,
- ),
- )
- } else {
- persistentListOf(
- EmptyScreenAction(
- stringResId = R.string.action_retry,
- icon = Icons.Outlined.Refresh,
- onClick = mangaList::refresh,
- ),
- EmptyScreenAction(
- stringResId = R.string.action_open_in_web_view,
- icon = Icons.Outlined.Public,
- onClick = onWebViewClick,
- ),
- EmptyScreenAction(
- stringResId = R.string.label_help,
- icon = Icons.Outlined.HelpOutline,
- onClick = onHelpClick,
- ),
- )
- },
- )
- return
- }
- if (mangaList.itemCount == 0 && mangaList.loadState.refresh is LoadState.Loading) {
- LoadingScreen(
- modifier = Modifier.padding(contentPadding),
- )
- return
- }
- when (displayMode) {
- LibraryDisplayMode.ComfortableGrid -> {
- BrowseSourceComfortableGrid(
- mangaList = mangaList,
- columns = columns,
- contentPadding = contentPadding,
- onMangaClick = onMangaClick,
- onMangaLongClick = onMangaLongClick,
- )
- }
- LibraryDisplayMode.List -> {
- BrowseSourceList(
- mangaList = mangaList,
- contentPadding = contentPadding,
- onMangaClick = onMangaClick,
- onMangaLongClick = onMangaLongClick,
- )
- }
- LibraryDisplayMode.CompactGrid, LibraryDisplayMode.CoverOnlyGrid -> {
- BrowseSourceCompactGrid(
- mangaList = mangaList,
- columns = columns,
- contentPadding = contentPadding,
- onMangaClick = onMangaClick,
- onMangaLongClick = onMangaLongClick,
- )
- }
- }
- }
- @Composable
- fun MissingSourceScreen(
- source: StubSource,
- navigateUp: () -> Unit,
- ) {
- Scaffold(
- topBar = { scrollBehavior ->
- AppBar(
- title = source.name,
- navigateUp = navigateUp,
- scrollBehavior = scrollBehavior,
- )
- },
- ) { paddingValues ->
- EmptyScreen(
- message = stringResource(R.string.source_not_installed, source.toString()),
- modifier = Modifier.padding(paddingValues),
- )
- }
- }
|