Deal with SY for the coroutine function changes
This commit is contained in:
parent
0edff11353
commit
a0ac2daad1
@ -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) }
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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(
|
||||
(
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 ->
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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++
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 ->
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user