Small cleanup and optimizations, add a coroutine version of insertFlatMetadata

This commit is contained in:
Jobobby04 2021-01-20 21:00:23 -05:00
parent e6d62dd1dc
commit 0a4fcb480d
25 changed files with 137 additions and 308 deletions

View File

@ -36,7 +36,7 @@ import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.source.online.all.MergedSource
import exh.MERGED_SOURCE_ID import exh.MERGED_SOURCE_ID
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.savedsearches.JsonSavedSearch import exh.savedsearches.JsonSavedSearch
import exh.source.getMainSource import exh.source.getMainSource
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
@ -527,12 +527,12 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
} }
} }
internal fun restoreFlatMetadata(manga: Manga, backupFlatMetadata: BackupFlatMetadata) { internal suspend fun restoreFlatMetadata(manga: Manga, backupFlatMetadata: BackupFlatMetadata) {
manga.id?.let { mangaId -> manga.id?.let { mangaId ->
databaseHelper.getFlatMetadataForManga(mangaId).executeAsBlocking().let { databaseHelper.getFlatMetadataForManga(mangaId).executeAsBlocking().let {
if (it == null) { if (it == null) {
val flatMetadata = backupFlatMetadata.getFlatMetadata(mangaId) val flatMetadata = backupFlatMetadata.getFlatMetadata(mangaId)
databaseHelper.insertFlatMetadata(flatMetadata).await() databaseHelper.insertFlatMetadataAsync(flatMetadata).await()
} }
} }
} }

View File

@ -223,7 +223,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
} }
} }
private fun restoreExtraForManga(manga: Manga, categories: List<Int>, history: List<BackupHistory>, tracks: List<Track>, backupCategories: List<BackupCategory>, mergedMangaReferences: List<BackupMergedMangaReference>, flatMetadata: BackupFlatMetadata?) { private suspend fun restoreExtraForManga(manga: Manga, categories: List<Int>, history: List<BackupHistory>, tracks: List<Track>, backupCategories: List<BackupCategory>, mergedMangaReferences: List<BackupMergedMangaReference>, flatMetadata: BackupFlatMetadata?) {
// Restore categories // Restore categories
backupManager.restoreCategoriesForManga(manga, categories, backupCategories) backupManager.restoreCategoriesForManga(manga, categories, backupCategories)

View File

@ -32,7 +32,6 @@ import eu.kanade.tachiyomi.ui.library.LibraryGroup
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.chapter.NoChaptersException import eu.kanade.tachiyomi.util.chapter.NoChaptersException
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.lang.await
import eu.kanade.tachiyomi.util.lang.runAsObservable import eu.kanade.tachiyomi.util.lang.runAsObservable
import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.prepUpdateCover
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters import eu.kanade.tachiyomi.util.shouldDownloadNewChapters

View File

@ -10,12 +10,11 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.lang.await
import exh.md.utils.FollowStatus import exh.md.utils.FollowStatus
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.util.executeOnIO import exh.util.executeOnIO
import exh.util.floor import exh.util.floor
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -59,7 +58,7 @@ class MdList(private val context: Context, id: Int) : TrackService(id) {
if (mangaMetadata.follow_status != followStatus.int) { if (mangaMetadata.follow_status != followStatus.int) {
mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), followStatus) mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), followStatus)
mangaMetadata.follow_status = followStatus.int mangaMetadata.follow_status = followStatus.int
db.insertFlatMetadata(mangaMetadata.flatten()).await() db.insertFlatMetadataAsync(mangaMetadata.flatten()).await()
} }
if (track.score.toInt() > 0) { if (track.score.toInt() > 0) {
@ -78,7 +77,7 @@ class MdList(private val context: Context, id: Int) : TrackService(id) {
track.status = FollowStatus.READING.int track.status = FollowStatus.READING.int
mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), newFollowStatus) mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), newFollowStatus)
mangaMetadata.follow_status = newFollowStatus.int mangaMetadata.follow_status = newFollowStatus.int
db.insertFlatMetadata(mangaMetadata.flatten()).await() db.insertFlatMetadataAsync(mangaMetadata.flatten()).await()
} }
mdex.updateReadingProgress(track) mdex.updateReadingProgress(track)

View File

