Release version v6.1.4

Offload metadata check to background thread
Add search cache
This commit is contained in:
NerdNumber9 2017-08-28 03:20:35 -04:00
parent 1107b95ebd
commit 7053777997
6 changed files with 141 additions and 113 deletions

View File

@ -44,8 +44,8 @@ android {
minSdkVersion 16
targetSdkVersion 25
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionCode 6103
versionName "v6.1.3-EH"
versionCode 6104
versionName "v6.1.4-EH"
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.library
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.data.database.models.Manga
import exh.*
import exh.metadata.metadataClass
import exh.metadata.models.ExGalleryMetadata
import exh.metadata.models.NHentaiMetadata
import exh.metadata.models.PervEdenGalleryMetadata
@ -12,6 +13,7 @@ import exh.search.SearchEngine
import exh.util.defRealm
import io.realm.RealmResults
import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap
import kotlin.concurrent.thread
/**
@ -42,11 +44,9 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
// Sync manga IDs in background (EH)
thread {
//Wait 1s to reduce UI stutter during animations
Thread.sleep(1000)
Thread.sleep(2000)
defRealm {
it.syncMangaIds(list.map {
it.manga
})
it.syncMangaIds(mangas)
}
}
@ -64,93 +64,103 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
fun performFilter() {
if(searchText.isNotBlank()) {
if(cacheText != searchText) {
globalSearchCache.clear()
cacheText = searchText
}
try {
val thisCache = globalSearchCache.getOrPut(view.category.name, {
SearchCache(mangas.size)
})
if(thisCache.ready) {
//Skip everything if cache matches our query exactly
updateDataSet(mangas.filter {
thisCache.cache[it.manga.id] ?: false
})
} else {
thisCache.cache.clear()
val parsedQuery = searchEngine.parseQuery(searchText)
val metadata = view.meta!!.map {
var totalFilteredSize = 0
val metadata = view.controller.meta!!.map {
val meta: RealmResults<out SearchableGalleryMetadata> = if (it.value.isNotEmpty())
searchEngine.filterResults(it.value.where(),
parsedQuery,
it.value.first().titleFields)
.findAllSorted(SearchableGalleryMetadata::mangaId.name)
.findAllSorted(SearchableGalleryMetadata::mangaId.name).apply {
totalFilteredSize += size
}
else
it.value
Pair(it.key, meta)
}.toMap()
// --> Possible data set compare algorithm?
// var curUnfilteredMetaIndex = 0
// var curFilteredMetaIndex = 0
// val res = mangas.sortedBy { it.manga.id }.filter { manga ->
val res = mangas.filter { manga ->
val out = ArrayList<LibraryItem>(mangas.size)
var lewdMatches = 0
for(manga in mangas) {
// --> EH
try {
if (isLewdSource(manga.manga.source)) {
val unfilteredMeta: RealmResults<out SearchableGalleryMetadata>?
val filteredMeta: RealmResults<out SearchableGalleryMetadata>?
when (manga.manga.source) {
EH_SOURCE_ID,
EXH_SOURCE_ID -> {
unfilteredMeta = view.meta!![ExGalleryMetadata::class]
filteredMeta = metadata[ExGalleryMetadata::class]
}
PERV_EDEN_IT_SOURCE_ID,
PERV_EDEN_EN_SOURCE_ID -> {
unfilteredMeta = view.meta!![PervEdenGalleryMetadata::class]
filteredMeta = metadata[PervEdenGalleryMetadata::class]
}
NHENTAI_SOURCE_ID -> {
unfilteredMeta = view.meta!![NHentaiMetadata::class]
filteredMeta = metadata[NHentaiMetadata::class]
}
else -> {
unfilteredMeta = null
filteredMeta = null
}
}
//Stop matching lewd manga if we have matched them all already!
if (lewdMatches >= totalFilteredSize)
continue
/*
--> Possible data set compare algorithm?
val metaClass = manga.manga.metadataClass
val unfilteredMeta = view.controller.meta!![metaClass]
val filteredMeta = metadata[metaClass]
var atUnfilteredMeta = unfilteredMeta?.getOrNull(curUnfilteredMetaIndex)
while(atUnfilteredMeta?.mangaId != null
&& atUnfilteredMeta.mangaId!! < manga.manga.id!!) {
curUnfilteredMetaIndex++
atUnfilteredMeta = unfilteredMeta?.getOrNull(curUnfilteredMetaIndex)
}
if(atUnfilteredMeta?.mangaId == manga.manga.id) {
var atFilteredMeta = filteredMeta?.getOrNull(curFilteredMetaIndex)
while(atFilteredMeta?.mangaId != null
&& atFilteredMeta.mangaId!! < manga.manga.id!!) {
curFilteredMetaIndex++
atFilteredMeta = filteredMeta?.getOrNull(curFilteredMetaIndex)
}
return@filter atFilteredMeta?.mangaId == manga.manga.id
}*/
val hasMeta = unfilteredMeta
val hasMeta = manga.hasMetadata ?: (unfilteredMeta
?.where()
?.equalTo(SearchableGalleryMetadata::mangaId.name, manga.manga.id)
?.count() ?: 0 > 0
if (hasMeta)
return@filter filteredMeta!!.where()
?.count() ?: 0 > 0)
if (hasMeta) {
if (filteredMeta!!.where()
.equalTo(SearchableGalleryMetadata::mangaId.name, manga.manga.id)
.count() > 0
.count() > 0) {
//Metadata match!
lewdMatches++
thisCache.cache[manga.manga.id!!] = true
out += manga
continue
}
}
}
} catch (e: Exception) {
Timber.w(e, "Could not filter manga!", manga.manga)
}
manga.filter(searchText)
//Fallback to regular filter
val filterRes = manga.filter(searchText)
thisCache.cache[manga.manga.id!!] = filterRes
if(filterRes) out += manga
// <-- EH
}
updateDataSet(res)
thisCache.ready = true
updateDataSet(out)
}
} catch(e: Exception) {
Timber.w(e, "Could not filter mangas!")
updateDataSet(mangas)
}
} else {
globalSearchCache.clear()
updateDataSet(mangas)
}
}
class SearchCache(size: Int) {
var ready = false
var cache = HashMap<Long, Boolean>(size)
}
companion object {
var cacheText: String? = null
val globalSearchCache = ConcurrentHashMap<String, SearchCache>()
}
}

