mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-29 12:03:11 -05:00
Consolidate missing chapters functions to domain module and add tests
This commit is contained in:
parent
94c94b2d88
commit
26f3995595
6 changed files with 67 additions and 65 deletions
|
@ -2,45 +2,11 @@ package eu.kanade.tachiyomi.ui.reader.viewer
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.toDomainChapter
|
import eu.kanade.tachiyomi.data.database.models.toDomainChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
import tachiyomi.domain.chapter.model.Chapter
|
import tachiyomi.domain.chapter.service.calculateChapterGap as domainCalculateChapterGap
|
||||||
import kotlin.math.floor
|
|
||||||
|
|
||||||
private val pattern = Regex("""\d+""")
|
fun calculateChapterGap(higherReaderChapter: ReaderChapter?, lowerReaderChapter: ReaderChapter?): Int {
|
||||||
|
return domainCalculateChapterGap(
|
||||||
fun hasMissingChapters(higherReaderChapter: ReaderChapter?, lowerReaderChapter: ReaderChapter?): Boolean {
|
higherReaderChapter?.chapter?.toDomainChapter(),
|
||||||
if (higherReaderChapter == null || lowerReaderChapter == null) return false
|
lowerReaderChapter?.chapter?.toDomainChapter(),
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At
|
||||||
bold { append(context.getString(R.string.transition_previous)) }
|
bold { append(context.getString(R.string.transition_previous)) }
|
||||||
append("\n${prevChapter.name}")
|
append("\n${prevChapter.name}")
|
||||||
if (!prevChapter.scanlator.isNullOrBlank()) {
|
if (!prevChapter.scanlator.isNullOrBlank()) {
|
||||||
append(DOT_SEPERATOR)
|
append(DOT_SEPARATOR)
|
||||||
append("${prevChapter.scanlator}")
|
append("${prevChapter.scanlator}")
|
||||||
}
|
}
|
||||||
if (isPrevDownloaded) addDLImageSpan()
|
if (isPrevDownloaded) addDLImageSpan()
|
||||||
|
@ -73,7 +73,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At
|
||||||
bold { append(context.getString(R.string.transition_current)) }
|
bold { append(context.getString(R.string.transition_current)) }
|
||||||
append("\n${transition.from.chapter.name}")
|
append("\n${transition.from.chapter.name}")
|
||||||
if (!transition.from.chapter.scanlator.isNullOrBlank()) {
|
if (!transition.from.chapter.scanlator.isNullOrBlank()) {
|
||||||
append(DOT_SEPERATOR)
|
append(DOT_SEPARATOR)
|
||||||
append("${transition.from.chapter.scanlator}")
|
append("${transition.from.chapter.scanlator}")
|
||||||
}
|
}
|
||||||
if (isCurrentDownloaded) addDLImageSpan()
|
if (isCurrentDownloaded) addDLImageSpan()
|
||||||
|
@ -109,7 +109,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At
|
||||||
bold { append(context.getString(R.string.transition_finished)) }
|
bold { append(context.getString(R.string.transition_finished)) }
|
||||||
append("\n${transition.from.chapter.name}")
|
append("\n${transition.from.chapter.name}")
|
||||||
if (!transition.from.chapter.scanlator.isNullOrBlank()) {
|
if (!transition.from.chapter.scanlator.isNullOrBlank()) {
|
||||||
append(DOT_SEPERATOR)
|
append(DOT_SEPARATOR)
|
||||||
append("${transition.from.chapter.scanlator}")
|
append("${transition.from.chapter.scanlator}")
|
||||||
}
|
}
|
||||||
if (isCurrentDownloaded) addDLImageSpan()
|
if (isCurrentDownloaded) addDLImageSpan()
|
||||||
|
@ -118,7 +118,7 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At
|
||||||
bold { append(context.getString(R.string.transition_next)) }
|
bold { append(context.getString(R.string.transition_next)) }
|
||||||
append("\n${nextChapter.name}")
|
append("\n${nextChapter.name}")
|
||||||
if (!nextChapter.scanlator.isNullOrBlank()) {
|
if (!nextChapter.scanlator.isNullOrBlank()) {
|
||||||
append(DOT_SEPERATOR)
|
append(DOT_SEPARATOR)
|
||||||
append("${nextChapter.scanlator}")
|
append("${nextChapter.scanlator}")
|
||||||
}
|
}
|
||||||
if (isNextDownloaded) addDLImageSpan()
|
if (isNextDownloaded) addDLImageSpan()
|
||||||
|
@ -146,24 +146,19 @@ class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: At
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val hasMissingChapters = when (transition) {
|
val chapterGap = when (transition) {
|
||||||
is ChapterTransition.Prev -> hasMissingChapters(transition.from, transition.to)
|
is ChapterTransition.Prev -> calculateChapterGap(transition.from, transition.to)
|
||||||
is ChapterTransition.Next -> hasMissingChapters(transition.to, transition.from)
|
is ChapterTransition.Next -> calculateChapterGap(transition.to, transition.from)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasMissingChapters) {
|
if (chapterGap == 0) {
|
||||||
binding.warning.isVisible = false
|
binding.warning.isVisible = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val chapterDifference = when (transition) {
|
binding.warningText.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterGap.toInt(), chapterGap.toInt())
|
||||||
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.warning.isVisible = true
|
binding.warning.isVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val DOT_SEPERATOR = " • "
|
private const val DOT_SEPARATOR = " • "
|
||||||
|
|
|
@ -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.ReaderChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
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.util.system.createReaderThemeContext
|
||||||
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
|
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
|
@ -48,8 +48,8 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||||
val newItems = mutableListOf<Any>()
|
val newItems = mutableListOf<Any>()
|
||||||
|
|
||||||
// Forces chapter transition if there is missing chapters
|
// Forces chapter transition if there is missing chapters
|
||||||
val prevHasMissingChapters = hasMissingChapters(chapters.currChapter, chapters.prevChapter)
|
val prevHasMissingChapters = calculateChapterGap(chapters.currChapter, chapters.prevChapter) > 0
|
||||||
val nextHasMissingChapters = hasMissingChapters(chapters.nextChapter, chapters.currChapter)
|
val nextHasMissingChapters = calculateChapterGap(chapters.nextChapter, chapters.currChapter) > 0
|
||||||
|
|
||||||
// Add previous chapter pages and transition.
|
// Add previous chapter pages and transition.
|
||||||
if (chapters.prevChapter != null) {
|
if (chapters.prevChapter != null) {
|
||||||
|
|
|
@ -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.StencilPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
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 eu.kanade.tachiyomi.util.system.createReaderThemeContext
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
|
||||||
val newItems = mutableListOf<Any>()
|
val newItems = mutableListOf<Any>()
|
||||||
|
|
||||||
// Forces chapter transition if there is missing chapters
|
// Forces chapter transition if there is missing chapters
|
||||||
val prevHasMissingChapters = hasMissingChapters(chapters.currChapter, chapters.prevChapter)
|
val prevHasMissingChapters = calculateChapterGap(chapters.currChapter, chapters.prevChapter) > 0
|
||||||
val nextHasMissingChapters = hasMissingChapters(chapters.nextChapter, chapters.currChapter)
|
val nextHasMissingChapters = calculateChapterGap(chapters.nextChapter, chapters.currChapter) > 0
|
||||||
|
|
||||||
// Add previous chapter pages and transition.
|
// Add previous chapter pages and transition.
|
||||||
if (chapters.prevChapter != null) {
|
if (chapters.prevChapter != null) {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package tachiyomi.domain.chapter.service
|
package tachiyomi.domain.chapter.service
|
||||||
|
|
||||||
|
import tachiyomi.domain.chapter.model.Chapter
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
fun List<Float>.missingChaptersCount(): Int {
|
fun List<Float>.missingChaptersCount(): Int {
|
||||||
if (this.isEmpty()) {
|
if (this.isEmpty()) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -33,3 +36,14 @@ fun List<Float>.missingChaptersCount(): Int {
|
||||||
|
|
||||||
return missingChaptersCount
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -4,27 +4,54 @@ import io.kotest.matchers.shouldBe
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.parallel.Execution
|
import org.junit.jupiter.api.parallel.Execution
|
||||||
import org.junit.jupiter.api.parallel.ExecutionMode
|
import org.junit.jupiter.api.parallel.ExecutionMode
|
||||||
|
import tachiyomi.domain.chapter.model.Chapter
|
||||||
|
|
||||||
@Execution(ExecutionMode.CONCURRENT)
|
@Execution(ExecutionMode.CONCURRENT)
|
||||||
class MissingChaptersTest {
|
class MissingChaptersTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `returns 0 when empty list`() {
|
fun `missingChaptersCount returns 0 when empty list`() {
|
||||||
emptyList<Float>().missingChaptersCount() shouldBe 0
|
emptyList<Float>().missingChaptersCount() shouldBe 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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
|
listOf(-1f, -1f, -1f).missingChaptersCount() shouldBe 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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
|
listOf(1f, 1.0f, 1.1f, 1.5f, 1.6f, 1.99f).missingChaptersCount() shouldBe 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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
|
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,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue