From 071e6311a1d5b291361ff154553e4437dd033141 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Wed, 19 Jul 2023 11:04:59 +0200 Subject: [PATCH] feat: swipe to delete downloads --- .../libretube/ui/adapters/DownloadsAdapter.kt | 45 +++++++++++++++++-- .../ui/fragments/DownloadsFragment.kt | 25 ++++++++++- .../ui/sheets/DownloadOptionsBottomSheet.kt | 25 +---------- 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/adapters/DownloadsAdapter.kt b/app/src/main/java/com/github/libretube/ui/adapters/DownloadsAdapter.kt index 8a85450d6..b8e9dd8b4 100644 --- a/app/src/main/java/com/github/libretube/ui/adapters/DownloadsAdapter.kt +++ b/app/src/main/java/com/github/libretube/ui/adapters/DownloadsAdapter.kt @@ -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 } diff --git a/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt index 502c46bb0..236cd83f4 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt @@ -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) { diff --git a/app/src/main/java/com/github/libretube/ui/sheets/DownloadOptionsBottomSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/DownloadOptionsBottomSheet.kt index 6a959d58f..966dc9c8f 100644 --- a/app/src/main/java/com/github/libretube/ui/sheets/DownloadOptionsBottomSheet.kt +++ b/app/src/main/java/com/github/libretube/ui/sheets/DownloadOptionsBottomSheet.kt @@ -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, private val onDelete: () -> Unit ) : BaseBottomSheet() { override fun onCreate(savedInstanceState: Bundle?) { @@ -50,23 +44,8 @@ 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() + onDelete.invoke() + dialog?.dismiss() } } }