Przeglądaj źródła

Convert tracker add/update/login methods to coroutines

arkon 4 lat temu
rodzic
commit
ea33179a95

+ 3 - 4
app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt

@@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.model.TrackSearch
 import eu.kanade.tachiyomi.network.NetworkHelper
 import okhttp3.OkHttpClient
-import rx.Completable
 import rx.Observable
 import uy.kohesive.injekt.injectLazy
 
@@ -43,9 +42,9 @@ abstract class TrackService(val id: Int) {
 
     abstract fun displayScore(track: Track): String
 
-    abstract fun add(track: Track): Observable<Track>
+    abstract suspend fun add(track: Track): Track
 
-    abstract fun update(track: Track): Observable<Track>
+    abstract suspend fun update(track: Track): Track
 
     abstract fun bind(track: Track): Observable<Track>
 
@@ -53,7 +52,7 @@ abstract class TrackService(val id: Int) {
 
     abstract fun refresh(track: Track): Observable<Track>
 
-    abstract fun login(username: String, password: String): Completable
+    abstract suspend fun login(username: String, password: String)
 
     @CallSuper
     open fun logout() {

+ 17 - 21
app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt

@@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.util.lang.runAsObservable
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
-import rx.Completable
 import rx.Observable
 import uy.kohesive.injekt.injectLazy
 
@@ -132,23 +131,19 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
         }
     }
 
-    override fun add(track: Track): Observable<Track> {
-        return runAsObservable({ api.addLibManga(track) })
+    override suspend fun add(track: Track): Track {
+        return api.addLibManga(track)
     }
 
-    override fun update(track: Track): Observable<Track> {
+    override suspend fun update(track: Track): Track {
         // If user was using API v1 fetch library_id
         if (track.library_id == null || track.library_id!! == 0L) {
-            return runAsObservable({ api.findLibManga(track, getUsername().toInt()) }).flatMap {
-                if (it == null) {
-                    throw Exception("$track not found on user library")
-                }
-                track.library_id = it.library_id
-                runAsObservable({ api.updateLibManga(track) })
-            }
+            val libManga = api.findLibManga(track, getUsername().toInt())
+                ?: throw Exception("$track not found on user library")
+            track.library_id = libManga.library_id
         }
 
-        return runAsObservable({ api.updateLibManga(track) })
+        return api.updateLibManga(track)
     }
 
     override fun bind(track: Track): Observable<Track> {
@@ -157,12 +152,12 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
                 if (remoteTrack != null) {
                     track.copyPersonalFrom(remoteTrack)
                     track.library_id = remoteTrack.library_id
-                    update(track)
+                    runAsObservable({ update(track) })
                 } else {
                     // Set default fields if it's not found in the list
                     track.score = DEFAULT_SCORE.toFloat()
                     track.status = DEFAULT_STATUS
-                    add(track)
+                    runAsObservable({ add(track) })
                 }
             }
     }
@@ -180,17 +175,18 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
             }
     }
 
-    override fun login(username: String, password: String) = login(password)
+    override suspend fun login(username: String, password: String) = login(password)
 
