Improve page previews

This commit is contained in:
Jobobby04 2023-12-24 15:18:15 -05:00
parent c36d2794bb
commit cbb743f995
4 changed files with 134 additions and 61 deletions

View File

@ -34,6 +34,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@ -44,6 +45,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastMap
@ -57,6 +59,7 @@ import eu.kanade.presentation.manga.components.MangaInfoBox
import eu.kanade.presentation.manga.components.MangaInfoButtons
import eu.kanade.presentation.manga.components.MangaToolbar
import eu.kanade.presentation.manga.components.MissingChapterCountListItem
import eu.kanade.presentation.manga.components.PagePreviewItems
import eu.kanade.presentation.manga.components.PagePreviews
import eu.kanade.presentation.manga.components.SearchMetadataChips
import eu.kanade.presentation.util.formatChapterNumber
@ -339,6 +342,9 @@ private fun MangaScreenSmallImpl(
}
// SY -->
val metadataDescription = metadataDescription(state.source)
var maxWidth by remember {
mutableStateOf(Dp.Hairline)
}
// SY <--
val internalOnBackPressed = {
@ -546,16 +552,13 @@ private fun MangaScreenSmallImpl(
}
if (state.pagePreviewsState !is PagePreviewState.Unused) {
item(
key = MangaScreenItem.CHAPTER_PREVIEW,
contentType = MangaScreenItem.CHAPTER_PREVIEW,
) {
PagePreviews(
pagePreviewState = state.pagePreviewsState,
onOpenPage = onOpenPagePreview,
onMorePreviewsClicked = onMorePreviewsClicked,
)
}
PagePreviewItems(
pagePreviewState = state.pagePreviewsState,
onOpenPage = onOpenPagePreview,
onMorePreviewsClicked = onMorePreviewsClicked,
maxWidth = maxWidth,
setMaxWidth = { maxWidth = it }
)
}
// SY <--

View File

@ -25,7 +25,9 @@ enum class MangaScreenItem {
// SY -->
INFO_BUTTONS,
CHAPTER_PREVIEW,
CHAPTER_PREVIEW_LOADING,
CHAPTER_PREVIEW_ROW,
CHAPTER_PREVIEW_MORE,
// SY <--
CHAPTER_HEADER,

View File

@ -10,6 +10,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@ -31,69 +33,132 @@ import androidx.compose.ui.unit.dp
import coil.compose.SubcomposeAsyncImage
import coil.compose.SubcomposeAsyncImageContent
import eu.kanade.domain.manga.model.PagePreview
import eu.kanade.presentation.manga.MangaScreenItem
import eu.kanade.tachiyomi.ui.manga.PagePreviewState
import exh.util.floor
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
@Composable
private fun PagePreviewLoading(
setMaxWidth: (Dp) -> Unit
) {
val density = LocalDensity.current
Box(
modifier = Modifier
.height(60.dp)
.fillMaxWidth()
.onGloballyPositioned {
setMaxWidth(with(density) { it.size.width.toDp() })
},
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator()
}
}
@Composable
private fun PagePreviewRow(
onOpenPage: (Int) -> Unit,
items: ImmutableList<PagePreview>
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium),
) {
items.forEach { page ->
PagePreview(
modifier = Modifier.weight(1F),
page = page,
onOpenPage = onOpenPage,
)
}
}
}
@Composable
private fun PagePreviewMore(
onMorePreviewsClicked: () -> Unit,
) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
TextButton(onClick = onMorePreviewsClicked) {
Text(stringResource(SYMR.strings.more_previews))
}
}
}
@Composable
fun PagePreviews(
pagePreviewState: PagePreviewState,
onOpenPage: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit,
) {
when (pagePreviewState) {
PagePreviewState.Loading -> {
Box(
modifier = Modifier
.height(60.dp)
.fillMaxWidth(),
contentAlignment = Alignment.Center,
Column(Modifier.fillMaxWidth()) {
var maxWidth by remember {
mutableStateOf(Dp.Hairline)
}
when {
pagePreviewState is PagePreviewState.Loading || maxWidth == Dp.Hairline -> {
PagePreviewLoading(setMaxWidth = { maxWidth = it })
}
pagePreviewState is PagePreviewState.Success -> {
val itemPerRowCount = (maxWidth / 120.dp).floor()
pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount).forEach {
PagePreviewRow(
onOpenPage = onOpenPage,
items = remember(it) { it.toImmutableList() }
)
}
PagePreviewMore(onMorePreviewsClicked)
}
else -> {}
}
}
}
fun LazyListScope.PagePreviewItems(
pagePreviewState: PagePreviewState,
onOpenPage: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit,
maxWidth: Dp,
setMaxWidth: (Dp) -> Unit
) {
when {
pagePreviewState is PagePreviewState.Loading || maxWidth == Dp.Hairline -> {
item(
key = MangaScreenItem.CHAPTER_PREVIEW_LOADING,
contentType = MangaScreenItem.CHAPTER_PREVIEW_LOADING,
) {
CircularProgressIndicator()
PagePreviewLoading(setMaxWidth = setMaxWidth)
}
}
is PagePreviewState.Success -> {
var maxWidth by remember {
mutableStateOf(Dp.Hairline)
}
val density = LocalDensity.current
Box(
Modifier
.fillMaxWidth()
.onGloballyPositioned {
maxWidth = with(density) { it.size.width.toDp() }
},
pagePreviewState is PagePreviewState.Success -> {
val itemPerRowCount = (maxWidth / 120.dp).floor()
items(
key = { "${MangaScreenItem.CHAPTER_PREVIEW_ROW}-$it" },
contentType = { MangaScreenItem.CHAPTER_PREVIEW_ROW },
items = pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount),
) {
if (maxWidth == Dp.Hairline) return@Box
val itemPerRowCount = (maxWidth / 120.dp).floor()
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
) {
pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount).forEach {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium),
) {
it.forEach { page ->
PagePreview(
modifier = Modifier.weight(1F),
page = page,
onOpenPage = onOpenPage,
)
}
}
}
TextButton(onClick = onMorePreviewsClicked) {
Text(stringResource(SYMR.strings.more_previews))
}
}
PagePreviewRow(
onOpenPage = onOpenPage,
items = remember(it) { it.toImmutableList() }
)
}
item(
key = MangaScreenItem.CHAPTER_PREVIEW_MORE,
contentType = MangaScreenItem.CHAPTER_PREVIEW_MORE,
) {
PagePreviewMore(onMorePreviewsClicked)
}
}
else -> {}

View File

@ -406,7 +406,6 @@ class EHentai(
@Suppress("DEPRECATION")
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
fun fetchChapterList(manga: SManga, throttleFunc: suspend () -> Unit) = runAsObservable {
getChapterList(manga, throttleFunc)
@ -476,6 +475,7 @@ class EHentai(
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates"))
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
@Suppress("DEPRECATION")
return super<HttpSource>.fetchLatestUpdates(page).checkValid()
}
@ -485,6 +485,7 @@ class EHentai(
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularManga"))
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
@Suppress("DEPRECATION")
return super<HttpSource>.fetchPopularManga(page).checkValid()
}
@ -496,6 +497,7 @@ class EHentai(
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getSearchManga"))
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
urlImportFetchSearchManga(context, query) {
@Suppress("DEPRECATION")
super<HttpSource>.fetchSearchManga(page, query, filters).checkValid()
}
@ -506,7 +508,7 @@ class EHentai(
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val toplist = ToplistOption.values()[filters.firstNotNullOfOrNull { (it as? ToplistOptions)?.state } ?: 0]
val toplist = ToplistOption.entries[filters.firstNotNullOfOrNull { (it as? ToplistOptions)?.state } ?: 0]
if (toplist != ToplistOption.NONE) {
val uri = "https://e-hentai.org".toUri().buildUpon()
uri.appendPath("toplist.php")
@ -794,6 +796,7 @@ class EHentai(
override fun pageListParse(response: Response) =
throw UnsupportedOperationException("Unused method was called somehow!")
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getImageUrl"))
override fun fetchImageUrl(page: Page): Observable<String> {
return client.newCall(imageUrlRequest(page))
.asObservableSuccess()
@ -957,7 +960,7 @@ class EHentai(
class ToplistOptions : Filter.Select<ToplistOption>(
"Toplists",
ToplistOption.values(),
ToplistOption.entries.toTypedArray(),
)
class GenreOption(name: String, val genreId: Int) : Filter.CheckBox(name, false)