|
@@ -1,10 +1,18 @@
|
|
|
package eu.kanade.presentation.browse
|
|
|
|
|
|
+import androidx.compose.animation.AnimatedVisibility
|
|
|
+import androidx.compose.foundation.layout.Arrangement
|
|
|
import androidx.compose.foundation.layout.PaddingValues
|
|
|
+import androidx.compose.foundation.layout.Row
|
|
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
|
|
+import androidx.compose.foundation.layout.size
|
|
|
import androidx.compose.foundation.lazy.grid.GridCells
|
|
|
import androidx.compose.material.icons.Icons
|
|
|
+import androidx.compose.material.icons.outlined.Favorite
|
|
|
import androidx.compose.material.icons.outlined.FilterList
|
|
|
+import androidx.compose.material.icons.outlined.NewReleases
|
|
|
+import androidx.compose.material3.FilterChip
|
|
|
+import androidx.compose.material3.FilterChipDefaults
|
|
|
import androidx.compose.material3.Icon
|
|
|
import androidx.compose.material3.SnackbarDuration
|
|
|
import androidx.compose.material3.SnackbarHost
|
|
@@ -20,22 +28,24 @@ import androidx.compose.ui.Modifier
|
|
|
import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.platform.LocalUriHandler
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
+import androidx.compose.ui.unit.dp
|
|
|
import androidx.paging.LoadState
|
|
|
import androidx.paging.compose.LazyPagingItems
|
|
|
import androidx.paging.compose.collectAsLazyPagingItems
|
|
|
+import eu.kanade.data.source.NoResultsException
|
|
|
import eu.kanade.domain.manga.model.Manga
|
|
|
+import eu.kanade.domain.source.interactor.GetRemoteManga
|
|
|
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.browse.components.BrowseSourceToolbar
|
|
|
import eu.kanade.presentation.components.EmptyScreen
|
|
|
import eu.kanade.presentation.components.ExtendedFloatingActionButton
|
|
|
+import eu.kanade.presentation.components.LoadingScreen
|
|
|
import eu.kanade.presentation.components.Scaffold
|
|
|
import eu.kanade.tachiyomi.R
|
|
|
-import eu.kanade.tachiyomi.source.CatalogueSource
|
|
|
import eu.kanade.tachiyomi.source.LocalSource
|
|
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
|
|
-import eu.kanade.tachiyomi.ui.browse.source.browse.NoResultsException
|
|
|
import eu.kanade.tachiyomi.ui.library.setting.LibraryDisplayMode
|
|
|
import eu.kanade.tachiyomi.ui.more.MoreController
|
|
|
import eu.kanade.tachiyomi.widget.EmptyView
|
|
@@ -44,7 +54,6 @@ import eu.kanade.tachiyomi.widget.EmptyView
|
|
|
fun BrowseSourceScreen(
|
|
|
presenter: BrowseSourcePresenter,
|
|
|
navigateUp: () -> Unit,
|
|
|
- onDisplayModeChange: (LibraryDisplayMode) -> Unit,
|
|
|
onFabClick: () -> Unit,
|
|
|
onMangaClick: (Manga) -> Unit,
|
|
|
onMangaLongClick: (Manga) -> Unit,
|
|
@@ -68,7 +77,7 @@ fun BrowseSourceScreen(
|
|
|
state = presenter,
|
|
|
source = presenter.source!!,
|
|
|
displayMode = presenter.displayMode,
|
|
|
- onDisplayModeChange = onDisplayModeChange,
|
|
|
+ onDisplayModeChange = { presenter.displayMode = it },
|
|
|
navigateUp = navigateUp,
|
|
|
onWebViewClick = onWebViewClick,
|
|
|
onHelpClick = onHelpClick,
|
|
@@ -77,21 +86,17 @@ fun BrowseSourceScreen(
|
|
|
)
|
|
|
},
|
|
|
floatingActionButton = {
|
|
|
- if (presenter.filters.isNotEmpty()) {
|
|
|
- ExtendedFloatingActionButton(
|
|
|
- modifier = Modifier.navigationBarsPadding(),
|
|
|
- text = { Text(text = stringResource(id = R.string.action_filter)) },
|
|
|
- icon = { Icon(Icons.Outlined.FilterList, contentDescription = "") },
|
|
|
- onClick = onFabClick,
|
|
|
- )
|
|
|
- }
|
|
|
+ BrowseSourceFloatingActionButton(
|
|
|
+ isVisible = presenter.filters.isNotEmpty(),
|
|
|
+ onFabClick = onFabClick,
|
|
|
+ )
|
|
|
},
|
|
|
snackbarHost = {
|
|
|
SnackbarHost(hostState = snackbarHostState)
|
|
|
},
|
|
|
) { paddingValues ->
|
|
|
BrowseSourceContent(
|
|
|
- source = presenter.source,
|
|
|
+ state = presenter,
|
|
|
mangaList = mangaList,
|
|
|
getMangaState = { presenter.getManga(it) },
|
|
|
columns = columns,
|
|
@@ -103,15 +108,93 @@ fun BrowseSourceScreen(
|
|
|
onLocalSourceHelpClick = onHelpClick,
|
|
|
onMangaClick = onMangaClick,
|
|
|
onMangaLongClick = onMangaLongClick,
|
|
|
+ header = {
|
|
|
+ Row(
|
|
|
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
|
|
|
+ ) {
|
|
|
+ FilterChip(
|
|
|
+ selected = presenter.currentQuery == GetRemoteManga.QUERY_POPULAR,
|
|
|
+ onClick = {
|
|
|
+ presenter.resetFilter()
|
|
|
+ presenter.search(GetRemoteManga.QUERY_POPULAR)
|
|
|
+ },
|
|
|
+ leadingIcon = {
|
|
|
+ Icon(
|
|
|
+ imageVector = Icons.Outlined.Favorite,
|
|
|
+ contentDescription = "",
|
|
|
+ modifier = Modifier
|
|
|
+ .size(FilterChipDefaults.IconSize),
|
|
|
+ )
|
|
|
+ },
|
|
|
+ label = {
|
|
|
+ Text(text = stringResource(id = R.string.popular))
|
|
|
+ },
|
|
|
+ )
|
|
|
+ if (presenter.source?.supportsLatest == true) {
|
|
|
+ FilterChip(
|
|
|
+ selected = presenter.currentQuery == GetRemoteManga.QUERY_LATEST,
|
|
|
+ onClick = {
|
|
|
+ presenter.resetFilter()
|
|
|
+ presenter.search(GetRemoteManga.QUERY_LATEST)
|
|
|
+ },
|
|
|
+ leadingIcon = {
|
|
|
+ Icon(
|
|
|
+ imageVector = Icons.Outlined.NewReleases,
|
|
|
+ contentDescription = "",
|
|
|
+ modifier = Modifier
|
|
|
+ .size(FilterChipDefaults.IconSize),
|
|
|
+ )
|
|
|
+ },
|
|
|
+ label = {
|
|
|
+ Text(text = stringResource(id = R.string.latest))
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+ if (presenter.filters.isNotEmpty()) {
|
|
|
+ FilterChip(
|
|
|
+ selected = presenter.currentQuery != GetRemoteManga.QUERY_POPULAR && presenter.currentQuery != GetRemoteManga.QUERY_LATEST,
|
|
|
+ onClick = onFabClick,
|
|
|
+ leadingIcon = {
|
|
|
+ Icon(
|
|
|
+ imageVector = Icons.Outlined.FilterList,
|
|
|
+ contentDescription = "",
|
|
|
+ modifier = Modifier
|
|
|
+ .size(FilterChipDefaults.IconSize),
|
|
|
+ )
|
|
|
+ },
|
|
|
+ label = {
|
|
|
+ Text(text = stringResource(id = R.string.action_filter))
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
+fun BrowseSourceFloatingActionButton(
|
|
|
+ modifier: Modifier = Modifier.navigationBarsPadding(),
|
|
|
+ isVisible: Boolean,
|
|
|
+ onFabClick: () -> Unit,
|
|
|
+) {
|
|
|
+ AnimatedVisibility(visible = isVisible) {
|
|
|
+ ExtendedFloatingActionButton(
|
|
|
+ modifier = modifier,
|
|
|
+ text = { Text(text = stringResource(id = R.string.action_filter)) },
|
|
|
+ icon = { Icon(Icons.Outlined.FilterList, contentDescription = "") },
|
|
|
+ onClick = onFabClick,
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Composable
|
|
|
fun BrowseSourceContent(
|
|
|
- source: CatalogueSource?,
|
|
|
+ state: BrowseSourceState,
|
|
|
mangaList: LazyPagingItems<Manga>,
|
|
|
getMangaState: @Composable ((Manga) -> State<Manga>),
|
|
|
+ header: (@Composable () -> Unit)? = null,
|
|
|
columns: GridCells,
|
|
|
displayMode: LibraryDisplayMode,
|
|
|
snackbarHostState: SnackbarHostState,
|
|
@@ -153,7 +236,7 @@ fun BrowseSourceContent(
|
|
|
if (mangaList.itemCount <= 0 && errorState != null && errorState is LoadState.Error) {
|
|
|
EmptyScreen(
|
|
|
message = getErrorMessage(errorState),
|
|
|
- actions = if (source is LocalSource) {
|
|
|
+ actions = if (state.source is LocalSource) {
|
|
|
listOf(
|
|
|
EmptyView.Action(R.string.local_source_help_guide, R.drawable.ic_help_24dp) { onLocalSourceHelpClick() },
|
|
|
)
|
|
@@ -169,6 +252,11 @@ fun BrowseSourceContent(
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+ if (mangaList.itemCount == 0 && mangaList.loadState.refresh is LoadState.Loading) {
|
|
|
+ LoadingScreen()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
when (displayMode) {
|
|
|
LibraryDisplayMode.ComfortableGrid -> {
|
|
|
BrowseSourceComfortableGrid(
|
|
@@ -178,6 +266,7 @@ fun BrowseSourceContent(
|
|
|
contentPadding = contentPadding,
|
|
|
onMangaClick = onMangaClick,
|
|
|
onMangaLongClick = onMangaLongClick,
|
|
|
+ header = header,
|
|
|
)
|
|
|
}
|
|
|
LibraryDisplayMode.List -> {
|
|
@@ -187,6 +276,7 @@ fun BrowseSourceContent(
|
|
|
contentPadding = contentPadding,
|
|
|
onMangaClick = onMangaClick,
|
|
|
onMangaLongClick = onMangaLongClick,
|
|
|
+ header = header,
|
|
|
)
|
|
|
}
|
|
|
else -> {
|
|
@@ -197,6 +287,7 @@ fun BrowseSourceContent(
|
|
|
contentPadding = contentPadding,
|
|
|
onMangaClick = onMangaClick,
|
|
|
onMangaLongClick = onMangaLongClick,
|
|
|
+ header = header,
|
|
|
)
|
|
|
}
|
|
|
}
|