-    fun login(token: String): Completable {
-        val oauth = api.createOAuth(token)
-        interceptor.setAuth(oauth)
-        return runAsObservable({ api.getCurrentUser() }).map { (username, scoreType) ->
+    suspend fun login(token: String) {
+        try {
+            val oauth = api.createOAuth(token)
+            interceptor.setAuth(oauth)
+            val (username, scoreType) = api.getCurrentUser()
             scorePreference.set(scoreType)
             saveCredentials(username.toString(), oauth.access_token)
-        }.doOnError {
+        } catch (e: Throwable) {
             logout()
-        }.toCompletable()
+        }
     }
 
     override fun logout() {

+ 13 - 15
app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt

@@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.util.lang.runAsObservable
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
-import rx.Completable
 import rx.Observable
 import uy.kohesive.injekt.injectLazy
 
@@ -32,12 +31,12 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
         return track.score.toInt().toString()
     }
 
-    override fun add(track: Track): Observable<Track> {
-        return runAsObservable({ api.addLibManga(track) })
+    override suspend fun add(track: Track): Track {
+        return api.addLibManga(track)
     }
 
-    override fun update(track: Track): Observable<Track> {
-        return runAsObservable({ api.updateLibManga(track) })
+    override suspend fun update(track: Track): Track {
+        return api.updateLibManga(track)
     }
 
     override fun bind(track: Track): Observable<Track> {
@@ -54,8 +53,8 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
                         // Set default fields if it's not found in the list
                         track.score = DEFAULT_SCORE.toFloat()
                         track.status = DEFAULT_STATUS
-                        add(track)
-                        update(track)
+                        runAsObservable({ add(track) })
+                        runAsObservable({ update(track) })
                     }
                 }
             }
@@ -101,17 +100,16 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
 
     override fun getCompletionStatus(): Int = COMPLETED
 
-    override fun login(username: String, password: String) = login(password)
+    override suspend fun login(username: String, password: String) = login(password)
 
-    fun login(code: String): Completable {
-        return runAsObservable({ api.accessToken(code) }).map { oauth: OAuth? ->
+    suspend fun login(code: String) {
+        try {
+            val oauth = api.accessToken(code)
             interceptor.newAuth(oauth)
-            if (oauth != null) {
-                saveCredentials(oauth.user_id.toString(), oauth.access_token)
-            }
-        }.doOnError {
+            saveCredentials(oauth.user_id.toString(), oauth.access_token)
+        } catch (e: Throwable) {
             logout()
-        }.toCompletable()
+        }
     }
 
     fun saveToken(oauth: OAuth?) {

+ 15 - 14
app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt

@@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.util.lang.runAsObservable
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
-import rx.Completable
 import rx.Observable
 import uy.kohesive.injekt.injectLazy
 import java.text.DecimalFormat
@@ -71,12 +70,12 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
         return df.format(track.score)
     }
 
-    override fun add(track: Track): Observable<Track> {
-        return runAsObservable({ api.addLibManga(track, getUserId()) })
+    override suspend fun add(track: Track): Track {
+        return api.addLibManga(track, getUserId())
     }
 
-    override fun update(track: Track): Observable<Track> {
-        return runAsObservable({ api.updateLibManga(track) })
+    override suspend fun update(track: Track): Track {
+        return api.updateLibManga(track)
     }
 
     override fun bind(track: Track): Observable<Track> {
@@ -85,11 +84,11 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
                 if (remoteTrack != null) {
                     track.copyPersonalFrom(remoteTrack)
                     track.media_id = remoteTrack.media_id
-                    update(track)
+                    runAsObservable({ update(track) })
                 } else {
                     track.score = DEFAULT_SCORE
                     track.status = DEFAULT_STATUS
-                    add(track)
+                    runAsObservable({ add(track) })
                 }
             }
     }
@@ -107,13 +106,15 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
             }
     }
 
-    override fun login(username: String, password: String): Completable {
-        return runAsObservable({ api.login(username, password) })
-            .doOnNext { interceptor.newAuth(it) }
-            .flatMap { runAsObservable({ api.getCurrentUser() }) }
-            .doOnNext { userId -> saveCredentials(username, userId) }
-            .doOnError { logout() }
-            .toCompletable()
+    override suspend fun login(username: String, password: String) {
+        try {
+            val token = api.login(username, password)
+            interceptor.newAuth(token)
+            val userId = api.getCurrentUser()
+            saveCredentials(username, userId)
+        } catch (e: Throwable) {
+            logout()
+        }
     }
 
     override fun logout() {

+ 11 - 20
app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt

@@ -7,15 +7,10 @@ import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.data.track.TrackService
 import eu.kanade.tachiyomi.data.track.model.TrackSearch
 import eu.kanade.tachiyomi.util.lang.runAsObservable
-import kotlinx.coroutines.runBlocking
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
-import rx.Completable
 import rx.Observable
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
-import timber.log.Timber
 import uy.kohesive.injekt.injectLazy
 
 class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
@@ -67,12 +62,12 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
         return track.score.toInt().toString()
     }
 
-    override fun add(track: Track): Observable<Track> {
-        return runAsObservable({ api.addItemToList(track) })
+    override suspend fun add(track: Track): Track {
+        return api.addItemToList(track)
     }
 
-    override fun update(track: Track): Observable<Track> {
-        return runAsObservable({ api.updateItem(track) })
+    override suspend fun update(track: Track): Track {
+        return api.updateItem(track)
     }
 
     override fun bind(track: Track): Observable<Track> {
@@ -88,21 +83,17 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
         return runAsObservable({ api.getListItem(track) })
     }
 
-    override fun login(username: String, password: String) = login(password)
+    override suspend fun login(username: String, password: String) = login(password)
 
-    fun login(authCode: String): Completable {
-        return Completable.fromCallable {
-            val oauth = runBlocking { api.getAccessToken(authCode) }
+    suspend fun login(authCode: String) {
+        try {
+            val oauth = api.getAccessToken(authCode)
             interceptor.setAuth(oauth)
-            val username = runBlocking { api.getCurrentUser() }
+            val username = api.getCurrentUser()
             saveCredentials(username, oauth.access_token)
+        } catch (e: Throwable) {
+            logout()
         }
-            .doOnError {
-                Timber.e(it)
-                logout()
-            }
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
     }
 
     override fun logout() {

+ 14 - 16
app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt

@@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.util.lang.runAsObservable
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
-import rx.Completable
 import rx.Observable
 import uy.kohesive.injekt.injectLazy
 
@@ -44,12 +43,12 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
         return track.score.toInt().toString()
     }
 
-    override fun add(track: Track): Observable<Track> {
-        return runAsObservable({ api.addLibManga(track, getUsername()) })
+    override suspend fun add(track: Track): Track {
+        return api.addLibManga(track, getUsername())
     }
 
-    override fun update(track: Track): Observable<Track> {
-        return runAsObservable({ api.updateLibManga(track, getUsername()) })
+    override suspend fun update(track: Track): Track {
+        return api.updateLibManga(track, getUsername())
     }
 
     override fun bind(track: Track): Observable<Track> {
@@ -58,12 +57,12 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
                 if (remoteTrack != null) {
                     track.copyPersonalFrom(remoteTrack)
                     track.library_id = remoteTrack.library_id
-                    update(track)
+                    runAsObservable({ update(track) })
                 } else {
                     // Set default fields if it's not found in the list
                     track.score = DEFAULT_SCORE.toFloat()
                     track.status = DEFAULT_STATUS
-                    add(track)
+                    runAsObservable({ add(track) })
                 }
             }
     }
@@ -105,18 +104,17 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
 
     override fun getCompletionStatus(): Int = COMPLETED
 
-    override fun login(username: String, password: String) = login(password)
+    override suspend fun login(username: String, password: String) = login(password)
 
-    fun login(code: String): Completable {
-        return runAsObservable({ api.accessToken(code) }).map { oauth: OAuth? ->
+    suspend fun login(code: String) {
+        try {
+            val oauth = api.accessToken(code)
             interceptor.newAuth(oauth)
-            if (oauth != null) {
-                val user = api.getCurrentUser()
-                saveCredentials(user.toString(), oauth.access_token)
-            }
-        }.doOnError {
+            val user = api.getCurrentUser()
+            saveCredentials(user.toString(), oauth.access_token)
+        } catch (e: Throwable) {
             logout()
-        }.toCompletable()
+        }
     }
 
     fun saveToken(oauth: OAuth?) {

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt

@@ -131,7 +131,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
             if (responseBody.isEmpty()) {
                 throw Exception("Null Response")
             }
-            json.decodeFromString<OAuth>(responseBody)
+            json.decodeFromString(responseBody)
         }
     }
 

+ 15 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackPresenter.kt

@@ -8,6 +8,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.TrackService
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.util.lang.await
+import eu.kanade.tachiyomi.util.lang.launchIO
+import eu.kanade.tachiyomi.util.lang.launchUI
 import eu.kanade.tachiyomi.util.system.toast
 import rx.Observable
 import rx.Subscription
@@ -107,19 +110,22 @@ class TrackPresenter(
     }
 
     private fun updateRemote(track: Track, service: TrackService) {
-        service.update(track)
-            .flatMap { db.insertTrack(track).asRxObservable() }
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .subscribeFirst(
-                { view, _ -> view.onRefreshDone() },
-                { view, error ->
-                    view.onRefreshError(error)
+        launchIO {
+            try {
+                service.update(track)
+                db.insertTrack(track).await()
+                launchUI {
+                    view!!.onRefreshDone()
+                }
+            } catch (e: Throwable) {
+                launchUI {
+                    view!!.onRefreshError(e)
 
                     // Restart on error to set old values
                     fetchTrackings()
                 }
-            )
+            }
+        }
     }
 
     fun setStatus(item: TrackItem, index: Int) {

+ 20 - 22
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -21,13 +21,15 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
 import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 import eu.kanade.tachiyomi.util.isLocal
+import eu.kanade.tachiyomi.util.lang.await
 import eu.kanade.tachiyomi.util.lang.byteSize
 import eu.kanade.tachiyomi.util.lang.launchIO
 import eu.kanade.tachiyomi.util.lang.takeBytes
 import eu.kanade.tachiyomi.util.storage.DiskUtil
 import eu.kanade.tachiyomi.util.system.ImageUtil
 import eu.kanade.tachiyomi.util.updateCoverLastModified
-import rx.Completable
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers
@@ -661,29 +663,25 @@ class ReaderPresenter(
 
         val trackManager = Injekt.get<TrackManager>()
 
-        db.getTracks(manga).asRxSingle()
-            .flatMapCompletable { trackList ->
-                Completable.concat(
-                    trackList.map { track ->
-                        val service = trackManager.getService(track.sync_id)
-                        if (service != null && service.isLogged && chapterRead > track.last_chapter_read) {
-                            track.last_chapter_read = chapterRead
-
-                            // We wan't these to execute even if the presenter is destroyed and leaks
-                            // for a while. The view can still be garbage collected.
-                            Observable.defer { service.update(track) }
-                                .map { db.insertTrack(track).executeAsBlocking() }
-                                .toCompletable()
-                                .onErrorComplete()
-                        } else {
-                            Completable.complete()
+        launchIO {
+            db.getTracks(manga).await()
+                .mapNotNull { track ->
+                    val service = trackManager.getService(track.sync_id)
+                    if (service != null && service.isLogged && chapterRead > track.last_chapter_read) {
+                        track.last_chapter_read = chapterRead
+
+                        // We want these to execute even if the presenter is destroyed and leaks
+                        // for a while. The view can still be garbage collected.
+                        async {
+                            service.update(track)
+                            db.insertTrack(track).await()
                         }
+                    } else {
+                        null
                     }
-                )
-            }
-            .onErrorComplete()
-            .subscribeOn(Schedulers.io())
-            .subscribe()
+                }
+                .awaitAll()
+        }
     }
 
     /**

+ 8 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/AnilistLoginActivity.kt

@@ -1,8 +1,8 @@
 package eu.kanade.tachiyomi.ui.setting.track
 
 import android.net.Uri
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
+import eu.kanade.tachiyomi.util.lang.launchIO
+import eu.kanade.tachiyomi.util.lang.launchUI
 
 class AnilistLoginActivity : BaseOAuthLoginActivity() {
 
@@ -10,17 +10,12 @@ class AnilistLoginActivity : BaseOAuthLoginActivity() {
         val regex = "(?:access_token=)(.*?)(?:&)".toRegex()
         val matchResult = regex.find(data?.fragment.toString())
         if (matchResult?.groups?.get(1) != null) {
-            trackManager.aniList.login(matchResult.groups[1]!!.value)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(
-                    {
-                        returnToSettings()
-                    },
-                    {
-                        returnToSettings()
-                    }
-                )
+            launchIO {
+                trackManager.aniList.login(matchResult.groups[1]!!.value)
+                launchUI {
+                    returnToSettings()
+                }
+            }
         } else {
             trackManager.aniList.logout()
             returnToSettings()

+ 8 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BangumiLoginActivity.kt

@@ -1,25 +1,20 @@
 package eu.kanade.tachiyomi.ui.setting.track
 
 import android.net.Uri
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
+import eu.kanade.tachiyomi.util.lang.launchIO
+import eu.kanade.tachiyomi.util.lang.launchUI
 
 class BangumiLoginActivity : BaseOAuthLoginActivity() {
 
     override fun handleResult(data: Uri?) {
         val code = data?.getQueryParameter("code")
         if (code != null) {
-            trackManager.bangumi.login(code)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(
-                    {
-                        returnToSettings()
-                    },
-                    {
-                        returnToSettings()
-                    }
-                )
+            launchIO {
+                trackManager.bangumi.login(code)
+                launchUI {
+                    returnToSettings()
+                }
+            }
         } else {
             trackManager.bangumi.logout()
             returnToSettings()

+ 8 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/MyAnimeListLoginActivity.kt

@@ -1,25 +1,20 @@
 package eu.kanade.tachiyomi.ui.setting.track
 
 import android.net.Uri
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
+import eu.kanade.tachiyomi.util.lang.launchIO
+import eu.kanade.tachiyomi.util.lang.launchUI
 
 class MyAnimeListLoginActivity : BaseOAuthLoginActivity() {
 
     override fun handleResult(data: Uri?) {
         val code = data?.getQueryParameter("code")
         if (code != null) {
-            trackManager.myAnimeList.login(code)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(
-                    {
-                        returnToSettings()
-                    },
-                    {
-                        returnToSettings()
-                    }
-                )
+            launchIO {
+                trackManager.myAnimeList.login(code)
+                launchUI {
+                    returnToSettings()
+                }
+            }
         } else {
             trackManager.myAnimeList.logout()
             returnToSettings()

+ 8 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/ShikimoriLoginActivity.kt

@@ -1,25 +1,20 @@
 package eu.kanade.tachiyomi.ui.setting.track
 
 import android.net.Uri
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
+import eu.kanade.tachiyomi.util.lang.launchIO
+import eu.kanade.tachiyomi.util.lang.launchUI
 
 class ShikimoriLoginActivity : BaseOAuthLoginActivity() {
 
     override fun handleResult(data: Uri?) {
         val code = data?.getQueryParameter("code")
         if (code != null) {
-            trackManager.shikimori.login(code)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(
-                    {
-                        returnToSettings()
-                    },
-                    {
-                        returnToSettings()
-                    }
-                )
+            launchIO {
+                trackManager.shikimori.login(code)
+                launchUI {
+                    returnToSettings()
+                }
+            }
         } else {
             trackManager.shikimori.logout()
             returnToSettings()

+ 12 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLoginDialog.kt

@@ -7,10 +7,10 @@ import androidx.core.os.bundleOf
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.TrackService
+import eu.kanade.tachiyomi.util.lang.launchIO
+import eu.kanade.tachiyomi.util.lang.launchUI
 import eu.kanade.tachiyomi.util.system.toast
 import eu.kanade.tachiyomi.widget.preference.LoginDialogPreference
-import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 
@@ -34,8 +34,6 @@ class TrackLoginDialog(
     }
 
     override fun checkLogin() {
-        requestSubscription?.unsubscribe()
-
         if (binding!!.username.text.isNullOrEmpty() || binding!!.password.text.isNullOrEmpty()) {
             return
         }
@@ -44,20 +42,21 @@ class TrackLoginDialog(
         val user = binding!!.username.text.toString()
         val pass = binding!!.password.text.toString()
 
-        requestSubscription = service.login(user, pass)
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .subscribe(
-                {
+        launchIO {
+            try {
+                service.login(user, pass)
+                launchUI {
                     dialog?.dismiss()
                     view?.context?.toast(R.string.login_success)
-                },
-                { error ->
+                }
+            } catch (e: Throwable) {
+                launchUI {
                     binding!!.login.progress = -1
                     binding!!.login.setText(R.string.unknown_error)
-                    error.message?.let { view?.context?.toast(it) }
+                    e.message?.let { view?.context?.toast(it) }
                 }
-            )
+            }
+        }
     }
 
     override fun onDialogClosed() {

+ 0 - 4
app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt

@@ -13,7 +13,6 @@ import com.dd.processbutton.iml.ActionProcessButton
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.databinding.PrefAccountLoginBinding
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
-import rx.Subscription
 import uy.kohesive.injekt.injectLazy
 
 abstract class LoginDialogPreference(
@@ -28,8 +27,6 @@ abstract class LoginDialogPreference(
 
     val preferences: PreferencesHelper by injectLazy()
 
-    var requestSubscription: Subscription? = null
-
     override fun onCreateDialog(savedViewState: Bundle?): Dialog {
         binding = PrefAccountLoginBinding.inflate(LayoutInflater.from(activity!!))
         var dialog = MaterialDialog(activity!!)
@@ -64,7 +61,6 @@ abstract class LoginDialogPreference(
     }
 
     open fun onDialogClosed() {
-        requestSubscription?.unsubscribe()
         binding = null
     }