Update parsers and fix compatibility
This commit is contained in:
@@ -20,7 +20,7 @@ import org.koitharu.kotatsu.core.db.TABLE_CHAPTERS
|
|||||||
data class ChapterEntity(
|
data class ChapterEntity(
|
||||||
@ColumnInfo(name = "chapter_id") val chapterId: Long,
|
@ColumnInfo(name = "chapter_id") val chapterId: Long,
|
||||||
@ColumnInfo(name = "manga_id") val mangaId: 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 = "number") val number: Float,
|
||||||
@ColumnInfo(name = "volume") val volume: Int,
|
@ColumnInfo(name = "volume") val volume: Int,
|
||||||
@ColumnInfo(name = "url") val url: String,
|
@ColumnInfo(name = "url") val url: String,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.parsers.model.MangaTag
|
|||||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||||
import org.koitharu.kotatsu.parsers.util.longHashCode
|
import org.koitharu.kotatsu.parsers.util.longHashCode
|
||||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
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.toArraySet
|
||||||
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ fun Collection<MangaWithTags>.toMangaList() = map { it.toManga() }
|
|||||||
|
|
||||||
fun ChapterEntity.toMangaChapter() = MangaChapter(
|
fun ChapterEntity.toMangaChapter() = MangaChapter(
|
||||||
id = chapterId,
|
id = chapterId,
|
||||||
name = name,
|
title = title.nullIfEmpty(),
|
||||||
number = number,
|
number = number,
|
||||||
volume = volume,
|
volume = volume,
|
||||||
url = url,
|
url = url,
|
||||||
@@ -93,7 +94,7 @@ fun Iterable<IndexedValue<MangaChapter>>.toEntities(mangaId: Long) = map { (inde
|
|||||||
ChapterEntity(
|
ChapterEntity(
|
||||||
chapterId = chapter.id,
|
chapterId = chapter.id,
|
||||||
mangaId = mangaId,
|
mangaId = mangaId,
|
||||||
name = chapter.name,
|
title = chapter.title.orEmpty(),
|
||||||
number = chapter.number,
|
number = chapter.number,
|
||||||
volume = chapter.volume,
|
volume = chapter.volume,
|
||||||
url = chapter.url,
|
url = chapter.url,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.koitharu.kotatsu.core.model
|
package org.koitharu.kotatsu.core.model
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import androidx.annotation.DrawableRes
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ data class ParcelableChapter(
|
|||||||
override fun create(parcel: Parcel) = ParcelableChapter(
|
override fun create(parcel: Parcel) = ParcelableChapter(
|
||||||
MangaChapter(
|
MangaChapter(
|
||||||
id = parcel.readLong(),
|
id = parcel.readLong(),
|
||||||
name = parcel.readString().orEmpty(),
|
title = parcel.readString(),
|
||||||
number = parcel.readFloat(),
|
number = parcel.readFloat(),
|
||||||
volume = parcel.readInt(),
|
volume = parcel.readInt(),
|
||||||
url = parcel.readString().orEmpty(),
|
url = parcel.readString().orEmpty(),
|
||||||
@@ -30,7 +30,7 @@ data class ParcelableChapter(
|
|||||||
|
|
||||||
override fun ParcelableChapter.write(parcel: Parcel, flags: Int) = with(chapter) {
|
override fun ParcelableChapter.write(parcel: Parcel, flags: Int) = with(chapter) {
|
||||||
parcel.writeLong(id)
|
parcel.writeLong(id)
|
||||||
parcel.writeString(name)
|
parcel.writeString(title)
|
||||||
parcel.writeFloat(number)
|
parcel.writeFloat(number)
|
||||||
parcel.writeInt(volume)
|
parcel.writeInt(volume)
|
||||||
parcel.writeString(url)
|
parcel.writeString(url)
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ class ExternalPluginContentSource(
|
|||||||
do {
|
do {
|
||||||
result += MangaChapter(
|
result += MangaChapter(
|
||||||
id = cursor.getLong(COLUMN_ID),
|
id = cursor.getLong(COLUMN_ID),
|
||||||
name = cursor.getString(COLUMN_NAME),
|
title = cursor.getStringOrNull(COLUMN_NAME),
|
||||||
number = cursor.getFloatOrDefault(COLUMN_NUMBER, 0f),
|
number = cursor.getFloatOrDefault(COLUMN_NUMBER, 0f),
|
||||||
volume = cursor.getIntOrDefault(COLUMN_VOLUME, 0),
|
volume = cursor.getIntOrDefault(COLUMN_VOLUME, 0),
|
||||||
url = cursor.getString(COLUMN_URL),
|
url = cursor.getString(COLUMN_URL),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ fun chapterListItemAD(
|
|||||||
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.textViewTitle.text = item.chapter.name
|
binding.textViewTitle.text = item.getTitle(context.resources)
|
||||||
binding.textViewDescription.textAndVisible = item.description
|
binding.textViewDescription.textAndVisible = item.description
|
||||||
when {
|
when {
|
||||||
item.isCurrent -> {
|
item.isCurrent -> {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package org.koitharu.kotatsu.details.ui.model
|
package org.koitharu.kotatsu.details.ui.model
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import org.jsoup.internal.StringUtil.StringJoiner
|
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.list.ui.model.ListModel
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
@@ -11,6 +13,8 @@ data class ChapterListItem(
|
|||||||
val flags: Byte,
|
val flags: Byte,
|
||||||
) : ListModel {
|
) : ListModel {
|
||||||
|
|
||||||
|
private var cachedTitle: String? = null
|
||||||
|
|
||||||
var description: String? = null
|
var description: String? = null
|
||||||
private set
|
private set
|
||||||
get() {
|
get() {
|
||||||
@@ -50,6 +54,22 @@ data class ChapterListItem(
|
|||||||
val isGrid: Boolean
|
val isGrid: Boolean
|
||||||
get() = hasFlag(FLAG_GRID)
|
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 {
|
private fun buildDescription(): String {
|
||||||
val joiner = StringJoiner(" • ")
|
val joiner = StringJoiner(" • ")
|
||||||
chapter.numberString()?.let {
|
chapter.numberString()?.let {
|
||||||
|
|||||||
@@ -216,9 +216,7 @@ abstract class ChaptersPagesViewModel(
|
|||||||
if (query.isEmpty() || this.isEmpty()) {
|
if (query.isEmpty() || this.isEmpty()) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
return filter {
|
return filter { it.contains(query) }
|
||||||
it.chapter.name.contains(query, ignoreCase = true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun onDownloadComplete(downloadedManga: LocalManga?) {
|
private suspend fun onDownloadComplete(downloadedManga: LocalManga?) {
|
||||||
|
|||||||
@@ -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.getStringOrNull
|
||||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||||
import org.koitharu.kotatsu.parsers.util.json.toStringSet
|
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.runCatchingCancellable
|
||||||
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -110,7 +111,7 @@ class MangaIndex(source: String?) {
|
|||||||
jo.put(KEY_NUMBER, chapter.value.number)
|
jo.put(KEY_NUMBER, chapter.value.number)
|
||||||
jo.put(KEY_VOLUME, chapter.value.volume)
|
jo.put(KEY_VOLUME, chapter.value.volume)
|
||||||
jo.put(KEY_URL, chapter.value.url)
|
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_UPLOAD_DATE, chapter.value.uploadDate)
|
||||||
jo.put(KEY_SCANLATOR, chapter.value.scanlator)
|
jo.put(KEY_SCANLATOR, chapter.value.scanlator)
|
||||||
jo.put(KEY_BRANCH, chapter.value.branch)
|
jo.put(KEY_BRANCH, chapter.value.branch)
|
||||||
@@ -178,7 +179,7 @@ class MangaIndex(source: String?) {
|
|||||||
chapters.add(
|
chapters.add(
|
||||||
MangaChapter(
|
MangaChapter(
|
||||||
id = k.toLong(),
|
id = k.toLong(),
|
||||||
name = v.getString(KEY_NAME),
|
title = v.getStringOrNull(KEY_NAME),
|
||||||
url = v.getString(KEY_URL),
|
url = v.getString(KEY_URL),
|
||||||
number = v.getFloatOrDefault(KEY_NUMBER, 0f),
|
number = v.getFloatOrDefault(KEY_NUMBER, 0f),
|
||||||
volume = v.getIntOrDefault(KEY_VOLUME, 0),
|
volume = v.getIntOrDefault(KEY_VOLUME, 0),
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ class LocalMangaParser(private val uri: Uri) {
|
|||||||
}.toString().removePrefix(Path.DIRECTORY_SEPARATOR)
|
}.toString().removePrefix(Path.DIRECTORY_SEPARATOR)
|
||||||
MangaChapter(
|
MangaChapter(
|
||||||
id = "$i$s".longHashCode(),
|
id = "$i$s".longHashCode(),
|
||||||
name = s.fileNameToTitle().ifEmpty { title },
|
title = null,
|
||||||
number = 0f,
|
number = 0f,
|
||||||
volume = 0,
|
volume = 0,
|
||||||
source = LocalMangaSource,
|
source = LocalMangaSource,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.koitharu.kotatsu.local.data.MangaIndex
|
|||||||
import org.koitharu.kotatsu.local.data.input.LocalMangaParser
|
import org.koitharu.kotatsu.local.data.input.LocalMangaParser
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||||
|
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class LocalMangaDirOutput(
|
class LocalMangaDirOutput(
|
||||||
@@ -145,7 +146,16 @@ class LocalMangaDirOutput(
|
|||||||
index.getChapterFileName(chapter.value.id)?.let {
|
index.getChapterFileName(chapter.value.id)?.let {
|
||||||
return it
|
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
|
var i = 0
|
||||||
while (true) {
|
while (true) {
|
||||||
val name = (if (i == 0) baseName else baseName + "_$i") + ".cbz"
|
val name = (if (i == 0) baseName else baseName + "_$i") + ".cbz"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import coil3.ImageLoader
|
|||||||
import coil3.request.ImageRequest
|
import coil3.request.ImageRequest
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.core.LocalizedAppContext
|
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.nav.AppRouter
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
|
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
|
||||||
@@ -76,7 +77,7 @@ class TrackerNotificationHelper @Inject constructor(
|
|||||||
setGroup(GROUP_NEW_CHAPTERS)
|
setGroup(GROUP_NEW_CHAPTERS)
|
||||||
val style = NotificationCompat.InboxStyle(this)
|
val style = NotificationCompat.InboxStyle(this)
|
||||||
for (chapter in newChapters) {
|
for (chapter in newChapters) {
|
||||||
style.addLine(chapter.name)
|
style.addLine(chapter.getLocalizedTitle(applicationContext.resources))
|
||||||
}
|
}
|
||||||
style.setSummaryText(manga.title)
|
style.setSummaryText(manga.title)
|
||||||
style.setBigContentTitle(summary)
|
style.setBigContentTitle(summary)
|
||||||
@@ -190,7 +191,6 @@ class TrackerNotificationHelper @Inject constructor(
|
|||||||
const val TAG = "tracker"
|
const val TAG = "tracker"
|
||||||
|
|
||||||
private const val LEGACY_CHANNELS_GROUP_ID = "trackers"
|
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_HISTORY = "track_history"
|
||||||
private const val LEGACY_CHANNEL_ID = "tracking"
|
private const val LEGACY_CHANNEL_ID = "tracking"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -806,4 +806,7 @@
|
|||||||
<string name="global_search">Global search</string>
|
<string name="global_search">Global search</string>
|
||||||
<string name="disable_captcha_notifications">Disable captcha notifications</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="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>
|
</resources>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ coroutines = "1.10.1"
|
|||||||
desugar = "2.1.5"
|
desugar = "2.1.5"
|
||||||
diskLruCache = "1.4"
|
diskLruCache = "1.4"
|
||||||
fragment = "1.8.6"
|
fragment = "1.8.6"
|
||||||
gradle = "8.8.1"
|
gradle = "8.8.2"
|
||||||
guava = "33.3.1-android"
|
guava = "33.3.1-android"
|
||||||
dagger = "2.55"
|
dagger = "2.55"
|
||||||
hilt = "1.2.0"
|
hilt = "1.2.0"
|
||||||
@@ -31,7 +31,7 @@ material = "1.13.0-alpha11"
|
|||||||
moshi = "1.15.2"
|
moshi = "1.15.2"
|
||||||
okhttp = "4.12.0"
|
okhttp = "4.12.0"
|
||||||
okio = "3.10.2"
|
okio = "3.10.2"
|
||||||
parsers = "843d1f1bea"
|
parsers = "531145c7f9"
|
||||||
preference = "1.2.1"
|
preference = "1.2.1"
|
||||||
recyclerview = "1.4.0"
|
recyclerview = "1.4.0"
|
||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user