diff --git a/src/en/comix/build.gradle b/src/en/comix/build.gradle index 73ba4a18c..d725839c9 100644 --- a/src/en/comix/build.gradle +++ b/src/en/comix/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Comix' extClass = '.Comix' - extVersionCode = 1 + extVersionCode = 2 isNsfw = true } diff --git a/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/Comix.kt b/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/Comix.kt index 993a3b513..76cfd437c 100644 --- a/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/Comix.kt +++ b/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/Comix.kt @@ -39,12 +39,18 @@ class Comix : HttpSource(), ConfigurableSource { /******************************* POPULAR MANGA ************************************/ override fun popularMangaRequest(page: Int): Request { - val url = apiUrl.toHttpUrl().newBuilder() - .addPathSegment("manga") - .addQueryParameter("order[views_30d]", "desc") - .addQueryParameter("limit", "50") - .addQueryParameter("page", page.toString()) - .build() + val url = apiUrl.toHttpUrl().newBuilder().apply { + addPathSegment("manga") + addQueryParameter("order[views_30d]", "desc") + addQueryParameter("limit", "50") + addQueryParameter("page", page.toString()) + + if (preferences.hideNsfw()) { + NSFW_GENRE_IDS.forEach { + addQueryParameter("genres[]", "-$it") + } + } + }.build() return GET(url, headers) } @@ -54,12 +60,18 @@ class Comix : HttpSource(), ConfigurableSource { /******************************* LATEST MANGA ************************************/ override fun latestUpdatesRequest(page: Int): Request { - val url = apiUrl.toHttpUrl().newBuilder() - .addPathSegment("manga") - .addQueryParameter("order[chapter_updated_at]", "desc") - .addQueryParameter("limit", "50") - .addQueryParameter("page", page.toString()) - .build() + val url = apiUrl.toHttpUrl().newBuilder().apply { + addPathSegment("manga") + addQueryParameter("order[chapter_updated_at]", "desc") + addQueryParameter("limit", "50") + addQueryParameter("page", page.toString()) + + if (preferences.hideNsfw()) { + NSFW_GENRE_IDS.forEach { + addQueryParameter("genres[]", "-$it") + } + } + }.build() return GET(url, headers) } @@ -71,23 +83,30 @@ class Comix : HttpSource(), ConfigurableSource { override fun getFilterList() = ComixFilters().getFilterList() override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val url = apiUrl.toHttpUrl().newBuilder() - .addPathSegment("manga") + val url = apiUrl.toHttpUrl().newBuilder().apply { + addPathSegment("manga") - filters.filterIsInstance() - .forEach { it.addToUri(url) } + filters.filterIsInstance() + .forEach { it.addToUri(this) } - // Make searches accurate - if (query.isNotBlank()) { - url.addQueryParameter("keyword", query) - url.removeAllQueryParameters("order[views_30d]") - url.setQueryParameter("order[relevance]", "desc") - } + // Make searches accurate + if (query.isNotBlank()) { + addQueryParameter("keyword", query) + removeAllQueryParameters("order[views_30d]") + setQueryParameter("order[relevance]", "desc") + } - url.addQueryParameter("limit", "50") - .addQueryParameter("page", page.toString()) + if (preferences.hideNsfw()) { + NSFW_GENRE_IDS.forEach { + addQueryParameter("genres[]", "-$it") + } + } - return GET(url.build(), headers) + addQueryParameter("limit", "50") + addQueryParameter("page", page.toString()) + }.build() + + return GET(url, headers) } override fun searchMangaParse(response: Response): MangasPage { @@ -121,6 +140,7 @@ class Comix : HttpSource(), ConfigurableSource { return mangaResponse.result.toSManga( preferences.posterQuality(), preferences.alternativeNamesInDescription(), + preferences.scorePosition(), ) } @@ -253,6 +273,13 @@ class Comix : HttpSource(), ConfigurableSource { setDefaultValue("large") }.let(screen::addPreference) + SwitchPreferenceCompat(screen.context).apply { + key = NSFW_PREF + title = "Hide NSFW content" + summary = "Hides NSFW content from popular, latest, and search lists." + setDefaultValue(false) + }.let(screen::addPreference) + SwitchPreferenceCompat(screen.context).apply { key = DEDUPLICATE_CHAPTERS title = "Deduplicate Chapters" @@ -269,6 +296,15 @@ class Comix : HttpSource(), ConfigurableSource { setDefaultValue(false) }.let(screen::addPreference) + + ListPreference(screen.context).apply { + key = PREF_SCORE_POSITION + title = "Score display position" + summary = "%s" + entries = arrayOf("Top of description", "Bottom of description", "Don't show") + entryValues = arrayOf("top", "bottom", "none") + setDefaultValue("top") + }.let(screen::addPreference) } private fun SharedPreferences.posterQuality() = @@ -280,9 +316,19 @@ class Comix : HttpSource(), ConfigurableSource { private fun SharedPreferences.alternativeNamesInDescription() = getBoolean(ALTERNATIVE_NAMES_IN_DESCRIPTION, false) + private fun SharedPreferences.scorePosition() = + getString(PREF_SCORE_POSITION, "top") ?: "top" + + private fun SharedPreferences.hideNsfw() = + getBoolean(NSFW_PREF, false) + companion object { private const val PREF_POSTER_QUALITY = "pref_poster_quality" + private const val NSFW_PREF = "nsfw_pref" private const val DEDUPLICATE_CHAPTERS = "pref_deduplicate_chapters" private const val ALTERNATIVE_NAMES_IN_DESCRIPTION = "pref_alt_names_in_description" + private const val PREF_SCORE_POSITION = "pref_score_position" + + private val NSFW_GENRE_IDS = listOf("87264", "8", "87265", "13", "87266", "87268") } } diff --git a/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixDto.kt b/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixDto.kt index f16008170..0077ae03c 100644 --- a/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixDto.kt +++ b/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixDto.kt @@ -4,6 +4,8 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import java.math.BigDecimal +import java.math.RoundingMode @Serializable data class Term( @@ -33,6 +35,8 @@ class Manga( private val genre: List?, private val theme: List?, private val demographic: List?, + @SerialName("rated_avg") + private val ratedAvg: Double = 0.0, ) { @Serializable class Poster( @@ -47,15 +51,44 @@ class Manga( } } + private val fancyScore: String + get() { + if (ratedAvg == 0.0) return "" + + val score = ratedAvg.toBigDecimal() + val stars = score.div(BigDecimal(2)) + .setScale(0, RoundingMode.HALF_UP).toInt() + + val scoreString = if (score.scale() == 0) { + score.toPlainString() + } else { + score.stripTrailingZeros().toPlainString() + } + + return buildString { + append("★".repeat(stars)) + if (stars < 5) append("☆".repeat(5 - stars)) + append(" $scoreString") + } + } + fun toSManga( posterQuality: String?, altTitlesInDesc: Boolean = false, + scorePosition: String, ) = SManga.create().apply { url = "/$hashId" title = this@Manga.title author = this@Manga.author.takeUnless { it.isNullOrEmpty() }?.joinToString { it.title } artist = this@Manga.artist.takeUnless { it.isNullOrEmpty() }?.joinToString { it.title } description = buildString { + if (scorePosition == "top") { + fancyScore.takeIf { it.isNotEmpty() }?.let { + append(it) + append("\n\n") + } + } + synopsis.takeUnless { it.isNullOrEmpty() } ?.let { append(it) } altTitles.takeIf { altTitlesInDesc && it.isNotEmpty() } @@ -64,6 +97,13 @@ class Manga( append("Alternative Names:\n") append(altName.joinToString("\n")) } + + if (scorePosition == "bottom") { + fancyScore.takeIf { it.isNotEmpty() }?.let { + if (isNotEmpty()) append("\n\n") + append(it) + } + } } initialized = true status = when (this@Manga.status) { diff --git a/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixFilters.kt b/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixFilters.kt index 96117a0dc..029b7287b 100644 --- a/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixFilters.kt +++ b/src/en/comix/src/eu/kanade/tachiyomi/extension/en/comix/ComixFilters.kt @@ -105,10 +105,10 @@ class ComixFilters { fun getFilterList() = FilterList( SortFilter(getSortables()), StatusFilter(), - MinChapterFilter(), GenreFilter(getGenres()), TypeFilter(), DemographicFilter(getDemographics()), + MinChapterFilter(), Filter.Separator(), Filter.Header("Release Year"), YearFromFilter(), @@ -180,7 +180,7 @@ class ComixFilters { private class TypeFilter : UriMultiSelectFilter( "Type", - "type", + "types[]", arrayOf( Pair("Manga", "manga"), Pair("Manhwa", "manhwa"),