Merge pull request #4269 from Bnyro/master

feat: swipe to delete downloads
This commit is contained in:
Bnyro 2023-07-19 11:04:28 +02:00 committed by GitHub
commit c658693695
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 28 deletions

View File

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.databinding.DownloadedMediaRowBinding import com.github.libretube.databinding.DownloadedMediaRowBinding
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.DownloadWithItems import com.github.libretube.db.obj.DownloadWithItems
import com.github.libretube.extensions.formatAsFileSize import com.github.libretube.extensions.formatAsFileSize
import com.github.libretube.helpers.ImageHelper import com.github.libretube.helpers.ImageHelper
@ -18,6 +19,10 @@ import com.github.libretube.ui.activities.OfflinePlayerActivity
import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet
import com.github.libretube.ui.viewholders.DownloadsViewHolder import com.github.libretube.ui.viewholders.DownloadsViewHolder
import com.github.libretube.util.TextUtils import com.github.libretube.util.TextUtils
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlin.io.path.deleteIfExists
import kotlin.io.path.fileSize import kotlin.io.path.fileSize
class DownloadsAdapter( class DownloadsAdapter(
@ -90,10 +95,8 @@ class DownloadsAdapter(
} }
root.setOnLongClickListener { root.setOnLongClickListener {
DownloadOptionsBottomSheet(download, items) { DownloadOptionsBottomSheet(download) {
downloads.removeAt(position) showDeleteDialog(root.context, position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount)
}.show( }.show(
(root.context as AppCompatActivity).supportFragmentManager (root.context as AppCompatActivity).supportFragmentManager
) )
@ -102,6 +105,40 @@ class DownloadsAdapter(
} }
} }
fun showDeleteDialog(context: Context, position: Int) {
MaterialAlertDialogBuilder(context)
.setTitle(R.string.delete)
.setMessage(R.string.irreversible)
.setPositiveButton(R.string.okay) { _, _ ->
deleteDownload(position)
}
.setNegativeButton(R.string.cancel, null)
.show()
}
private fun deleteDownload(position: Int) {
val download = downloads[position].download
val items = downloads[position].downloadItems
items.forEach {
it.path.deleteIfExists()
}
download.thumbnailPath?.deleteIfExists()
runBlocking(Dispatchers.IO) {
DatabaseHolder.Database.downloadDao().deleteDownload(download)
}
downloads.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount)
}
fun restoreItem(position: Int) {
// moves the item back to its initial horizontal position
notifyItemRemoved(position)
notifyItemInserted(position)
}
override fun getItemCount(): Int { override fun getItemCount(): Int {
return downloads.size return downloads.size
} }

View File

@ -11,6 +11,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R import com.github.libretube.R
@ -84,7 +85,7 @@ class DownloadsFragment : Fragment() {
binding.downloads.layoutManager = LinearLayoutManager(context) binding.downloads.layoutManager = LinearLayoutManager(context)
binding.downloads.adapter = DownloadsAdapter(requireContext(), downloads) { val adapter = DownloadsAdapter(requireContext(), downloads) {
var isDownloading = false var isDownloading = false
val ids = it.downloadItems val ids = it.downloadItems
.filter { item -> item.path.fileSize() < item.downloadSize } .filter { item -> item.path.fileSize() < item.downloadSize }
@ -110,6 +111,28 @@ class DownloadsFragment : Fragment() {
return@DownloadsAdapter isDownloading.not() return@DownloadsAdapter isDownloading.not()
} }
binding.downloads.adapter = adapter
val itemTouchCallback = object: ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int = makeMovementFlags(0, ItemTouchHelper.LEFT)
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
adapter.showDeleteDialog(requireContext(), viewHolder.absoluteAdapterPosition)
// put the item back to the center, as it's currently out of the screen
adapter.restoreItem(viewHolder.absoluteAdapterPosition)
}
}
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.downloads)
binding.downloads.adapter?.registerAdapterDataObserver( binding.downloads.adapter?.registerAdapterDataObserver(
object : RecyclerView.AdapterDataObserver() { object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {

View File

@ -5,22 +5,16 @@ import android.os.Bundle
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.Download import com.github.libretube.db.obj.Download
import com.github.libretube.db.obj.DownloadItem
import com.github.libretube.enums.ShareObjectType import com.github.libretube.enums.ShareObjectType
import com.github.libretube.helpers.NavigationHelper import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.obj.ShareData import com.github.libretube.obj.ShareData
import com.github.libretube.services.OfflinePlayerService import com.github.libretube.services.OfflinePlayerService
import com.github.libretube.ui.dialogs.ShareDialog import com.github.libretube.ui.dialogs.ShareDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlin.io.path.deleteIfExists
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
class DownloadOptionsBottomSheet( class DownloadOptionsBottomSheet(
private val download: Download, private val download: Download,
private val items: List<DownloadItem>,
private val onDelete: () -> Unit private val onDelete: () -> Unit
) : BaseBottomSheet() { ) : BaseBottomSheet() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -50,23 +44,8 @@ class DownloadOptionsBottomSheet(
} }
3 -> { 3 -> {
MaterialAlertDialogBuilder(requireContext()) onDelete.invoke()
.setTitle(R.string.delete) dialog?.dismiss()
.setMessage(R.string.irreversible)
.setPositiveButton(R.string.okay) { _, _ ->
items.forEach {
it.path.deleteIfExists()
}
download.thumbnailPath?.deleteIfExists()
runBlocking(Dispatchers.IO) {
DatabaseHolder.Database.downloadDao().deleteDownload(download)
}
onDelete.invoke()
dialog?.dismiss()
}
.setNegativeButton(R.string.cancel, null)
.show()
} }
} }
} }