Optimize imports, disallow wildcard imports because of klint, run linter
This commit is contained in:
parent
f18891a07e
commit
23ac3d18e5
@ -43,7 +43,6 @@ class CategoryPutResolver : DefaultPutResolver<Category>() {
|
|||||||
put(COL_FLAGS, obj.flags)
|
put(COL_FLAGS, obj.flags)
|
||||||
val orderString = obj.mangaOrder.joinToString("/")
|
val orderString = obj.mangaOrder.joinToString("/")
|
||||||
put(COL_MANGA_ORDER, orderString)
|
put(COL_MANGA_ORDER, orderString)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,4 @@ class MangaUrlPutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_URL, manga.url)
|
put(MangaTable.COL_URL, manga.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ object CategoryTable {
|
|||||||
$COL_MANGA_ORDER TEXT NOT NULL
|
$COL_MANGA_ORDER TEXT NOT NULL
|
||||||
)"""
|
)"""
|
||||||
|
|
||||||
|
|
||||||
val addMangaOrder: String
|
val addMangaOrder: String
|
||||||
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT"
|
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT"
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,11 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
import exh.metadata.metadata.base.insertFlatMetadata
|
import exh.metadata.metadata.base.insertFlatMetadata
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LEWD!
|
* LEWD!
|
||||||
|
@ -3,7 +3,12 @@ package eu.kanade.tachiyomi.source.online.all
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
import com.github.salomonbrys.kotson.*
|
import com.github.salomonbrys.kotson.array
|
||||||
|
import com.github.salomonbrys.kotson.get
|
||||||
|
import com.github.salomonbrys.kotson.int
|
||||||
|
import com.github.salomonbrys.kotson.obj
|
||||||
|
import com.github.salomonbrys.kotson.set
|
||||||
|
import com.github.salomonbrys.kotson.string
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
@ -13,7 +18,12 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
|
|||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace
|
import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -36,23 +46,30 @@ import exh.util.UriFilter
|
|||||||
import exh.util.UriGroup
|
import exh.util.UriGroup
|
||||||
import exh.util.ignore
|
import exh.util.ignore
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
|
import java.net.URLEncoder
|
||||||
|
import java.util.ArrayList
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.*
|
import okhttp3.CacheControl
|
||||||
|
import okhttp3.CookieJar
|
||||||
|
import okhttp3.Headers
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import org.jsoup.nodes.TextNode
|
import org.jsoup.nodes.TextNode
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.URLEncoder
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
// TODO Consider gallery updating when doing tabbed browsing
|
// TODO Consider gallery updating when doing tabbed browsing
|
||||||
class EHentai(override val id: Long,
|
class EHentai(
|
||||||
|
override val id: Long,
|
||||||
val exh: Boolean,
|
val exh: Boolean,
|
||||||
val context: Context) : HttpSource(), LewdSource<EHentaiSearchMetadata, Document>, UrlImportableSource {
|
val context: Context
|
||||||
|
) : HttpSource(), LewdSource<EHentaiSearchMetadata, Document>, UrlImportableSource {
|
||||||
override val metaClass = EHentaiSearchMetadata::class
|
override val metaClass = EHentaiSearchMetadata::class
|
||||||
|
|
||||||
val schema: String
|
val schema: String
|
||||||
@ -111,8 +128,8 @@ class EHentai(override val id: Long,
|
|||||||
val parsedLocation = doc.location().toHttpUrlOrNull()
|
val parsedLocation = doc.location().toHttpUrlOrNull()
|
||||||
|
|
||||||
// Add to page if required
|
// Add to page if required
|
||||||
val hasNextPage = if (parsedLocation == null
|
val hasNextPage = if (parsedLocation == null ||
|
||||||
|| !parsedLocation.queryParameterNames.contains(REVERSE_PARAM)) {
|
!parsedLocation.queryParameterNames.contains(REVERSE_PARAM)) {
|
||||||
select("a[onclick=return false]").last()?.let {
|
select("a[onclick=return false]").last()?.let {
|
||||||
it.text() == ">"
|
it.text() == ">"
|
||||||
} ?: false
|
} ?: false
|
||||||
@ -212,8 +229,11 @@ class EHentai(override val id: Long,
|
|||||||
}
|
}
|
||||||
}!!
|
}!!
|
||||||
|
|
||||||
private fun fetchChapterPage(chapter: SChapter, np: String,
|
private fun fetchChapterPage(
|
||||||
pastUrls: List<String> = emptyList()): Observable<List<String>> {
|
chapter: SChapter,
|
||||||
|
np: String,
|
||||||
|
pastUrls: List<String> = emptyList()
|
||||||
|
): Observable<List<String>> {
|
||||||
val urls = ArrayList(pastUrls)
|
val urls = ArrayList(pastUrls)
|
||||||
return chapterPageCall(np).flatMap {
|
return chapterPageCall(np).flatMap {
|
||||||
val jsoup = it.asJsoup()
|
val jsoup = it.asJsoup()
|
||||||
@ -407,8 +427,8 @@ class EHentai(override val id: Long,
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastUpdateCheck = System.currentTimeMillis()
|
lastUpdateCheck = System.currentTimeMillis()
|
||||||
if (datePosted != null
|
if (datePosted != null &&
|
||||||
&& lastUpdateCheck - datePosted!! > EHentaiUpdateWorkerConstants.GALLERY_AGE_TIME) {
|
lastUpdateCheck - datePosted!! > EHentaiUpdateWorkerConstants.GALLERY_AGE_TIME) {
|
||||||
aged = true
|
aged = true
|
||||||
XLog.d("aged %s - too old", title)
|
XLog.d("aged %s - too old", title)
|
||||||
}
|
}
|
||||||
@ -713,7 +733,6 @@ class EHentai(override val id: Long,
|
|||||||
return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/"
|
return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val QUERY_PREFIX = "?f_apply=Apply+Filter"
|
private const val QUERY_PREFIX = "?f_apply=Apply+Filter"
|
||||||
private const val TR_SUFFIX = "TR"
|
private const val TR_SUFFIX = "TR"
|
||||||
@ -738,6 +757,5 @@ class EHentai(override val id: Long,
|
|||||||
fun buildCookies(cookies: Map<String, String>) = cookies.entries.joinToString(separator = "; ") {
|
fun buildCookies(cookies: Map<String, String>) = cookies.entries.joinToString(separator = "; ") {
|
||||||
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
|
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,11 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -24,6 +28,8 @@ import exh.metadata.metadata.HitomiSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
|||||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
@ -32,8 +38,6 @@ import rx.Observable
|
|||||||
import rx.Single
|
import rx.Single
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Man, I hate this source :(
|
* Man, I hate this source :(
|
||||||
@ -61,8 +65,8 @@ class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImpo
|
|||||||
private var tagIndexVersionCacheTime: Long = 0
|
private var tagIndexVersionCacheTime: Long = 0
|
||||||
private fun tagIndexVersion(): Single<Long> {
|
private fun tagIndexVersion(): Single<Long> {
|
||||||
val sCachedTagIndexVersion = cachedTagIndexVersion
|
val sCachedTagIndexVersion = cachedTagIndexVersion
|
||||||
return if (sCachedTagIndexVersion == null
|
return if (sCachedTagIndexVersion == null ||
|
||||||
|| tagIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) {
|
tagIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) {
|
||||||
HitomiNozomi.getIndexVersion(client, "tagindex").subscribeOn(Schedulers.io()).doOnNext {
|
HitomiNozomi.getIndexVersion(client, "tagindex").subscribeOn(Schedulers.io()).doOnNext {
|
||||||
cachedTagIndexVersion = it
|
cachedTagIndexVersion = it
|
||||||
tagIndexVersionCacheTime = System.currentTimeMillis()
|
tagIndexVersionCacheTime = System.currentTimeMillis()
|
||||||
@ -76,8 +80,8 @@ class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImpo
|
|||||||
private var galleryIndexVersionCacheTime: Long = 0
|
private var galleryIndexVersionCacheTime: Long = 0
|
||||||
private fun galleryIndexVersion(): Single<Long> {
|
private fun galleryIndexVersion(): Single<Long> {
|
||||||
val sCachedGalleryIndexVersion = cachedGalleryIndexVersion
|
val sCachedGalleryIndexVersion = cachedGalleryIndexVersion
|
||||||
return if (sCachedGalleryIndexVersion == null
|
return if (sCachedGalleryIndexVersion == null ||
|
||||||
|| galleryIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) {
|
galleryIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) {
|
||||||
HitomiNozomi.getIndexVersion(client, "galleriesindex").subscribeOn(Schedulers.io()).doOnNext {
|
HitomiNozomi.getIndexVersion(client, "galleriesindex").subscribeOn(Schedulers.io()).doOnNext {
|
||||||
cachedGalleryIndexVersion = it
|
cachedGalleryIndexVersion = it
|
||||||
galleryIndexVersionCacheTime = System.currentTimeMillis()
|
galleryIndexVersionCacheTime = System.currentTimeMillis()
|
||||||
@ -307,7 +311,6 @@ class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImpo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable with the updated details for a manga. Normally it's not needed to
|
* Returns an observable with the updated details for a manga. Normally it's not needed to
|
||||||
* override this method.
|
* override this method.
|
||||||
@ -423,5 +426,4 @@ class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImpo
|
|||||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss'-05'", Locale.US)
|
SimpleDateFormat("yyyy-MM-dd HH:mm:ss'-05'", Locale.US)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,22 @@ package eu.kanade.tachiyomi.source.online.all
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.github.salomonbrys.kotson.*
|
import com.github.salomonbrys.kotson.get
|
||||||
|
import com.github.salomonbrys.kotson.nullArray
|
||||||
|
import com.github.salomonbrys.kotson.nullLong
|
||||||
|
import com.github.salomonbrys.kotson.nullObj
|
||||||
|
import com.github.salomonbrys.kotson.nullString
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -305,7 +314,6 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
|||||||
Pair("Chinese", " chinese")
|
Pair("Chinese", " chinese")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
val jsonParser by lazy {
|
val jsonParser by lazy {
|
||||||
JsonParser()
|
JsonParser()
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,12 @@ package eu.kanade.tachiyomi.source.online.all
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -17,14 +22,15 @@ import exh.metadata.metadata.base.RaisedTag
|
|||||||
import exh.util.UriFilter
|
import exh.util.UriFilter
|
||||||
import exh.util.UriGroup
|
import exh.util.UriGroup
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import org.jsoup.nodes.TextNode
|
import org.jsoup.nodes.TextNode
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
// TODO Transform into delegated source
|
// TODO Transform into delegated source
|
||||||
class PervEden(override val id: Long, val pvLang: PervEdenLang) : ParsedHttpSource(),
|
class PervEden(override val id: Long, val pvLang: PervEdenLang) : ParsedHttpSource(),
|
||||||
|
@ -2,10 +2,14 @@ package eu.kanade.tachiyomi.source.online.english
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.kizitonwose.time.hours
|
import com.kizitonwose.time.hours
|
||||||
import hu.akarnokd.rxjava.interop.RxJavaInterop
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -17,13 +21,18 @@ import exh.util.CachedField
|
|||||||
import exh.util.NakedTrie
|
import exh.util.NakedTrie
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
|
import hu.akarnokd.rxjava.interop.RxJavaInterop
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.rx2.asSingle
|
import kotlinx.coroutines.rx2.asSingle
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.*
|
import okhttp3.Headers
|
||||||
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
|
@ -4,12 +4,16 @@ import android.net.Uri
|
|||||||
import com.github.salomonbrys.kotson.array
|
import com.github.salomonbrys.kotson.array
|
||||||
import com.github.salomonbrys.kotson.string
|
import com.github.salomonbrys.kotson.string
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import hu.akarnokd.rxjava.interop.RxJavaInterop
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.asObservable
|
import eu.kanade.tachiyomi.network.asObservable
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
@ -23,7 +27,9 @@ import exh.search.Text
|
|||||||
import exh.util.await
|
import exh.util.await
|
||||||
import exh.util.dropBlank
|
import exh.util.dropBlank
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
|
import hu.akarnokd.rxjava.interop.RxJavaInterop
|
||||||
import info.debatty.java.stringsimilarity.Levenshtein
|
import info.debatty.java.stringsimilarity.Levenshtein
|
||||||
|
import kotlin.math.ceil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
@ -36,7 +42,6 @@ import org.jsoup.nodes.Document
|
|||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import kotlin.math.ceil
|
|
||||||
|
|
||||||
class HBrowse : HttpSource(), LewdSource<HBrowseSearchMetadata, Document>, UrlImportableSource {
|
class HBrowse : HttpSource(), LewdSource<HBrowseSearchMetadata, Document>, UrlImportableSource {
|
||||||
/**
|
/**
|
||||||
@ -182,7 +187,6 @@ class HBrowse : HttpSource(), LewdSource<HBrowseSearchMetadata, Document>, UrlIm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
"/result"
|
"/result"
|
||||||
} else {
|
} else {
|
||||||
"/search"
|
"/search"
|
||||||
|
@ -4,29 +4,25 @@ import android.net.Uri
|
|||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
import eu.kanade.tachiyomi.util.system.asJsoup
|
import eu.kanade.tachiyomi.util.system.asJsoup
|
||||||
import exh.metadata.metadata.TsuminoSearchMetadata
|
import exh.metadata.metadata.TsuminoSearchMetadata
|
||||||
import exh.metadata.metadata.TsuminoSearchMetadata.Companion.BASE_URL
|
|
||||||
import exh.metadata.metadata.TsuminoSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
import exh.metadata.metadata.TsuminoSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
import exh.source.DelegatedHttpSource
|
import exh.source.DelegatedHttpSource
|
||||||
import exh.util.dropBlank
|
|
||||||
import exh.util.trimAll
|
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class Tsumino(delegate: HttpSource) : DelegatedHttpSource(delegate),
|
class Tsumino(delegate: HttpSource) : DelegatedHttpSource(delegate),
|
||||||
LewdSource<TsuminoSearchMetadata, Document>, UrlImportableSource {
|
LewdSource<TsuminoSearchMetadata, Document>, UrlImportableSource {
|
||||||
override val metaClass = TsuminoSearchMetadata::class;
|
override val metaClass = TsuminoSearchMetadata::class
|
||||||
override val lang = "en"
|
override val lang = "en"
|
||||||
|
|
||||||
// Support direct URL importing
|
// Support direct URL importing
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.ui.browse.source.filter
|
package eu.kanade.tachiyomi.ui.browse.source.filter
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
|
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
@ -5,21 +5,24 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
|||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
|
import eu.kanade.tachiyomi.ui.category.CategoryAdapter
|
||||||
import exh.isLewdSource
|
import exh.isLewdSource
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable
|
import exh.metadata.sql.tables.SearchMetadataTable
|
||||||
import exh.search.SearchEngine
|
import exh.search.SearchEngine
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import exh.util.cancellable
|
import exh.util.cancellable
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.flow.asFlow
|
import kotlinx.coroutines.flow.asFlow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.toList
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
|
||||||
import eu.kanade.tachiyomi.ui.category.CategoryAdapter
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter storing a list of manga in a certain category.
|
* Adapter storing a list of manga in a certain category.
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package eu.kanade.tachiyomi.ui.library
|
package eu.kanade.tachiyomi.ui.library
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||||
|
|
||||||
@ -26,7 +26,6 @@ abstract class LibraryHolder(
|
|||||||
*/
|
*/
|
||||||
abstract fun onSetValues(item: LibraryItem)
|
abstract fun onSetValues(item: LibraryItem)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an item is released.
|
* Called when an item is released.
|
||||||
*
|
*
|
||||||
@ -36,5 +35,4 @@ abstract class LibraryHolder(
|
|||||||
super.onItemReleased(position)
|
super.onItemReleased(position)
|
||||||
(adapter as? LibraryCategoryAdapter)?.onItemReleaseListener?.onItemReleased(position)
|
(adapter as? LibraryCategoryAdapter)?.onItemReleaseListener?.onItemReleased(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -235,4 +235,3 @@ class MangaInfoPresenter(
|
|||||||
return toInsert
|
return toInsert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,17 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.util.preference.*
|
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||||
|
import eu.kanade.tachiyomi.util.preference.entriesRes
|
||||||
|
import eu.kanade.tachiyomi.util.preference.intListPreference
|
||||||
|
import eu.kanade.tachiyomi.util.preference.listPreference
|
||||||
|
import eu.kanade.tachiyomi.util.preference.multiSelectListPreference
|
||||||
|
import eu.kanade.tachiyomi.util.preference.onChange
|
||||||
|
import eu.kanade.tachiyomi.util.preference.onClick
|
||||||
|
import eu.kanade.tachiyomi.util.preference.preference
|
||||||
|
import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||||
|
import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||||
|
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
@ -34,6 +44,7 @@ import exh.ui.login.LoginController
|
|||||||
import exh.util.await
|
import exh.util.await
|
||||||
import exh.util.trans
|
import exh.util.trans
|
||||||
import humanize.Humanize
|
import humanize.Humanize
|
||||||
|
import java.util.Date
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -41,7 +52,6 @@ import kotlinx.coroutines.withContext
|
|||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EH Settings fragment
|
* EH Settings fragment
|
||||||
|
@ -53,7 +53,7 @@ private val lewdDelegatedSourceIds = SourceManager.DELEGATED_SOURCES.filter {
|
|||||||
}.map { it.value.sourceId }.sorted()
|
}.map { it.value.sourceId }.sorted()
|
||||||
|
|
||||||
// This method MUST be fast!
|
// This method MUST be fast!
|
||||||
fun isLewdSource(source: Long) = source in 6900..6999
|
fun isLewdSource(source: Long) = source in 6900..6999 ||
|
||||||
|| lewdDelegatedSourceIds.binarySearch(source) >= 0
|
lewdDelegatedSourceIds.binarySearch(source) >= 0
|
||||||
|
|
||||||
fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID
|
fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID
|
||||||
|
@ -2,6 +2,8 @@ package exh
|
|||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
|
||||||
data class EXHSavedSearch(val name: String,
|
data class EXHSavedSearch(
|
||||||
|
val name: String,
|
||||||
val query: String,
|
val query: String,
|
||||||
val filterList: FilterList)
|
val filterList: FilterList
|
||||||
|
)
|
||||||
|
@ -16,10 +16,12 @@ class GalleryAdder {
|
|||||||
|
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
|
|
||||||
fun addGallery(url: String,
|
fun addGallery(
|
||||||
|
url: String,
|
||||||
fav: Boolean = false,
|
fav: Boolean = false,
|
||||||
forceSource: UrlImportableSource? = null,
|
forceSource: UrlImportableSource? = null,
|
||||||
throttleFunc: () -> Unit = {}): GalleryAddEvent {
|
throttleFunc: () -> Unit = {}
|
||||||
|
): GalleryAddEvent {
|
||||||
XLog.d("Importing gallery (url: %s, fav: %s, forceSource: %s)...", url, fav, forceSource)
|
XLog.d("Importing gallery (url: %s, fav: %s, forceSource: %s)...", url, fav, forceSource)
|
||||||
try {
|
try {
|
||||||
val uri = Uri.parse(url)
|
val uri = Uri.parse(url)
|
||||||
@ -120,8 +122,10 @@ sealed class GalleryAddEvent {
|
|||||||
abstract val galleryUrl: String
|
abstract val galleryUrl: String
|
||||||
open val galleryTitle: String? = null
|
open val galleryTitle: String? = null
|
||||||
|
|
||||||
class Success(override val galleryUrl: String,
|
class Success(
|
||||||
val manga: Manga): GalleryAddEvent() {
|
override val galleryUrl: String,
|
||||||
|
val manga: Manga
|
||||||
|
) : GalleryAddEvent() {
|
||||||
override val galleryTitle = manga.title
|
override val galleryTitle = manga.title
|
||||||
override val logMessage = "Added gallery: $galleryTitle"
|
override val logMessage = "Added gallery: $galleryTitle"
|
||||||
}
|
}
|
||||||
@ -131,8 +135,10 @@ sealed class GalleryAddEvent {
|
|||||||
override val logMessage = "Unknown gallery type for gallery: $galleryUrl"
|
override val logMessage = "Unknown gallery type for gallery: $galleryUrl"
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Error(override val galleryUrl: String,
|
open class Error(
|
||||||
override val logMessage: String): Fail()
|
override val galleryUrl: String,
|
||||||
|
override val logMessage: String
|
||||||
|
) : Fail()
|
||||||
|
|
||||||
class NotFound(galleryUrl: String) :
|
class NotFound(galleryUrl: String) :
|
||||||
Error(galleryUrl, "Gallery does not exist: $galleryUrl")
|
Error(galleryUrl, "Gallery does not exist: $galleryUrl")
|
||||||
|
@ -9,20 +9,19 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.util.system.jobScheduler
|
import eu.kanade.tachiyomi.util.system.jobScheduler
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
|
||||||
import exh.EXHMigrations
|
import exh.EXHMigrations
|
||||||
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.eh.EHentaiUpdateWorker
|
import exh.eh.EHentaiUpdateWorker
|
||||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
import exh.metadata.metadata.base.insertFlatMetadata
|
import exh.metadata.metadata.base.insertFlatMetadata
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import exh.util.cancellable
|
import exh.util.cancellable
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.flow.asFlow
|
import kotlinx.coroutines.flow.asFlow
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.toList
|
import kotlinx.coroutines.flow.toList
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
object DebugFunctions {
|
object DebugFunctions {
|
||||||
val app: Application by injectLazy()
|
val app: Application by injectLazy()
|
||||||
|
@ -8,8 +8,12 @@ import android.widget.HorizontalScrollView
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import eu.kanade.tachiyomi.ui.setting.*
|
import eu.kanade.tachiyomi.ui.setting.SettingsController
|
||||||
import eu.kanade.tachiyomi.util.preference.*
|
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||||
|
import eu.kanade.tachiyomi.util.preference.onClick
|
||||||
|
import eu.kanade.tachiyomi.util.preference.preference
|
||||||
|
import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||||
|
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||||
import kotlin.reflect.KVisibility
|
import kotlin.reflect.KVisibility
|
||||||
import kotlin.reflect.full.declaredFunctions
|
import kotlin.reflect.full.declaredFunctions
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package exh.eh
|
package exh.eh
|
||||||
|
|
||||||
class EHentaiThrottleManager(private val max: Int = THROTTLE_MAX,
|
class EHentaiThrottleManager(
|
||||||
private val inc: Int = THROTTLE_INC) {
|
private val max: Int = THROTTLE_MAX,
|
||||||
|
private val inc: Int = THROTTLE_INC
|
||||||
|
) {
|
||||||
private var lastThrottleTime: Long = 0
|
private var lastThrottleTime: Long = 0
|
||||||
var throttleTime: Long = 0
|
var throttleTime: Long = 0
|
||||||
private set
|
private set
|
||||||
|
@ -8,10 +8,10 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
|||||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
||||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
|
import java.io.File
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
data class ChapterChain(val manga: Manga, val chapters: List<Chapter>)
|
data class ChapterChain(val manga: Manga, val chapters: List<Chapter>)
|
||||||
|
|
||||||
@ -75,9 +75,9 @@ class EHentaiUpdateHelper(context: Context) {
|
|||||||
|
|
||||||
chain.chapters.map { chapter ->
|
chain.chapters.map { chapter ->
|
||||||
// Convert old style chapters to new style chapters if possible
|
// Convert old style chapters to new style chapters if possible
|
||||||
if(chapter.date_upload <= 0
|
if (chapter.date_upload <= 0 &&
|
||||||
&& meta?.datePosted != null
|
meta?.datePosted != null &&
|
||||||
&& meta?.title != null) {
|
meta?.title != null) {
|
||||||
chapter.name = meta!!.title!!
|
chapter.name = meta!!.title!!
|
||||||
chapter.date_upload = meta!!.datePosted!!
|
chapter.date_upload = meta!!.datePosted!!
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||||
import eu.kanade.tachiyomi.util.system.jobScheduler
|
|
||||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||||
|
import eu.kanade.tachiyomi.util.system.jobScheduler
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.debug.DebugToggles
|
import exh.debug.DebugToggles
|
||||||
@ -31,15 +31,20 @@ import exh.metadata.metadata.base.getFlatMetadataForManga
|
|||||||
import exh.metadata.metadata.base.insertFlatMetadata
|
import exh.metadata.metadata.base.insertFlatMetadata
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import exh.util.cancellable
|
import exh.util.cancellable
|
||||||
import kotlinx.coroutines.*
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
import kotlinx.coroutines.flow.asFlow
|
import kotlinx.coroutines.flow.asFlow
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.toList
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
class EHentaiUpdateWorker : JobService(), CoroutineScope {
|
class EHentaiUpdateWorker : JobService(), CoroutineScope {
|
||||||
@ -215,8 +220,8 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope {
|
|||||||
val (acceptedRoot, discardedRoots, hasNew) =
|
val (acceptedRoot, discardedRoots, hasNew) =
|
||||||
updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters).await()
|
updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters).await()
|
||||||
|
|
||||||
if((new.isNotEmpty() && manga.id == acceptedRoot.manga.id)
|
if ((new.isNotEmpty() && manga.id == acceptedRoot.manga.id) ||
|
||||||
|| (hasNew && updatedManga.none { it.id == acceptedRoot.manga.id })) {
|
(hasNew && updatedManga.none { it.id == acceptedRoot.manga.id })) {
|
||||||
updatedManga += acceptedRoot.manga
|
updatedManga += acceptedRoot.manga
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,9 +295,11 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope {
|
|||||||
else JOB_ID_UPDATE_BACKGROUND, componentName())
|
else JOB_ID_UPDATE_BACKGROUND, componentName())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.periodicBackgroundJobInfo(period: Long,
|
private fun Context.periodicBackgroundJobInfo(
|
||||||
|
period: Long,
|
||||||
requireCharging: Boolean,
|
requireCharging: Boolean,
|
||||||
requireUnmetered: Boolean): JobInfo {
|
requireUnmetered: Boolean
|
||||||
|
): JobInfo {
|
||||||
return baseBackgroundJobInfo(false)
|
return baseBackgroundJobInfo(false)
|
||||||
.setPeriodic(period)
|
.setPeriodic(period)
|
||||||
.setPersisted(true)
|
.setPersisted(true)
|
||||||
|
@ -3,9 +3,6 @@ package exh.eh
|
|||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import androidx.core.util.AtomicFile
|
import androidx.core.util.AtomicFile
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
@ -13,6 +10,18 @@ import java.io.InputStream
|
|||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.NonCancellable
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In memory Int -> Obj lookup table implementation that
|
* In memory Int -> Obj lookup table implementation that
|
||||||
|
@ -5,7 +5,7 @@ import io.realm.RealmObject
|
|||||||
import io.realm.annotations.Index
|
import io.realm.annotations.Index
|
||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
import io.realm.annotations.RealmClass
|
import io.realm.annotations.RealmClass
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
@RealmClass
|
@RealmClass
|
||||||
open class FavoriteEntry : RealmObject() {
|
open class FavoriteEntry : RealmObject() {
|
||||||
|
@ -17,18 +17,21 @@ import eu.kanade.tachiyomi.util.lang.launchUI
|
|||||||
import eu.kanade.tachiyomi.util.system.powerManager
|
import eu.kanade.tachiyomi.util.system.powerManager
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.system.wifiManager
|
import eu.kanade.tachiyomi.util.system.wifiManager
|
||||||
import exh.*
|
import exh.EH_SOURCE_ID
|
||||||
|
import exh.EXH_SOURCE_ID
|
||||||
|
import exh.GalleryAddEvent
|
||||||
|
import exh.GalleryAdder
|
||||||
import exh.eh.EHentaiThrottleManager
|
import exh.eh.EHentaiThrottleManager
|
||||||
import exh.eh.EHentaiUpdateWorker
|
import exh.eh.EHentaiUpdateWorker
|
||||||
import exh.util.ignore
|
import exh.util.ignore
|
||||||
import exh.util.trans
|
import exh.util.trans
|
||||||
|
import kotlin.concurrent.thread
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import rx.subjects.BehaviorSubject
|
import rx.subjects.BehaviorSubject
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
class FavoritesSyncHelper(val context: Context) {
|
class FavoritesSyncHelper(val context: Context) {
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
@ -385,8 +388,8 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun needWarnThrottle()
|
fun needWarnThrottle() =
|
||||||
= throttleManager.throttleTime >= THROTTLE_WARN
|
throttleManager.throttleTime >= THROTTLE_WARN
|
||||||
|
|
||||||
class IgnoredException : RuntimeException()
|
class IgnoredException : RuntimeException()
|
||||||
|
|
||||||
@ -399,8 +402,10 @@ sealed class FavoritesSyncStatus(val message: String) {
|
|||||||
class Error(message: String) : FavoritesSyncStatus(message)
|
class Error(message: String) : FavoritesSyncStatus(message)
|
||||||
class Idle : FavoritesSyncStatus("Waiting for sync to start")
|
class Idle : FavoritesSyncStatus("Waiting for sync to start")
|
||||||
sealed class BadLibraryState(message: String) : FavoritesSyncStatus(message) {
|
sealed class BadLibraryState(message: String) : FavoritesSyncStatus(message) {
|
||||||
class MangaInMultipleCategories(val manga: Manga,
|
class MangaInMultipleCategories(
|
||||||
val categories: List<Category>):
|
val manga: Manga,
|
||||||
|
val categories: List<Category>
|
||||||
|
) :
|
||||||
BadLibraryState("The gallery: ${manga.title} is in more than one category (${categories.joinToString { it.name }})!")
|
BadLibraryState("The gallery: ${manga.title} is in more than one category (${categories.joinToString { it.name }})!")
|
||||||
}
|
}
|
||||||
class Initializing : FavoritesSyncStatus("Initializing sync")
|
class Initializing : FavoritesSyncStatus("Initializing sync")
|
||||||
|
@ -20,8 +20,8 @@ class LocalFavoritesStorage {
|
|||||||
|
|
||||||
fun getRealm() = Realm.getInstance(realmConfig)
|
fun getRealm() = Realm.getInstance(realmConfig)
|
||||||
|
|
||||||
fun getChangedDbEntries(realm: Realm)
|
fun getChangedDbEntries(realm: Realm) =
|
||||||
= getChangedEntries(realm,
|
getChangedEntries(realm,
|
||||||
parseToFavoriteEntries(
|
parseToFavoriteEntries(
|
||||||
loadDbCategories(
|
loadDbCategories(
|
||||||
db.getFavoriteMangas()
|
db.getFavoriteMangas()
|
||||||
@ -31,8 +31,8 @@ class LocalFavoritesStorage {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getChangedRemoteEntries(realm: Realm, entries: List<EHentai.ParsedManga>)
|
fun getChangedRemoteEntries(realm: Realm, entries: List<EHentai.ParsedManga>) =
|
||||||
= getChangedEntries(realm,
|
getChangedEntries(realm,
|
||||||
parseToFavoriteEntries(
|
parseToFavoriteEntries(
|
||||||
entries.asSequence().map {
|
entries.asSequence().map {
|
||||||
Pair(it.fav, it.manga.apply {
|
Pair(it.fav, it.manga.apply {
|
||||||
@ -80,18 +80,18 @@ class LocalFavoritesStorage {
|
|||||||
return ChangeSet(added, removed)
|
return ChangeSet(added, removed)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Realm.queryRealmForEntry(entry: FavoriteEntry)
|
private fun Realm.queryRealmForEntry(entry: FavoriteEntry) =
|
||||||
= where(FavoriteEntry::class.java)
|
where(FavoriteEntry::class.java)
|
||||||
.equalTo(FavoriteEntry::gid.name, entry.gid)
|
.equalTo(FavoriteEntry::gid.name, entry.gid)
|
||||||
.equalTo(FavoriteEntry::token.name, entry.token)
|
.equalTo(FavoriteEntry::token.name, entry.token)
|
||||||
.equalTo(FavoriteEntry::category.name, entry.category)
|
.equalTo(FavoriteEntry::category.name, entry.category)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
|
|
||||||
private fun queryListForEntry(list: List<FavoriteEntry>, entry: FavoriteEntry)
|
private fun queryListForEntry(list: List<FavoriteEntry>, entry: FavoriteEntry) =
|
||||||
= list.find {
|
list.find {
|
||||||
it.gid == entry.gid
|
it.gid == entry.gid &&
|
||||||
&& it.token == entry.token
|
it.token == entry.token &&
|
||||||
&& it.category == entry.category
|
it.category == entry.category
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadDbCategories(manga: Sequence<Manga>): Sequence<Pair<Int, Manga>> {
|
private fun loadDbCategories(manga: Sequence<Manga>): Sequence<Pair<Int, Manga>> {
|
||||||
@ -105,8 +105,8 @@ class LocalFavoritesStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseToFavoriteEntries(manga: Sequence<Pair<Int, Manga>>)
|
private fun parseToFavoriteEntries(manga: Sequence<Pair<Int, Manga>>) =
|
||||||
= manga.filter {
|
manga.filter {
|
||||||
validateDbManga(it.second)
|
validateDbManga(it.second)
|
||||||
}.mapNotNull {
|
}.mapNotNull {
|
||||||
FavoriteEntry().apply {
|
FavoriteEntry().apply {
|
||||||
@ -120,13 +120,15 @@ class LocalFavoritesStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validateDbManga(manga: Manga)
|
private fun validateDbManga(manga: Manga) =
|
||||||
= manga.favorite && (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID)
|
manga.favorite && (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MAX_CATEGORIES = 9
|
const val MAX_CATEGORIES = 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ChangeSet(val added: List<FavoriteEntry>,
|
data class ChangeSet(
|
||||||
val removed: List<FavoriteEntry>)
|
val added: List<FavoriteEntry>,
|
||||||
|
val removed: List<FavoriteEntry>
|
||||||
|
)
|
||||||
|
@ -4,28 +4,32 @@ import eu.kanade.tachiyomi.network.GET
|
|||||||
import eu.kanade.tachiyomi.network.asObservable
|
import eu.kanade.tachiyomi.network.asObservable
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import exh.metadata.metadata.HitomiSearchMetadata.Companion.LTN_BASE_URL
|
import exh.metadata.metadata.HitomiSearchMetadata.Companion.LTN_BASE_URL
|
||||||
|
import java.security.MessageDigest
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.vepta.vdm.ByteCursor
|
import org.vepta.vdm.ByteCursor
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
import java.security.MessageDigest
|
|
||||||
|
|
||||||
private typealias HashedTerm = ByteArray
|
private typealias HashedTerm = ByteArray
|
||||||
|
|
||||||
private data class DataPair(val offset: Long, val length: Int)
|
private data class DataPair(val offset: Long, val length: Int)
|
||||||
private data class Node(val keys: List<ByteArray>,
|
private data class Node(
|
||||||
|
val keys: List<ByteArray>,
|
||||||
val datas: List<DataPair>,
|
val datas: List<DataPair>,
|
||||||
val subnodeAddresses: List<Long>)
|
val subnodeAddresses: List<Long>
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kotlin port of the hitomi.la search algorithm
|
* Kotlin port of the hitomi.la search algorithm
|
||||||
* @author NerdNumber9
|
* @author NerdNumber9
|
||||||
*/
|
*/
|
||||||
class HitomiNozomi(private val client: OkHttpClient,
|
class HitomiNozomi(
|
||||||
|
private val client: OkHttpClient,
|
||||||
private val tagIndexVersion: Long,
|
private val tagIndexVersion: Long,
|
||||||
private val galleriesIndexVersion: Long) {
|
private val galleriesIndexVersion: Long
|
||||||
|
) {
|
||||||
fun getGalleryIdsForQuery(query: String): Single<List<Int>> {
|
fun getGalleryIdsForQuery(query: String): Single<List<Int>> {
|
||||||
val replacedQuery = query.replace('_', ' ')
|
val replacedQuery = query.replace('_', ' ')
|
||||||
|
|
||||||
@ -90,9 +94,9 @@ class HitomiNozomi(private val client: OkHttpClient,
|
|||||||
|
|
||||||
val expectedLength = numberOfGalleryIds * 4 + 4
|
val expectedLength = numberOfGalleryIds * 4 + 4
|
||||||
|
|
||||||
if(numberOfGalleryIds > 10000000
|
if (numberOfGalleryIds > 10000000 ||
|
||||||
|| numberOfGalleryIds <= 0
|
numberOfGalleryIds <= 0 ||
|
||||||
|| inbuf.size != expectedLength) {
|
inbuf.size != expectedLength) {
|
||||||
return@map emptyList<Int>()
|
return@map emptyList<Int>()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +238,6 @@ class HitomiNozomi(private val client: OkHttpClient,
|
|||||||
.build())
|
.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getIndexVersion(httpClient: OkHttpClient, name: String): Observable<Long> {
|
fun getIndexVersion(httpClient: OkHttpClient, name: String): Observable<Long> {
|
||||||
return httpClient.newCall(GET("$LTN_BASE_URL/$name/version?_=${System.currentTimeMillis()}"))
|
return httpClient.newCall(GET("$LTN_BASE_URL/$name/version?_=${System.currentTimeMillis()}"))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
|
@ -4,11 +4,11 @@ import android.content.Context
|
|||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
import com.ms_square.debugoverlay.DataObserver
|
import com.ms_square.debugoverlay.DataObserver
|
||||||
import com.ms_square.debugoverlay.OverlayModule
|
import com.ms_square.debugoverlay.OverlayModule
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package exh.metadata
|
package exh.metadata
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata utils
|
* Metadata utils
|
||||||
@ -35,7 +35,6 @@ fun parseHumanReadableByteCount(arg0: String): Double? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun String?.nullIfBlank(): String? = if (isNullOrBlank())
|
fun String?.nullIfBlank(): String? = if (isNullOrBlank())
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
|
@ -4,12 +4,14 @@ import android.net.Uri
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.*
|
import exh.metadata.EX_DATE_FORMAT
|
||||||
|
import exh.metadata.ONGOING_SUFFIX
|
||||||
|
import exh.metadata.humanReadableByteCount
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
|
import java.util.Date
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||||
var gId: String?
|
var gId: String?
|
||||||
@ -114,8 +116,8 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
const val EH_GENRE_NAMESPACE = "genre"
|
const val EH_GENRE_NAMESPACE = "genre"
|
||||||
private const val EH_ARTIST_NAMESPACE = "artist"
|
private const val EH_ARTIST_NAMESPACE = "artist"
|
||||||
|
|
||||||
private fun splitGalleryUrl(url: String)
|
private fun splitGalleryUrl(url: String) =
|
||||||
= url.let {
|
url.let {
|
||||||
// Only parse URL if is full URL
|
// Only parse URL if is full URL
|
||||||
val pathSegments = if (it.startsWith("http"))
|
val pathSegments = if (it.startsWith("http"))
|
||||||
Uri.parse(it).pathSegments
|
Uri.parse(it).pathSegments
|
||||||
@ -129,10 +131,10 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
fun galleryToken(url: String) =
|
fun galleryToken(url: String) =
|
||||||
splitGalleryUrl(url)[2]
|
splitGalleryUrl(url)[2]
|
||||||
|
|
||||||
fun normalizeUrl(url: String)
|
fun normalizeUrl(url: String) =
|
||||||
= idAndTokenToUrl(galleryId(url), galleryToken(url))
|
idAndTokenToUrl(galleryId(url), galleryToken(url))
|
||||||
|
|
||||||
fun idAndTokenToUrl(id: String, token: String)
|
fun idAndTokenToUrl(id: String, token: String) =
|
||||||
= "/g/$id/$token/?nw=always"
|
"/g/$id/$token/?nw=always"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,7 +34,6 @@ class EightMusesSearchMetadata : RaisedSearchMetadata() {
|
|||||||
manga.description = listOf(titleDesc.toString(), tagsDesc.toString())
|
manga.description = listOf(titleDesc.toString(), tagsDesc.toString())
|
||||||
.filter(String::isNotBlank)
|
.filter(String::isNotBlank)
|
||||||
.joinToString(separator = "\n")
|
.joinToString(separator = "\n")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -49,7 +49,7 @@ class HentaiCafeSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
const val BASE_URL = "https://hentai.cafe"
|
const val BASE_URL = "https://hentai.cafe"
|
||||||
|
|
||||||
fun hcIdFromUrl(url: String)
|
fun hcIdFromUrl(url: String) =
|
||||||
= url.split("/").last { it.isNotBlank() }
|
url.split("/").last { it.isNotBlank() }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.EX_DATE_FORMAT
|
import exh.metadata.EX_DATE_FORMAT
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
class HitomiSearchMetadata : RaisedSearchMetadata() {
|
class HitomiSearchMetadata : RaisedSearchMetadata() {
|
||||||
var url get() = hlId?.let { urlFromHlId(it) }
|
var url get() = hlId?.let { urlFromHlId(it) }
|
||||||
@ -92,10 +92,10 @@ class HitomiSearchMetadata: RaisedSearchMetadata() {
|
|||||||
const val LTN_BASE_URL = "https://ltn.hitomi.la"
|
const val LTN_BASE_URL = "https://ltn.hitomi.la"
|
||||||
const val BASE_URL = "https://hitomi.la"
|
const val BASE_URL = "https://hitomi.la"
|
||||||
|
|
||||||
fun hlIdFromUrl(url: String)
|
fun hlIdFromUrl(url: String) =
|
||||||
= url.split('/').last().split('-').last().substringBeforeLast('.')
|
url.split('/').last().split('-').last().substringBeforeLast('.')
|
||||||
|
|
||||||
fun urlFromHlId(id: String)
|
fun urlFromHlId(id: String) =
|
||||||
= "$BASE_URL/galleries/$id.html"
|
"$BASE_URL/galleries/$id.html"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,14 @@ package exh.metadata.metadata
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.*
|
import exh.metadata.EX_DATE_FORMAT
|
||||||
|
import exh.metadata.ONGOING_SUFFIX
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
|
import exh.metadata.nullIfBlank
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
|
import java.util.Date
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||||
var url get() = nhId?.let { BASE_URL + nhIdToPath(it) }
|
var url get() = nhId?.let { BASE_URL + nhIdToPath(it) }
|
||||||
@ -112,8 +114,8 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nhUrlToId(url: String)
|
fun nhUrlToId(url: String) =
|
||||||
= url.split("/").last { it.isNotBlank() }.toLong()
|
url.split("/").last { it.isNotBlank() }.toLong()
|
||||||
|
|
||||||
fun nhIdToPath(id: Long) = "/g/$id/"
|
fun nhIdToPath(id: Long) = "/g/$id/"
|
||||||
}
|
}
|
||||||
|
@ -80,15 +80,14 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() {
|
|||||||
.joinToString(separator = "\n")
|
.joinToString(separator = "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TITLE_TYPE_MAIN = 0
|
private const val TITLE_TYPE_MAIN = 0
|
||||||
private const val TITLE_TYPE_ALT = 1
|
private const val TITLE_TYPE_ALT = 1
|
||||||
|
|
||||||
const val TAG_TYPE_DEFAULT = 0
|
const val TAG_TYPE_DEFAULT = 0
|
||||||
|
|
||||||
private fun splitGalleryUrl(url: String)
|
private fun splitGalleryUrl(url: String) =
|
||||||
= url.let {
|
url.let {
|
||||||
Uri.parse(it).pathSegments.filterNot(String::isNullOrBlank)
|
Uri.parse(it).pathSegments.filterNot(String::isNullOrBlank)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +101,8 @@ enum class PervEdenLang(val id: Long) {
|
|||||||
it(PERV_EDEN_IT_SOURCE_ID);
|
it(PERV_EDEN_IT_SOURCE_ID);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun source(id: Long)
|
fun source(id: Long) =
|
||||||
= values().find { it.id == id }
|
values().find { it.id == id }
|
||||||
?: throw IllegalArgumentException("Unknown source ID: $id!")
|
?: throw IllegalArgumentException("Unknown source ID: $id!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.metadata.EX_DATE_FORMAT
|
import exh.metadata.EX_DATE_FORMAT
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
class TsuminoSearchMetadata : RaisedSearchMetadata() {
|
class TsuminoSearchMetadata : RaisedSearchMetadata() {
|
||||||
var tmId: Int? = null
|
var tmId: Int? = null
|
||||||
@ -76,8 +76,8 @@ class TsuminoSearchMetadata : RaisedSearchMetadata() {
|
|||||||
|
|
||||||
val BASE_URL = "https://www.tsumino.com"
|
val BASE_URL = "https://www.tsumino.com"
|
||||||
|
|
||||||
fun tmIdFromUrl(url: String)
|
fun tmIdFromUrl(url: String) =
|
||||||
= Uri.parse(url).lastPathSegment
|
Uri.parse(url).lastPathSegment
|
||||||
|
|
||||||
fun mangaUrlFromId(id: String) = "/Book/Info/$id"
|
fun mangaUrlFromId(id: String) = "/Book/Info/$id"
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|||||||
import exh.metadata.sql.models.SearchMetadata
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
import exh.metadata.sql.models.SearchTag
|
import exh.metadata.sql.models.SearchTag
|
||||||
import exh.metadata.sql.models.SearchTitle
|
import exh.metadata.sql.models.SearchTitle
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
data class FlatMetadata(
|
data class FlatMetadata(
|
||||||
val metadata: SearchMetadata,
|
val metadata: SearchMetadata,
|
||||||
@ -16,8 +16,8 @@ data class FlatMetadata(
|
|||||||
) {
|
) {
|
||||||
inline fun <reified T : RaisedSearchMetadata> raise(): T = raise(T::class)
|
inline fun <reified T : RaisedSearchMetadata> raise(): T = raise(T::class)
|
||||||
|
|
||||||
fun <T : RaisedSearchMetadata> raise(clazz: KClass<T>)
|
fun <T : RaisedSearchMetadata> raise(clazz: KClass<T>) =
|
||||||
= RaisedSearchMetadata.raiseFlattenGson
|
RaisedSearchMetadata.raiseFlattenGson
|
||||||
.fromJson(metadata.extra, clazz.java).apply {
|
.fromJson(metadata.extra, clazz.java).apply {
|
||||||
fillBaseFields(this@FlatMetadata)
|
fillBaseFields(this@FlatMetadata)
|
||||||
}
|
}
|
||||||
|
@ -35,12 +35,12 @@ abstract class RaisedSearchMetadata {
|
|||||||
|
|
||||||
abstract fun copyTo(manga: SManga)
|
abstract fun copyTo(manga: SManga)
|
||||||
|
|
||||||
fun tagsToGenreString()
|
fun tagsToGenreString() =
|
||||||
= tags.filter { it.type != TAG_TYPE_VIRTUAL }
|
tags.filter { it.type != TAG_TYPE_VIRTUAL }
|
||||||
.joinToString { (if (it.namespace != null) "${it.namespace}: " else "") + it.name }
|
.joinToString { (if (it.namespace != null) "${it.namespace}: " else "") + it.name }
|
||||||
|
|
||||||
fun tagsToDescription()
|
fun tagsToDescription() =
|
||||||
= StringBuilder("Tags:\n").apply {
|
StringBuilder("Tags:\n").apply {
|
||||||
// BiConsumer only available in Java 8, don't bother calling forEach directly on 'tags'
|
// BiConsumer only available in Java 8, don't bother calling forEach directly on 'tags'
|
||||||
val groupedTags = tags.filter { it.type != TAG_TYPE_VIRTUAL }.groupBy {
|
val groupedTags = tags.filter { it.type != TAG_TYPE_VIRTUAL }.groupBy {
|
||||||
it.namespace
|
it.namespace
|
||||||
@ -125,8 +125,8 @@ abstract class RaisedSearchMetadata {
|
|||||||
* @param property the metadata for the property.
|
* @param property the metadata for the property.
|
||||||
* @return the property value.
|
* @return the property value.
|
||||||
*/
|
*/
|
||||||
override fun getValue(thisRef: RaisedSearchMetadata, property: KProperty<*>)
|
override fun getValue(thisRef: RaisedSearchMetadata, property: KProperty<*>) =
|
||||||
= thisRef.getTitleOfType(type)
|
thisRef.getTitleOfType(type)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the property for the given object.
|
* Sets the value of the property for the given object.
|
||||||
@ -134,8 +134,8 @@ abstract class RaisedSearchMetadata {
|
|||||||
* @param property the metadata for the property.
|
* @param property the metadata for the property.
|
||||||
* @param value the value to set.
|
* @param value the value to set.
|
||||||
*/
|
*/
|
||||||
override fun setValue(thisRef: RaisedSearchMetadata, property: KProperty<*>, value: String?)
|
override fun setValue(thisRef: RaisedSearchMetadata, property: KProperty<*>, value: String?) =
|
||||||
= thisRef.replaceTitleOfType(type, value)
|
thisRef.replaceTitleOfType(type, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package exh.metadata.metadata.base
|
package exh.metadata.metadata.base
|
||||||
|
|
||||||
data class RaisedTag(val namespace: String?,
|
data class RaisedTag(
|
||||||
|
val namespace: String?,
|
||||||
val name: String,
|
val name: String,
|
||||||
val type: Int)
|
val type: Int
|
||||||
|
)
|
||||||
|
@ -3,7 +3,6 @@ package exh.metadata.sql.queries
|
|||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable
|
import exh.metadata.sql.tables.SearchMetadataTable
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||||
import eu.kanade.tachiyomi.data.database.inTransaction
|
import eu.kanade.tachiyomi.data.database.inTransaction
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
|
||||||
import exh.metadata.sql.models.SearchTitle
|
import exh.metadata.sql.models.SearchTitle
|
||||||
import exh.metadata.sql.tables.SearchTitleTable
|
import exh.metadata.sql.tables.SearchTitleTable
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
package exh.search
|
package exh.search
|
||||||
|
|
||||||
class Namespace(var namespace: String,
|
class Namespace(
|
||||||
var tag: Text? = null) : QueryComponent()
|
var namespace: String,
|
||||||
|
var tag: Text? = null
|
||||||
|
) : QueryComponent()
|
||||||
|
@ -7,8 +7,10 @@ import exh.metadata.sql.tables.SearchTitleTable
|
|||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
private val queryCache = mutableMapOf<String, List<QueryComponent>>()
|
private val queryCache = mutableMapOf<String, List<QueryComponent>>()
|
||||||
|
|
||||||
fun textToSubQueries(namespace: String?,
|
fun textToSubQueries(
|
||||||
component: Text?): Pair<String, List<String>>? {
|
namespace: String?,
|
||||||
|
component: Text?
|
||||||
|
): Pair<String, List<String>>? {
|
||||||
val maybeLenientComponent = component?.let {
|
val maybeLenientComponent = component?.let {
|
||||||
if (!it.exact)
|
if (!it.exact)
|
||||||
it.asLenientTagQueries()
|
it.asLenientTagQueries()
|
||||||
@ -97,7 +99,6 @@ class SearchEngine {
|
|||||||
completeParams += pair.second
|
completeParams += pair.second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exclude.forEach {
|
exclude.forEach {
|
||||||
wheres += """
|
wheres += """
|
||||||
(meta.${SearchMetadataTable.COL_MANGA_ID} NOT IN ${it.first})
|
(meta.${SearchMetadataTable.COL_MANGA_ID} NOT IN ${it.first})
|
||||||
@ -197,7 +198,6 @@ class SearchEngine {
|
|||||||
return string.replace("\\", "\\\\")
|
return string.replace("\\", "\\\\")
|
||||||
.replace("_", "\\_")
|
.replace("_", "\\_")
|
||||||
.replace("%", "\\%")
|
.replace("%", "\\%")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,19 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.ui.smartsearch.SmartSearchPresenter
|
import exh.ui.smartsearch.SmartSearchPresenter
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import info.debatty.java.stringsimilarity.NormalizedLevenshtein
|
import info.debatty.java.stringsimilarity.NormalizedLevenshtein
|
||||||
import kotlinx.coroutines.*
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.supervisorScope
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class SmartSearchEngine(parentContext: CoroutineContext,
|
class SmartSearchEngine(
|
||||||
val extraSearchParams: String? = null): CoroutineScope {
|
parentContext: CoroutineContext,
|
||||||
|
val extraSearchParams: String? = null
|
||||||
|
) : CoroutineScope {
|
||||||
override val coroutineContext: CoroutineContext = parentContext + Job() + Dispatchers.Default
|
override val coroutineContext: CoroutineContext = parentContext + Job() + Dispatchers.Default
|
||||||
|
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package exh.source
|
package exh.source
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.lang.RuntimeException
|
|
||||||
|
|
||||||
abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() {
|
||||||
/**
|
/**
|
||||||
@ -14,16 +17,16 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() {
|
|||||||
*
|
*
|
||||||
* @param page the page number to retrieve.
|
* @param page the page number to retrieve.
|
||||||
*/
|
*/
|
||||||
override fun popularMangaRequest(page: Int)
|
override fun popularMangaRequest(page: Int) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun popularMangaParse(response: Response)
|
override fun popularMangaParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for the search manga given the page.
|
* Returns the request for the search manga given the page.
|
||||||
@ -32,64 +35,64 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() {
|
|||||||
* @param query the search query.
|
* @param query the search query.
|
||||||
* @param filters the list of filters to apply.
|
* @param filters the list of filters to apply.
|
||||||
*/
|
*/
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList)
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun searchMangaParse(response: Response)
|
override fun searchMangaParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for latest manga given the page.
|
* Returns the request for latest manga given the page.
|
||||||
*
|
*
|
||||||
* @param page the page number to retrieve.
|
* @param page the page number to retrieve.
|
||||||
*/
|
*/
|
||||||
override fun latestUpdatesRequest(page: Int)
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun latestUpdatesParse(response: Response)
|
override fun latestUpdatesParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns the details of a manga.
|
* Parses the response from the site and returns the details of a manga.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun mangaDetailsParse(response: Response)
|
override fun mangaDetailsParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a list of chapters.
|
* Parses the response from the site and returns a list of chapters.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun chapterListParse(response: Response)
|
override fun chapterListParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a list of pages.
|
* Parses the response from the site and returns a list of pages.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun pageListParse(response: Response)
|
override fun pageListParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns the absolute url to the source image.
|
* Parses the response from the site and returns the absolute url to the source image.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun imageUrlParse(response: Response)
|
override fun imageUrlParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base url of the website without the trailing slash, like: http://mysite.com
|
* Base url of the website without the trailing slash, like: http://mysite.com
|
||||||
@ -236,8 +239,8 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() {
|
|||||||
override fun getFilterList() = delegate.getFilterList()
|
override fun getFilterList() = delegate.getFilterList()
|
||||||
|
|
||||||
private fun ensureDelegateCompatible() {
|
private fun ensureDelegateCompatible() {
|
||||||
if(versionId != delegate.versionId
|
if (versionId != delegate.versionId ||
|
||||||
|| lang != delegate.lang) {
|
lang != delegate.lang) {
|
||||||
throw IncompatibleDelegateException("Delegate source is not compatible (versionId: $versionId <=> ${delegate.versionId}, lang: $lang <=> ${delegate.lang})!")
|
throw IncompatibleDelegateException("Delegate source is not compatible (versionId: $versionId <=> ${delegate.versionId}, lang: $lang <=> ${delegate.lang})!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,19 @@ package exh.source
|
|||||||
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class EnhancedHttpSource(val originalSource: HttpSource,
|
class EnhancedHttpSource(
|
||||||
val enchancedSource: HttpSource): HttpSource() {
|
val originalSource: HttpSource,
|
||||||
|
val enchancedSource: HttpSource
|
||||||
|
) : HttpSource() {
|
||||||
private val prefs: PreferencesHelper by injectLazy()
|
private val prefs: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,16 +22,16 @@ class EnhancedHttpSource(val originalSource: HttpSource,
|
|||||||
*
|
*
|
||||||
* @param page the page number to retrieve.
|
* @param page the page number to retrieve.
|
||||||
*/
|
*/
|
||||||
override fun popularMangaRequest(page: Int)
|
override fun popularMangaRequest(page: Int) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun popularMangaParse(response: Response)
|
override fun popularMangaParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for the search manga given the page.
|
* Returns the request for the search manga given the page.
|
||||||
@ -34,64 +40,64 @@ class EnhancedHttpSource(val originalSource: HttpSource,
|
|||||||
* @param query the search query.
|
* @param query the search query.
|
||||||
* @param filters the list of filters to apply.
|
* @param filters the list of filters to apply.
|
||||||
*/
|
*/
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList)
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun searchMangaParse(response: Response)
|
override fun searchMangaParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for latest manga given the page.
|
* Returns the request for latest manga given the page.
|
||||||
*
|
*
|
||||||
* @param page the page number to retrieve.
|
* @param page the page number to retrieve.
|
||||||
*/
|
*/
|
||||||
override fun latestUpdatesRequest(page: Int)
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun latestUpdatesParse(response: Response)
|
override fun latestUpdatesParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns the details of a manga.
|
* Parses the response from the site and returns the details of a manga.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun mangaDetailsParse(response: Response)
|
override fun mangaDetailsParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a list of chapters.
|
* Parses the response from the site and returns a list of chapters.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun chapterListParse(response: Response)
|
override fun chapterListParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a list of pages.
|
* Parses the response from the site and returns a list of pages.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun pageListParse(response: Response)
|
override fun pageListParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns the absolute url to the source image.
|
* Parses the response from the site and returns the absolute url to the source image.
|
||||||
*
|
*
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
override fun imageUrlParse(response: Response)
|
override fun imageUrlParse(response: Response) =
|
||||||
= throw UnsupportedOperationException("Should never be called!")
|
throw UnsupportedOperationException("Should never be called!")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base url of the website without the trailing slash, like: http://mysite.com
|
* Base url of the website without the trailing slash, like: http://mysite.com
|
||||||
@ -146,8 +152,8 @@ class EnhancedHttpSource(val originalSource: HttpSource,
|
|||||||
* @param query the search query.
|
* @param query the search query.
|
||||||
* @param filters the list of filters to apply.
|
* @param filters the list of filters to apply.
|
||||||
*/
|
*/
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList)
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) =
|
||||||
= source().fetchSearchManga(page, query, filters)
|
source().fetchSearchManga(page, query, filters)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable containing a page with a list of latest manga updates.
|
* Returns an observable containing a page with a list of latest manga updates.
|
||||||
@ -202,8 +208,8 @@ class EnhancedHttpSource(val originalSource: HttpSource,
|
|||||||
* @param chapter the chapter to be added.
|
* @param chapter the chapter to be added.
|
||||||
* @param manga the manga of the chapter.
|
* @param manga the manga of the chapter.
|
||||||
*/
|
*/
|
||||||
override fun prepareNewChapter(chapter: SChapter, manga: SManga)
|
override fun prepareNewChapter(chapter: SChapter, manga: SManga) =
|
||||||
= source().prepareNewChapter(chapter, manga)
|
source().prepareNewChapter(chapter, manga)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of filters for the source.
|
* Returns the list of filters for the source.
|
||||||
|
@ -7,8 +7,8 @@ import com.afollestad.materialdialogs.MaterialDialog
|
|||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import timber.log.Timber
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
class ConfiguringDialogController : DialogController() {
|
class ConfiguringDialogController : DialogController() {
|
||||||
private var materialDialog: MaterialDialog? = null
|
private var materialDialog: MaterialDialog? = null
|
||||||
@ -62,4 +62,3 @@ class ConfiguringDialogController : DialogController() {
|
|||||||
router.popController(this)
|
router.popController(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,13 @@ class EHConfigurator {
|
|||||||
private fun EHentai.requestWithCreds(sp: Int = 1) = Request.Builder()
|
private fun EHentai.requestWithCreds(sp: Int = 1) = Request.Builder()
|
||||||
.addHeader("Cookie", cookiesHeader(sp))
|
.addHeader("Cookie", cookiesHeader(sp))
|
||||||
|
|
||||||
private fun EHentai.execProfileActions(action: String,
|
private fun EHentai.execProfileActions(
|
||||||
|
action: String,
|
||||||
name: String,
|
name: String,
|
||||||
set: String,
|
set: String,
|
||||||
sp: Int)
|
sp: Int
|
||||||
= configuratorClient.newCall(requestWithCreds(sp)
|
) =
|
||||||
|
configuratorClient.newCall(requestWithCreds(sp)
|
||||||
.url(uconfigUrl)
|
.url(uconfigUrl)
|
||||||
.post(FormBody.Builder()
|
.post(FormBody.Builder()
|
||||||
.add("profile_action", action)
|
.add("profile_action", action)
|
||||||
|
@ -9,7 +9,6 @@ class EHHathPerksResponse {
|
|||||||
var pagingEnlargementII = false
|
var pagingEnlargementII = false
|
||||||
var pagingEnlargementIII = false
|
var pagingEnlargementIII = false
|
||||||
|
|
||||||
override fun toString()
|
override fun toString() =
|
||||||
= "EHHathPerksResponse(moreThumbs=$moreThumbs, thumbsUp=$thumbsUp, allThumbs=$allThumbs, pagingEnlargementI=$pagingEnlargementI, pagingEnlargementII=$pagingEnlargementII, pagingEnlargementIII=$pagingEnlargementIII)"
|
"EHHathPerksResponse(moreThumbs=$moreThumbs, thumbsUp=$thumbsUp, allThumbs=$allThumbs, pagingEnlargementI=$pagingEnlargementI, pagingEnlargementII=$pagingEnlargementII, pagingEnlargementIII=$pagingEnlargementIII)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package exh.ui
|
package exh.ui
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
|
||||||
|
|
||||||
typealias LoadingHandle = String
|
typealias LoadingHandle = String
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
abstract class BaseExhController(bundle: Bundle? = null) : BaseController(bundle), CoroutineScope {
|
abstract class BaseExhController(bundle: Bundle? = null) : BaseController(bundle), CoroutineScope {
|
||||||
abstract val layoutId: Int
|
abstract val layoutId: Int
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package exh.ui.batchadd
|
package exh.ui.batchadd
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -7,16 +7,18 @@ import android.webkit.WebView
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import eu.kanade.tachiyomi.util.system.asJsoup
|
import eu.kanade.tachiyomi.util.system.asJsoup
|
||||||
import exh.ui.captcha.BrowserActionActivity.Companion.CROSS_WINDOW_SCRIPT_INNER
|
import exh.ui.captcha.BrowserActionActivity.Companion.CROSS_WINDOW_SCRIPT_INNER
|
||||||
|
import java.nio.charset.Charset
|
||||||
import org.jsoup.nodes.DataNode
|
import org.jsoup.nodes.DataNode
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.nio.charset.Charset
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
class AutoSolvingWebViewClient(activity: BrowserActionActivity,
|
class AutoSolvingWebViewClient(
|
||||||
|
activity: BrowserActionActivity,
|
||||||
verifyComplete: (String) -> Boolean,
|
verifyComplete: (String) -> Boolean,
|
||||||
injectScript: String?,
|
injectScript: String?,
|
||||||
headers: Map<String, String>)
|
headers: Map<String, String>
|
||||||
: HeadersInjectingWebViewClient(activity, verifyComplete, injectScript, headers) {
|
) :
|
||||||
|
HeadersInjectingWebViewClient(activity, verifyComplete, injectScript, headers) {
|
||||||
|
|
||||||
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
||||||
// Inject our custom script into the recaptcha iframes
|
// Inject our custom script into the recaptcha iframes
|
||||||
|
@ -4,9 +4,11 @@ import android.os.Build
|
|||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
|
|
||||||
open class BasicWebViewClient(protected val activity: BrowserActionActivity,
|
open class BasicWebViewClient(
|
||||||
|
protected val activity: BrowserActionActivity,
|
||||||
protected val verifyComplete: (String) -> Boolean,
|
protected val verifyComplete: (String) -> Boolean,
|
||||||
private val injectScript: String?) : WebViewClient() {
|
private val injectScript: String?
|
||||||
|
) : WebViewClient() {
|
||||||
override fun onPageFinished(view: WebView, url: String) {
|
override fun onPageFinished(view: WebView, url: String) {
|
||||||
super.onPageFinished(view, url)
|
super.onPageFinished(view, url)
|
||||||
|
|
||||||
|
@ -6,7 +6,12 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.webkit.*
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.CookieSyncManager
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
|
import android.webkit.JsResult
|
||||||
|
import android.webkit.WebChromeClient
|
||||||
|
import android.webkit.WebView
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
@ -22,6 +27,9 @@ import eu.kanade.tachiyomi.source.SourceManager
|
|||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import exh.source.DelegatedHttpSource
|
import exh.source.DelegatedHttpSource
|
||||||
import exh.util.melt
|
import exh.util.melt
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.UUID
|
||||||
import kotlinx.android.synthetic.main.eh_activity_captcha.*
|
import kotlinx.android.synthetic.main.eh_activity_captcha.*
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
@ -33,10 +41,6 @@ import rx.Single
|
|||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.Serializable
|
|
||||||
import java.net.URL
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.HashMap
|
|
||||||
|
|
||||||
class BrowserActionActivity : AppCompatActivity() {
|
class BrowserActionActivity : AppCompatActivity() {
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
@ -72,8 +76,8 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
it.value.joinToString(",")
|
it.value.joinToString(",")
|
||||||
} ?: emptyMap()) + (intent.getSerializableExtra(HEADERS_EXTRA) as? HashMap<String, String> ?: emptyMap())
|
} ?: emptyMap()) + (intent.getSerializableExtra(HEADERS_EXTRA) as? HashMap<String, String> ?: emptyMap())
|
||||||
|
|
||||||
val cookies: HashMap<String, String>?
|
val cookies: HashMap<String, String>? =
|
||||||
= intent.getSerializableExtra(COOKIES_EXTRA) as? HashMap<String, String>
|
intent.getSerializableExtra(COOKIES_EXTRA) as? HashMap<String, String>
|
||||||
val script: String? = intent.getStringExtra(SCRIPT_EXTRA)
|
val script: String? = intent.getStringExtra(SCRIPT_EXTRA)
|
||||||
val url: String? = intent.getStringExtra(URL_EXTRA)
|
val url: String? = intent.getStringExtra(URL_EXTRA)
|
||||||
val actionName = intent.getStringExtra(ACTION_NAME_EXTRA)
|
val actionName = intent.getStringExtra(ACTION_NAME_EXTRA)
|
||||||
@ -120,8 +124,8 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
// Wait for both inner scripts to be loaded
|
// Wait for both inner scripts to be loaded
|
||||||
if (loadedInners >= 2) {
|
if (loadedInners >= 2) {
|
||||||
// Attempt to autosolve captcha
|
// Attempt to autosolve captcha
|
||||||
if(preferencesHelper.eh_autoSolveCaptchas().getOrDefault()
|
if (preferencesHelper.eh_autoSolveCaptchas().getOrDefault() &&
|
||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
webview.post {
|
webview.post {
|
||||||
// 10 seconds to auto-solve captcha
|
// 10 seconds to auto-solve captcha
|
||||||
strictValidationStartTime = System.currentTimeMillis() + 1000 * 10
|
strictValidationStartTime = System.currentTimeMillis() + 1000 * 10
|
||||||
@ -415,7 +419,6 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
doStageCheckbox(loopId)
|
doStageCheckbox(loopId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun validateCaptchaCallback(result: Boolean, loopId: String) {
|
fun validateCaptchaCallback(result: Boolean, loopId: String) {
|
||||||
@ -434,8 +437,8 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val savedStrictValidationStartTime = strictValidationStartTime
|
val savedStrictValidationStartTime = strictValidationStartTime
|
||||||
if(savedStrictValidationStartTime != null
|
if (savedStrictValidationStartTime != null &&
|
||||||
&& System.currentTimeMillis() > savedStrictValidationStartTime) {
|
System.currentTimeMillis() > savedStrictValidationStartTime) {
|
||||||
captchaSolveFail()
|
captchaSolveFail()
|
||||||
} else {
|
} else {
|
||||||
webview.postDelayed({
|
webview.postDelayed({
|
||||||
@ -624,12 +627,14 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launchCaptcha(context: Context,
|
fun launchCaptcha(
|
||||||
|
context: Context,
|
||||||
source: ActionCompletionVerifier,
|
source: ActionCompletionVerifier,
|
||||||
cookies: Map<String, String>,
|
cookies: Map<String, String>,
|
||||||
script: String?,
|
script: String?,
|
||||||
url: String,
|
url: String,
|
||||||
autoSolveSubmitBtnSelector: String? = null) {
|
autoSolveSubmitBtnSelector: String? = null
|
||||||
|
) {
|
||||||
val intent = baseIntent(context).apply {
|
val intent = baseIntent(context).apply {
|
||||||
putExtra(SOURCE_ID_EXTRA, source.id)
|
putExtra(SOURCE_ID_EXTRA, source.id)
|
||||||
putExtra(COOKIES_EXTRA, HashMap(cookies))
|
putExtra(COOKIES_EXTRA, HashMap(cookies))
|
||||||
@ -641,9 +646,11 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launchUniversal(context: Context,
|
fun launchUniversal(
|
||||||
|
context: Context,
|
||||||
source: HttpSource,
|
source: HttpSource,
|
||||||
url: String) {
|
url: String
|
||||||
|
) {
|
||||||
val intent = baseIntent(context).apply {
|
val intent = baseIntent(context).apply {
|
||||||
putExtra(SOURCE_ID_EXTRA, source.id)
|
putExtra(SOURCE_ID_EXTRA, source.id)
|
||||||
putExtra(URL_EXTRA, url)
|
putExtra(URL_EXTRA, url)
|
||||||
@ -652,9 +659,11 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launchUniversal(context: Context,
|
fun launchUniversal(
|
||||||
|
context: Context,
|
||||||
sourceId: Long,
|
sourceId: Long,
|
||||||
url: String) {
|
url: String
|
||||||
|
) {
|
||||||
val intent = baseIntent(context).apply {
|
val intent = baseIntent(context).apply {
|
||||||
putExtra(SOURCE_ID_EXTRA, sourceId)
|
putExtra(SOURCE_ID_EXTRA, sourceId)
|
||||||
putExtra(URL_EXTRA, url)
|
putExtra(URL_EXTRA, url)
|
||||||
@ -663,11 +672,13 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launchAction(context: Context,
|
fun launchAction(
|
||||||
|
context: Context,
|
||||||
completionVerifier: ActionCompletionVerifier,
|
completionVerifier: ActionCompletionVerifier,
|
||||||
script: String?,
|
script: String?,
|
||||||
url: String,
|
url: String,
|
||||||
actionName: String) {
|
actionName: String
|
||||||
|
) {
|
||||||
val intent = baseIntent(context).apply {
|
val intent = baseIntent(context).apply {
|
||||||
putExtra(SOURCE_ID_EXTRA, completionVerifier.id)
|
putExtra(SOURCE_ID_EXTRA, completionVerifier.id)
|
||||||
putExtra(SCRIPT_EXTRA, script)
|
putExtra(SCRIPT_EXTRA, script)
|
||||||
@ -678,12 +689,14 @@ class BrowserActionActivity : AppCompatActivity() {
|
|||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launchAction(context: Context,
|
fun launchAction(
|
||||||
|
context: Context,
|
||||||
completionVerifier: (String) -> Boolean,
|
completionVerifier: (String) -> Boolean,
|
||||||
script: String?,
|
script: String?,
|
||||||
url: String,
|
url: String,
|
||||||
actionName: String,
|
actionName: String,
|
||||||
headers: Map<String, String>? = emptyMap()) {
|
headers: Map<String, String>? = emptyMap()
|
||||||
|
) {
|
||||||
val intent = baseIntent(context).apply {
|
val intent = baseIntent(context).apply {
|
||||||
putExtra(HEADERS_EXTRA, HashMap(headers))
|
putExtra(HEADERS_EXTRA, HashMap(headers))
|
||||||
putExtra(VERIFY_LAMBDA_EXTRA, completionVerifier as Serializable)
|
putExtra(VERIFY_LAMBDA_EXTRA, completionVerifier as Serializable)
|
||||||
@ -708,4 +721,3 @@ class NoopActionCompletionVerifier(private val source: HttpSource): DelegatedHtt
|
|||||||
interface ActionCompletionVerifier : Source {
|
interface ActionCompletionVerifier : Source {
|
||||||
fun verifyComplete(url: String): Boolean
|
fun verifyComplete(url: String): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,13 @@ import android.webkit.WebView
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
open class HeadersInjectingWebViewClient(activity: BrowserActionActivity,
|
open class HeadersInjectingWebViewClient(
|
||||||
|
activity: BrowserActionActivity,
|
||||||
verifyComplete: (String) -> Boolean,
|
verifyComplete: (String) -> Boolean,
|
||||||
injectScript: String?,
|
injectScript: String?,
|
||||||
private val headers: Map<String, String>)
|
private val headers: Map<String, String>
|
||||||
: BasicWebViewClient(activity, verifyComplete, injectScript) {
|
) :
|
||||||
|
BasicWebViewClient(activity, verifyComplete, injectScript) {
|
||||||
|
|
||||||
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
||||||
// Temp disabled as it's unreliable
|
// Temp disabled as it's unreliable
|
||||||
|
@ -3,8 +3,8 @@ package exh.ui.intercept
|
|||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import exh.GalleryAddEvent
|
import exh.GalleryAddEvent
|
||||||
import exh.GalleryAdder
|
import exh.GalleryAdder
|
||||||
import rx.subjects.BehaviorSubject
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import rx.subjects.BehaviorSubject
|
||||||
|
|
||||||
class InterceptActivityPresenter : BasePresenter<InterceptActivity>() {
|
class InterceptActivityPresenter : BasePresenter<InterceptActivity>() {
|
||||||
private val galleryAdder = GalleryAdder()
|
private val galleryAdder = GalleryAdder()
|
||||||
|
@ -28,13 +28,13 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At
|
|||||||
val prefs: PreferencesHelper by injectLazy()
|
val prefs: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
val fingerprintSupported
|
val fingerprintSupported
|
||||||
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||||
&& Reprint.isHardwarePresent()
|
Reprint.isHardwarePresent() &&
|
||||||
&& Reprint.hasFingerprintRegistered()
|
Reprint.hasFingerprintRegistered()
|
||||||
|
|
||||||
val useFingerprint
|
val useFingerprint
|
||||||
get() = fingerprintSupported
|
get() = fingerprintSupported &&
|
||||||
&& prefs.eh_lockUseFingerprint().getOrDefault()
|
prefs.eh_lockUseFingerprint().getOrDefault()
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
override fun onAttached() {
|
override fun onAttached() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package exh.ui.lock
|
package exh.ui.lock
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
@ -8,7 +7,6 @@ import com.bluelinelabs.conductor.RouterTransaction
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
object LockActivityDelegate {
|
object LockActivityDelegate {
|
||||||
private val preferences by injectLazy<PreferencesHelper>()
|
private val preferences by injectLazy<PreferencesHelper>()
|
||||||
@ -20,7 +18,6 @@ object LockActivityDelegate {
|
|||||||
.popChangeHandler(LockChangeHandler(animate)))
|
.popChangeHandler(LockChangeHandler(animate)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun onCreate(activity: FragmentActivity) {
|
fun onCreate(activity: FragmentActivity) {
|
||||||
preferences.secureScreen().asObservable()
|
preferences.secureScreen().asObservable()
|
||||||
.subscribe {
|
.subscribe {
|
||||||
@ -42,5 +39,4 @@ object LockActivityDelegate {
|
|||||||
private fun isAppLocked(router: Router): Boolean {
|
private fun isAppLocked(router: Router): Boolean {
|
||||||
return router.backstack.lastOrNull()?.controller() is LockController
|
return router.backstack.lastOrNull()?.controller() is LockController
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler
|
import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
|
||||||
class LockChangeHandler : AnimatorChangeHandler {
|
class LockChangeHandler : AnimatorChangeHandler {
|
||||||
constructor() : super()
|
constructor() : super()
|
||||||
@ -36,6 +36,4 @@ class LockChangeHandler : AnimatorChangeHandler {
|
|||||||
|
|
||||||
override fun copy(): ControllerChangeHandler =
|
override fun copy(): ControllerChangeHandler =
|
||||||
LockChangeHandler(animationDuration, removesFromViewOnPush())
|
LockChangeHandler(animationDuration, removesFromViewOnPush())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ class LockController : NucleusController<LockPresenter>() {
|
|||||||
|
|
||||||
val prefs: PreferencesHelper by injectLazy()
|
val prefs: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup)
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup) =
|
||||||
= inflater.inflate(R.layout.activity_lock, container, false)!!
|
inflater.inflate(R.layout.activity_lock, container, false)!!
|
||||||
|
|
||||||
override fun createPresenter() = LockPresenter()
|
override fun createPresenter() = LockPresenter()
|
||||||
|
|
||||||
|
@ -8,12 +8,12 @@ import com.afollestad.materialdialogs.MaterialDialog
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.util.preference.onChange
|
import eu.kanade.tachiyomi.util.preference.onChange
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.security.SecureRandom
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.math.BigInteger
|
|
||||||
import java.security.SecureRandom
|
|
||||||
|
|
||||||
class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
SwitchPreferenceCompat(context, attrs) {
|
SwitchPreferenceCompat(context, attrs) {
|
||||||
|
@ -11,9 +11,8 @@ class LockPresenter: BasePresenter<LockController>() {
|
|||||||
val prefs: PreferencesHelper by injectLazy()
|
val prefs: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
val useFingerprint
|
val useFingerprint
|
||||||
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||||
&& Reprint.isHardwarePresent()
|
Reprint.isHardwarePresent() &&
|
||||||
&& Reprint.hasFingerprintRegistered()
|
Reprint.hasFingerprintRegistered() &&
|
||||||
&& prefs.eh_lockUseFingerprint().getOrDefault()
|
prefs.eh_lockUseFingerprint().getOrDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,11 +13,10 @@ import com.elvishew.xlog.XLog
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Password hashing utils
|
* Password hashing utils
|
||||||
@ -40,22 +39,24 @@ fun sha512(passwordToHash: String, salt: String): String {
|
|||||||
/**
|
/**
|
||||||
* Check if lock is enabled
|
* Check if lock is enabled
|
||||||
*/
|
*/
|
||||||
fun lockEnabled(prefs: PreferencesHelper = Injekt.get())
|
fun lockEnabled(prefs: PreferencesHelper = Injekt.get()) =
|
||||||
= prefs.eh_lockHash().get() != null
|
prefs.eh_lockHash().get() != null &&
|
||||||
&& prefs.eh_lockSalt().get() != null
|
prefs.eh_lockSalt().get() != null &&
|
||||||
&& prefs.eh_lockLength().getOrDefault() != -1
|
prefs.eh_lockLength().getOrDefault() != -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the lock will function properly
|
* Check if the lock will function properly
|
||||||
*
|
*
|
||||||
* @return true if action is required, false if lock is working properly
|
* @return true if action is required, false if lock is working properly
|
||||||
*/
|
*/
|
||||||
fun notifyLockSecurity(context: Context,
|
fun notifyLockSecurity(
|
||||||
prefs: PreferencesHelper = Injekt.get()): Boolean {
|
context: Context,
|
||||||
|
prefs: PreferencesHelper = Injekt.get()
|
||||||
|
): Boolean {
|
||||||
return false
|
return false
|
||||||
if (!prefs.eh_lockManually().getOrDefault()
|
if (!prefs.eh_lockManually().getOrDefault() &&
|
||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
|
||||||
&& !hasAccessToUsageStats(context)) {
|
!hasAccessToUsageStats(context)) {
|
||||||
MaterialDialog.Builder(context)
|
MaterialDialog.Builder(context)
|
||||||
.title("Permission required")
|
.title("Permission required")
|
||||||
.content("${context.getString(R.string.app_name)} requires the usage stats permission to detect when you leave the app. " +
|
.content("${context.getString(R.string.app_name)} requires the usage stats permission to detect when you leave the app. " +
|
||||||
|
@ -12,14 +12,14 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||||
import eu.kanade.tachiyomi.util.view.gone
|
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
|
import eu.kanade.tachiyomi.util.view.gone
|
||||||
import eu.kanade.tachiyomi.util.view.visible
|
import eu.kanade.tachiyomi.util.view.visible
|
||||||
import exh.uconfig.WarnConfigureDialogController
|
import exh.uconfig.WarnConfigureDialogController
|
||||||
|
import java.net.HttpCookie
|
||||||
import kotlinx.android.synthetic.main.eh_activity_login.view.*
|
import kotlinx.android.synthetic.main.eh_activity_login.view.*
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.HttpCookie
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoginController
|
* LoginController
|
||||||
@ -105,8 +105,8 @@ class LoginController : NucleusController<LoginPresenter>() {
|
|||||||
val parsedUrl = Uri.parse(url)
|
val parsedUrl = Uri.parse(url)
|
||||||
if (parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) {
|
if (parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) {
|
||||||
// Hide distracting content
|
// Hide distracting content
|
||||||
if(!parsedUrl.queryParameterNames.contains(PARAM_SKIP_INJECT)
|
if (!parsedUrl.queryParameterNames.contains(PARAM_SKIP_INJECT) &&
|
||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||||
view.evaluateJavascript(HIDE_JS, null)
|
view.evaluateJavascript(HIDE_JS, null)
|
||||||
|
|
||||||
// Check login result
|
// Check login result
|
||||||
@ -138,9 +138,9 @@ class LoginController : NucleusController<LoginPresenter>() {
|
|||||||
fun checkLoginCookies(url: String): Boolean {
|
fun checkLoginCookies(url: String): Boolean {
|
||||||
getCookies(url)?.let { parsed ->
|
getCookies(url)?.let { parsed ->
|
||||||
return parsed.filter {
|
return parsed.filter {
|
||||||
(it.name.equals(MEMBER_ID_COOKIE, ignoreCase = true)
|
(it.name.equals(MEMBER_ID_COOKIE, ignoreCase = true) ||
|
||||||
|| it.name.equals(PASS_HASH_COOKIE, ignoreCase = true))
|
it.name.equals(PASS_HASH_COOKIE, ignoreCase = true)) &&
|
||||||
&& it.value.isNotBlank()
|
it.value.isNotBlank()
|
||||||
}.count() >= 2
|
}.count() >= 2
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -177,8 +177,8 @@ class LoginController : NucleusController<LoginPresenter>() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCookies(url: String): List<HttpCookie>?
|
fun getCookies(url: String): List<HttpCookie>? =
|
||||||
= CookieManager.getInstance().getCookie(url)?.let {
|
CookieManager.getInstance().getCookie(url)?.let {
|
||||||
it.split("; ").flatMap {
|
it.split("; ").flatMap {
|
||||||
HttpCookie.parse(it)
|
HttpCookie.parse(it)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,4 @@ package exh.ui.login
|
|||||||
|
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
|
||||||
class LoginPresenter: BasePresenter<LoginController>() {
|
class LoginPresenter : BasePresenter<LoginController>()
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -12,9 +12,9 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
|
|||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.isLewdSource
|
import exh.isLewdSource
|
||||||
|
import kotlin.concurrent.thread
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
class MetadataFetchDialog {
|
class MetadataFetchDialog {
|
||||||
|
|
||||||
@ -132,7 +132,6 @@ class MetadataFetchDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun adviseMigrationLater(activity: Activity) {
|
fun adviseMigrationLater(activity: Activity) {
|
||||||
|
@ -4,8 +4,10 @@ import android.os.Bundle
|
|||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import exh.debug.DebugFunctions.sourceManager
|
import exh.debug.DebugFunctions.sourceManager
|
||||||
|
|
||||||
class MigrationSourceAdapter(val items: List<MigrationSourceItem>,
|
class MigrationSourceAdapter(
|
||||||
val controller: MigrationDesignController): FlexibleAdapter<MigrationSourceItem>(
|
val items: List<MigrationSourceItem>,
|
||||||
|
val controller: MigrationDesignController
|
||||||
|
) : FlexibleAdapter<MigrationSourceItem>(
|
||||||
items,
|
items,
|
||||||
controller,
|
controller,
|
||||||
true
|
true
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package exh.ui.migration.manga.design
|
package exh.ui.migration.manga.design
|
||||||
|
|
||||||
|
import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.util.view.getRound
|
import eu.kanade.tachiyomi.util.view.getRound
|
||||||
import kotlinx.android.synthetic.main.eh_source_item.*
|
import kotlinx.android.synthetic.main.eh_source_item.*
|
||||||
import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
|
|
||||||
|
|
||||||
class MigrationSourceHolder(view: View, val adapter: FlexibleAdapter<MigrationSourceItem>) :
|
class MigrationSourceHolder(view: View, val adapter: FlexibleAdapter<MigrationSourceItem>) :
|
||||||
BaseFlexibleViewHolder(view, adapter) {
|
BaseFlexibleViewHolder(view, adapter) {
|
||||||
|
@ -25,10 +25,12 @@ class MigrationSourceItem(val source: HttpSource, var sourceEnabled: Boolean): A
|
|||||||
* @param position The position of this item in the adapter.
|
* @param position The position of this item in the adapter.
|
||||||
* @param payloads List of partial changes.
|
* @param payloads List of partial changes.
|
||||||
*/
|
*/
|
||||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<androidx.recyclerview.widget.RecyclerView.ViewHolder>>,
|
override fun bindViewHolder(
|
||||||
|
adapter: FlexibleAdapter<IFlexible<androidx.recyclerview.widget.RecyclerView.ViewHolder>>,
|
||||||
holder: MigrationSourceHolder,
|
holder: MigrationSourceHolder,
|
||||||
position: Int,
|
position: Int,
|
||||||
payloads: List<Any?>?) {
|
payloads: List<Any?>?
|
||||||
|
) {
|
||||||
holder.bind(source, sourceEnabled)
|
holder.bind(source, sourceEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,17 @@ import eu.kanade.tachiyomi.source.Source
|
|||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import exh.util.DeferredField
|
import exh.util.DeferredField
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||||
|
|
||||||
class MigratingManga(private val db: DatabaseHelper,
|
class MigratingManga(
|
||||||
|
private val db: DatabaseHelper,
|
||||||
private val sourceManager: SourceManager,
|
private val sourceManager: SourceManager,
|
||||||
val mangaId: Long,
|
val mangaId: Long,
|
||||||
parentContext: CoroutineContext) {
|
parentContext: CoroutineContext
|
||||||
|
) {
|
||||||
val searchResult = DeferredField<Long?>()
|
val searchResult = DeferredField<Long?>()
|
||||||
|
|
||||||
// <MAX, PROGRESS>
|
// <MAX, PROGRESS>
|
||||||
|
@ -22,20 +22,27 @@ import eu.kanade.tachiyomi.util.view.inflate
|
|||||||
import eu.kanade.tachiyomi.util.view.visible
|
import eu.kanade.tachiyomi.util.view.visible
|
||||||
import exh.MERGED_SOURCE_ID
|
import exh.MERGED_SOURCE_ID
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
import kotlinx.android.synthetic.main.eh_manga_card.view.*
|
|
||||||
import kotlinx.android.synthetic.main.eh_migration_process_item.view.*
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.flow.asFlow
|
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlinx.android.synthetic.main.eh_manga_card.view.*
|
||||||
|
import kotlinx.android.synthetic.main.eh_migration_process_item.view.*
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class MigrationProcedureAdapter(val controller: MigrationProcedureController,
|
class MigrationProcedureAdapter(
|
||||||
|
val controller: MigrationProcedureController,
|
||||||
val migratingManga: List<MigratingManga>,
|
val migratingManga: List<MigratingManga>,
|
||||||
override val coroutineContext: CoroutineContext) : androidx.viewpager.widget.PagerAdapter(), CoroutineScope {
|
override val coroutineContext: CoroutineContext
|
||||||
|
) : androidx.viewpager.widget.PagerAdapter(), CoroutineScope {
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
private val gson: Gson by injectLazy()
|
private val gson: Gson by injectLazy()
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
@ -96,9 +103,11 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun migrateMangaInternal(prevManga: Manga,
|
private fun migrateMangaInternal(
|
||||||
|
prevManga: Manga,
|
||||||
manga: Manga,
|
manga: Manga,
|
||||||
replace: Boolean) {
|
replace: Boolean
|
||||||
|
) {
|
||||||
db.inTransaction {
|
db.inTransaction {
|
||||||
// Update chapters read
|
// Update chapters read
|
||||||
if (MigrationFlags.hasChapters(controller.config.migrationFlags)) {
|
if (MigrationFlags.hasChapters(controller.config.migrationFlags)) {
|
||||||
|
@ -15,13 +15,21 @@ import eu.kanade.tachiyomi.util.system.toast
|
|||||||
import exh.smartsearch.SmartSearchEngine
|
import exh.smartsearch.SmartSearchEngine
|
||||||
import exh.ui.base.BaseExhController
|
import exh.ui.base.BaseExhController
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlinx.android.synthetic.main.eh_migration_process.*
|
import kotlinx.android.synthetic.main.eh_migration_process.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Semaphore
|
import kotlinx.coroutines.sync.Semaphore
|
||||||
import kotlinx.coroutines.sync.withPermit
|
import kotlinx.coroutines.sync.withPermit
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
|
|
||||||
// TODO Will probably implode if activity is fully destroyed
|
// TODO Will probably implode if activity is fully destroyed
|
||||||
class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(bundle), CoroutineScope {
|
class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(bundle), CoroutineScope {
|
||||||
|
@ -14,7 +14,13 @@ import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController
|
|||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.android.synthetic.main.eh_smart_search.*
|
import kotlinx.android.synthetic.main.eh_smart_search.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.NonCancellable
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class SmartSearchController(bundle: Bundle? = null) : NucleusController<SmartSearchPresenter>(), CoroutineScope {
|
class SmartSearchController(bundle: Bundle? = null) : NucleusController<SmartSearchPresenter>(), CoroutineScope {
|
||||||
|
@ -8,8 +8,13 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
||||||
import exh.smartsearch.SmartSearchEngine
|
import exh.smartsearch.SmartSearchEngine
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class SmartSearchPresenter(private val source: CatalogueSource?, private val config: CatalogueController.SmartSearchConfig?) :
|
class SmartSearchPresenter(private val source: CatalogueSource?, private val config: CatalogueController.SmartSearchConfig?) :
|
||||||
BasePresenter<SmartSearchController>(), CoroutineScope {
|
BasePresenter<SmartSearchController>(), CoroutineScope {
|
||||||
@ -48,7 +53,6 @@ class SmartSearchPresenter(private val source: CatalogueSource?, private val con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package exh.util
|
package exh.util
|
||||||
|
|
||||||
|
import kotlin.coroutines.coroutineContext
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlin.coroutines.coroutineContext
|
|
||||||
|
|
||||||
@FlowPreview
|
@FlowPreview
|
||||||
fun <T> Flow<T>.cancellable() = onEach {
|
fun <T> Flow<T>.cancellable() = onEach {
|
||||||
|
@ -112,7 +112,6 @@ private inline class IteratorShim<E>(private val iterator: Iterator<E>) : FakeMu
|
|||||||
override fun next() = iterator.next()
|
override fun next() = iterator.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface FakeMutableIterator<E> : MutableIterator<E> {
|
interface FakeMutableIterator<E> : MutableIterator<E> {
|
||||||
/**
|
/**
|
||||||
* Removes from the underlying collection the last element returned by this iterator.
|
* Removes from the underlying collection the last element returned by this iterator.
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package exh.util
|
package exh.util
|
||||||
|
|
||||||
import io.realm.*
|
import io.realm.Case
|
||||||
import java.util.*
|
import io.realm.RealmModel
|
||||||
|
import io.realm.RealmQuery
|
||||||
|
import io.realm.RealmResults
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Realm query with logging
|
* Realm query with logging
|
||||||
@ -9,14 +12,16 @@ import java.util.*
|
|||||||
* @author nulldev
|
* @author nulldev
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline fun <reified E : RealmModel> RealmQuery<out E>.beginLog(clazz: Class<out E>? =
|
inline fun <reified E : RealmModel> RealmQuery<out E>.beginLog(
|
||||||
E::class.java): LoggingRealmQuery<out E>
|
clazz: Class<out E>? =
|
||||||
= LoggingRealmQuery.fromQuery(this, clazz)
|
E::class.java
|
||||||
|
): LoggingRealmQuery<out E> =
|
||||||
|
LoggingRealmQuery.fromQuery(this, clazz)
|
||||||
|
|
||||||
class LoggingRealmQuery<E : RealmModel>(val query: RealmQuery<E>) {
|
class LoggingRealmQuery<E : RealmModel>(val query: RealmQuery<E>) {
|
||||||
companion object {
|
companion object {
|
||||||
fun <E : RealmModel> fromQuery(q: RealmQuery<out E>, clazz: Class<out E>?)
|
fun <E : RealmModel> fromQuery(q: RealmQuery<out E>, clazz: Class<out E>?) =
|
||||||
= LoggingRealmQuery(q).apply {
|
LoggingRealmQuery(q).apply {
|
||||||
log += "SELECT * FROM ${clazz?.name ?: "???"} WHERE"
|
log += "SELECT * FROM ${clazz?.name ?: "???"} WHERE"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package exh.util
|
package exh.util
|
||||||
|
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import java.util.*
|
import java.util.AbstractMap
|
||||||
|
import java.util.LinkedList
|
||||||
|
|
||||||
class NakedTrieNode<T>(val key: Int, var parent: NakedTrieNode<T>?) {
|
class NakedTrieNode<T>(val key: Int, var parent: NakedTrieNode<T>?) {
|
||||||
val children = SparseArray<NakedTrieNode<T>>(1)
|
val children = SparseArray<NakedTrieNode<T>>(1)
|
||||||
|
@ -8,8 +8,8 @@ import org.jsoup.nodes.Document
|
|||||||
|
|
||||||
fun Response.interceptAsHtml(block: (Document) -> Unit): Response {
|
fun Response.interceptAsHtml(block: (Document) -> Unit): Response {
|
||||||
val body = body
|
val body = body
|
||||||
if (body?.contentType()?.type == "text"
|
if (body?.contentType()?.type == "text" &&
|
||||||
&& body.contentType()?.subtype == "html") {
|
body.contentType()?.subtype == "html") {
|
||||||
val bodyString = body.string()
|
val bodyString = body.string()
|
||||||
val rebuiltResponse = newBuilder()
|
val rebuiltResponse = newBuilder()
|
||||||
.body(ResponseBody.create(body.contentType(), bodyString))
|
.body(ResponseBody.create(body.contentType(), bodyString))
|
||||||
|
@ -3,7 +3,7 @@ package exh.util
|
|||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmModel
|
import io.realm.RealmModel
|
||||||
import io.realm.log.RealmLog
|
import io.realm.log.RealmLog
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
inline fun <T> realmTrans(block: (Realm) -> T): T {
|
inline fun <T> realmTrans(block: (Realm) -> T): T {
|
||||||
return defRealm {
|
return defRealm {
|
||||||
@ -49,9 +49,8 @@ inline fun <T> Realm.useTrans(block: (Realm) -> T): T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : RealmModel> Realm.createUUIDObj(clazz: Class<T>)
|
fun <T : RealmModel> Realm.createUUIDObj(clazz: Class<T>) =
|
||||||
= createObject(clazz, UUID.randomUUID().toString())!!
|
createObject(clazz, UUID.randomUUID().toString())!!
|
||||||
|
|
||||||
inline fun <reified T : RealmModel> Realm.createUUIDObj()
|
|
||||||
= createUUIDObj(T::class.java)
|
|
||||||
|
|
||||||
|
inline fun <reified T : RealmModel> Realm.createUUIDObj() =
|
||||||
|
createUUIDObj(T::class.java)
|
||||||
|
@ -2,10 +2,14 @@ package exh.util
|
|||||||
|
|
||||||
import com.pushtorefresh.storio.operations.PreparedOperation
|
import com.pushtorefresh.storio.operations.PreparedOperation
|
||||||
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
|
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import rx.*
|
|
||||||
import rx.subjects.ReplaySubject
|
|
||||||
import kotlin.coroutines.resumeWithException
|
import kotlin.coroutines.resumeWithException
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import rx.Completable
|
||||||
|
import rx.Observable
|
||||||
|
import rx.Scheduler
|
||||||
|
import rx.Single
|
||||||
|
import rx.Subscription
|
||||||
|
import rx.subjects.ReplaySubject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform a cold single to a hot single
|
* Transform a cold single to a hot single
|
||||||
|
@ -1,6 +1,17 @@
|
|||||||
package xyz.nulldev.ts.api.http.serializer
|
package xyz.nulldev.ts.api.http.serializer
|
||||||
|
|
||||||
import com.github.salomonbrys.kotson.*
|
import com.github.salomonbrys.kotson.bool
|
||||||
|
import com.github.salomonbrys.kotson.byte
|
||||||
|
import com.github.salomonbrys.kotson.char
|
||||||
|
import com.github.salomonbrys.kotson.double
|
||||||
|
import com.github.salomonbrys.kotson.float
|
||||||
|
import com.github.salomonbrys.kotson.get
|
||||||
|
import com.github.salomonbrys.kotson.int
|
||||||
|
import com.github.salomonbrys.kotson.long
|
||||||
|
import com.github.salomonbrys.kotson.obj
|
||||||
|
import com.github.salomonbrys.kotson.set
|
||||||
|
import com.github.salomonbrys.kotson.short
|
||||||
|
import com.github.salomonbrys.kotson.string
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
Loading…
x
Reference in New Issue
Block a user