mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-12 03:58:56 +01:00
Merge Latest and Browse into one screen (#7921)
* Merge Latest and Browse into one * Add back Latest button * Change context to IO instead of launching a job * Use loading screen when loading initial page
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
package eu.kanade.presentation.browse
|
||||
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.presentation.browse.components.BrowseLatestToolbar
|
||||
import eu.kanade.presentation.components.Scaffold
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||
import eu.kanade.tachiyomi.ui.more.MoreController
|
||||
|
||||
@Composable
|
||||
fun BrowseLatestScreen(
|
||||
presenter: BrowseSourcePresenter,
|
||||
navigateUp: () -> Unit,
|
||||
onMangaClick: (Manga) -> Unit,
|
||||
onMangaLongClick: (Manga) -> Unit,
|
||||
onWebViewClick: () -> Unit,
|
||||
) {
|
||||
val columns by presenter.getColumnsPreferenceForCurrentOrientation()
|
||||
|
||||
val uriHandler = LocalUriHandler.current
|
||||
|
||||
val onHelpClick = {
|
||||
uriHandler.openUri(LocalSource.HELP_URL)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
BrowseLatestToolbar(
|
||||
navigateUp = navigateUp,
|
||||
source = presenter.source!!,
|
||||
displayMode = presenter.displayMode,
|
||||
onDisplayModeChange = { presenter.displayMode = it },
|
||||
onHelpClick = onHelpClick,
|
||||
onWebViewClick = onWebViewClick,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
BrowseSourceContent(
|
||||
source = presenter.source,
|
||||
mangaList = presenter.getMangaList().collectAsLazyPagingItems(),
|
||||
getMangaState = { presenter.getManga(it) },
|
||||
columns = columns,
|
||||
displayMode = presenter.displayMode,
|
||||
snackbarHostState = remember { SnackbarHostState() },
|
||||
contentPadding = paddingValues,
|
||||
onWebViewClick = onWebViewClick,
|
||||
onHelpClick = { uriHandler.openUri(MoreController.URL_HELP) },
|
||||
onLocalSourceHelpClick = onHelpClick,
|
||||
onMangaClick = onMangaClick,
|
||||
onMangaLongClick = onMangaLongClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.domain.source.interactor.GetRemoteManga
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||
@@ -16,22 +17,31 @@ interface BrowseSourceState {
|
||||
val source: CatalogueSource?
|
||||
var searchQuery: String?
|
||||
val currentQuery: String
|
||||
val isUserQuery: Boolean
|
||||
val filters: FilterList
|
||||
val filterItems: List<IFlexible<*>>
|
||||
val appliedFilters: FilterList
|
||||
val currentFilters: FilterList
|
||||
var dialog: BrowseSourcePresenter.Dialog?
|
||||
}
|
||||
|
||||
fun BrowseSourceState(initialQuery: String?): BrowseSourceState {
|
||||
return BrowseSourceStateImpl(initialQuery)
|
||||
if (initialQuery == GetRemoteManga.QUERY_POPULAR || initialQuery == GetRemoteManga.QUERY_LATEST) {
|
||||
return BrowseSourceStateImpl(initialCurrentQuery = initialQuery)
|
||||
}
|
||||
return BrowseSourceStateImpl(initialQuery = initialQuery)
|
||||
}
|
||||
|
||||
class BrowseSourceStateImpl(initialQuery: String?) : BrowseSourceState {
|
||||
class BrowseSourceStateImpl(initialQuery: String? = null, initialCurrentQuery: String? = initialQuery) : BrowseSourceState {
|
||||
override var source: CatalogueSource? by mutableStateOf(null)
|
||||
override var searchQuery: String? by mutableStateOf(initialQuery)
|
||||
override var currentQuery: String by mutableStateOf(initialQuery ?: "")
|
||||
override var currentQuery: String by mutableStateOf(initialCurrentQuery ?: "")
|
||||
override val isUserQuery: Boolean by derivedStateOf {
|
||||
currentQuery.isNotEmpty() &&
|
||||
currentQuery != GetRemoteManga.QUERY_POPULAR &&
|
||||
currentQuery != GetRemoteManga.QUERY_LATEST
|
||||
}
|
||||
override var filters: FilterList by mutableStateOf(FilterList())
|
||||
override val filterItems: List<IFlexible<*>> by derivedStateOf { filters.toItems() }
|
||||
override var appliedFilters by mutableStateOf(FilterList())
|
||||
override var currentFilters by mutableStateOf(FilterList())
|
||||
override var dialog: BrowseSourcePresenter.Dialog? by mutableStateOf(null)
|
||||
}
|
||||
|
||||
@@ -1,32 +1,73 @@
|
||||
package eu.kanade.presentation.browse
|
||||
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceSearchToolbar
|
||||
import eu.kanade.presentation.components.Scaffold
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.ui.more.MoreController
|
||||
|
||||
@Composable
|
||||
fun SourceSearchScreen(
|
||||
presenter: BrowseSourcePresenter,
|
||||
navigateUp: () -> Unit,
|
||||
onFabClick: () -> Unit,
|
||||
onClickManga: (Manga) -> Unit,
|
||||
onMangaClick: (Manga) -> Unit,
|
||||
onWebViewClick: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val columns by presenter.getColumnsPreferenceForCurrentOrientation()
|
||||
|
||||
BrowseSourceScreen(
|
||||
presenter = presenter,
|
||||
navigateUp = navigateUp,
|
||||
onDisplayModeChange = { presenter.displayMode = (it) },
|
||||
onFabClick = onFabClick,
|
||||
onMangaClick = onClickManga,
|
||||
onMangaLongClick = onClickManga,
|
||||
onWebViewClick = f@{
|
||||
val source = presenter.source as? HttpSource ?: return@f
|
||||
val intent = WebViewActivity.newIntent(context, source.baseUrl, source.id, source.name)
|
||||
context.startActivity(intent)
|
||||
val mangaList = presenter.getMangaList().collectAsLazyPagingItems()
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
||||
val uriHandler = LocalUriHandler.current
|
||||
|
||||
val onHelpClick = {
|
||||
uriHandler.openUri(LocalSource.HELP_URL)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
BrowseSourceSearchToolbar(
|
||||
searchQuery = presenter.searchQuery ?: "",
|
||||
onSearchQueryChanged = { presenter.searchQuery = it },
|
||||
navigateUp = navigateUp,
|
||||
onResetClick = { presenter.searchQuery = "" },
|
||||
onSearchClick = { presenter.search() },
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
},
|
||||
)
|
||||
floatingActionButton = {
|
||||
BrowseSourceFloatingActionButton(
|
||||
isVisible = presenter.filters.isNotEmpty(),
|
||||
onFabClick = onFabClick,
|
||||
)
|
||||
},
|
||||
snackbarHost = {
|
||||
SnackbarHost(hostState = snackbarHostState)
|
||||
},
|
||||
) { paddingValues ->
|
||||
BrowseSourceContent(
|
||||
state = presenter,
|
||||
mangaList = mangaList,
|
||||
getMangaState = { presenter.getManga(it) },
|
||||
columns = columns,
|
||||
displayMode = presenter.displayMode,
|
||||
snackbarHostState = snackbarHostState,
|
||||
contentPadding = paddingValues,
|
||||
onWebViewClick = onWebViewClick,
|
||||
onHelpClick = { uriHandler.openUri(MoreController.URL_HELP) },
|
||||
onLocalSourceHelpClick = onHelpClick,
|
||||
onMangaClick = onMangaClick,
|
||||
onMangaLongClick = onMangaClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.source.interactor.GetRemoteManga
|
||||
import eu.kanade.domain.source.model.Pin
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.presentation.browse.components.BaseSourceItem
|
||||
@@ -45,9 +46,8 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
@Composable
|
||||
fun SourcesScreen(
|
||||
presenter: SourcesPresenter,
|
||||
onClickItem: (Source) -> Unit,
|
||||
onClickItem: (Source, String) -> Unit,
|
||||
onClickDisable: (Source) -> Unit,
|
||||
onClickLatest: (Source) -> Unit,
|
||||
onClickPin: (Source) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@@ -59,7 +59,6 @@ fun SourcesScreen(
|
||||
state = presenter,
|
||||
onClickItem = onClickItem,
|
||||
onClickDisable = onClickDisable,
|
||||
onClickLatest = onClickLatest,
|
||||
onClickPin = onClickPin,
|
||||
)
|
||||
}
|
||||
@@ -78,9 +77,8 @@ fun SourcesScreen(
|
||||
@Composable
|
||||
fun SourceList(
|
||||
state: SourcesState,
|
||||
onClickItem: (Source) -> Unit,
|
||||
onClickItem: (Source, String) -> Unit,
|
||||
onClickDisable: (Source) -> Unit,
|
||||
onClickLatest: (Source) -> Unit,
|
||||
onClickPin: (Source) -> Unit,
|
||||
) {
|
||||
ScrollbarLazyColumn(
|
||||
@@ -113,7 +111,6 @@ fun SourceList(
|
||||
source = model.source,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = { state.dialog = SourcesPresenter.Dialog(it) },
|
||||
onClickLatest = onClickLatest,
|
||||
onClickPin = onClickPin,
|
||||
)
|
||||
}
|
||||
@@ -155,19 +152,18 @@ fun SourceHeader(
|
||||
fun SourceItem(
|
||||
modifier: Modifier = Modifier,
|
||||
source: Source,
|
||||
onClickItem: (Source) -> Unit,
|
||||
onClickItem: (Source, String) -> Unit,
|
||||
onLongClickItem: (Source) -> Unit,
|
||||
onClickLatest: (Source) -> Unit,
|
||||
onClickPin: (Source) -> Unit,
|
||||
) {
|
||||
BaseSourceItem(
|
||||
modifier = modifier,
|
||||
source = source,
|
||||
onClickItem = { onClickItem(source) },
|
||||
onClickItem = { onClickItem(source, GetRemoteManga.QUERY_POPULAR) },
|
||||
onLongClickItem = { onLongClickItem(source) },
|
||||
action = { source ->
|
||||
if (source.supportsLatest) {
|
||||
TextButton(onClick = { onClickLatest(source) }) {
|
||||
TextButton(onClick = { onClickItem(source, GetRemoteManga.QUERY_LATEST) }) {
|
||||
Text(
|
||||
text = stringResource(R.string.latest),
|
||||
style = LocalTextStyle.current.copy(
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
package eu.kanade.presentation.browse.components
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ViewModule
|
||||
import androidx.compose.material.icons.outlined.Check
|
||||
import androidx.compose.material.icons.outlined.Help
|
||||
import androidx.compose.material.icons.outlined.Public
|
||||
import androidx.compose.material.icons.outlined.ViewModule
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.ui.library.setting.LibraryDisplayMode
|
||||
|
||||
@Composable
|
||||
fun BrowseLatestToolbar(
|
||||
navigateUp: () -> Unit,
|
||||
source: CatalogueSource,
|
||||
displayMode: LibraryDisplayMode,
|
||||
onDisplayModeChange: (LibraryDisplayMode) -> Unit,
|
||||
onHelpClick: () -> Unit,
|
||||
onWebViewClick: () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
) {
|
||||
AppBar(
|
||||
navigateUp = navigateUp,
|
||||
title = source.name,
|
||||
actions = {
|
||||
var selectingDisplayMode by remember { mutableStateOf(false) }
|
||||
AppBarActions(
|
||||
actions = listOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(id = R.string.action_display_mode),
|
||||
icon = Icons.Filled.ViewModule,
|
||||
onClick = { selectingDisplayMode = true },
|
||||
),
|
||||
if (source is LocalSource) {
|
||||
AppBar.Action(
|
||||
title = stringResource(id = R.string.label_help),
|
||||
icon = Icons.Outlined.Help,
|
||||
onClick = onHelpClick,
|
||||
)
|
||||
} else {
|
||||
AppBar.Action(
|
||||
title = stringResource(id = R.string.action_web_view),
|
||||
icon = Icons.Outlined.Public,
|
||||
onClick = onWebViewClick,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = selectingDisplayMode,
|
||||
onDismissRequest = { selectingDisplayMode = false },
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(id = R.string.action_display_comfortable_grid)) },
|
||||
onClick = { onDisplayModeChange(LibraryDisplayMode.ComfortableGrid) },
|
||||
trailingIcon = {
|
||||
if (displayMode == LibraryDisplayMode.ComfortableGrid) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Check,
|
||||
contentDescription = "",
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(id = R.string.action_display_grid)) },
|
||||
onClick = { onDisplayModeChange(LibraryDisplayMode.CompactGrid) },
|
||||
trailingIcon = {
|
||||
if (displayMode == LibraryDisplayMode.CompactGrid) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Check,
|
||||
contentDescription = "",
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(id = R.string.action_display_list)) },
|
||||
onClick = { onDisplayModeChange(LibraryDisplayMode.List) },
|
||||
trailingIcon = {
|
||||
if (displayMode == LibraryDisplayMode.List) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Check,
|
||||
contentDescription = "",
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import eu.kanade.tachiyomi.R
|
||||
fun BrowseSourceComfortableGrid(
|
||||
mangaList: LazyPagingItems<Manga>,
|
||||
getMangaState: @Composable ((Manga) -> State<Manga>),
|
||||
header: (@Composable () -> Unit)? = null,
|
||||
columns: GridCells,
|
||||
contentPadding: PaddingValues,
|
||||
onMangaClick: (Manga) -> Unit,
|
||||
@@ -37,12 +38,18 @@ fun BrowseSourceComfortableGrid(
|
||||
) {
|
||||
LazyVerticalGrid(
|
||||
columns = columns,
|
||||
contentPadding = PaddingValues(8.dp) + contentPadding,
|
||||
contentPadding = PaddingValues(8.dp, 4.dp) + contentPadding,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
if (mangaList.loadState.prepend is LoadState.Loading) {
|
||||
if (header != null) {
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
header()
|
||||
}
|
||||
}
|
||||
|
||||
if (mangaList.loadState.prepend is LoadState.Loading) {
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
BrowseSourceLoadingItem()
|
||||
}
|
||||
}
|
||||
@@ -57,8 +64,8 @@ fun BrowseSourceComfortableGrid(
|
||||
)
|
||||
}
|
||||
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
if (mangaList.loadState.refresh is LoadState.Loading || mangaList.loadState.append is LoadState.Loading) {
|
||||
if (mangaList.loadState.refresh is LoadState.Loading || mangaList.loadState.append is LoadState.Loading) {
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
BrowseSourceLoadingItem()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,20 @@ fun BrowseSourceCompactGrid(
|
||||
contentPadding: PaddingValues,
|
||||
onMangaClick: (Manga) -> Unit,
|
||||
onMangaLongClick: (Manga) -> Unit,
|
||||
header: (@Composable () -> Unit)? = null,
|
||||
) {
|
||||
LazyVerticalGrid(
|
||||
columns = columns,
|
||||
contentPadding = PaddingValues(8.dp) + contentPadding,
|
||||
contentPadding = PaddingValues(8.dp, 4.dp) + contentPadding,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
if (header != null) {
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
header()
|
||||
}
|
||||
}
|
||||
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
if (mangaList.loadState.prepend is LoadState.Loading) {
|
||||
BrowseSourceLoadingItem()
|
||||
|
||||
@@ -30,10 +30,17 @@ fun BrowseSourceList(
|
||||
contentPadding: PaddingValues,
|
||||
onMangaClick: (Manga) -> Unit,
|
||||
onMangaLongClick: (Manga) -> Unit,
|
||||
header: (@Composable () -> Unit)? = null,
|
||||
) {
|
||||
LazyColumn(
|
||||
contentPadding = contentPadding,
|
||||
) {
|
||||
if (header != null) {
|
||||
item {
|
||||
header()
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
if (mangaList.loadState.prepend is LoadState.Loading) {
|
||||
BrowseSourceLoadingItem()
|
||||
|
||||
@@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -18,8 +17,6 @@ fun BrowseSourceLoadingItem() {
|
||||
.padding(vertical = 16.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(64.dp),
|
||||
)
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,12 @@ fun BrowseSourceToolbar(
|
||||
) {
|
||||
if (state.searchQuery == null) {
|
||||
BrowseSourceRegularToolbar(
|
||||
source = source,
|
||||
title = if (state.isUserQuery) state.currentQuery else source.name,
|
||||
isLocalSource = source is LocalSource,
|
||||
displayMode = displayMode,
|
||||
onDisplayModeChange = onDisplayModeChange,
|
||||
navigateUp = navigateUp,
|
||||
onSearchClick = { state.searchQuery = "" },
|
||||
onSearchClick = { state.searchQuery = if (state.isUserQuery) state.currentQuery else "" },
|
||||
onWebViewClick = onWebViewClick,
|
||||
onHelpClick = onHelpClick,
|
||||
scrollBehavior = scrollBehavior,
|
||||
@@ -56,10 +57,7 @@ fun BrowseSourceToolbar(
|
||||
BrowseSourceSearchToolbar(
|
||||
searchQuery = state.searchQuery!!,
|
||||
onSearchQueryChanged = { state.searchQuery = it },
|
||||
navigateUp = {
|
||||
state.searchQuery = null
|
||||
onSearch()
|
||||
},
|
||||
navigateUp = { state.searchQuery = null },
|
||||
onResetClick = { state.searchQuery = "" },
|
||||
onSearchClick = onSearch,
|
||||
scrollBehavior = scrollBehavior,
|
||||
@@ -69,7 +67,8 @@ fun BrowseSourceToolbar(
|
||||
|
||||
@Composable
|
||||
fun BrowseSourceRegularToolbar(
|
||||
source: CatalogueSource,
|
||||
title: String,
|
||||
isLocalSource: Boolean,
|
||||
displayMode: LibraryDisplayMode,
|
||||
onDisplayModeChange: (LibraryDisplayMode) -> Unit,
|
||||
navigateUp: () -> Unit,
|
||||
@@ -80,7 +79,7 @@ fun BrowseSourceRegularToolbar(
|
||||
) {
|
||||
AppBar(
|
||||
navigateUp = navigateUp,
|
||||
title = source.name,
|
||||
title = title,
|
||||
actions = {
|
||||
var selectingDisplayMode by remember { mutableStateOf(false) }
|
||||
AppBarActions(
|
||||
@@ -95,7 +94,7 @@ fun BrowseSourceRegularToolbar(
|
||||
icon = Icons.Filled.ViewModule,
|
||||
onClick = { selectingDisplayMode = true },
|
||||
),
|
||||
if (source is LocalSource) {
|
||||
if (isLocalSource) {
|
||||
AppBar.Action(
|
||||
title = stringResource(id = R.string.label_help),
|
||||
icon = Icons.Outlined.Help,
|
||||
|
||||
Reference in New Issue
Block a user