added check for present downloads & fixed downloads not getting cancelled
This commit is contained in:
parent
562dd82845
commit
a6a4754bb2
10 changed files with 82 additions and 27 deletions
|
|
@ -19,6 +19,9 @@ interface DownloadDao {
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active'")
|
||||||
fun getActiveDownloadsList() : List<DownloadItem>
|
fun getActiveDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM downloads WHERE status='Active' or status='Queued'")
|
||||||
|
fun getActiveAndQueuedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
|
||||||
fun getQueuedDownloads() : LiveData<List<DownloadItem>>
|
fun getQueuedDownloads() : LiveData<List<DownloadItem>>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,10 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
return downloadDao.getActiveDownloadsList()
|
return downloadDao.getActiveDownloadsList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getActiveAndQueuedDownloads() : List<DownloadItem> {
|
||||||
|
return downloadDao.getActiveAndQueuedDownloadsList()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun deleteCancelled(){
|
suspend fun deleteCancelled(){
|
||||||
downloadDao.deleteCancelled()
|
downloadDao.deleteCancelled()
|
||||||
}
|
}
|
||||||
|
|
@ -61,9 +65,6 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
downloadDao.cancelQueued()
|
downloadDao.cancelQueued()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkIfPresentForProcessing(item: ResultItem): DownloadItem{
|
|
||||||
return downloadDao.checkIfErrorOrCancelled(item.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkIfReDownloadingErroredOrCancelled(item: DownloadItem) : Long {
|
fun checkIfReDownloadingErroredOrCancelled(item: DownloadItem) : Long {
|
||||||
val converters = Converters()
|
val converters = Converters()
|
||||||
|
|
|
||||||
|
|
@ -354,14 +354,33 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
return repository.getActiveDownloads()
|
return repository.getActiveDownloads()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getActiveAndQueuedDownloads() : List<DownloadItem>{
|
||||||
|
return repository.getActiveAndQueuedDownloads()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun queueDownloads(items: List<DownloadItem>) {
|
suspend fun queueDownloads(items: List<DownloadItem>) {
|
||||||
val context = getApplication<App>().applicationContext
|
val context = getApplication<App>().applicationContext
|
||||||
|
val activeAndQueuedDownloads = withContext(Dispatchers.IO){
|
||||||
|
repository.getActiveAndQueuedDownloads()
|
||||||
|
}
|
||||||
val allowMeteredNetworks = sharedPreferences.getBoolean("metered_networks", true)
|
val allowMeteredNetworks = sharedPreferences.getBoolean("metered_networks", true)
|
||||||
items.forEach { it.status = DownloadRepository.Status.Queued.toString() }
|
val queuedItems = mutableListOf<DownloadItem>()
|
||||||
val ids = repository.insertAll(items)
|
items.forEach {
|
||||||
for (i in ids.indices){
|
it.status = DownloadRepository.Status.Queued.toString()
|
||||||
val it = items[i]
|
if (activeAndQueuedDownloads.firstOrNull{d ->
|
||||||
it.id = ids[i]
|
d.id = 0
|
||||||
|
d.status = DownloadRepository.Status.Queued.toString()
|
||||||
|
d.toString() == it.toString()
|
||||||
|
} != null) {
|
||||||
|
Toast.makeText(context, context.getString(R.string.download_already_exists), Toast.LENGTH_LONG).show()
|
||||||
|
}else{
|
||||||
|
it.id = withContext(Dispatchers.IO){
|
||||||
|
repository.insert(it)
|
||||||
|
}
|
||||||
|
queuedItems.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queuedItems.forEach {
|
||||||
val currentTime = System.currentTimeMillis()
|
val currentTime = System.currentTimeMillis()
|
||||||
var delay = if (it.downloadStartTime != 0L){
|
var delay = if (it.downloadStartTime != 0L){
|
||||||
it.downloadStartTime - currentTime
|
it.downloadStartTime - currentTime
|
||||||
|
|
@ -383,8 +402,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
ExistingWorkPolicy.KEEP,
|
ExistingWorkPolicy.KEEP,
|
||||||
workRequest
|
workRequest
|
||||||
).enqueue()
|
).enqueue()
|
||||||
}
|
|
||||||
items.forEach {
|
|
||||||
it.id = withContext(Dispatchers.IO){
|
it.id = withContext(Dispatchers.IO){
|
||||||
repository.checkIfReDownloadingErroredOrCancelled(it)
|
repository.checkIfReDownloadingErroredOrCancelled(it)
|
||||||
}
|
}
|
||||||
|
|
@ -392,6 +410,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
repository.delete(it)
|
repository.delete(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isCurrentNetworkMetered = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).isActiveNetworkMetered
|
val isCurrentNetworkMetered = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).isActiveNetworkMetered
|
||||||
if (!allowMeteredNetworks && isCurrentNetworkMetered){
|
if (!allowMeteredNetworks && isCurrentNetworkMetered){
|
||||||
Toast.makeText(context, context.getString(R.string.metered_network_download_start_info), Toast.LENGTH_LONG).show()
|
Toast.makeText(context, context.getString(R.string.metered_network_download_start_info), Toast.LENGTH_LONG).show()
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,12 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
viewPager2.setPageTransformer(BackgroundToForegroundPageTransformer())
|
viewPager2.setPageTransformer(BackgroundToForegroundPageTransformer())
|
||||||
|
|
||||||
val scheduleBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_schedule_button)
|
val scheduleBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_schedule_button)
|
||||||
|
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
||||||
|
|
||||||
|
|
||||||
scheduleBtn.setOnClickListener{
|
scheduleBtn.setOnClickListener{
|
||||||
|
scheduleBtn.isEnabled = false
|
||||||
|
download.isEnabled = false
|
||||||
uiUtil.showDatePicker(fragmentManager) {
|
uiUtil.showDatePicker(fragmentManager) {
|
||||||
val item: DownloadItem = getDownloadItem();
|
val item: DownloadItem = getDownloadItem();
|
||||||
item.downloadStartTime = it.timeInMillis
|
item.downloadStartTime = it.timeInMillis
|
||||||
|
|
@ -166,8 +171,9 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
|
||||||
download!!.setOnClickListener {
|
download!!.setOnClickListener {
|
||||||
|
scheduleBtn.isEnabled = false
|
||||||
|
download.isEnabled = false
|
||||||
val item: DownloadItem = getDownloadItem();
|
val item: DownloadItem = getDownloadItem();
|
||||||
runBlocking {
|
runBlocking {
|
||||||
downloadViewModel.queueDownloads(listOf(item))
|
downloadViewModel.queueDownloads(listOf(item))
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,12 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
|
|
||||||
val scheduleBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_schedule_button)
|
val scheduleBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_schedule_button)
|
||||||
|
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
||||||
|
|
||||||
|
|
||||||
scheduleBtn.setOnClickListener{
|
scheduleBtn.setOnClickListener{
|
||||||
|
scheduleBtn.isEnabled = false
|
||||||
|
download.isEnabled = false
|
||||||
uiUtil.showDatePicker(parentFragmentManager) {
|
uiUtil.showDatePicker(parentFragmentManager) {
|
||||||
items.forEach { item ->
|
items.forEach { item ->
|
||||||
item.downloadStartTime = it.timeInMillis
|
item.downloadStartTime = it.timeInMillis
|
||||||
|
|
@ -117,8 +122,9 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
|
||||||
download!!.setOnClickListener {
|
download!!.setOnClickListener {
|
||||||
|
scheduleBtn.isEnabled = false
|
||||||
|
download.isEnabled = false
|
||||||
runBlocking {
|
runBlocking {
|
||||||
downloadViewModel.queueDownloads(items)
|
downloadViewModel.queueDownloads(items)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import androidx.viewpager2.widget.ViewPager2
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.await
|
import androidx.work.await
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.ui.BaseActivity
|
import com.deniscerri.ytdlnis.ui.BaseActivity
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
|
@ -126,19 +127,19 @@ class DownloadQueueActivity : BaseActivity(){
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelAllDownloads() {
|
private fun cancelAllDownloads() {
|
||||||
|
workManager.cancelAllWorkByTag("download")
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val notificationUtil = NotificationUtil(this@DownloadQueueActivity)
|
val notificationUtil = NotificationUtil(this@DownloadQueueActivity)
|
||||||
val activeDownloads = withContext(Dispatchers.IO){
|
val activeAndQueued = withContext(Dispatchers.IO){
|
||||||
downloadViewModel.getActiveDownloads()
|
downloadViewModel.getActiveAndQueuedDownloads()
|
||||||
}
|
}
|
||||||
val workManager = WorkManager.getInstance(this@DownloadQueueActivity)
|
activeAndQueued.forEach {
|
||||||
activeDownloads.forEach {
|
it.status = DownloadRepository.Status.Cancelled.toString()
|
||||||
|
downloadViewModel.updateDownload(it)
|
||||||
val id = it.id.toInt()
|
val id = it.id.toInt()
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
workManager.cancelUniqueWork(id.toString())
|
|
||||||
notificationUtil.cancelDownloadNotification(id)
|
notificationUtil.cancelDownloadNotification(id)
|
||||||
}
|
}
|
||||||
workManager.cancelAllWorkByTag("download")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
}
|
}
|
||||||
|
|
||||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||||
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
|
||||||
override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder
|
override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return false
|
return false
|
||||||
|
|
@ -238,6 +238,11 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
val position = viewHolder.bindingAdapterPosition
|
val position = viewHolder.bindingAdapterPosition
|
||||||
when (direction) {
|
when (direction) {
|
||||||
|
ItemTouchHelper.RIGHT -> {
|
||||||
|
runBlocking{
|
||||||
|
downloadViewModel.queueDownloads(listOf(items[position]))
|
||||||
|
}
|
||||||
|
}
|
||||||
ItemTouchHelper.LEFT -> {
|
ItemTouchHelper.LEFT -> {
|
||||||
val deletedItem = items[position]
|
val deletedItem = items[position]
|
||||||
downloadViewModel.deleteDownload(deletedItem)
|
downloadViewModel.deleteDownload(deletedItem)
|
||||||
|
|
@ -277,6 +282,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
R.attr.colorOnSurfaceInverse, Color.TRANSPARENT
|
R.attr.colorOnSurfaceInverse, Color.TRANSPARENT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.addSwipeRightActionIcon(R.drawable.ic_refresh)
|
||||||
.create()
|
.create()
|
||||||
.decorate()
|
.decorate()
|
||||||
super.onChildDraw(
|
super.onChildDraw(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.deniscerri.ytdlnis.ui.downloads
|
package com.deniscerri.ytdlnis.ui.downloads
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.DialogInterface
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
|
@ -35,6 +36,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||||
|
|
@ -111,7 +113,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
downloadViewModel.deleteDownload(downloadViewModel.getItemByID(itemID))
|
downloadViewModel.deleteDownload(downloadViewModel.getItemByID(itemID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cancelDownload(itemID)
|
removeItem(itemID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCardClick(itemID: Long) {
|
override fun onCardClick(itemID: Long) {
|
||||||
|
|
@ -206,7 +208,8 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
val remove = bottomSheet.findViewById<Button>(R.id.bottomsheet_remove_button)
|
val remove = bottomSheet.findViewById<Button>(R.id.bottomsheet_remove_button)
|
||||||
remove!!.tag = itemID
|
remove!!.tag = itemID
|
||||||
remove.setOnClickListener{
|
remove.setOnClickListener{
|
||||||
cancelDownload(itemID)
|
bottomSheet.hide()
|
||||||
|
removeItem(itemID)
|
||||||
}
|
}
|
||||||
val openFile = bottomSheet.findViewById<Button>(R.id.bottomsheet_open_file_button)
|
val openFile = bottomSheet.findViewById<Button>(R.id.bottomsheet_open_file_button)
|
||||||
openFile!!.visibility = View.GONE
|
openFile!!.visibility = View.GONE
|
||||||
|
|
@ -238,11 +241,19 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelDownload(itemID: Long){
|
private fun removeItem(itemID: Long){
|
||||||
val id = itemID.toInt()
|
val item = items.find { it.id == itemID }
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
val deleteDialog = MaterialAlertDialogBuilder(requireContext())
|
||||||
WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString())
|
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + item?.title + "\"!")
|
||||||
notificationUtil.cancelDownloadNotification(id)
|
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
|
val id = itemID.toInt()
|
||||||
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
|
WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString())
|
||||||
|
notificationUtil.cancelDownloadNotification(id)
|
||||||
|
downloadViewModel.deleteDownload(item!!)
|
||||||
|
}
|
||||||
|
deleteDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||||
|
|
@ -257,7 +268,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
when (direction) {
|
when (direction) {
|
||||||
ItemTouchHelper.LEFT -> {
|
ItemTouchHelper.LEFT -> {
|
||||||
val deletedItem = items[position]
|
val deletedItem = items[position]
|
||||||
cancelDownload(deletedItem.id)
|
removeItem(deletedItem.id)
|
||||||
Snackbar.make(queuedRecyclerView, getString(R.string.cancelled) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
|
Snackbar.make(queuedRecyclerView, getString(R.string.cancelled) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
|
||||||
.setAction(getString(R.string.undo)) {
|
.setAction(getString(R.string.undo)) {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ class DownloadWorker(
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
|
if (downloadItem.status != DownloadRepository.Status.Queued.toString()) return Result.failure()
|
||||||
|
|
||||||
Log.e(TAG, downloadItem.toString())
|
Log.e(TAG, downloadItem.toString())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -246,4 +246,5 @@
|
||||||
<string name="remove_audio">Remove Audio</string>
|
<string name="remove_audio">Remove Audio</string>
|
||||||
<string name="preferred_format_id">Preferred Format ID</string>
|
<string name="preferred_format_id">Preferred Format ID</string>
|
||||||
<string name="download_now">Download Now</string>
|
<string name="download_now">Download Now</string>
|
||||||
|
<string name="download_already_exists">Download already exists</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in a new issue