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 3d8cab975..ee0c53efd 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 @@ -46,6 +46,7 @@ import exh.md.utils.FollowStatus import exh.md.utils.MdUtil import exh.metadata.metadata.base.insertFlatMetadata import exh.source.getMainSource +import exh.util.executeOnIO import exh.util.nullIfBlank import rx.Observable import rx.Subscription @@ -456,11 +457,11 @@ class LibraryUpdateService( // SY --> if (source is MangaDex && trackManager.mdList.isLogged) { runAsObservable({ - val tracks = db.getTracks(manga).await() + val tracks = db.getTracks(manga).executeOnIO() if (tracks.isEmpty() || tracks.none { it.sync_id == TrackManager.MDLIST }) { var track = trackManager.mdList.createInitialTracker(manga) track = trackManager.mdList.refresh(track) - db.insertTrack(track).await() + db.insertTrack(track).executeOnIO() } }) .onErrorResumeNext { Observable.just(Unit) } 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 891f40a53..075a68891 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 @@ -16,6 +16,7 @@ import exh.md.utils.MdUtil import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.insertFlatMetadata +import exh.util.executeOnIO import exh.util.floor import uy.kohesive.injekt.injectLazy @@ -49,7 +50,7 @@ class MdList(private val context: Context, id: Int) : TrackService(id) { override suspend fun update(track: Track): Track { val mdex = mdex ?: throw Exception("Mangadex not enabled") - val mangaMetadata = db.getFlatMetadataForManga(track.manga_id).await() + val mangaMetadata = db.getFlatMetadataForManga(track.manga_id).executeAsBlocking() ?.raise() ?: throw Exception("Invalid manga metadata") val followStatus = FollowStatus.fromInt(track.status) ?: throw Exception("Follow status was not a valid value") @@ -88,8 +89,8 @@ class MdList(private val context: Context, id: Int) : TrackService(id) { val mdex = mdex ?: throw Exception("Mangadex not enabled") val remoteTrack = mdex.fetchTrackingInfo(track.tracking_url) track.copyPersonalFrom(remoteTrack) - if (track.total_chapters == 0 && db.getManga(track.manga_id).await()?.status == SManga.COMPLETED) { - track.total_chapters = db.getChapters(track.manga_id).await().maxOfOrNull { it.chapter_number }?.floor() ?: 0 + if (track.total_chapters == 0 && db.getManga(track.manga_id).executeOnIO()?.status == SManga.COMPLETED) { + track.total_chapters = db.getChapters(track.manga_id).executeOnIO().maxOfOrNull { it.chapter_number }?.floor() ?: 0 } return track } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt index b06bf907d..46fa7dc19 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt @@ -29,7 +29,7 @@ import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.manga.MangaController -import eu.kanade.tachiyomi.util.lang.asObservable +import eu.kanade.tachiyomi.util.lang.runAsObservable import exh.GalleryAddEvent import exh.GalleryAdder import exh.md.MangaDexFabHeaderAdapter @@ -48,7 +48,6 @@ import exh.ui.metadata.adapters.MangaDexDescriptionAdapter import exh.util.urlImportFetchSearchManga import exh.widget.preference.MangadexLoginDialog import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.withContext import okhttp3.CacheControl import okhttp3.FormBody @@ -207,7 +206,7 @@ class MangaDex(delegate: HttpSource, val context: Context) : ) ).await() - response.body!!.string().let { + withContext(Dispatchers.IO) { response.body!!.string() }.let { if (it.isEmpty()) { true } else { @@ -230,9 +229,9 @@ class MangaDex(delegate: HttpSource, val context: Context) : } val result = client.newCall( POST("${MdUtil.baseUrl}/ajax/actions.ajax.php?function=logout", headers).newBuilder().addHeader(REMEMBER_ME, token).build() - ).execute() - val resultStr = result.body!!.string() - if (resultStr.contains("success", true)) { + ).await() + val resultStr = withContext(Dispatchers.IO) { result.body?.string() } + if (resultStr?.contains("success", true) == true) { network.cookieManager.remove(httpUrl) trackManager.mdList.logout() return@withContext true @@ -282,10 +281,9 @@ class MangaDex(delegate: HttpSource, val context: Context) : private fun importIdToMdId(query: String, fail: () -> Observable): Observable = when { query.toIntOrNull() != null -> { - flow { - emit(GalleryAdder().addGallery(context, MdUtil.baseUrl + MdUtil.mapMdIdToMangaUrl(query.toInt()), false, this@MangaDex)) - } - .asObservable() + runAsObservable({ + GalleryAdder().addGallery(context, MdUtil.baseUrl + MdUtil.mapMdIdToMangaUrl(query.toInt()), false, this@MangaDex) + }) .map { res -> MangasPage( ( diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt index 21fe778db..8298a00f3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt @@ -17,16 +17,12 @@ import eu.kanade.tachiyomi.source.model.toSChapter import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.source.online.SuspendHttpSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import eu.kanade.tachiyomi.util.lang.await -import eu.kanade.tachiyomi.util.lang.awaitSingleOrNull +import eu.kanade.tachiyomi.util.lang.awaitSingle +import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.shouldDownloadNewChapters import exh.MERGED_SOURCE_ID import exh.merged.sql.models.MergedMangaReference -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext +import exh.util.executeOnIO import okhttp3.Response import rx.Observable import uy.kohesive.injekt.injectLazy @@ -59,9 +55,9 @@ class MergedSource : SuspendHttpSource() { override suspend fun fetchPopularMangaSuspended(page: Int) = throw UnsupportedOperationException() override suspend fun fetchMangaDetailsSuspended(manga: SManga): SManga { - return withContext(Dispatchers.IO) { - val mergedManga = db.getManga(manga.url, id).await() ?: throw Exception("merged manga not in db") - val mangaReferences = mergedManga.id?.let { withContext(Dispatchers.IO) { db.getMergedMangaReferences(it).await() } } ?: throw Exception("merged manga id is null") + return withIOContext { + val mergedManga = db.getManga(manga.url, id).executeAsBlocking() ?: throw Exception("merged manga not in db") + val mangaReferences = mergedManga.id?.let { db.getMergedMangaReferences(it).executeOnIO() } ?: throw Exception("merged manga id is null") if (mangaReferences.isEmpty()) throw IllegalArgumentException("Manga references are empty, info unavailable, merge is likely corrupted") if (mangaReferences.size == 1 || run { val mangaReference = mangaReferences.firstOrNull() @@ -71,7 +67,7 @@ class MergedSource : SuspendHttpSource() { SManga.create().apply { val mangaInfoReference = mangaReferences.firstOrNull { it.isInfoManga } ?: mangaReferences.firstOrNull { it.mangaId != it.mergeId } - val dbManga = mangaInfoReference?.let { withContext(Dispatchers.IO) { db.getManga(it.mangaUrl, it.mangaSourceId).await() } } + val dbManga = mangaInfoReference?.let { db.getManga(it.mangaUrl, it.mangaSourceId).executeOnIO() } this.copyFrom(dbManga ?: mergedManga) url = manga.url } @@ -82,7 +78,7 @@ class MergedSource : SuspendHttpSource() { // TODO more chapter dedupe return db.getChaptersByMergedMangaId(manga.id!!).asRxObservable() .map { chapterList -> - val mangaReferences = runBlocking(Dispatchers.IO) { db.getMergedMangaReferences(manga.id!!).await().orEmpty() } + val mangaReferences = db.getMergedMangaReferences(manga.id!!).executeAsBlocking() if (editScanlators) { val sources = mangaReferences.map { sourceManager.getOrStub(it.mangaSourceId) to it.mangaId } chapterList.onEach { chapter -> @@ -124,21 +120,21 @@ class MergedSource : SuspendHttpSource() { } suspend fun fetchChaptersForMergedManga(manga: Manga, downloadChapters: Boolean = true, editScanlators: Boolean = false, dedupe: Boolean = true): List { - return withContext(Dispatchers.IO) { + return withIOContext { fetchChaptersAndSync(manga, downloadChapters) - getChaptersFromDB(manga, editScanlators, dedupe).awaitSingleOrNull() ?: emptyList() + getChaptersFromDB(manga, editScanlators, dedupe).awaitSingle() } } suspend fun fetchChaptersAndSync(manga: Manga, downloadChapters: Boolean = true): Pair, List> { - val mangaReferences = db.getMergedMangaReferences(manga.id!!).await() + val mangaReferences = db.getMergedMangaReferences(manga.id!!).executeAsBlocking() if (mangaReferences.isEmpty()) throw IllegalArgumentException("Manga references are empty, chapters unavailable, merge is likely corrupted") val ifDownloadNewChapters = downloadChapters && manga.shouldDownloadNewChapters(db, preferences) return mangaReferences.filter { it.mangaSourceId != MERGED_SOURCE_ID }.map { it.load(db, sourceManager) }.mapNotNull { loadedManga -> - withContext(Dispatchers.IO) { + withIOContext { if (loadedManga.manga != null && loadedManga.reference.getChapterUpdates) { loadedManga.source.getChapterList(loadedManga.manga.toMangaInfo()) .map { it.toSChapter() } @@ -166,7 +162,7 @@ class MergedSource : SuspendHttpSource() { } suspend fun MergedMangaReference.load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource { - var manga = db.getManga(mangaUrl, mangaSourceId).await() + var manga = db.getManga(mangaUrl, mangaSourceId).executeOnIO() val source = sourceManager.getOrStub(manga?.source ?: mangaSourceId) if (manga == null) { manga = Manga.create(mangaSourceId).apply { @@ -174,9 +170,9 @@ class MergedSource : SuspendHttpSource() { } manga.copyFrom(source.getMangaDetails(manga.toMangaInfo()).toSManga()) try { - manga.id = db.insertManga(manga).await().insertedId() + manga.id = db.insertManga(manga).executeOnIO().insertedId() mangaId = manga.id - db.insertNewMergedMangaId(this).await() + db.insertNewMergedMangaId(this).executeOnIO() } catch (e: Exception) { XLog.tag("MergedSource").enableStackTrace(e.stackTrace.contentToString(), 5) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigratingManga.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigratingManga.kt index a2379313b..7725ae81f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigratingManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigratingManga.kt @@ -4,8 +4,8 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager -import eu.kanade.tachiyomi.util.lang.await import exh.util.DeferredField +import exh.util.executeOnIO import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.channels.ConflatedBroadcastChannel @@ -29,7 +29,7 @@ class MigratingManga( @Volatile private var manga: Manga? = null suspend fun manga(): Manga? { - if (manga == null) manga = db.getManga(mangaId).await() + if (manga == null) manga = db.getManga(mangaId).executeOnIO() return manga } 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 5eaf72f13..a4b82c9b9 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 @@ -250,7 +250,7 @@ class MigrationListController(bundle: Bundle? = null) : val newManga = sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo()) result.copyFrom(newManga.toSManga()) - db.insertManga(result).await() + db.insertManga(result).executeOnIO() } catch (e: CancellationException) { // Ignore cancellations throw e @@ -365,7 +365,7 @@ class MigrationListController(bundle: Bundle? = null) : val newManga = sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo()) result.copyFrom(newManga.toSManga()) - db.insertManga(result).await() + db.insertManga(result).executeOnIO() } catch (e: CancellationException) { // Ignore cancellations throw e diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt index 6da58e077..46cc2e379 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt @@ -17,11 +17,11 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.manga.MangaController -import eu.kanade.tachiyomi.util.lang.await import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.view.setVectorCompat import exh.MERGED_SOURCE_ID +import exh.util.executeOnIO import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -157,7 +157,7 @@ class MigrationProcessHolder( gradient.isVisible = true mangaSourceLabel.text = if (source.id == MERGED_SOURCE_ID) { - db.getMergedMangaReferences(manga.id!!).await().map { + db.getMergedMangaReferences(manga.id!!).executeOnIO().map { sourceManager.getOrStub(it.mangaSourceId).toString() }.distinct().joinToString() } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index 0ae22a11d..23f70dee9 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.ui.category.CategoryAdapter -import eu.kanade.tachiyomi.util.lang.await import exh.isMetadataSource import exh.metadata.sql.models.SearchTag import exh.metadata.sql.models.SearchTitle @@ -115,7 +114,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC // Prepare filter object val parsedQuery = searchEngine.parseQuery(savedSearchText) - val mangaWithMetaIdsQuery = db.getIdsOfFavoriteMangaWithMetadata().await() + val mangaWithMetaIdsQuery = db.getIdsOfFavoriteMangaWithMetadata().executeAsBlocking() val mangaWithMetaIds = LongArray(mangaWithMetaIdsQuery.count) if (mangaWithMetaIds.isNotEmpty()) { val mangaIdCol = mangaWithMetaIdsQuery.getColumnIndex(MangaTable.COL_ID) @@ -138,8 +137,8 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC // No meta? Filter using title filterManga(parsedQuery, item.manga) } else { - val tags = db.getSearchTagsForManga(mangaId).await() - val titles = db.getSearchTitlesForManga(mangaId).await() + val tags = db.getSearchTagsForManga(mangaId).executeAsBlocking() + val titles = db.getSearchTitlesForManga(mangaId).executeAsBlocking() filterManga(parsedQuery, item.manga, false, tags, titles) } } else { @@ -167,7 +166,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC private suspend fun filterManga(queries: List, manga: LibraryManga, checkGenre: Boolean = true, searchTags: List? = null, searchTitles: List? = null): Boolean { val mappedQueries = queries.groupBy { it.excluded } - val tracks = if (hasLoggedServices) db.getTracks(manga).await().toList() else null + val tracks = if (hasLoggedServices) db.getTracks(manga).executeAsBlocking().toList() else null val source = sourceManager.get(manga.source) val genre = if (checkGenre) manga.getGenres().orEmpty() else emptyList() val hasNormalQuery = mappedQueries[false]?.all { queryComponent -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 80e04af0a..1b4ff23a8 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -19,8 +19,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.isLocal -import eu.kanade.tachiyomi.util.lang.await -import eu.kanade.tachiyomi.util.lang.awaitSingleOrNull +import eu.kanade.tachiyomi.util.lang.awaitSingle import eu.kanade.tachiyomi.util.lang.combineLatest import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed import eu.kanade.tachiyomi.util.lang.launchIO @@ -32,6 +31,7 @@ import exh.MERGED_SOURCE_ID import exh.favorites.FavoritesSyncHelper import exh.md.utils.FollowStatus import exh.md.utils.MdUtil +import exh.util.executeOnIO import exh.util.isLewd import exh.util.nullIfBlank import kotlinx.coroutines.runBlocking @@ -499,10 +499,10 @@ class LibraryPresenter( mangas.forEach { manga -> launchIO { /* SY --> */ val chapters = if (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) { - val chapter = db.getChapters(manga).await().minByOrNull { it.source_order } + val chapter = db.getChapters(manga).executeOnIO().minByOrNull { it.source_order } if (chapter != null && !chapter.read) listOf(chapter) else emptyList() } else if (manga.source == MERGED_SOURCE_ID) { - (sourceManager.getOrStub(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingleOrNull()?.filter { !it.read }.orEmpty() + (sourceManager.getOrStub(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingle()?.filter { !it.read }.orEmpty() } else /* SY <-- */ db.getChapters(manga).executeAsBlocking() .filter { !it.read } @@ -557,7 +557,7 @@ class LibraryPresenter( fun markReadStatus(mangas: List, read: Boolean) { mangas.forEach { manga -> launchIO { - val chapters = if (manga.source == MERGED_SOURCE_ID) (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingleOrNull().orEmpty() else db.getChapters(manga).executeAsBlocking() + val chapters = if (manga.source == MERGED_SOURCE_ID) (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingle().orEmpty() else db.getChapters(manga).executeAsBlocking() chapters.forEach { it.read = read if (!read) { @@ -612,7 +612,7 @@ class LibraryPresenter( val source = sourceManager.get(manga.source) as? HttpSource if (source != null) { if (source is MergedSource) { - val mergedMangas = db.getMergedMangas(manga.id!!).await() + val mergedMangas = db.getMergedMangas(manga.id!!).executeAsBlocking() val sources = mergedMangas.distinctBy { it.source }.map { sourceManager.getOrStub(it.source) } mergedMangas.forEach merge@{ mergedManga -> val mergedSource = sources.firstOrNull { mergedManga.source == it.id } ?: return@merge @@ -644,7 +644,7 @@ class LibraryPresenter( // SY --> /** Returns first unread chapter of a manga */ fun getFirstUnread(manga: Manga): Chapter? { - val chapters = (if (manga.source == MERGED_SOURCE_ID) (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource).let { runBlocking { it?.getChaptersFromDB(manga)?.awaitSingleOrNull().orEmpty() } } else db.getChapters(manga).executeAsBlocking()) + val chapters = (if (manga.source == MERGED_SOURCE_ID) (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource).let { runBlocking { it?.getChaptersFromDB(manga)?.awaitSingle().orEmpty() } } else db.getChapters(manga).executeAsBlocking()) return if (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) { val chapter = chapters.sortedBy { it.source_order }.getOrNull(0) if (chapter?.read == false) chapter 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 4a426b280..9049bd4cc 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 @@ -143,7 +143,7 @@ class MangaPresenter( // SY --> if (source is MergedSource) { - launchIO { mergedManga = db.getMergedMangas(manga.id!!).await() } + launchIO { mergedManga = db.getMergedMangas(manga.id!!).executeAsBlocking() } } // SY <-- @@ -379,9 +379,9 @@ class MangaPresenter( } suspend fun smartSearchMerge(manga: Manga, originalMangaId: Long): Manga { - val originalManga = db.getManga(originalMangaId).await() ?: throw IllegalArgumentException("Unknown manga ID: $originalMangaId") + val originalManga = db.getManga(originalMangaId).executeAsBlocking() ?: throw IllegalArgumentException("Unknown manga ID: $originalMangaId") if (originalManga.source == MERGED_SOURCE_ID) { - val children = db.getMergedMangaReferences(originalMangaId).await() + val children = db.getMergedMangaReferences(originalMangaId).executeAsBlocking() if (children.any { it.mangaSourceId == manga.source && it.mangaUrl == manga.url }) { throw IllegalArgumentException("This manga is already merged with the current manga!") } @@ -418,7 +418,7 @@ class MangaPresenter( ) } - db.insertMergedMangas(mangaReferences).await() + db.insertMergedMangas(mangaReferences).executeAsBlocking() return originalManga } else { @@ -431,30 +431,30 @@ class MangaPresenter( sorting = Manga.SORTING_NUMBER date_added = System.currentTimeMillis() } - var existingManga = db.getManga(mergedManga.url, mergedManga.source).await() + var existingManga = db.getManga(mergedManga.url, mergedManga.source).executeAsBlocking() while (existingManga != null) { if (existingManga.favorite) { throw IllegalArgumentException("This merged manga is a duplicate!") } else if (!existingManga.favorite) { withContext(NonCancellable) { - db.deleteManga(existingManga!!).await() - db.deleteMangaForMergedManga(existingManga!!.id!!).await() + db.deleteManga(existingManga!!).executeAsBlocking() + db.deleteMangaForMergedManga(existingManga!!.id!!).executeAsBlocking() } } - existingManga = db.getManga(mergedManga.url, mergedManga.source).await() + existingManga = db.getManga(mergedManga.url, mergedManga.source).executeAsBlocking() } // Reload chapters immediately mergedManga.initialized = false - val newId = db.insertManga(mergedManga).await().insertedId() + val newId = db.insertManga(mergedManga).executeAsBlocking().insertedId() if (newId != null) mergedManga.id = newId db.getCategoriesForManga(originalManga) - .await() + .executeAsBlocking() .map { MangaCategory.create(mergedManga, it) } .let { - db.insertMangasCategories(it).await() + db.insertMangasCategories(it).executeAsBlocking() } val originalMangaReference = MergedMangaReference( @@ -499,7 +499,7 @@ class MangaPresenter( mangaSourceId = MERGED_SOURCE_ID ) - db.insertMergedMangas(listOf(originalMangaReference, newMangaReference, mergedMangaReference)).await() + db.insertMergedMangas(listOf(originalMangaReference, newMangaReference, mergedMangaReference)).executeAsBlocking() return mergedManga } @@ -510,9 +510,9 @@ class MangaPresenter( fun updateMergeSettings(mergeReference: MergedMangaReference?, mergedMangaReferences: List) { launchIO { mergeReference?.let { - db.updateMergeMangaSettings(it).await() + db.updateMergeMangaSettings(it).executeAsBlocking() } - if (mergedMangaReferences.isNotEmpty()) db.updateMergedMangaSettings(mergedMangaReferences).await() + if (mergedMangaReferences.isNotEmpty()) db.updateMergedMangaSettings(mergedMangaReferences).executeAsBlocking() } } 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 8a9eb6284..78ca13cbd 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 @@ -26,7 +26,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.util.isLocal -import eu.kanade.tachiyomi.util.lang.awaitSingleOrNull +import eu.kanade.tachiyomi.util.lang.awaitSingle import eu.kanade.tachiyomi.util.lang.byteSize import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.takeBytes @@ -119,7 +119,7 @@ class ReaderPresenter( val meta = meta val filteredScanlators = meta?.filteredScanlators?.let { MdUtil.getScanlators(it) } // SY <-- - val dbChapters = /* SY --> */if (manga.source == MERGED_SOURCE_ID) runBlocking { (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingleOrNull().orEmpty() } else /* SY <-- */ db.getChapters(manga).executeAsBlocking() + val dbChapters = /* SY --> */if (manga.source == MERGED_SOURCE_ID) runBlocking { (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingle().orEmpty() } else /* SY <-- */ db.getChapters(manga).executeAsBlocking() val selectedChapter = dbChapters.find { it.id == chapterId } ?: error("Requested chapter of id $chapterId not found in chapter list") diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt index a79598439..694e7e67e 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt @@ -21,7 +21,6 @@ import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.databinding.EhDialogCategoriesBinding import eu.kanade.tachiyomi.databinding.EhDialogLanguagesBinding import eu.kanade.tachiyomi.ui.webview.WebViewActivity -import eu.kanade.tachiyomi.util.lang.await import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.entriesRes import eu.kanade.tachiyomi.util.preference.intListPreference @@ -641,10 +640,10 @@ class SettingsEhController : SettingsController() { context.getString(R.string.gallery_updater_stats_text, getRelativeTimeString(getRelativeTimeFromNow(stats.startTime.milliseconds), context), stats.updateCount, stats.possibleUpdates) } else context.getString(R.string.gallery_updater_not_ran_yet) - val allMeta = db.getFavoriteMangaWithMetadata().await().filter { + val allMeta = db.getFavoriteMangaWithMetadata().executeAsBlocking().filter { it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID }.mapNotNull { - db.getFlatMetadataForManga(it.id!!).await() + db.getFlatMetadataForManga(it.id!!).executeAsBlocking() ?.raise() }.toList() diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index 7540fb04d..fb80eded8 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -21,6 +21,7 @@ import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.insertFlatMetadata import exh.savedsearches.JsonSavedSearch import exh.util.cancellable +import exh.util.executeOnIO import exh.util.jobScheduler import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.mapNotNull @@ -51,7 +52,7 @@ object DebugFunctions { fun resetAgedFlagInEXHManga() { runBlocking { - val metadataManga = db.getFavoriteMangaWithMetadata().await() + val metadataManga = db.getFavoriteMangaWithMetadata().executeOnIO() val allManga = metadataManga.asFlow().cancellable().mapNotNull { manga -> if (manga.source != EH_SOURCE_ID && manga.source != EXH_SOURCE_ID) { @@ -60,7 +61,7 @@ object DebugFunctions { }.toList() allManga.forEach { manga -> - val meta = db.getFlatMetadataForManga(manga.id!!).await()?.raise() ?: return@forEach + val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise() ?: return@forEach // remove age flag meta.aged = false db.insertFlatMetadata(meta.flatten()).await() @@ -74,7 +75,7 @@ object DebugFunctions { fun resetEHGalleriesForUpdater() { throttleManager.resetThrottle() runBlocking { - val metadataManga = db.getFavoriteMangaWithMetadata().await() + val metadataManga = db.getFavoriteMangaWithMetadata().executeOnIO() val allManga = metadataManga.asFlow().cancellable().mapNotNull { manga -> if (manga.source != EH_SOURCE_ID && manga.source != EXH_SOURCE_ID) { @@ -104,7 +105,7 @@ object DebugFunctions { fun getEHMangaListWithAgedFlagInfo(): String { val galleries = mutableListOf(String()) runBlocking { - val metadataManga = db.getFavoriteMangaWithMetadata().await() + val metadataManga = db.getFavoriteMangaWithMetadata().executeOnIO() val allManga = metadataManga.asFlow().cancellable().mapNotNull { manga -> if (manga.source != EH_SOURCE_ID && manga.source != EXH_SOURCE_ID) { @@ -113,7 +114,7 @@ object DebugFunctions { }.toList() allManga.forEach { manga -> - val meta = db.getFlatMetadataForManga(manga.id!!).await()?.raise() ?: return@forEach + val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise() ?: return@forEach galleries += "Aged: ${meta.aged}\t Title: ${manga.title}" } } @@ -123,7 +124,7 @@ object DebugFunctions { fun countAgedFlagInEXHManga(): Int { var agedAmount = 0 runBlocking { - val metadataManga = db.getFavoriteMangaWithMetadata().await() + val metadataManga = db.getFavoriteMangaWithMetadata().executeAsBlocking() val allManga = metadataManga.asFlow().cancellable().mapNotNull { manga -> if (manga.source != EH_SOURCE_ID && manga.source != EXH_SOURCE_ID) { @@ -132,7 +133,7 @@ object DebugFunctions { }.toList() allManga.forEach { manga -> - val meta = db.getFlatMetadataForManga(manga.id!!).await()?.raise() ?: return@forEach + val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise() ?: return@forEach if (meta.aged) { // remove age flag agedAmount++ diff --git a/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt b/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt index f22c339df..f0be3288d 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt @@ -6,7 +6,7 @@ import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.ChapterImpl import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.MangaCategory -import eu.kanade.tachiyomi.util.lang.await +import exh.util.executeOnIO import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -33,13 +33,13 @@ class EHentaiUpdateHelper(context: Context) { val chainsFlow = flowOf(chapters) .map { chapterList -> chapterList.flatMap { chapter -> - db.getChapters(chapter.url).await().mapNotNull { it.manga_id } + db.getChapters(chapter.url).executeOnIO().mapNotNull { it.manga_id } }.distinct() } .map { mangaIds -> mangaIds .mapNotNull { mangaId -> - (db.getManga(mangaId).await() ?: return@mapNotNull null) to db.getChapters(mangaId).await() + (db.getManga(mangaId).executeOnIO() ?: return@mapNotNull null) to db.getChapters(mangaId).executeOnIO() } .map { ChapterChain(it.first, it.second) diff --git a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt index 019ba780c..1c9343cca 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt @@ -28,6 +28,7 @@ import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.insertFlatMetadata import exh.util.cancellable +import exh.util.executeOnIO import exh.util.jobScheduler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -136,7 +137,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope { val startTime = System.currentTimeMillis() logger.d("Finding manga with metadata...") - val metadataManga = db.getFavoriteMangaWithMetadata().await() + val metadataManga = db.getFavoriteMangaWithMetadata().executeOnIO() logger.d("Filtering manga and raising metadata...") val curTime = System.currentTimeMillis() @@ -145,7 +146,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope { return@mapNotNull null } - val meta = db.getFlatMetadataForManga(manga.id!!).await() + val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking() ?: return@mapNotNull null val raisedMeta = meta.raise() @@ -155,7 +156,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope { return@mapNotNull null } - val chapter = db.getChapters(manga.id!!).await().minByOrNull { + val chapter = db.getChapters(manga.id!!).executeOnIO().minByOrNull { it.date_upload } @@ -265,16 +266,16 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope { try { val updatedManga = source.getMangaDetails(manga.toMangaInfo()) manga.copyFrom(updatedManga.toSManga()) - db.insertManga(manga).await() + db.insertManga(manga).executeOnIO() val newChapters = source.getChapterList(manga.toMangaInfo()) .map { it.toSChapter() } val (new, _) = syncChaptersWithSource(db, newChapters, manga, source) // Not suspending, but does block, maybe fix this? - return new to db.getChapters(manga).await() + return new to db.getChapters(manga).executeOnIO() } catch (t: Throwable) { if (t is EHentai.GalleryNotFoundException) { - val meta = db.getFlatMetadataForManga(manga.id!!).await()?.raise() + val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise() if (meta != null) { // Age dead galleries logger.d("Aged %s - notfound", manga.id) diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index be48e0814..69c8bef6e 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -84,13 +84,13 @@ class FavoritesSyncHelper(val context: Context) { // Validate library state status.value = FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_verifying_library), context = context) - val libraryManga = db.getLibraryMangas().await() + val libraryManga = db.getLibraryMangas().executeOnIO() val seenManga = HashSet(libraryManga.size) libraryManga.forEach { if (it.source != EXH_SOURCE_ID && it.source != EH_SOURCE_ID) return@forEach if (it.id in seenManga) { - val inCategories = db.getCategoriesForManga(it).await() + val inCategories = db.getCategoriesForManga(it).executeOnIO() status.value = FavoritesSyncStatus.BadLibraryState.MangaInMultipleCategories(it, inCategories, context) logger.w(context.getString(R.string.favorites_sync_manga_multiple_categories_error, it.id)) diff --git a/app/src/main/java/exh/md/handlers/FollowsHandler.kt b/app/src/main/java/exh/md/handlers/FollowsHandler.kt index 55238ff28..b5555c167 100644 --- a/app/src/main/java/exh/md/handlers/FollowsHandler.kt +++ b/app/src/main/java/exh/md/handlers/FollowsHandler.kt @@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MetadataMangasPage import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.util.lang.withIOContext import exh.md.handlers.serializers.FollowPage import exh.md.handlers.serializers.FollowsIndividualSerializer import exh.md.handlers.serializers.FollowsPageSerializer @@ -17,8 +18,6 @@ import exh.md.utils.FollowStatus import exh.md.utils.MdUtil import exh.metadata.metadata.MangaDexSearchMetadata import exh.util.floor -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import kotlinx.serialization.decodeFromString import okhttp3.CacheControl import okhttp3.FormBody @@ -122,7 +121,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere title = manga.title mdUrl = manga.url thumbnail_url = manga.thumbnail_url - follow_status = FollowStatus.fromInt(result.followType)?.int + follow_status = FollowStatus.fromInt(result.followType).int } } @@ -130,7 +129,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere * Change the status of a manga */ suspend fun updateFollowStatus(mangaID: String, followStatus: FollowStatus): Boolean { - return withContext(Dispatchers.IO) { + return withIOContext { val response: Response = if (followStatus == FollowStatus.UNFOLLOWED) { client.newCall( @@ -153,12 +152,12 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere .await() } - withContext(Dispatchers.IO) { response.body?.string().isNullOrEmpty() } + withIOContext { response.body?.string().isNullOrEmpty() } } } suspend fun updateReadingProgress(track: Track): Boolean { - return withContext(Dispatchers.IO) { + return withIOContext { val mangaID = MdUtil.getMangaId(track.tracking_url) val formBody = FormBody.Builder() .add("chapter", track.last_chapter_read.toString()) @@ -178,12 +177,12 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere ) ).await().body?.close() - withContext(Dispatchers.IO) { response.body?.string().isNullOrEmpty() } + withIOContext { response.body?.string().isNullOrEmpty() } } } suspend fun updateRating(track: Track): Boolean { - return withContext(Dispatchers.IO) { + return withIOContext { val mangaID = MdUtil.getMangaId(track.tracking_url) val response = client.newCall( GET( @@ -193,7 +192,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere ) .await() - withContext(Dispatchers.IO) { response.body?.string().isNullOrEmpty() } + withIOContext { response.body?.string().isNullOrEmpty() } } } @@ -201,7 +200,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere * fetch all manga from all possible pages */ suspend fun fetchAllFollows(forceHd: Boolean): List> { - return withContext(Dispatchers.IO) { + return withIOContext { val listManga = mutableListOf>() val response = client.newCall(followsListRequest()).await() val mangasPage = followsParseMangaPage(response, forceHd) @@ -215,7 +214,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere } suspend fun fetchTrackingInfo(url: String): Track { - return withContext(Dispatchers.IO) { + return withIOContext { val request = GET( "${MdUtil.apiUrl}${MdUtil.followsMangaApi}" + MdUtil.getMangaId(url), headers, diff --git a/app/src/main/java/exh/md/handlers/MangaHandler.kt b/app/src/main/java/exh/md/handlers/MangaHandler.kt index 19c4b529b..b9cff537d 100644 --- a/app/src/main/java/exh/md/handlers/MangaHandler.kt +++ b/app/src/main/java/exh/md/handlers/MangaHandler.kt @@ -10,10 +10,9 @@ import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.toMangaInfo import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.util.lang.runAsObservable +import eu.kanade.tachiyomi.util.lang.withIOContext import exh.md.handlers.serializers.ApiCovers import exh.md.utils.MdUtil -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import okhttp3.CacheControl import okhttp3.Headers import okhttp3.OkHttpClient @@ -25,12 +24,12 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: Str // TODO make use of this suspend fun fetchMangaAndChapterDetails(manga: MangaInfo, sourceId: Long): Pair> { - return withContext(Dispatchers.IO) { + return withIOContext { val response = client.newCall(apiRequest(manga.toSManga())).await() val covers = getCovers(manga, forceLatestCovers) val parser = ApiMangaParser(lang) - val jsonData = withContext(Dispatchers.IO) { response.body!!.string() } + val jsonData = withIOContext { response.body!!.string() } if (response.code != 200) { XLog.tag("MangaHandler").enableStackTrace(2).e("error from MangaDex with response code ${response.code} \n body: \n$jsonData") throw Exception("Error from MangaDex Response code ${response.code} ") @@ -55,7 +54,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: Str } suspend fun getMangaIdFromChapterId(urlChapterId: String): Int { - return withContext(Dispatchers.IO) { + return withIOContext { val request = GET(MdUtil.apiUrl + MdUtil.newApiChapter + urlChapterId + MdUtil.apiChapterSuffix, headers, CacheControl.FORCE_NETWORK) val response = client.newCall(request).await() ApiMangaParser(lang).chapterParseForMangaId(response) @@ -63,7 +62,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: Str } suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long): MangaInfo { - return withContext(Dispatchers.IO) { + return withIOContext { val response = client.newCall(apiRequest(manga.toSManga())).await() val covers = getCovers(manga, forceLatestCovers) ApiMangaParser(lang).parseToManga(manga, response, covers, sourceId) @@ -100,7 +99,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: Str } suspend fun fetchChapterList(manga: SManga): List { - return withContext(Dispatchers.IO) { + return withIOContext { val response = client.newCall(apiRequest(manga)).await() ApiMangaParser(lang).chapterListParse(response) } @@ -115,7 +114,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: Str } suspend fun fetchRandomMangaId(): String { - return withContext(Dispatchers.IO) { + return withIOContext { val response = client.newCall(randomMangaRequest()).await() ApiMangaParser(lang).randomMangaIdParse(response) } diff --git a/app/src/main/java/exh/md/similar/SimilarUpdateService.kt b/app/src/main/java/exh/md/similar/SimilarUpdateService.kt index ae4ca4326..303272ba0 100644 --- a/app/src/main/java/exh/md/similar/SimilarUpdateService.kt +++ b/app/src/main/java/exh/md/similar/SimilarUpdateService.kt @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.await +import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.notificationManager import exh.md.similar.sql.models.MangaSimilarImpl @@ -28,7 +29,6 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.isActive import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import okio.buffer import okio.sink import okio.source @@ -149,7 +149,7 @@ class SimilarUpdateService( /** * Method that updates the similar database for manga */ - private suspend fun updateSimilar() = withContext(Dispatchers.IO) { + private suspend fun updateSimilar() = withIOContext { val response = client .newCall(GET(similarUrl)) .await() @@ -157,7 +157,7 @@ class SimilarUpdateService( throw Exception("Error trying to download similar file") } val destinationFile = File(filesDir, "neko-similar.json") - val buffer = withContext(Dispatchers.IO) { destinationFile.sink().buffer() } + val buffer = withIOContext { destinationFile.sink().buffer() } // write json to file response.body?.byteStream()?.source()?.use { input -> diff --git a/app/src/main/java/exh/recs/RecommendsPager.kt b/app/src/main/java/exh/recs/RecommendsPager.kt index 7f98736bc..1cdd2787d 100644 --- a/app/src/main/java/exh/recs/RecommendsPager.kt +++ b/app/src/main/java/exh/recs/RecommendsPager.kt @@ -8,15 +8,13 @@ import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.SMangaImpl import eu.kanade.tachiyomi.ui.browse.source.browse.NoResultsException import eu.kanade.tachiyomi.ui.browse.source.browse.Pager -import eu.kanade.tachiyomi.util.lang.asObservable +import eu.kanade.tachiyomi.util.lang.runAsObservable +import eu.kanade.tachiyomi.util.lang.withIOContext import exh.log.maybeInjectEHLogger import exh.util.MangaType import exh.util.mangaType import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonArray @@ -32,6 +30,7 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.OkHttpClient import okhttp3.RequestBody.Companion.toRequestBody import rx.Observable +import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import timber.log.Timber @@ -55,7 +54,7 @@ class MyAnimeList : API("https://api.jikan.moe/v3/") { .toString() val response = client.newCall(GET(apiUrl)).await() - val body = withContext(Dispatchers.IO) { response.body?.string() } ?: throw Exception("Null Response") + val body = withIOContext { response.body?.string() } ?: throw Exception("Null Response") val data = Json.decodeFromString(body) val recommendations = data["recommendations"] as? JsonArray return recommendations?.filterIsInstance()?.map { rec -> @@ -79,7 +78,7 @@ class MyAnimeList : API("https://api.jikan.moe/v3/") { .toString() val response = client.newCall(GET(url)).await() - val body = withContext(Dispatchers.IO) { response.body?.string() } ?: throw Exception("Null Response") + val body = withIOContext { response.body?.string() } ?: throw Exception("Null Response") val data = Json.decodeFromString(body) val results = data["results"] as? JsonArray if (results.isNullOrEmpty()) { @@ -167,7 +166,7 @@ class Anilist : API("https://graphql.anilist.co/") { val payloadBody = payload.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull()) val response = client.newCall(POST(endpoint, body = payloadBody)).await() - val body = withContext(Dispatchers.IO) { response.body?.string() } ?: throw Exception("Null Response") + val body = withIOContext { response.body?.string() } ?: throw Exception("Null Response") val data = Json.decodeFromString(body)["data"] as? JsonObject ?: throw Exception("Unexpected response") val media = data["Page"]?.jsonObject?.get("media")?.jsonArray @@ -203,7 +202,7 @@ open class RecommendsPager( private var preferredApi: API = API.MYANIMELIST ) : Pager() { override fun requestNext(): Observable { - return flow { + return runAsObservable({ if (smart) preferredApi = if (manga.mangaType() != MangaType.TYPE_MANGA) API.ANILIST else preferredApi val apiList = API_MAP.toList().sortedByDescending { it.first == preferredApi } @@ -223,19 +222,17 @@ open class RecommendsPager( .firstOrNull { it.isNotEmpty() } .orEmpty() - val page = MangasPage(recs, false) - emit(page) - } - .onEach { - withContext(Dispatchers.Main) { - if (it.mangas.isNotEmpty()) { - onPageReceived(it) - } else { - throw NoResultsException() - } - } - }.asObservable() + MangasPage(recs, false) + }) .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext { + if (it.mangas.isNotEmpty()) { + onPageReceived(it) + } else { + throw NoResultsException() + } + } } companion object { diff --git a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt index 537c38cf7..6f06ea233 100644 --- a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt +++ b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt @@ -7,6 +7,7 @@ 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 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -170,11 +171,11 @@ class SmartSearchEngine( * @return a manga from the database. */ suspend fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).await() + var localManga = db.getManga(sManga.url, sourceId).executeOnIO() if (localManga == null) { val newManga = Manga.create(sManga.url, sManga.title, sourceId) newManga.copyFrom(sManga) - val result = db.insertManga(newManga).await() + val result = db.insertManga(newManga).executeOnIO() newManga.id = result.insertedId() localManga = newManga } diff --git a/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt b/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt index 001babc54..1d7887e49 100644 --- a/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt +++ b/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt @@ -7,29 +7,26 @@ import com.afollestad.materialdialogs.MaterialDialog import com.elvishew.xlog.XLog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.toast -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job +import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext class ConfiguringDialogController : DialogController() { private var materialDialog: MaterialDialog? = null - val scope = CoroutineScope(Job() + Dispatchers.Main) + val scope = MainScope() override fun onCreateDialog(savedViewState: Bundle?): Dialog { if (savedViewState == null) { - scope.launch(Dispatchers.IO) { + scope.launchIO { try { EHConfigurator(activity!!).configureAll() launchUI { activity?.toast(activity?.getString(R.string.eh_settings_successfully_uploaded)) } } catch (e: Exception) { - withContext(Dispatchers.Main) { + launchUI { activity?.let { MaterialDialog(it) .title(R.string.eh_settings_configuration_failed) diff --git a/app/src/main/java/exh/ui/base/CoroutinePresenter.kt b/app/src/main/java/exh/ui/base/CoroutinePresenter.kt index e79cc2a0f..ad89446ae 100644 --- a/app/src/main/java/exh/ui/base/CoroutinePresenter.kt +++ b/app/src/main/java/exh/ui/base/CoroutinePresenter.kt @@ -1,9 +1,10 @@ package exh.ui.base import androidx.annotation.CallSuper +import eu.kanade.tachiyomi.util.lang.launchUI +import eu.kanade.tachiyomi.util.lang.withUIContext import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job +import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect @@ -11,14 +12,13 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import nucleus.presenter.Presenter import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @Suppress("DEPRECATION", "unused") open class CoroutinePresenter( - scope: CoroutineScope = CoroutineScope(Job() + Dispatchers.Main) + scope: CoroutineScope = MainScope() ) : Presenter(), CoroutineScope by scope { @Suppress("DeprecatedCallableAddReplaceWith") @Deprecated("Use launchInView, Flow.inView, Flow.mapView") @@ -26,19 +26,19 @@ open class CoroutinePresenter( return super.getView() } - fun launchInView(block: (CoroutineScope, V) -> Unit) = launch(Dispatchers.Main) { + fun launchInView(block: (CoroutineScope, V) -> Unit) = launchUI { view?.let { block.invoke(this, it) } } inline fun Flow.inView(crossinline block: (V, F) -> Unit) = onEach { - withContext(Dispatchers.Main) { + withUIContext { view?.let { view -> block(view, it) } } } inline fun Flow.mapView(crossinline block: (V, F) -> P): Flow

{ return mapNotNull { - withContext(Dispatchers.Main) { + withUIContext { view?.let { view -> block(view, it) } } } diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt index 99c19a3df..85c22e388 100644 --- a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt +++ b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt @@ -7,6 +7,7 @@ import com.jakewharton.rxrelay.ReplayRelay import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.util.lang.withIOContext import exh.GalleryAddEvent import exh.GalleryAdder import exh.util.trimOrNull @@ -14,7 +15,6 @@ import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ensureActive import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -65,7 +65,7 @@ class BatchAddPresenter : BasePresenter() { splitGalleries.forEachIndexed { i, s -> ensureActive() - val result = withContext(Dispatchers.IO) { galleryAdder.addGallery(context, s, true) } + val result = withIOContext { galleryAdder.addGallery(context, s, true) } if (result is GalleryAddEvent.Success) { succeeded.add(s) } else { diff --git a/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt b/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt index 55c348110..89eec3b19 100644 --- a/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt +++ b/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt @@ -21,12 +21,11 @@ import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.system.setDefaultSettings import exh.source.DelegatedHttpSource import exh.util.melt -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject @@ -188,7 +187,7 @@ class BrowserActionActivity : AppCompatActivity() { currentLoopId = null validateCurrentLoopId = null XLog.tag("BrowserActionActivity").enableStackTrace(2).e(IllegalStateException("Captcha solve failure!")) - withContext(Dispatchers.Main) { + withUIContext { binding.webview.evaluateJavascript(SOLVE_UI_SCRIPT_HIDE, null) MaterialDialog(this@BrowserActionActivity) .title(R.string.captcha_solve_failure) diff --git a/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt b/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt index 325ce2ba6..bc897919c 100644 --- a/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt +++ b/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt @@ -12,12 +12,12 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.browse.source.SourceController import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController import eu.kanade.tachiyomi.ui.manga.MangaController +import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.plus -import kotlinx.coroutines.withContext import uy.kohesive.injekt.injectLazy class SmartSearchController(bundle: Bundle? = null) : NucleusController() { @@ -52,7 +52,7 @@ class SmartSearchController(bundle: Bundle? = null) : NucleusController if (results is SmartSearchPresenter.SearchResults.Found) { val transaction = MangaController(results.manga, true, smartSearchConfig).withFadeTransaction() - withContext(Dispatchers.Main) { + withUIContext { router.replaceTopController(transaction) } } else { @@ -63,7 +63,7 @@ class SmartSearchController(bundle: Bundle? = null) : NucleusController - val loggedOut = withContext(Dispatchers.IO) { source.logout() } + val loggedOut = withIOContext { source.logout() } if (loggedOut) { trackManager.mdList.logout()