Remove ColoredManga (#6201)
This commit is contained in:
parent
e1f897f6c8
commit
297cb4c6e4
|
@ -1,8 +0,0 @@
|
||||||
ext {
|
|
||||||
extName = 'ColoredManga'
|
|
||||||
extClass = '.ColoredManga'
|
|
||||||
extVersionCode = 36
|
|
||||||
isNsfw = true
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -1,439 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.coloredmanga
|
|
||||||
|
|
||||||
import android.util.Base64
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
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.model.SManga.Companion.COMPLETED
|
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import okhttp3.Interceptor
|
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
|
||||||
import okhttp3.MultipartBody
|
|
||||||
import okhttp3.Protocol
|
|
||||||
import okhttp3.Request
|
|
||||||
import okhttp3.Response
|
|
||||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
|
||||||
import org.json.JSONObject
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import rx.Observable
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.TimeZone
|
|
||||||
|
|
||||||
class ColoredManga : HttpSource() {
|
|
||||||
|
|
||||||
override val name = "ColoredManga"
|
|
||||||
|
|
||||||
override val baseUrl = "https://coloredmanga.net"
|
|
||||||
|
|
||||||
override val versionId = 2
|
|
||||||
|
|
||||||
private val searchUrl = "$baseUrl/manga"
|
|
||||||
|
|
||||||
override val lang = "en"
|
|
||||||
|
|
||||||
override val supportsLatest = true
|
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
|
||||||
|
|
||||||
private val nameRegex = Regex(" -$")
|
|
||||||
|
|
||||||
private val chapterNameRegex = Regex(" 0+(\\d+)")
|
|
||||||
|
|
||||||
override val client = network.cloudflareClient
|
|
||||||
.newBuilder()
|
|
||||||
.addInterceptor(::Intercept)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// Popular
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
|
||||||
return GET(searchUrl, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val dateFormat = SimpleDateFormat("MMM dd, yyyy, HH:mm", Locale.ENGLISH).apply {
|
|
||||||
timeZone = TimeZone.getTimeZone("UTC")
|
|
||||||
}
|
|
||||||
private val chapterDateFormat = SimpleDateFormat("MMM d, yyyy, HH:mm", Locale.ENGLISH).apply {
|
|
||||||
timeZone = TimeZone.getTimeZone("UTC")
|
|
||||||
}
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage = searchMangas(response, sortBy = "pop" to "desc")
|
|
||||||
|
|
||||||
private fun searchMangas(response: Response, title: String = "", filters: FilterList? = null, sortBy: Pair<String, String> = "" to ""): MangasPage {
|
|
||||||
var sort = sortBy
|
|
||||||
val mangas = getMangas(response.asJsoup()).filter {
|
|
||||||
val genreIncluded: MutableList<String> = mutableListOf()
|
|
||||||
val genreExcluded: MutableList<String> = mutableListOf()
|
|
||||||
|
|
||||||
val typeIncluded: MutableList<String> = mutableListOf()
|
|
||||||
val typeExcluded: MutableList<String> = mutableListOf()
|
|
||||||
|
|
||||||
val colorIncluded: MutableList<String> = mutableListOf()
|
|
||||||
val colorExcluded: MutableList<String> = mutableListOf()
|
|
||||||
|
|
||||||
val statusIncluded: MutableList<String> = mutableListOf()
|
|
||||||
val statusExcluded: MutableList<String> = mutableListOf()
|
|
||||||
|
|
||||||
filters?.forEach { filter ->
|
|
||||||
when (filter) {
|
|
||||||
is SortFilter -> {
|
|
||||||
sort = filter.getValue() to if (filter.state!!.ascending) "asc" else "desc"
|
|
||||||
}
|
|
||||||
is GenreFilter -> {
|
|
||||||
if (filter.state.isNotEmpty()) {
|
|
||||||
filter.state.split(",").filter(String::isNotBlank).map { tag ->
|
|
||||||
val trimmed = tag.trim().lowercase()
|
|
||||||
if (trimmed.startsWith("-")) {
|
|
||||||
genreExcluded.add(trimmed)
|
|
||||||
} else {
|
|
||||||
genreIncluded.add(trimmed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is TypeFilter -> {
|
|
||||||
filter.state.filter { state -> state.isIncluded() }.forEach { tri ->
|
|
||||||
typeIncluded.add(tri.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.state.filter { state -> state.isExcluded() }.forEach { tri ->
|
|
||||||
typeExcluded.add(tri.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is ColorFilter -> {
|
|
||||||
filter.state.filter { state -> state.isIncluded() }.forEach { tri ->
|
|
||||||
colorIncluded.add(tri.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.state.filter { state -> state.isExcluded() }.forEach { tri ->
|
|
||||||
colorExcluded.add(tri.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is StatusFilter -> {
|
|
||||||
filter.state.filter { state -> state.isIncluded() }.forEach { tri ->
|
|
||||||
statusIncluded.add(tri.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.state.filter { state -> state.isExcluded() }.forEach { tri ->
|
|
||||||
statusExcluded.add(tri.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val includeGenre = genreIncluded.isEmpty() || it.tags.map { genre -> genre.lowercase() }.containsAll(genreIncluded)
|
|
||||||
val excludeGenre = genreExcluded.isNotEmpty() && it.tags.map { genre -> genre.lowercase() }.containsAll(genreExcluded)
|
|
||||||
|
|
||||||
val includeType = typeIncluded.isEmpty() || typeIncluded.contains(it.type.lowercase())
|
|
||||||
val excludeType = typeExcluded.isNotEmpty() && typeExcluded.contains(it.type)
|
|
||||||
|
|
||||||
val includeColor = colorIncluded.isEmpty() || colorIncluded.contains(it.version)
|
|
||||||
val excludeColor = colorExcluded.isNotEmpty() && colorExcluded.contains(it.version)
|
|
||||||
|
|
||||||
val regularSearch = it.name.contains(title, true) || it.synopsis.contains(title, true)
|
|
||||||
|
|
||||||
includeGenre && !excludeGenre &&
|
|
||||||
includeType && !excludeType &&
|
|
||||||
includeColor && !excludeColor &&
|
|
||||||
regularSearch
|
|
||||||
}
|
|
||||||
|
|
||||||
val sorted = when (sort.first) {
|
|
||||||
"pop" -> {
|
|
||||||
if (sort.second == "desc") {
|
|
||||||
mangas.sortedByDescending { it.totalViews }
|
|
||||||
} else {
|
|
||||||
mangas.sortedBy { it.totalViews }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"tit" -> {
|
|
||||||
if (sort.second == "desc") {
|
|
||||||
mangas.sortedByDescending { it.name }
|
|
||||||
} else {
|
|
||||||
mangas.sortedBy { it.name }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"new" -> {
|
|
||||||
if (sort.second == "desc") {
|
|
||||||
mangas.sortedByDescending {
|
|
||||||
try {
|
|
||||||
dateFormat.parse(it.date)!!.time
|
|
||||||
} catch (e: Exception) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mangas.sortedBy {
|
|
||||||
try {
|
|
||||||
dateFormat.parse(it.date)!!.time
|
|
||||||
} catch (e: Exception) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
if (sort.second == "desc") {
|
|
||||||
mangas.sortedByDescending {
|
|
||||||
try {
|
|
||||||
dateFormat.parse(it.chapters.last().date)!!.time
|
|
||||||
} catch (e: Exception) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mangas.sortedBy {
|
|
||||||
try {
|
|
||||||
dateFormat.parse(it.chapters.last().date)!!.time
|
|
||||||
} catch (e: Exception) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val final = sorted.map(::popularManga)
|
|
||||||
return MangasPage(final, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMangas(doc: Document): List<Mangas> {
|
|
||||||
val mangasRaw = doc.selectFirst("script:containsData(\\\"cover)")!!.data()
|
|
||||||
val mangasJson = mangasRaw
|
|
||||||
.replace(Regex("""\\([\\"])"""), "$1")
|
|
||||||
.replaceBefore("\"data\":[", "{")
|
|
||||||
.removeSuffix("]}]\\n\"])")
|
|
||||||
|
|
||||||
return mangasJson.parseAs<MangasList>().data
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getManga(url: String): Request {
|
|
||||||
val formData = MultipartBody.Builder().setType(MultipartBody.FORM)
|
|
||||||
.addFormDataPart("id", url.substringAfter("manga/"))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url("$baseUrl/api/selectedManga")
|
|
||||||
.put(formData)
|
|
||||||
.addHeader("Cache-Control", "no-store")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
return request
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getImage(manga_name: String, volume_name: String? = "", chapter: Chapter, index: String): String {
|
|
||||||
val chapterNumber = index.padStart(4, '0')
|
|
||||||
val chapterName = listOf(chapter.number, chapter.title)
|
|
||||||
.joinToString(" - ")
|
|
||||||
.trim()
|
|
||||||
.replace(nameRegex, "")
|
|
||||||
|
|
||||||
val formData = MultipartBody.Builder().setType(MultipartBody.FORM)
|
|
||||||
.addFormDataPart("path", "/images/content/$manga_name/$volume_name$chapterName")
|
|
||||||
.addFormDataPart("number", chapterNumber)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url("$baseUrl/api/dynamicImages")
|
|
||||||
.put(formData)
|
|
||||||
.addHeader("Cache-Control", "no-store")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val response = client.newCall(request).execute().body.string()
|
|
||||||
|
|
||||||
val responseJson = JSONObject(response)
|
|
||||||
val image = responseJson.getString("image")
|
|
||||||
|
|
||||||
return image
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun popularManga(manga: Mangas): SManga {
|
|
||||||
return SManga.create().apply {
|
|
||||||
title = manga.name
|
|
||||||
setUrlWithoutDomain("$baseUrl/manga/${manga.id}")
|
|
||||||
thumbnail_url = "$baseUrl${manga.cover}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Latest
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request = popularMangaRequest(page)
|
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage = searchMangas(response, sortBy = "lat" to "desc")
|
|
||||||
|
|
||||||
// Search
|
|
||||||
|
|
||||||
override fun fetchSearchManga(
|
|
||||||
page: Int,
|
|
||||||
query: String,
|
|
||||||
filters: FilterList,
|
|
||||||
): Observable<MangasPage> {
|
|
||||||
val response = client.newCall(GET(searchUrl, headers)).execute()
|
|
||||||
|
|
||||||
return Observable.just(
|
|
||||||
searchMangas(response, query, filters),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = popularMangaRequest(page)
|
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response)
|
|
||||||
|
|
||||||
// Details
|
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
|
||||||
return getManga(manga.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getMangaUrl(manga: SManga): String = "$baseUrl${manga.url}"
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
|
||||||
val manga = response.parseAs<Mangas>()
|
|
||||||
return SManga.create().apply {
|
|
||||||
title = manga.name
|
|
||||||
url = "/manga/${manga.id}"
|
|
||||||
author = manga.author
|
|
||||||
artist = manga.artist
|
|
||||||
genre = manga.tags.joinToString()
|
|
||||||
description = manga.synopsis
|
|
||||||
status = when (manga.status.lowercase()) {
|
|
||||||
"Ongoing" -> SManga.ONGOING
|
|
||||||
"Cancelled" -> SManga.CANCELLED
|
|
||||||
"Hiatus" -> SManga.ON_HIATUS
|
|
||||||
else -> COMPLETED
|
|
||||||
}
|
|
||||||
thumbnail_url = "$baseUrl${manga.cover}"
|
|
||||||
initialized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chapters
|
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request = mangaDetailsRequest(manga)
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
|
||||||
val manga = response.parseAs<Mangas>()
|
|
||||||
|
|
||||||
val listMangas = if (manga.chapters.isNotEmpty()) {
|
|
||||||
manga.chapters.map { chapter ->
|
|
||||||
SChapter.create().apply {
|
|
||||||
name = listOf(chapter.number, chapter.title)
|
|
||||||
.joinToString(" - ")
|
|
||||||
.trim()
|
|
||||||
.replace(nameRegex, "")
|
|
||||||
.replace(chapterNameRegex, " $1")
|
|
||||||
|
|
||||||
url = "/manga/${manga.id}/${chapter.number}"
|
|
||||||
date_upload = try {
|
|
||||||
chapterDateFormat.parse(chapter.date)!!.time
|
|
||||||
} catch (e: Exception) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
manga.volume.flatMap { volume ->
|
|
||||||
volume.chapters.map { chapter ->
|
|
||||||
SChapter.create().apply {
|
|
||||||
name = "${volume.number} | ${chapter.number} - ${chapter.title}".replace(nameRegex, "").replace(chapterNameRegex, " $1")
|
|
||||||
url = "/manga/${manga.id}/${chapter.number}"
|
|
||||||
date_upload = try {
|
|
||||||
chapterDateFormat.parse(chapter.date)!!.time
|
|
||||||
} catch (e: Exception) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return listMangas.reversed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFilterList(): FilterList = getFilters()
|
|
||||||
|
|
||||||
// Pages
|
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
|
||||||
return getManga(chapter.url.substringBeforeLast("/"))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
|
||||||
val response = client.newCall(pageListRequest(chapter)).execute()
|
|
||||||
val manga = response.parseAs<Mangas>()
|
|
||||||
val volumes = manga.chapters.isEmpty() || manga.volume.isNotEmpty()
|
|
||||||
chapter.apply { name = chapter.url.substringAfterLast("/") }
|
|
||||||
|
|
||||||
val spChapter = if (volumes) {
|
|
||||||
manga.volume
|
|
||||||
.flatMap { it.chapters }
|
|
||||||
.find { it.number == chapter.name }
|
|
||||||
} else {
|
|
||||||
manga.chapters.find { it.number == chapter.name }
|
|
||||||
}
|
|
||||||
val chapterJson = spChapter!!.toJson()
|
|
||||||
|
|
||||||
return Observable.just(
|
|
||||||
List(spChapter.totalImage) {
|
|
||||||
val url = "https://127.0.0.1/#${it + 1}+${manga.name}"
|
|
||||||
val volumeInfo = if (volumes) {
|
|
||||||
manga.volume.find { vol -> vol.chapters.any { chap -> chap.number == chapter.name } }
|
|
||||||
?.let { vol ->
|
|
||||||
listOf(vol.number, vol.title)
|
|
||||||
.joinToString(" - ")
|
|
||||||
.trim()
|
|
||||||
.replace(nameRegex, "") + "/"
|
|
||||||
} ?: ""
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
Page(it, url = "$baseUrl${chapter.url}", imageUrl = "$url&volume=$volumeInfo&chapter=$chapterJson")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val mediaTypePattern = Regex("""(^[^;,]*)[;,]""")
|
|
||||||
private fun Intercept(chain: Interceptor.Chain): Response {
|
|
||||||
val yurl = chain.request().url
|
|
||||||
return if (yurl.toString().startsWith("https://127.0.0.1/#")) {
|
|
||||||
val index = yurl.fragment!!.substringBefore("+")
|
|
||||||
val manga_name = yurl.fragment!!.substringAfter("+").substringBefore("&chapter=").substringBefore("&volume=")
|
|
||||||
val volume_name = yurl.fragment!!.substringAfter("&volume=").substringBefore("&chapter=")
|
|
||||||
val chapter = (yurl.fragment!!.substringAfter("chapter=")).parseAs<Chapter>()
|
|
||||||
|
|
||||||
val image = getImage(manga_name, volume_name, chapter, index)
|
|
||||||
|
|
||||||
val dataString = image.substringAfter(":")
|
|
||||||
val byteArray = Base64.decode(dataString.substringAfter("base64,"), Base64.DEFAULT)
|
|
||||||
val mediaType = mediaTypePattern.find(dataString)!!.value.toMediaTypeOrNull()
|
|
||||||
Response.Builder().body(byteArray.toResponseBody(mediaType))
|
|
||||||
.request(chain.request())
|
|
||||||
.protocol(Protocol.HTTP_1_0)
|
|
||||||
.code(200)
|
|
||||||
.message("")
|
|
||||||
.build()
|
|
||||||
} else {
|
|
||||||
chain.proceed(chain.request())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private inline fun <reified T> String.parseAs(): T {
|
|
||||||
return json.decodeFromString(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <reified T> Response.parseAs(): T {
|
|
||||||
return json.decodeFromString(body.string())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Chapter.toJson(): String {
|
|
||||||
return json.encodeToString(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
|
|
||||||
override fun pageListParse(response: Response): List<Page> = throw UnsupportedOperationException()
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.coloredmanga
|
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class Mangas(
|
|
||||||
val id: String,
|
|
||||||
val name: String,
|
|
||||||
val date: String,
|
|
||||||
val tags: List<String>,
|
|
||||||
val volume: List<Volume> = listOf(),
|
|
||||||
val chapters: List<Chapter> = listOf(),
|
|
||||||
val totalViews: Int,
|
|
||||||
val synopsis: String,
|
|
||||||
val author: String,
|
|
||||||
val artist: String,
|
|
||||||
val cover: String,
|
|
||||||
val status: String,
|
|
||||||
val version: String,
|
|
||||||
val type: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class MangasList(
|
|
||||||
val data: List<Mangas>,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class Volume(
|
|
||||||
val id: String,
|
|
||||||
val title: String = "",
|
|
||||||
val number: String,
|
|
||||||
val chapters: List<Chapter>,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class Chapter(
|
|
||||||
val id: String,
|
|
||||||
val title: String = "",
|
|
||||||
val number: String,
|
|
||||||
val date: String,
|
|
||||||
val totalImage: Int,
|
|
||||||
)
|
|
|
@ -1,63 +0,0 @@
|
||||||
@file:JvmName("ColoredMangaKt")
|
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.extension.en.coloredmanga
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
|
||||||
|
|
||||||
fun getFilters(): FilterList {
|
|
||||||
return FilterList(
|
|
||||||
SortFilter("Sort by", Filter.Sort.Selection(0, false), getSortsList),
|
|
||||||
TypeFilter("Types"),
|
|
||||||
ColorFilter("Color"),
|
|
||||||
StatusFilter("Status"),
|
|
||||||
GenreFilter("Genre"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ColorFilter(name: String) :
|
|
||||||
Filter.Group<TriFilter>(
|
|
||||||
name,
|
|
||||||
listOf(
|
|
||||||
"B/W",
|
|
||||||
"Color",
|
|
||||||
).map { TriFilter(it, it.lowercase()) },
|
|
||||||
)
|
|
||||||
|
|
||||||
internal class TypeFilter(name: String) :
|
|
||||||
Filter.Group<TriFilter>(
|
|
||||||
name,
|
|
||||||
listOf(
|
|
||||||
"Manga",
|
|
||||||
"Manhwa",
|
|
||||||
).map { TriFilter(it, it.lowercase()) },
|
|
||||||
)
|
|
||||||
|
|
||||||
internal class StatusFilter(name: String) :
|
|
||||||
Filter.Group<TriFilter>(
|
|
||||||
name,
|
|
||||||
listOf(
|
|
||||||
"Ongoing",
|
|
||||||
"Completed",
|
|
||||||
"Cancelled",
|
|
||||||
"Hiatus",
|
|
||||||
).map { TriFilter(it, it.lowercase()) },
|
|
||||||
)
|
|
||||||
|
|
||||||
internal class GenreFilter(name: String) : TextFilter(name)
|
|
||||||
|
|
||||||
internal open class TriFilter(name: String, val value: String) : Filter.TriState(name)
|
|
||||||
|
|
||||||
internal open class TextFilter(name: String) : Filter.Text(name)
|
|
||||||
|
|
||||||
internal open class SortFilter(name: String, selection: Selection, private val vals: List<Pair<String, String>>) :
|
|
||||||
Filter.Sort(name, vals.map { it.first }.toTypedArray(), selection) {
|
|
||||||
fun getValue() = vals[state!!.index].second
|
|
||||||
}
|
|
||||||
|
|
||||||
private val getSortsList: List<Pair<String, String>> = listOf(
|
|
||||||
Pair("Last Updated", "lat"),
|
|
||||||
Pair("Newest", "new"),
|
|
||||||
Pair("Popularity", "pop"),
|
|
||||||
Pair("Title", "tit"),
|
|
||||||
)
|
|
Loading…
Reference in New Issue