From 2d3bfa9a89e08bb7318a39ba73620ae2820d6181 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 5 Dec 2019 21:50:36 -0800 Subject: [PATCH] Implement long hold selection for Manga Chapters and library Co-Authored-By: zhuoyang Co-Authored-By: Jays2Kings --- .../ui/library/LibraryCategoryView.kt | 38 ++++++++++++++++--- .../ui/manga/chapter/ChaptersController.kt | 32 ++++++++++++++-- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt index d0208027c..5293d8c18 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt @@ -1,11 +1,11 @@ package eu.kanade.tachiyomi.ui.library import android.content.Context -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import android.util.AttributeSet import android.view.View import android.widget.FrameLayout +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.SelectableAdapter import eu.kanade.tachiyomi.R @@ -18,8 +18,8 @@ import eu.kanade.tachiyomi.util.inflate import eu.kanade.tachiyomi.util.plusAssign import eu.kanade.tachiyomi.util.toast import eu.kanade.tachiyomi.widget.AutofitRecyclerView -import kotlinx.android.synthetic.main.chapters_controller.fast_scroller -import kotlinx.android.synthetic.main.library_category.view.* +import kotlinx.android.synthetic.main.library_category.view.fast_scroller +import kotlinx.android.synthetic.main.library_category.view.swipe_refresh import rx.subscriptions.CompositeSubscription import uy.kohesive.injekt.injectLazy @@ -62,6 +62,8 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att */ private var subscriptions = CompositeSubscription() + private var lastClickPosition = -1 + fun onCreate(controller: LibraryController) { this.controller = controller @@ -174,6 +176,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att } is LibrarySelectionEvent.Unselected -> { findAndToggleSelection(event.manga) + if (adapter.indexOf(event.manga) != -1) lastClickPosition = -1 if (controller.selectedMangas.isEmpty()) { adapter.mode = SelectableAdapter.Mode.SINGLE } @@ -181,6 +184,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att is LibrarySelectionEvent.Cleared -> { adapter.mode = SelectableAdapter.Mode.SINGLE adapter.clearSelection() + lastClickPosition = -1 } } } @@ -204,10 +208,11 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att * @param position the position of the element clicked. * @return true if the item should be selected, false otherwise. */ - override fun onItemClick(view: View, position: Int): Boolean { + override fun onItemClick(view: View?, position: Int): Boolean { // If the action mode is created and the position is valid, toggle the selection. val item = adapter.getItem(position) ?: return false if (adapter.mode == SelectableAdapter.Mode.MULTI) { + lastClickPosition = position toggleSelection(position) return true } else { @@ -223,7 +228,15 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att */ override fun onItemLongClick(position: Int) { controller.createActionModeIfNeeded() - toggleSelection(position) + when { + lastClickPosition == -1 -> setSelection(position) + lastClickPosition > position -> for (i in position until lastClickPosition) + setSelection(i) + lastClickPosition < position -> for (i in lastClickPosition + 1..position) + setSelection(i) + else -> setSelection(position) + } + lastClickPosition = position } /** @@ -247,4 +260,17 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att controller.invalidateActionMode() } + + /** + * Tells the presenter to set the selection for the given position. + * + * @param position the position to toggle. + */ + private fun setSelection(position: Int) { + val item = adapter.getItem(position) ?: return + + controller.setSelection(item.manga, true) + controller.invalidateActionMode() + } + } 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 a6fe7cddf..d7c57826a 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 @@ -55,6 +55,8 @@ class ChaptersController : NucleusController(), */ private val selectedItems = mutableSetOf() + private var lastClickPosition = -1 + init { setHasOptionsMenu(true) setOptionsMenuHidden(true) @@ -184,8 +186,9 @@ class ChaptersController : NucleusController(), fun onNextChapters(chapters: List) { // If the list is empty, fetch chapters from source if the conditions are met // We use presenter chapters instead because they are always unfiltered - if (presenter.chapters.isEmpty()) + if (presenter.chapters.isEmpty()) { initialFetchChapters() + } val adapter = adapter ?: return adapter.updateDataSet(chapters) @@ -242,10 +245,11 @@ class ChaptersController : NucleusController(), startActivity(intent) } - override fun onItemClick(view: View, position: Int): Boolean { + override fun onItemClick(view: View?, position: Int): Boolean { val adapter = adapter ?: return false val item = adapter.getItem(position) ?: return false if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) { + lastClickPosition = position toggleSelection(position) return true } else { @@ -256,7 +260,16 @@ class ChaptersController : NucleusController(), override fun onItemLongClick(position: Int) { createActionModeIfNeeded() - toggleSelection(position) + when { + lastClickPosition == -1 -> setSelection(position) + lastClickPosition > position -> for (i in position until lastClickPosition) + setSelection(i) + lastClickPosition < position -> for (i in lastClickPosition + 1..position) + setSelection(i) + else -> setSelection(position) + } + lastClickPosition = position + adapter?.notifyDataSetChanged() } // SELECTIONS & ACTION MODE @@ -265,6 +278,7 @@ class ChaptersController : NucleusController(), val adapter = adapter ?: return val item = adapter.getItem(position) ?: return adapter.toggleSelection(position) + adapter.notifyDataSetChanged() if (adapter.isSelected(position)) { selectedItems.add(item) } else { @@ -273,6 +287,16 @@ class ChaptersController : NucleusController(), actionMode?.invalidate() } + private fun setSelection(position: Int) { + val adapter = adapter ?: return + val item = adapter.getItem(position) ?: return + if (!adapter.isSelected(position)) { + adapter.toggleSelection(position) + selectedItems.add(item) + actionMode?.invalidate() + } + } + private fun getSelectedChapters(): List { val adapter = adapter ?: return emptyList() return adapter.selectedPositions.mapNotNull { adapter.getItem(it) } @@ -285,6 +309,7 @@ class ChaptersController : NucleusController(), } private fun destroyActionModeIfNeeded() { + lastClickPosition = -1 actionMode?.finish() } @@ -373,7 +398,6 @@ class ChaptersController : NucleusController(), } } - private fun showDeleteChaptersConfirmationDialog() { DeleteChaptersDialog(this).showDialog(router) }