Avoid using global scope where appropriate
Also fixes the crash in tracking when an exception is thrown during a refresh.
This commit is contained in:
parent
96b8beb9cd
commit
2ffbee3db2
14 changed files with 88 additions and 81 deletions
|
@ -8,8 +8,7 @@ import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.network.jsonMime
|
import eu.kanade.tachiyomi.network.jsonMime
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
import kotlinx.serialization.json.contentOrNull
|
import kotlinx.serialization.json.contentOrNull
|
||||||
|
@ -30,7 +29,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
suspend fun addLibManga(track: Track): Track {
|
suspend fun addLibManga(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val query =
|
val query =
|
||||||
"""
|
"""
|
||||||
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) {
|
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) {
|
||||||
|
@ -65,7 +64,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateLibManga(track: Track): Track {
|
suspend fun updateLibManga(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val query =
|
val query =
|
||||||
"""
|
"""
|
||||||
|mutation UpdateManga(${'$'}listId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus, ${'$'}score: Int) {
|
|mutation UpdateManga(${'$'}listId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus, ${'$'}score: Int) {
|
||||||
|
@ -92,7 +91,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun search(search: String): List<TrackSearch> {
|
suspend fun search(search: String): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val query =
|
val query =
|
||||||
"""
|
"""
|
||||||
|query Search(${'$'}query: String) {
|
|query Search(${'$'}query: String) {
|
||||||
|
@ -143,7 +142,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track, userid: Int): Track? {
|
suspend fun findLibManga(track: Track, userid: Int): Track? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val query =
|
val query =
|
||||||
"""
|
"""
|
||||||
|query (${'$'}id: Int!, ${'$'}manga_id: Int!) {
|
|query (${'$'}id: Int!, ${'$'}manga_id: Int!) {
|
||||||
|
@ -209,7 +208,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentUser(): Pair<Int, String> {
|
suspend fun getCurrentUser(): Pair<Int, String> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val query =
|
val query =
|
||||||
"""
|
"""
|
||||||
|query User {
|
|query User {
|
||||||
|
|
|
@ -9,8 +9,7 @@ import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
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
|
||||||
|
@ -33,7 +32,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
suspend fun addLibManga(track: Track): Track {
|
suspend fun addLibManga(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
.add("rating", track.score.toInt().toString())
|
.add("rating", track.score.toInt().toString())
|
||||||
.add("status", track.toBangumiStatus())
|
.add("status", track.toBangumiStatus())
|
||||||
|
@ -45,7 +44,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateLibManga(track: Track): Track {
|
suspend fun updateLibManga(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
// read status update
|
// read status update
|
||||||
val sbody = FormBody.Builder()
|
val sbody = FormBody.Builder()
|
||||||
.add("status", track.toBangumiStatus())
|
.add("status", track.toBangumiStatus())
|
||||||
|
@ -69,7 +68,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun search(search: String): List<TrackSearch> {
|
suspend fun search(search: String): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
|
val url = "$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
|
||||||
.toUri()
|
.toUri()
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
|
@ -117,7 +116,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track): Track? {
|
suspend fun findLibManga(track: Track): Track? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
authClient.newCall(GET("$apiUrl/subject/${track.media_id}"))
|
authClient.newCall(GET("$apiUrl/subject/${track.media_id}"))
|
||||||
.await()
|
.await()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
|
@ -126,7 +125,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun statusLibManga(track: Track): Track? {
|
suspend fun statusLibManga(track: Track): Track? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
||||||
val requestUserRead = Request.Builder()
|
val requestUserRead = Request.Builder()
|
||||||
.url(urlUserRead)
|
.url(urlUserRead)
|
||||||
|
@ -147,7 +146,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun accessToken(code: String): OAuth {
|
suspend fun accessToken(code: String): OAuth {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
client.newCall(accessTokenRequest(code))
|
client.newCall(accessTokenRequest(code))
|
||||||
.await()
|
.await()
|
||||||
.parseAs()
|
.parseAs()
|
||||||
|
|
|
@ -8,8 +8,7 @@ import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.network.jsonMime
|
import eu.kanade.tachiyomi.network.jsonMime
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
import kotlinx.serialization.json.int
|
import kotlinx.serialization.json.int
|
||||||
|
@ -31,7 +30,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
suspend fun addLibManga(track: Track, userId: String): Track {
|
suspend fun addLibManga(track: Track, userId: String): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val data = buildJsonObject {
|
val data = buildJsonObject {
|
||||||
putJsonObject("data") {
|
putJsonObject("data") {
|
||||||
put("type", "libraryEntries")
|
put("type", "libraryEntries")
|
||||||
|
@ -76,7 +75,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateLibManga(track: Track): Track {
|
suspend fun updateLibManga(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val data = buildJsonObject {
|
val data = buildJsonObject {
|
||||||
putJsonObject("data") {
|
putJsonObject("data") {
|
||||||
put("type", "libraryEntries")
|
put("type", "libraryEntries")
|
||||||
|
@ -110,7 +109,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun search(query: String): List<TrackSearch> {
|
suspend fun search(query: String): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
authClient.newCall(GET(algoliaKeyUrl))
|
authClient.newCall(GET(algoliaKeyUrl))
|
||||||
.await()
|
.await()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
|
@ -122,7 +121,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun algoliaSearch(key: String, query: String): List<TrackSearch> {
|
private suspend fun algoliaSearch(key: String, query: String): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val jsonObject = buildJsonObject {
|
val jsonObject = buildJsonObject {
|
||||||
put("params", "query=$query$algoliaFilter")
|
put("params", "query=$query$algoliaFilter")
|
||||||
}
|
}
|
||||||
|
@ -151,7 +150,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track, userId: String): Track? {
|
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
||||||
.encodedQuery("filter[manga_id]=${track.media_id}&filter[user_id]=$userId")
|
.encodedQuery("filter[manga_id]=${track.media_id}&filter[user_id]=$userId")
|
||||||
.appendQueryParameter("include", "manga")
|
.appendQueryParameter("include", "manga")
|
||||||
|
@ -172,7 +171,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getLibManga(track: Track): Track {
|
suspend fun getLibManga(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
||||||
.encodedQuery("filter[id]=${track.media_id}")
|
.encodedQuery("filter[id]=${track.media_id}")
|
||||||
.appendQueryParameter("include", "manga")
|
.appendQueryParameter("include", "manga")
|
||||||
|
@ -193,7 +192,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun login(username: String, password: String): OAuth {
|
suspend fun login(username: String, password: String): OAuth {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val formBody: RequestBody = FormBody.Builder()
|
val formBody: RequestBody = FormBody.Builder()
|
||||||
.add("username", username)
|
.add("username", username)
|
||||||
.add("password", password)
|
.add("password", password)
|
||||||
|
@ -208,7 +207,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentUser(): String {
|
suspend fun getCurrentUser(): String {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "${baseUrl}users".toUri().buildUpon()
|
val url = "${baseUrl}users".toUri().buildUpon()
|
||||||
.encodedQuery("filter[self]=true")
|
.encodedQuery("filter[self]=true")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -10,10 +10,9 @@ import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import eu.kanade.tachiyomi.util.PkceUtil
|
import eu.kanade.tachiyomi.util.PkceUtil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.boolean
|
import kotlinx.serialization.json.boolean
|
||||||
import kotlinx.serialization.json.contentOrNull
|
import kotlinx.serialization.json.contentOrNull
|
||||||
|
@ -33,7 +32,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
suspend fun getAccessToken(authCode: String): OAuth {
|
suspend fun getAccessToken(authCode: String): OAuth {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val formBody: RequestBody = FormBody.Builder()
|
val formBody: RequestBody = FormBody.Builder()
|
||||||
.add("client_id", clientId)
|
.add("client_id", clientId)
|
||||||
.add("code", authCode)
|
.add("code", authCode)
|
||||||
|
@ -47,7 +46,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentUser(): String {
|
suspend fun getCurrentUser(): String {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("$baseApiUrl/users/@me")
|
.url("$baseApiUrl/users/@me")
|
||||||
.get()
|
.get()
|
||||||
|
@ -60,7 +59,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun search(query: String): List<TrackSearch> {
|
suspend fun search(query: String): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
||||||
.appendQueryParameter("q", query)
|
.appendQueryParameter("q", query)
|
||||||
.appendQueryParameter("nsfw", "true")
|
.appendQueryParameter("nsfw", "true")
|
||||||
|
@ -82,7 +81,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMangaDetails(id: Int): TrackSearch {
|
suspend fun getMangaDetails(id: Int): TrackSearch {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
val url = "$baseApiUrl/manga".toUri().buildUpon()
|
||||||
.appendPath(id.toString())
|
.appendPath(id.toString())
|
||||||
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
|
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
|
||||||
|
@ -113,7 +112,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getListItem(track: Track): Track {
|
suspend fun getListItem(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val formBody: RequestBody = FormBody.Builder()
|
val formBody: RequestBody = FormBody.Builder()
|
||||||
.add("status", track.toMyAnimeListStatus() ?: "reading")
|
.add("status", track.toMyAnimeListStatus() ?: "reading")
|
||||||
.build()
|
.build()
|
||||||
|
@ -129,7 +128,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun addItemToList(track: Track): Track {
|
suspend fun addItemToList(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val formBody: RequestBody = FormBody.Builder()
|
val formBody: RequestBody = FormBody.Builder()
|
||||||
.add("status", "reading")
|
.add("status", "reading")
|
||||||
.add("score", "0")
|
.add("score", "0")
|
||||||
|
@ -146,7 +145,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateItem(track: Track): Track {
|
suspend fun updateItem(track: Track): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val formBody: RequestBody = FormBody.Builder()
|
val formBody: RequestBody = FormBody.Builder()
|
||||||
.add("status", track.toMyAnimeListStatus() ?: "reading")
|
.add("status", track.toMyAnimeListStatus() ?: "reading")
|
||||||
.add("is_rereading", (track.status == MyAnimeList.REREADING).toString())
|
.add("is_rereading", (track.status == MyAnimeList.REREADING).toString())
|
||||||
|
@ -188,7 +187,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findListItems(query: String, offset: Int = 0): List<TrackSearch> {
|
suspend fun findListItems(query: String, offset: Int = 0): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val json = getListPage(offset)
|
val json = getListPage(offset)
|
||||||
val obj = json.jsonObject
|
val obj = json.jsonObject
|
||||||
|
|
||||||
|
@ -215,7 +214,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getListPage(offset: Int): JsonObject {
|
private suspend fun getListPage(offset: Int): JsonObject {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val urlBuilder = "$baseApiUrl/users/@me/mangalist".toUri().buildUpon()
|
val urlBuilder = "$baseApiUrl/users/@me/mangalist".toUri().buildUpon()
|
||||||
.appendQueryParameter("fields", "list_status")
|
.appendQueryParameter("fields", "list_status")
|
||||||
.appendQueryParameter("limit", listPaginationAmount.toString())
|
.appendQueryParameter("limit", listPaginationAmount.toString())
|
||||||
|
|
|
@ -9,9 +9,8 @@ import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.network.jsonMime
|
import eu.kanade.tachiyomi.network.jsonMime
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.JsonArray
|
import kotlinx.serialization.json.JsonArray
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
|
@ -30,7 +29,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
suspend fun addLibManga(track: Track, user_id: String): Track {
|
suspend fun addLibManga(track: Track, user_id: String): Track {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val payload = buildJsonObject {
|
val payload = buildJsonObject {
|
||||||
putJsonObject("user_rate") {
|
putJsonObject("user_rate") {
|
||||||
put("user_id", user_id)
|
put("user_id", user_id)
|
||||||
|
@ -54,7 +53,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
suspend fun updateLibManga(track: Track, user_id: String): Track = addLibManga(track, user_id)
|
suspend fun updateLibManga(track: Track, user_id: String): Track = addLibManga(track, user_id)
|
||||||
|
|
||||||
suspend fun search(search: String): List<TrackSearch> {
|
suspend fun search(search: String): List<TrackSearch> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val url = "$apiUrl/mangas".toUri().buildUpon()
|
val url = "$apiUrl/mangas".toUri().buildUpon()
|
||||||
.appendQueryParameter("order", "popularity")
|
.appendQueryParameter("order", "popularity")
|
||||||
.appendQueryParameter("search", search)
|
.appendQueryParameter("search", search)
|
||||||
|
@ -98,7 +97,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track, user_id: String): Track? {
|
suspend fun findLibManga(track: Track, user_id: String): Track? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
||||||
.appendPath(track.media_id.toString())
|
.appendPath(track.media_id.toString())
|
||||||
.build()
|
.build()
|
||||||
|
@ -138,7 +137,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun accessToken(code: String): OAuth {
|
suspend fun accessToken(code: String): OAuth {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
client.newCall(accessTokenRequest(code))
|
client.newCall(accessTokenRequest(code))
|
||||||
.await()
|
.await()
|
||||||
.parseAs()
|
.parseAs()
|
||||||
|
|
|
@ -6,8 +6,7 @@ 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.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class GithubUpdateChecker {
|
class GithubUpdateChecker {
|
||||||
|
@ -23,7 +22,7 @@ class GithubUpdateChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkForUpdate(): UpdateResult {
|
suspend fun checkForUpdate(): UpdateResult {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
networkService.client
|
networkService.client
|
||||||
.newCall(GET("https://api.github.com/repos/$repo/releases/latest"))
|
.newCall(GET("https://api.github.com/repos/$repo/releases/latest"))
|
||||||
.await()
|
.await()
|
||||||
|
|
|
@ -9,8 +9,7 @@ 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.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.coroutines.Dispatchers
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.JsonArray
|
import kotlinx.serialization.json.JsonArray
|
||||||
import kotlinx.serialization.json.int
|
import kotlinx.serialization.json.int
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
@ -24,7 +23,7 @@ internal class ExtensionGithubApi {
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
suspend fun findExtensions(): List<Extension.Available> {
|
suspend fun findExtensions(): List<Extension.Available> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withIOContext {
|
||||||
networkService.client
|
networkService.client
|
||||||
.newCall(GET("${REPO_URL_PREFIX}index.min.json"))
|
.newCall(GET("${REPO_URL_PREFIX}index.min.json"))
|
||||||
.await()
|
.await()
|
||||||
|
|
|
@ -55,13 +55,13 @@ class SearchPresenter(
|
||||||
|
|
||||||
replacingMangaRelay.call(true)
|
replacingMangaRelay.call(true)
|
||||||
|
|
||||||
launchIO {
|
presenterScope.launchIO {
|
||||||
val chapters = source.getChapterList(manga.toMangaInfo())
|
val chapters = source.getChapterList(manga.toMangaInfo())
|
||||||
.map { it.toSChapter() }
|
.map { it.toSChapter() }
|
||||||
|
|
||||||
migrateMangaInternal(source, chapters, prevManga, manga, replace)
|
migrateMangaInternal(source, chapters, prevManga, manga, replace)
|
||||||
}.invokeOnCompletion {
|
}.invokeOnCompletion {
|
||||||
launchUI { replacingMangaRelay.call(false) }
|
presenterScope.launchUI { replacingMangaRelay.call(false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
|
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
|
||||||
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
|
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asFlow
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
@ -213,12 +213,12 @@ open class BrowseSourcePresenter(
|
||||||
* @param mangas the list of manga to initialize.
|
* @param mangas the list of manga to initialize.
|
||||||
*/
|
*/
|
||||||
fun initializeMangas(mangas: List<Manga>) {
|
fun initializeMangas(mangas: List<Manga>) {
|
||||||
launchIO {
|
presenterScope.launchIO {
|
||||||
mangas.asFlow()
|
mangas.asFlow()
|
||||||
.filter { it.thumbnail_url == null && !it.initialized }
|
.filter { it.thumbnail_url == null && !it.initialized }
|
||||||
.map { getMangaDetails(it) }
|
.map { getMangaDetails(it) }
|
||||||
.onEach {
|
.onEach {
|
||||||
launchUI {
|
withUIContext {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
view?.onMangaInitialized(it)
|
view?.onMangaInitialized(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
setSelectedNavItem(startScreenId)
|
setSelectedNavItem(startScreenId)
|
||||||
} else if (shouldHandleExitConfirmation()) {
|
} else if (shouldHandleExitConfirmation()) {
|
||||||
// Exit confirmation (resets after 2 seconds)
|
// Exit confirmation (resets after 2 seconds)
|
||||||
launchUI { resetExitConfirmation() }
|
lifecycleScope.launchUI { resetExitConfirmation() }
|
||||||
} else if (backstackSize == 1 || !router.handleBack()) {
|
} else if (backstackSize == 1 || !router.handleBack()) {
|
||||||
// Regular back
|
// Regular back
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
|
|
|
@ -26,7 +26,7 @@ import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||||
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.await
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.prepUpdateCover
|
import eu.kanade.tachiyomi.util.prepUpdateCover
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
||||||
|
@ -161,7 +161,7 @@ class MangaPresenter(
|
||||||
*/
|
*/
|
||||||
fun fetchMangaFromSource(manualFetch: Boolean = false) {
|
fun fetchMangaFromSource(manualFetch: Boolean = false) {
|
||||||
if (fetchMangaJob?.isActive == true) return
|
if (fetchMangaJob?.isActive == true) return
|
||||||
fetchMangaJob = launchIO {
|
fetchMangaJob = presenterScope.launchIO {
|
||||||
try {
|
try {
|
||||||
val networkManga = source.getMangaDetails(manga.toMangaInfo())
|
val networkManga = source.getMangaDetails(manga.toMangaInfo())
|
||||||
val sManga = networkManga.toSManga()
|
val sManga = networkManga.toSManga()
|
||||||
|
@ -170,9 +170,9 @@ class MangaPresenter(
|
||||||
manga.initialized = true
|
manga.initialized = true
|
||||||
db.insertManga(manga).await()
|
db.insertManga(manga).await()
|
||||||
|
|
||||||
launchUI { view?.onFetchMangaInfoDone() }
|
withUIContext { view?.onFetchMangaInfoDone() }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
launchUI { view?.onFetchMangaInfoError(e) }
|
withUIContext { view?.onFetchMangaInfoError(e) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,9 +360,9 @@ class MangaPresenter(
|
||||||
downloadNewChapters(newChapters)
|
downloadNewChapters(newChapters)
|
||||||
}
|
}
|
||||||
|
|
||||||
launchUI { view?.onFetchChaptersDone() }
|
withUIContext { view?.onFetchChaptersDone() }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
launchUI { view?.onFetchChaptersError(e) }
|
withUIContext { view?.onFetchChaptersError(e) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,12 @@ import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.util.lang.await
|
import eu.kanade.tachiyomi.util.lang.await
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
|
import kotlinx.coroutines.supervisorScope
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
@ -59,20 +60,22 @@ class TrackPresenter(
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
refreshJob?.cancel()
|
refreshJob?.cancel()
|
||||||
refreshJob = launchIO {
|
refreshJob = launchIO {
|
||||||
try {
|
supervisorScope {
|
||||||
trackList
|
try {
|
||||||
.filter { it.track != null }
|
trackList
|
||||||
.map {
|
.filter { it.track != null }
|
||||||
async {
|
.map {
|
||||||
val track = it.service.refresh(it.track!!)
|
async {
|
||||||
db.insertTrack(track).await()
|
val track = it.service.refresh(it.track!!)
|
||||||
|
db.insertTrack(track).await()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.awaitAll()
|
||||||
.awaitAll()
|
|
||||||
|
|
||||||
view?.onRefreshDone()
|
withUIContext { view?.onRefreshDone() }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
view?.onRefreshError(e)
|
withUIContext { view?.onRefreshError(e) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,9 +85,9 @@ class TrackPresenter(
|
||||||
searchJob = launchIO {
|
searchJob = launchIO {
|
||||||
try {
|
try {
|
||||||
val results = service.search(query)
|
val results = service.search(query)
|
||||||
launchUI { view?.onSearchResults(results) }
|
withUIContext { view?.onSearchResults(results) }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
launchUI { view?.onSearchResultsError(e) }
|
withUIContext { view?.onSearchResultsError(e) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +100,7 @@ class TrackPresenter(
|
||||||
service.bind(item)
|
service.bind(item)
|
||||||
db.insertTrack(item).await()
|
db.insertTrack(item).await()
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
launchUI { context.toast(e.message) }
|
withUIContext { context.toast(e.message) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -114,9 +117,9 @@ class TrackPresenter(
|
||||||
try {
|
try {
|
||||||
service.update(track)
|
service.update(track)
|
||||||
db.insertTrack(track).await()
|
db.insertTrack(track).await()
|
||||||
view?.onRefreshDone()
|
withUIContext { view?.onRefreshDone() }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
launchUI { view?.onRefreshError(e) }
|
withUIContext { view?.onRefreshError(e) }
|
||||||
|
|
||||||
// Restart on error to set old values
|
// Restart on error to set old values
|
||||||
fetchTrackings()
|
fetchTrackings()
|
||||||
|
|
|
@ -8,7 +8,7 @@ import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.widget.preference.LoginDialogPreference
|
import eu.kanade.tachiyomi.widget.preference.LoginDialogPreference
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
@ -46,11 +46,11 @@ class TrackLoginDialog(
|
||||||
try {
|
try {
|
||||||
service.login(user, pass)
|
service.login(user, pass)
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
launchUI { view?.context?.toast(R.string.login_success) }
|
withUIContext { view?.context?.toast(R.string.login_success) }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
binding?.login?.progress = -1
|
binding?.login?.progress = -1
|
||||||
binding?.login?.setText(R.string.unknown_error)
|
binding?.login?.setText(R.string.unknown_error)
|
||||||
launchUI { e.message?.let { view?.context?.toast(it) } }
|
withUIContext { e.message?.let { view?.context?.toast(it) } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
fun launchUI(block: suspend CoroutineScope.() -> Unit): Job =
|
fun launchUI(block: suspend CoroutineScope.() -> Unit): Job =
|
||||||
GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT, block)
|
GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT, block)
|
||||||
|
@ -15,3 +16,13 @@ fun launchIO(block: suspend CoroutineScope.() -> Unit): Job =
|
||||||
|
|
||||||
fun launchNow(block: suspend CoroutineScope.() -> Unit): Job =
|
fun launchNow(block: suspend CoroutineScope.() -> Unit): Job =
|
||||||
GlobalScope.launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED, block)
|
GlobalScope.launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED, block)
|
||||||
|
|
||||||
|
fun CoroutineScope.launchUI(block: suspend CoroutineScope.() -> Unit): Job =
|
||||||
|
launch(Dispatchers.Main, block = block)
|
||||||
|
|
||||||
|
fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job =
|
||||||
|
launch(Dispatchers.IO, block = block)
|
||||||
|
|
||||||
|
suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block)
|
||||||
|
|
||||||
|
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block)
|
||||||
|
|
Reference in a new issue