浏览代码

Implement long hold selection for Manga Chapters and library

Co-Authored-By: zhuoyang <[email protected]>

Co-Authored-By: Jays2Kings <[email protected]>
Jay 5 年之前
父节点
当前提交
2d3bfa9a89

+ 32 - 6
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()
+    }
+
 }

+ 28 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersController.kt

@@ -55,6 +55,8 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
      */
     private val selectedItems = mutableSetOf<ChapterItem>()
 
+    private var lastClickPosition = -1
+
     init {
         setHasOptionsMenu(true)
         setOptionsMenuHidden(true)
@@ -184,8 +186,9 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
     fun onNextChapters(chapters: List<ChapterItem>) {
         // 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<ChaptersPresenter>(),
         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<ChaptersPresenter>(),
 
     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<ChaptersPresenter>(),
         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<ChaptersPresenter>(),
         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<ChapterItem> {
         val adapter = adapter ?: return emptyList()
         return adapter.selectedPositions.mapNotNull { adapter.getItem(it) }
@@ -285,6 +309,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
     }
 
     private fun destroyActionModeIfNeeded() {
+        lastClickPosition = -1
         actionMode?.finish()
     }
 
@@ -373,7 +398,6 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
         }
     }
 
-
     private fun showDeleteChaptersConfirmationDialog() {
         DeleteChaptersDialog(this).showDialog(router)
     }