Improve Source display, in library badge, add comfortable and list display

This commit is contained in:
Syer10
2022-03-06 17:38:25 -05:00
parent e4f5e24e84
commit 8666c0f3ff
9 changed files with 534 additions and 42 deletions

View File

@@ -8,10 +8,15 @@ package ca.gosyer.data.catalog
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.library.model.DisplayMode
import java.util.Locale
class CatalogPreferences(private val preferenceStore: PreferenceStore) {
fun languages(): Preference<Set<String>> {
return preferenceStore.getStringSet("enabled_langs", setOf("en", Locale.getDefault().language))
}
fun displayMode(): Preference<DisplayMode> {
return preferenceStore.getJsonObject("display_mode", DisplayMode.CompactGrid, DisplayMode.serializer())
}
}

View File

@@ -89,6 +89,7 @@
<string name="move_to_latest">Latest</string>
<string name="reset_filters">Reset</string>
<string name="filter_source">Filter</string>
<string name="in_library">In library</string>
<!-- Reader Menu -->
<string name="default_reader_mode">Default</string>

View File

@@ -39,6 +39,9 @@ class SourceScreen(val source: Source) : Screen {
onMangaClick = { navigator push MangaScreen(it) },
onCloseSourceTabClick = sourcesNavigator::remove,
onSourceSettingsClick = { navigator push SourceSettingsScreen(it) },
displayMode = sourceVM.displayMode.collectAsState().value,
gridColumns = sourceVM.gridColumns.collectAsState().value,
gridSize = sourceVM.gridSize.collectAsState().value,
mangas = sourceVM.mangas.collectAsState().value,
hasNextPage = sourceVM.hasNextPage.collectAsState().value,
loading = sourceVM.loading.collectAsState().value,
@@ -51,6 +54,7 @@ class SourceScreen(val source: Source) : Screen {
setMode = sourceVM::setMode,
loadNextPage = sourceVM::loadNextPage,
setUsingFilters = sourceVM::setUsingFilters,
onSelectDisplayMode = sourceVM::selectDisplayMode,
// FilterVM
filters = filterVM.filters.collectAsState().value,
showingFilters = filterVM.showingFilters.collectAsState().value,

View File

@@ -7,6 +7,9 @@
package ca.gosyer.ui.sources.browse
import ca.gosyer.core.logging.CKLogger
import ca.gosyer.data.catalog.CatalogPreferences
import ca.gosyer.data.library.LibraryPreferences
import ca.gosyer.data.library.model.DisplayMode
import ca.gosyer.data.models.Manga
import ca.gosyer.data.models.MangaPage
import ca.gosyer.data.models.Source
@@ -24,19 +27,29 @@ import me.tatarka.inject.annotations.Inject
class SourceScreenViewModel(
private val source: Source,
private val sourceHandler: SourceInteractionHandler,
private val catalogPreferences: CatalogPreferences,
private val libraryPreferences: LibraryPreferences,
contextWrapper: ContextWrapper
) : ViewModel(contextWrapper) {
@Inject constructor(
sourceHandler: SourceInteractionHandler,
catalogPreferences: CatalogPreferences,
libraryPreferences: LibraryPreferences,
contextWrapper: ContextWrapper,
params: Params
) : this(
params.source,
sourceHandler,
catalogPreferences,
libraryPreferences,
contextWrapper
)
val displayMode = catalogPreferences.displayMode().stateIn(scope)
val gridColumns = libraryPreferences.gridColumns().stateIn(scope)
val gridSize = libraryPreferences.gridSize().stateIn(scope)
private val _mangas = MutableStateFlow(emptyList<Manga>())
val mangas = _mangas.asStateFlow()
@@ -139,6 +152,10 @@ class SourceScreenViewModel(
startSearch(sourceSearchQuery.value)
}
fun selectDisplayMode(displayMode: DisplayMode) {
catalogPreferences.displayMode().set(displayMode)
}
data class Params(val source: Source)
private companion object : CKLogger({})

View File

@@ -0,0 +1,38 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.ui.sources.browse.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import ca.gosyer.i18n.MR
import ca.gosyer.uicore.resources.stringResource
@Composable
fun SourceMangaBadges(
inLibrary: Boolean,
modifier: Modifier = Modifier,
) {
if (!inLibrary) return
Row(modifier = modifier.clip(MaterialTheme.shapes.medium)) {
Text(
text = stringResource(MR.strings.in_library),
modifier = Modifier.background(MaterialTheme.colors.primary).then(BadgesInnerPadding),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onPrimary
)
}
}
private val BadgesInnerPadding = Modifier.padding(horizontal = 3.dp, vertical = 1.dp)

View File

@@ -0,0 +1,123 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.ui.sources.browse.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.data.models.Manga
import ca.gosyer.ui.base.components.VerticalScrollbar
import ca.gosyer.ui.base.components.rememberScrollbarAdapter
import ca.gosyer.uicore.image.KamelImage
import io.kamel.image.lazyPainterResource
@Composable
fun SourceMangaComfortableGrid(
mangas: List<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
hasNextPage: Boolean = false,
onLoadNextPage: () -> Unit,
) {
Box {
val state = rememberLazyListState()
val cells = if (gridColumns < 1) {
GridCells.Adaptive(gridSize.dp)
} else {
GridCells.Fixed(gridColumns)
}
LazyVerticalGrid(
cells = cells,
state = state,
modifier = Modifier.fillMaxSize().padding(4.dp)
) {
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
SourceMangaComfortableGridItem(
modifier = Modifier.clickable(
onClick = { onClickManga(manga.id) }
),
manga = manga,
inLibrary = manga.inLibrary
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
@Composable
private fun SourceMangaComfortableGridItem(
modifier: Modifier,
manga: Manga,
inLibrary: Boolean
) {
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)
Box(
modifier = Modifier
.padding(4.dp)
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium) then modifier
) {
Column {
KamelImage(
cover,
contentDescription = manga.title,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(3f / 4f)
.clip(MaterialTheme.shapes.medium),
contentScale = ContentScale.Crop
)
Text(
text = manga.title,
style = fontStyle,
maxLines = 3,
modifier = Modifier.padding(vertical = 4.dp, horizontal = 4.dp)
)
}
SourceMangaBadges(
inLibrary = inLibrary,
modifier = Modifier.padding(4.dp)
)
}
}

View File

@@ -0,0 +1,135 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.ui.sources.browse.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.data.models.Manga
import ca.gosyer.ui.base.components.VerticalScrollbar
import ca.gosyer.ui.base.components.rememberScrollbarAdapter
import ca.gosyer.uicore.image.KamelImage
import io.kamel.image.lazyPainterResource
@Composable
fun SourceMangaCompactGrid(
mangas: List<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
hasNextPage: Boolean = false,
onLoadNextPage: () -> Unit,
) {
Box {
val state = rememberLazyListState()
val cells = if (gridColumns < 1) {
GridCells.Adaptive(gridSize.dp)
} else {
GridCells.Fixed(gridColumns)
}
LazyVerticalGrid(
cells = cells,
state = state,
modifier = Modifier.fillMaxSize().padding(4.dp)
) {
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
SourceMangaCompactGridItem(
modifier = Modifier.clickable(
onClick = { onClickManga(manga.id) }
),
manga = manga,
inLibrary = manga.inLibrary
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
@Composable
private fun SourceMangaCompactGridItem(
modifier: Modifier,
manga: Manga,
inLibrary: Boolean
) {
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)
Box(
modifier = Modifier.padding(4.dp)
.fillMaxWidth()
.aspectRatio(3f / 4f)
.clip(MaterialTheme.shapes.medium) then modifier
) {
KamelImage(
cover,
manga.title,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
Box(modifier = Modifier.fillMaxSize().then(shadowGradient))
Text(
text = manga.title,
color = Color.White,
style = fontStyle,
maxLines = 2,
modifier = Modifier.align(Alignment.BottomStart).padding(8.dp)
)
SourceMangaBadges(
inLibrary = inLibrary,
modifier = Modifier.padding(4.dp)
)
}
}
private val shadowGradient = Modifier.drawWithCache {
val gradient = Brush.linearGradient(
0.75f to Color.Transparent,
1.0f to Color(0xAA000000),
start = Offset(0f, 0f),
end = Offset(0f, size.height)
)
onDrawBehind {
drawRect(gradient)
}
}

View File

@@ -0,0 +1,97 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.ui.sources.browse.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.unit.dp
import ca.gosyer.data.models.Manga
import ca.gosyer.ui.base.components.VerticalScrollbar
import ca.gosyer.ui.base.components.rememberScrollbarAdapter
import ca.gosyer.uicore.components.MangaListItem
import ca.gosyer.uicore.components.MangaListItemImage
import ca.gosyer.uicore.components.MangaListItemTitle
import io.kamel.image.lazyPainterResource
@Composable
fun SourceMangaList(
mangas: List<Manga>,
onClickManga: (Long) -> Unit,
hasNextPage: Boolean = false,
onLoadNextPage: () -> Unit,
) {
Box {
val state = rememberLazyListState()
LazyColumn(
state = state,
modifier = Modifier.fillMaxSize()
) {
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
MangaListItem(
modifier = Modifier.clickable(
onClick = { onClickManga(manga.id) }
),
manga = manga,
inLibrary = manga.inLibrary
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(state),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
)
}
}
@Composable
private fun MangaListItem(
modifier: Modifier,
manga: Manga,
inLibrary: Boolean
) {
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
MangaListItem(
modifier = modifier then Modifier
.requiredHeight(56.dp)
.padding(horizontal = 16.dp),
) {
MangaListItemImage(
modifier = Modifier
.size(40.dp)
.clip(MaterialTheme.shapes.medium),
cover = cover,
contentDescription = manga.title
)
MangaListItemTitle(
modifier = Modifier
.weight(1f)
.padding(horizontal = 16.dp),
text = manga.title,
)
SourceMangaBadges(inLibrary)
}
}

View File

@@ -15,17 +15,14 @@ import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.forEachGesture
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.BottomSheetScaffold
import androidx.compose.material.BottomSheetState
import androidx.compose.material.BottomSheetValue
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.ExtendedFloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.Scaffold
@@ -35,29 +32,31 @@ import androidx.compose.material.icons.rounded.Explore
import androidx.compose.material.icons.rounded.FilterList
import androidx.compose.material.icons.rounded.NewReleases
import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material.icons.rounded.ViewModule
import androidx.compose.material.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import ca.gosyer.data.library.model.DisplayMode
import ca.gosyer.data.models.Manga
import ca.gosyer.data.models.Source
import ca.gosyer.i18n.MR
import ca.gosyer.ui.base.components.VerticalScrollbar
import ca.gosyer.ui.base.components.rememberScrollbarAdapter
import ca.gosyer.ui.base.navigation.ActionItem
import ca.gosyer.ui.base.navigation.BackHandler
import ca.gosyer.ui.base.navigation.Toolbar
import ca.gosyer.ui.sources.browse.filter.SourceFiltersMenu
import ca.gosyer.ui.sources.browse.filter.model.SourceFiltersView
import ca.gosyer.uicore.components.LoadingScreen
import ca.gosyer.uicore.components.MangaGridItem
import ca.gosyer.uicore.resources.stringResource
import io.kamel.image.lazyPainterResource
@Composable
fun SourceScreenContent(
@@ -65,6 +64,9 @@ fun SourceScreenContent(
onMangaClick: (Long) -> Unit,
onCloseSourceTabClick: (Source) -> Unit,
onSourceSettingsClick: (Long) -> Unit,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: List<Manga>,
hasNextPage: Boolean,
loading: Boolean,
@@ -77,6 +79,7 @@ fun SourceScreenContent(
setMode: (Boolean) -> Unit,
loadNextPage: () -> Unit,
setUsingFilters: (Boolean) -> Unit,
onSelectDisplayMode: (DisplayMode) -> Unit,
// filter
filters: List<SourceFiltersView<*, *>>,
showingFilters: Boolean,
@@ -103,6 +106,9 @@ fun SourceScreenContent(
onMangaClick = onMangaClick,
onCloseSourceTabClick = onCloseSourceTabClick,
onSourceSettingsClick = onSourceSettingsClick,
displayMode = displayMode,
gridColumns = gridColumns,
gridSize = gridSize,
mangas = mangas,
hasNextPage = hasNextPage,
loading = loading,
@@ -118,6 +124,7 @@ fun SourceScreenContent(
showingFilters = showingFilters,
showFilterButton = showFilterButton,
setShowingFilters = setShowingFilters,
onSelectDisplayMode = onSelectDisplayMode,
resetFiltersClicked = resetFiltersClicked
)
} else {
@@ -126,6 +133,9 @@ fun SourceScreenContent(
onMangaClick = onMangaClick,
onCloseSourceTabClick = onCloseSourceTabClick,
onSourceSettingsClick = onSourceSettingsClick,
displayMode = displayMode,
gridColumns = gridColumns,
gridSize = gridSize,
mangas = mangas,
hasNextPage = hasNextPage,
loading = loading,
@@ -141,6 +151,7 @@ fun SourceScreenContent(
showingFilters = showingFilters,
showFilterButton = showFilterButton,
setShowingFilters = setShowingFilters,
onSelectDisplayMode = onSelectDisplayMode,
resetFiltersClicked = resetFiltersClicked
)
}
@@ -153,6 +164,9 @@ private fun SourceWideScreenContent(
onMangaClick: (Long) -> Unit,
onCloseSourceTabClick: (Source) -> Unit,
onSourceSettingsClick: (Long) -> Unit,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: List<Manga>,
hasNextPage: Boolean,
loading: Boolean,
@@ -169,6 +183,7 @@ private fun SourceWideScreenContent(
showingFilters: Boolean,
showFilterButton: Boolean,
setShowingFilters: (Boolean) -> Unit,
onSelectDisplayMode: (DisplayMode) -> Unit,
resetFiltersClicked: () -> Unit
) {
Scaffold(
@@ -186,11 +201,15 @@ private fun SourceWideScreenContent(
showingFilters = showingFilters,
onClickMode = setMode,
onToggleFiltersClick = setShowingFilters,
onSelectDisplayMode = onSelectDisplayMode
)
},
) { padding ->
Box(Modifier.padding(padding)) {
MangaTable(
displayMode = displayMode,
gridColumns = gridColumns,
gridSize = gridSize,
mangas = mangas,
isLoading = loading,
hasNextPage = hasNextPage,
@@ -235,6 +254,9 @@ private fun SourceThinScreenContent(
onMangaClick: (Long) -> Unit,
onCloseSourceTabClick: (Source) -> Unit,
onSourceSettingsClick: (Long) -> Unit,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: List<Manga>,
hasNextPage: Boolean,
loading: Boolean,
@@ -251,6 +273,7 @@ private fun SourceThinScreenContent(
showingFilters: Boolean,
showFilterButton: Boolean,
setShowingFilters: (Boolean) -> Unit,
onSelectDisplayMode: (DisplayMode) -> Unit,
resetFiltersClicked: () -> Unit
) {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
@@ -288,6 +311,7 @@ private fun SourceThinScreenContent(
showingFilters = showingFilters,
onClickMode = setMode,
onToggleFiltersClick = setShowingFilters,
onSelectDisplayMode = onSelectDisplayMode
)
},
sheetContent = {
@@ -306,6 +330,9 @@ private fun SourceThinScreenContent(
) { padding ->
Box(Modifier.padding(padding)) {
MangaTable(
displayMode = displayMode,
gridColumns = gridColumns,
gridSize = gridSize,
mangas = mangas,
isLoading = loading,
hasNextPage = hasNextPage,
@@ -358,7 +385,8 @@ fun SourceToolbar(
isLatest: Boolean,
showingFilters: Boolean,
onClickMode: (Boolean) -> Unit,
onToggleFiltersClick: (Boolean) -> Unit
onToggleFiltersClick: (Boolean) -> Unit,
onSelectDisplayMode: (DisplayMode) -> Unit,
) {
Toolbar(
source.name,
@@ -370,6 +398,12 @@ fun SourceToolbar(
search = onSearch,
searchSubmit = onSubmitSearch,
actions = {
var displayModeSelectOpen by remember { mutableStateOf(false) }
DisplayModeSelect(
isVisible = displayModeSelectOpen,
onSelectDisplayMode = onSelectDisplayMode,
onDismissRequest = { displayModeSelectOpen = false }
)
getActionItems(
isConfigurable = source.isConfigurable,
onSourceSettingsClick = {
@@ -383,14 +417,44 @@ fun SourceToolbar(
},
onClickMode = {
onClickMode(!isLatest)
}
},
openDisplayModeSelect = { displayModeSelectOpen = true }
)
}
)
}
@Composable
fun DisplayModeSelect(
isVisible: Boolean,
onSelectDisplayMode: (DisplayMode) -> Unit,
onDismissRequest: () -> Unit
) {
DropdownMenu(
isVisible,
onDismissRequest
) {
val list = DisplayMode.values().toList() - DisplayMode.CoverOnlyGrid
list.fastForEach {
DropdownMenuItem(
onClick = {
onSelectDisplayMode(it)
onDismissRequest()
}
) {
Text(stringResource(it.res))
}
}
}
}
@Composable
private fun MangaTable(
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: List<Manga>,
isLoading: Boolean = false,
hasNextPage: Boolean = false,
@@ -400,28 +464,30 @@ private fun MangaTable(
if (isLoading || mangas.isEmpty()) {
LoadingScreen(isLoading)
} else {
val lazyListState = rememberLazyListState()
Box {
LazyVerticalGrid(GridCells.Adaptive(160.dp), state = lazyListState) {
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
MangaGridItem(
title = manga.title,
cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium),
onClick = {
onMangaClick(manga.id)
}
)
}
}
VerticalScrollbar(
rememberScrollbarAdapter(lazyListState),
Modifier.align(Alignment.CenterEnd)
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 8.dp)
when (displayMode) {
DisplayMode.CompactGrid -> SourceMangaCompactGrid(
mangas = mangas,
gridColumns = gridColumns,
gridSize = gridSize,
onClickManga = onMangaClick,
hasNextPage = hasNextPage,
onLoadNextPage = onLoadNextPage
)
DisplayMode.ComfortableGrid -> SourceMangaComfortableGrid(
mangas = mangas,
gridColumns = gridColumns,
gridSize = gridSize,
onClickManga = onMangaClick,
hasNextPage = hasNextPage,
onLoadNextPage = onLoadNextPage
)
DisplayMode.List -> SourceMangaList(
mangas = mangas,
onClickManga = onMangaClick,
hasNextPage = hasNextPage,
onLoadNextPage = onLoadNextPage
)
else -> Box {}
}
}
}
@@ -435,16 +501,10 @@ private fun getActionItems(
showLatestButton: Boolean,
showFilterButton: Boolean,
onToggleFiltersClick: () -> Unit,
onClickMode: () -> Unit
onClickMode: () -> Unit,
openDisplayModeSelect: () -> Unit
): List<ActionItem> {
return listOfNotNull(
if (isConfigurable) {
ActionItem(
name = stringResource(MR.strings.location_settings),
icon = Icons.Rounded.Settings,
doAction = onSourceSettingsClick
)
} else null,
if (showFilterButton) {
ActionItem(
name = stringResource(MR.strings.filter_source),
@@ -469,6 +529,18 @@ private fun getActionItems(
},
doAction = onClickMode
)
} else null
} else null,
ActionItem(
name = stringResource(MR.strings.display_mode),
icon = Icons.Rounded.ViewModule,
doAction = openDisplayModeSelect
),
if (isConfigurable) {
ActionItem(
name = stringResource(MR.strings.location_settings),
icon = Icons.Rounded.Settings,
doAction = onSourceSettingsClick
)
} else null,
)
}