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.constants.IntentData
import com.github.libretube.databinding.DownloadedMediaRowBinding
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.DownloadWithItems
import com.github.libretube.extensions.formatAsFileSize
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.viewholders.DownloadsViewHolder
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
class DownloadsAdapter(
@ -90,10 +95,8 @@ class DownloadsAdapter(
}
root.setOnLongClickListener {
DownloadOptionsBottomSheet(download, items) {
downloads.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount)
DownloadOptionsBottomSheet(download) {
showDeleteDialog(root.context, position)
}.show(
(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 {
return downloads.size
}

View File

@ -11,6 +11,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
@ -84,7 +85,7 @@ class DownloadsFragment : Fragment() {
binding.downloads.layoutManager = LinearLayoutManager(context)
binding.downloads.adapter = DownloadsAdapter(requireContext(), downloads) {
val adapter = DownloadsAdapter(requireContext(), downloads) {
var isDownloading = false
val ids = it.downloadItems
.filter { item -> item.path.fileSize() < item.downloadSize }
@ -110,6 +111,28 @@ class DownloadsFragment : Fragment() {
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(
object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {

View File

@ -5,22 +5,16 @@ import android.os.Bundle
import androidx.core.content.ContextCompat
import com.github.libretube.R
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.DownloadItem
import com.github.libretube.enums.ShareObjectType
import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.obj.ShareData
import com.github.libretube.services.OfflinePlayerService
import com.github.libretube.ui.dialogs.ShareDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlin.io.path.deleteIfExists
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
class DownloadOptionsBottomSheet(
private val download: Download,
private val items: List<DownloadItem>,
private val onDelete: () -> Unit
) : BaseBottomSheet() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -50,24 +44,9 @@ class DownloadOptionsBottomSheet(
}
3 -> {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.delete)
.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()
}
}
}