From 94cbfbd394b7fabf42a6729211a37a2a36faea02 Mon Sep 17 00:00:00 2001 From: "Mio." Date: Mon, 14 Jul 2025 22:15:48 +0200 Subject: [PATCH] fix broken pages --- .../tachiyomi/extension/all/kavita/Kavita.kt | 60 ++++++------- .../extension/all/kavita/KavitaHelper.kt | 89 ++++++++++++------- 2 files changed, 86 insertions(+), 63 deletions(-) diff --git a/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt b/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt index 426d7cff..1a81c9eb 100644 --- a/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt +++ b/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt @@ -1009,7 +1009,7 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou if (chapter.coverImage.isNotBlank()) { val url = "$apiUrl/Image/chapter-cover?chapterId=${chapter.id}&apiKey=$apiKey" coverCandidates.add( - Triple(url, chapter.pagesRead < chapter.pages, chapter.number.toFloatOrNull() ?: 0f) + Triple(url, chapter.pagesRead < chapter.pages, chapter.number.toFloatOrNull() ?: 0f), ) chapterMap[url] = chapter } @@ -1567,16 +1567,12 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou throw IOException(helper.intl["error_invalid_reading_list_item"]) } - val pages = mutableListOf() - for (i in 0 until chapterDetails.pages) { - pages.add( - Page( - index = i, - imageUrl = "$apiUrl/Reader/image?chapterId=${chapterDetails.id}&page=$i&extractPdf=true&apiKey=$apiKey", - ), + (0 until chapterDetails.pages).map { i -> + Page( + index = i, + imageUrl = "$apiUrl/Reader/image?chapterId=${chapterDetails.id}&page=$i&extractPdf=true&apiKey=$apiKey", ) } - pages.toList() }.onErrorResumeNext { error -> Log.e(LOG_TAG, "Error fetching reading list chapter pages", error) Observable.error(error) @@ -1596,30 +1592,36 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou val matchingChapter = volume.chapters.firstOrNull() // or match a chapterId if available ?: throw IOException(helper.intl["error_no_chapters_found"]) - val pages = (0 until matchingChapter.pages).map { i -> + val initialPages = (0 until matchingChapter.pages).map { i -> Page( index = i, imageUrl = "$apiUrl/Reader/image?chapterId=${matchingChapter.id}&page=$i&extractPdf=true&apiKey=$apiKey", ) - }.toMutableList() - - var pageOffset = matchingChapter.pages - - volume.chapters.sortedBy { it.number.toFloatOrNull() ?: 0f }.forEach { chapterDto -> - val chapterPages = (0 until chapterDto.pages).map { i -> - Page( - index = pageOffset + i, - imageUrl = "$apiUrl/Reader/image?chapterId=${chapterDto.id}&page=$i&extractPdf=true&apiKey=$apiKey", - ) - } - pages.addAll(chapterPages) - pageOffset += chapterDto.pages } - pages.toList() + val remainingPages = volume.chapters + .sortedBy { it.number.toFloatOrNull() ?: 0f } + .runningFold(initialPages.size) { acc, chapter -> acc + chapter.pages } + .drop(1) + .zip(volume.chapters.sortedBy { it.number.toFloatOrNull() ?: 0f }) + .flatMap { (offset, chapter) -> + (0 until chapter.pages).map { i -> + Page( + index = offset - chapter.pages + i, + imageUrl = "$apiUrl/Reader/image?chapterId=${chapter.id}&page=$i&extractPdf=true&apiKey=$apiKey", + ) + } + } + + (initialPages + remainingPages).toList() } else { // Original chapter handling - val chapterId = chapter.url.substringAfter("/Chapter/").substringBefore("_") + val chapterId = when { + chapter.url.startsWith("chapter_") -> chapter.url.substringAfter("chapter_").substringBefore("_") + chapter.url.contains("/Chapter/") -> chapter.url.substringAfter("/Chapter/").substringBefore("_") + else -> throw IOException("Invalid chapter URL format") + } + val chapterRequest = GET("$apiUrl/Chapter?chapterId=$chapterId", headersBuilder().build()) val response = client.newCall(chapterRequest).execute() @@ -1633,25 +1635,23 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou throw IOException("${helper.intl["error_failed_parse_chapter"]}: ${e.message}") } - val pages = (0 until chapterDetails.pages).map { i -> + (0 until chapterDetails.pages).map { i -> Page( index = i, imageUrl = "$apiUrl/Reader/image?chapterId=$chapterId&page=$i&extractPdf=true&apiKey=$apiKey", ) } - pages.toList() } }.onErrorResumeNext { error -> // Fallback to using the scanlator field if we can't get chapter details Log.e(LOG_TAG, "Error fetching chapter details, using fallback", error) val fallbackPageCount = chapter.scanlator?.replace(" pages", "")?.toIntOrNull() ?: 1 - val pages = (0 until fallbackPageCount).map { i -> + (0 until fallbackPageCount).map { i -> Page( index = i, imageUrl = "$apiUrl/Reader/image?chapterId=${chapter.url.substringBefore("_")}&page=$i&extractPdf=true&apiKey=$apiKey", ) - } - Observable.just(pages.toList()) + }.let { Observable.just(it) } } } diff --git a/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/KavitaHelper.kt b/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/KavitaHelper.kt index 631adbaf..4f80291d 100644 --- a/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/KavitaHelper.kt +++ b/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/KavitaHelper.kt @@ -163,39 +163,59 @@ class KavitaHelper { } } + // @todo Keeping this in case we're switching the logic here this after the Mihon PR // Handle decimal chapter numbers properly - chapter_number = when { - type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null -> - singleFileVolumeNumber.toFloat() +// chapter_number = when { +// type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null -> +// singleFileVolumeNumber.toFloat() +// +// type == ChapterType.SingleFileVolume -> { +// // For standalone volumes, use positive numbers +// volume.minNumber.toFloat() +// } +// +// // For regular chapters +// type != ChapterType.SingleFileVolume && type != ChapterType.Special -> { +// // Handle decimal chapter numbers +// if (chapter.minNumber % 1 != 0.0) { +// chapter.minNumber.toFloat() +// } else { +// chapter.minNumber.toInt().toFloat() +// } +// } +// +// // For volumes/specials in mixed content, place them below chapter 0 +// else -> { +// val volumeNum = try { +// if (volume.minNumber % 1 != 0.0) { +// volume.minNumber.toFloat() +// } else { +// volume.minNumber.toInt().toFloat() +// } +// } catch (e: NumberFormatException) { +// 0f +// } +// -volumeNum - KavitaConstants.VOLUME_NUMBER_OFFSET +// } +// } +// +// url = when { +// type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null -> +// "volume_${volume.id}" +// else -> "chapter_${chapter.id}" +// } - type == ChapterType.SingleFileVolume -> { - // For standalone volumes, use positive numbers + // Handle decimal chapter numbers properly + chapter_number = if (type == ChapterType.SingleFileVolume) { + if (volume.minNumber % 1 != 0.0) { volume.minNumber.toFloat() + } else { + volume.minNumber.toInt().toFloat() } - - // For regular chapters - type != ChapterType.SingleFileVolume && type != ChapterType.Special -> { - // Handle decimal chapter numbers - if (chapter.minNumber % 1 != 0.0) { - chapter.minNumber.toFloat() - } else { - chapter.minNumber.toInt().toFloat() - } - } - - // For volumes/specials in mixed content, place them below chapter 0 - else -> { - val volumeNum = try { - if (volume.minNumber % 1 != 0.0) { - volume.minNumber.toFloat() - } else { - volume.minNumber.toInt().toFloat() - } - } catch (e: NumberFormatException) { - 0f - } - -volumeNum - KavitaConstants.VOLUME_NUMBER_OFFSET - } + } else if (chapter.minNumber % 1 != 0.0) { + chapter.minNumber.toFloat() + } else { + chapter.minNumber.toInt().toFloat() } url = when { @@ -248,11 +268,14 @@ class KavitaHelper { // Helper function to remove .0 from whole numbers while preserving actual decimals @SuppressLint("DefaultLocale") private fun removeTrailingZero(number: Double): String { - return if (number % 1 == 0.0) { - number.toInt().toString() + return if (number.isInfinite() || number.isNaN()) { + number.toString() } else { - // Use String.format to avoid scientific notation for very small decimals - String.format("%.10f", number).replace(",", ".").trimEnd('0').trimEnd('.') + val formatted = String.format("%.10f", number) + .replace(",", ".") + .trimEnd('0') + .trimEnd('.') + formatted.ifEmpty { "0" } } }