Update parsers and fix compatibility

This commit is contained in:
Koitharu
2025-03-02 19:22:27 +02:00
parent d918b1e274
commit 5d91e20844
14 changed files with 67 additions and 18 deletions

View File

@@ -20,7 +20,7 @@ import org.koitharu.kotatsu.core.db.TABLE_CHAPTERS
data class ChapterEntity(
@ColumnInfo(name = "chapter_id") val chapterId: Long,
@ColumnInfo(name = "manga_id") val mangaId: Long,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "name") val title: String,
@ColumnInfo(name = "number") val number: Float,
@ColumnInfo(name = "volume") val volume: Int,
@ColumnInfo(name = "url") val url: String,

View File

@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.util.longHashCode
import org.koitharu.kotatsu.parsers.util.mapToSet
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
import org.koitharu.kotatsu.parsers.util.toArraySet
import org.koitharu.kotatsu.parsers.util.toTitleCase
@@ -50,7 +51,7 @@ fun Collection<MangaWithTags>.toMangaList() = map { it.toManga() }
fun ChapterEntity.toMangaChapter() = MangaChapter(
id = chapterId,
name = name,
title = title.nullIfEmpty(),
number = number,
volume = volume,
url = url,
@@ -93,7 +94,7 @@ fun Iterable<IndexedValue<MangaChapter>>.toEntities(mangaId: Long) = map { (inde
ChapterEntity(
chapterId = chapter.id,
mangaId = mangaId,
name = chapter.name,
title = chapter.title.orEmpty(),
number = chapter.number,
volume = chapter.volume,
url = chapter.url,

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.core.model
import android.content.res.Resources
import android.net.Uri
import android.text.SpannableStringBuilder
import androidx.annotation.DrawableRes
@@ -168,3 +169,18 @@ private fun SpannableStringBuilder.appendTagsSummary(filter: MangaListFilter) {
}
}
}
fun MangaChapter.getLocalizedTitle(resources: Resources): String {
title?.let {
if (it.isNotBlank()) {
return it
}
}
val num = numberString()
val vol = volumeString()
return when {
num != null && vol != null -> resources.getString(R.string.chapter_volume_number, vol, num)
num != null -> resources.getString(R.string.chapter_number, num)
else -> resources.getString(R.string.unnamed_chapter) // TODO fallback to manga title + index
}
}

View File

@@ -17,7 +17,7 @@ data class ParcelableChapter(
override fun create(parcel: Parcel) = ParcelableChapter(
MangaChapter(
id = parcel.readLong(),
name = parcel.readString().orEmpty(),
title = parcel.readString(),
number = parcel.readFloat(),
volume = parcel.readInt(),
url = parcel.readString().orEmpty(),
@@ -30,7 +30,7 @@ data class ParcelableChapter(
override fun ParcelableChapter.write(parcel: Parcel, flags: Int) = with(chapter) {
parcel.writeLong(id)
parcel.writeString(name)
parcel.writeString(title)
parcel.writeFloat(number)
parcel.writeInt(volume)
parcel.writeString(url)

View File

@@ -229,7 +229,7 @@ class ExternalPluginContentSource(
do {
result += MangaChapter(
id = cursor.getLong(COLUMN_ID),
name = cursor.getString(COLUMN_NAME),
title = cursor.getStringOrNull(COLUMN_NAME),
number = cursor.getFloatOrDefault(COLUMN_NUMBER, 0f),
volume = cursor.getIntOrDefault(COLUMN_VOLUME, 0),
url = cursor.getString(COLUMN_URL),

View File

@@ -25,7 +25,7 @@ fun chapterListItemAD(
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
bind {
binding.textViewTitle.text = item.chapter.name
binding.textViewTitle.text = item.getTitle(context.resources)
binding.textViewDescription.textAndVisible = item.description
when {
item.isCurrent -> {

View File

@@ -1,7 +1,9 @@
package org.koitharu.kotatsu.details.ui.model
import android.content.res.Resources
import android.text.format.DateUtils
import org.jsoup.internal.StringUtil.StringJoiner
import org.koitharu.kotatsu.core.model.getLocalizedTitle
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.parsers.model.MangaChapter
import kotlin.experimental.and
@@ -11,6 +13,8 @@ data class ChapterListItem(
val flags: Byte,
) : ListModel {
private var cachedTitle: String? = null
var description: String? = null
private set
get() {
@@ -50,6 +54,22 @@ data class ChapterListItem(
val isGrid: Boolean
get() = hasFlag(FLAG_GRID)
operator fun contains(query: String): Boolean = with(chapter) {
title?.contains(query, ignoreCase = true) == true
|| numberString()?.contains(query) == true
|| volumeString()?.contains(query) == true
}
fun getTitle(resources: Resources): String {
cachedTitle?.let {
return it
}
return chapter.getLocalizedTitle(resources).also {
cachedTitle = it
}
}
private fun buildDescription(): String {
val joiner = StringJoiner("")
chapter.numberString()?.let {

View File

@@ -216,9 +216,7 @@ abstract class ChaptersPagesViewModel(
if (query.isEmpty() || this.isEmpty()) {
return this
}
return filter {
it.chapter.name.contains(query, ignoreCase = true)
}
return filter { it.contains(query) }
}
private suspend fun onDownloadComplete(downloadedManga: LocalManga?) {

View File

@@ -27,6 +27,7 @@ import org.koitharu.kotatsu.parsers.util.json.getLongOrDefault
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
import org.koitharu.kotatsu.parsers.util.json.toStringSet
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import org.koitharu.kotatsu.parsers.util.toTitleCase
import java.io.File
@@ -110,7 +111,7 @@ class MangaIndex(source: String?) {
jo.put(KEY_NUMBER, chapter.value.number)
jo.put(KEY_VOLUME, chapter.value.volume)
jo.put(KEY_URL, chapter.value.url)
jo.put(KEY_NAME, chapter.value.name)
jo.put(KEY_NAME, chapter.value.title.orEmpty())
jo.put(KEY_UPLOAD_DATE, chapter.value.uploadDate)
jo.put(KEY_SCANLATOR, chapter.value.scanlator)
jo.put(KEY_BRANCH, chapter.value.branch)
@@ -178,7 +179,7 @@ class MangaIndex(source: String?) {
chapters.add(
MangaChapter(
id = k.toLong(),
name = v.getString(KEY_NAME),
title = v.getStringOrNull(KEY_NAME),
url = v.getString(KEY_URL),
number = v.getFloatOrDefault(KEY_NUMBER, 0f),
volume = v.getIntOrDefault(KEY_VOLUME, 0),

View File

@@ -113,7 +113,7 @@ class LocalMangaParser(private val uri: Uri) {
}.toString().removePrefix(Path.DIRECTORY_SEPARATOR)
MangaChapter(
id = "$i$s".longHashCode(),
name = s.fileNameToTitle().ifEmpty { title },
title = null,
number = 0f,
volume = 0,
source = LocalMangaSource,

View File

@@ -18,6 +18,7 @@ import org.koitharu.kotatsu.local.data.MangaIndex
import org.koitharu.kotatsu.local.data.input.LocalMangaParser
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
import java.io.File
class LocalMangaDirOutput(
@@ -145,7 +146,16 @@ class LocalMangaDirOutput(
index.getChapterFileName(chapter.value.id)?.let {
return it
}
val baseName = "${chapter.index}_${chapter.value.name.toFileNameSafe()}".take(32)
val baseName = buildString {
append(chapter.index)
chapter.value.title?.nullIfEmpty()?.let {
append('_')
append(it.toFileNameSafe())
}
if (length > 32) {
deleteRange(31, lastIndex)
}
}
var i = 0
while (true) {
val name = (if (i == 0) baseName else baseName + "_$i") + ".cbz"

View File

@@ -16,6 +16,7 @@ import coil3.ImageLoader
import coil3.request.ImageRequest
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.LocalizedAppContext
import org.koitharu.kotatsu.core.model.getLocalizedTitle
import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
@@ -76,7 +77,7 @@ class TrackerNotificationHelper @Inject constructor(
setGroup(GROUP_NEW_CHAPTERS)
val style = NotificationCompat.InboxStyle(this)
for (chapter in newChapters) {
style.addLine(chapter.name)
style.addLine(chapter.getLocalizedTitle(applicationContext.resources))
}
style.setSummaryText(manga.title)
style.setBigContentTitle(summary)
@@ -190,7 +191,6 @@ class TrackerNotificationHelper @Inject constructor(
const val TAG = "tracker"
private const val LEGACY_CHANNELS_GROUP_ID = "trackers"
private const val LEGACY_CHANNEL_ID_PREFIX = "track_fav_"
private const val LEGACY_CHANNEL_ID_HISTORY = "track_history"
private const val LEGACY_CHANNEL_ID = "tracking"
}

View File

@@ -806,4 +806,7 @@
<string name="global_search">Global search</string>
<string name="disable_captcha_notifications">Disable captcha notifications</string>
<string name="disable_captcha_notifications_summary">You will not receive notifications about solving CAPTCHA for this source but this can lead to breaking background operations (checking for new chapters, obtaining recommendations, etc)</string>
<string name="chapter_volume_number">Vol %1$s Chapter %2$s</string>
<string name="chapter_number">Chapter %s</string>
<string name="unnamed_chapter">Unnamed chapter</string>
</resources>