mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-13 04:28:55 +01:00
Initial implementation of favorites syncing
General code cleanup Fix some cases of duplicate galleries (not completely fixed)
This commit is contained in:
@@ -11,21 +11,26 @@ import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.metadata.*
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.ignore
|
||||
import exh.metadata.models.ExGalleryMetadata
|
||||
import exh.metadata.models.Tag
|
||||
import exh.metadata.nullIfBlank
|
||||
import exh.metadata.parseHumanReadableByteCount
|
||||
import exh.ui.login.LoginController
|
||||
import exh.util.UriFilter
|
||||
import exh.util.UriGroup
|
||||
import exh.util.urlImportFetchSearchManga
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
import exh.ui.login.LoginController
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import exh.util.*
|
||||
|
||||
class EHentai(override val id: Long,
|
||||
val exh: Boolean,
|
||||
@@ -51,14 +56,14 @@ class EHentai(override val id: Long,
|
||||
/**
|
||||
* Gallery list entry
|
||||
*/
|
||||
data class ParsedManga(val fav: String?, val manga: Manga)
|
||||
data class ParsedManga(val fav: Int, val manga: Manga)
|
||||
|
||||
fun extendedGenericMangaParse(doc: Document)
|
||||
= with(doc) {
|
||||
//Parse mangas
|
||||
val parsedMangas = select(".gtr0,.gtr1").map {
|
||||
ParsedManga(
|
||||
fav = it.select(".itd .it3 > .i[id]").first()?.attr("title"),
|
||||
fav = parseFavoritesStyle(it.select(".itd .it3 > .i[id]").first()?.attr("style")),
|
||||
manga = Manga.create(id).apply {
|
||||
//Get title
|
||||
it.select(".itd .it5 a").first()?.apply {
|
||||
@@ -85,6 +90,14 @@ class EHentai(override val id: Long,
|
||||
Pair(parsedMangas, hasNextPage)
|
||||
}
|
||||
|
||||
fun parseFavoritesStyle(style: String?): Int {
|
||||
val offset = style?.substringAfterLast("background-position:0px ")
|
||||
?.removeSuffix("px; cursor:pointer")
|
||||
?.toIntOrNull() ?: return -1
|
||||
|
||||
return (offset + 2)/-19
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a list of galleries
|
||||
*/
|
||||
@@ -287,9 +300,7 @@ class EHentai(override val id: Long,
|
||||
throw UnsupportedOperationException("Unused method was called somehow!")
|
||||
}
|
||||
|
||||
//Too lazy to write return type
|
||||
fun fetchFavorites() = {
|
||||
//Used to get "s" cookie
|
||||
fun fetchFavorites(): Pair<List<ParsedManga>, List<String>> {
|
||||
val favoriteUrl = "$baseUrl/favorites.php"
|
||||
val result = mutableListOf<ParsedManga>()
|
||||
var page = 1
|
||||
@@ -308,22 +319,23 @@ class EHentai(override val id: Long,
|
||||
|
||||
//Parse fav names
|
||||
if (favNames == null)
|
||||
favNames = doc.getElementsByClass("nosel").first().children().filter {
|
||||
it.children().size >= 3
|
||||
}.mapNotNull { it.child(2).text() }
|
||||
favNames = doc.select(".fp:not(.fps)").mapNotNull {
|
||||
it.child(2).text()
|
||||
}
|
||||
|
||||
//Next page
|
||||
page++
|
||||
} while (parsed.second)
|
||||
Pair(result as List<ParsedManga>, favNames!!)
|
||||
}()
|
||||
|
||||
return Pair(result as List<ParsedManga>, favNames!!)
|
||||
}
|
||||
|
||||
val cookiesHeader by lazy {
|
||||
val cookies: MutableMap<String, String> = mutableMapOf()
|
||||
if(prefs.enableExhentai().getOrDefault()) {
|
||||
cookies.put(LoginController.MEMBER_ID_COOKIE, prefs.memberIdVal().get()!!)
|
||||
cookies.put(LoginController.PASS_HASH_COOKIE, prefs.passHashVal().get()!!)
|
||||
cookies.put(LoginController.IGNEOUS_COOKIE, prefs.igneousVal().get()!!)
|
||||
cookies[LoginController.MEMBER_ID_COOKIE] = prefs.memberIdVal().get()!!
|
||||
cookies[LoginController.PASS_HASH_COOKIE] = prefs.passHashVal().get()!!
|
||||
cookies[LoginController.IGNEOUS_COOKIE] = prefs.igneousVal().get()!!
|
||||
}
|
||||
|
||||
//Setup settings
|
||||
@@ -458,20 +470,5 @@ class EHentai(override val id: Long,
|
||||
companion object {
|
||||
val QUERY_PREFIX = "?f_apply=Apply+Filter"
|
||||
val TR_SUFFIX = "TR"
|
||||
|
||||
fun getCookies(cookies: String): Map<String, String>? {
|
||||
val foundCookies = HashMap<String, String>()
|
||||
for (cookie in cookies.split(";".toRegex()).dropLastWhile(String::isEmpty).toTypedArray()) {
|
||||
val splitCookie = cookie.split("=".toRegex()).dropLastWhile(String::isEmpty).toTypedArray()
|
||||
if (splitCookie.size < 2) {
|
||||
return null
|
||||
}
|
||||
val trimmedKey = splitCookie[0].trim { it <= ' ' }
|
||||
if (!foundCookies.containsKey(trimmedKey)) {
|
||||
foundCookies.put(trimmedKey, splitCookie[1].trim { it <= ' ' })
|
||||
}
|
||||
}
|
||||
return foundCookies
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.view.ActionMode
|
||||
import android.support.v7.widget.SearchView
|
||||
import android.view.*
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.f2prateek.rx.preferences.Preference
|
||||
@@ -36,7 +37,7 @@ import eu.kanade.tachiyomi.ui.migration.MigrationController
|
||||
import eu.kanade.tachiyomi.util.inflate
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import eu.kanade.tachiyomi.widget.DrawerSwipeCloseListener
|
||||
import exh.FavoritesSyncHelper
|
||||
import exh.favorites.FavoritesSyncStatus
|
||||
import exh.metadata.loadAllMetadata
|
||||
import exh.metadata.models.SearchableGalleryMetadata
|
||||
import io.realm.Realm
|
||||
@@ -133,8 +134,12 @@ class LibraryController(
|
||||
var realm: Realm? = null
|
||||
//Cached metadata
|
||||
var meta: Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>>? = null
|
||||
//Sync dialog
|
||||
private var favSyncDialog: MaterialDialog? = null
|
||||
//Old sync status
|
||||
private var oldSyncStatus: FavoritesSyncStatus? = null
|
||||
//Favorites
|
||||
val favorites by lazy { FavoritesSyncHelper(activity!!) }
|
||||
private var favoritesSyncSubscription: Subscription? = null
|
||||
// <-- EH
|
||||
|
||||
init {
|
||||
@@ -406,7 +411,7 @@ class LibraryController(
|
||||
router.pushController(MigrationController().withFadeTransaction())
|
||||
}
|
||||
R.id.action_download_favorites -> {
|
||||
favorites.guiSyncFavorites { }
|
||||
presenter.favoritesSync.runSync()
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
@@ -531,6 +536,100 @@ class LibraryController(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
|
||||
// --> EXH
|
||||
cleanupSyncState()
|
||||
favoritesSyncSubscription =
|
||||
presenter.favoritesSync.status
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
updateSyncStatus(it)
|
||||
}
|
||||
// <-- EXH
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
super.onDetach(view)
|
||||
|
||||
//EXH
|
||||
cleanupSyncState()
|
||||
}
|
||||
|
||||
// --> EXH
|
||||
private fun cleanupSyncState() {
|
||||
favoritesSyncSubscription?.unsubscribe()
|
||||
favoritesSyncSubscription = null
|
||||
//Close sync status
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = null
|
||||
oldSyncStatus = null
|
||||
}
|
||||
|
||||
private fun buildDialog() = activity?.let {
|
||||
MaterialDialog.Builder(it)
|
||||
}
|
||||
|
||||
private fun showSyncProgressDialog() {
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = buildDialog()
|
||||
?.title("Favorites syncing")
|
||||
?.cancelable(false)
|
||||
?.progress(true, 0)
|
||||
?.show()
|
||||
}
|
||||
|
||||
private fun updateSyncStatus(status: FavoritesSyncStatus) {
|
||||
when(status) {
|
||||
is FavoritesSyncStatus.Idle -> {
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = null
|
||||
}
|
||||
is FavoritesSyncStatus.Error -> {
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = buildDialog()
|
||||
?.title("Favorites sync error")
|
||||
?.content("An error occurred during the sync process: ${status.message}")
|
||||
?.cancelable(false)
|
||||
?.positiveText("Ok")
|
||||
?.onPositive { _, _ ->
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
}
|
||||
?.show()
|
||||
}
|
||||
is FavoritesSyncStatus.Processing,
|
||||
is FavoritesSyncStatus.Initializing -> {
|
||||
if(favSyncDialog == null || (oldSyncStatus != null
|
||||
&& oldSyncStatus !is FavoritesSyncStatus.Initializing
|
||||
&& oldSyncStatus !is FavoritesSyncStatus.Processing))
|
||||
showSyncProgressDialog()
|
||||
|
||||
favSyncDialog?.setContent(status.message)
|
||||
}
|
||||
is FavoritesSyncStatus.Complete -> {
|
||||
favSyncDialog?.dismiss()
|
||||
|
||||
if(status.errors.isNotEmpty()) {
|
||||
favSyncDialog = buildDialog()
|
||||
?.title("Favorites sync complete with errors")
|
||||
?.content("Some errors occurred during the sync process:\n\n"
|
||||
+ status.errors.joinToString("\n"))
|
||||
?.cancelable(false)
|
||||
?.positiveText("Ok")
|
||||
?.onPositive { _, _ ->
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
}
|
||||
?.show()
|
||||
} else {
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
}
|
||||
}
|
||||
}
|
||||
oldSyncStatus = status
|
||||
}
|
||||
// <-- EXH
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_IMAGE_OPEN) {
|
||||
if (data == null || resultCode != Activity.RESULT_OK) return
|
||||
|
||||
@@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.util.combineLatest
|
||||
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
|
||||
import exh.favorites.FavoritesSyncHelper
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
@@ -76,6 +77,10 @@ class LibraryPresenter(
|
||||
*/
|
||||
private var librarySubscription: Subscription? = null
|
||||
|
||||
// --> EXH
|
||||
val favoritesSync = FavoritesSyncHelper(context)
|
||||
// <-- EXH
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
subscribeLibrary()
|
||||
|
||||
Reference in New Issue
Block a user