mirror of
https://github.com/keiyoushi/extensions-source.git
synced 2024-11-22 10:22:47 +01:00
Komga: Filter out EPUB books, fix chapter timestamps, allow setting default libraries, rename None sort to Relevance (#1282)
* Komga: Filter out EPUB books, fix chapter timestamps * Add default library setting * Make some settings not require a restart * Don't use fixed enums * Rename None sort to Relevance (#1284) * make popular default to alphabetical sort
This commit is contained in:
parent
fcd38a3ed6
commit
e571f95688
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Komga'
|
||||
extClass = '.KomgaFactory'
|
||||
extVersionCode = 54
|
||||
extVersionCode = 55
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
@ -7,6 +7,7 @@ import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.MultiSelectListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.AppInfo
|
||||
import eu.kanade.tachiyomi.extension.all.komga.KomgaUtils.addEditTextPreference
|
||||
@ -50,6 +51,12 @@ import kotlin.concurrent.write
|
||||
|
||||
open class Komga(private val suffix: String = "") : ConfigurableSource, UnmeteredSource, HttpSource() {
|
||||
|
||||
internal val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
|
||||
private val displayName by lazy { preferences.getString(PREF_DISPLAY_NAME, "")!! }
|
||||
|
||||
override val name by lazy { "Komga${displayName.ifBlank { suffix }.let { if (it.isNotBlank()) " ($it)" else "" }}" }
|
||||
|
||||
override val lang = "all"
|
||||
@ -65,14 +72,13 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
||||
}
|
||||
|
||||
internal val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
|
||||
private val displayName by lazy { preferences.getString(PREF_DISPLAY_NAME, "")!! }
|
||||
private val username by lazy { preferences.getString(PREF_USERNAME, "")!! }
|
||||
|
||||
private val password by lazy { preferences.getString(PREF_PASSWORD, "")!! }
|
||||
|
||||
private val defaultLibraries
|
||||
get() = preferences.getStringSet(PREF_DEFAULT_LIBRARIES, emptySet())!!
|
||||
|
||||
override fun headersBuilder() = super.headersBuilder()
|
||||
.set("User-Agent", "TachiyomiKomga/${AppInfo.getVersionName()}")
|
||||
|
||||
@ -94,7 +100,9 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
searchMangaRequest(
|
||||
page,
|
||||
"",
|
||||
FilterList(SeriesSort()),
|
||||
FilterList(
|
||||
SeriesSort(Filter.Sort.Selection(1, true)),
|
||||
),
|
||||
)
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage =
|
||||
@ -104,7 +112,9 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
searchMangaRequest(
|
||||
page,
|
||||
"",
|
||||
FilterList(SeriesSort(Filter.Sort.Selection(3, false))),
|
||||
FilterList(
|
||||
SeriesSort(Filter.Sort.Selection(3, false)),
|
||||
),
|
||||
)
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage =
|
||||
@ -124,14 +134,20 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
}
|
||||
|
||||
val url = "$baseUrl/api/v1/$type?search=$query&page=${page - 1}&deleted=false".toHttpUrl().newBuilder()
|
||||
val filterList = filters.ifEmpty { getFilterList() }
|
||||
|
||||
filters.forEach { filter ->
|
||||
if (filterList.filterIsInstance<LibraryFilter>().isEmpty()) {
|
||||
url.addQueryParameter("library_id", defaultLibraries.joinToString(","))
|
||||
}
|
||||
|
||||
filterList.forEach { filter ->
|
||||
when (filter) {
|
||||
is UriFilter -> filter.addToUri(url)
|
||||
is Filter.Sort -> {
|
||||
val state = filter.state ?: return@forEach
|
||||
|
||||
val sortCriteria = when (state.index) {
|
||||
0 -> "relevance"
|
||||
1 -> if (type == "series") "metadata.titleSort" else "name"
|
||||
2 -> "createdDate"
|
||||
3 -> "lastModifiedDate"
|
||||
@ -162,9 +178,8 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
}
|
||||
}
|
||||
|
||||
private val chapterNameTemplate by lazy {
|
||||
preferences.getString(PREF_CHAPTER_NAME_TEMPLATE, PREF_CHAPTER_NAME_TEMPLATE_DEFAULT)!!
|
||||
}
|
||||
private val chapterNameTemplate
|
||||
get() = preferences.getString(PREF_CHAPTER_NAME_TEMPLATE, PREF_CHAPTER_NAME_TEMPLATE_DEFAULT)!!
|
||||
|
||||
override fun getChapterUrl(chapter: SChapter) = chapter.url.replace("/api/v1/books", "/book")
|
||||
|
||||
@ -174,18 +189,23 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val page = response.parseAs<PageWrapperDto<BookDto>>().content
|
||||
val isFromReadList = response.isFromReadList()
|
||||
val r = page.mapIndexed { index, book ->
|
||||
val chapterNameTemplate = chapterNameTemplate
|
||||
|
||||
return page
|
||||
.filter {
|
||||
it.media.mediaProfile != "EPUB" || it.media.epubDivinaCompatible
|
||||
}
|
||||
.mapIndexed { index, book ->
|
||||
SChapter.create().apply {
|
||||
chapter_number = if (!isFromReadList) book.metadata.numberSort else index + 1F
|
||||
url = "$baseUrl/api/v1/books/${book.id}"
|
||||
name = KomgaUtils.formatChapterName(book, chapterNameTemplate, isFromReadList)
|
||||
scanlator = book.metadata.authors.filter { it.role == "translator" }.joinToString { it.name }
|
||||
date_upload = book.metadata.releaseDate?.let { KomgaUtils.parseDate(it) }
|
||||
?: KomgaUtils.parseDateTime(book.fileLastModified)
|
||||
?: KomgaUtils.parseDateTime(book.lastModified)
|
||||
}
|
||||
}
|
||||
|
||||
return r.sortedByDescending { it.chapter_number }
|
||||
.sortedByDescending { it.chapter_number }
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter) = GET("${chapter.url}/pages")
|
||||
@ -221,11 +241,7 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
}
|
||||
},
|
||||
),
|
||||
UriMultiSelectFilter(
|
||||
"Libraries",
|
||||
"library_id",
|
||||
libraries.map { UriMultiSelectOption(it.name, it.id) },
|
||||
),
|
||||
LibraryFilter(libraries, defaultLibraries),
|
||||
UriMultiSelectFilter(
|
||||
"Status",
|
||||
"status",
|
||||
@ -283,6 +299,7 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
default = suffix,
|
||||
summary = displayName.ifBlank { "Here you can change the source displayed suffix" },
|
||||
key = PREF_DISPLAY_NAME,
|
||||
restartRequired = true,
|
||||
)
|
||||
screen.addEditTextPreference(
|
||||
title = "Address",
|
||||
@ -292,12 +309,14 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
validate = { it.toHttpUrlOrNull() != null },
|
||||
validationMessage = "The URL is invalid or malformed",
|
||||
key = PREF_ADDRESS,
|
||||
restartRequired = true,
|
||||
)
|
||||
screen.addEditTextPreference(
|
||||
title = "Username",
|
||||
default = "",
|
||||
summary = username.ifBlank { "The user account email" },
|
||||
key = PREF_USERNAME,
|
||||
restartRequired = true,
|
||||
)
|
||||
screen.addEditTextPreference(
|
||||
title = "Password",
|
||||
@ -305,8 +324,24 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
summary = if (password.isBlank()) "The user account password" else "*".repeat(password.length),
|
||||
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD,
|
||||
key = PREF_PASSWORD,
|
||||
restartRequired = true,
|
||||
)
|
||||
|
||||
MultiSelectListPreference(screen.context).apply {
|
||||
key = PREF_DEFAULT_LIBRARIES
|
||||
title = "Default libraries"
|
||||
summary = buildString {
|
||||
append("Show content from selected libraries by default.")
|
||||
|
||||
if (libraries.isEmpty()) {
|
||||
append(" Browse the source to load available options.")
|
||||
}
|
||||
}
|
||||
entries = libraries.map { it.name }.toTypedArray()
|
||||
entryValues = libraries.map { it.id }.toTypedArray()
|
||||
setDefaultValue(emptySet<String>())
|
||||
}.also(screen::addPreference)
|
||||
|
||||
EditTextPreference(screen.context).apply {
|
||||
key = PREF_CHAPTER_NAME_TEMPLATE
|
||||
title = "Chapter title format"
|
||||
@ -323,10 +358,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
""".trimMargin()
|
||||
|
||||
setDefaultValue(PREF_CHAPTER_NAME_TEMPLATE_DEFAULT)
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
Toast.makeText(screen.context, "Restart Tachiyomi to apply new setting.", Toast.LENGTH_LONG).show()
|
||||
true
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
|
||||
@ -396,6 +427,7 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere
|
||||
private const val PREF_ADDRESS = "Address"
|
||||
private const val PREF_USERNAME = "Username"
|
||||
private const val PREF_PASSWORD = "Password"
|
||||
private const val PREF_DEFAULT_LIBRARIES = "Default libraries"
|
||||
private const val PREF_CHAPTER_NAME_TEMPLATE = "Chapter name template"
|
||||
private const val PREF_CHAPTER_NAME_TEMPLATE_DEFAULT = "{number} - {title} ({size})"
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package eu.kanade.tachiyomi.extension.all.komga
|
||||
|
||||
import eu.kanade.tachiyomi.extension.all.komga.dto.AuthorDto
|
||||
import eu.kanade.tachiyomi.extension.all.komga.dto.LibraryDto
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import okhttp3.HttpUrl
|
||||
|
||||
@ -18,8 +19,8 @@ internal class TypeSelect : Filter.Select<String>(
|
||||
|
||||
internal class SeriesSort(selection: Selection? = null) : Filter.Sort(
|
||||
"Sort",
|
||||
arrayOf("None", "Alphabetically", "Date added", "Date updated"),
|
||||
selection ?: Selection(0, true),
|
||||
arrayOf("Relevance", "Alphabetically", "Date added", "Date updated"),
|
||||
selection ?: Selection(0, false),
|
||||
)
|
||||
|
||||
internal class UnreadFilter : Filter.CheckBox("Unread", false), UriFilter {
|
||||
@ -53,9 +54,22 @@ internal class ReadFilter : Filter.CheckBox("Read", false), UriFilter {
|
||||
}
|
||||
}
|
||||
|
||||
internal class LibraryFilter(
|
||||
libraries: List<LibraryDto>,
|
||||
defaultLibraries: Set<String>,
|
||||
) : UriMultiSelectFilter(
|
||||
"Libraries",
|
||||
"library_id",
|
||||
libraries.map {
|
||||
UriMultiSelectOption(it.name, it.id).apply {
|
||||
state = defaultLibraries.contains(it.id)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
internal class UriMultiSelectOption(name: String, val id: String = name) : Filter.CheckBox(name, false)
|
||||
|
||||
internal class UriMultiSelectFilter(
|
||||
internal open class UriMultiSelectFilter(
|
||||
name: String,
|
||||
private val param: String,
|
||||
genres: List<UriMultiSelectOption>,
|
||||
|
@ -98,9 +98,9 @@ internal object KomgaUtils {
|
||||
}
|
||||
genre = (metadata.genres + metadata.tags + booksMetadata.tags).distinct().joinToString(", ")
|
||||
description = metadata.summary.ifBlank { booksMetadata.summary }
|
||||
booksMetadata.authors.groupBy { it.role }.let { map ->
|
||||
author = map["writer"]?.map { it.name }?.distinct()?.joinToString()
|
||||
artist = map["penciller"]?.map { it.name }?.distinct()?.joinToString()
|
||||
booksMetadata.authors.groupBy({ it.role }, { it.name }).let { map ->
|
||||
author = map["writer"]?.distinct()?.joinToString()
|
||||
artist = map["penciller"]?.distinct()?.joinToString()
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,6 +121,7 @@ internal object KomgaUtils {
|
||||
validate: ((String) -> Boolean)? = null,
|
||||
validationMessage: String? = null,
|
||||
key: String = title,
|
||||
restartRequired: Boolean = false,
|
||||
) {
|
||||
EditTextPreference(context).apply {
|
||||
this.key = key
|
||||
@ -159,8 +160,13 @@ internal object KomgaUtils {
|
||||
|
||||
setOnPreferenceChangeListener { _, _ ->
|
||||
try {
|
||||
val result = text.isBlank() || validate?.invoke(text) ?: true
|
||||
|
||||
if (restartRequired && result) {
|
||||
Toast.makeText(context, "Restart Tachiyomi to apply new setting.", Toast.LENGTH_LONG).show()
|
||||
text.isBlank() || validate?.invoke(text) ?: true
|
||||
}
|
||||
|
||||
result
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
false
|
||||
|
@ -78,6 +78,8 @@ data class MediaDto(
|
||||
val status: String,
|
||||
val mediaType: String,
|
||||
val pagesCount: Int,
|
||||
val mediaProfile: String = "DIVINA",
|
||||
val epubDivinaCompatible: Boolean = false,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
Loading…
Reference in New Issue
Block a user