Fix ChapterList parsing issue (#24)
This commit is contained in:
@@ -342,33 +342,30 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou
|
|||||||
item.volumeId != null && item.volumeId > 0 ->
|
item.volumeId != null && item.volumeId > 0 ->
|
||||||
"/Volume/${item.volumeId}?readingListId=$readingListId&seriesId=${item.seriesId}&volumeId=${item.volumeId}"
|
"/Volume/${item.volumeId}?readingListId=$readingListId&seriesId=${item.seriesId}&volumeId=${item.volumeId}"
|
||||||
else ->
|
else ->
|
||||||
// Fallback: use both seriesId and order to distinguish
|
|
||||||
"/Series/${item.seriesId}?readingListId=$readingListId&seriesId=${item.seriesId}&order=${item.order}"
|
"/Series/${item.seriesId}?readingListId=$readingListId&seriesId=${item.seriesId}&order=${item.order}"
|
||||||
}
|
}
|
||||||
name = buildString {
|
name = buildString {
|
||||||
append("${item.order + 1}. ")
|
append("${item.order + 1}. ")
|
||||||
when {
|
when {
|
||||||
!item.chapterTitleName.isNullOrBlank() && !item.chapterTitleName.matches(Regex("^\\d+$")) -> {
|
item.volumeNumber != null && item.volumeNumber != KavitaConstants.UNNUMBERED_VOLUME_STR -> {
|
||||||
append(item.chapterTitleName)
|
append("Volume ${item.volumeNumber}")
|
||||||
}
|
}
|
||||||
!item.volumeNumber.isNullOrBlank() && item.volumeNumber != UNNUMBERED_VOLUME_STR -> {
|
item.chapterNumber != null && item.chapterNumber != KavitaConstants.UNNUMBERED_VOLUME_STR -> {
|
||||||
append("Volume ${item.volumeNumber.padStart(2, '0')}")
|
|
||||||
}
|
|
||||||
!item.chapterNumber.isNullOrBlank() && item.chapterNumber != UNNUMBERED_VOLUME_STR -> {
|
|
||||||
val libraryType = getLibraryType(item.seriesId)
|
val libraryType = getLibraryType(item.seriesId)
|
||||||
when (libraryType) {
|
when (libraryType) {
|
||||||
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine ->
|
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> append("Issue #${item.chapterNumber}")
|
||||||
append("Issue #${item.chapterNumber.padStart(3, '0')}")
|
else -> append("Chapter ${item.chapterNumber}")
|
||||||
else ->
|
|
||||||
append("Chapter ${item.chapterNumber.padStart(2, '0')}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
|
append("Item ${item.order + 1}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
date_upload = if (preferences.RdDate && !item.releaseDate.isNullOrBlank()) {
|
date_upload = if (preferences.RdDate && !item.releaseDate.isNullOrBlank()) {
|
||||||
parseDateSafe(item.releaseDate)
|
parseDateSafe(item.releaseDate)
|
||||||
} else {
|
} else {
|
||||||
0L // Explicitly unset the date
|
0L
|
||||||
}
|
}
|
||||||
chapter_number = item.order.toFloat()
|
chapter_number = item.order.toFloat()
|
||||||
scanlator = item.seriesName
|
scanlator = item.seriesName
|
||||||
@@ -1021,7 +1018,7 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou
|
|||||||
|
|
||||||
for (volume in volumes) {
|
for (volume in volumes) {
|
||||||
// Issue: use chapter covers
|
// Issue: use chapter covers
|
||||||
if (isComicLibrary && volume.number == UNNUMBERED_VOLUME) {
|
if (isComicLibrary && volume.number == KavitaConstants.UNNUMBERED_VOLUME) {
|
||||||
coverCandidates += volume.chapters
|
coverCandidates += volume.chapters
|
||||||
.filterNot { it.coverImage.isNullOrBlank() }
|
.filterNot { it.coverImage.isNullOrBlank() }
|
||||||
.map { chapter ->
|
.map { chapter ->
|
||||||
@@ -1250,23 +1247,16 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou
|
|||||||
val chapters = mutableListOf<SChapter>()
|
val chapters = mutableListOf<SChapter>()
|
||||||
val volumeItems = mutableListOf<SChapter>()
|
val volumeItems = mutableListOf<SChapter>()
|
||||||
|
|
||||||
// First determine the content type
|
|
||||||
val hasChapters = volumes.any { volume ->
|
|
||||||
volume.chapters.any { chapter ->
|
|
||||||
ChapterType.of(chapter, volume, libraryType) != ChapterType.SingleFileVolume
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val hasVolumes = volumes.any { volume ->
|
|
||||||
volume.chapters.any { chapter ->
|
|
||||||
ChapterType.of(chapter, volume, libraryType) == ChapterType.SingleFileVolume
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volumes.forEach { volume ->
|
volumes.forEach { volume ->
|
||||||
volume.chapters.forEach { chapter ->
|
volume.chapters.forEach { chapter ->
|
||||||
val sChapter = helper.chapterFromVolume(chapter, volume, libraryType = libraryType)
|
val sChapter = helper.chapterFromVolume(chapter, volume, libraryType = libraryType)
|
||||||
when (ChapterType.of(chapter, volume, libraryType)) {
|
when (ChapterType.of(chapter, volume, libraryType)) {
|
||||||
ChapterType.SingleFileVolume -> volumeItems.add(sChapter)
|
ChapterType.SingleFileVolume -> {
|
||||||
|
// For Case 2, use positive volume numbers
|
||||||
|
// For Case 3, use negative numbers
|
||||||
|
sChapter.chapter_number = volume.number.toFloat()
|
||||||
|
volumeItems.add(sChapter)
|
||||||
|
}
|
||||||
else -> chapters.add(sChapter)
|
else -> chapters.add(sChapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1274,17 +1264,19 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
// Case 1: Only chapters
|
// Case 1: Only chapters
|
||||||
hasChapters && !hasVolumes -> chapters.sortedByDescending { it.chapter_number }
|
chapters.isNotEmpty() && volumeItems.isEmpty() ->
|
||||||
|
chapters.sortedByDescending { it.chapter_number }
|
||||||
|
|
||||||
// Case 2: Only volumes (treat as chapters)
|
// Case 2: Only volumes - treat as chapters with positive numbers
|
||||||
!hasChapters && hasVolumes -> volumeItems.sortedByDescending { it.chapter_number }
|
volumeItems.isNotEmpty() && chapters.isEmpty() ->
|
||||||
|
volumeItems.sortedByDescending { it.chapter_number }
|
||||||
|
|
||||||
// Case 3: Mixed content
|
// Case 3: Mixed content - chapters first, then volumes (as negative numbers)
|
||||||
else -> {
|
else -> {
|
||||||
// Chapters first (sorted descending)
|
// Convert volume numbers to negative for proper sorting
|
||||||
|
volumeItems.forEach { it.chapter_number = -it.chapter_number }
|
||||||
val sortedChapters = chapters.sortedByDescending { it.chapter_number }
|
val sortedChapters = chapters.sortedByDescending { it.chapter_number }
|
||||||
// Volumes after (sorted descending with negative numbers)
|
val sortedVolumes = volumeItems.sortedBy { it.chapter_number }
|
||||||
val sortedVolumes = volumeItems.sortedByDescending { it.chapter_number }
|
|
||||||
sortedChapters + sortedVolumes
|
sortedChapters + sortedVolumes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1846,9 +1838,6 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val UNNUMBERED_VOLUME = -100000
|
|
||||||
private const val UNNUMBERED_VOLUME_STR = "-100000"
|
|
||||||
|
|
||||||
private const val ADDRESS_TITLE = "Address"
|
private const val ADDRESS_TITLE = "Address"
|
||||||
private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
|
private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.extension.all.kavita
|
|||||||
|
|
||||||
object KavitaConstants {
|
object KavitaConstants {
|
||||||
|
|
||||||
|
const val UNNUMBERED_VOLUME = -100000
|
||||||
|
const val UNNUMBERED_VOLUME_STR = "-100000"
|
||||||
|
|
||||||
val PERSON_ROLES = listOf(
|
val PERSON_ROLES = listOf(
|
||||||
"Writer", "Penciller", "Inker", "Colorist",
|
"Writer", "Penciller", "Inker", "Colorist",
|
||||||
"Letterer", "CoverArtist", "Editor",
|
"Letterer", "CoverArtist", "Editor",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.extension.all.kavita.dto
|
package eu.kanade.tachiyomi.extension.all.kavita.dto
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.extension.all.kavita.KavitaConstants
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -202,27 +203,33 @@ data class VolumeDto(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class ChapterType {
|
enum class ChapterType {
|
||||||
Regular, // chapter with volume information
|
Regular, // Chapter with volume information
|
||||||
Chapter, // manga chapter without volume information
|
Chapter, // Chapter without volume information
|
||||||
SingleFileVolume,
|
SingleFileVolume,
|
||||||
Special,
|
Special,
|
||||||
Issue, // For comics
|
Issue, // For comics
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val SPECIAL_NUMBER = 100_000
|
||||||
|
private const val UNNUMBERED_VOLUME_NUMBER = -100_000
|
||||||
|
|
||||||
fun of(chapter: ChapterDto, volume: VolumeDto, libraryType: LibraryTypeEnum? = null): ChapterType =
|
fun of(chapter: ChapterDto, volume: VolumeDto, libraryType: LibraryTypeEnum? = null): ChapterType =
|
||||||
when {
|
when {
|
||||||
volume.number == 100_000 -> Special
|
// Special cases
|
||||||
volume.number == -100_000 -> when (libraryType) {
|
volume.number == SPECIAL_NUMBER -> Special
|
||||||
|
volume.number == UNNUMBERED_VOLUME_NUMBER -> when (libraryType) {
|
||||||
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
||||||
LibraryTypeEnum.Manga, LibraryTypeEnum.LightNovel, LibraryTypeEnum.Book -> Chapter
|
else -> Chapter
|
||||||
else -> Chapter // Default to Chapter for other types
|
|
||||||
}
|
}
|
||||||
chapter.number == "-100000" -> SingleFileVolume
|
// Single file volumes
|
||||||
|
chapter.number == KavitaConstants.UNNUMBERED_VOLUME_STR -> SingleFileVolume
|
||||||
|
// Regular volumes
|
||||||
|
volume.number > 0 -> SingleFileVolume
|
||||||
|
// Everything else depends on library type
|
||||||
else -> when (libraryType) {
|
else -> when (libraryType) {
|
||||||
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
||||||
LibraryTypeEnum.Manga, LibraryTypeEnum.LightNovel, LibraryTypeEnum.Book -> Chapter
|
else -> Chapter
|
||||||
else -> Regular
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user