View File

@ -16,14 +16,9 @@ import eu.kanade.tachiyomi.util.inflate
import eu.kanade.tachiyomi.util.plusAssign
import eu.kanade.tachiyomi.util.toast
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import exh.metadata.loadAllMetadata
import exh.metadata.models.SearchableGalleryMetadata
import io.realm.Realm
import io.realm.RealmResults
import kotlinx.android.synthetic.main.library_category.view.*
import rx.subscriptions.CompositeSubscription
import uy.kohesive.injekt.injectLazy
import kotlin.reflect.KClass
/**
* Fragment containing the library manga for a certain category.
@ -41,7 +36,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
/**
* The fragment containing this view.
*/
private lateinit var controller: LibraryController
lateinit var controller: LibraryController
/**
* Category for this view.
@ -64,14 +59,6 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
*/
private var subscriptions = CompositeSubscription()
// --> EH
// Cached Realm instance
var realm: Realm? = null
// Cached metadata (auto-updating)
var meta: Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>>? = null
// <-- EH
fun onCreate(controller: LibraryController) {
this.controller = controller
@ -139,22 +126,9 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
subscriptions.clear()
}
override fun onAttachedToWindow() {
// --> EH
realm?.close()
realm = Realm.getDefaultInstance()?.apply {
meta = loadAllMetadata()
}
// <-- EH
super.onAttachedToWindow()
}
override fun onDetachedFromWindow() {
subscriptions.clear()
// --> EH
meta = null
realm?.close()
// <-- EH
super.onDetachedFromWindow()
}
@ -270,5 +244,4 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
controller.setSelection(item.manga, !adapter.isSelected(position))
controller.invalidateActionMode()
}
}

