From 5d91e20844b0d58f3220748eb4309c8b9926e93b Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 2 Mar 2025 19:22:27 +0200 Subject: [PATCH] Update parsers and fix compatibility --- .../kotatsu/core/db/entity/ChapterEntity.kt | 2 +- .../kotatsu/core/db/entity/EntityMapping.kt | 5 +++-- .../org/koitharu/kotatsu/core/model/Manga.kt | 16 +++++++++++++++ .../model/parcelable/ParcelableChapter.kt | 4 ++-- .../external/ExternalPluginContentSource.kt | 2 +- .../details/ui/adapter/ChapterListItemAD.kt | 2 +- .../details/ui/model/ChapterListItem.kt | 20 +++++++++++++++++++ .../ui/pager/ChaptersPagesViewModel.kt | 4 +--- .../koitharu/kotatsu/local/data/MangaIndex.kt | 5 +++-- .../local/data/input/LocalMangaParser.kt | 2 +- .../local/data/output/LocalMangaDirOutput.kt | 12 ++++++++++- .../tracker/work/TrackerNotificationHelper.kt | 4 ++-- app/src/main/res/values/strings.xml | 3 +++ gradle/libs.versions.toml | 4 ++-- 14 files changed, 67 insertions(+), 18 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/ChapterEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/ChapterEntity.kt index d03827c99..d1e026945 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/ChapterEntity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/ChapterEntity.kt @@ -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, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt index 1689a5115..508b25f22 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt @@ -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.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>.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, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt index a077ee19a..7ef2c4702 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt @@ -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 + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableChapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableChapter.kt index 148060125..a28796f60 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableChapter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableChapter.kt @@ -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) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/external/ExternalPluginContentSource.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/external/ExternalPluginContentSource.kt index 49170f18f..e81192dca 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/external/ExternalPluginContentSource.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/external/ExternalPluginContentSource.kt @@ -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), diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt index 8d6275875..110b1ab33 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt @@ -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 -> { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt index f0085001b..14dd9f0aa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt @@ -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 { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesViewModel.kt index 8eab8ab7f..3643a4c9e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesViewModel.kt @@ -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?) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/MangaIndex.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/MangaIndex.kt index c9a591c44..d7713b290 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/MangaIndex.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/MangaIndex.kt @@ -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), diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaParser.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaParser.kt index 7fffabad4..81ac408ff 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaParser.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaParser.kt @@ -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, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt index 6fabb761f..5c0202382 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt @@ -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" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackerNotificationHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackerNotificationHelper.kt index 8fe22a445..54bb294a9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackerNotificationHelper.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackerNotificationHelper.kt @@ -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" } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6023f5a7c..1031e5d3e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -806,4 +806,7 @@ Global search Disable captcha notifications 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) + Vol %1$s Chapter %2$s + Chapter %s + Unnamed chapter diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 113e82445..636b781b9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ coroutines = "1.10.1" desugar = "2.1.5" diskLruCache = "1.4" fragment = "1.8.6" -gradle = "8.8.1" +gradle = "8.8.2" guava = "33.3.1-android" dagger = "2.55" hilt = "1.2.0" @@ -31,7 +31,7 @@ material = "1.13.0-alpha11" moshi = "1.15.2" okhttp = "4.12.0" okio = "3.10.2" -parsers = "843d1f1bea" +parsers = "531145c7f9" preference = "1.2.1" recyclerview = "1.4.0" room = "2.6.1"