mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Minor performance optimization and split to new class file and cleanup
This commit is contained in:
parent
34c5c9f621
commit
3ceabb4de3
2 changed files with 179 additions and 159 deletions
|
@ -4,23 +4,15 @@ import android.annotation.SuppressLint
|
|||
import android.app.Dialog
|
||||
import android.content.ClipboardManager
|
||||
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.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.format.Formatter.formatShortFileSize
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
|
@ -32,7 +24,6 @@ import com.lagradost.cloudstream3.CommonActivity.showToast
|
|||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.databinding.FragmentDownloadsBinding
|
||||
import com.lagradost.cloudstream3.databinding.StreamInputBinding
|
||||
import com.lagradost.cloudstream3.isEpisodeBased
|
||||
import com.lagradost.cloudstream3.isMovieType
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
|
@ -46,7 +37,6 @@ import com.lagradost.cloudstream3.ui.settings.Globals.TV
|
|||
import com.lagradost.cloudstream3.ui.settings.Globals.isLayout
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
|
||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
|
||||
import com.lagradost.cloudstream3.utils.DataStore
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
|
@ -215,7 +205,12 @@ class DownloadFragment : Fragment() {
|
|||
)
|
||||
//layoutManager = GridLayoutManager(context, 1)
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(this.adapter as DownloadHeaderAdapter))
|
||||
val itemTouchHelper = ItemTouchHelper(
|
||||
DownloadSwipeToDeleteCallback(
|
||||
this.adapter as DownloadHeaderAdapter,
|
||||
context
|
||||
)
|
||||
)
|
||||
itemTouchHelper.attachToRecyclerView(binding?.downloadList)
|
||||
}
|
||||
|
||||
|
@ -298,151 +293,3 @@ class DownloadFragment : Fragment() {
|
|||
fixPaddingStatusbar(binding?.downloadRoot)
|
||||
}
|
||||
}
|
||||
|
||||
class SwipeToDeleteCallback(private val adapter: DownloadHeaderAdapter) : ItemTouchHelper.Callback() {
|
||||
|
||||
private val swipeOpenItems: MutableSet<Int> = mutableSetOf()
|
||||
|
||||
override fun getMovementFlags(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
): Int {
|
||||
val position = viewHolder.bindingAdapterPosition
|
||||
val item = adapter.cardList[position]
|
||||
if (item.data.type.isEpisodeBased()) return 0
|
||||
return makeMovementFlags(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT)
|
||||
}
|
||||
|
||||
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
|
||||
) {}
|
||||
|
||||
private fun handleDelete(position: Int) {
|
||||
val item = adapter.cardList[position]
|
||||
|
||||
runOnMainThread {
|
||||
item.child?.let { clickEvent ->
|
||||
handleDownloadClick(
|
||||
DownloadClickEvent(
|
||||
DOWNLOAD_ACTION_DELETE_FILE,
|
||||
clickEvent
|
||||
)
|
||||
) { adapter.notifyItemRemoved(position) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
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 position = viewHolder.bindingAdapterPosition
|
||||
|
||||
val deleteIcon: Drawable = ContextCompat.getDrawable(
|
||||
recyclerView.context,
|
||||
R.drawable.ic_baseline_delete_outline_24
|
||||
) ?: return
|
||||
|
||||
val background = ColorDrawable(Color.RED)
|
||||
background.alpha = 160
|
||||
|
||||
val itemView = viewHolder.itemView
|
||||
|
||||
val scaleFactor = 1.25f
|
||||
val iconWidth = (deleteIcon.intrinsicWidth * scaleFactor).toInt()
|
||||
val iconHeight = (deleteIcon.intrinsicHeight * scaleFactor).toInt()
|
||||
|
||||
val iconTop = itemView.top + (itemView.height - iconHeight) / 2
|
||||
val iconBottom = iconTop + iconHeight
|
||||
|
||||
val maxSwipeDistance = 230f
|
||||
val minSwipeDistance = itemView.width / 4.5f
|
||||
val swipeDistance = minOf(minSwipeDistance, maxSwipeDistance)
|
||||
|
||||
val limitedDX = if (dX < -swipeDistance) -swipeDistance else if (dX >= 0) 0f else dX
|
||||
|
||||
if (limitedDX < 0) { // Swiping to the left
|
||||
val backgroundLeft = itemView.right + limitedDX.toInt()
|
||||
val backgroundRight = itemView.right
|
||||
val backgroundTop = itemView.top
|
||||
val backgroundBottom = itemView.bottom
|
||||
|
||||
val iconLeft = backgroundLeft + (backgroundRight - backgroundLeft - iconWidth) / 2
|
||||
val iconRight = iconLeft + iconWidth
|
||||
deleteIcon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||
|
||||
val path = Path()
|
||||
val rectF = RectF(
|
||||
backgroundLeft.toFloat(),
|
||||
backgroundTop.toFloat(),
|
||||
backgroundRight.toFloat(),
|
||||
backgroundBottom.toFloat()
|
||||
)
|
||||
|
||||
val radii = floatArrayOf(0f, 0f, 20f, 20f, 20f, 20f, 0f, 0f)
|
||||
path.addRoundRect(rectF, radii, Path.Direction.CW)
|
||||
c.clipPath(path)
|
||||
|
||||
background.setBounds(backgroundLeft, backgroundTop, backgroundRight, backgroundBottom)
|
||||
} else background.setBounds(0, 0, 0, 0)
|
||||
|
||||
background.draw(c)
|
||||
deleteIcon.draw(c)
|
||||
|
||||
if (dX <= -swipeDistance && !isCurrentlyActive) {
|
||||
swipeOpenItems.add(position)
|
||||
} else {
|
||||
swipeOpenItems.remove(position)
|
||||
super.onChildDraw(c, recyclerView, viewHolder, limitedDX, dY, actionState, isCurrentlyActive)
|
||||
}
|
||||
|
||||
if (swipeOpenItems.isNotEmpty()) {
|
||||
recyclerView.setOnTouchListener { _, event ->
|
||||
if (event.action == MotionEvent.ACTION_UP) {
|
||||
val x = event.x.toInt()
|
||||
val y = event.y.toInt()
|
||||
var handled = false
|
||||
|
||||
swipeOpenItems.forEach { pos ->
|
||||
val vh = recyclerView.findViewHolderForAdapterPosition(pos)
|
||||
if (vh != null) {
|
||||
val swipeItemView = vh.itemView
|
||||
val backgroundLeft = swipeItemView.right - swipeDistance.toInt()
|
||||
val backgroundRight = swipeItemView.right
|
||||
val backgroundTop = swipeItemView.top
|
||||
val backgroundBottom = swipeItemView.bottom
|
||||
|
||||
if (x in backgroundLeft..backgroundRight && y in backgroundTop..backgroundBottom) {
|
||||
handleDelete(pos)
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
handled
|
||||
} else false
|
||||
}
|
||||
} else recyclerView.setOnTouchListener(null)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
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.utils.Coroutines.runOnMainThread
|
||||
|
||||
class DownloadSwipeToDeleteCallback(
|
||||
private val adapter: DownloadHeaderAdapter,
|
||||
private val context: Context
|
||||
) : ItemTouchHelper.Callback() {
|
||||
|
||||
private val swipeOpenItems: MutableSet<Int> = 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 position = viewHolder.bindingAdapterPosition
|
||||
val item = adapter.cardList[position]
|
||||
return if (item.data.type.isEpisodeBased()) 0 else {
|
||||
makeMovementFlags(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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, 20f, 20f, 20f, 20f, 0f, 0f),
|
||||
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) {
|
||||
swipeOpenItems.add(viewHolder.bindingAdapterPosition)
|
||||
setRecyclerViewTouchListener(recyclerView, swipeDistance)
|
||||
} else {
|
||||
swipeOpenItems.remove(viewHolder.bindingAdapterPosition)
|
||||
if (swipeOpenItems.isEmpty()) removeRecyclerViewTouchListener(recyclerView)
|
||||
super.onChildDraw(c, recyclerView, viewHolder, limitedDX, dY, actionState, isCurrentlyActive)
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
handleDelete(pos)
|
||||
return@setOnTouchListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
} else false
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun removeRecyclerViewTouchListener(
|
||||
recyclerView: RecyclerView
|
||||
): Unit = recyclerView.setOnTouchListener(null)
|
||||
|
||||
private fun handleDelete(position: Int) {
|
||||
val item = adapter.cardList[position]
|
||||
runOnMainThread {
|
||||
item.child?.let { clickEvent ->
|
||||
DownloadButtonSetup.handleDownloadClick(
|
||||
DownloadClickEvent(
|
||||
DOWNLOAD_ACTION_DELETE_FILE,
|
||||
clickEvent
|
||||
)
|
||||
) { adapter.notifyItemRemoved(position) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue