diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt index d26fbcfae..6303553f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt @@ -36,7 +36,7 @@ import eu.kanade.tachiyomi.source.online.MetadataSource import eu.kanade.tachiyomi.source.online.all.MergedSource import exh.MERGED_SOURCE_ID import exh.metadata.metadata.base.getFlatMetadataForManga -import exh.metadata.metadata.base.insertFlatMetadata +import exh.metadata.metadata.base.insertFlatMetadataAsync import exh.savedsearches.JsonSavedSearch import exh.source.getMainSource 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 -> databaseHelper.getFlatMetadataForManga(mangaId).executeAsBlocking().let { if (it == null) { val flatMetadata = backupFlatMetadata.getFlatMetadata(mangaId) - databaseHelper.insertFlatMetadata(flatMetadata).await() + databaseHelper.insertFlatMetadataAsync(flatMetadata).await() } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt index 4ab1ca858..c2d8c67f7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt @@ -223,7 +223,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val } } - private fun restoreExtraForManga(manga: Manga, categories: List, history: List, tracks: List, backupCategories: List, mergedMangaReferences: List, flatMetadata: BackupFlatMetadata?) { + private suspend fun restoreExtraForManga(manga: Manga, categories: List, history: List, tracks: List, backupCategories: List, mergedMangaReferences: List, flatMetadata: BackupFlatMetadata?) { // Restore categories backupManager.restoreCategoriesForManga(manga, categories, backupCategories) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index ee0c53efd..5a269e3e0 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -32,7 +32,6 @@ import eu.kanade.tachiyomi.ui.library.LibraryGroup import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.util.chapter.NoChaptersException 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.prepUpdateCover import eu.kanade.tachiyomi.util.shouldDownloadNewChapters diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt index 02f3942f2..35b9d5a2c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt @@ -10,12 +10,11 @@ import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.util.lang.await import exh.md.utils.FollowStatus import exh.md.utils.MdUtil import exh.metadata.metadata.MangaDexSearchMetadata 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.floor 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) { mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), followStatus) mangaMetadata.follow_status = followStatus.int - db.insertFlatMetadata(mangaMetadata.flatten()).await() + db.insertFlatMetadataAsync(mangaMetadata.flatten()).await() } if (track.score.toInt() > 0) { @@ -78,7 +77,7 @@ class MdList(private val context: Context, id: Int) : TrackService(id) { track.status = FollowStatus.READING.int mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), newFollowStatus) mangaMetadata.follow_status = newFollowStatus.int - db.insertFlatMetadata(mangaMetadata.flatten()).await() + db.insertFlatMetadataAsync(mangaMetadata.flatten()).await() } mdex.updateReadingProgress(track) diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt b/app/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt index 58ae94d5e..d38d88cb6 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt @@ -18,8 +18,7 @@ open class Page( // SY --> var imageUrl = imageUrl get() { - if (field == null) return null - return DataSaver().compress(field!!) + return field?.let { DataSaver.compress(it) } } // SY <-- diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt index b7c76a028..0a3a3b8b1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/MetadataSource.kt @@ -11,7 +11,8 @@ import eu.kanade.tachiyomi.ui.manga.MangaController import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga 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.Single import tachiyomi.source.model.MangaInfo @@ -79,14 +80,14 @@ interface MetadataSource : CatalogueSource { suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo { val mangaId = manga.id() val metadata = if (mangaId != null) { - val flatMetadata = db.getFlatMetadataForManga(mangaId).await() + val flatMetadata = db.getFlatMetadataForManga(mangaId).executeOnIO() flatMetadata?.raise(metaClass) ?: newMetaInstance() } else newMetaInstance() parseInfoIntoMetadata(metadata, input) if (mangaId != null) { metadata.mangaId = mangaId - db.insertFlatMetadata(metadata.flatten()).await() + db.insertFlatMetadataAsync(metadata.flatten()).await() } return metadata.createMangaInfo(manga) @@ -134,7 +135,7 @@ interface MetadataSource : CatalogueSource { */ suspend fun fetchOrLoadMetadata(mangaId: Long?, inputProducer: suspend () -> I): M { val meta = if (mangaId != null) { - val flatMetadata = db.getFlatMetadataForManga(mangaId).await() + val flatMetadata = db.getFlatMetadataForManga(mangaId).executeOnIO() flatMetadata?.raise(metaClass) } else { null @@ -145,14 +146,14 @@ interface MetadataSource : CatalogueSource { parseInfoIntoMetadata(newMeta, input) if (mangaId != null) { newMeta.mangaId = mangaId - db.insertFlatMetadata(newMeta.flatten()).let { newMeta } + db.insertFlatMetadataAsync(newMeta.flatten()).await().let { newMeta } } else newMeta } } 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 SChapter.mangaId get() = (this as? Chapter)?.manga_id } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationListController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationListController.kt index def8c9528..f75703e5c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationListController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationListController.kt @@ -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.manga.MangaController 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.withIOContext import eu.kanade.tachiyomi.util.system.getResourceColor @@ -49,7 +49,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.async import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import timber.log.Timber @@ -115,7 +114,7 @@ class MigrationListController(bundle: Bundle? = null) : adapter?.updateDataSet(newMigratingManga.map { it.toModal() }) if (migrationsJob == null) { - migrationsJob = viewScope.launch(Dispatchers.IO) { + migrationsJob = viewScope.launchIO { runMigrations(newMigratingManga) } } @@ -128,7 +127,7 @@ class MigrationListController(bundle: Bundle? = null) : val useSmartSearch = preferences.smartMigration().get() val sources = preferences.migrationSources().get().split("/").mapNotNull { - val value = it.toLongOrNull() ?: return + val value = it.toLongOrNull() ?: return@mapNotNull null sourceManager.get(value) as? CatalogueSource } for (manga in mangas) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesController.kt index 616ce5d9f..cced4967d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesController.kt @@ -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.migration.advanced.design.PreMigrationController 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.withUIContext import eu.kanade.tachiyomi.util.system.openInBrowser -import rx.schedulers.Schedulers +import exh.util.executeOnIO import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -84,8 +83,9 @@ class MigrationSourcesController : override fun onItemClick(view: View?, position: Int): Boolean { val item = adapter?.getItem(position) as? SourceItem ?: return false val controller = MigrationMangaController(item.source.id, item.source.name) + val parentController = parentController if (parentController is BrowseController) { - parentController!!.router.pushController(controller.withFadeTransaction()) + parentController.router.pushController(controller.withFadeTransaction()) } else { router.pushController(controller.withFadeTransaction()) } @@ -97,15 +97,18 @@ class MigrationSourcesController : val item = adapter?.getItem(position) as? SourceItem ?: return launchUI { - val manga = Injekt.get().getFavoriteMangas().asRxSingle().await(Schedulers.io()) - val sourceMangas = manga.asSequence().filter { it.source == item.source.id }.map { it.id!! }.toList() + val manga = Injekt.get().getFavoriteMangas().executeOnIO() + val sourceMangas = manga.asSequence().filter { it.source == item.source.id }.mapNotNull { it.id }.toList() withUIContext { PreMigrationController.navigateToMigration( Injekt.get().skipPreMigration().get(), - if (parentController is BrowseController) { - parentController!!.router - } else { - router + run { + val parentController = parentController + if (parentController is BrowseController) { + parentController.router + } else { + router + } }, sourceMangas ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt index 5291d7ade..7d624f6ca 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt @@ -208,7 +208,7 @@ class EditMangaDialog : DialogController { addView(addTagChip) } - private fun ChipGroup.getTextStrings(): List? = children.mapNotNull { + private fun ChipGroup.getTextStrings(): List = children.mapNotNull { if (it is Chip && !it.text.toString().contains(context.getString(R.string.add_tag), ignoreCase = true)) { it.text.toString() } else null diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 9049bd4cc..be5ecabe3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -52,7 +52,7 @@ import exh.merged.sql.models.MergedMangaReference import exh.metadata.metadata.base.FlatMetadata import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga -import exh.metadata.metadata.base.insertFlatMetadata +import exh.metadata.metadata.base.insertFlatMetadataAsync import exh.source.getMainSource import exh.util.shouldDeleteChapters import exh.util.trimOrNull @@ -1002,11 +1002,11 @@ class MangaPresenter( } // SY --> - fun setScanlatorFilter(filteredScanlators: Set) { + suspend fun setScanlatorFilter(filteredScanlators: Set) { val meta = meta ?: return meta.filteredScanlators = if (filteredScanlators.size == allChapterScanlators.size) null else MdUtil.getScanlatorString(filteredScanlators) meta.flatten().let { - db.insertFlatMetadata(it).await() + db.insertFlatMetadataAsync(it).await() } refreshChapters() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt index cbc78c84b..1608a42b1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt @@ -11,6 +11,8 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.source.online.MetadataSource 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.view.popupMenu import eu.kanade.tachiyomi.widget.ExtendedNavigationView @@ -19,6 +21,7 @@ import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog import exh.md.utils.MdUtil import exh.metadata.metadata.MangaDexSearchMetadata import exh.source.getMainSource +import kotlinx.coroutines.supervisorScope class ChaptersSettingsSheet( private val router: Router, @@ -132,13 +135,21 @@ class ChaptersSettingsSheet( MaterialDialog(context) .title(R.string.select_scanlators) .listItemsMultiChoice(items = presenter.allChapterScanlators.toList(), initialSelection = preselected) { _, selections, _ -> - val selected = selections.map { scanlators[it] }.toSet() - presenter.setScanlatorFilter(selected) - onGroupClicked(this) + launchIO { + supervisorScope { + val selected = selections.map { scanlators[it] }.toSet() + presenter.setScanlatorFilter(selected) + withUIContext { onGroupClicked(this@FilterGroup) } + } + } } .negativeButton(R.string.action_reset) { - presenter.setScanlatorFilter(presenter.allChapterScanlators) - onGroupClicked(this) + launchIO { + supervisorScope { + presenter.setScanlatorFilter(presenter.allChapterScanlators) + withUIContext { onGroupClicked(this@FilterGroup) } + } + } } .positiveButton(android.R.string.ok) .show() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index a7407cd7d..133f92832 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -71,6 +71,7 @@ import eu.kanade.tachiyomi.widget.SimpleAnimationListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener import exh.isEhBasedSource import exh.util.defaultReaderType +import exh.util.mangaType import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -729,7 +730,7 @@ class ReaderActivity : BaseRxActivity() binding.viewerContainer.addView(newViewer.getView()) // 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) { binding.root.snack(resources.getString(R.string.eh_auto_webtoon_snack), Snackbar.LENGTH_LONG) } else if (preferences.showReadingMode()) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index 7fc3a4e1d..28b8f5080 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -44,6 +44,7 @@ import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga import exh.source.getMainSource import exh.util.defaultReaderType +import exh.util.mangaType import exh.util.shouldDeleteChapters import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -598,7 +599,7 @@ class ReaderPresenter( val manga = manga ?: return preferences.defaultViewer() // SY --> 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) { preferences.defaultViewer() } else { diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index fb80eded8..0ea8f5239 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.toSManga -import eu.kanade.tachiyomi.util.lang.await import exh.EH_SOURCE_ID import exh.EXHMigrations import exh.EXH_SOURCE_ID @@ -18,7 +17,7 @@ import exh.eh.EHentaiThrottleManager import exh.eh.EHentaiUpdateWorker import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga -import exh.metadata.metadata.base.insertFlatMetadata +import exh.metadata.metadata.base.insertFlatMetadataAsync import exh.savedsearches.JsonSavedSearch import exh.util.cancellable import exh.util.executeOnIO @@ -64,7 +63,7 @@ object DebugFunctions { val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise() ?: return@forEach // remove age flag meta.aged = false - db.insertFlatMetadata(meta.flatten()).await() + db.insertFlatMetadataAsync(meta.flatten()).await() } } } diff --git a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt index 1c9343cca..54e473edf 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt @@ -19,14 +19,13 @@ import eu.kanade.tachiyomi.source.model.toSChapter import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import eu.kanade.tachiyomi.util.lang.await import exh.EH_SOURCE_ID import exh.EXH_SOURCE_ID import exh.debug.DebugToggles import exh.eh.EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION import exh.metadata.metadata.EHentaiSearchMetadata 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.executeOnIO import exh.util.jobScheduler @@ -280,7 +279,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope { // Age dead galleries logger.d("Aged %s - notfound", manga.id) meta.aged = true - db.insertFlatMetadata(meta.flatten()).await() + db.insertFlatMetadataAsync(meta.flatten()).await() } throw GalleryNotUpdatedException(false, t) } diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index 69c8bef6e..a58cc1a7b 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -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.MangaCategory import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.SourceManager 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.system.powerManager import eu.kanade.tachiyomi.util.system.toast @@ -239,17 +239,15 @@ class FavoritesSyncHelper(val context: Context) { private suspend fun addGalleryRemote(errorList: MutableList, gallery: FavoriteEntry) { val url = "${exh.baseUrl}/gallerypopups.php?gid=${gallery.gid}&t=${gallery.token}&act=addfav" - val request = Request.Builder() - .url(url) - .post( - FormBody.Builder() - .add("favcat", gallery.category.toString()) - .add("favnote", "") - .add("apply", "Add to Favorites") - .add("update", "1") - .build() - ) - .build() + val request = POST( + url = url, + body = FormBody.Builder() + .add("favcat", gallery.category.toString()) + .add("favnote", "") + .add("apply", "Add to Favorites") + .add("update", "1") + .build() + ) if (!explicitlyRetryExhRequest(10, request)) { 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) } - val request = Request.Builder() - .url("https://exhentai.org/favorites.php") - .post(formBody.build()) - .build() + val request = POST( + url = "https://exhentai.org/favorites.php", + body = formBody.build() + ) if (!explicitlyRetryExhRequest(10, request)) { 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 - insertedMangaCategories.chunked(10).map { - Pair(it.map { it.first }, it.map { it.second }) + insertedMangaCategories.chunked(10).map { mangaCategories -> + mangaCategories.map { it.first } to mangaCategories.map { it.second } }.forEach { db.setMangaCategories(it.first, it.second) } diff --git a/app/src/main/java/exh/md/handlers/ApiMangaParser.kt b/app/src/main/java/exh/md/handlers/ApiMangaParser.kt index 9c3f598ae..23a3fc21c 100644 --- a/app/src/main/java/exh/md/handlers/ApiMangaParser.kt +++ b/app/src/main/java/exh/md/handlers/ApiMangaParser.kt @@ -15,7 +15,8 @@ import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.base.RaisedTag import exh.metadata.metadata.base.getFlatMetadataForManga 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.nullIfZero import okhttp3.Response @@ -70,16 +71,16 @@ class ApiMangaParser(private val lang: String) { } suspend fun parseToManga(manga: MangaInfo, input: Response, coverUrls: List, 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 flatMetadata = db.getFlatMetadataForManga(mangaId).await() + val flatMetadata = db.getFlatMetadataForManga(mangaId).executeOnIO() flatMetadata?.raise(metaClass) ?: newMetaInstance() } else newMetaInstance() parseInfoIntoMetadata(metadata, input, coverUrls) if (mangaId != null) { metadata.mangaId = mangaId - db.insertFlatMetadata(metadata.flatten()).await() + db.insertFlatMetadataAsync(metadata.flatten()).await() } return metadata.createMangaInfo(manga) diff --git a/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt b/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt index 0df33b144..fd1dc2861 100644 --- a/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt @@ -5,9 +5,12 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.models.SearchTag 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.Serializable -import kotlinx.serialization.decodeFromString import kotlinx.serialization.serializer import rx.Completable import rx.Single @@ -99,3 +102,15 @@ fun DatabaseHelper.insertFlatMetadata(flatMetadata: FlatMetadata): Completable = setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles) } } + +suspend fun DatabaseHelper.insertFlatMetadataAsync(flatMetadata: FlatMetadata): Deferred = coroutineScope { + async { + require(flatMetadata.metadata.mangaId != -1L) + + inTransaction { + insertSearchMetadata(flatMetadata.metadata).executeOnIO() + setSearchTagsForManga(flatMetadata.metadata.mangaId, flatMetadata.tags) + setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles) + } + } +} diff --git a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt index 6f06ea233..20c2e4a4e 100644 --- a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt +++ b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt @@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.util.lang.await import eu.kanade.tachiyomi.util.lang.awaitSingle import exh.util.executeOnIO import info.debatty.java.stringsimilarity.NormalizedLevenshtein diff --git a/app/src/main/java/exh/util/DataSaver.kt b/app/src/main/java/exh/util/DataSaver.kt index d2880c93c..5fc1ba6e7 100644 --- a/app/src/main/java/exh/util/DataSaver.kt +++ b/app/src/main/java/exh/util/DataSaver.kt @@ -1,11 +1,10 @@ package exh.util import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy -class DataSaver { - private val preferences: PreferencesHelper = Injekt.get() +object DataSaver { + private val preferences: PreferencesHelper by injectLazy() fun compress(imageUrl: String): String { 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 { val server = preferences.dataSaverServer().get() + "/?" val format = "jpg=${if (preferences.dataSaverImageFormatJpeg().get()) "1" else "0"}" - val quality = "&l=${preferences.dataSaverImageQuality().get()}" - val colorBW = "&bw=${if (preferences.dataSaverColorBW().get()) "1" else "0"}" - val url = "$server$format$quality$colorBW&url=" + val quality = "l=${preferences.dataSaverImageQuality().get()}" + val colorBW = "bw=${if (preferences.dataSaverColorBW().get()) "1" else "0"}" + val url = "url=$imageUrl" - return url + imageUrl + return "$server&$format&$quality&$colorBW&$url" } } diff --git a/app/src/main/java/exh/util/DatabaseExtensions.kt b/app/src/main/java/exh/util/DatabaseExtensions.kt index 57978b79f..ba11915d9 100644 --- a/app/src/main/java/exh/util/DatabaseExtensions.kt +++ b/app/src/main/java/exh/util/DatabaseExtensions.kt @@ -1,5 +1,6 @@ package exh.util +import com.pushtorefresh.storio.operations.PreparedOperation import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects @@ -16,3 +17,5 @@ suspend fun PreparedGetObject.executeOnIO(): T? = withContext(Dispatchers suspend fun PreparedPutObject.executeOnIO(): PutResult = withContext(Dispatchers.IO) { executeAsBlocking() } suspend fun PreparedPutCollectionOfObjects.executeOnIO(): PutResults = withContext(Dispatchers.IO) { executeAsBlocking() } + +suspend fun PreparedOperation.executeOnIO(): T? = withContext(Dispatchers.IO) { executeAsBlocking() } diff --git a/app/src/main/java/exh/util/FakeMutables.kt b/app/src/main/java/exh/util/FakeMutables.kt deleted file mode 100644 index a5c1677cc..000000000 --- a/app/src/main/java/exh/util/FakeMutables.kt +++ /dev/null @@ -1,176 +0,0 @@ -package exh.util - -// Zero-allocation-overhead mutable collection shims - -private inline class CollectionShim(private val coll: Collection) : FakeMutableCollection { - override val size: Int get() = coll.size - - override fun contains(element: E) = coll.contains(element) - - override fun containsAll(elements: Collection) = coll.containsAll(elements) - - override fun isEmpty() = coll.isEmpty() - - override fun fakeIterator() = coll.iterator() -} - -interface FakeMutableCollection : MutableCollection, FakeMutableIterable { - override fun add(element: E): Boolean { - throw UnsupportedOperationException("This collection is immutable!") - } - - override fun addAll(elements: Collection): 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): Boolean { - throw UnsupportedOperationException("This collection is immutable!") - } - - override fun retainAll(elements: Collection): Boolean { - throw UnsupportedOperationException("This collection is immutable!") - } - - override fun iterator(): MutableIterator = super.iterator() - - companion object { - fun fromCollection(coll: Collection): FakeMutableCollection = CollectionShim(coll) - } -} - -private inline class SetShim(private val set: Set) : FakeMutableSet { - override val size: Int get() = set.size - - override fun contains(element: E) = set.contains(element) - - override fun containsAll(elements: Collection) = set.containsAll(elements) - - override fun isEmpty() = set.isEmpty() - - override fun fakeIterator() = set.iterator() -} - -interface FakeMutableSet : MutableSet, FakeMutableCollection { - /** - * 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): Boolean = super.addAll(elements) - - override fun clear() = super.clear() - - override fun remove(element: E): Boolean = super.remove(element) - - override fun removeAll(elements: Collection): Boolean = super.removeAll(elements) - - override fun retainAll(elements: Collection): Boolean = super.retainAll(elements) - - override fun iterator(): MutableIterator = super.iterator() - - companion object { - fun fromSet(set: Set): FakeMutableSet = SetShim(set) - } -} - -private inline class IterableShim(private val iterable: Iterable) : FakeMutableIterable { - override fun fakeIterator() = iterable.iterator() -} - -interface FakeMutableIterable : MutableIterable { - /** - * Returns an iterator over the elements of this sequence that supports removing elements during iteration. - */ - override fun iterator(): MutableIterator = FakeMutableIterator.fromIterator(fakeIterator()) - - fun fakeIterator(): Iterator - - companion object { - fun fromIterable(iterable: Iterable): FakeMutableIterable = IterableShim(iterable) - } -} - -private inline class IteratorShim(private val iterator: Iterator) : FakeMutableIterator { - /** - * 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 : MutableIterator { - /** - * Removes from the underlying collection the last element returned by this iterator. - */ - override fun remove() { - throw UnsupportedOperationException("This set is immutable!") - } - - companion object { - fun fromIterator(iterator: Iterator): FakeMutableIterator = IteratorShim(iterator) - } -} - -private inline class EntryShim(private val entry: Map.Entry) : FakeMutableEntry { - /** - * 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(private val pair: Pair) : FakeMutableEntry { - /** - * 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 : MutableMap.MutableEntry { - override fun setValue(newValue: V): V { - throw UnsupportedOperationException("This entry is immutable!") - } - - companion object { - fun fromEntry(entry: Map.Entry): FakeMutableEntry = EntryShim(entry) - - fun fromPair(pair: Pair): FakeMutableEntry = PairShim(pair) - - fun fromPair(key: K, value: V) = object : FakeMutableEntry { - /** - * 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 - } - } -} diff --git a/app/src/main/java/exh/util/MangaType.kt b/app/src/main/java/exh/util/MangaType.kt index fb93096ff..66ce48f4f 100644 --- a/app/src/main/java/exh/util/MangaType.kt +++ b/app/src/main/java/exh/util/MangaType.kt @@ -24,21 +24,27 @@ fun Manga.mangaType(context: Context): String { /** * The type of comic the manga is (ie. manga, manhwa, manhua) */ -fun Manga.mangaType(): MangaType { - val sourceName = Injekt.get().getOrStub(source).name +fun Manga.mangaType(sourceName: String = Injekt.get().getOrStub(source).name): MangaType { val currentTags = getGenres().orEmpty() - return if (currentTags.any { tag -> isMangaTag(tag) }) { - MangaType.TYPE_MANGA - } else if (currentTags.any { tag -> isWebtoonTag(tag) } || isWebtoonSource(sourceName)) { - MangaType.TYPE_WEBTOON - } else if (currentTags.any { tag -> isComicTag(tag) } || isComicSource(sourceName)) { - MangaType.TYPE_COMIC - } else if (currentTags.any { tag -> isManhuaTag(tag) } || isManhuaSource(sourceName)) { - MangaType.TYPE_MANHUA - } else if (currentTags.any { tag -> isManhwaTag(tag) } || isManhwaSource(sourceName)) { - MangaType.TYPE_MANHWA - } else { - MangaType.TYPE_MANGA + return when { + currentTags.any { tag -> isMangaTag(tag) } -> { + MangaType.TYPE_MANGA + } + currentTags.any { tag -> isWebtoonTag(tag) } || isWebtoonSource(sourceName) -> { + MangaType.TYPE_WEBTOON + } + currentTags.any { tag -> isComicTag(tag) } || isComicSource(sourceName) -> { + MangaType.TYPE_COMIC + } + currentTags.any { tag -> isManhuaTag(tag) } || isManhuaSource(sourceName) -> { + 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 * read types */ -fun Manga.defaultReaderType(): Int? { - val type = mangaType() +fun Manga.defaultReaderType(type: MangaType = mangaType()): Int? { return if (type == MangaType.TYPE_MANHWA || type == MangaType.TYPE_WEBTOON) { ReaderActivity.WEBTOON } else null diff --git a/app/src/main/java/exh/util/RxUtil.kt b/app/src/main/java/exh/util/RxUtil.kt index 39c4a1164..f64d49646 100644 --- a/app/src/main/java/exh/util/RxUtil.kt +++ b/app/src/main/java/exh/util/RxUtil.kt @@ -1,32 +1,8 @@ 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.Observer -import rx.Scheduler import rx.Single -import rx.SingleSubscriber -import rx.Subscriber -import rx.Subscription import rx.subjects.ReplaySubject -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException /** * Transform a cold single to a hot single @@ -49,7 +25,7 @@ fun Observable.melt(): Observable { subscribe(rs) return rs } - +/* suspend fun Single.await(subscribeOn: Scheduler? = null): T { return suspendCancellableCoroutine { continuation -> val self = if (subscribeOn != null) subscribeOn(subscribeOn) else this @@ -181,11 +157,11 @@ private suspend fun Observable.awaitOne(): T = suspendCancellableCoroutin } override fun onError(e: Throwable) { - /* + *//* * Rx1 observable throws NoSuchElementException if cancellation happened before * element emission. To mitigate this we try to atomically resume continuation with exception: * if resume failed, then we know that continuation successfully cancelled itself - */ + *//* val token = cont.tryResumeWithException(e) if (token != null) { cont.completeResume(token) @@ -220,10 +196,10 @@ fun Observable.asFlow(): Flow = callbackFlow { fun Flow.asObservable(backpressureMode: Emitter.BackpressureMode = Emitter.BackpressureMode.NONE): Observable { return Observable.create( { emitter -> - /* + *//* * ATOMIC is used here to provide stable behaviour of subscribe+dispose pair even if * asObservable is already invoked from unconfined - */ + *//* val job = GlobalScope.launch(Dispatchers.Unconfined, start = CoroutineStart.ATOMIC) { try { collect { emitter.onNext(it) } @@ -241,4 +217,4 @@ fun Flow.asObservable(backpressureMode: Emitter.BackpressureMode = }, backpressureMode ) -} +}*/ diff --git a/app/src/main/java/exh/util/SearchOverride.kt b/app/src/main/java/exh/util/SearchOverride.kt index 42e91d00e..0cd8ceb11 100644 --- a/app/src/main/java/exh/util/SearchOverride.kt +++ b/app/src/main/java/exh/util/SearchOverride.kt @@ -23,13 +23,11 @@ fun UrlImportableSource.urlImportFetchSearchManga(context: Context, query: Strin }) .map { res -> MangasPage( - ( - if (res is GalleryAddEvent.Success) { - listOf(res.manga) - } else { - emptyList() - } - ), + if (res is GalleryAddEvent.Success) { + listOf(res.manga) + } else { + emptyList() + }, false ) }