Fix reading position not being saved when opening multi-versioned EH manga

This commit is contained in:
NerdNumber9 2019-08-04 21:27:59 -04:00
parent 3dac6366ff
commit cd5545284e
7 changed files with 95 additions and 34 deletions

View File

@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.data.updater.UpdaterJob
import eu.kanade.tachiyomi.util.LocaleHelper import eu.kanade.tachiyomi.util.LocaleHelper
import exh.debug.DebugToggles
import exh.log.CrashlyticsPrinter import exh.log.CrashlyticsPrinter
import exh.log.EHDebugModeOverlay import exh.log.EHDebugModeOverlay
import exh.log.EHLogLevel import exh.log.EHLogLevel
@ -53,7 +54,7 @@ open class App : Application() {
setupNotificationChannels() setupNotificationChannels()
GlobalScope.launch { deleteOldMetadataRealm() } // Delete old metadata DB (EH) GlobalScope.launch { deleteOldMetadataRealm() } // Delete old metadata DB (EH)
Reprint.initialize(this) //Setup fingerprint (EH) Reprint.initialize(this) //Setup fingerprint (EH)
if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "releaseTest") { if((BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "releaseTest") && DebugToggles.ENABLE_DEBUG_OVERLAY.enabled) {
setupDebugOverlay() setupDebugOverlay()
} }

View File

