Bläddra i källkod

Ask for chapter deletion when removing from library

len 8 år sedan
förälder
incheckning
f7c791d153

+ 10 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt

@@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.ui.category.CategoryActivity
 import eu.kanade.tachiyomi.ui.main.MainActivity
 import eu.kanade.tachiyomi.util.inflate
 import eu.kanade.tachiyomi.util.toast
+import eu.kanade.tachiyomi.widget.DialogCheckboxView
 import kotlinx.android.synthetic.main.activity_main.*
 import kotlinx.android.synthetic.main.fragment_library.*
 import nucleus.factory.RequiresPresenter
@@ -480,12 +481,19 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
     }
 
     private fun showDeleteMangaDialog() {
+        val view = DialogCheckboxView(context).apply {
+            setDescription(R.string.confirm_delete_manga)
+            setOptionDescription(R.string.also_delete_chapters)
+        }
+
         MaterialDialog.Builder(activity)
-                .content(R.string.confirm_delete_manga)
+                .title(R.string.action_remove)
+                .customView(view, true)
                 .positiveText(android.R.string.yes)
                 .negativeText(android.R.string.no)
                 .onPositive { dialog, action ->
-                    presenter.removeMangaFromLibrary()
+                    val deleteChapters = view.isChecked()
+                    presenter.removeMangaFromLibrary(deleteChapters)
                     destroyActionModeIfNeeded()
                 }
                 .show()

+ 21 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.source.LocalSource
 import eu.kanade.tachiyomi.source.SourceManager
+import eu.kanade.tachiyomi.source.online.HttpSource
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.util.combineLatest
 import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
@@ -303,19 +304,31 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
 
     /**
      * Remove the selected manga from the library.
+     *
+     * @param deleteChapters whether to also delete downloaded chapters.
      */
-    fun removeMangaFromLibrary() {
+    fun removeMangaFromLibrary(deleteChapters: Boolean) {
         // Create a set of the list
-        val mangaToDelete = selectedMangas.toSet()
+        val mangaToDelete = selectedMangas.distinctBy { it.id }
+        mangaToDelete.forEach { it.favorite = false }
 
-        Observable.from(mangaToDelete)
+        Observable.fromCallable { db.insertMangas(mangaToDelete).executeAsBlocking() }
+                .onErrorResumeNext { Observable.empty() }
                 .subscribeOn(Schedulers.io())
-                .doOnNext {
-                    it.favorite = false
-                    coverCache.deleteFromCache(it.thumbnail_url)
+                .subscribe()
+
+        Observable.fromCallable {
+            mangaToDelete.forEach { manga ->
+                coverCache.deleteFromCache(manga.thumbnail_url)
+                if (deleteChapters) {
+                    val source = sourceManager.get(manga.source) as? HttpSource
+                    if (source != null) {
+                        downloadManager.findMangaDir(source, manga)?.delete()
+                    }
                 }
-                .toList()
-                .flatMap { db.insertMangas(it).asRxObservable() }
+            }
+        }
+                .subscribeOn(Schedulers.io())
                 .subscribe()
     }
 

+ 27 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt

@@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
 import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
 import eu.kanade.tachiyomi.ui.manga.MangaActivity
 import eu.kanade.tachiyomi.util.getResourceColor
+import eu.kanade.tachiyomi.util.snack
 import eu.kanade.tachiyomi.util.toast
 import jp.wasabeef.glide.transformations.CropCircleTransformation
 import jp.wasabeef.glide.transformations.CropSquareTransformation
@@ -62,7 +63,7 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
 
     override fun onViewCreated(view: View?, savedState: Bundle?) {
         // Set onclickListener to toggle favorite when FAB clicked.
-        fab_favorite.setOnClickListener { presenter.toggleFavorite() }
+        fab_favorite.setOnClickListener { toggleFavorite() }
 
         // Set SwipeRefresh to refresh manga data.
         swipe_refresh.setOnRefreshListener { fetchMangaFromSource() }
@@ -160,13 +161,31 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
         manga_chapters.text = count.toString()
     }
 
+    /**
+     * Toggles the favorite status and asks for confirmation to delete downloaded chapters.
+     */
+    fun toggleFavorite() {
+        if (!isAdded) return
+
+        val isNowFavorite = presenter.toggleFavorite()
+        if (!isNowFavorite && presenter.hasDownloads()) {
+            view!!.snack(getString(R.string.delete_downloads_for_manga)) {
+                setAction(R.string.action_delete) {
+                    presenter.deleteDownloads()
+                }
+            }
+        }
+    }
+
     /**
      * Open the manga in browser.
      */
     fun openInBrowser() {
+        if (!isAdded) return
+
         val source = presenter.source as? HttpSource ?: return
         try {
-            val url = Uri.parse(source.baseUrl + presenter.manga.url)
+            val url = Uri.parse(source.mangaDetailsRequest(presenter.manga).url().toString())
             val intent = CustomTabsIntent.Builder()
                     .setToolbarColor(context.getResourceColor(R.attr.colorPrimary))
                     .build()
@@ -180,14 +199,16 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
      * Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
      */
     private fun shareManga() {
+        if (!isAdded) return
+
         val source = presenter.source as? HttpSource ?: return
         try {
             val url = source.mangaDetailsRequest(presenter.manga).url().toString()
             val sharingIntent = Intent(Intent.ACTION_SEND).apply {
                 type = "text/plain"
-                putExtra(android.content.Intent.EXTRA_TEXT, resources.getString(R.string.share_text, presenter.manga.title, url))
+                putExtra(Intent.EXTRA_TEXT, getString(R.string.share_text, presenter.manga.title, url))
             }
-            startActivity(Intent.createChooser(sharingIntent, resources.getText(R.string.action_share)))
+            startActivity(Intent.createChooser(sharingIntent, getString(R.string.action_share)))
         } catch (e: Exception) {
             context.toast(e.message)
         }
@@ -197,6 +218,8 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
      * Add the manga to the home screen
      */
     fun addToHomeScreen() {
+        if (!isAdded) return
+
         val shortcutIntent = activity.intent
         shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                 .putExtra(MangaActivity.FROM_LAUNCHER_EXTRA, true)

+ 22 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt

@@ -4,6 +4,7 @@ import android.os.Bundle
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.source.Source
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
@@ -50,6 +51,8 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
      */
     val coverCache: CoverCache by injectLazy()
 
+    private val downloadManager: DownloadManager by injectLazy()
+
     /**
      * Subscription to send the manga to the view.
      */
@@ -75,7 +78,7 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
         // Update favorite status
         SharedData.get(MangaFavoriteEvent::class.java)?.observable
                 ?.observeOn(AndroidSchedulers.mainThread())
-                ?.subscribe{setFavorite(it)}
+                ?.subscribe { setFavorite(it) }
     }
 
     /**
@@ -111,14 +114,17 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
 
     /**
      * Update favorite status of manga, (removes / adds) manga (to / from) library.
+     *
+     * @return the new status of the manga.
      */
-    fun toggleFavorite() {
+    fun toggleFavorite(): Boolean {
         manga.favorite = !manga.favorite
         if (!manga.favorite) {
             coverCache.deleteFromCache(manga.thumbnail_url)
         }
         db.insertManga(manga).executeAsBlocking()
         sendMangaToView()
+        return manga.favorite
     }
 
     private fun setFavorite(favorite: Boolean) {
@@ -128,4 +134,18 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
         toggleFavorite()
     }
 
+    /**
+     * Returns true if the manga has any downloads.
+     */
+    fun hasDownloads(): Boolean {
+        return downloadManager.findMangaDir(source, manga) != null
+    }
+
+    /**
+     * Deletes all the downloads for the manga.
+     */
+    fun deleteDownloads() {
+        downloadManager.findMangaDir(source, manga)?.delete()
+    }
+
 }

+ 3 - 2
app/src/main/java/eu/kanade/tachiyomi/widget/DialogCheckboxView.kt

@@ -4,14 +4,15 @@ import android.content.Context
 import android.support.annotation.StringRes
 import android.util.AttributeSet
 import android.widget.LinearLayout
-import android.widget.RelativeLayout
 import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.util.inflate
 import kotlinx.android.synthetic.main.dialog_with_checkbox.view.*
 
 class DialogCheckboxView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
         LinearLayout(context, attrs) {
+
     init {
-        RelativeLayout.inflate(context, R.layout.dialog_with_checkbox, this)
+        addView(inflate(R.layout.dialog_with_checkbox))
     }
 
     fun setDescription(@StringRes id: Int){

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -218,6 +218,7 @@
     <string name="library_search_hint">Title or author…</string>
     <string name="updating_category">Updating category</string>
     <string name="confirm_delete_manga">Are you sure you want to remove selected manga?</string>
+    <string name="also_delete_chapters">Also delete downloaded chapters</string>
 
     <!-- Catalogue fragment -->
     <string name="source_requires_login">This source requires you to log in</string>
@@ -251,6 +252,7 @@
     <string name="shortcut_title">Shortcut title</string>
     <string name="icon_shape">Icon shape</string>
     <string name="icon_creation_fail">Failed to create shortcut!</string>
+    <string name="delete_downloads_for_manga">Delete downloaded chapters?</string>
 
     <!-- Manga chapters fragment -->
     <string name="manga_chapters_tab">Chapters</string>