From d24b56835ff225a40cb36dc69a7a32e79e3bf1fd Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Fri, 28 Apr 2023 21:45:03 +0200 Subject: [PATCH] added context app bar for cancelled and errored downloads --- .../ytdlnis/adapter/GenericDownloadAdapter.kt | 72 ++++++++++- .../database/viewmodel/ResultViewModel.kt | 3 +- .../CancelDownloadNotificationReceiver.kt | 1 - .../com/deniscerri/ytdlnis/ui/HomeFragment.kt | 9 +- .../downloadcard/DownloadBottomSheetDialog.kt | 31 +++-- .../ui/downloads/ActiveDownloadsFragment.kt | 10 +- .../downloads/CancelledDownloadsFragment.kt | 112 +++++++++++++++++- .../ui/downloads/ErroredDownloadsFragment.kt | 106 ++++++++++++++++- .../ui/downloads/QueuedDownloadsFragment.kt | 4 + .../com/deniscerri/ytdlnis/util/InfoUtil.kt | 6 +- .../deniscerri/ytdlnis/work/DownloadWorker.kt | 6 + .../ytdlnis/work/TerminalDownloadWorker.kt | 5 + app/src/main/res/layout/download_card.xml | 8 +- .../res/layout/header_navigation_drawer.xml | 32 +++-- .../menu/cancelled_downloads_menu_context.xml | 29 +++++ app/src/main/res/xml/provider_paths.xml | 1 + 16 files changed, 384 insertions(+), 51 deletions(-) create mode 100644 app/src/main/res/menu/cancelled_downloads_menu_context.xml diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt index 8713d3f7..3b40d2c4 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt @@ -1,5 +1,6 @@ package com.deniscerri.ytdlnis.adapter +import android.annotation.SuppressLint import android.app.Activity import android.os.Handler import android.os.Looper @@ -15,24 +16,29 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.util.FileUtil import com.google.android.material.button.MaterialButton +import com.google.android.material.card.MaterialCardView import com.squareup.picasso.Picasso +import java.util.ArrayList class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) { private val onItemClickListener: OnItemClickListener private val activity: Activity private var fileUtil: FileUtil + private val checkedItems: ArrayList init { + checkedItems = ArrayList() this.onItemClickListener = onItemClickListener this.activity = activity fileUtil = FileUtil() } class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) { - val cardView: FrameLayout + val cardView: MaterialCardView init { cardView = itemView.findViewById(R.id.download_card_view) } @@ -116,15 +122,75 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: actionButton.setOnClickListener { onItemClickListener.onActionButtonClick(item.id) } - + if (checkedItems.contains(item.id)) { + card.isChecked = true + card.strokeWidth = 5 + } else { + card.isChecked = false + card.strokeWidth = 0 + } card.setOnClickListener { - onItemClickListener.onCardClick(item.id) + if (checkedItems.size > 0) { + checkCard(card, item.id) + } else { + onItemClickListener.onCardClick(item.id) + } + } + + card.setOnLongClickListener { + checkCard(card, item.id) + true } } + + @SuppressLint("NotifyDataSetChanged") + fun clearCheckeditems() { + for (i in 0 until itemCount){ + val item = getItem(i) + if (checkedItems.find { it == item?.id } != null){ + checkedItems.remove(item?.id) + notifyItemChanged(i) + } + } + + checkedItems.clear() + } + + @SuppressLint("NotifyDataSetChanged") + fun checkAll(items: List?){ + checkedItems.clear() + checkedItems.addAll(items!!.map { it!!.id }) + notifyDataSetChanged() + } + + @SuppressLint("NotifyDataSetChanged") + fun invertSelected(items: List?){ + val invertedList = mutableListOf() + items?.forEach { + if (!checkedItems.contains(it!!.id)) invertedList.add(it.id) + } + checkedItems.clear() + checkedItems.addAll(invertedList) + notifyDataSetChanged() + } + + private fun checkCard(card: MaterialCardView, itemID: Long) { + if (card.isChecked) { + card.strokeWidth = 0 + checkedItems.remove(itemID) + } else { + card.strokeWidth = 5 + checkedItems.add(itemID) + } + card.isChecked = !card.isChecked + onItemClickListener.onCardSelect(itemID, card.isChecked) + } + interface OnItemClickListener { fun onActionButtonClick(itemID: Long) fun onCardClick(itemID: Long) + fun onCardSelect(itemID: Long, isChecked: Boolean) } companion object { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt index b05d5303..c24c5198 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt @@ -75,7 +75,8 @@ class ResultViewModel(application: Application) : AndroidViewModel(application) } suspend fun parseQuery(inputQuery: String, resetResults: Boolean) : ArrayList { - if (resetResults) loadingItems.postValue(true) + if (resetResults) + loadingItems.postValue(true) val type = getQueryType(inputQuery) var res = arrayListOf() return withContext(Dispatchers.IO){ diff --git a/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt b/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt index 7d8c229d..9c152538 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt @@ -15,7 +15,6 @@ class CancelDownloadNotificationReceiver : BroadcastReceiver() { val notificationUtil = NotificationUtil(c) YoutubeDL.getInstance().destroyProcessById(id.toString()) - WorkManager.getInstance(c).cancelUniqueWork(id.toString()) notificationUtil.cancelDownloadNotification(id) } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt index a553c6b6..9fcd0677 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -191,6 +191,13 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi downloadAllFab.tag = "downloadAll" downloadAllFab.setOnClickListener(this) + if (arguments?.getString("url") != null){ + val url = requireArguments().getString("url") + if (inputQueries == null) inputQueries = mutableListOf() + searchBar?.text = url + inputQueries!!.add(url!!) + } + if (inputQueries != null) { resultViewModel.deleteAll() lifecycleScope.launch(Dispatchers.IO){ @@ -470,7 +477,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi } }else{ resultViewModel.parseQueries(queryList) - } } } @@ -654,6 +660,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi super.onStop() } + companion object { private const val TAG = "HomeFragment" } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt index 13278ab4..b2a2b1a4 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt @@ -15,6 +15,7 @@ import android.widget.LinearLayout import android.widget.Toast import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.deniscerri.ytdlnis.R @@ -195,19 +196,23 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val if (quickDownload) { (updateItem.parent as LinearLayout).visibility = View.VISIBLE updateItem.setOnClickListener { - lifecycleScope.launch(Dispatchers.IO){ - if (activity is ShareActivity) { - val intent = Intent(context, ShareActivity::class.java) - intent.action = Intent.ACTION_SEND - intent.type = "text/plain" - intent.putExtra(Intent.EXTRA_TEXT, resultItem.url) - intent.putExtra("quick_download", false) - startActivity(intent) - dismiss() - }else{ - resultViewModel.parseQueries(listOf(resultItem.url)) - dismiss() - } + if (activity is ShareActivity) { + val intent = Intent(context, ShareActivity::class.java) + intent.action = Intent.ACTION_SEND + intent.type = "text/plain" + intent.putExtra(Intent.EXTRA_TEXT, resultItem.url) + intent.putExtra("quick_download", false) + startActivity(intent) + dismiss() + }else{ + dismiss() + val bundle = Bundle() + bundle.putString("url", resultItem.url) + findNavController().popBackStack(R.id.homeFragment, true) + findNavController().navigate( + R.id.homeFragment, + bundle + ) } } }else{ diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt index fb9289fb..a99982f2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt @@ -126,16 +126,16 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL } private fun cancelDownload(itemID: Long){ + val id = itemID.toInt() + YoutubeDL.getInstance().destroyProcessById(id.toString()) + WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString()) + notificationUtil.cancelDownloadNotification(id) + list.find { it.id == itemID }?.let { it.status = DownloadRepository.Status.Cancelled.toString() downloadViewModel.updateDownload(it) } - - val id = itemID.toInt() - YoutubeDL.getInstance().destroyProcessById(id.toString()) - WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString()) - notificationUtil.cancelDownloadNotification(id) } override fun onClick(p0: View?) { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt index 1254063f..f8cbe5a2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt @@ -7,22 +7,25 @@ import android.graphics.Canvas import android.graphics.Color import android.os.Bundle import android.util.DisplayMetrics -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.Window +import android.view.* import android.widget.Button import android.widget.TextView import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.view.ActionMode import androidx.core.content.ContextCompat +import androidx.core.view.forEach import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView +import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.adapter.GenericDownloadAdapter import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog @@ -35,7 +38,11 @@ import com.google.android.material.color.MaterialColors import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import java.util.ArrayList class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener { @@ -45,6 +52,8 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic private lateinit var downloadViewModel : DownloadViewModel private lateinit var cancelledRecyclerView : RecyclerView private lateinit var cancelledDownloads : GenericDownloadAdapter + private var selectedObjects: ArrayList? = null + private var actionMode : ActionMode? = null private lateinit var items : MutableList private lateinit var fileUtil: FileUtil private lateinit var uiUtil : UiUtil @@ -57,6 +66,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic _binding = FragmentHomeBinding.inflate(inflater, container, false) fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false) activity = getActivity() + selectedObjects = arrayListOf() downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] items = mutableListOf() fileUtil = FileUtil() @@ -213,6 +223,26 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic ) } + override fun onCardSelect(itemID: Long, isChecked: Boolean) { + val item = items.find { it.id == itemID } + if (isChecked) { + selectedObjects!!.add(item!!) + if (actionMode == null){ + actionMode = (getActivity() as AppCompatActivity?)!!.startSupportActionMode(contextualActionBar) + + }else{ + actionMode!!.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + } + } + else { + selectedObjects!!.remove(item) + actionMode?.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + if (selectedObjects!!.isEmpty()){ + actionMode?.finish() + } + } + } + private fun removeItem(item: DownloadItem, bottomSheet: BottomSheetDialog?){ bottomSheet?.hide() @@ -225,6 +255,80 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic deleteDialog.show() } + + private val contextualActionBar = object : ActionMode.Callback { + override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { + mode!!.menuInflater.inflate(R.menu.cancelled_downloads_menu_context, menu) + mode.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + return true + } + + override fun onPrepareActionMode( + mode: ActionMode?, + menu: Menu? + ): Boolean { + return false + } + + override fun onActionItemClicked( + mode: ActionMode?, + item: MenuItem? + ): Boolean { + return when (item!!.itemId) { + R.id.delete_results -> { + val deleteDialog = MaterialAlertDialogBuilder(requireContext()) + deleteDialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items)) + deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() } + deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int -> + for (obj in selectedObjects!!){ + downloadViewModel.deleteDownload(obj) + } + clearCheckedItems() + actionMode?.finish() + } + deleteDialog.show() + true + } + R.id.redownload -> { + runBlocking { + downloadViewModel.queueDownloads(selectedObjects!!.toMutableList()) + actionMode?.finish() + } + true + } + R.id.select_all -> { + cancelledDownloads.checkAll(items) + selectedObjects?.clear() + items.forEach { selectedObjects?.add(it) } + mode?.title = getString(R.string.all_items_selected) + true + } + R.id.invert_selected -> { + cancelledDownloads.invertSelected(items) + val invertedList = arrayListOf() + items.forEach { + if (!selectedObjects?.contains(it)!!) invertedList.add(it) + } + selectedObjects?.clear() + selectedObjects?.addAll(invertedList) + actionMode!!.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + true + } + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + actionMode = null + clearCheckedItems() + } + } + + private fun clearCheckedItems(){ + cancelledDownloads.clearCheckeditems() + selectedObjects?.clear() + } + private var simpleCallback: ItemTouchHelper.SimpleCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt index 70138107..d10f55e2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt @@ -8,14 +8,13 @@ import android.graphics.Canvas import android.graphics.Color import android.os.Bundle import android.util.DisplayMetrics -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.Window +import android.view.* import android.widget.AdapterView import android.widget.AdapterView.OnItemClickListener import android.widget.Button import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.view.ActionMode import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider @@ -40,6 +39,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator import kotlinx.coroutines.runBlocking +import java.util.ArrayList class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener { @@ -50,6 +50,8 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL private lateinit var erroredRecyclerView : RecyclerView private lateinit var erroredDownloads : GenericDownloadAdapter private lateinit var items : MutableList + private var selectedObjects: ArrayList? = null + private var actionMode : ActionMode? = null private lateinit var fileUtil: FileUtil private lateinit var uiUtil : UiUtil override fun onCreateView( @@ -62,6 +64,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL activity = getActivity() downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] items = mutableListOf() + selectedObjects = arrayListOf() fileUtil = FileUtil() uiUtil = UiUtil(fileUtil) return fragmentView @@ -213,6 +216,26 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL ) } + override fun onCardSelect(itemID: Long, isChecked: Boolean) { + val item = items.find { it.id == itemID } + if (isChecked) { + selectedObjects!!.add(item!!) + if (actionMode == null){ + actionMode = (getActivity() as AppCompatActivity?)!!.startSupportActionMode(contextualActionBar) + + }else{ + actionMode!!.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + } + } + else { + selectedObjects!!.remove(item) + actionMode?.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + if (selectedObjects!!.isEmpty()){ + actionMode?.finish() + } + } + } + private fun removeItem(item: DownloadItem, bottomSheet: BottomSheetDialog?){ bottomSheet?.hide() val deleteDialog = MaterialAlertDialogBuilder(requireContext()) @@ -228,6 +251,81 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL TODO("Not yet implemented") } + + + private val contextualActionBar = object : ActionMode.Callback { + override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { + mode!!.menuInflater.inflate(R.menu.cancelled_downloads_menu_context, menu) + mode.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + return true + } + + override fun onPrepareActionMode( + mode: ActionMode?, + menu: Menu? + ): Boolean { + return false + } + + override fun onActionItemClicked( + mode: ActionMode?, + item: MenuItem? + ): Boolean { + return when (item!!.itemId) { + R.id.delete_results -> { + val deleteDialog = MaterialAlertDialogBuilder(requireContext()) + deleteDialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items)) + deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() } + deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int -> + for (obj in selectedObjects!!){ + downloadViewModel.deleteDownload(obj) + } + clearCheckedItems() + actionMode?.finish() + } + deleteDialog.show() + true + } + R.id.redownload -> { + runBlocking { + downloadViewModel.queueDownloads(selectedObjects!!.toMutableList()) + actionMode?.finish() + } + true + } + R.id.select_all -> { + erroredDownloads.checkAll(items) + selectedObjects?.clear() + items.forEach { selectedObjects?.add(it) } + mode?.title = getString(R.string.all_items_selected) + true + } + R.id.invert_selected -> { + erroredDownloads.invertSelected(items) + val invertedList = arrayListOf() + items.forEach { + if (!selectedObjects?.contains(it)!!) invertedList.add(it) + } + selectedObjects?.clear() + selectedObjects?.addAll(invertedList) + actionMode!!.title = "${selectedObjects!!.size} ${getString(R.string.selected)}" + true + } + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + actionMode = null + clearCheckedItems() + } + } + + private fun clearCheckedItems(){ + erroredDownloads.clearCheckeditems() + selectedObjects?.clear() + } + private var simpleCallback: ItemTouchHelper.SimpleCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt index 3dff5a24..ca97bd6b 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt @@ -241,6 +241,10 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi ) } + override fun onCardSelect(itemID: Long, isChecked: Boolean) { + TODO("Not yet implemented") + } + private fun removeItem(itemID: Long){ val item = items.find { it.id == itemID } val deleteDialog = MaterialAlertDialogBuilder(requireContext()) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt index 6080a5b8..f3c8f554 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt @@ -613,8 +613,10 @@ class InfoUtil(private val context: Context) { author = jsonObject.getString("uploader") } var duration = "" - if (jsonObject.has("duration")) { - duration = formatIntegerDuration(jsonObject.getInt("duration"), Locale.getDefault()) + runCatching { + if (jsonObject.has("duration")) { + duration = formatIntegerDuration(jsonObject.getInt("duration"), Locale.getDefault()) + } } val url = jsonObject.getString("webpage_url") var thumb: String? = "" diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt index aff8d1c0..b10ce85e 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -388,6 +388,12 @@ class DownloadWorker( return Result.success() } + + override fun onStopped() { + YoutubeDL.getInstance().destroyProcessById(itemId.toInt().toString()) + super.onStopped() + } + @Throws(Exception::class) private fun moveFile(originDir: File, downLocation: String, progress: (progress: Int) -> Unit) : String{ val fileUtil = FileUtil() diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt index 06addc25..9bd7e37d 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt @@ -131,6 +131,11 @@ class TerminalDownloadWorker( return Result.success() } + override fun onStopped() { + YoutubeDL.getInstance().destroyProcessById(DownloadWorker.itemId.toInt().toString()) + super.onStopped() + } + @Throws(Exception::class) private fun moveFile(originDir: File, downLocation: String, progress: (progress: Int) -> Unit) : String{ val fileUtil = FileUtil() diff --git a/app/src/main/res/layout/download_card.xml b/app/src/main/res/layout/download_card.xml index eccea226..2b47e3da 100644 --- a/app/src/main/res/layout/download_card.xml +++ b/app/src/main/res/layout/download_card.xml @@ -5,13 +5,13 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/header_navigation_drawer.xml b/app/src/main/res/layout/header_navigation_drawer.xml index 339fe930..735d26b3 100644 --- a/app/src/main/res/layout/header_navigation_drawer.xml +++ b/app/src/main/res/layout/header_navigation_drawer.xml @@ -1,4 +1,5 @@ - + android:insetBottom="0dp" + android:padding="0dp" + app:icon="@drawable/ic_app_icon" + app:iconSize="50dp" + app:iconTint="@null" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toEndOf="@+id/materialButton" + app:layout_constraintTop_toTopOf="parent" /> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/menu/cancelled_downloads_menu_context.xml b/app/src/main/res/menu/cancelled_downloads_menu_context.xml new file mode 100644 index 00000000..4457b1ef --- /dev/null +++ b/app/src/main/res/menu/cancelled_downloads_menu_context.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml index bce93183..20151e82 100644 --- a/app/src/main/res/xml/provider_paths.xml +++ b/app/src/main/res/xml/provider_paths.xml @@ -1,6 +1,7 @@ +