@ -18,8 +18,7 @@ open class Page(
// SY --> // SY -->
var imageUrl = imageUrl var imageUrl = imageUrl
get() { get() {
if (field == null) return null return field?.let { DataSaver.compress(it) }
return DataSaver().compress(field!!)
} }
// SY <-- // SY <--

View File

@ -11,7 +11,8 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadata
import exh.util.await import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.util.executeOnIO
import rx.Completable import rx.Completable
import rx.Single import rx.Single
import tachiyomi.source.model.MangaInfo import tachiyomi.source.model.MangaInfo
@ -79,14 +80,14 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo { suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo {
val mangaId = manga.id() val mangaId = manga.id()
val metadata = if (mangaId != null) { val metadata = if (mangaId != null) {
val flatMetadata = db.getFlatMetadataForManga(mangaId).await() val flatMetadata = db.getFlatMetadataForManga(mangaId).executeOnIO()
flatMetadata?.raise(metaClass) ?: newMetaInstance() flatMetadata?.raise(metaClass) ?: newMetaInstance()
} else newMetaInstance() } else newMetaInstance()
parseInfoIntoMetadata(metadata, input) parseInfoIntoMetadata(metadata, input)
if (mangaId != null) { if (mangaId != null) {
metadata.mangaId = mangaId metadata.mangaId = mangaId
db.insertFlatMetadata(metadata.flatten()).await() db.insertFlatMetadataAsync(metadata.flatten()).await()
} }
return metadata.createMangaInfo(manga) return metadata.createMangaInfo(manga)
@ -134,7 +135,7 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
*/ */
suspend fun fetchOrLoadMetadata(mangaId: Long?, inputProducer: suspend () -> I): M { suspend fun fetchOrLoadMetadata(mangaId: Long?, inputProducer: suspend () -> I): M {
val meta = if (mangaId != null) { val meta = if (mangaId != null) {
val flatMetadata = db.getFlatMetadataForManga(mangaId).await() val flatMetadata = db.getFlatMetadataForManga(mangaId).executeOnIO()
flatMetadata?.raise(metaClass) flatMetadata?.raise(metaClass)
} else { } else {
null null
@ -145,14 +146,14 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
parseInfoIntoMetadata(newMeta, input) parseInfoIntoMetadata(newMeta, input)
if (mangaId != null) { if (mangaId != null) {
newMeta.mangaId = mangaId newMeta.mangaId = mangaId
db.insertFlatMetadata(newMeta.flatten()).let { newMeta } db.insertFlatMetadataAsync(newMeta.flatten()).await().let { newMeta }
} else newMeta } else newMeta
} }
} }
fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>? fun getDescriptionAdapter(controller: MangaController): RecyclerView.Adapter<*>?
suspend fun MangaInfo.id() = db.getManga(key, id).await()?.id suspend fun MangaInfo.id() = db.getManga(key, id).executeOnIO()?.id
val SManga.id get() = (this as? Manga)?.id val SManga.id get() = (this as? Manga)?.id
val SChapter.mangaId get() = (this as? Chapter)?.manga_id val SChapter.mangaId get() = (this as? Chapter)?.manga_id
} }

View File

@ -35,7 +35,7 @@ import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationContr
import eu.kanade.tachiyomi.ui.browse.migration.search.SearchController import eu.kanade.tachiyomi.ui.browse.migration.search.SearchController
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.lang.await import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
@ -49,7 +49,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import timber.log.Timber import timber.log.Timber
@ -115,7 +114,7 @@ class MigrationListController(bundle: Bundle? = null) :
adapter?.updateDataSet(newMigratingManga.map { it.toModal() }) adapter?.updateDataSet(newMigratingManga.map { it.toModal() })
if (migrationsJob == null) { if (migrationsJob == null) {
migrationsJob = viewScope.launch(Dispatchers.IO) { migrationsJob = viewScope.launchIO {
runMigrations(newMigratingManga) runMigrations(newMigratingManga)
} }
} }
@ -128,7 +127,7 @@ class MigrationListController(bundle: Bundle? = null) :
val useSmartSearch = preferences.smartMigration().get() val useSmartSearch = preferences.smartMigration().get()
val sources = preferences.migrationSources().get().split("/").mapNotNull { val sources = preferences.migrationSources().get().split("/").mapNotNull {
val value = it.toLongOrNull() ?: return val value = it.toLongOrNull() ?: return@mapNotNull null
sourceManager.get(value) as? CatalogueSource sourceManager.get(value) as? CatalogueSource
} }
for (manga in mangas) { for (manga in mangas) {

View File

@ -17,11 +17,10 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.BrowseController import eu.kanade.tachiyomi.ui.browse.BrowseController
import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationController import eu.kanade.tachiyomi.ui.browse.migration.advanced.design.PreMigrationController
import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaController import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaController
import eu.kanade.tachiyomi.util.lang.await
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.openInBrowser
import rx.schedulers.Schedulers import exh.util.executeOnIO
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -84,8 +83,9 @@ class MigrationSourcesController :
override fun onItemClick(view: View?, position: Int): Boolean { override fun onItemClick(view: View?, position: Int): Boolean {
val item = adapter?.getItem(position) as? SourceItem ?: return false val item = adapter?.getItem(position) as? SourceItem ?: return false
val controller = MigrationMangaController(item.source.id, item.source.name) val controller = MigrationMangaController(item.source.id, item.source.name)
val parentController = parentController
if (parentController is BrowseController) { if (parentController is BrowseController) {
parentController!!.router.pushController(controller.withFadeTransaction()) parentController.router.pushController(controller.withFadeTransaction())
} else { } else {
router.pushController(controller.withFadeTransaction()) router.pushController(controller.withFadeTransaction())
} }
@ -97,15 +97,18 @@ class MigrationSourcesController :
val item = adapter?.getItem(position) as? SourceItem ?: return val item = adapter?.getItem(position) as? SourceItem ?: return
launchUI { launchUI {
val manga = Injekt.get<DatabaseHelper>().getFavoriteMangas().asRxSingle().await(Schedulers.io()) val manga = Injekt.get<DatabaseHelper>().getFavoriteMangas().executeOnIO()
val sourceMangas = manga.asSequence().filter { it.source == item.source.id }.map { it.id!! }.toList() val sourceMangas = manga.asSequence().filter { it.source == item.source.id }.mapNotNull { it.id }.toList()
withUIContext { withUIContext {
PreMigrationController.navigateToMigration( PreMigrationController.navigateToMigration(
Injekt.get<PreferencesHelper>().skipPreMigration().get(), Injekt.get<PreferencesHelper>().skipPreMigration().get(),
if (parentController is BrowseController) { run {
parentController!!.router val parentController = parentController
} else { if (parentController is BrowseController) {
router parentController.router
} else {
router
}
}, },
sourceMangas sourceMangas
) )

View File

@ -208,7 +208,7 @@ class EditMangaDialog : DialogController {
addView(addTagChip) addView(addTagChip)
} }
private fun ChipGroup.getTextStrings(): List<String>? = children.mapNotNull { private fun ChipGroup.getTextStrings(): List<String> = children.mapNotNull {
if (it is Chip && !it.text.toString().contains(context.getString(R.string.add_tag), ignoreCase = true)) { if (it is Chip && !it.text.toString().contains(context.getString(R.string.add_tag), ignoreCase = true)) {
it.text.toString() it.text.toString()
} else null } else null

View File

@ -52,7 +52,7 @@ import exh.merged.sql.models.MergedMangaReference
import exh.metadata.metadata.base.FlatMetadata import exh.metadata.metadata.base.FlatMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.source.getMainSource import exh.source.getMainSource
import exh.util.shouldDeleteChapters import exh.util.shouldDeleteChapters
import exh.util.trimOrNull import exh.util.trimOrNull
@ -1002,11 +1002,11 @@ class MangaPresenter(
} }
// SY --> // SY -->
fun setScanlatorFilter(filteredScanlators: Set<String>) { suspend fun setScanlatorFilter(filteredScanlators: Set<String>) {
val meta = meta ?: return val meta = meta ?: return
meta.filteredScanlators = if (filteredScanlators.size == allChapterScanlators.size) null else MdUtil.getScanlatorString(filteredScanlators) meta.filteredScanlators = if (filteredScanlators.size == allChapterScanlators.size) null else MdUtil.getScanlatorString(filteredScanlators)
meta.flatten().let { meta.flatten().let {
db.insertFlatMetadata(it).await() db.insertFlatMetadataAsync(it).await()
} }
refreshChapters() refreshChapters()
} }

View File

@ -11,6 +11,8 @@ 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.source.online.MetadataSource import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.ui.manga.MangaPresenter import eu.kanade.tachiyomi.ui.manga.MangaPresenter
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.popupMenu import eu.kanade.tachiyomi.util.view.popupMenu
import eu.kanade.tachiyomi.widget.ExtendedNavigationView import eu.kanade.tachiyomi.widget.ExtendedNavigationView
@ -19,6 +21,7 @@ import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
import exh.source.getMainSource import exh.source.getMainSource
import kotlinx.coroutines.supervisorScope
class ChaptersSettingsSheet( class ChaptersSettingsSheet(
private val router: Router, private val router: Router,
@ -132,13 +135,21 @@ class ChaptersSettingsSheet(
MaterialDialog(context) MaterialDialog(context)
.title(R.string.select_scanlators) .title(R.string.select_scanlators)
.listItemsMultiChoice(items = presenter.allChapterScanlators.toList(), initialSelection = preselected) { _, selections, _ -> .listItemsMultiChoice(items = presenter.allChapterScanlators.toList(), initialSelection = preselected) { _, selections, _ ->
val selected = selections.map { scanlators[it] }.toSet() launchIO {
presenter.setScanlatorFilter(selected) supervisorScope {
onGroupClicked(this) val selected = selections.map { scanlators[it] }.toSet()
presenter.setScanlatorFilter(selected)
withUIContext { onGroupClicked(this@FilterGroup) }
}
}
} }
.negativeButton(R.string.action_reset) { .negativeButton(R.string.action_reset) {
presenter.setScanlatorFilter(presenter.allChapterScanlators) launchIO {
onGroupClicked(this) supervisorScope {
presenter.setScanlatorFilter(presenter.allChapterScanlators)
withUIContext { onGroupClicked(this@FilterGroup) }
}
}
} }
.positiveButton(android.R.string.ok) .positiveButton(android.R.string.ok)
.show() .show()

View File

@ -71,6 +71,7 @@ import eu.kanade.tachiyomi.widget.SimpleAnimationListener
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
import exh.isEhBasedSource import exh.isEhBasedSource
import exh.util.defaultReaderType import exh.util.defaultReaderType
import exh.util.mangaType
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -729,7 +730,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
binding.viewerContainer.addView(newViewer.getView()) binding.viewerContainer.addView(newViewer.getView())
// SY --> // SY -->
val defaultReaderType = manga.defaultReaderType() val defaultReaderType = manga.defaultReaderType(manga.mangaType(sourceName = sourceManager.getOrStub(manga.source).name))
if (preferences.useAutoWebtoon().get() && manga.viewer == 0 && defaultReaderType != null && defaultReaderType == WEBTOON) { if (preferences.useAutoWebtoon().get() && manga.viewer == 0 && defaultReaderType != null && defaultReaderType == WEBTOON) {
binding.root.snack(resources.getString(R.string.eh_auto_webtoon_snack), Snackbar.LENGTH_LONG) binding.root.snack(resources.getString(R.string.eh_auto_webtoon_snack), Snackbar.LENGTH_LONG)
} else if (preferences.showReadingMode()) { } else if (preferences.showReadingMode()) {

View File

@ -44,6 +44,7 @@ import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.source.getMainSource import exh.source.getMainSource
import exh.util.defaultReaderType import exh.util.defaultReaderType
import exh.util.mangaType
import exh.util.shouldDeleteChapters import exh.util.shouldDeleteChapters
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
@ -598,7 +599,7 @@ class ReaderPresenter(
val manga = manga ?: return preferences.defaultViewer() val manga = manga ?: return preferences.defaultViewer()
// SY --> // SY -->
return if (manga.viewer == 0 && preferences.useAutoWebtoon().get()) { return if (manga.viewer == 0 && preferences.useAutoWebtoon().get()) {
manga.defaultReaderType() ?: if (manga.viewer == 0) preferences.defaultViewer() else manga.viewer manga.defaultReaderType(manga.mangaType(sourceName = sourceManager.getOrStub(manga.source).name)) ?: if (manga.viewer == 0) preferences.defaultViewer() else manga.viewer
} else if (manga.viewer == 0) { } else if (manga.viewer == 0) {
preferences.defaultViewer() preferences.defaultViewer()
} else { } else {

View File

@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.util.lang.await
import exh.EH_SOURCE_ID import exh.EH_SOURCE_ID
import exh.EXHMigrations import exh.EXHMigrations
import exh.EXH_SOURCE_ID import exh.EXH_SOURCE_ID
@ -18,7 +17,7 @@ import exh.eh.EHentaiThrottleManager
import exh.eh.EHentaiUpdateWorker import exh.eh.EHentaiUpdateWorker
import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.savedsearches.JsonSavedSearch import exh.savedsearches.JsonSavedSearch
import exh.util.cancellable import exh.util.cancellable
import exh.util.executeOnIO import exh.util.executeOnIO
@ -64,7 +63,7 @@ object DebugFunctions {
val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise<EHentaiSearchMetadata>() ?: return@forEach val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise<EHentaiSearchMetadata>() ?: return@forEach
// remove age flag // remove age flag
meta.aged = false meta.aged = false
db.insertFlatMetadata(meta.flatten()).await() db.insertFlatMetadataAsync(meta.flatten()).await()
} }
} }
} }

View File

@ -19,14 +19,13 @@ import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.source.online.all.EHentai
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.lang.await
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.debug.DebugToggles
import exh.eh.EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION import exh.eh.EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION
import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.util.cancellable import exh.util.cancellable
import exh.util.executeOnIO import exh.util.executeOnIO
import exh.util.jobScheduler import exh.util.jobScheduler
@ -280,7 +279,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope {
// Age dead galleries // Age dead galleries
logger.d("Aged %s - notfound", manga.id) logger.d("Aged %s - notfound", manga.id)
meta.aged = true meta.aged = true
db.insertFlatMetadata(meta.flatten()).await() db.insertFlatMetadataAsync(meta.flatten()).await()
} }
throw GalleryNotUpdatedException(false, t) throw GalleryNotUpdatedException(false, t)
} }

View File

@ -10,10 +10,10 @@ import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.source.online.all.EHentai
import eu.kanade.tachiyomi.util.lang.await
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.system.powerManager import eu.kanade.tachiyomi.util.system.powerManager
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
@ -239,17 +239,15 @@ class FavoritesSyncHelper(val context: Context) {
private suspend fun addGalleryRemote(errorList: MutableList<String>, gallery: FavoriteEntry) { private suspend fun addGalleryRemote(errorList: MutableList<String>, gallery: FavoriteEntry) {
val url = "${exh.baseUrl}/gallerypopups.php?gid=${gallery.gid}&t=${gallery.token}&act=addfav" val url = "${exh.baseUrl}/gallerypopups.php?gid=${gallery.gid}&t=${gallery.token}&act=addfav"
val request = Request.Builder() val request = POST(
.url(url) url = url,
.post( body = FormBody.Builder()
FormBody.Builder() .add("favcat", gallery.category.toString())
.add("favcat", gallery.category.toString()) .add("favnote", "")
.add("favnote", "") .add("apply", "Add to Favorites")
.add("apply", "Add to Favorites") .add("update", "1")
.add("update", "1") .build()
.build() )
)
.build()
if (!explicitlyRetryExhRequest(10, request)) { if (!explicitlyRetryExhRequest(10, request)) {
val errorString = "Unable to add gallery to remote server: '${gallery.title}' (GID: ${gallery.gid})!" val errorString = "Unable to add gallery to remote server: '${gallery.title}' (GID: ${gallery.gid})!"
@ -296,10 +294,10 @@ class FavoritesSyncHelper(val context: Context) {
formBody.add("modifygids[]", it.gid) formBody.add("modifygids[]", it.gid)
} }
val request = Request.Builder() val request = POST(
.url("https://exhentai.org/favorites.php") url = "https://exhentai.org/favorites.php",
.post(formBody.build()) body = formBody.build()
.build() )
if (!explicitlyRetryExhRequest(10, request)) { if (!explicitlyRetryExhRequest(10, request)) {
val errorString = context.getString(R.string.favorites_sync_unable_to_delete) val errorString = context.getString(R.string.favorites_sync_unable_to_delete)
@ -408,8 +406,8 @@ class FavoritesSyncHelper(val context: Context) {
} }
// Can't do too many DB OPs in one go // Can't do too many DB OPs in one go
insertedMangaCategories.chunked(10).map { insertedMangaCategories.chunked(10).map { mangaCategories ->
Pair(it.map { it.first }, it.map { it.second }) mangaCategories.map { it.first } to mangaCategories.map { it.second }
}.forEach { }.forEach {
db.setMangaCategories(it.first, it.second) db.setMangaCategories(it.first, it.second)
} }

View File

@ -15,7 +15,8 @@ import exh.metadata.metadata.MangaDexSearchMetadata
import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.RaisedTag
import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata import exh.metadata.metadata.base.insertFlatMetadata
import exh.util.await import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.util.executeOnIO
import exh.util.floor import exh.util.floor
import exh.util.nullIfZero import exh.util.nullIfZero
import okhttp3.Response import okhttp3.Response
@ -70,16 +71,16 @@ class ApiMangaParser(private val lang: String) {
} }
suspend fun parseToManga(manga: MangaInfo, input: Response, coverUrls: List<String>, sourceId: Long): MangaInfo { suspend fun parseToManga(manga: MangaInfo, input: Response, coverUrls: List<String>, sourceId: Long): MangaInfo {
val mangaId = db.getManga(manga.key, sourceId).await()?.id val mangaId = db.getManga(manga.key, sourceId).executeOnIO()?.id
val metadata = if (mangaId != null) { val metadata = if (mangaId != null) {
val flatMetadata = db.getFlatMetadataForManga(mangaId).await() val flatMetadata = db.getFlatMetadataForManga(mangaId).executeOnIO()
flatMetadata?.raise(metaClass) ?: newMetaInstance() flatMetadata?.raise(metaClass) ?: newMetaInstance()
} else newMetaInstance() } else newMetaInstance()
parseInfoIntoMetadata(metadata, input, coverUrls) parseInfoIntoMetadata(metadata, input, coverUrls)
if (mangaId != null) { if (mangaId != null) {
metadata.mangaId = mangaId metadata.mangaId = mangaId
db.insertFlatMetadata(metadata.flatten()).await() db.insertFlatMetadataAsync(metadata.flatten()).await()
} }
return metadata.createMangaInfo(manga) return metadata.createMangaInfo(manga)

View File

@ -5,9 +5,12 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.models.SearchMetadata
import exh.metadata.sql.models.SearchTag import exh.metadata.sql.models.SearchTag
import exh.metadata.sql.models.SearchTitle import exh.metadata.sql.models.SearchTitle
import exh.util.executeOnIO
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.serializer import kotlinx.serialization.serializer
import rx.Completable import rx.Completable
import rx.Single import rx.Single
@ -99,3 +102,15 @@ fun DatabaseHelper.insertFlatMetadata(flatMetadata: FlatMetadata): Completable =
setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles) setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles)
} }
} }
suspend fun DatabaseHelper.insertFlatMetadataAsync(flatMetadata: FlatMetadata): Deferred<Unit> = coroutineScope {
async {
require(flatMetadata.metadata.mangaId != -1L)
inTransaction {
insertSearchMetadata(flatMetadata.metadata).executeOnIO()
setSearchTagsForManga(flatMetadata.metadata.mangaId, flatMetadata.tags)
setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles)
}
}
}

View File

@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.lang.await
import eu.kanade.tachiyomi.util.lang.awaitSingle import eu.kanade.tachiyomi.util.lang.awaitSingle
import exh.util.executeOnIO import exh.util.executeOnIO
import info.debatty.java.stringsimilarity.NormalizedLevenshtein import info.debatty.java.stringsimilarity.NormalizedLevenshtein

View File

@ -1,11 +1,10 @@
package exh.util package exh.util
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.injectLazy
import uy.kohesive.injekt.api.get
class DataSaver { object DataSaver {
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper by injectLazy()
fun compress(imageUrl: String): String { fun compress(imageUrl: String): String {
return if (preferences.dataSaver().get() && preferences.dataSaverServer().get().isNotBlank() && !imageUrl.contains(preferences.dataSaverServer().get() + "/?")) { return if (preferences.dataSaver().get() && preferences.dataSaverServer().get().isNotBlank() && !imageUrl.contains(preferences.dataSaverServer().get() + "/?")) {
@ -20,10 +19,10 @@ class DataSaver {
private fun getUrl(imageUrl: String): String { private fun getUrl(imageUrl: String): String {
val server = preferences.dataSaverServer().get() + "/?" val server = preferences.dataSaverServer().get() + "/?"
val format = "jpg=${if (preferences.dataSaverImageFormatJpeg().get()) "1" else "0"}" val format = "jpg=${if (preferences.dataSaverImageFormatJpeg().get()) "1" else "0"}"
val quality = "&l=${preferences.dataSaverImageQuality().get()}" val quality = "l=${preferences.dataSaverImageQuality().get()}"
val colorBW = "&bw=${if (preferences.dataSaverColorBW().get()) "1" else "0"}" val colorBW = "bw=${if (preferences.dataSaverColorBW().get()) "1" else "0"}"
val url = "$server$format$quality$colorBW&url=" val url = "url=$imageUrl"
return url + imageUrl return "$server&$format&$quality&$colorBW&$url"
} }
} }

View File

@ -1,5 +1,6 @@
package exh.util package exh.util
import com.pushtorefresh.storio.operations.PreparedOperation
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects
@ -16,3 +17,5 @@ suspend fun <T> PreparedGetObject<T>.executeOnIO(): T? = withContext(Dispatchers
suspend fun <T> PreparedPutObject<T>.executeOnIO(): PutResult = withContext(Dispatchers.IO) { executeAsBlocking() } suspend fun <T> PreparedPutObject<T>.executeOnIO(): PutResult = withContext(Dispatchers.IO) { executeAsBlocking() }
suspend fun <T> PreparedPutCollectionOfObjects<T>.executeOnIO(): PutResults<T> = withContext(Dispatchers.IO) { executeAsBlocking() } suspend fun <T> PreparedPutCollectionOfObjects<T>.executeOnIO(): PutResults<T> = withContext(Dispatchers.IO) { executeAsBlocking() }
suspend fun <T> PreparedOperation<T>.executeOnIO(): T? = withContext(Dispatchers.IO) { executeAsBlocking() }

View File

@ -1,176 +0,0 @@
package exh.util
// Zero-allocation-overhead mutable collection shims
private inline class CollectionShim<E>(private val coll: Collection<E>) : FakeMutableCollection<E> {
override val size: Int get() = coll.size
override fun contains(element: E) = coll.contains(element)
override fun containsAll(elements: Collection<E>) = coll.containsAll(elements)
override fun isEmpty() = coll.isEmpty()
override fun fakeIterator() = coll.iterator()
}
interface FakeMutableCollection<E> : MutableCollection<E>, FakeMutableIterable<E> {
override fun add(element: E): Boolean {
throw UnsupportedOperationException("This collection is immutable!")
}
override fun addAll(elements: Collection<E>): Boolean {
throw UnsupportedOperationException("This collection is immutable!")
}
override fun clear() {
throw UnsupportedOperationException("This collection is immutable!")
}
override fun remove(element: E): Boolean {
throw UnsupportedOperationException("This collection is immutable!")
}
override fun removeAll(elements: Collection<E>): Boolean {
throw UnsupportedOperationException("This collection is immutable!")
}
override fun retainAll(elements: Collection<E>): Boolean {
throw UnsupportedOperationException("This collection is immutable!")
}
override fun iterator(): MutableIterator<E> = super.iterator()
companion object {
fun <E> fromCollection(coll: Collection<E>): FakeMutableCollection<E> = CollectionShim(coll)
}
}
private inline class SetShim<E>(private val set: Set<E>) : FakeMutableSet<E> {
override val size: Int get() = set.size
override fun contains(element: E) = set.contains(element)
override fun containsAll(elements: Collection<E>) = set.containsAll(elements)
override fun isEmpty() = set.isEmpty()
override fun fakeIterator() = set.iterator()
}
interface FakeMutableSet<E> : MutableSet<E>, FakeMutableCollection<E> {
/**
* Adds the specified element to the set.
*
* @return `true` if the element has been added, `false` if the element is already contained in the set.
*/
override fun add(element: E): Boolean = super.add(element)
override fun addAll(elements: Collection<E>): Boolean = super.addAll(elements)
override fun clear() = super.clear()
override fun remove(element: E): Boolean = super.remove(element)
override fun removeAll(elements: Collection<E>): Boolean = super.removeAll(elements)
override fun retainAll(elements: Collection<E>): Boolean = super.retainAll(elements)
override fun iterator(): MutableIterator<E> = super.iterator()
companion object {
fun <E> fromSet(set: Set<E>): FakeMutableSet<E> = SetShim(set)
}
}
private inline class IterableShim<E>(private val iterable: Iterable<E>) : FakeMutableIterable<E> {
override fun fakeIterator() = iterable.iterator()
}
interface FakeMutableIterable<E> : MutableIterable<E> {
/**
* Returns an iterator over the elements of this sequence that supports removing elements during iteration.
*/
override fun iterator(): MutableIterator<E> = FakeMutableIterator.fromIterator(fakeIterator())
fun fakeIterator(): Iterator<E>
companion object {
fun <E> fromIterable(iterable: Iterable<E>): FakeMutableIterable<E> = IterableShim(iterable)
}
}
private inline class IteratorShim<E>(private val iterator: Iterator<E>) : FakeMutableIterator<E> {
/**
* Returns `true` if the iteration has more elements.
*/
override fun hasNext() = iterator.hasNext()
/**
* Returns the next element in the iteration.
*/
override fun next() = iterator.next()
}
interface FakeMutableIterator<E> : MutableIterator<E> {
/**
* Removes from the underlying collection the last element returned by this iterator.
*/
override fun remove() {
throw UnsupportedOperationException("This set is immutable!")
}
companion object {
fun <E> fromIterator(iterator: Iterator<E>): FakeMutableIterator<E> = IteratorShim(iterator)
}
}
private inline class EntryShim<K, V>(private val entry: Map.Entry<K, V>) : FakeMutableEntry<K, V> {
/**
* Returns the key of this key/value pair.
*/
override val key: K
get() = entry.key
/**
* Returns the value of this key/value pair.
*/
override val value: V
get() = entry.value
}
private inline class PairShim<K, V>(private val pair: Pair<K, V>) : FakeMutableEntry<K, V> {
/**
* Returns the key of this key/value pair.
*/
override val key: K get() = pair.first
/**
* Returns the value of this key/value pair.
*/
override val value: V get() = pair.second
}
interface FakeMutableEntry<K, V> : MutableMap.MutableEntry<K, V> {
override fun setValue(newValue: V): V {
throw UnsupportedOperationException("This entry is immutable!")
}
companion object {
fun <K, V> fromEntry(entry: Map.Entry<K, V>): FakeMutableEntry<K, V> = EntryShim(entry)
fun <K, V> fromPair(pair: Pair<K, V>): FakeMutableEntry<K, V> = PairShim(pair)
fun <K, V> fromPair(key: K, value: V) = object : FakeMutableEntry<K, V> {
/**
* Returns the key of this key/value pair.
*/
override val key: K = key
/**
* Returns the value of this key/value pair.
*/
override val value: V = value
}
}
}

View File

@ -24,21 +24,27 @@ fun Manga.mangaType(context: Context): String {
/** /**
* The type of comic the manga is (ie. manga, manhwa, manhua) * The type of comic the manga is (ie. manga, manhwa, manhua)
*/ */
fun Manga.mangaType(): MangaType { fun Manga.mangaType(sourceName: String = Injekt.get<SourceManager>().getOrStub(source).name): MangaType {
val sourceName = Injekt.get<SourceManager>().getOrStub(source).name
val currentTags = getGenres().orEmpty() val currentTags = getGenres().orEmpty()
return if (currentTags.any { tag -> isMangaTag(tag) }) { return when {
MangaType.TYPE_MANGA currentTags.any { tag -> isMangaTag(tag) } -> {
} else if (currentTags.any { tag -> isWebtoonTag(tag) } || isWebtoonSource(sourceName)) { MangaType.TYPE_MANGA
MangaType.TYPE_WEBTOON }
} else if (currentTags.any { tag -> isComicTag(tag) } || isComicSource(sourceName)) { currentTags.any { tag -> isWebtoonTag(tag) } || isWebtoonSource(sourceName) -> {
MangaType.TYPE_COMIC MangaType.TYPE_WEBTOON
} else if (currentTags.any { tag -> isManhuaTag(tag) } || isManhuaSource(sourceName)) { }
MangaType.TYPE_MANHUA currentTags.any { tag -> isComicTag(tag) } || isComicSource(sourceName) -> {
} else if (currentTags.any { tag -> isManhwaTag(tag) } || isManhwaSource(sourceName)) { MangaType.TYPE_COMIC
MangaType.TYPE_MANHWA }
} else { currentTags.any { tag -> isManhuaTag(tag) } || isManhuaSource(sourceName) -> {
MangaType.TYPE_MANGA MangaType.TYPE_MANHUA
}
currentTags.any { tag -> isManhwaTag(tag) } || isManhwaSource(sourceName) -> {
MangaType.TYPE_MANHWA
}
else -> {
MangaType.TYPE_MANGA
}
} }
} }
@ -46,8 +52,7 @@ fun Manga.mangaType(): MangaType {
* The type the reader should use. Different from manga type as certain manga has different * The type the reader should use. Different from manga type as certain manga has different
* read types * read types
*/ */
fun Manga.defaultReaderType(): Int? { fun Manga.defaultReaderType(type: MangaType = mangaType()): Int? {
val type = mangaType()
return if (type == MangaType.TYPE_MANHWA || type == MangaType.TYPE_WEBTOON) { return if (type == MangaType.TYPE_MANHWA || type == MangaType.TYPE_WEBTOON) {
ReaderActivity.WEBTOON ReaderActivity.WEBTOON
} else null } else null

View File

@ -1,32 +1,8 @@
package exh.util package exh.util
import com.pushtorefresh.storio.operations.PreparedOperation
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import rx.Completable
import rx.CompletableSubscriber
import rx.Emitter
import rx.Observable import rx.Observable
import rx.Observer
import rx.Scheduler
import rx.Single import rx.Single
import rx.SingleSubscriber
import rx.Subscriber
import rx.Subscription
import rx.subjects.ReplaySubject import rx.subjects.ReplaySubject
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
/** /**
* Transform a cold single to a hot single * Transform a cold single to a hot single
@ -49,7 +25,7 @@ fun <T> Observable<T>.melt(): Observable<T> {
subscribe(rs) subscribe(rs)
return rs return rs
} }
/*
suspend fun <T> Single<T>.await(subscribeOn: Scheduler? = null): T { suspend fun <T> Single<T>.await(subscribeOn: Scheduler? = null): T {
return suspendCancellableCoroutine { continuation -> return suspendCancellableCoroutine { continuation ->
val self = if (subscribeOn != null) subscribeOn(subscribeOn) else this val self = if (subscribeOn != null) subscribeOn(subscribeOn) else this
@ -181,11 +157,11 @@ private suspend fun <T> Observable<T>.awaitOne(): T = suspendCancellableCoroutin
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
/* *//*
* Rx1 observable throws NoSuchElementException if cancellation happened before * Rx1 observable throws NoSuchElementException if cancellation happened before
* element emission. To mitigate this we try to atomically resume continuation with exception: * element emission. To mitigate this we try to atomically resume continuation with exception:
* if resume failed, then we know that continuation successfully cancelled itself * if resume failed, then we know that continuation successfully cancelled itself
*/ *//*
val token = cont.tryResumeWithException(e) val token = cont.tryResumeWithException(e)
if (token != null) { if (token != null) {
cont.completeResume(token) cont.completeResume(token)
@ -220,10 +196,10 @@ fun <T : Any> Observable<T>.asFlow(): Flow<T> = callbackFlow {
fun <T : Any> Flow<T>.asObservable(backpressureMode: Emitter.BackpressureMode = Emitter.BackpressureMode.NONE): Observable<T> { fun <T : Any> Flow<T>.asObservable(backpressureMode: Emitter.BackpressureMode = Emitter.BackpressureMode.NONE): Observable<T> {
return Observable.create( return Observable.create(
{ emitter -> { emitter ->
/* *//*
* ATOMIC is used here to provide stable behaviour of subscribe+dispose pair even if * ATOMIC is used here to provide stable behaviour of subscribe+dispose pair even if
* asObservable is already invoked from unconfined * asObservable is already invoked from unconfined
*/ *//*
val job = GlobalScope.launch(Dispatchers.Unconfined, start = CoroutineStart.ATOMIC) { val job = GlobalScope.launch(Dispatchers.Unconfined, start = CoroutineStart.ATOMIC) {
try { try {
collect { emitter.onNext(it) } collect { emitter.onNext(it) }
@ -241,4 +217,4 @@ fun <T : Any> Flow<T>.asObservable(backpressureMode: Emitter.BackpressureMode =
}, },
backpressureMode backpressureMode
) )
} }*/

View File

@ -23,13 +23,11 @@ fun UrlImportableSource.urlImportFetchSearchManga(context: Context, query: Strin
}) })
.map { res -> .map { res ->
MangasPage( MangasPage(
( if (res is GalleryAddEvent.Success) {
if (res is GalleryAddEvent.Success) { listOf(res.manga)
listOf(res.manga) } else {
} else { emptyList()
emptyList() },
}
),
false false
) )
} }