Manga District: add tag browse (#7035)

* Manga District: add tag browse

* Apply suggestions from code review

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>

* correction

* Separate method to load tags from preferences & always initialize with at least 1 tag to avoid excessively reading preferences

* remove unnecessary getter

* Fix: actually update backing field; also improve load tags from preferences

---------

Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com>
This commit is contained in:
Cuong-Tran 2025-01-08 19:50:03 +07:00 committed by Draff
parent 6f90a79c96
commit 4bc138aa39
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
2 changed files with 68 additions and 17 deletions

View File

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

View File

@ -7,7 +7,12 @@ import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
@ -17,6 +22,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
@ -41,23 +47,13 @@ class MangaDistrict :
private val titleVersion = Regex("\\(.*\\)")
override fun popularMangaFromElement(element: Element): SManga {
return super.popularMangaFromElement(element).apply {
if (isRemoveTitleVersion()) {
title = this.title.replace(titleVersion, "").trim()
}
}
}
override fun searchMangaFromElement(element: Element): SManga {
return super.searchMangaFromElement(element).apply {
if (isRemoveTitleVersion()) {
title = this.title.replace(titleVersion, "").trim()
}
}
}
override fun mangaDetailsParse(document: Document): SManga {
val tags = document.select(mangaDetailsSelectorTag).mapNotNull { element ->
element.ownText() to element.attr("href")
.removeSuffix("/").substringAfterLast('/')
}
tagList = tagList.plus(tags)
return super.mangaDetailsParse(document).apply {
if (isRemoveTitleVersion()) {
title = this.title.replace(titleVersion, "").trim()
@ -103,6 +99,60 @@ class MangaDistrict :
return super.pageListParse(document)
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
val tagFilter = filters.filterIsInstance<TagList>().firstOrNull()
if (tagFilter != null && tagFilter.state > 0) {
val urlBuilder = baseUrl.toHttpUrl().newBuilder()
urlBuilder.addPathSegment("publication-tag")
urlBuilder.addPathSegment(tagFilter.toUriPart())
urlBuilder.addPathSegments("page/$page")
return client.newCall(GET(urlBuilder.build(), headers))
.asObservableSuccess().map { response ->
popularMangaParse(response)
}
} else {
return super.fetchSearchManga(page, query, filters)
}
}
private fun loadTagListFromPreferences(): Set<Pair<String, String>> =
preferences.getStringSet(TAG_LIST_PREF, emptySet())
?.mapNotNull {
it.split('|')
.let { splits ->
if (splits.size == 2) {
splits[0] to splits[1]
} else {
null
}
}
}
?.toSet()
// Create at least 1 tag to avoid excessively reading preferences
.let { if (it.isNullOrEmpty()) setOf("Manhwa" to "manhwa") else it }
private var tagList: Set<Pair<String, String>> = loadTagListFromPreferences()
set(value) {
preferences.edit().putStringSet(
TAG_LIST_PREF,
value.map { "${it.first}|${it.second}" }.toSet(),
).apply()
field = value
}
override fun getFilterList(): FilterList {
val filters = super.getFilterList().list.toMutableList()
if (tagList.isNotEmpty()) {
filters += Filter.Separator()
filters += Filter.Header("Tag browse will ignore other filters")
filters += TagList("Tag browse", listOf(Pair("<Browse tag>", "")) + tagList.toList())
}
return FilterList(filters)
}
private class TagList(title: String, options: List<Pair<String, String>>, state: Int = 0) :
UriPartFilter(title, options.toTypedArray(), state)
private fun String.urlKey(): String {
return toHttpUrl().pathSegments.let { path ->
"${path[1]}/${path[2]}"
@ -154,6 +204,7 @@ class MangaDistrict :
companion object {
private const val REMOVE_TITLE_VERSION_PREF = "REMOVE_TITLE_VERSION"
private const val TAG_LIST_PREF = "TAG_LIST"
private const val IMG_RES_PREF = "IMG_RES"
private const val IMG_RES_ALL = "all"