Skip to content

Commit

Permalink
new features
Browse files Browse the repository at this point in the history
added a header on cancelled, errored, saved, scheduled tabs to show the count of items and their own separate menus to copy the urls and delete them all
fix app not starting a scheduled download when there were no paused items, strange ik
add socket timeout in download settings
fixed app not putting extra commands in the very end of the command list
home screen channel tab filter bug fixes
Add ability to Set default command template
  • Loading branch information
zaednasr committed Oct 19, 2024
1 parent 02a5c0c commit 80672a2
Show file tree
Hide file tree
Showing 52 changed files with 371 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ interface DownloadDao {
@Query("UPDATE downloads SET downloadStartTime=0, status='Queued' where id in (:list)")
suspend fun resetScheduleTimeForItems(list: List<Long>)

@Query("UPDATE downloads SET downloadStartTime=0, status='Queued' WHERE status = 'Scheduled'")
suspend fun resetScheduleTimeForAllScheduledItems()

@Query("Update downloads SET status='Queued', downloadStartTime = 0 WHERE id in (:list)")
suspend fun reQueueDownloadItems(list: List<Long>)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
repository.startDownloadWorker(emptyList(), application)
}

suspend fun resetScheduleItemForAllScheduledItemsAndStartDownload() = CoroutineScope(Dispatchers.IO).launch {
dbManager.downloadDao.resetScheduleTimeForAllScheduledItems()
repository.startDownloadWorker(emptyList(), application)
}

suspend fun putAtTopOfQueue(ids: List<Long>) = CoroutineScope(Dispatchers.IO).launch{
val downloads = dao.getQueuedDownloadsListIDs()
val lastID = ids.maxOf { it }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
val sortOrder = MutableLiveData(SORTING.DESC)
val sortType = MutableLiveData(HistorySortType.DATE)
val websiteFilter = MutableLiveData("")
val statusFilter = MutableLiveData(HistoryStatus.UNSET)
val statusFilter = MutableLiveData(HistoryStatus.ALL)
private val queryFilter = MutableLiveData("")
private val typeFilter = MutableLiveData("")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
downloadViewModel.deleteDownload(id)

if (processingItemsCount > 0){
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.undo)) {
lifecycleScope.launch(Dispatchers.IO) {
processingItemsCount++
Expand Down Expand Up @@ -976,7 +976,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure


if (processingItemsCount > 0) {
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.undo)) {
processingItemsCount++
downloadViewModel.insert(deletedItem)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ import android.content.DialogInterface
import android.content.SharedPreferences
import android.graphics.Canvas
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.core.view.get
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
Expand All @@ -36,6 +42,7 @@ import com.deniscerri.ytdl.util.Extensions.forceFastScrollMode
import com.deniscerri.ytdl.util.Extensions.toListString
import com.deniscerri.ytdl.util.UiUtil
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton
import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
Expand All @@ -60,6 +67,10 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
private var actionMode : ActionMode? = null
private var totalSize = 0

private lateinit var listHeader : ConstraintLayout
private lateinit var count : TextView
private lateinit var headerMenuBtn : TextView

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -72,7 +83,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
return fragmentView
}

@SuppressLint("RestrictedApi")
@SuppressLint("RestrictedApi", "SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Expand Down Expand Up @@ -100,8 +111,39 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
}
}

listHeader = view.findViewById(R.id.list_header)
count = view.findViewById(R.id.count)
headerMenuBtn = view.findViewById(R.id.dropdown_menu)

headerMenuBtn.setOnClickListener {
val popup = PopupMenu(activity, it)
popup.menuInflater.inflate(R.menu.cancelled_header_menu, popup.menu)
popup.setOnMenuItemClickListener { m ->
when(m.itemId){
R.id.delete_all -> {
UiUtil.showGenericDeleteAllDialog(requireContext()) {
downloadViewModel.deleteCancelled()
}
}
R.id.copy_urls -> {
lifecycleScope.launch {
val urls = withContext(Dispatchers.IO){
downloadViewModel.getURLsByStatus(listOf(DownloadRepository.Status.Cancelled))
}
UiUtil.copyToClipboard(urls.joinToString("\n"), requireActivity())
}
}
}
true
}

popup.show()
}

