diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt index d39a63a805..3c7c03aea1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt @@ -2,45 +2,11 @@ package eu.kanade.tachiyomi.ui.reader.viewer import eu.kanade.tachiyomi.data.database.models.toDomainChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter -import tachiyomi.domain.chapter.model.Chapter -import kotlin.math.floor +import tachiyomi.domain.chapter.service.calculateChapterGap as domainCalculateChapterGap -private val pattern = Regex("""\d+""") - -fun hasMissingChapters(higherReaderChapter: ReaderChapter?, lowerReaderChapter: ReaderChapter?): Boolean { - if (higherReaderChapter == null || lowerReaderChapter == null) return false - return hasMissingChapters(higherReaderChapter.chapter.toDomainChapter(), lowerReaderChapter.chapter.toDomainChapter()) -} - -fun hasMissingChapters(higherChapter: Chapter?, lowerChapter: Chapter?): Boolean { - if (higherChapter == null || lowerChapter == null) return false - // Check if name contains a number that is potential chapter number - if (!pattern.containsMatchIn(higherChapter.name) || !pattern.containsMatchIn(lowerChapter.name)) return false - // Check if potential chapter number was recognized as chapter number - if (!higherChapter.isRecognizedNumber || !lowerChapter.isRecognizedNumber) return false - return hasMissingChapters(higherChapter.chapterNumber, lowerChapter.chapterNumber) -} - -fun hasMissingChapters(higherChapterNumber: Float, lowerChapterNumber: Float): Boolean { - if (higherChapterNumber < 0f || lowerChapterNumber < 0f) return false - return calculateChapterDifference(higherChapterNumber, lowerChapterNumber) > 0f -} - -fun calculateChapterDifference(higherReaderChapter: ReaderChapter?, lowerReaderChapter: ReaderChapter?): Float { - if (higherReaderChapter == null || lowerReaderChapter == null) return 0f - return calculateChapterDifference(higherReaderChapter.chapter.toDomainChapter(), lowerReaderChapter.chapter.toDomainChapter()) -} - -fun calculateChapterDifference(higherChapter: Chapter?, lowerChapter: Chapter?): Float { - if (higherChapter == null || lowerChapter == null) return 0f - // Check if name contains a number that is potential chapter number - if (!pattern.containsMatchIn(higherChapter.name) || !pattern.containsMatchIn(lowerChapter.name)) return 0f - // Check if potential chapter number was recognized as chapter number - if (!higherChapter.isRecognizedNumber || !lowerChapter.isRecognizedNumber) return 0f - return calculateChapterDifference(higherChapter.chapterNumber, lowerChapter.chapterNumber) -} - -fun calculateChapterDifference(higherChapterNumber: Float, lowerChapterNumber: Float): Float { - if (higherChapterNumber < 0f || lowerChapterNumber < 0f) return 0f - return floor(higherChapterNumber) - floor(lowerChapterNumber) - 1f +fun calculateChapterGap(higherReaderChapter: ReaderChapter?, lowerReaderChapter: ReaderChapter?): Int { + return domainCalculateChapterGap( + higherReaderChapter?.chapter?.toDomainChapter(), + lowerReaderChapter?.chapter?.toDomainChapter(), + ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt index feea51002d..9efeb7988e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt @@ -64,7 +64,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At bold { append(context.getString(R.string.transition_previous)) } append("\n${prevChapter.name}") if (!prevChapter.scanlator.isNullOrBlank()) { - append(DOT_SEPERATOR) + append(DOT_SEPARATOR) append("${prevChapter.scanlator}") } if (isPrevDownloaded) addDLImageSpan() @@ -73,7 +73,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At bold { append(context.getString(R.string.transition_current)) } append("\n${transition.from.chapter.name}") if (!transition.from.chapter.scanlator.isNullOrBlank()) { - append(DOT_SEPERATOR) + append(DOT_SEPARATOR) append("${transition.from.chapter.scanlator}") } if (isCurrentDownloaded) addDLImageSpan() @@ -109,7 +109,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At bold { append(context.getString(R.string.transition_finished)) } append("\n${transition.from.chapter.name}") if (!transition.from.chapter.scanlator.isNullOrBlank()) { - append(DOT_SEPERATOR) + append(DOT_SEPARATOR) append("${transition.from.chapter.scanlator}") } if (isCurrentDownloaded) addDLImageSpan() @@ -118,7 +118,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At bold { append(context.getString(R.string.transition_next)) } append("\n${nextChapter.name}") if (!nextChapter.scanlator.isNullOrBlank()) { - append(DOT_SEPERATOR) + append(DOT_SEPARATOR) append("${nextChapter.scanlator}") } if (isNextDownloaded) addDLImageSpan() @@ -146,24 +146,19 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At return } - val hasMissingChapters = when (transition) { - is ChapterTransition.Prev -> hasMissingChapters(transition.from, transition.to) - is ChapterTransition.Next -> hasMissingChapters(transition.to, transition.from) + val chapterGap = when (transition) { + is ChapterTransition.Prev -> calculateChapterGap(transition.from, transition.to) + is ChapterTransition.Next -> calculateChapterGap(transition.to, transition.from) } - if (!hasMissingChapters) { + if (chapterGap == 0) { binding.warning.isVisible = false return } - val chapterDifference = when (transition) { - is ChapterTransition.Prev -> calculateChapterDifference(transition.from, transition.to) - is ChapterTransition.Next -> calculateChapterDifference(transition.to, transition.from) - } - - binding.warningText.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterDifference.toInt(), chapterDifference.toInt()) + binding.warningText.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterGap.toInt(), chapterGap.toInt()) binding.warning.isVisible = true } } -private const val DOT_SEPERATOR = " • " +private const val DOT_SEPARATOR = " • " diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt index 59c5fb52bd..ec78dc8c6c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt @@ -7,7 +7,7 @@ import eu.kanade.tachiyomi.ui.reader.model.InsertPage import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters -import eu.kanade.tachiyomi.ui.reader.viewer.hasMissingChapters +import eu.kanade.tachiyomi.ui.reader.viewer.calculateChapterGap import eu.kanade.tachiyomi.util.system.createReaderThemeContext import eu.kanade.tachiyomi.widget.ViewPagerAdapter import tachiyomi.core.util.system.logcat @@ -48,8 +48,8 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() { val newItems = mutableListOf() // Forces chapter transition if there is missing chapters - val prevHasMissingChapters = hasMissingChapters(chapters.currChapter, chapters.prevChapter) - val nextHasMissingChapters = hasMissingChapters(chapters.nextChapter, chapters.currChapter) + val prevHasMissingChapters = calculateChapterGap(chapters.currChapter, chapters.prevChapter) > 0 + val nextHasMissingChapters = calculateChapterGap(chapters.nextChapter, chapters.currChapter) > 0 // Add previous chapter pages and transition. if (chapters.prevChapter != null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt index 71766a2e6c..87edd1da45 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt @@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.StencilPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView -import eu.kanade.tachiyomi.ui.reader.viewer.hasMissingChapters +import eu.kanade.tachiyomi.ui.reader.viewer.calculateChapterGap import eu.kanade.tachiyomi.util.system.createReaderThemeContext import tachiyomi.core.util.system.logcat @@ -62,8 +62,8 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter() // Forces chapter transition if there is missing chapters - val prevHasMissingChapters = hasMissingChapters(chapters.currChapter, chapters.prevChapter) - val nextHasMissingChapters = hasMissingChapters(chapters.nextChapter, chapters.currChapter) + val prevHasMissingChapters = calculateChapterGap(chapters.currChapter, chapters.prevChapter) > 0 + val nextHasMissingChapters = calculateChapterGap(chapters.nextChapter, chapters.currChapter) > 0 // Add previous chapter pages and transition. if (chapters.prevChapter != null) { diff --git a/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt b/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt index 71fafe1c94..b5b728ff6b 100644 --- a/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt +++ b/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt @@ -1,5 +1,8 @@ package tachiyomi.domain.chapter.service +import tachiyomi.domain.chapter.model.Chapter +import kotlin.math.floor + fun List.missingChaptersCount(): Int { if (this.isEmpty()) { return 0 @@ -33,3 +36,14 @@ fun List.missingChaptersCount(): Int { return missingChaptersCount } + +fun calculateChapterGap(higherChapter: Chapter?, lowerChapter: Chapter?): Int { + if (higherChapter == null || lowerChapter == null) return 0 + if (!higherChapter.isRecognizedNumber || !lowerChapter.isRecognizedNumber) return 0 + return calculateChapterGap(higherChapter.chapterNumber, lowerChapter.chapterNumber) +} + +fun calculateChapterGap(higherChapterNumber: Float, lowerChapterNumber: Float): Int { + if (higherChapterNumber < 0f || lowerChapterNumber < 0f) return 0 + return floor(higherChapterNumber).toInt() - floor(lowerChapterNumber).toInt() - 1 +} diff --git a/domain/src/test/java/tachiyomi/domain/chapter/service/MissingChaptersTest.kt b/domain/src/test/java/tachiyomi/domain/chapter/service/MissingChaptersTest.kt index 4d50750c01..0424bb71d4 100644 --- a/domain/src/test/java/tachiyomi/domain/chapter/service/MissingChaptersTest.kt +++ b/domain/src/test/java/tachiyomi/domain/chapter/service/MissingChaptersTest.kt @@ -4,27 +4,54 @@ import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test import org.junit.jupiter.api.parallel.Execution import org.junit.jupiter.api.parallel.ExecutionMode +import tachiyomi.domain.chapter.model.Chapter @Execution(ExecutionMode.CONCURRENT) class MissingChaptersTest { @Test - fun `returns 0 when empty list`() { + fun `missingChaptersCount returns 0 when empty list`() { emptyList().missingChaptersCount() shouldBe 0 } @Test - fun `returns 0 when all unknown chapter numbers`() { + fun `missingChaptersCount returns 0 when all unknown chapter numbers`() { listOf(-1f, -1f, -1f).missingChaptersCount() shouldBe 0 } @Test - fun `handles repeated base chapter numbers`() { + fun `missingChaptersCount handles repeated base chapter numbers`() { listOf(1f, 1.0f, 1.1f, 1.5f, 1.6f, 1.99f).missingChaptersCount() shouldBe 0 } @Test - fun `returns number of missing chapters`() { + fun `missingChaptersCount returns number of missing chapters`() { listOf(-1f, 1f, 2f, 2.2f, 4f, 6f, 10f, 11f).missingChaptersCount() shouldBe 5 } + + @Test + fun `calculateChapterGap returns difference`() { + calculateChapterGap(chapter(10f), chapter(9f)) shouldBe 0f + calculateChapterGap(chapter(10f), chapter(8f)) shouldBe 1f + calculateChapterGap(chapter(10f), chapter(8.5f)) shouldBe 1f + calculateChapterGap(chapter(10f), chapter(1.1f)) shouldBe 8f + + calculateChapterGap(10f, 9f) shouldBe 0f + calculateChapterGap(10f, 8f) shouldBe 1f + calculateChapterGap(10f, 8.5f) shouldBe 1f + calculateChapterGap(10f, 1.1f) shouldBe 8f + } + + @Test + fun `calculateChapterGap returns 0 if either are not valid chapter numbers`() { + calculateChapterGap(chapter(-1f), chapter(10f)) shouldBe 0 + calculateChapterGap(chapter(99f), chapter(-1f)) shouldBe 0 + + calculateChapterGap(-1f, 10f) shouldBe 0 + calculateChapterGap(99f, -1f) shouldBe 0 + } + + private fun chapter(number: Float) = Chapter.create().copy( + chapterNumber = number, + ) }