From fa14b5e17f4abfd36c89cd20e40601516e508c88 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:02:55 -0600 Subject: [PATCH] Remove swipe to delete --- .../ui/download/DownloadChildFragment.kt | 11 - .../ui/download/DownloadFragment.kt | 13 - .../download/DownloadSwipeDeleteCallback.kt | 260 ------------------ 3 files changed, 284 deletions(-) delete mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadSwipeDeleteCallback.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt index b9de8cbb..89c8b31b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt @@ -6,7 +6,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.databinding.FragmentChildDownloadsBinding @@ -131,16 +130,6 @@ class DownloadChildFragment : Fragment() { nextRight = FOCUS_SELF, nextDown = FOCUS_SELF ) - - if (isLayout(PHONE or EMULATOR)) { - val itemTouchHelper = ItemTouchHelper( - DownloadSwipeDeleteCallback( - this.adapter as DownloadAdapter, - context ?: return@apply - ) - ) - itemTouchHelper.attachToRecyclerView(binding?.downloadChildList) - } } updateList(folder) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt index d7842b5d..3c440417 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt @@ -18,7 +18,6 @@ import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider -import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R @@ -33,8 +32,6 @@ import com.lagradost.cloudstream3.ui.player.GeneratorPlayer import com.lagradost.cloudstream3.ui.player.LinkGenerator import com.lagradost.cloudstream3.ui.result.FOCUS_SELF import com.lagradost.cloudstream3.ui.result.setLinearListLayout -import com.lagradost.cloudstream3.ui.settings.Globals.EMULATOR -import com.lagradost.cloudstream3.ui.settings.Globals.PHONE import com.lagradost.cloudstream3.ui.settings.Globals.TV import com.lagradost.cloudstream3.ui.settings.Globals.isLayout import com.lagradost.cloudstream3.utils.AppUtils.loadResult @@ -198,16 +195,6 @@ class DownloadFragment : Fragment() { nextUp = FOCUS_SELF, nextDown = FOCUS_SELF ) - - if (isLayout(PHONE or EMULATOR)) { - val itemTouchHelper = ItemTouchHelper( - DownloadSwipeDeleteCallback( - this.adapter as DownloadAdapter, - context - ) - ) - itemTouchHelper.attachToRecyclerView(binding?.downloadList) - } } // Should be visible in emulator layout diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadSwipeDeleteCallback.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadSwipeDeleteCallback.kt deleted file mode 100644 index fafb4512..00000000 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadSwipeDeleteCallback.kt +++ /dev/null @@ -1,260 +0,0 @@ -package com.lagradost.cloudstream3.ui.download - -import android.annotation.SuppressLint -import android.content.Context -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Path -import android.graphics.RectF -import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable -import android.view.MotionEvent -import androidx.core.content.ContextCompat -import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.RecyclerView -import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.isEpisodeBased -import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick -import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread -import com.lagradost.cloudstream3.utils.VideoDownloadHelper -import com.lagradost.cloudstream3.utils.VideoDownloadManager.downloadDeleteEvent - -class DownloadSwipeDeleteCallback( - private val adapter: DownloadAdapter, - private val context: Context -) : ItemTouchHelper.Callback() { - - private var downloadDeleteEventListener: ((Int) -> Unit)? = null - - private val swipeOpenItems: MutableSet = mutableSetOf() - private val deleteIcon: Drawable? by lazy { - ContextCompat.getDrawable(context, R.drawable.ic_baseline_delete_outline_24) - } - private val background: ColorDrawable by lazy { - ColorDrawable(Color.RED).apply { alpha = 160 } - } - private val scaleFactor = 1.25f - private val maxSwipeDistance = 230f - - override fun getMovementFlags( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder - ): Int { - val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT - - val position = viewHolder.bindingAdapterPosition - val item = adapter.cardList[position] - if (item !is VisualDownloadHeaderCached) return makeMovementFlags(0, swipeFlags) - return if (item.data.type.isEpisodeBased()) 0 else { - makeMovementFlags(0, swipeFlags) - } - } - - override fun isLongPressDragEnabled(): Boolean = false - - override fun isItemViewSwipeEnabled(): Boolean = true - - override fun onMove( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - target: RecyclerView.ViewHolder - ): Boolean = false - - override fun onSwiped( - viewHolder: RecyclerView.ViewHolder, - direction: Int - ) {} - - override fun onChildDraw( - c: Canvas, - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - dX: Float, - dY: Float, - actionState: Int, - isCurrentlyActive: Boolean - ) { - if (dX == 0f) { - super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) - return - } - - val itemView = viewHolder.itemView - - val minSwipeDistance = itemView.width / 4.5f - val swipeDistance = minOf(minSwipeDistance, maxSwipeDistance) - val limitedDX = if (dX < -swipeDistance) -swipeDistance else if (dX >= 0) 0f else dX - - val position = viewHolder.bindingAdapterPosition - - if (swipeOpenItems.contains(position)) { - // If the item is already swiped we need to restore that - // state so that you can delete items without the state - // resetting, making it easier to quickly delete multiple items. - super.onChildDraw(c, recyclerView, viewHolder, limitedDX, dY, actionState, isCurrentlyActive) - } - - if (limitedDX < 0) { // Swiping to the left - val icon = deleteIcon ?: return - - val backgroundLeft = itemView.right + limitedDX.toInt() - - val iconWidth = (icon.intrinsicWidth * scaleFactor).toInt() - val iconHeight = (icon.intrinsicHeight * scaleFactor).toInt() - - val iconTop = itemView.top + (itemView.height - iconHeight) / 2 - val iconBottom = iconTop + iconHeight - - val iconLeft = backgroundLeft + (itemView.right - backgroundLeft - iconWidth) / 2 - val iconRight = iconLeft + iconWidth - - icon.setBounds(iconLeft, iconTop, iconRight, iconBottom) - - val path = Path().apply { - addRoundRect( - RectF( - backgroundLeft.toFloat(), - itemView.top.toFloat(), - itemView.right.toFloat(), - itemView.bottom.toFloat() - ), - floatArrayOf( - 0f, 0f, // Top-left corner - 20f, 20f, // Top-right corner - 20f, 20f, // Bottom-right corner - 0f, 0f // Bottom-left corner - ), - Path.Direction.CW - ) - } - c.clipPath(path) - background.setBounds( - backgroundLeft, - itemView.top, - itemView.right, - itemView.bottom - ) - background.draw(c) - icon.draw(c) - } else background.setBounds(0, 0, 0, 0) - - if (dX <= -swipeDistance && !isCurrentlyActive && adapter.cardList.getOrNull(position) != null) { - swipeOpenItems.add(position) - setRecyclerViewTouchListener(recyclerView, swipeDistance) - } else { - swipeOpenItems.remove(position) - if (swipeOpenItems.isEmpty()) removeRecyclerViewTouchListener(recyclerView) - super.onChildDraw(c, recyclerView, viewHolder, limitedDX, dY, actionState, isCurrentlyActive) - } - } - - override fun clearView( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder - ) { - clearDownloadDeleteEvent() - super.clearView(recyclerView, viewHolder) - } - - @SuppressLint("ClickableViewAccessibility") - private fun setRecyclerViewTouchListener( - recyclerView: RecyclerView, - swipeDistance: Float - ) { - recyclerView.setOnTouchListener { _, event -> - if (event.action == MotionEvent.ACTION_UP) { - val x = event.x.toInt() - val y = event.y.toInt() - swipeOpenItems.forEach { pos -> - val vh = recyclerView.findViewHolderForAdapterPosition(pos) - vh?.itemView?.let { swipeItemView -> - val backgroundLeft: Int = swipeItemView.right - swipeDistance.toInt() - val backgroundXRange: IntRange = backgroundLeft..swipeItemView.right - val backgroundYRange: IntRange = swipeItemView.top..swipeItemView.bottom - if (x in backgroundXRange && y in backgroundYRange) { - handleDeleteAction(pos) - addDownloadDeleteEvent(pos) - return@setOnTouchListener true - } - } - } - false - } else false - } - } - - @SuppressLint("ClickableViewAccessibility") - private fun removeRecyclerViewTouchListener(recyclerView: RecyclerView) { - // We don't want to unnecessarily listen to unused touch events - recyclerView.setOnTouchListener(null) - - /** - * If we are not listening to touch events, then - * we should clear the delete event as it will - * not be used at the moment. - */ - clearDownloadDeleteEvent() - } - - private fun handleDeleteAction(position: Int) { - val item = adapter.cardList[position] - runOnMainThread { - val data: VideoDownloadHelper.DownloadEpisodeCached? = if (item is VisualDownloadHeaderCached) item.child else { - item.data as VideoDownloadHelper.DownloadEpisodeCached? - } - data?.let { clickEvent -> - handleDownloadClick( - DownloadClickEvent( - DOWNLOAD_ACTION_DELETE_FILE, - clickEvent - ) - ) - } - } - } - - private fun addDownloadDeleteEvent(position: Int) { - // Clear any old events as we don't want to get - // concurrent modification errors - clearDownloadDeleteEvent() - downloadDeleteEventListener = { id: Int -> - val list = adapter.cardList - if (list.any { it.data.id == id }) { - /** - * Seamlessly remove now-deleted item from adapter. - * We don't need to reload from the viewModel, - * that just causes more unnecessary actions and - * unreliable data to be returned oftentimes, - * as it would cause it to reload the entire - * view model (which is all items) we only want - * to target one item and this provides a more seamless - * and performant solution to it since we do have access to - * the position we need to target here. - */ - if (list.getOrNull(position) != null) { - adapter.cardList.removeAt(position) - } - adapter.notifyItemRemoved(position) - } - } - - // We use synchronized to ensure we are thread-safe and - // to avoid potential race conditions that may cause - // concurrent modification errors - synchronized(this) { - downloadDeleteEventListener?.let { downloadDeleteEvent += it } - } - } - - private fun clearDownloadDeleteEvent() { - // We use synchronized to ensure we are thread-safe and - // to avoid potential race conditions that may cause - // concurrent modification errors - synchronized(this) { - if (downloadDeleteEventListener != null) { - downloadDeleteEvent -= downloadDeleteEventListener!! - downloadDeleteEventListener = null - } - } - } -} \ No newline at end of file