Implement search and filters (#8706)
This commit is contained in:
parent
4ba9118ce3
commit
40ea248097
@ -1,11 +1,12 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'Comic Fx'
|
||||
pkgNameSuffix = 'id.comicfx'
|
||||
extClass = '.ComicFx'
|
||||
extVersionCode = 2
|
||||
extVersionCode = 3
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,27 @@
|
||||
package eu.kanade.tachiyomi.extension.id.comicfx
|
||||
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
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
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.api.get
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
@ -62,14 +71,54 @@ class ComicFx : ParsedHttpSource() {
|
||||
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
// Search
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
// Text search cannot use filters
|
||||
if (query.isNotEmpty()) {
|
||||
return client.newCall(GET("$baseUrl/search?query=$query"))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
parseSearchApiResponse(response)
|
||||
}
|
||||
}
|
||||
return super.fetchSearchManga(page, query, filters)
|
||||
}
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private fun parseSearchApiResponse(response: Response): MangasPage {
|
||||
val results = json.parseToJsonElement(response.body!!.string()).jsonObject["suggestions"]!!.jsonArray
|
||||
val manga = results.map {
|
||||
SManga.create().apply {
|
||||
title = it.jsonObject["value"]!!.jsonPrimitive.content
|
||||
url = "/komik/${it.jsonObject["data"]!!.jsonPrimitive.content}"
|
||||
}
|
||||
}
|
||||
return MangasPage(manga, false)
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val filters = if (filters.isEmpty()) getFilterList() else filters
|
||||
val genre = filters.findInstance<GenreList>()?.toUriPart()
|
||||
val order = filters.findInstance<OrderByFilter>()?.toUriPart()
|
||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||
|
||||
// todo search
|
||||
val url = "$baseUrl/filterList".toHttpUrlOrNull()!!.newBuilder()
|
||||
|
||||
return GET("$baseUrl/filterList?page=$page&cstatus=&ctype=&cat=$genre&alpha=&$order&author=&artist=&tag=") // filter
|
||||
for (filter in filterList) {
|
||||
when (filter) {
|
||||
is GenreFilter -> url.addQueryParameter("cat", filter.toUriPart())
|
||||
is SortFilter -> {
|
||||
url.addQueryParameter("sortBy", filter.toUriPart())
|
||||
url.addQueryParameter("asc", filter.state!!.ascending.toString())
|
||||
}
|
||||
is StatusFilter -> url.addQueryParameter("cstatus", filter.toUriPart())
|
||||
is TypeFilter -> url.addQueryParameter("ctype", filter.toUriPart())
|
||||
is AuthorFilter -> url.addQueryParameter("author", filter.state)
|
||||
is ArtistFilter -> url.addQueryParameter("artist", filter.state)
|
||||
}
|
||||
}
|
||||
|
||||
url.addQueryParameter("page", page.toString())
|
||||
// Unimplemented parameters: "alpha" (For filtering by alphabet) and "tag" (idk)
|
||||
return GET(url.toString())
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = popularMangaSelector()
|
||||
@ -105,18 +154,31 @@ class ComicFx : ParsedHttpSource() {
|
||||
val updateOn = document.select(".infokomik .infolengkap span:contains(update) b").text()
|
||||
val date = document.select(".infokomik .infolengkap span:contains(update)").text().substringAfter(updateOn)
|
||||
val checkChapter = document.select(chapterListSelector()).firstOrNull()
|
||||
if (date != "" && checkChapter != null) chapters[0].date_upload = parseDate(date)
|
||||
if (date != "" && checkChapter != null && chapters[0].date_upload == 0L) {
|
||||
chapters[0].date_upload = SimpleDateFormat("dd mmm yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
return chapters
|
||||
}
|
||||
|
||||
private fun parseDate(date: String): Long {
|
||||
return SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
return when (date) {
|
||||
"hari ini" -> System.currentTimeMillis()
|
||||
"kemarin" -> System.currentTimeMillis() - (1000 * 60 * 60 * 24) // yesterday
|
||||
else -> {
|
||||
try {
|
||||
SimpleDateFormat("dd-mm-yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
} catch (_: ParseException) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
name = element.text()
|
||||
name = element.selectFirst("span.chapternum").text()
|
||||
date_upload = parseDate(element.selectFirst("span.chapterdate").text())
|
||||
}
|
||||
|
||||
// Pages
|
||||
@ -137,22 +199,29 @@ class ComicFx : ParsedHttpSource() {
|
||||
|
||||
// filters
|
||||
override fun getFilterList() = FilterList(
|
||||
OrderByFilter(),
|
||||
GenreList()
|
||||
SortFilter(sortList),
|
||||
GenreFilter(),
|
||||
StatusFilter(),
|
||||
TypeFilter(),
|
||||
ArtistFilter("Artist"),
|
||||
AuthorFilter("Author")
|
||||
)
|
||||
|
||||
private class OrderByFilter : UriPartFilter(
|
||||
"Sort by",
|
||||
arrayOf(
|
||||
Pair("sortBy=name&asc=true", "Default"),
|
||||
Pair("sortBy=name&asc=true", "A-Z"),
|
||||
Pair("sortBy=name&asc=false", "Z-A"),
|
||||
Pair("sortBy=views&asc=false", "Popular to Less"),
|
||||
Pair("sortBy=views&asc=true", "Less to Popular")
|
||||
)
|
||||
private class ArtistFilter(name: String) : Filter.Text(name)
|
||||
private class AuthorFilter(name: String) : Filter.Text(name)
|
||||
|
||||
private class SortFilter(val sortables: List<Pair<String, String>>) : Filter.Sort("Sort", sortables.map { it.second }.toTypedArray(), Selection(1, false)) {
|
||||
fun toUriPart(): String {
|
||||
return sortables[this.state!!.index].first
|
||||
}
|
||||
}
|
||||
|
||||
private val sortList = listOf(
|
||||
Pair("name", "Alphabetical"),
|
||||
Pair("views", "Popular"),
|
||||
)
|
||||
|
||||
private class GenreList : UriPartFilter(
|
||||
private class GenreFilter : UriPartFilter(
|
||||
"Select Genre",
|
||||
arrayOf(
|
||||
Pair("", "<select>"),
|
||||
@ -190,6 +259,26 @@ class ComicFx : ParsedHttpSource() {
|
||||
)
|
||||
)
|
||||
|
||||
private class StatusFilter : UriPartFilter(
|
||||
"Status",
|
||||
arrayOf(
|
||||
Pair("", "All"),
|
||||
Pair("1", "Ongoing"),
|
||||
Pair("2", "Complete")
|
||||
)
|
||||
)
|
||||
|
||||
private class TypeFilter : UriPartFilter(
|
||||
"Type",
|
||||
arrayOf(
|
||||
Pair("", "All"),
|
||||
Pair("1", "Manhua (Chinese)"),
|
||||
Pair("2", "Manhwa (Korean)"),
|
||||
Pair("3", "Manga"),
|
||||
Pair("4", "Oneshot"),
|
||||
)
|
||||
)
|
||||
|
||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray()) {
|
||||
fun toUriPart() = vals[state].first
|
||||
|
Loading…
x
Reference in New Issue
Block a user