[Comick] Various updates (#19118)
* Add setting for Score positioning Localization support for settings * Simplify score position evaluation Reformat code * Include backup domain in Manifest * Refine logic for picking the first volume cover * Officially moved their main TLD * Fallback to default value instead of empty string
This commit is contained in:
parent
76d9997262
commit
67c4e30577
|
@ -14,7 +14,9 @@
|
|||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="comick.ink" />
|
||||
<data android:host="comick.app" />
|
||||
<data android:host="comick.fun" />
|
||||
<data android:pathPattern="/comic/.*/..*" />
|
||||
<data android:pathPattern="/comic/..*" />
|
||||
</intent-filter>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
ignored_groups_title=Ignored Groups
|
||||
ignored_groups_summary=Chapters from these groups won't be shown.\nOne group name per line (case-insensitive)
|
||||
include_tags_title=Include Tags
|
||||
include_tags_on=More specific, but might contain spoilers!
|
||||
include_tags_off=Only the broader genres
|
||||
update_cover_title=Update Covers
|
||||
update_cover_on=Keep cover updated
|
||||
update_cover_off=Prefer first cover
|
||||
score_position_title=Score Position in the Description
|
||||
score_position_top=Top
|
||||
score_position_middle=Middle
|
||||
score_position_bottom=Bottom
|
||||
score_position_none=Hide Score
|
|
@ -0,0 +1,13 @@
|
|||
ignored_groups_title=Grupos Ignorados
|
||||
ignored_groups_summary=Capítulos desses grupos não aparecerão.\nUm grupo por linha
|
||||
include_tags_title=Incluir Tags
|
||||
include_tags_on=Mais detalhadas, mas podem conter spoilers
|
||||
include_tags_off=Apenas os gêneros básicos
|
||||
update_cover_title=Atualizar Capas
|
||||
update_cover_on=Manter capas atualizadas
|
||||
update_cover_off=Usar apenas a primeira capa
|
||||
score_position_title=Posição da Nota na Descrição
|
||||
score_position_top=Topo
|
||||
score_position_middle=Meio
|
||||
score_position_bottom=Final
|
||||
score_position_none=Sem Nota
|
|
@ -6,8 +6,12 @@ ext {
|
|||
extName = 'Comick'
|
||||
pkgNameSuffix = 'all.comickfun'
|
||||
extClass = '.ComickFunFactory'
|
||||
extVersionCode = 39
|
||||
extVersionCode = 40
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":lib-i18n"))
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
|
|
@ -3,8 +3,10 @@ package eu.kanade.tachiyomi.extension.all.comickfun
|
|||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import eu.kanade.tachiyomi.lib.i18n.Intl
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
|
@ -36,7 +38,7 @@ abstract class ComickFun(
|
|||
|
||||
override val name = "Comick"
|
||||
|
||||
override val baseUrl = "https://comick.app"
|
||||
override val baseUrl = "https://comick.ink"
|
||||
|
||||
private val apiUrl = "https://api.comick.fun"
|
||||
|
||||
|
@ -51,6 +53,15 @@ abstract class ComickFun(
|
|||
|
||||
private lateinit var searchResponse: List<SearchManga>
|
||||
|
||||
private val intl by lazy {
|
||||
Intl(
|
||||
language = lang,
|
||||
baseLanguage = "en",
|
||||
availableLanguages = setOf("en", "pt-BR"),
|
||||
classLoader = this::class.java.classLoader!!,
|
||||
)
|
||||
}
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
|
@ -58,9 +69,8 @@ abstract class ComickFun(
|
|||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
EditTextPreference(screen.context).apply {
|
||||
key = IGNORED_GROUPS_PREF
|
||||
title = "Ignored Groups"
|
||||
summary =
|
||||
"Chapters from these groups won't be shown.\nOne group name per line (case-insensitive)"
|
||||
title = intl["ignored_groups_title"]
|
||||
summary = intl["ignored_groups_summary"]
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
preferences.edit()
|
||||
|
@ -71,9 +81,9 @@ abstract class ComickFun(
|
|||
|
||||
SwitchPreferenceCompat(screen.context).apply {
|
||||
key = INCLUDE_MU_TAGS_PREF
|
||||
title = "Include Tags"
|
||||
summaryOn = "More specific, but might contain spoilers!"
|
||||
summaryOff = "Only the broader genres"
|
||||
title = intl["include_tags_title"]
|
||||
summaryOn = intl["include_tags_on"]
|
||||
summaryOff = intl["include_tags_off"]
|
||||
setDefaultValue(INCLUDE_MU_TAGS_DEFAULT)
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
|
@ -85,9 +95,9 @@ abstract class ComickFun(
|
|||
|
||||
SwitchPreferenceCompat(screen.context).apply {
|
||||
key = FIRST_COVER_PREF
|
||||
title = "Update Covers"
|
||||
summaryOff = "Prefer first cover"
|
||||
summaryOn = "Keep cover updated"
|
||||
title = intl["update_cover_title"]
|
||||
summaryOff = intl["update_cover_off"]
|
||||
summaryOn = intl["update_cover_on"]
|
||||
setDefaultValue(FIRST_COVER_DEFAULT)
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
|
@ -96,6 +106,30 @@ abstract class ComickFun(
|
|||
.commit()
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
|
||||
ListPreference(screen.context).apply {
|
||||
key = SCORE_POSITION_PREF
|
||||
title = intl["score_position_title"]
|
||||
summary = "%s"
|
||||
entries = arrayOf(
|
||||
intl["score_position_top"],
|
||||
intl["score_position_middle"],
|
||||
intl["score_position_bottom"],
|
||||
intl["score_position_none"],
|
||||
)
|
||||
entryValues = arrayOf(SCORE_POSITION_DEFAULT, "middle", "bottom", "none")
|
||||
setDefaultValue(SCORE_POSITION_DEFAULT)
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val selected = newValue as String
|
||||
val index = findIndexOfValue(selected)
|
||||
val entry = entryValues[index] as String
|
||||
|
||||
preferences.edit()
|
||||
.putString(SCORE_POSITION_PREF, entry)
|
||||
.commit()
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
|
||||
private val SharedPreferences.ignoredGroups: Set<String>
|
||||
|
@ -114,6 +148,9 @@ abstract class ComickFun(
|
|||
private val SharedPreferences.updateCover: Boolean
|
||||
get() = getBoolean(FIRST_COVER_PREF, FIRST_COVER_DEFAULT)
|
||||
|
||||
private val SharedPreferences.scorePosition: String
|
||||
get() = getString(SCORE_POSITION_PREF, SCORE_POSITION_DEFAULT) ?: SCORE_POSITION_DEFAULT
|
||||
|
||||
init {
|
||||
preferences.newLineIgnoredGroups()
|
||||
}
|
||||
|
@ -314,13 +351,15 @@ abstract class ComickFun(
|
|||
private fun mangaDetailsParse(response: Response, manga: SManga): SManga {
|
||||
val mangaData = response.parseAs<Manga>()
|
||||
if (!preferences.updateCover && manga.thumbnail_url != mangaData.comic.cover) {
|
||||
if (manga.thumbnail_url.toString().endsWith("#")) {
|
||||
if (manga.thumbnail_url.toString().endsWith("#1")) {
|
||||
return mangaData.toSManga(
|
||||
includeMuTags = preferences.includeMuTags,
|
||||
scorePosition = preferences.scorePosition,
|
||||
covers = listOf(
|
||||
MDcovers(
|
||||
b2key = manga.thumbnail_url?.removeSuffix("#")
|
||||
b2key = manga.thumbnail_url?.substringBeforeLast("#")
|
||||
?.substringAfterLast("/"),
|
||||
vol = "1",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -329,7 +368,10 @@ abstract class ComickFun(
|
|||
"$apiUrl/comic/${mangaData.comic.slug ?: mangaData.comic.hid}/covers?tachiyomi=true"
|
||||
val covers = client.newCall(GET(coversUrl)).execute()
|
||||
.parseAs<Covers>().md_covers.reversed()
|
||||
return mangaData.toSManga(includeMuTags = preferences.includeMuTags, covers = covers)
|
||||
return mangaData.toSManga(
|
||||
includeMuTags = preferences.includeMuTags,
|
||||
covers = if (covers.any { it.vol == "1" }) covers.filter { it.vol == "1" } else covers,
|
||||
)
|
||||
}
|
||||
return mangaData.toSManga(includeMuTags = preferences.includeMuTags)
|
||||
}
|
||||
|
@ -440,6 +482,8 @@ abstract class ComickFun(
|
|||
private const val MIGRATED_IGNORED_GROUPS = "MigratedIgnoredGroups"
|
||||
private const val FIRST_COVER_PREF = "DefaultCover"
|
||||
private const val FIRST_COVER_DEFAULT = true
|
||||
private const val SCORE_POSITION_PREF = "ScorePosition"
|
||||
private const val SCORE_POSITION_DEFAULT = "top"
|
||||
private const val limit = 20
|
||||
val dateFormat by lazy {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH).apply {
|
||||
|
|
|
@ -13,7 +13,6 @@ data class SearchManga(
|
|||
val title: String,
|
||||
@SerialName("md_covers") val mdCovers: List<MDcovers> = emptyList(),
|
||||
@SerialName("cover_url") val cover: String? = null,
|
||||
|
||||
) {
|
||||
fun toSManga() = SManga.create().apply {
|
||||
// appending # at end as part of migration from slug to hid
|
||||
|
@ -31,24 +30,26 @@ data class Manga(
|
|||
val genres: List<Name> = emptyList(),
|
||||
val demographic: String? = null,
|
||||
) {
|
||||
fun toSManga(includeMuTags: Boolean = false, covers: List<MDcovers>? = null) =
|
||||
fun toSManga(
|
||||
includeMuTags: Boolean = false,
|
||||
scorePosition: String = "",
|
||||
covers: List<MDcovers>? = null,
|
||||
) =
|
||||
SManga.create().apply {
|
||||
// appennding # at end as part of migration from slug to hid
|
||||
url = "/comic/${comic.hid}#"
|
||||
title = comic.title
|
||||
description = buildString {
|
||||
if (!comic.score.isNullOrEmpty()) {
|
||||
val stars = comic.score.toBigDecimal().div(BigDecimal(2))
|
||||
.setScale(0, RoundingMode.HALF_UP).toInt()
|
||||
append("★".repeat(stars))
|
||||
if (stars < 5) append("☆".repeat(5 - stars))
|
||||
append(" ${comic.score} ")
|
||||
}
|
||||
if (scorePosition == "top") append(comic.fancyScore)
|
||||
val desc = comic.desc?.beautifyDescription()
|
||||
if (!desc.isNullOrEmpty()) {
|
||||
if (this.isNotEmpty()) append("\n\n")
|
||||
append(desc)
|
||||
}
|
||||
if (scorePosition == "middle") {
|
||||
if (this.isNotEmpty()) append("\n\n")
|
||||
append(comic.fancyScore)
|
||||
}
|
||||
if (comic.altTitles.isNotEmpty()) {
|
||||
if (this.isNotEmpty()) append("\n\n")
|
||||
append("Alternative Titles:\n")
|
||||
|
@ -58,6 +59,10 @@ data class Manga(
|
|||
}.joinToString("\n"),
|
||||
)
|
||||
}
|
||||
if (scorePosition == "bottom") {
|
||||
if (this.isNotEmpty()) append("\n\n")
|
||||
append(comic.fancyScore)
|
||||
}
|
||||
}
|
||||
|
||||
status = comic.status.parseStatus(comic.translationComplete)
|
||||
|
@ -106,6 +111,17 @@ data class Comic(
|
|||
"cn" -> Name("Manhua")
|
||||
else -> null
|
||||
}
|
||||
val fancyScore: String = if (score.isNullOrEmpty()) {
|
||||
""
|
||||
} else {
|
||||
val stars = score.toBigDecimal().div(BigDecimal(2))
|
||||
.setScale(0, RoundingMode.HALF_UP).toInt()
|
||||
buildString {
|
||||
append("★".repeat(stars))
|
||||
if (stars < 5) append("☆".repeat(5 - stars))
|
||||
append(" $score")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
@ -131,6 +147,7 @@ data class Covers(
|
|||
@Serializable
|
||||
data class MDcovers(
|
||||
val b2key: String?,
|
||||
val vol: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -37,8 +37,9 @@ internal fun Int?.parseStatus(translationComplete: Boolean?): Int {
|
|||
internal fun parseCover(thumbnailUrl: String?, mdCovers: List<MDcovers>): String? {
|
||||
val b2key = mdCovers.firstOrNull()?.b2key
|
||||
?: return thumbnailUrl
|
||||
val vol = mdCovers.firstOrNull()?.vol.orEmpty()
|
||||
|
||||
return thumbnailUrl?.replaceAfterLast("/", "$b2key#")
|
||||
return thumbnailUrl?.replaceAfterLast("/", "$b2key#$vol")
|
||||
}
|
||||
|
||||
internal fun thumbnailIntercept(chain: Interceptor.Chain): Response {
|
||||
|
|
Loading…
Reference in New Issue