Improve page previews
This commit is contained in:
parent
c36d2794bb
commit
cbb743f995
@ -34,6 +34,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
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.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.util.fastAll
|
import androidx.compose.ui.util.fastAll
|
||||||
import androidx.compose.ui.util.fastAny
|
import androidx.compose.ui.util.fastAny
|
||||||
import androidx.compose.ui.util.fastMap
|
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.MangaInfoButtons
|
||||||
import eu.kanade.presentation.manga.components.MangaToolbar
|
import eu.kanade.presentation.manga.components.MangaToolbar
|
||||||
import eu.kanade.presentation.manga.components.MissingChapterCountListItem
|
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.PagePreviews
|
||||||
import eu.kanade.presentation.manga.components.SearchMetadataChips
|
import eu.kanade.presentation.manga.components.SearchMetadataChips
|
||||||
import eu.kanade.presentation.util.formatChapterNumber
|
import eu.kanade.presentation.util.formatChapterNumber
|
||||||
@ -339,6 +342,9 @@ private fun MangaScreenSmallImpl(
|
|||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
val metadataDescription = metadataDescription(state.source)
|
val metadataDescription = metadataDescription(state.source)
|
||||||
|
var maxWidth by remember {
|
||||||
|
mutableStateOf(Dp.Hairline)
|
||||||
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
val internalOnBackPressed = {
|
val internalOnBackPressed = {
|
||||||
@ -546,17 +552,14 @@ private fun MangaScreenSmallImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.pagePreviewsState !is PagePreviewState.Unused) {
|
if (state.pagePreviewsState !is PagePreviewState.Unused) {
|
||||||
item(
|
PagePreviewItems(
|
||||||
key = MangaScreenItem.CHAPTER_PREVIEW,
|
|
||||||
contentType = MangaScreenItem.CHAPTER_PREVIEW,
|
|
||||||
) {
|
|
||||||
PagePreviews(
|
|
||||||
pagePreviewState = state.pagePreviewsState,
|
pagePreviewState = state.pagePreviewsState,
|
||||||
onOpenPage = onOpenPagePreview,
|
onOpenPage = onOpenPagePreview,
|
||||||
onMorePreviewsClicked = onMorePreviewsClicked,
|
onMorePreviewsClicked = onMorePreviewsClicked,
|
||||||
|
maxWidth = maxWidth,
|
||||||
|
setMaxWidth = { maxWidth = it }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
item(
|
item(
|
||||||
|
@ -25,7 +25,9 @@ enum class MangaScreenItem {
|
|||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
INFO_BUTTONS,
|
INFO_BUTTONS,
|
||||||
CHAPTER_PREVIEW,
|
CHAPTER_PREVIEW_LOADING,
|
||||||
|
CHAPTER_PREVIEW_ROW,
|
||||||
|
CHAPTER_PREVIEW_MORE,
|
||||||
|
|
||||||
// SY <--
|
// SY <--
|
||||||
CHAPTER_HEADER,
|
CHAPTER_HEADER,
|
||||||
|
@ -10,6 +10,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
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.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@ -31,49 +33,38 @@ import androidx.compose.ui.unit.dp
|
|||||||
import coil.compose.SubcomposeAsyncImage
|
import coil.compose.SubcomposeAsyncImage
|
||||||
import coil.compose.SubcomposeAsyncImageContent
|
import coil.compose.SubcomposeAsyncImageContent
|
||||||
import eu.kanade.domain.manga.model.PagePreview
|
import eu.kanade.domain.manga.model.PagePreview
|
||||||
|
import eu.kanade.presentation.manga.MangaScreenItem
|
||||||
import eu.kanade.tachiyomi.ui.manga.PagePreviewState
|
import eu.kanade.tachiyomi.ui.manga.PagePreviewState
|
||||||
import exh.util.floor
|
import exh.util.floor
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PagePreviews(
|
private fun PagePreviewLoading(
|
||||||
pagePreviewState: PagePreviewState,
|
setMaxWidth: (Dp) -> Unit
|
||||||
onOpenPage: (Int) -> Unit,
|
|
||||||
onMorePreviewsClicked: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
when (pagePreviewState) {
|
val density = LocalDensity.current
|
||||||
PagePreviewState.Loading -> {
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(60.dp)
|
.height(60.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth()
|
||||||
|
.onGloballyPositioned {
|
||||||
|
setMaxWidth(with(density) { it.size.width.toDp() })
|
||||||
|
},
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
CircularProgressIndicator()
|
CircularProgressIndicator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PagePreviewState.Success -> {
|
|
||||||
var maxWidth by remember {
|
@Composable
|
||||||
mutableStateOf(Dp.Hairline)
|
private fun PagePreviewRow(
|
||||||
}
|
onOpenPage: (Int) -> Unit,
|
||||||
val density = LocalDensity.current
|
items: ImmutableList<PagePreview>
|
||||||
Box(
|
) {
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.onGloballyPositioned {
|
|
||||||
maxWidth = with(density) { it.size.width.toDp() }
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
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(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -81,7 +72,7 @@ fun PagePreviews(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium),
|
||||||
) {
|
) {
|
||||||
it.forEach { page ->
|
items.forEach { page ->
|
||||||
PagePreview(
|
PagePreview(
|
||||||
modifier = Modifier.weight(1F),
|
modifier = Modifier.weight(1F),
|
||||||
page = page,
|
page = page,
|
||||||
@ -89,11 +80,85 @@ fun PagePreviews(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun PagePreviewMore(
|
||||||
|
onMorePreviewsClicked: () -> Unit,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
TextButton(onClick = onMorePreviewsClicked) {
|
TextButton(onClick = onMorePreviewsClicked) {
|
||||||
Text(stringResource(SYMR.strings.more_previews))
|
Text(stringResource(SYMR.strings.more_previews))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PagePreviews(
|
||||||
|
pagePreviewState: PagePreviewState,
|
||||||
|
onOpenPage: (Int) -> Unit,
|
||||||
|
onMorePreviewsClicked: () -> Unit,
|
||||||
|
) {
|
||||||
|
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,
|
||||||
|
) {
|
||||||
|
PagePreviewLoading(setMaxWidth = setMaxWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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),
|
||||||
|
) {
|
||||||
|
PagePreviewRow(
|
||||||
|
onOpenPage = onOpenPage,
|
||||||
|
items = remember(it) { it.toImmutableList() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
item(
|
||||||
|
key = MangaScreenItem.CHAPTER_PREVIEW_MORE,
|
||||||
|
contentType = MangaScreenItem.CHAPTER_PREVIEW_MORE,
|
||||||
|
) {
|
||||||
|
PagePreviewMore(onMorePreviewsClicked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
|
@ -406,7 +406,6 @@ class EHentai(
|
|||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
|
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
|
||||||
|
|
||||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
|
||||||
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
|
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
|
||||||
fun fetchChapterList(manga: SManga, throttleFunc: suspend () -> Unit) = runAsObservable {
|
fun fetchChapterList(manga: SManga, throttleFunc: suspend () -> Unit) = runAsObservable {
|
||||||
getChapterList(manga, throttleFunc)
|
getChapterList(manga, throttleFunc)
|
||||||
@ -476,6 +475,7 @@ class EHentai(
|
|||||||
|
|
||||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates"))
|
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates"))
|
||||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
return super<HttpSource>.fetchLatestUpdates(page).checkValid()
|
return super<HttpSource>.fetchLatestUpdates(page).checkValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,6 +485,7 @@ class EHentai(
|
|||||||
|
|
||||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularManga"))
|
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularManga"))
|
||||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
return super<HttpSource>.fetchPopularManga(page).checkValid()
|
return super<HttpSource>.fetchPopularManga(page).checkValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,6 +497,7 @@ class EHentai(
|
|||||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getSearchManga"))
|
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getSearchManga"))
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
||||||
urlImportFetchSearchManga(context, query) {
|
urlImportFetchSearchManga(context, query) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
super<HttpSource>.fetchSearchManga(page, query, filters).checkValid()
|
super<HttpSource>.fetchSearchManga(page, query, filters).checkValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +508,7 @@ class EHentai(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
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) {
|
if (toplist != ToplistOption.NONE) {
|
||||||
val uri = "https://e-hentai.org".toUri().buildUpon()
|
val uri = "https://e-hentai.org".toUri().buildUpon()
|
||||||
uri.appendPath("toplist.php")
|
uri.appendPath("toplist.php")
|
||||||
@ -794,6 +796,7 @@ class EHentai(
|
|||||||
override fun pageListParse(response: Response) =
|
override fun pageListParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Unused method was called somehow!")
|
throw UnsupportedOperationException("Unused method was called somehow!")
|
||||||
|
|
||||||
|
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getImageUrl"))
|
||||||
override fun fetchImageUrl(page: Page): Observable<String> {
|
override fun fetchImageUrl(page: Page): Observable<String> {
|
||||||
return client.newCall(imageUrlRequest(page))
|
return client.newCall(imageUrlRequest(page))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
@ -957,7 +960,7 @@ class EHentai(
|
|||||||
|
|
||||||
class ToplistOptions : Filter.Select<ToplistOption>(
|
class ToplistOptions : Filter.Select<ToplistOption>(
|
||||||
"Toplists",
|
"Toplists",
|
||||||
ToplistOption.values(),
|
ToplistOption.entries.toTypedArray(),
|
||||||
)
|
)
|
||||||
|
|
||||||
class GenreOption(name: String, val genreId: Int) : Filter.CheckBox(name, false)
|
class GenreOption(name: String, val genreId: Int) : Filter.CheckBox(name, false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user