mangadex: r18 property support, add title during json, add [END] tag (#323)

* mangadex: r18 property support

* removed log statement

* fixed browse/latest not updating on property change

* clean up formatting

* Mangadex:
adds [END] tag back on final chapter.
Assign title during details parse

* move to preference-stub

* add summary

* fixed finished status
This commit is contained in:
Carlos 2018-05-20 20:23:13 -04:00 committed by GitHub
parent 021884c121
commit 4266908f14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 222 additions and 13 deletions

View File

@ -15,6 +15,7 @@ allprojects {
jcenter()
google()
maven { url 'https://dl.bintray.com/inorichi/tachiyomi' }
maven { url "https://jitpack.io" }
}
}

View File

@ -0,0 +1,8 @@
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.6"
targetCompatibility = "1.6"

View File

@ -0,0 +1,7 @@
package android.content;
/**
* Created by Carlos on 5/9/2018.
*/
public class Context {}

View File

@ -0,0 +1,7 @@
package android.support.v7.preference;
/**
* Created by Carlos on 5/9/2018.
*/
public abstract class DialogPreference extends Preference {}

View File

@ -0,0 +1,69 @@
package android.support.v7.preference;
import android.content.Context;
/**
* Created by Carlos on 5/9/2018.
*/
public class ListPreference extends Preference {
public ListPreference(Context context) {
throw new RuntimeException("Stub!");
}
public CharSequence getTitle() {
throw new RuntimeException("Stub!");
}
public void setTitle(CharSequence title) {
throw new RuntimeException("Stub!");
}
public void setEntries(CharSequence[] entries) {
throw new RuntimeException("Stub!");
}
public CharSequence[] getEntries() {
throw new RuntimeException("Stub!");
}
public void setOnPreferenceChangeListener(OnPreferenceChangeListener onPreferenceChangeListener) {
throw new RuntimeException("Stub!");
}
public int findIndexOfValue(String value) {
throw new RuntimeException("Stub!");
}
public void setEntryValues(CharSequence[] entryValues) {
throw new RuntimeException("Stub!");
}
public CharSequence[] getEntryValues() {
throw new RuntimeException("Stub!");
}
public void setValueIndex(int index) {
throw new RuntimeException("Stub!");
}
public String getValue() {
throw new RuntimeException("Stub!");
}
public void setValue(String value) {
throw new RuntimeException("Stub!");
}
public void setSummary(CharSequence summary) {
throw new RuntimeException("Stub!");
}
public CharSequence getSummary() {
throw new RuntimeException("Stub!");
}
}

View File

@ -0,0 +1,19 @@
package android.support.v7.preference;
/**
* Created by Carlos on 5/9/2018.
*/
public class Preference {
public interface OnPreferenceChangeListener {
boolean onPreferenceChange(Preference preference, Object newValue);
}
public void setKey(String key) {
throw new RuntimeException("Stub!");
}
public String getKey() {
throw new RuntimeException("Stub!");
}
}

View File

@ -0,0 +1,18 @@
package android.support.v7.preference;
import android.content.Context;
/**
* Created by Carlos on 5/7/2018.
*/
public class PreferenceScreen{
public boolean addPreference(Preference preference) {
throw new RuntimeException("Stub!");
}
public Context getContext() {
throw new RuntimeException("Stub!");
}
}

View File

@ -0,0 +1,13 @@
package eu.kanade.tachiyomi.source;
import android.support.v7.preference.PreferenceScreen;
/**
* Created by Carlos on 5/7/2018.
*/
public interface ConfigurableSource {
void setupPreferenceScreen(PreferenceScreen screen);
}

View File

@ -6,4 +6,6 @@ new File(rootDir, "src").eachDir { dir ->
}
}
include ':duktape-stub'
project(':duktape-stub').projectDir = new File("lib/duktape-stub")
include ':preference-stub'
project(':duktape-stub').projectDir = new File("lib/duktape-stub")
project(':preference-stub').projectDir = new File("lib/preference-stub")

View File

@ -5,14 +5,16 @@ ext {
appName = 'Tachiyomi: MangaDex'
pkgNameSuffix = "all.mangadex"
extClass = '.MangadexFactory'
extVersionCode = 22
extVersionSuffix = 22
extVersionCode = 23
extVersionSuffix = 23
libVersion = '1.2'
}
dependencies {
provided "com.google.code.gson:gson:2.8.0"
provided "com.github.salomonbrys.kotson:kotson:2.5.0"
provided project(':preference-stub')
provided "com.github.inorichi.injekt:injekt-core:65b0440"
}
apply from: "$rootDir/common.gradle"

View File

