MangaDistrict: custom title regex (#11161)

* feat(MangaDistrict): only set chapter date got from page-list if it still has NEW tag

* feat(MangaDistrict): Add custom title regex & remove the cleaning from browsing

* verify regex

* switch to checkbox

* refactor: remove redundant methods for popular and latest manga elements

* update summary after edit

* validate custom regex on edit

* refactor: simplify regex validation logic

* refactor: improve null safety in afterTextChanged method

* Revert "refactor: remove redundant methods for popular and latest manga elements"

This reverts commit dfc0e643aaa5330d48edf07204db10dd29a24c35.

* Add back cleaning title for browsing/searching

* clear date from preference

* small refactor
This commit is contained in:
Cuong-Tran 2025-10-22 12:27:51 +07:00 committed by Draff
parent fa899de7d9
commit ad03299e49
Signed by: Draff
GPG Key ID: E8A89F3211677653
2 changed files with 74 additions and 9 deletions

View File

@ -3,7 +3,7 @@ ext {
extClass = '.MangaDistrict' extClass = '.MangaDistrict'
themePkg = 'madara' themePkg = 'madara'
baseUrl = 'https://mangadistrict.com' baseUrl = 'https://mangadistrict.com'
overrideVersionCode = 12 overrideVersionCode = 13
isNsfw = true isNsfw = true
} }

View File

@ -2,9 +2,14 @@ package eu.kanade.tachiyomi.extension.en.mangadistrict
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.SharedPreferences import android.content.SharedPreferences
import android.text.Editable
import android.text.TextWatcher
import android.widget.Button
import android.widget.Toast
import androidx.preference.CheckBoxPreference
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.multisrc.madara.Madara import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.network.asObservableSuccess
@ -84,8 +89,15 @@ class MangaDistrict :
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
return super.chapterFromElement(element).apply { return super.chapterFromElement(element).apply {
val urlKey = url.urlKey() val urlKey = url.urlKey()
preferences.dates[urlKey]?.also { val dates = preferences.dates
date_upload = it dates[urlKey]?.also {
if (date_upload == 0L) {
// If date_upload is not set (due to NEW tag), try to get it from the page lists
date_upload = it
} else {
dates.remove(urlKey)
preferences.dates = dates
}
} }
} }
} }
@ -168,11 +180,18 @@ class MangaDistrict :
} }
} }
private val titleVersion = Regex("\\(.*\\)")
private fun SManga.cleanTitleIfNeeded() = apply { private fun SManga.cleanTitleIfNeeded() = apply {
if (isRemoveTitleVersion()) { title = title.let { originalTitle ->
title = title.replace(titleVersion, "").trim() var tempTitle = originalTitle
customRemoveTitle().takeIf { it.isNotEmpty() }?.let { customRegex ->
runCatching {
tempTitle = tempTitle.replace(Regex(customRegex), "")
}
}
if (isRemoveTitleVersion()) {
tempTitle = tempTitle.replace(titleRegex, "")
}
tempTitle.trim()
} }
} }
@ -277,6 +296,8 @@ class MangaDistrict :
) )
private fun isRemoveTitleVersion() = preferences.getBoolean(REMOVE_TITLE_VERSION_PREF, false) private fun isRemoveTitleVersion() = preferences.getBoolean(REMOVE_TITLE_VERSION_PREF, false)
private fun customRemoveTitle(): String =
preferences.getString("${REMOVE_TITLE_CUSTOM_PREF}_$lang", "")!!
private fun getImgRes() = preferences.getString(IMG_RES_PREF, IMG_RES_DEFAULT)!! private fun getImgRes() = preferences.getString(IMG_RES_PREF, IMG_RES_DEFAULT)!!
private var SharedPreferences.dates: MutableMap<String, Long> private var SharedPreferences.dates: MutableMap<String, Long>
@ -292,7 +313,7 @@ class MangaDistrict :
} }
override fun setupPreferenceScreen(screen: PreferenceScreen) { override fun setupPreferenceScreen(screen: PreferenceScreen) {
SwitchPreferenceCompat(screen.context).apply { CheckBoxPreference(screen.context).apply {
key = REMOVE_TITLE_VERSION_PREF key = REMOVE_TITLE_VERSION_PREF
title = "Remove version information from entry titles" title = "Remove version information from entry titles"
summary = "This removes version tags like “(Official)” or “(Doujinshi)” from entry titles " + summary = "This removes version tags like “(Official)” or “(Doujinshi)” from entry titles " +
@ -302,6 +323,46 @@ class MangaDistrict :
setDefaultValue(false) setDefaultValue(false)
}.let(screen::addPreference) }.let(screen::addPreference)
EditTextPreference(screen.context).apply {
key = "${REMOVE_TITLE_CUSTOM_PREF}_$lang"
title = "Custom regex to be removed from title"
summary = customRemoveTitle()
setDefaultValue("")
val validate = { str: String ->
runCatching { Regex(str) }
.map { true to "" }
.getOrElse { false to it.message }
}
setOnBindEditTextListener { editText ->
editText.addTextChangedListener(
object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun afterTextChanged(editable: Editable?) {
editable ?: return
val text = editable.toString()
val valid = validate(text)
editText.error = if (!valid.first) valid.second else null
editText.rootView.findViewById<Button>(android.R.id.button1)?.isEnabled = editText.error == null
}
},
)
}
setOnPreferenceChangeListener { _, newValue ->
val (isValid, message) = validate(newValue as String)
if (isValid) {
summary = newValue
} else {
Toast.makeText(screen.context, message, Toast.LENGTH_LONG).show()
}
isValid
}
}.let(screen::addPreference)
ListPreference(screen.context).apply { ListPreference(screen.context).apply {
key = IMG_RES_PREF key = IMG_RES_PREF
title = "Image quality" title = "Image quality"
@ -320,7 +381,11 @@ class MangaDistrict :
} }
companion object { companion object {
private val titleRegex: Regex =
Regex("\\([^()]*\\)|\\{[^{}]*\\}|\\[(?:(?!]).)*]|«[^»]*»|〘[^〙]*〙|「[^」]*」|『[^』]*』|≪[^≫]*≫|﹛[^﹜]*﹜|〖[^〖〗]*〗|\uD81A\uDD0D.+?\uD81A\uDD0D|《[^》]*》|⌜.+?⌝|⟨[^⟩]*⟩|/Official|/ Official", RegexOption.IGNORE_CASE)
private const val REMOVE_TITLE_VERSION_PREF = "REMOVE_TITLE_VERSION" private const val REMOVE_TITLE_VERSION_PREF = "REMOVE_TITLE_VERSION"
private const val REMOVE_TITLE_CUSTOM_PREF = "REMOVE_TITLE_CUSTOM"
private const val TAG_LIST_PREF = "TAG_LIST" private const val TAG_LIST_PREF = "TAG_LIST"
private const val IMG_RES_PREF = "IMG_RES" private const val IMG_RES_PREF = "IMG_RES"