Browse Source

Minor improvements for sync services

len 8 years ago
parent
commit
18cdddf433

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaSync.java

@@ -6,7 +6,7 @@ import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteType;
 import java.io.Serializable;
 
 import eu.kanade.tachiyomi.data.database.tables.MangaSyncTable;
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService;
+import eu.kanade.tachiyomi.data.mangasync.MangaSyncService;
 
 @StorIOSQLiteType(table = MangaSyncTable.TABLE)
 public class MangaSync implements Serializable {

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaSyncQueries.kt

@@ -6,7 +6,7 @@ import eu.kanade.tachiyomi.data.database.DbProvider
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.MangaSync
 import eu.kanade.tachiyomi.data.database.tables.MangaSyncTable
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
+import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
 
 interface MangaSyncQueries : DbProvider {
 

+ 5 - 10
app/src/main/java/eu/kanade/tachiyomi/data/mangasync/MangaSyncManager.kt

@@ -1,23 +1,18 @@
 package eu.kanade.tachiyomi.data.mangasync
 
 import android.content.Context
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
-import eu.kanade.tachiyomi.data.mangasync.services.MyAnimeList
+import eu.kanade.tachiyomi.data.mangasync.myanimelist.MyAnimeList
 
 class MangaSyncManager(private val context: Context) {
 
-    val services: List<MangaSyncService>
-    val myAnimeList: MyAnimeList
-
     companion object {
         const val MYANIMELIST = 1
     }
 
-    init {
-        myAnimeList = MyAnimeList(context, MYANIMELIST)
-        services = listOf(myAnimeList)
-    }
+    val myAnimeList = MyAnimeList(context, MYANIMELIST)
+
+    val services = listOf(myAnimeList)
 
-    fun getService(id: Int): MangaSyncService = services.find { it.id == id }!!
+    fun getService(id: Int) = services.find { it.id == id }
 
 }

+ 56 - 0
app/src/main/java/eu/kanade/tachiyomi/data/mangasync/MangaSyncService.kt

@@ -0,0 +1,56 @@
+package eu.kanade.tachiyomi.data.mangasync
+
+import android.content.Context
+import android.support.annotation.CallSuper
+import eu.kanade.tachiyomi.App
+import eu.kanade.tachiyomi.data.database.models.MangaSync
+import eu.kanade.tachiyomi.data.network.NetworkHelper
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import okhttp3.OkHttpClient
+import rx.Completable
+import rx.Observable
+import javax.inject.Inject
+
+abstract class MangaSyncService(private val context: Context, val id: Int) {
+
+    @Inject lateinit var preferences: PreferencesHelper
+    @Inject lateinit var networkService: NetworkHelper
+
+    init {
+        App.get(context).component.inject(this)
+    }
+
+    open val client: OkHttpClient
+        get() = networkService.client
+
+    // Name of the manga sync service to display
+    abstract val name: String
+
+    abstract fun login(username: String, password: String): Completable
+
+    open val isLogged: Boolean
+        get() = !getUsername().isEmpty() &&
+                !getPassword().isEmpty()
+
+    abstract fun add(manga: MangaSync): Observable<MangaSync>
+
+    abstract fun update(manga: MangaSync): Observable<MangaSync>
+
+    abstract fun bind(manga: MangaSync): Observable<MangaSync>
+
+    abstract fun getStatus(status: Int): String
+
+    fun saveCredentials(username: String, password: String) {
+        preferences.setMangaSyncCredentials(this, username, password)
+    }
+
+    @CallSuper
+    open fun logout() {
+        preferences.setMangaSyncCredentials(this, "", "")
+    }
+
+    fun getUsername() = preferences.mangaSyncUsername(this)
+
+    fun getPassword() = preferences.mangaSyncPassword(this)
+
+}

+ 5 - 7
app/src/main/java/eu/kanade/tachiyomi/data/mangasync/UpdateMangaSyncService.kt

@@ -48,15 +48,13 @@ class UpdateMangaSyncService : Service() {
 
     private fun updateLastChapterRead(mangaSync: MangaSync, startId: Int) {
         val sync = syncManager.getService(mangaSync.sync_id)
+        if (sync == null) {
+            stopSelf(startId)
+            return
+        }
 
         subscriptions.add(Observable.defer { sync.update(mangaSync) }
-                .flatMap {
-                    if (it.isSuccessful) {
-                        db.insertMangaSync(mangaSync).asRxObservable()
-                    } else {
-                        Observable.error(Exception("Could not update manga in remote service"))
-                    }
-                }
+                .flatMap { db.insertMangaSync(mangaSync).asRxObservable() }
                 .subscribeOn(Schedulers.io())
                 .observeOn(AndroidSchedulers.mainThread())
                 .subscribe({ stopSelf(startId) },

+ 0 - 42
app/src/main/java/eu/kanade/tachiyomi/data/mangasync/base/MangaSyncService.kt

@@ -1,42 +0,0 @@
-package eu.kanade.tachiyomi.data.mangasync.base
-
-import android.content.Context
-import eu.kanade.tachiyomi.App
-import eu.kanade.tachiyomi.data.database.models.MangaSync
-import eu.kanade.tachiyomi.data.network.NetworkHelper
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
-import okhttp3.OkHttpClient
-import okhttp3.Response
-import rx.Observable
-import javax.inject.Inject
-
-abstract class MangaSyncService(private val context: Context, val id: Int) {
-
-    @Inject lateinit var preferences: PreferencesHelper
-    @Inject lateinit var networkService: NetworkHelper
-
-    init {
-        App.get(context).component.inject(this)
-    }
-
-    open val client: OkHttpClient
-        get() = networkService.client
-
-    // Name of the manga sync service to display
-    abstract val name: String
-
-    abstract fun login(username: String, password: String): Observable<Boolean>
-
-    open val isLogged: Boolean
-        get() = !preferences.mangaSyncUsername(this).isEmpty() &&
-                !preferences.mangaSyncPassword(this).isEmpty()
-
-    abstract fun update(manga: MangaSync): Observable<Response>
-
-    abstract fun add(manga: MangaSync): Observable<Response>
-
-    abstract fun bind(manga: MangaSync): Observable<Response>
-
-    abstract fun getStatus(status: Int): String
-
-}

+ 71 - 73
app/src/main/java/eu/kanade/tachiyomi/data/mangasync/services/MyAnimeList.kt → app/src/main/java/eu/kanade/tachiyomi/data/mangasync/myanimelist/MyAnimeList.kt

@@ -1,26 +1,29 @@
-package eu.kanade.tachiyomi.data.mangasync.services
+package eu.kanade.tachiyomi.data.mangasync.myanimelist
 
 import android.content.Context
 import android.net.Uri
 import android.util.Xml
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.MangaSync
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
+import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
 import eu.kanade.tachiyomi.data.network.GET
 import eu.kanade.tachiyomi.data.network.POST
 import eu.kanade.tachiyomi.data.network.asObservable
 import eu.kanade.tachiyomi.util.selectInt
 import eu.kanade.tachiyomi.util.selectText
-import okhttp3.*
+import okhttp3.Credentials
+import okhttp3.FormBody
+import okhttp3.Headers
+import okhttp3.RequestBody
 import org.jsoup.Jsoup
 import org.xmlpull.v1.XmlSerializer
+import rx.Completable
 import rx.Observable
 import java.io.StringWriter
 
 class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(context, id) {
 
     private lateinit var headers: Headers
-    private lateinit var username: String
 
     companion object {
         val BASE_URL = "http://myanimelist.net"
@@ -41,8 +44,8 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
     }
 
     init {
-        val username = preferences.mangaSyncUsername(this)
-        val password = preferences.mangaSyncPassword(this)
+        val username = getUsername()
+        val password = getPassword()
 
         if (!username.isEmpty() && !password.isEmpty()) {
             createHeaders(username, password)
@@ -52,25 +55,39 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
     override val name: String
         get() = "MyAnimeList"
 
-    fun getLoginUrl(): String {
-        return Uri.parse(BASE_URL).buildUpon()
-                .appendEncodedPath("api/account/verify_credentials.xml")
-                .toString()
-    }
-
-    override fun login(username: String, password: String): Observable<Boolean> {
+    fun getLoginUrl() = Uri.parse(BASE_URL).buildUpon()
+            .appendEncodedPath("api/account/verify_credentials.xml")
+            .toString()
+
+    fun getSearchUrl(query: String) = Uri.parse(BASE_URL).buildUpon()
+            .appendEncodedPath("api/manga/search.xml")
+            .appendQueryParameter("q", query)
+            .toString()
+
+    fun getListUrl(username: String) = Uri.parse(BASE_URL).buildUpon()
+            .appendPath("malappinfo.php")
+            .appendQueryParameter("u", username)
+            .appendQueryParameter("status", "all")
+            .appendQueryParameter("type", "manga")
+            .toString()
+
+    fun getUpdateUrl(manga: MangaSync) = Uri.parse(BASE_URL).buildUpon()
+            .appendEncodedPath("api/mangalist/update")
+            .appendPath("${manga.remote_id}.xml")
+            .toString()
+
+    fun getAddUrl(manga: MangaSync) = Uri.parse(BASE_URL).buildUpon()
+            .appendEncodedPath("api/mangalist/add")
+            .appendPath("${manga.remote_id}.xml")
+            .toString()
+
+    override fun login(username: String, password: String): Completable {
         createHeaders(username, password)
         return client.newCall(GET(getLoginUrl(), headers))
                 .asObservable()
                 .doOnNext { it.close() }
-                .map { it.code() == 200 }
-    }
-
-    fun getSearchUrl(query: String): String {
-        return Uri.parse(BASE_URL).buildUpon()
-                .appendEncodedPath("api/manga/search.xml")
-                .appendQueryParameter("q", query)
-                .toString()
+                .doOnNext { if (it.code() != 200) throw Exception("Login error") }
+                .toCompletable()
     }
 
     fun search(query: String): Observable<List<MangaSync>> {
@@ -80,73 +97,56 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
                 .flatMap { Observable.from(it.select("entry")) }
                 .filter { it.select("type").text() != "Novel" }
                 .map {
-                    val manga = MangaSync.create(this)
-                    manga.title = it.selectText("title")
-                    manga.remote_id = it.selectInt("id")
-                    manga.total_chapters = it.selectInt("chapters")
-                    manga
+                    MangaSync.create(this).apply {
+                        title = it.selectText("title")
+                        remote_id = it.selectInt("id")
+                        total_chapters = it.selectInt("chapters")
+                    }
                 }
                 .toList()
     }
 
-    fun getListUrl(username: String): String {
-        return Uri.parse(BASE_URL).buildUpon()
-                .appendPath("malappinfo.php")
-                .appendQueryParameter("u", username)
-                .appendQueryParameter("status", "all")
-                .appendQueryParameter("type", "manga")
-                .toString()
-    }
-
     // MAL doesn't support score with decimals
     fun getList(): Observable<List<MangaSync>> {
         return networkService.forceCacheClient
-                .newCall(GET(getListUrl(username), headers))
+                .newCall(GET(getListUrl(getUsername()), headers))
                 .asObservable()
                 .map { Jsoup.parse(it.body().string()) }
                 .flatMap { Observable.from(it.select("manga")) }
                 .map {
-                    val manga = MangaSync.create(this)
-                    manga.title = it.selectText("series_title")
-                    manga.remote_id = it.selectInt("series_mangadb_id")
-                    manga.last_chapter_read = it.selectInt("my_read_chapters")
-                    manga.status = it.selectInt("my_status")
-                    manga.score = it.selectInt("my_score").toFloat()
-                    manga.total_chapters = it.selectInt("series_chapters")
-                    manga
+                    MangaSync.create(this).apply {
+                        title = it.selectText("series_title")
+                        remote_id = it.selectInt("series_mangadb_id")
+                        last_chapter_read = it.selectInt("my_read_chapters")
+                        status = it.selectInt("my_status")
+                        score = it.selectInt("my_score").toFloat()
+                        total_chapters = it.selectInt("series_chapters")
+                    }
                 }
                 .toList()
     }
 
-    fun getUpdateUrl(manga: MangaSync): String {
-        return Uri.parse(BASE_URL).buildUpon()
-                .appendEncodedPath("api/mangalist/update")
-                .appendPath(manga.remote_id.toString() + ".xml")
-                .toString()
-    }
-
-    override fun update(manga: MangaSync): Observable<Response> {
+    override fun update(manga: MangaSync): Observable<MangaSync> {
         return Observable.defer {
             if (manga.total_chapters != 0 && manga.last_chapter_read == manga.total_chapters) {
                 manga.status = COMPLETED
             }
             client.newCall(POST(getUpdateUrl(manga), headers, getMangaPostPayload(manga)))
                     .asObservable()
+                    .doOnNext { it.close() }
+                    .doOnNext { if (!it.isSuccessful) throw Exception("Could not update manga") }
+                    .map { manga }
         }
 
     }
 
-    fun getAddUrl(manga: MangaSync): String {
-        return Uri.parse(BASE_URL).buildUpon()
-                .appendEncodedPath("api/mangalist/add")
-                .appendPath(manga.remote_id.toString() + ".xml")
-                .toString()
-    }
-
-    override fun add(manga: MangaSync): Observable<Response> {
+    override fun add(manga: MangaSync): Observable<MangaSync> {
         return Observable.defer {
             client.newCall(POST(getAddUrl(manga), headers, getMangaPostPayload(manga)))
                     .asObservable()
+                    .doOnNext { it.close() }
+                    .doOnNext { if (!it.isSuccessful) throw Exception("Could not add manga") }
+                    .map { manga }
         }
     }
 
@@ -184,21 +184,20 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
         endTag(namespace, tag)
     }
 
-    override fun bind(manga: MangaSync): Observable<Response> {
+    override fun bind(manga: MangaSync): Observable<MangaSync> {
         return getList()
-                .flatMap {
+                .flatMap { userlist ->
                     manga.sync_id = id
-                    for (remoteManga in it) {
-                        if (remoteManga.remote_id == manga.remote_id) {
-                            // Manga is already in the list
-                            manga.copyPersonalFrom(remoteManga)
-                            return@flatMap update(manga)
-                        }
+                    val mangaFromList = userlist.find { it.remote_id == manga.remote_id }
+                    if (mangaFromList != null) {
+                        manga.copyPersonalFrom(mangaFromList)
+                        update(manga)
+                    } else {
+                        // Set default fields if it's not found in the list
+                        manga.score = DEFAULT_SCORE.toFloat()
+                        manga.status = DEFAULT_STATUS
+                        add(manga)
                     }
-                    // Set default fields if it's not found in the list
-                    manga.score = DEFAULT_SCORE.toFloat()
-                    manga.status = DEFAULT_STATUS
-                    return@flatMap add(manga)
                 }
     }
 
@@ -214,7 +213,6 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
     }
 
     fun createHeaders(username: String, password: String) {
-        this.username = username
         val builder = Headers.Builder()
         builder.add("Authorization", Credentials.basic(username, password))
         builder.add("User-Agent", "api-indiv-9F93C52A963974CF674325391990191C")

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -6,7 +6,7 @@ import android.preference.PreferenceManager
 import com.f2prateek.rx.preferences.Preference
 import com.f2prateek.rx.preferences.RxSharedPreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
+import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
 import eu.kanade.tachiyomi.data.source.Source
 import java.io.File
 import java.io.IOException

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/injection/component/AppComponent.kt

@@ -6,8 +6,8 @@ import eu.kanade.tachiyomi.data.download.DownloadService
 import eu.kanade.tachiyomi.data.glide.AppGlideModule
 import eu.kanade.tachiyomi.data.glide.MangaModelLoader
 import eu.kanade.tachiyomi.data.library.LibraryUpdateService
+import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
 import eu.kanade.tachiyomi.data.mangasync.UpdateMangaSyncService
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
 import eu.kanade.tachiyomi.data.source.Source
 import eu.kanade.tachiyomi.data.source.online.OnlineSource
 import eu.kanade.tachiyomi.data.updater.UpdateDownloader

+ 2 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.kt

@@ -98,7 +98,7 @@ class MyAnimeListPresenter : BasePresenter<MyAnimeListFragment>() {
         mangaSync?.let { mangaSync ->
             add(myAnimeList.update(mangaSync)
                     .subscribeOn(Schedulers.io())
-                    .flatMap { response -> db.insertMangaSync(mangaSync).asRxObservable() }
+                    .flatMap { db.insertMangaSync(mangaSync).asRxObservable() }
                     .observeOn(AndroidSchedulers.mainThread())
                     .subscribe({ next -> },
                             { error ->
@@ -126,13 +126,7 @@ class MyAnimeListPresenter : BasePresenter<MyAnimeListFragment>() {
         if (sync != null) {
             sync.manga_id = manga.id
             add(myAnimeList.bind(sync)
-                    .flatMap { response ->
-                        if (response.isSuccessful) {
-                            db.insertMangaSync(sync).asRxObservable()
-                        } else {
-                            Observable.error(Exception("Could not bind manga"))
-                        }
-                    }
+                    .flatMap { db.insertMangaSync(sync).asRxObservable() }
                     .subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
                     .subscribe({ },

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

@@ -374,7 +374,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
 
     fun updateMangaSyncLastChapterRead() {
         for (mangaSync in mangaSyncList ?: emptyList()) {
-            val service = syncManager.getService(mangaSync.sync_id)
+            val service = syncManager.getService(mangaSync.sync_id) ?: continue
             if (service.isLogged && mangaSync.update) {
                 UpdateMangaSyncService.start(context, mangaSync)
             }

+ 13 - 18
app/src/main/java/eu/kanade/tachiyomi/widget/preference/MangaSyncLoginDialog.kt

@@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.widget.preference
 import android.os.Bundle
 import android.view.View
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
+import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
 import eu.kanade.tachiyomi.ui.setting.SettingsActivity
 import eu.kanade.tachiyomi.util.toast
 import kotlinx.android.synthetic.main.pref_account_login.view.*
@@ -29,13 +29,13 @@ class MangaSyncLoginDialog : LoginDialogPreference() {
         super.onCreate(savedInstanceState)
 
         val syncId = arguments.getInt("key")
-        sync = (activity as SettingsActivity).syncManager.getService(syncId)
+        sync = (activity as SettingsActivity).syncManager.getService(syncId)!!
     }
 
     override fun setCredentialsOnView(view: View) = with(view) {
         dialog_title.text = getString(R.string.login_title, sync.name)
-        username.setText(preferences.mangaSyncUsername(sync))
-        password.setText(preferences.mangaSyncPassword(sync))
+        username.setText(sync.getUsername())
+        password.setText(sync.getPassword())
     }
 
     override fun checkLogin() {
@@ -46,25 +46,20 @@ class MangaSyncLoginDialog : LoginDialogPreference() {
                 return
 
             login.progress = 1
+            val user = username.text.toString()
+            val pass = password.text.toString()
 
-            requestSubscription = sync.login(username.text.toString(), password.text.toString())
+            requestSubscription = sync.login(user, pass)
                     .subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
-                    .subscribe({ logged ->
-                        if (logged) {
-                            preferences.setMangaSyncCredentials(sync,
-                                    username.text.toString(),
-                                    password.text.toString())
-
-                            dialog.dismiss()
-                            context.toast(R.string.login_success)
-                        } else {
-                            preferences.setMangaSyncCredentials(sync, "", "")
-                            login.progress = -1
-                        }
-                    }, { error ->
+                    .subscribe({ error ->
+                        sync.logout()
                         login.progress = -1
                         login.setText(R.string.unknown_error)
+                    }, {
+                        sync.saveCredentials(user, pass)
+                        dialog.dismiss()
+                        context.toast(R.string.login_success)
                     })
 
         }