Ask for chapter deletion when removing from library
This commit is contained in:
parent
b66f06d9dc
commit
f7c791d153
@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.ui.category.CategoryActivity
|
|||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.util.inflate
|
import eu.kanade.tachiyomi.util.inflate
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
|
import eu.kanade.tachiyomi.widget.DialogCheckboxView
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.fragment_library.*
|
import kotlinx.android.synthetic.main.fragment_library.*
|
||||||
import nucleus.factory.RequiresPresenter
|
import nucleus.factory.RequiresPresenter
|
||||||
@ -480,12 +481,19 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showDeleteMangaDialog() {
|
private fun showDeleteMangaDialog() {
|
||||||
|
val view = DialogCheckboxView(context).apply {
|
||||||
|
setDescription(R.string.confirm_delete_manga)
|
||||||
|
setOptionDescription(R.string.also_delete_chapters)
|
||||||
|
}
|
||||||
|
|
||||||
MaterialDialog.Builder(activity)
|
MaterialDialog.Builder(activity)
|
||||||
.content(R.string.confirm_delete_manga)
|
.title(R.string.action_remove)
|
||||||
|
.customView(view, true)
|
||||||
.positiveText(android.R.string.yes)
|
.positiveText(android.R.string.yes)
|
||||||
.negativeText(android.R.string.no)
|
.negativeText(android.R.string.no)
|
||||||
.onPositive { dialog, action ->
|
.onPositive { dialog, action ->
|
||||||
presenter.removeMangaFromLibrary()
|
val deleteChapters = view.isChecked()
|
||||||
|
presenter.removeMangaFromLibrary(deleteChapters)
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
|
@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
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.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.util.combineLatest
|
import eu.kanade.tachiyomi.util.combineLatest
|
||||||
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
|
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
|
||||||
@ -303,19 +304,31 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the selected manga from the library.
|
* 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
|
// 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())
|
.subscribeOn(Schedulers.io())
|
||||||
.doOnNext {
|
.subscribe()
|
||||||
it.favorite = false
|
|
||||||
coverCache.deleteFromCache(it.thumbnail_url)
|
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()
|
.subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
|||||||
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
|
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaActivity
|
import eu.kanade.tachiyomi.ui.manga.MangaActivity
|
||||||
import eu.kanade.tachiyomi.util.getResourceColor
|
import eu.kanade.tachiyomi.util.getResourceColor
|
||||||
|
import eu.kanade.tachiyomi.util.snack
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
import jp.wasabeef.glide.transformations.CropCircleTransformation
|
import jp.wasabeef.glide.transformations.CropCircleTransformation
|
||||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||||
@ -62,7 +63,7 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View?, savedState: Bundle?) {
|
override fun onViewCreated(view: View?, savedState: Bundle?) {
|
||||||
// Set onclickListener to toggle favorite when FAB clicked.
|
// Set onclickListener to toggle favorite when FAB clicked.
|
||||||
fab_favorite.setOnClickListener { presenter.toggleFavorite() }
|
fab_favorite.setOnClickListener { toggleFavorite() }
|
||||||
|
|
||||||
// Set SwipeRefresh to refresh manga data.
|
// Set SwipeRefresh to refresh manga data.
|
||||||
swipe_refresh.setOnRefreshListener { fetchMangaFromSource() }
|
swipe_refresh.setOnRefreshListener { fetchMangaFromSource() }
|
||||||
@ -160,13 +161,31 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
|||||||
manga_chapters.text = count.toString()
|
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.
|
* Open the manga in browser.
|
||||||
*/
|
*/
|
||||||
fun openInBrowser() {
|
fun openInBrowser() {
|
||||||
|
if (!isAdded) return
|
||||||
|
|
||||||
val source = presenter.source as? HttpSource ?: return
|
val source = presenter.source as? HttpSource ?: return
|
||||||
try {
|
try {
|
||||||
val url = Uri.parse(source.baseUrl + presenter.manga.url)
|
val url = Uri.parse(source.mangaDetailsRequest(presenter.manga).url().toString())
|
||||||
val intent = CustomTabsIntent.Builder()
|
val intent = CustomTabsIntent.Builder()
|
||||||
.setToolbarColor(context.getResourceColor(R.attr.colorPrimary))
|
.setToolbarColor(context.getResourceColor(R.attr.colorPrimary))
|
||||||
.build()
|
.build()
|
||||||
@ -180,14 +199,16 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
|||||||
* Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
|
* Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
|
||||||
*/
|
*/
|
||||||
private fun shareManga() {
|
private fun shareManga() {
|
||||||
|
if (!isAdded) return
|
||||||
|
|
||||||
val source = presenter.source as? HttpSource ?: return
|
val source = presenter.source as? HttpSource ?: return
|
||||||
try {
|
try {
|
||||||
val url = source.mangaDetailsRequest(presenter.manga).url().toString()
|
val url = source.mangaDetailsRequest(presenter.manga).url().toString()
|
||||||
val sharingIntent = Intent(Intent.ACTION_SEND).apply {
|
val sharingIntent = Intent(Intent.ACTION_SEND).apply {
|
||||||
type = "text/plain"
|
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) {
|
} catch (e: Exception) {
|
||||||
context.toast(e.message)
|
context.toast(e.message)
|
||||||
}
|
}
|
||||||
@ -197,6 +218,8 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
|||||||
* Add the manga to the home screen
|
* Add the manga to the home screen
|
||||||
*/
|
*/
|
||||||
fun addToHomeScreen() {
|
fun addToHomeScreen() {
|
||||||
|
if (!isAdded) return
|
||||||
|
|
||||||
val shortcutIntent = activity.intent
|
val shortcutIntent = activity.intent
|
||||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
.putExtra(MangaActivity.FROM_LAUNCHER_EXTRA, true)
|
.putExtra(MangaActivity.FROM_LAUNCHER_EXTRA, true)
|
||||||
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
|||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
@ -50,6 +51,8 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
|
|||||||
*/
|
*/
|
||||||
val coverCache: CoverCache by injectLazy()
|
val coverCache: CoverCache by injectLazy()
|
||||||
|
|
||||||
|
private val downloadManager: DownloadManager by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscription to send the manga to the view.
|
* Subscription to send the manga to the view.
|
||||||
*/
|
*/
|
||||||
@ -75,7 +78,7 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
|
|||||||
// Update favorite status
|
// Update favorite status
|
||||||
SharedData.get(MangaFavoriteEvent::class.java)?.observable
|
SharedData.get(MangaFavoriteEvent::class.java)?.observable
|
||||||
?.observeOn(AndroidSchedulers.mainThread())
|
?.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.
|
* 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
|
manga.favorite = !manga.favorite
|
||||||
if (!manga.favorite) {
|
if (!manga.favorite) {
|
||||||
coverCache.deleteFromCache(manga.thumbnail_url)
|
coverCache.deleteFromCache(manga.thumbnail_url)
|
||||||
}
|
}
|
||||||
db.insertManga(manga).executeAsBlocking()
|
db.insertManga(manga).executeAsBlocking()
|
||||||
sendMangaToView()
|
sendMangaToView()
|
||||||
|
return manga.favorite
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setFavorite(favorite: Boolean) {
|
private fun setFavorite(favorite: Boolean) {
|
||||||
@ -128,4 +134,18 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
|
|||||||
toggleFavorite()
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,15 @@ import android.content.Context
|
|||||||
import android.support.annotation.StringRes
|
import android.support.annotation.StringRes
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.RelativeLayout
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.util.inflate
|
||||||
import kotlinx.android.synthetic.main.dialog_with_checkbox.view.*
|
import kotlinx.android.synthetic.main.dialog_with_checkbox.view.*
|
||||||
|
|
||||||
class DialogCheckboxView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
class DialogCheckboxView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
LinearLayout(context, attrs) {
|
LinearLayout(context, attrs) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
RelativeLayout.inflate(context, R.layout.dialog_with_checkbox, this)
|
addView(inflate(R.layout.dialog_with_checkbox))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDescription(@StringRes id: Int){
|
fun setDescription(@StringRes id: Int){
|
||||||
|
@ -218,6 +218,7 @@
|
|||||||
<string name="library_search_hint">Title or author…</string>
|
<string name="library_search_hint">Title or author…</string>
|
||||||
<string name="updating_category">Updating category</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="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 -->
|
<!-- Catalogue fragment -->
|
||||||
<string name="source_requires_login">This source requires you to log in</string>
|
<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="shortcut_title">Shortcut title</string>
|
||||||
<string name="icon_shape">Icon shape</string>
|
<string name="icon_shape">Icon shape</string>
|
||||||
<string name="icon_creation_fail">Failed to create shortcut!</string>
|
<string name="icon_creation_fail">Failed to create shortcut!</string>
|
||||||
|
<string name="delete_downloads_for_manga">Delete downloaded chapters?</string>
|
||||||
|
|
||||||
<!-- Manga chapters fragment -->
|
<!-- Manga chapters fragment -->
|
||||||
<string name="manga_chapters_tab">Chapters</string>
|
<string name="manga_chapters_tab">Chapters</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user