@ -19,8 +19,8 @@ fun Preference<Boolean>.invert(): Boolean = getOrDefault().let { set(!it); !it }
class PreferencesHelper(val context: Context) { class PreferencesHelper(val context: Context) {
private val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
private val rxPrefs = RxSharedPreferences.create(prefs) val rxPrefs = RxSharedPreferences.create(prefs)
private val defaultDownloadsDir = Uri.fromFile( private val defaultDownloadsDir = Uri.fromFile(
File(Environment.getExternalStorageDirectory().absolutePath + File.separator + File(Environment.getExternalStorageDirectory().absolutePath + File.separator +

View File

@ -22,6 +22,7 @@ import exh.metadata.metadata.EHentaiSearchMetadata.Companion.TAG_TYPE_NORMAL
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
import exh.metadata.nullIfBlank import exh.metadata.nullIfBlank
import exh.metadata.parseHumanReadableByteCount import exh.metadata.parseHumanReadableByteCount
import exh.debug.DebugToggles
import exh.ui.login.LoginController import exh.ui.login.LoginController
import exh.util.UriFilter import exh.util.UriFilter
import exh.util.UriGroup import exh.util.UriGroup
@ -321,7 +322,7 @@ class EHentai(override val id: Long,
// Pull to most recent // Pull to most recent
val doc = response.asJsoup() val doc = response.asJsoup()
val newerGallery = doc.select("#gnd a").lastOrNull() val newerGallery = doc.select("#gnd a").lastOrNull()
val pre = if(newerGallery != null) { val pre = if(newerGallery != null && DebugToggles.PULL_TO_ROOT_WHEN_LOADING_EXH_MANGA_DETAILS.enabled) {
manga.url = EHentaiSearchMetadata.normalizeUrl(newerGallery.attr("href")) manga.url = EHentaiSearchMetadata.normalizeUrl(newerGallery.attr("href"))
client.newCall(mangaDetailsRequest(manga)) client.newCall(mangaDetailsRequest(manga))
.asObservableSuccess().map { it.asJsoup() } .asObservableSuccess().map { it.asJsoup() }

View File

@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
import eu.kanade.tachiyomi.util.syncChaptersWithSource import eu.kanade.tachiyomi.util.syncChaptersWithSource
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.eh.EHentaiUpdateHelper import exh.eh.EHentaiUpdateHelper
import exh.isEhBasedSource import exh.isEhBasedSource
import rx.Observable import rx.Observable
@ -115,7 +116,8 @@ class ChaptersPresenter(
// EXH --> // EXH -->
if(chapters.isNotEmpty() if(chapters.isNotEmpty()
&& (source.id == EXH_SOURCE_ID || source.id == EH_SOURCE_ID)) { && (source.id == EXH_SOURCE_ID || source.id == EH_SOURCE_ID)
&& DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) {
// Check for gallery in library and accept manga with lowest id // Check for gallery in library and accept manga with lowest id
// Find chapters sharing same root // Find chapters sharing same root
add(updateHelper.findAcceptedRootAndDiscardOthers(chapters) add(updateHelper.findAcceptedRootAndDiscardOthers(chapters)

View File

@ -0,0 +1,22 @@
package exh.debug
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import uy.kohesive.injekt.injectLazy
enum class DebugToggles(val default: Boolean) {
ENABLE_EXH_ROOT_REDIRECT(true),
ENABLE_DEBUG_OVERLAY(true),
PULL_TO_ROOT_WHEN_LOADING_EXH_MANGA_DETAILS(true);
val prefKey = "eh_debug_toggle_${name.toLowerCase()}"
var enabled: Boolean
get() = prefs.rxPrefs.getBoolean(prefKey, default).get()!!
set(value) {
prefs.rxPrefs.getBoolean(prefKey).set(value)
}
companion object {
private val prefs: PreferencesHelper by injectLazy()
}
}

View File

@ -2,13 +2,12 @@ package exh.debug
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.support.v7.preference.PreferenceScreen import android.support.v7.preference.PreferenceScreen
import android.text.Html
import android.util.Log import android.util.Log
import android.widget.HorizontalScrollView import android.widget.HorizontalScrollView
import android.widget.TextView import android.widget.TextView
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.*
import eu.kanade.tachiyomi.ui.setting.onClick
import eu.kanade.tachiyomi.ui.setting.preference
import kotlin.reflect.KVisibility import kotlin.reflect.KVisibility
import kotlin.reflect.full.declaredFunctions import kotlin.reflect.full.declaredFunctions
@ -17,33 +16,55 @@ class SettingsDebugController : SettingsController() {
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
title = "DEBUG MENU" title = "DEBUG MENU"
DebugFunctions::class.declaredFunctions.filter { preferenceCategory {
it.visibility == KVisibility.PUBLIC title = "Functions"
}.forEach {
preference {
title = it.name.replace(Regex("(.)(\\p{Upper})"), "$1 $2").toLowerCase().capitalize()
isPersistent = false
onClick { DebugFunctions::class.declaredFunctions.filter {
val view = TextView(context) it.visibility == KVisibility.PUBLIC
view.setHorizontallyScrolling(true) }.forEach {
view.setTextIsSelectable(true) preference {
title = it.name.replace(Regex("(.)(\\p{Upper})"), "$1 $2").toLowerCase().capitalize()
isPersistent = false
val hView = HorizontalScrollView(context) onClick {
hView.addView(view) val view = TextView(context)
view.setHorizontallyScrolling(true)
view.setTextIsSelectable(true)
try { val hView = HorizontalScrollView(context)
val result = it.call(DebugFunctions) hView.addView(view)
view.text = "Function returned result:\n\n$result"
MaterialDialog.Builder(context) try {
.customView(hView, true) val result = it.call(DebugFunctions)
} catch(t: Throwable) { view.text = "Function returned result:\n\n$result"
view.text = "Function threw exception:\n\n${Log.getStackTraceString(t)}" MaterialDialog.Builder(context)
MaterialDialog.Builder(context) .customView(hView, true)
.customView(hView, true) } catch(t: Throwable) {
}.show() view.text = "Function threw exception:\n\n${Log.getStackTraceString(t)}"
MaterialDialog.Builder(context)
.customView(hView, true)
}.show()
}
}
}
}
preferenceCategory {
title = "Toggles"
DebugToggles.values().forEach {
switchPreference {
title = it.name.replace('_', ' ').toLowerCase().capitalize()
key = it.prefKey
defaultValue = it.default
summaryOn = if(it.default) "" else MODIFIED_TEXT
summaryOff = if(it.default) MODIFIED_TEXT else ""
} }
} }
} }
} }
companion object {
private val MODIFIED_TEXT = Html.fromHtml("<font color='red'>MODIFIED</font>")
}
} }

View File

@ -57,6 +57,8 @@ class EHentaiUpdateHelper(context: Context) {
return chainsWithAccepted.map { (accepted, chains) -> return chainsWithAccepted.map { (accepted, chains) ->
val toDiscard = chains.filter { it.manga.favorite && it.manga.id != accepted.manga.id } val toDiscard = chains.filter { it.manga.favorite && it.manga.id != accepted.manga.id }
val chainsAsChapters = chains.flatMap { it.chapters }
if(toDiscard.isNotEmpty()) { if(toDiscard.isNotEmpty()) {
// Copy chain chapters to curChapters // Copy chain chapters to curChapters
val newChapters = toDiscard val newChapters = toDiscard
@ -81,9 +83,16 @@ class EHentaiUpdateHelper(context: Context) {
.fold(accepted.chapters) { curChapters, chapter -> .fold(accepted.chapters) { curChapters, chapter ->
val existing = curChapters.find { it.url == chapter.url } val existing = curChapters.find { it.url == chapter.url }
val newLastPageRead = chainsAsChapters.filter { it.date_upload < chapter.date_upload }.maxBy {
it.last_page_read
}?.last_page_read
if (existing != null) { if (existing != null) {
existing.read = existing.read || chapter.read existing.read = existing.read || chapter.read
existing.last_page_read = existing.last_page_read.coerceAtLeast(chapter.last_page_read) existing.last_page_read = existing.last_page_read.coerceAtLeast(chapter.last_page_read)
if(newLastPageRead != null && existing.last_page_read <= 0) {
existing.last_page_read = newLastPageRead
}
existing.bookmark = existing.bookmark || chapter.bookmark existing.bookmark = existing.bookmark || chapter.bookmark
curChapters curChapters
} else if (chapter.date_upload > 0) { // Ignore chapters using the old system } else if (chapter.date_upload > 0) { // Ignore chapters using the old system
@ -93,19 +102,24 @@ class EHentaiUpdateHelper(context: Context) {
name = chapter.name name = chapter.name
read = chapter.read read = chapter.read
bookmark = chapter.bookmark bookmark = chapter.bookmark
last_page_read = chapter.last_page_read last_page_read = chapter.last_page_read
if(newLastPageRead != null && last_page_read <= 0) {
last_page_read = newLastPageRead
}
date_fetch = chapter.date_fetch date_fetch = chapter.date_fetch
date_upload = chapter.date_upload date_upload = chapter.date_upload
} }
} else curChapters } else curChapters
} }
.filter { it.date_upload <= 0 } // Ignore chapters using the old system (filter after to prevent dupes from insert) .filter { it.date_upload > 0 } // Ignore chapters using the old system (filter after to prevent dupes from insert)
.sortedBy { it.date_upload } .sortedBy { it.date_upload }
.apply { .apply {
withIndex().map { (index, chapter) -> mapIndexed { index, chapter ->
chapter.name = "v${index + 1}: " + chapter.name.substringAfter(" ") chapter.name = "v${index + 1}: " + chapter.name.substringAfter(" ")
chapter.chapter_number = index + 1f chapter.chapter_number = index + 1f
chapter.source_order = index chapter.source_order = lastIndex - index
} }
} }
@ -119,7 +133,7 @@ class EHentaiUpdateHelper(context: Context) {
// Apply changes to all manga // Apply changes to all manga
db.insertMangas(rootsToMutate.map { it.manga }).executeAsBlocking() db.insertMangas(rootsToMutate.map { it.manga }).executeAsBlocking()
// Insert new chapters for accepted manga // Insert new chapters for accepted manga
db.insertChapters(newAccepted.chapters) db.insertChapters(newAccepted.chapters).executeAsBlocking()
// Copy categories from all chains to accepted manga // Copy categories from all chains to accepted manga
val newCategories = rootsToMutate.flatMap { val newCategories = rootsToMutate.flatMap {
db.getCategoriesForManga(it.manga).executeAsBlocking() db.getCategoriesForManga(it.manga).executeAsBlocking()