diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e1e3a3686..a9a88be0e 100755 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,8 +1,7 @@ -dontobfuscate -dontwarn eu.kanade.tachiyomi.** --keep class eu.kanade.tachiyomi.** --keep class eu.kanade.tachiyomi.source.model.** { *; } +-keep class eu.kanade.tachiyomi.** { *; } -keep class com.hippo.image.** { *; } -keep interface com.hippo.image.** { *; } @@ -112,3 +111,20 @@ # Keep google stuff -dontwarn com.google.android.gms.** -dontwarn com.google.firebase.** + +# Jackson +# Proguard configuration for Jackson 2.x +-keep class com.fasterxml.jackson.databind.ObjectMapper { + public ; + protected ; +} +-keep class com.fasterxml.jackson.databind.ObjectWriter { + public ** writeValueAsString(**); +} +-keepnames class com.fasterxml.jackson.** { *; } +-dontwarn com.fasterxml.jackson.databind.** +# Proguard configuration for Jackson 2.x +-dontwarn com.fasterxml.jackson.databind.** +-keepclassmembers class * { + @com.fasterxml.jackson.annotation.* *; +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 25d21c1d6..56a92be55 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -250,5 +250,5 @@ class PreferencesHelper(val context: Context) { fun eh_lastVersionCode() = rxPrefs.getInteger("eh_last_version_code", 0) - fun eh_savedSearches() = rxPrefs.getString("eh_saved_searches", "") + fun eh_savedSearches() = rxPrefs.getStringSet("eh_saved_searches", emptySet()) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt index 3139ec8fd..cbdd9df8e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt @@ -143,30 +143,21 @@ open class BrowseCatalogueController(bundle: Bundle) : drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.END) // EXH --> - presenter.loadSearches()?.let { - navView.setSavedSearches(it) - } ?: run { - MaterialDialog.Builder(navView.context) - .title("Failed to load saved searches!") - .content("An error occurred while loading your saved searches.") - .cancelable(true) - .canceledOnTouchOutside(true) - .show() - } + navView.setSavedSearches(presenter.loadSearches().map { it.second }) navView.onSaveClicked = { MaterialDialog.Builder(navView.context) .title("Save current search query?") .input("My search name", "") { _, searchName -> - val oldSavedSearches = presenter.loadSearches() ?: emptyList() + val oldSavedSearches = presenter.loadSearches() if(searchName.isNotBlank() && oldSavedSearches.size < CatalogueNavigationView.MAX_SAVED_SEARCHES) { - val newSearches = oldSavedSearches + EXHSavedSearch( + val newSearches = oldSavedSearches + (presenter.source.id to EXHSavedSearch( searchName.toString().trim(), presenter.query, presenter.sourceFilters.toList() - ) + )) presenter.saveSearches(newSearches) - navView.setSavedSearches(newSearches) + navView.setSavedSearches(newSearches.map { it.second }) } } .positiveText("Save") @@ -179,7 +170,9 @@ open class BrowseCatalogueController(bundle: Bundle) : navView.onSavedSearchClicked = cb@{ indexToSearch -> val savedSearches = presenter.loadSearches() - if(savedSearches == null) { + val search = savedSearches.getOrNull(indexToSearch) + + if(search == null) { MaterialDialog.Builder(navView.context) .title("Failed to load saved searches!") .content("An error occurred while loading your saved searches.") @@ -189,23 +182,23 @@ open class BrowseCatalogueController(bundle: Bundle) : return@cb } - val search = savedSearches[indexToSearch] - - presenter.sourceFilters = FilterList(search.filterList) + presenter.sourceFilters = FilterList(search.second.filterList) navView.setFilters(presenter.filterItems) val allDefault = presenter.sourceFilters == presenter.source.getFilterList() showProgressBar() adapter?.clear() drawer.closeDrawer(Gravity.END) - presenter.restartPager(search.query, if (allDefault) FilterList() else presenter.sourceFilters) + presenter.restartPager(search.second.query, if (allDefault) FilterList() else presenter.sourceFilters) activity?.invalidateOptionsMenu() } navView.onSavedSearchDeleteClicked = cb@{ indexToDelete -> val savedSearches = presenter.loadSearches() - if(savedSearches == null) { + val search = savedSearches.getOrNull(indexToDelete) + + if(search == null) { MaterialDialog.Builder(navView.context) .title("Failed to delete saved search!") .content("An error occurred while deleting the search.") @@ -215,11 +208,9 @@ open class BrowseCatalogueController(bundle: Bundle) : return@cb } - val search = savedSearches[indexToDelete] - MaterialDialog.Builder(navView.context) .title("Delete saved search query?") - .content("Are you sure you wish to delete your saved search query: '${search.name}'?") + .content("Are you sure you wish to delete your saved search query: '${search.second.name}'?") .positiveText("Cancel") .negativeText("Confirm") .onNegative { _, _ -> @@ -227,7 +218,7 @@ open class BrowseCatalogueController(bundle: Bundle) : index != indexToDelete } presenter.saveSearches(newSearches) - navView.setSavedSearches(newSearches) + navView.setSavedSearches(newSearches.map { it.second }) } .cancelable(true) .canceledOnTouchOutside(true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt index 083af0919..9d2306dd3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt @@ -1,7 +1,12 @@ package eu.kanade.tachiyomi.ui.catalogue.browse import android.os.Bundle +import com.fasterxml.jackson.annotation.JsonAutoDetect +import com.fasterxml.jackson.annotation.PropertyAccessor import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.type.TypeFactory import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import eu.davidea.flexibleadapter.items.IFlexible @@ -29,6 +34,7 @@ import rx.subjects.PublishSubject import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy /** * Presenter of [BrowseCatalogueController]. @@ -380,22 +386,37 @@ open class BrowseCataloguePresenter( } // EXH --> - private val mapper = jacksonObjectMapper().enableDefaultTyping() - fun saveSearches(searches: List) { - val serialized = mapper.writeValueAsString(searches.toTypedArray()) + private val sourceManager: SourceManager by injectLazy() + private fun mapper() = jacksonObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL) + .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE) + .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + fun saveSearches(searches: List>) { + val m = mapper() + val serialized = searches.map { + "${it.first}:" + m.writeValueAsString(it.second) + }.toSet() prefs.eh_savedSearches().set(serialized) } - fun loadSearches(): List? { + fun loadSearches(): List> { val loaded = prefs.eh_savedSearches().getOrDefault() - return try { - if (!loaded.isEmpty()) mapper.readValue>(loaded).toList() - else emptyList() - } catch(t: JsonProcessingException) { - // Load failed - Timber.e(t, "Failed to load saved searches!") - null - } + return loaded.map { + try { + val id = it.substringBefore(':').toLong() + val content = it.substringAfter(':') + val newMapper = mapper() + .setTypeFactory(TypeFactory.defaultInstance() + .withClassLoader(sourceManager.getOrStub(id).javaClass.classLoader)) + id to newMapper.readValue(content) + + } catch(t: JsonProcessingException) { + // Load failed + Timber.e(t, "Failed to load saved search!") + t.printStackTrace() + null + } + }.filterNotNull() } // EXH <-- } diff --git a/app/src/main/java/exh/EHSourceHelpers.kt b/app/src/main/java/exh/EHSourceHelpers.kt index 22befc160..0bb077437 100755 --- a/app/src/main/java/exh/EHSourceHelpers.kt +++ b/app/src/main/java/exh/EHSourceHelpers.kt @@ -18,7 +18,6 @@ const val PERV_EDEN_IT_SOURCE_ID = LEWD_SOURCE_SERIES + 6 const val NHENTAI_SOURCE_ID = LEWD_SOURCE_SERIES + 7 -@Deprecated("Now a delegated source") val HENTAI_CAFE_SOURCE_ID = SourceManager.DELEGATED_SOURCES.entries.find { it.value.newSourceClass == HentaiCafe::class }!!.value.sourceId diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index b336d8bef..27a268294 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -34,5 +34,5 @@ object DebugFunctions { it.favorite && db.getSearchMetadataForManga(it.id!!).executeAsBlocking() == null } - fun clearSavedSearches() = prefs.eh_savedSearches().set("") + fun clearSavedSearches() = prefs.eh_savedSearches().set(emptySet()) } \ No newline at end of file