mirror of
https://github.com/mihonapp/mihon.git
synced 2025-03-13 08:10:07 +01:00
Release v6.1.3
Make search engine synchronous Offload some search engine tasks to background threads Minor search engine speedups
This commit is contained in:
parent
bcc2ec1668
commit
84121ff901
@ -44,8 +44,8 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
versionCode 6102
|
versionCode 6103
|
||||||
versionName "v6.1.2-EH"
|
versionName "v6.1.3-EH"
|
||||||
|
|
||||||
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
|
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
|
||||||
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
|
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
|
||||||
|
@ -62,7 +62,8 @@ open class App : Application() {
|
|||||||
Realm.init(this)
|
Realm.init(this)
|
||||||
val config = RealmConfiguration.Builder()
|
val config = RealmConfiguration.Builder()
|
||||||
.name("gallery-metadata.realm")
|
.name("gallery-metadata.realm")
|
||||||
.schemaVersion(1)
|
.schemaVersion(2)
|
||||||
|
.deleteRealmIfMigrationNeeded()
|
||||||
.build()
|
.build()
|
||||||
Realm.setDefaultConfiguration(config)
|
Realm.setDefaultConfiguration(config)
|
||||||
|
|
||||||
|
@ -3,16 +3,16 @@ package eu.kanade.tachiyomi.ui.library
|
|||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import exh.*
|
import exh.*
|
||||||
import exh.metadata.loadAllMetadata
|
|
||||||
import exh.metadata.models.ExGalleryMetadata
|
import exh.metadata.models.ExGalleryMetadata
|
||||||
import exh.metadata.models.NHentaiMetadata
|
import exh.metadata.models.NHentaiMetadata
|
||||||
import exh.metadata.models.PervEdenGalleryMetadata
|
import exh.metadata.models.PervEdenGalleryMetadata
|
||||||
|
import exh.metadata.models.SearchableGalleryMetadata
|
||||||
import exh.metadata.queryMetadataFromManga
|
import exh.metadata.queryMetadataFromManga
|
||||||
|
import exh.metadata.syncMangaIds
|
||||||
import exh.search.SearchEngine
|
import exh.search.SearchEngine
|
||||||
import exh.util.defRealm
|
import exh.util.defRealm
|
||||||
import rx.Observable
|
import io.realm.RealmResults
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import timber.log.Timber
|
||||||
import rx.schedulers.Schedulers
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,18 +20,17 @@ import kotlin.concurrent.thread
|
|||||||
*
|
*
|
||||||
* @param view the fragment containing this adapter.
|
* @param view the fragment containing this adapter.
|
||||||
*/
|
*/
|
||||||
class LibraryCategoryAdapter(view: LibraryCategoryView) :
|
class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||||
FlexibleAdapter<LibraryItem>(null, view, true) {
|
FlexibleAdapter<LibraryItem>(null, view, true) {
|
||||||
|
// --> EH
|
||||||
|
private val searchEngine = SearchEngine()
|
||||||
|
// <-- EH
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of manga in this category.
|
* The list of manga in this category.
|
||||||
*/
|
*/
|
||||||
private var mangas: List<LibraryItem> = emptyList()
|
private var mangas: List<LibraryItem> = emptyList()
|
||||||
|
|
||||||
// --> EH
|
|
||||||
private val searchEngine = SearchEngine()
|
|
||||||
// <-- EH
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a list of manga in the adapter.
|
* Sets a list of manga in the adapter.
|
||||||
*
|
*
|
||||||
@ -41,6 +40,17 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) :
|
|||||||
// A copy of manga always unfiltered.
|
// A copy of manga always unfiltered.
|
||||||
mangas = list.toList()
|
mangas = list.toList()
|
||||||
|
|
||||||
|
// Sync manga IDs in background (EH)
|
||||||
|
thread {
|
||||||
|
//Wait 1s to reduce UI stutter during animations
|
||||||
|
Thread.sleep(1000)
|
||||||
|
defRealm {
|
||||||
|
it.syncMangaIds(list.map {
|
||||||
|
it.manga
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
performFilter()
|
performFilter()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,44 +64,95 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun performFilter() {
|
fun performFilter() {
|
||||||
Observable.fromCallable {
|
//TODO Wrap in try catch
|
||||||
defRealm { realm ->
|
if(searchText.isNotBlank()) {
|
||||||
|
try {
|
||||||
val parsedQuery = searchEngine.parseQuery(searchText)
|
val parsedQuery = searchEngine.parseQuery(searchText)
|
||||||
val metadata = realm.loadAllMetadata().map {
|
val metadata = view.meta!!.map {
|
||||||
Pair(it.key, searchEngine.filterResults(it.value, parsedQuery))
|
val meta: RealmResults<out SearchableGalleryMetadata> = if (it.value.isNotEmpty())
|
||||||
}
|
searchEngine.filterResults(it.value.where(),
|
||||||
mangas.filter { manga ->
|
parsedQuery,
|
||||||
|
it.value.first().titleFields)
|
||||||
|
.findAllSorted(SearchableGalleryMetadata::mangaId.name)
|
||||||
|
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 ->
|
||||||
// --> EH
|
// --> EH
|
||||||
if (isLewdSource(manga.manga.source)) {
|
try {
|
||||||
val hasMeta
|
if (isLewdSource(manga.manga.source)) {
|
||||||
= realm.queryMetadataFromManga(manga.manga).count() > 0
|
val unfilteredMeta: RealmResults<out SearchableGalleryMetadata>?
|
||||||
if(hasMeta)
|
val filteredMeta: RealmResults<out SearchableGalleryMetadata>?
|
||||||
metadata.any {
|
when (manga.manga.source) {
|
||||||
when (manga.manga.source) {
|
EH_SOURCE_ID,
|
||||||
EH_SOURCE_ID,
|
EXH_SOURCE_ID -> {
|
||||||
EXH_SOURCE_ID ->
|
unfilteredMeta = view.meta!![ExGalleryMetadata::class]
|
||||||
if (it.first != ExGalleryMetadata::class)
|
filteredMeta = metadata[ExGalleryMetadata::class]
|
||||||
return@any false
|
}
|
||||||
PERV_EDEN_IT_SOURCE_ID,
|
PERV_EDEN_IT_SOURCE_ID,
|
||||||
PERV_EDEN_EN_SOURCE_ID ->
|
PERV_EDEN_EN_SOURCE_ID -> {
|
||||||
if (it.first != PervEdenGalleryMetadata::class)
|
unfilteredMeta = view.meta!![PervEdenGalleryMetadata::class]
|
||||||
return@any false
|
filteredMeta = metadata[PervEdenGalleryMetadata::class]
|
||||||
NHENTAI_SOURCE_ID ->
|
}
|
||||||
if (it.first != NHentaiMetadata::class)
|
NHENTAI_SOURCE_ID -> {
|
||||||
return@any false
|
unfilteredMeta = view.meta!![NHentaiMetadata::class]
|
||||||
|
filteredMeta = metadata[NHentaiMetadata::class]
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
unfilteredMeta = null
|
||||||
|
filteredMeta = null
|
||||||
}
|
}
|
||||||
return@filter realm.queryMetadataFromManga(manga.manga, it.second.where()).count() > 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
--> Possible data set compare algorithm?
|
||||||
|
|
||||||
|
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
|
||||||
|
?.where()
|
||||||
|
?.equalTo(SearchableGalleryMetadata::mangaId.name, manga.manga.id)
|
||||||
|
?.count() ?: 0 > 0
|
||||||
|
if (hasMeta)
|
||||||
|
return@filter filteredMeta!!.where()
|
||||||
|
.equalTo(SearchableGalleryMetadata::mangaId.name, manga.manga.id)
|
||||||
|
.count() > 0
|
||||||
|
}
|
||||||
|
} catch(e: Exception) {
|
||||||
|
Timber.w(e, "Could not filter manga!", manga.manga)
|
||||||
}
|
}
|
||||||
manga.filter(searchText)
|
manga.filter(searchText)
|
||||||
// <-- EH
|
// <-- EH
|
||||||
}
|
}
|
||||||
|
updateDataSet(res)
|
||||||
|
} catch(e: Exception) {
|
||||||
|
Timber.w(e, "Could not filter mangas!")
|
||||||
|
updateDataSet(mangas)
|
||||||
}
|
}
|
||||||
}.subscribeOn(Schedulers.io())
|
} else {
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
updateDataSet(mangas)
|
||||||
.subscribe {
|
}
|
||||||
updateDataSet(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,14 @@ import eu.kanade.tachiyomi.util.inflate
|
|||||||
import eu.kanade.tachiyomi.util.plusAssign
|
import eu.kanade.tachiyomi.util.plusAssign
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
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 kotlinx.android.synthetic.main.library_category.view.*
|
||||||
import rx.subscriptions.CompositeSubscription
|
import rx.subscriptions.CompositeSubscription
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment containing the library manga for a certain category.
|
* Fragment containing the library manga for a certain category.
|
||||||
@ -59,6 +64,14 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
|||||||
*/
|
*/
|
||||||
private var subscriptions = CompositeSubscription()
|
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) {
|
fun onCreate(controller: LibraryController) {
|
||||||
this.controller = controller
|
this.controller = controller
|
||||||
|
|
||||||
@ -102,6 +115,12 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
|||||||
fun onBind(category: Category) {
|
fun onBind(category: Category) {
|
||||||
this.category = category
|
this.category = category
|
||||||
|
|
||||||
|
// Cache Realm (EH)
|
||||||
|
realm?.close()
|
||||||
|
realm = Realm.getDefaultInstance()?.apply {
|
||||||
|
meta = loadAllMetadata()
|
||||||
|
}
|
||||||
|
|
||||||
adapter.mode = if (controller.selectedMangas.isNotEmpty()) {
|
adapter.mode = if (controller.selectedMangas.isNotEmpty()) {
|
||||||
FlexibleAdapter.MODE_MULTI
|
FlexibleAdapter.MODE_MULTI
|
||||||
} else {
|
} else {
|
||||||
@ -126,8 +145,22 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
|||||||
subscriptions.clear()
|
subscriptions.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToWindow() {
|
||||||
|
// --> EH
|
||||||
|
realm?.close()
|
||||||
|
realm = Realm.getDefaultInstance()?.apply {
|
||||||
|
meta = loadAllMetadata()
|
||||||
|
}
|
||||||
|
// <-- EH
|
||||||
|
super.onAttachedToWindow()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDetachedFromWindow() {
|
override fun onDetachedFromWindow() {
|
||||||
subscriptions.clear()
|
subscriptions.clear()
|
||||||
|
// --> EH
|
||||||
|
meta = null
|
||||||
|
realm?.close()
|
||||||
|
// <-- EH
|
||||||
super.onDetachedFromWindow()
|
super.onDetachedFromWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ class LibraryController(
|
|||||||
|
|
||||||
// Debounce search (EH)
|
// Debounce search (EH)
|
||||||
searchView.queryTextChanges()
|
searchView.queryTextChanges()
|
||||||
.debounce(200, TimeUnit.MILLISECONDS)
|
.debounce(350, TimeUnit.MILLISECONDS)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribeUntilDestroy {
|
.subscribeUntilDestroy {
|
||||||
query = it.toString()
|
query = it.toString()
|
||||||
|
@ -12,9 +12,23 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.util.inflate
|
import eu.kanade.tachiyomi.util.inflate
|
||||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||||
|
import exh.*
|
||||||
|
import exh.metadata.ehMetaQueryFromUrl
|
||||||
|
import exh.metadata.models.ExGalleryMetadata
|
||||||
|
import exh.metadata.models.NHentaiMetadata
|
||||||
|
import exh.metadata.models.PervEdenGalleryMetadata
|
||||||
|
import exh.metadata.models.SearchableGalleryMetadata
|
||||||
|
import exh.metadata.nhentaiMetaQueryFromUrl
|
||||||
|
import exh.metadata.pervEdenMetaQueryFromUrl
|
||||||
|
import exh.search.SearchEngine
|
||||||
|
import exh.util.defRealm
|
||||||
|
import io.realm.RealmQuery
|
||||||
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
|
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
|
||||||
|
|
||||||
class LibraryItem(val manga: Manga) : AbstractFlexibleItem<LibraryHolder>(), IFilterable {
|
class LibraryItem(val manga: Manga) : AbstractFlexibleItem<LibraryHolder>(), IFilterable {
|
||||||
|
// --> EH
|
||||||
|
private val searchEngine = SearchEngine()
|
||||||
|
// <-- EH
|
||||||
|
|
||||||
override fun getLayoutRes(): Int {
|
override fun getLayoutRes(): Int {
|
||||||
return R.layout.catalogue_grid_item
|
return R.layout.catalogue_grid_item
|
||||||
@ -53,6 +67,38 @@ class LibraryItem(val manga: Manga) : AbstractFlexibleItem<LibraryHolder>(), IFi
|
|||||||
* @return true if the manga should be included, false otherwise.
|
* @return true if the manga should be included, false otherwise.
|
||||||
*/
|
*/
|
||||||
override fun filter(constraint: String): Boolean {
|
override fun filter(constraint: String): Boolean {
|
||||||
|
defRealm { realm ->
|
||||||
|
if (isLewdSource(manga.source)) {
|
||||||
|
val titleFields: List<String>?
|
||||||
|
var query: RealmQuery<out SearchableGalleryMetadata>?
|
||||||
|
when (manga.source) {
|
||||||
|
EH_SOURCE_ID -> {
|
||||||
|
titleFields = ExGalleryMetadata.TITLE_FIELDS
|
||||||
|
query = realm.ehMetaQueryFromUrl(manga.url, false)
|
||||||
|
}
|
||||||
|
EXH_SOURCE_ID -> {
|
||||||
|
titleFields = ExGalleryMetadata.TITLE_FIELDS
|
||||||
|
query = realm.ehMetaQueryFromUrl(manga.url, true)
|
||||||
|
}
|
||||||
|
PERV_EDEN_IT_SOURCE_ID,
|
||||||
|
PERV_EDEN_EN_SOURCE_ID -> {
|
||||||
|
titleFields = PervEdenGalleryMetadata.TITLE_FIELDS
|
||||||
|
query = realm.pervEdenMetaQueryFromUrl(manga.url, manga.source)
|
||||||
|
}
|
||||||
|
NHENTAI_SOURCE_ID -> {
|
||||||
|
titleFields = NHentaiMetadata.TITLE_FIELDS
|
||||||
|
query = realm.nhentaiMetaQueryFromUrl(manga.url)
|
||||||
|
}
|
||||||
|
else -> return@defRealm
|
||||||
|
}
|
||||||
|
val hasMeta = query!!.count() > 0
|
||||||
|
if(hasMeta) {
|
||||||
|
val parsedQuery = searchEngine.parseQuery(constraint)
|
||||||
|
query = searchEngine.filterResults(query, parsedQuery, titleFields)
|
||||||
|
return@filter query.count() > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return manga.title.contains(constraint, true) ||
|
return manga.title.contains(constraint, true) ||
|
||||||
(manga.author?.contains(constraint, true) ?: false)
|
(manga.author?.contains(constraint, true) ?: false)
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,14 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
|
|||||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||||
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
||||||
|
import exh.metadata.loadAllMetadata
|
||||||
import exh.ui.batchadd.BatchAddController
|
import exh.ui.batchadd.BatchAddController
|
||||||
import exh.ui.lock.LockChangeHandler
|
import exh.ui.lock.LockChangeHandler
|
||||||
import exh.ui.lock.LockController
|
import exh.ui.lock.LockController
|
||||||
import exh.ui.lock.lockEnabled
|
import exh.ui.lock.lockEnabled
|
||||||
import exh.ui.lock.notifyLockSecurity
|
import exh.ui.lock.notifyLockSecurity
|
||||||
import exh.ui.migration.MetadataFetchDialog
|
import exh.ui.migration.MetadataFetchDialog
|
||||||
|
import exh.util.defRealm
|
||||||
import kotlinx.android.synthetic.main.main_activity.*
|
import kotlinx.android.synthetic.main.main_activity.*
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
@ -168,9 +170,12 @@ class MainActivity : BaseActivity() {
|
|||||||
ChangelogDialogController().showDialog(router)
|
ChangelogDialogController().showDialog(router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate metadata to Realm (EH)
|
// Migrate metadata if empty (EH)
|
||||||
if(!preferences.migrateLibraryAsked2().getOrDefault())
|
if(!defRealm {
|
||||||
MetadataFetchDialog().askMigration(this, false)
|
it.loadAllMetadata().any {
|
||||||
|
it.value.isNotEmpty()
|
||||||
|
}
|
||||||
|
}) MetadataFetchDialog().askMigration(this, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import io.realm.Realm
|
|||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import timber.log.Timber
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
fun Realm.ehMetaQueryFromUrl(url: String,
|
fun Realm.ehMetaQueryFromUrl(url: String,
|
||||||
@ -50,7 +51,7 @@ private fun pervEdenSourceToLang(source: Long)
|
|||||||
|
|
||||||
fun Realm.pervEdenMetaQueryFromUrl(url: String,
|
fun Realm.pervEdenMetaQueryFromUrl(url: String,
|
||||||
source: Long,
|
source: Long,
|
||||||
meta: RealmQuery<PervEdenGalleryMetadata>?) =
|
meta: RealmQuery<PervEdenGalleryMetadata>? = null) =
|
||||||
pervEdenMetadataQuery(
|
pervEdenMetadataQuery(
|
||||||
PervEdenGalleryMetadata.pvIdFromUrl(url),
|
PervEdenGalleryMetadata.pvIdFromUrl(url),
|
||||||
source,
|
source,
|
||||||
@ -74,7 +75,7 @@ fun Realm.loadPervEdenAsync(pvId: String, source: Long): Observable<PervEdenGall
|
|||||||
.asObservable()
|
.asObservable()
|
||||||
|
|
||||||
fun Realm.nhentaiMetaQueryFromUrl(url: String,
|
fun Realm.nhentaiMetaQueryFromUrl(url: String,
|
||||||
meta: RealmQuery<NHentaiMetadata>?) =
|
meta: RealmQuery<NHentaiMetadata>? = null) =
|
||||||
nhentaiMetadataQuery(
|
nhentaiMetadataQuery(
|
||||||
NHentaiMetadata.nhIdFromUrl(url),
|
NHentaiMetadata.nhIdFromUrl(url),
|
||||||
meta
|
meta
|
||||||
@ -95,11 +96,13 @@ fun Realm.loadNhentaiAsync(nhId: Long): Observable<NHentaiMetadata?>
|
|||||||
.asObservable()
|
.asObservable()
|
||||||
|
|
||||||
fun Realm.loadAllMetadata(): Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>> =
|
fun Realm.loadAllMetadata(): Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>> =
|
||||||
mapOf(
|
listOf<Pair<KClass<out SearchableGalleryMetadata>, RealmQuery<out SearchableGalleryMetadata>>>(
|
||||||
Pair(ExGalleryMetadata::class, where(ExGalleryMetadata::class.java).findAll()),
|
Pair(ExGalleryMetadata::class, where(ExGalleryMetadata::class.java)),
|
||||||
Pair(NHentaiMetadata::class, where(NHentaiMetadata::class.java).findAll()),
|
Pair(NHentaiMetadata::class, where(NHentaiMetadata::class.java)),
|
||||||
Pair(PervEdenGalleryMetadata::class, where(PervEdenGalleryMetadata::class.java).findAll())
|
Pair(PervEdenGalleryMetadata::class, where(PervEdenGalleryMetadata::class.java))
|
||||||
)
|
).map {
|
||||||
|
Pair(it.first, it.second.findAllSorted(SearchableGalleryMetadata::mangaId.name))
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
fun Realm.queryMetadataFromManga(manga: Manga,
|
fun Realm.queryMetadataFromManga(manga: Manga,
|
||||||
meta: RealmQuery<out SearchableGalleryMetadata>? = null): RealmQuery<out SearchableGalleryMetadata> =
|
meta: RealmQuery<out SearchableGalleryMetadata>? = null): RealmQuery<out SearchableGalleryMetadata> =
|
||||||
@ -112,3 +115,21 @@ fun Realm.queryMetadataFromManga(manga: Manga,
|
|||||||
NHENTAI_SOURCE_ID -> nhentaiMetaQueryFromUrl(manga.url, meta as? RealmQuery<NHentaiMetadata>)
|
NHENTAI_SOURCE_ID -> nhentaiMetaQueryFromUrl(manga.url, meta as? RealmQuery<NHentaiMetadata>)
|
||||||
else -> throw IllegalArgumentException("Unknown source type!")
|
else -> throw IllegalArgumentException("Unknown source type!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Realm.syncMangaIds(mangas: List<Manga>) {
|
||||||
|
Timber.d("--> EH: Begin syncing ${mangas.size} manga IDs...")
|
||||||
|
executeTransaction {
|
||||||
|
mangas.filter {
|
||||||
|
isLewdSource(it.source)
|
||||||
|
}.forEach { manga ->
|
||||||
|
try {
|
||||||
|
queryMetadataFromManga(manga).findFirst()?.let { meta ->
|
||||||
|
meta.mangaId = manga.id
|
||||||
|
}
|
||||||
|
} catch(e: Exception) {
|
||||||
|
Timber.w(e, "Error syncing manga IDs! Ignoring...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timber.d("--> EH: Finish syncing ${mangas.size} manga IDs!")
|
||||||
|
}
|
@ -56,10 +56,10 @@ open class ExGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
override fun getTitles() = listOf(title, altTitle).filterNotNull()
|
override fun getTitles() = listOf(title, altTitle).filterNotNull()
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
override val titleFields = listOf(
|
override val titleFields = TITLE_FIELDS
|
||||||
ExGalleryMetadata::title.name,
|
|
||||||
ExGalleryMetadata::altTitle.name
|
@Index
|
||||||
)
|
override var mangaId: Long? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun splitGalleryUrl(url: String)
|
private fun splitGalleryUrl(url: String)
|
||||||
@ -72,5 +72,10 @@ open class ExGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
|
|
||||||
fun galleryToken(url: String) =
|
fun galleryToken(url: String) =
|
||||||
splitGalleryUrl(url).last()
|
splitGalleryUrl(url).last()
|
||||||
|
|
||||||
|
val TITLE_FIELDS = listOf(
|
||||||
|
ExGalleryMetadata::title.name,
|
||||||
|
ExGalleryMetadata::altTitle.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -53,11 +53,10 @@ open class NHentaiMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
override fun getTitles() = listOf(japaneseTitle, englishTitle, shortTitle).filterNotNull()
|
override fun getTitles() = listOf(japaneseTitle, englishTitle, shortTitle).filterNotNull()
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
override val titleFields = listOf(
|
override val titleFields = TITLE_FIELDS
|
||||||
NHentaiMetadata::japaneseTitle.name,
|
|
||||||
NHentaiMetadata::englishTitle.name,
|
@Index
|
||||||
NHentaiMetadata::shortTitle.name
|
override var mangaId: Long? = null
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val BASE_URL = "https://nhentai.net"
|
val BASE_URL = "https://nhentai.net"
|
||||||
@ -71,6 +70,12 @@ open class NHentaiMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
|
|
||||||
fun nhIdFromUrl(url: String)
|
fun nhIdFromUrl(url: String)
|
||||||
= url.split("/").last { it.isNotBlank() }.toLong()
|
= url.split("/").last { it.isNotBlank() }.toLong()
|
||||||
|
|
||||||
|
val TITLE_FIELDS = listOf(
|
||||||
|
NHentaiMetadata::japaneseTitle.name,
|
||||||
|
NHentaiMetadata::englishTitle.name,
|
||||||
|
NHentaiMetadata::shortTitle.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +45,10 @@ open class PervEdenGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
}).filterNotNull()
|
}).filterNotNull()
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
override val titleFields = listOf(
|
override val titleFields = TITLE_FIELDS
|
||||||
//TODO Somehow include altTitles
|
|
||||||
PervEdenGalleryMetadata::title.name
|
@Index
|
||||||
)
|
override var mangaId: Long? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun splitGalleryUrl(url: String)
|
private fun splitGalleryUrl(url: String)
|
||||||
@ -57,6 +57,11 @@ open class PervEdenGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun pvIdFromUrl(url: String) = splitGalleryUrl(url).last()
|
fun pvIdFromUrl(url: String) = splitGalleryUrl(url).last()
|
||||||
|
|
||||||
|
val TITLE_FIELDS = listOf(
|
||||||
|
//TODO Somehow include altTitles
|
||||||
|
PervEdenGalleryMetadata::title.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,4 +21,6 @@ interface SearchableGalleryMetadata: RealmModel {
|
|||||||
fun getTitles(): List<String>
|
fun getTitles(): List<String>
|
||||||
|
|
||||||
val titleFields: List<String>
|
val titleFields: List<String>
|
||||||
|
|
||||||
|
var mangaId: Long?
|
||||||
}
|
}
|
@ -2,18 +2,17 @@ package exh.search
|
|||||||
|
|
||||||
import exh.metadata.models.SearchableGalleryMetadata
|
import exh.metadata.models.SearchableGalleryMetadata
|
||||||
import exh.metadata.models.Tag
|
import exh.metadata.models.Tag
|
||||||
import exh.util.beginLog
|
|
||||||
import io.realm.Case
|
import io.realm.Case
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmQuery
|
||||||
|
|
||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
|
|
||||||
private val queryCache = mutableMapOf<String, List<QueryComponent>>()
|
private val queryCache = mutableMapOf<String, List<QueryComponent>>()
|
||||||
|
|
||||||
fun filterResults(metadata: RealmResults<out SearchableGalleryMetadata>, query: List<QueryComponent>):
|
fun <T : SearchableGalleryMetadata> filterResults(rQuery: RealmQuery<T>,
|
||||||
RealmResults<out SearchableGalleryMetadata> {
|
query: List<QueryComponent>,
|
||||||
val first = metadata.firstOrNull() ?: return metadata
|
titleFields: List<String>):
|
||||||
val rQuery = metadata.where()//.beginLog(SearchableGalleryMetadata::class.java)
|
RealmQuery<T> {
|
||||||
var queryEmpty = true
|
var queryEmpty = true
|
||||||
|
|
||||||
fun matchTagList(namespace: String?,
|
fun matchTagList(namespace: String?,
|
||||||
@ -59,14 +58,13 @@ class SearchEngine {
|
|||||||
rQuery.beginGroup()
|
rQuery.beginGroup()
|
||||||
|
|
||||||
//Match title
|
//Match title
|
||||||
first.titleFields
|
titleFields.forEachIndexed { index, s ->
|
||||||
.forEachIndexed { index, s ->
|
queryEmpty = false
|
||||||
queryEmpty = false
|
if(index > 0)
|
||||||
if(index > 0)
|
rQuery.or()
|
||||||
rQuery.or()
|
|
||||||
|
|
||||||
rQuery.like(s, component.asLenientTitleQuery(), Case.INSENSITIVE)
|
rQuery.like(s, component.asLenientTitleQuery(), Case.INSENSITIVE)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Match tags
|
//Match tags
|
||||||
matchTagList(null, component, false) //We already deal with exclusions here
|
matchTagList(null, component, false) //We already deal with exclusions here
|
||||||
@ -89,7 +87,7 @@ class SearchEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rQuery.findAll()
|
return rQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseQuery(query: String) = queryCache.getOrPut(query, {
|
fun parseQuery(query: String) = queryCache.getOrPut(query, {
|
||||||
|
@ -88,7 +88,6 @@ class MetadataFetchDialog {
|
|||||||
db.getLibraryMangas().asRxSingle().subscribe {
|
db.getLibraryMangas().asRxSingle().subscribe {
|
||||||
if(!explicit && it.isEmpty()) {
|
if(!explicit && it.isEmpty()) {
|
||||||
//Do not open dialog on startup if no manga
|
//Do not open dialog on startup if no manga
|
||||||
preferenceHelper.migrateLibraryAsked2().set(true)
|
|
||||||
} else {
|
} else {
|
||||||
//Not logged in but have ExHentai galleries
|
//Not logged in but have ExHentai galleries
|
||||||
if (!preferenceHelper.enableExhentai().getOrDefault()) {
|
if (!preferenceHelper.enableExhentai().getOrDefault()) {
|
||||||
@ -109,9 +108,7 @@ class MetadataFetchDialog {
|
|||||||
.onNegative({ _, _ -> adviseMigrationLater(activity) })
|
.onNegative({ _, _ -> adviseMigrationLater(activity) })
|
||||||
.cancelable(false)
|
.cancelable(false)
|
||||||
.canceledOnTouchOutside(false)
|
.canceledOnTouchOutside(false)
|
||||||
.dismissListener {
|
.show()
|
||||||
preferenceHelper.migrateLibraryAsked2().set(true)
|
|
||||||
}.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user