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