diff --git a/app/build.gradle b/app/build.gradle index c5fd976da1..6334c6ea8e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -258,12 +258,6 @@ repositories { mavenCentral() } -kotlin { - experimental { - coroutines 'enable' - } -} - androidExtensions { experimental = true } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt index 520ce8b2b0..96db0846bd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt @@ -67,25 +67,4 @@ class CoverCache(private val context: Context) { val file = getCoverFile(thumbnailUrl) return file.exists() && file.delete() } - - /** - * Delete the cover file from the cache. - * - * @param thumbnailUrl the thumbnail url. - * @return status of deletion. - */ - fun deleteFromCache(manga: Manga, delayBy:Long) { - val thumbnailUrl = manga.thumbnail_url - // Check if url is empty. - if (thumbnailUrl.isNullOrEmpty()) return - launchUI { - delay(delayBy) - if (!manga.favorite) { - // Remove file. - val file = getCoverFile(thumbnailUrl) - if (file.exists()) file.delete() - } - } - } - } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 8214818373..f490956eec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -190,22 +190,6 @@ class DownloadManager(context: Context) { cache.removeManga(manga) } - - /** - * Deletes the directory of a downloaded manga. - * - * @param manga the manga to delete. - * @param source the source of the manga. - */ - fun deleteManga(manga: Manga, source: Source, delayBy: Long) { - launchUI { - delay(delayBy) - if (!manga.favorite) { - deleteManga(manga, source) - } - } - } - /** * Adds a list of chapters to be deleted later. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index 38aaedf86d..44d9670094 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -64,7 +64,7 @@ class NotificationReceiver : BroadcastReceiver() { ACTION_DELETE_IMAGE -> deleteImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION), intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)) // Cancel library update and dismiss notification - ACTION_CANCEL_LIBRARY_UPDATE -> cancelLibraryUpdate(context, Notifications.ID_LIBRARY_PROGRESS) + ACTION_CANCEL_LIBRARY_UPDATE -> cancelLibraryUpdate(context) // Open reader activity ACTION_OPEN_CHAPTER -> { openChapter(context, intent.getLongExtra(EXTRA_MANGA_ID, -1), @@ -76,7 +76,8 @@ class NotificationReceiver : BroadcastReceiver() { context, notificationId, intent.getStringExtra(EXTRA_GROUP_ID) ) val url = intent.getStringExtra(EXTRA_CHAPTER_URL) ?: return - markAsRead(url) + val mangaId = intent.getLongExtra(EXTRA_MANGA_ID, -1) + markAsRead(url, mangaId) } } } @@ -157,9 +158,9 @@ class NotificationReceiver : BroadcastReceiver() { * @param context context of application * @param notificationId id of notification */ - private fun cancelLibraryUpdate(context: Context, notificationId: Int) { + private fun cancelLibraryUpdate(context: Context) { LibraryUpdateService.stop(context) - Handler().post { dismissNotification(context, notificationId) } + Handler().post { dismissNotification(context, Notifications.ID_LIBRARY_PROGRESS) } } /** @@ -168,9 +169,9 @@ class NotificationReceiver : BroadcastReceiver() { * @param context context of application * @param notificationId id of notification */ - private fun markAsRead(chapterUrl: String) { + private fun markAsRead(chapterUrl: String, mangaaId: Long) { val db: DatabaseHelper = Injekt.get() - val chapter = db.getChapter(chapterUrl).executeAsBlocking() ?: return + val chapter = db.getChapter(chapterUrl, mangaaId).executeAsBlocking() ?: return chapter.read = true db.updateChapterProgress(chapter).executeAsBlocking() val preferences: PreferencesHelper = Injekt.get() @@ -398,6 +399,7 @@ class NotificationReceiver : BroadcastReceiver() { val newIntent = Intent(context, NotificationReceiver::class.java).apply { action = ACTION_MARK_AS_READ putExtra(EXTRA_CHAPTER_URL, chapter.url) + putExtra(EXTRA_MANGA_ID, manga.id) putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode()) putExtra(EXTRA_GROUP_ID, groupId) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt index baa3fad5eb..7d0e7bbaef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCatalogueController.kt @@ -9,6 +9,7 @@ import android.view.* import androidx.core.view.GravityCompat import com.afollestad.materialdialogs.MaterialDialog import com.f2prateek.rx.preferences.Preference +import com.google.android.material.snackbar.BaseTransientBottomBar import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible @@ -24,6 +25,7 @@ import eu.kanade.tachiyomi.ui.base.controller.SecondaryDrawerController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.library.ChangeMangaCategoriesDialog import eu.kanade.tachiyomi.ui.library.HeightTopWindowInsetsListener +import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.info.MangaWebViewController import eu.kanade.tachiyomi.util.* @@ -501,18 +503,23 @@ open class BrowseCatalogueController(bundle: Bundle) : * @param position the position of the element clicked. */ override fun onItemLongClick(position: Int) { - val activity = activity ?: return val manga = (adapter?.getItem(position) as? CatalogueItem?)?.manga ?: return snack?.dismiss() if (manga.favorite) { presenter.changeMangaFavorite(manga) adapter?.notifyItemChanged(position) - snack = - catalouge_layout?.snack(R.string.manga_removed_library, 5000) { - setAction(R.string.action_undo) { - if (!manga.favorite) addManga(manga, position) - } + snack = catalouge_layout?.snack(R.string.manga_removed_library, Snackbar.LENGTH_INDEFINITE) { + setAction(R.string.action_undo) { + if (!manga.favorite) addManga(manga, position) } + addCallback(object : BaseTransientBottomBar.BaseCallback() { + override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { + super.onDismissed(transientBottomBar, event) + if (!manga.favorite) presenter.confirmDeletion(manga) + } + }) + } + (activity as? MainActivity)?.setUndoSnackBar(snack) } else { addManga(manga, position) snack = catalouge_layout?.snack(R.string.manga_added_library) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt index 33843587b3..d81f1f044b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/browse/BrowseCataloguePresenter.kt @@ -254,14 +254,15 @@ open class BrowseCataloguePresenter( */ fun changeMangaFavorite(manga: Manga) { manga.favorite = !manga.favorite - if (!manga.favorite) { - coverCache.deleteFromCache(manga, 5000) - val downloadManager: DownloadManager = Injekt.get() - downloadManager.deleteManga(manga,source,5000) - } db.insertManga(manga).executeAsBlocking() } + fun confirmDeletion(manga: Manga) { + coverCache.deleteFromCache(manga.thumbnail_url) + val downloadManager: DownloadManager = Injekt.get() + downloadManager.deleteManga(manga,source) + } + /** * Changes the active display mode. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt index 1a28e41c30..5cefa5de6b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/global_search/CatalogueSearchController.kt @@ -171,12 +171,29 @@ open class CatalogueSearchController( return null } + override fun handleBack(): Boolean { + return if (extensionFilter != null) { + activity?.finishAffinity() + true + } else super.handleBack() + } + /** * Add search result to adapter. * * @param searchResult result of search. */ fun setItems(searchResult: List) { + if (extensionFilter != null) { + val results = searchResult.first().results + if (results != null && results.size == 1) { + val manga = results.first().manga + router.pushController(MangaController(manga,true,fromExtension = true) + .withFadeTransaction() + ) + return + } + } adapter?.updateDataSet(searchResult) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt deleted file mode 100644 index 1aa376eb87..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/DeleteLibraryMangasDialog.kt +++ /dev/null @@ -1,43 +0,0 @@ -package eu.kanade.tachiyomi.ui.library - -import android.app.Dialog -import android.os.Bundle -import com.afollestad.materialdialogs.MaterialDialog -import com.bluelinelabs.conductor.Controller -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.ui.base.controller.DialogController -import eu.kanade.tachiyomi.widget.DialogCheckboxView - -class DeleteLibraryMangasDialog(bundle: Bundle? = null) : - DialogController(bundle) where T : Controller, T: DeleteLibraryMangasDialog.Listener { - - private var mangas = emptyList() - - constructor(target: T, mangas: List) : this() { - this.mangas = mangas - targetController = target - } - - override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val view = DialogCheckboxView(activity!!).apply { - setDescription(R.string.confirm_delete_manga) - setOptionDescription(R.string.also_delete_chapters) - } - - return MaterialDialog.Builder(activity!!) - .title(R.string.action_remove) - .customView(view, true) - .positiveText(android.R.string.yes) - .negativeText(android.R.string.no) - .onPositive { _, _ -> - val deleteChapters = view.isChecked() - (targetController as? Listener)?.deleteMangasFromLibrary(mangas, deleteChapters) - } - .build() - } - - interface Listener { - fun deleteMangasFromLibrary(mangas: List, deleteChapters: Boolean) - } -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index ca2d3eebb0..3fba4e0487 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -21,6 +21,7 @@ import androidx.core.view.GravityCompat import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType import com.f2prateek.rx.preferences.Preference +import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.jakewharton.rxbinding.support.v4.view.pageSelections @@ -66,7 +67,6 @@ class LibraryController( SecondaryDrawerController, ActionMode.Callback, ChangeMangaCategoriesDialog.Listener, - DeleteLibraryMangasDialog.Listener, MigrationInterface { /** @@ -530,14 +530,24 @@ class LibraryController( private fun deleteMangasFromLibrary() { val mangas = selectedMangas.toList() - presenter.removeMangaFromLibrary(mangas, true) + presenter.removeMangaFromLibrary(mangas) destroyActionModeIfNeeded() snack?.dismiss() - snack = view?.snack(activity?.getString(R.string.manga_removed_library) ?: "", 5000) { + snack = view?.snack(activity?.getString(R.string.manga_removed_library) ?: "", Snackbar.LENGTH_INDEFINITE) { + var undoing = false setAction(R.string.action_undo) { presenter.addMangas(mangas) + undoing = true } + addCallback(object : BaseTransientBottomBar.BaseCallback() { + override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { + super.onDismissed(transientBottomBar, event) + if (!undoing) + presenter.confirmDeletion(mangas) + } + }) } + (activity as? MainActivity)?.setUndoSnackBar(snack) } override fun updateCategoriesForMangas(mangas: List, categories: List) { @@ -545,11 +555,6 @@ class LibraryController( destroyActionModeIfNeeded() } - override fun deleteMangasFromLibrary(mangas: List, deleteChapters: Boolean) { - presenter.removeMangaFromLibrary(mangas, deleteChapters) - destroyActionModeIfNeeded() - } - /** * Changes the cover for the selected manga. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index c55470500b..9cb1e2adb6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -305,7 +305,7 @@ class LibraryPresenter( * @param mangas the list of manga to delete. * @param deleteChapters whether to also delete downloaded chapters. */ - fun removeMangaFromLibrary(mangas: List, deleteChapters: Boolean) { + fun removeMangaFromLibrary(mangas: List) { // Create a set of the list val mangaToDelete = mangas.distinctBy { it.id } mangaToDelete.forEach { it.favorite = false } @@ -314,20 +314,18 @@ class LibraryPresenter( .onErrorResumeNext { Observable.empty() } .subscribeOn(Schedulers.io()) .subscribe() + } + fun confirmDeletion(mangas: List) { Observable.fromCallable { + val mangaToDelete = mangas.distinctBy { it.id } mangaToDelete.forEach { manga -> - coverCache.deleteFromCache(manga, 5000) - if (deleteChapters) { - val source = sourceManager.get(manga.source) as? HttpSource - if (source != null) { - downloadManager.deleteManga(manga, source, 5000) - } - } + coverCache.deleteFromCache(manga.thumbnail_url) + val source = sourceManager.get(manga.source) as? HttpSource + if (source != null) + downloadManager.deleteManga(manga, source) } - } - .subscribeOn(Schedulers.io()) - .subscribe() + }.subscribeOn(Schedulers.io()).subscribe() } fun addMangas(mangas: List) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 72f23bebc0..a68c5301ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -5,25 +5,19 @@ import android.app.SearchManager import android.content.Intent import android.content.res.Configuration import android.graphics.Color +import android.graphics.Rect import android.os.Build import android.os.Bundle -import androidx.annotation.NonNull -import androidx.annotation.Px -import androidx.annotation.RequiresApi +import android.view.MotionEvent import androidx.core.view.GravityCompat -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.drawerlayout.widget.DrawerLayout -import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate.* import androidx.appcompat.graphics.drawable.DrawerArrowDrawable import android.view.View import android.view.ViewGroup -import android.view.WindowInsets -import android.view.WindowManager import android.widget.FrameLayout import android.widget.LinearLayout import com.bluelinelabs.conductor.* +import com.google.android.material.snackbar.Snackbar import eu.kanade.tachiyomi.Migrations import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.NotificationReceiver @@ -34,7 +28,6 @@ import eu.kanade.tachiyomi.ui.catalogue.CatalogueController import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.extension.ExtensionController -import eu.kanade.tachiyomi.ui.library.HeightTopWindowInsetsListener import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController @@ -42,17 +35,17 @@ import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController import eu.kanade.tachiyomi.ui.setting.SettingsMainController import eu.kanade.tachiyomi.util.NoopWindowInsetsListener import eu.kanade.tachiyomi.util.doOnApplyWindowInsets +import eu.kanade.tachiyomi.util.launchUI import eu.kanade.tachiyomi.util.marginBottom import eu.kanade.tachiyomi.util.marginTop import eu.kanade.tachiyomi.util.openInBrowser import eu.kanade.tachiyomi.util.updateLayoutParams import eu.kanade.tachiyomi.util.updatePadding import eu.kanade.tachiyomi.util.updatePaddingRelative -import kotlinx.android.synthetic.main.chapters_controller.view.* import kotlinx.android.synthetic.main.main_activity.* +import kotlinx.coroutines.delay import uy.kohesive.injekt.injectLazy - class MainActivity : BaseActivity() { private lateinit var router: Router @@ -63,6 +56,25 @@ class MainActivity : BaseActivity() { private var secondaryDrawer: ViewGroup? = null + private var snackBar:Snackbar? = null + var extraRectForUndo:Rect? = null + private var canDismissSnackBar = false + + fun setUndoSnackBar(snackBar: Snackbar?, extraViewToCheck: View? = null) { + this.snackBar = snackBar + canDismissSnackBar = false + launchUI { + delay(1000) + canDismissSnackBar = true + } + if (extraViewToCheck != null) { + extraRectForUndo = Rect() + extraViewToCheck.getGlobalVisibleRect(extraRectForUndo) + } + else + extraRectForUndo = null + } + private val startScreenId by lazy { when (preferences.startScreen()) { 2 -> R.id.nav_drawer_recently_read @@ -296,6 +308,28 @@ class MainActivity : BaseActivity() { router.setRoot(controller.withFadeTransaction().tag(id.toString())) } + override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { + if (ev?.action == MotionEvent.ACTION_DOWN) { + if (snackBar != null && snackBar!!.isShown) { + val sRect = Rect() + snackBar!!.view.getGlobalVisibleRect(sRect) + + //This way the snackbar will only be dismissed if + //the user clicks outside it. + if (canDismissSnackBar && !sRect.contains(ev.x.toInt(), ev.y.toInt()) + && (extraRectForUndo == null || + !extraRectForUndo!!.contains(ev.x.toInt(), ev.y.toInt()))) { + snackBar?.dismiss() + snackBar = null + extraRectForUndo = null + } + } + else if (snackBar != null) + snackBar = null + } + return super.dispatchTouchEvent(ev) + } + private fun syncActivityViewWithController(to: Controller?, from: Controller? = null) { if (from is DialogController || to is DialogController) { return diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 25f1583589..1f9fd1a1b4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -1,22 +1,20 @@ package eu.kanade.tachiyomi.ui.manga import android.Manifest.permission.WRITE_EXTERNAL_STORAGE -import android.app.NotificationManager -import android.content.Context -import android.content.Intent +import android.app.Activity import android.os.Bundle -import com.google.android.material.tabs.TabLayout -import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView +import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.support.RouterPagerAdapter +import com.google.android.material.tabs.TabLayout import com.jakewharton.rxrelay.BehaviorRelay import com.jakewharton.rxrelay.PublishRelay import eu.kanade.tachiyomi.R @@ -42,7 +40,10 @@ import java.util.Date class MangaController : RxController, TabbedController { - constructor(manga: Manga?, fromCatalogue: Boolean = false) : super(Bundle().apply { + constructor(manga: Manga?, fromCatalogue: Boolean = false, fromExtension: Boolean = false) : + super + (Bundle() + .apply { putLong(MANGA_EXTRA, manga?.id ?: 0) putBoolean(FROM_CATALOGUE_EXTRA, fromCatalogue) }) { @@ -50,6 +51,7 @@ class MangaController : RxController, TabbedController { if (manga != null) { source = Injekt.get().getOrStub(manga.source) } + backClosesApp = fromExtension } constructor(manga: Manga?, startY:Float?) : super(Bundle().apply { @@ -74,12 +76,32 @@ class MangaController : RxController, TabbedController { ) } + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + backClosesApp = false + super.onRestoreInstanceState(savedInstanceState) + } + + override fun onActivityResumed(activity: Activity) { + backClosesApp = false + super.onActivityResumed(activity) + } + + override fun handleBack(): Boolean { + return if (backClosesApp) { + activity?.finishAffinity() + true + } else super.handleBack() + } + var manga: Manga? = null private set var source: Source? = null private set + var backClosesApp = false + private set + var startingChapterYPos:Float? = null private var adapter: MangaDetailAdapter? = null diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt index db801fa42b..6783f964fd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt @@ -34,6 +34,7 @@ import android.content.Context import android.util.AttributeSet import androidx.core.view.ViewCompat import androidx.recyclerview.widget.RecyclerView +import eu.kanade.tachiyomi.ui.main.MainActivity import kotlin.math.* class ChaptersController() : NucleusController(), @@ -411,19 +412,20 @@ class ChaptersController() : NucleusController(), val view = view destroyActionModeIfNeeded() presenter.downloadChapters(chapters) - if (view != null && !presenter.manga.favorite && (snack == null || snack?.getText() != view.context.getString(R.string.snack_add_to_library))) { - snack = - view.snack(view.context.getString(R.string.snack_add_to_library), Snackbar.LENGTH_INDEFINITE) { - setAction(R.string.action_add) { - presenter.addToLibrary() - } - addCallback(object : BaseTransientBottomBar.BaseCallback() { - override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { - super.onDismissed(transientBottomBar, event) - if (snack == transientBottomBar) snack = null - } - }) + if (view != null && !presenter.manga.favorite && (snack == null || + snack?.getText() != view.context.getString(R.string.snack_add_to_library))) { + snack = view.snack(view.context.getString(R.string.snack_add_to_library), Snackbar.LENGTH_INDEFINITE) { + setAction(R.string.action_add) { + presenter.addToLibrary() } + addCallback(object : BaseTransientBottomBar.BaseCallback() { + override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { + super.onDismissed(transientBottomBar, event) + if (snack == transientBottomBar) snack = null + } + }) + } + (activity as? MainActivity)?.setUndoSnackBar(snack) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt index 4168df9b9d..0d2cb9ec15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt @@ -11,18 +11,22 @@ import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.os.Build import android.os.Bundle -import com.google.android.material.snackbar.Snackbar +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat -import android.view.* -import android.widget.Toast import com.afollestad.materialdialogs.MaterialDialog import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.target.CustomTarget -import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.transition.Transition +import com.google.android.material.snackbar.BaseTransientBottomBar +import com.google.android.material.snackbar.Snackbar import com.jakewharton.rxbinding.support.v4.widget.refreshes import com.jakewharton.rxbinding.view.clicks import com.jakewharton.rxbinding.view.longClicks @@ -42,7 +46,14 @@ import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.library.ChangeMangaCategoriesDialog import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaController -import eu.kanade.tachiyomi.util.* +import eu.kanade.tachiyomi.util.doOnApplyWindowInsets +import eu.kanade.tachiyomi.util.getUriCompat +import eu.kanade.tachiyomi.util.marginBottom +import eu.kanade.tachiyomi.util.openInBrowser +import eu.kanade.tachiyomi.util.snack +import eu.kanade.tachiyomi.util.toast +import eu.kanade.tachiyomi.util.updateLayoutParams +import eu.kanade.tachiyomi.util.updatePaddingRelative import jp.wasabeef.glide.transformations.CropSquareTransformation import jp.wasabeef.glide.transformations.MaskTransformation import kotlinx.android.synthetic.main.manga_info_controller.* @@ -460,11 +471,19 @@ class MangaInfoController : NucleusController(), val view = container snack?.dismiss() if (view != null) { - snack = view.snack(view.context.getString(R.string.manga_removed_library), 5000) { + snack = view.snack(view.context.getString(R.string.manga_removed_library), Snackbar.LENGTH_INDEFINITE) { setAction(R.string.action_undo) { presenter.setFavorite(true) } + addCallback(object : BaseTransientBottomBar.BaseCallback() { + override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { + super.onDismissed(transientBottomBar, event) + if (!presenter.manga.favorite) + presenter.confirmDeletion() + } + }) } + (activity as? MainActivity)?.setUndoSnackBar(snack, fab_favorite) } } @@ -480,7 +499,7 @@ class MangaInfoController : NucleusController(), val categories = presenter.getCategories() if (categories.isEmpty()) { // no categories exist, display a message about adding categories - activity?.toast(activity?.getString(R.string.action_add_category)) + snack = container?.snack(R.string.action_add_category) } else { val ids = presenter.getMangaCategoryIds(manga) val preselected = ids.mapNotNull { id -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt index 692ec70d92..a87f56d38b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt @@ -109,15 +109,16 @@ class MangaInfoPresenter( */ fun toggleFavorite(): Boolean { manga.favorite = !manga.favorite - if (!manga.favorite) { - coverCache.deleteFromCache(manga, 5000) - downloadManager.deleteManga(manga, source, 5000) - } db.insertManga(manga).executeAsBlocking() sendMangaToView() return manga.favorite } + fun confirmDeletion() { + coverCache.deleteFromCache(manga.thumbnail_url) + downloadManager.deleteManga(manga, source) + } + fun setFavorite(favorite: Boolean) { if (manga.favorite == favorite) { return diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersController.kt index 1dd05fb1cb..0b07263555 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersController.kt @@ -89,7 +89,7 @@ class RecentChaptersController : NucleusController(), swipe_refresh.refreshes().subscribeUntilDestroy { if (!LibraryUpdateService.isRunning(view.context)) { LibraryUpdateService.start(view.context) - view.snack(R.string.action_update_library) + view.snack(R.string.updating_library) } // It can be a very long operation, so we disable swipe refresh and show a snackbar. swipe_refresh.isRefreshing = false diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bbee6bdecc..3b8f1aca88 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,7 +50,7 @@ Remove bookmark Delete Update - Updating library + Update library Edit Add Add category @@ -317,6 +317,7 @@ Title or author… + Updating library Updating category Local Are you sure you want to remove selected manga?