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.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>, 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) { listOf( EmptyScreenAction( stringResId = R.string.local_source_help_guide, icon = Icons.Outlined.HelpOutline, onClick = onLocalSourceHelpClick, ), ) } else { listOf( 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), ) } }