@ -1,10 +1,15 @@
package eu.kanade.tachiyomi.extension.all.mangadex
import android.app.Application
import android.content.SharedPreferences
import android.support.v7.preference.ListPreference
import android.support.v7.preference.PreferenceScreen
import com.github.salomonbrys.kotson.*
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import okhttp3.HttpUrl
@ -15,11 +20,14 @@ import org.jsoup.Jsoup
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.net.URLEncoder
import java.util.*
import java.util.concurrent.TimeUnit
open class Mangadex(override val lang: String, private val internalLang: String, private val langCode: Int) : ParsedHttpSource() {
open class Mangadex(override val lang: String, private val internalLang: String, private val langCode: Int) : ConfigurableSource, ParsedHttpSource() {
override val name = "MangaDex"
@ -27,7 +35,12 @@ open class Mangadex(override val lang: String, private val internalLang: String,
override val supportsLatest = true
override val client = clientBuilder(ALL)
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
private fun clientBuilder(): OkHttpClient = clientBuilder(getShowR18())
private fun clientBuilder(r18Toggle: Int): OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
@ -97,6 +110,22 @@ open class Mangadex(override val lang: String, private val internalLang: String,
override fun searchMangaNextPageSelector() = ".pagination li:not(.disabled) span[title*=last page]:not(disabled)"
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
return clientBuilder().newCall(popularMangaRequest(page))
.asObservableSuccess()
.map { response ->
popularMangaParse(response)
}
}
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
return clientBuilder().newCall(latestUpdatesRequest(page))
.asObservableSuccess()
.map { response ->
latestUpdatesParse(response)
}
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return getSearchClient(filters).newCall(searchMangaRequest(page, query, filters))
.asObservableSuccess()
@ -105,8 +134,6 @@ open class Mangadex(override val lang: String, private val internalLang: String,
}
}
/* get search client based off r18 filter. This will always return default client builder now until r18 solution is found or login is add
*/
private fun getSearchClient(filters: FilterList): OkHttpClient {
filters.forEach { filter ->
when (filter) {
@ -165,7 +192,7 @@ open class Mangadex(override val lang: String, private val internalLang: String,
}
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return client.newCall(apiRequest(manga))
return clientBuilder().newCall(apiRequest(manga))
.asObservableSuccess()
.map { response ->
mangaDetailsParse(response).apply { initialized = true }
@ -192,11 +219,18 @@ open class Mangadex(override val lang: String, private val internalLang: String,
var jsonData = response.body()!!.string()
val json = JsonParser().parse(jsonData).asJsonObject
val mangaJson = json.getAsJsonObject("manga")
manga.title = baseUrl + mangaJson.get("title").string
manga.thumbnail_url = baseUrl + mangaJson.get("cover_url").string
manga.description = cleanString(mangaJson.get("description").string)
manga.author = mangaJson.get("author").string
manga.artist = mangaJson.get("artist").string
manga.status = parseStatus(mangaJson.get("status").int)
val finalChapterNumber = mangaJson.get("last_chapter").int
if (finalChapterNumber != 0) {
manga.status = SManga.COMPLETED
} else {
manga.status = parseStatus(mangaJson.get("status").int)
}
var genres = mutableListOf<String>()
mangaJson.get("genres").asJsonArray.forEach { id ->
@ -219,7 +253,7 @@ open class Mangadex(override val lang: String, private val internalLang: String,
override fun chapterListSelector() = ""
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
return client.newCall(apiRequest(manga))
return clientBuilder().newCall(apiRequest(manga))
.asObservableSuccess()
.map { response ->
chapterListParse(response)
@ -230,6 +264,9 @@ open class Mangadex(override val lang: String, private val internalLang: String,
val now = Date().time
var jsonData = response.body()!!.string()
val json = JsonParser().parse(jsonData).asJsonObject
val mangaJson = json.getAsJsonObject("manga")
val finalChapterNumber = mangaJson.get("last_chapter").double
val chapterJson = json.getAsJsonObject("chapter")
val chapters = mutableListOf<SChapter>()
@ -238,13 +275,13 @@ open class Mangadex(override val lang: String, private val internalLang: String,
val chapterElement = jsonElement.asJsonObject
if (chapterElement.get("lang_code").string == internalLang && (chapterElement.get("timestamp").asLong * 1000) <= now) {
chapterElement.toString()
chapters.add(chapterFromJson(key, chapterElement))
chapters.add(chapterFromJson(key, chapterElement, finalChapterNumber))
}
}
return chapters
}
private fun chapterFromJson(chapterId: String, chapterJson: JsonObject): SChapter {
private fun chapterFromJson(chapterId: String, chapterJson: JsonObject, finalChapterNumber: Double): SChapter {
val chapter = SChapter.create()
chapter.url = BASE_CHAPTER + chapterId
var chapterName = mutableListOf<String>()
@ -259,6 +296,9 @@ open class Mangadex(override val lang: String, private val internalLang: String,
chapterName.add("-")
chapterName.add(chapterJson.get("title").string)
}
if (finalChapterNumber != 0.00 && chapterJson.get("chapter").double == finalChapterNumber) {
chapterName.add(" [END]")
}
chapter.name = cleanString(chapterName.joinToString(" "))
//convert from unix time
@ -302,7 +342,6 @@ open class Mangadex(override val lang: String, private val internalLang: String,
private fun parseStatus(status: Int) = when (status) {
1 -> SManga.ONGOING
2 -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
@ -314,6 +353,28 @@ open class Mangadex(override val lang: String, private val internalLang: String,
return baseUrl + attr
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val myPref = ListPreference(screen.context).apply {
key = SHOW_R18_PREF_Title
title = SHOW_R18_PREF_Title
title = SHOW_R18_PREF_Title
entries = arrayOf("Show No R18+", "Show All", "Show Only R18+")
entryValues = arrayOf("0", "1", "2")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = this.findIndexOfValue(selected)
preferences.edit().putInt(SHOW_R18_PREF, index).commit()
}
}
screen.addPreference(myPref)
}
private fun getShowR18(): Int = preferences.getInt(SHOW_R18_PREF, 0)
private class TextField(name: String, val key: String) : Filter.Text(name)
private class Genre(val id: String, name: String) : Filter.CheckBox(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
@ -376,6 +437,8 @@ open class Mangadex(override val lang: String, private val internalLang: String,
private const val NO_R18 = 0
private const val ALL = 1
private const val ONLY_R18 = 2
private const val SHOW_R18_PREF_Title = "Default R18 Setting"
private const val SHOW_R18_PREF = "showR18Default"
private const val URL = "/api/3640f3fb/"
private const val BASE_CHAPTER = "/chapter/"