downloadViewModel.getTotalSize(listOf(DownloadRepository.Status.Cancelled)).observe(viewLifecycleOwner){
totalSize = it
listHeader.isVisible = it > 0
count.text = "$it ${getString(R.string.items)}"
noResults.visibility = if (it == 0) View.VISIBLE else View.GONE
}
}
Expand Down Expand Up @@ -331,7 +373,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
downloadViewModel.getItemByID(itemID)
}
downloadViewModel.deleteDownload(deletedItem.id)
Snackbar.make(cancelledRecyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title.ifEmpty { deletedItem.url }, Snackbar.LENGTH_LONG)
Snackbar.make(cancelledRecyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title.ifEmpty { deletedItem.url }, Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.undo)) {
downloadViewModel.insert(deletedItem)
}.show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,54 +208,15 @@ class DownloadQueueMainFragment : Fragment(){
try{
when(m.itemId){
R.id.clear_all -> {
showDeleteDialog {
UiUtil.showGenericDeleteAllDialog(requireContext()) {
downloadViewModel.deleteAll()
}
}
R.id.clear_queue -> {
showDeleteDialog {
UiUtil.showGenericDeleteAllDialog(requireContext()) {
downloadViewModel.cancelAllDownloads()
}
}
R.id.clear_cancelled -> {
showDeleteDialog {
downloadViewModel.deleteCancelled()
}
}
R.id.clear_scheduled -> {
showDeleteDialog {
downloadViewModel.deleteScheduled()
}
}
R.id.clear_errored -> {
showDeleteDialog {
downloadViewModel.deleteErrored()
}
}
R.id.clear_saved -> {
showDeleteDialog {
downloadViewModel.deleteSaved()
}
}
R.id.copy_urls -> {
lifecycleScope.launch {
val tabStatus = mapOf(
0 to listOf(DownloadRepository.Status.Active),
1 to listOf(DownloadRepository.Status.Queued),
2 to listOf(DownloadRepository.Status.Scheduled),
3 to listOf(DownloadRepository.Status.Cancelled),
4 to listOf(DownloadRepository.Status.Error),
5 to listOf(DownloadRepository.Status.Saved),
)
tabStatus[tabLayout.selectedTabPosition]?.apply {
val urls = withContext(Dispatchers.IO){
downloadViewModel.getURLsByStatus(this@apply)
}
UiUtil.copyToClipboard(urls.joinToString("\n"), requireActivity())
}
}

}
}
}catch (e: Exception){
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
Expand All @@ -265,16 +226,6 @@ class DownloadQueueMainFragment : Fragment(){
}
}

private fun showDeleteDialog (deleteClicked: (deleteClicked: Boolean) -> Unit){
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 ->
deleteClicked(true)
}
deleteDialog.show()
}

fun scrollToActive(){
tabLayout.getTabAt(0)!!.select()
viewPager2.setCurrentItem(0, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import android.widget.PopupMenu
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
Expand Down Expand Up @@ -60,6 +64,11 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
private lateinit var adapter : GenericDownloadAdapter
private var actionMode : ActionMode? = null
private var totalSize: Int = 0

private lateinit var listHeader : ConstraintLayout
private lateinit var count : TextView
private lateinit var headerMenuBtn : TextView

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -72,7 +81,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
return fragmentView
}

@SuppressLint("RestrictedApi")
@SuppressLint("RestrictedApi", "SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Expand Down Expand Up @@ -100,8 +109,39 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
}
}

listHeader = view.findViewById(R.id.list_header)
count = view.findViewById(R.id.count)
headerMenuBtn = view.findViewById(R.id.dropdown_menu)

headerMenuBtn.setOnClickListener {
val popup = PopupMenu(activity, it)
popup.menuInflater.inflate(R.menu.errored_header_menu, popup.menu)
popup.setOnMenuItemClickListener { m ->
when(m.itemId){
R.id.delete_all -> {
UiUtil.showGenericDeleteAllDialog(requireContext()) {
downloadViewModel.deleteErrored()
}
}
R.id.copy_urls -> {
lifecycleScope.launch {
val urls = withContext(Dispatchers.IO){
downloadViewModel.getURLsByStatus(listOf(DownloadRepository.Status.Error))
}
UiUtil.copyToClipboard(urls.joinToString("\n"), requireActivity())
}
}
}
true
}

popup.show()
}

downloadViewModel.getTotalSize(listOf(DownloadRepository.Status.Error)).observe(viewLifecycleOwner){
totalSize = it
listHeader.isVisible = it > 0
count.text = "$it ${getString(R.string.items)}"
noResults.visibility = if (it == 0) View.VISIBLE else View.GONE
}
}
Expand Down Expand Up @@ -334,7 +374,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
downloadViewModel.getItemByID(itemID)
}
downloadViewModel.deleteDownload(deletedItem.id)
Snackbar.make(erroredRecyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title.ifEmpty { deletedItem.url }, Snackbar.LENGTH_LONG)
Snackbar.make(erroredRecyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title.ifEmpty { deletedItem.url }, Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.undo)) {
downloadViewModel.insert(deletedItem)
}.show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
}

if (!deleteFile){
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.undo)) {
historyViewModel.insert(deletedItem)
}.show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class QueuedDownloadsFragment : Fragment(), QueuedDownloadAdapter.OnItemClickLis
downloadViewModel.updateDownload(item)
}

Snackbar.make(queuedRecyclerView, getString(R.string.cancelled) + ": " + item.title.ifEmpty { item.url }, Snackbar.LENGTH_LONG)
Snackbar.make(queuedRecyclerView, getString(R.string.cancelled) + ": " + item.title.ifEmpty { item.url }, Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.undo)) {
lifecycleScope.launch(Dispatchers.IO) {
downloadViewModel.deleteDownload(item.id)
Expand Down
Loading

0 comments on commit 80672a2

Please sign in to comment.