diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index e3ad3fc86..7dc4740e1 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -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 <-- diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt index 72bf5ece0..f4671eef4 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt @@ -25,7 +25,9 @@ enum class MangaScreenItem { // SY --> INFO_BUTTONS, - CHAPTER_PREVIEW, + CHAPTER_PREVIEW_LOADING, + CHAPTER_PREVIEW_ROW, + CHAPTER_PREVIEW_MORE, // SY <-- CHAPTER_HEADER, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/PagePreviews.kt b/app/src/main/java/eu/kanade/presentation/manga/components/PagePreviews.kt index 6419d2fdf..cd9153592 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/PagePreviews.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/PagePreviews.kt @@ -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 +) { + 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 -> {} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt index de9633b79..b7a173185 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt @@ -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 { + @Suppress("DEPRECATION") return super.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 { + @Suppress("DEPRECATION") return super.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 = urlImportFetchSearchManga(context, query) { + @Suppress("DEPRECATION") super.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 { return client.newCall(imageUrlRequest(page)) .asObservableSuccess() @@ -957,7 +960,7 @@ class EHentai( class ToplistOptions : Filter.Select( "Toplists", - ToplistOption.values(), + ToplistOption.entries.toTypedArray(), ) class GenreOption(name: String, val genreId: Int) : Filter.CheckBox(name, false)