View File

@ -36,6 +36,10 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.inflate
import eu.kanade.tachiyomi.util.toast
import eu.kanade.tachiyomi.widget.DrawerSwipeCloseListener
import exh.metadata.loadAllMetadata
import exh.metadata.models.SearchableGalleryMetadata
import io.realm.Realm
import io.realm.RealmResults
import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.library_controller.view.*
import rx.Subscription
@ -45,6 +49,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.util.concurrent.TimeUnit
import kotlin.reflect.KClass
class LibraryController(
@ -126,6 +131,13 @@ class LibraryController(
private var tabsVisibilitySubscription: Subscription? = null
// --> EH
//Cached realm
var realm: Realm? = null
//Cached metadata
var meta: Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>>? = null
// <-- EH
init {
setHasOptionsMenu(true)
}
@ -142,6 +154,16 @@ class LibraryController(
return inflater.inflate(R.layout.library_controller, container, false)
}
// --> EH
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View {
//Load realm
realm = Realm.getDefaultInstance()?.apply {
meta = loadAllMetadata()
}
return super.onCreateView(inflater, container, savedViewState)
}
// <-- EH
override fun onViewCreated(view: View, savedViewState: Bundle?) {
super.onViewCreated(view, savedViewState)
@ -183,6 +205,12 @@ class LibraryController(
actionMode = null
tabsVisibilitySubscription?.unsubscribe()
tabsVisibilitySubscription = null
// --> EH
//Clean up realm
realm?.close()
meta = null
// <-- EH
}
override fun createSecondaryDrawer(drawer: DrawerLayout): ViewGroup {

View File

@ -15,6 +15,10 @@ import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
class LibraryItem(val manga: Manga) : AbstractFlexibleItem<LibraryHolder>(), IFilterable {
// Temp metadata holder EH
@Volatile
var hasMetadata: Boolean? = null
override fun getLayoutRes(): Int {
return R.layout.catalogue_grid_item
}

View File

@ -2,6 +2,7 @@ package exh.metadata
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.library.LibraryItem
import exh.*
import exh.metadata.models.ExGalleryMetadata
import exh.metadata.models.NHentaiMetadata
@ -116,16 +117,18 @@ fun Realm.queryMetadataFromManga(manga: Manga,
else -> throw IllegalArgumentException("Unknown source type!")
}
fun Realm.syncMangaIds(mangas: List<Manga>) {
fun Realm.syncMangaIds(mangas: List<LibraryItem>) {
Timber.d("--> EH: Begin syncing ${mangas.size} manga IDs...")
executeTransaction {
mangas.filter {
isLewdSource(it.source)
isLewdSource(it.manga.source)
}.forEach { manga ->
try {
queryMetadataFromManga(manga).findFirst()?.let { meta ->
meta.mangaId = manga.id
}
manga.hasMetadata =
queryMetadataFromManga(manga.manga).findFirst()?.let { meta ->
meta.mangaId = manga.manga.id
true
} ?: false
} catch(e: Exception) {
Timber.w(e, "Error syncing manga IDs! Ignoring...")
}
@ -133,3 +136,13 @@ fun Realm.syncMangaIds(mangas: List<Manga>) {
}
Timber.d("--> EH: Finish syncing ${mangas.size} manga IDs!")
}
val Manga.metadataClass
get() = when (source) {
EH_SOURCE_ID,
EXH_SOURCE_ID -> ExGalleryMetadata::class
PERV_EDEN_IT_SOURCE_ID,
PERV_EDEN_EN_SOURCE_ID -> PervEdenGalleryMetadata::class
NHENTAI_SOURCE_ID -> NHentaiMetadata::class
else -> null
}