Deal with SY for the coroutine function changes

This commit is contained in:
Jobobby04 2021-01-10 19:36:24 -05:00
parent 0edff11353
commit a0ac2daad1
27 changed files with 146 additions and 159 deletions

View File

@ -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) }

View File

@ -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<MangaDexSearchMetadata>()
?: 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
}

View File

@ -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<MangasPage>): Observable<MangasPage> =
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(
(

View File

@ -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<Chapter> {
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<Chapter>, List<Chapter>> {
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)
}

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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<QueryComponent>, manga: LibraryManga, checkGenre: Boolean = true, searchTags: List<SearchTag>? = null, searchTitles: List<SearchTitle>? = 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 ->

View File

@ -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<Manga>, 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

View File

@ -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<MergedMangaReference>) {
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()
}
}

View File

@ -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")

View File

@ -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<EHentaiSearchMetadata>()
}.toList()

View File

@ -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<EHentaiSearchMetadata>() ?: return@forEach
val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise<EHentaiSearchMetadata>() ?: 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<EHentaiSearchMetadata>() ?: return@forEach
val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise<EHentaiSearchMetadata>() ?: 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<EHentaiSearchMetadata>() ?: return@forEach
val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise<EHentaiSearchMetadata>() ?: return@forEach
if (meta.aged) {
// remove age flag
agedAmount++

View File

@ -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)

View File

@ -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<EHentaiSearchMetadata>()
@ -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<EHentaiSearchMetadata>()
val meta = db.getFlatMetadataForManga(manga.id!!).executeAsBlocking()?.raise<EHentaiSearchMetadata>()
if (meta != null) {
// Age dead galleries
logger.d("Aged %s - notfound", manga.id)

View File

@ -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<Long>(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))

View File

@ -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<Pair<SManga, MangaDexSearchMetadata>> {
return withContext(Dispatchers.IO) {
return withIOContext {
val listManga = mutableListOf<Pair<SManga, MangaDexSearchMetadata>>()
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,

View File

@ -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<MangaInfo, List<SChapter>> {
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<SChapter> {
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)
}

View File

@ -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 ->

View File

@ -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<JsonObject>(body)
val recommendations = data["recommendations"] as? JsonArray
return recommendations?.filterIsInstance<JsonObject>()?.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<JsonObject>(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<JsonObject>(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<MangasPage> {
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 {

View File

@ -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
}

View File

@ -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)

View File

@ -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<V>(
scope: CoroutineScope = CoroutineScope(Job() + Dispatchers.Main)
scope: CoroutineScope = MainScope()
) : Presenter<V>(), CoroutineScope by scope {
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Use launchInView, Flow.inView, Flow.mapView")
@ -26,19 +26,19 @@ open class CoroutinePresenter<V>(
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 <F> Flow<F>.inView(crossinline block: (V, F) -> Unit) = onEach {
withContext(Dispatchers.Main) {
withUIContext {
view?.let { view -> block(view, it) }
}
}
inline fun <F, P> Flow<F>.mapView(crossinline block: (V, F) -> P): Flow<P> {
return mapNotNull {
withContext(Dispatchers.Main) {
withUIContext {
view?.let { view -> block(view, it) }
}
}

View File

@ -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<BatchAddController>() {
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 {

View File

@ -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)

View File

@ -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<EhSmartSearchBinding, SmartSearchPresenter>() {
@ -52,7 +52,7 @@ class SmartSearchController(bundle: Bundle? = null) : NucleusController<EhSmartS
.onEach { results ->
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<EhSmartS
}
val transaction = BrowseSourceController(source, smartSearchConfig.origTitle, smartSearchConfig).withFadeTransaction()
withContext(Dispatchers.Main) {
withUIContext {
router.replaceTopController(transaction)
}
}

View File

@ -11,10 +11,9 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.MangaDex
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.lang.launchNow
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.system.toast
import exh.source.getMainSource
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -37,7 +36,7 @@ class MangadexLogoutDialog(bundle: Bundle? = null) : DialogController(bundle) {
.positiveButton(R.string.logout) {
launchNow {
source?.let { source ->
val loggedOut = withContext(Dispatchers.IO) { source.logout() }
val loggedOut = withIOContext { source.logout() }
if (loggedOut) {
trackManager.mdList.logout()