From fd151105ef2cf4e6bf9a270bb8513fc5aeeacf1a Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:34:30 +0100 Subject: [PATCH] tmp --- .../ytdl/database/dao/DownloadDao.kt | 4 +- .../database/viewmodel/DownloadViewModel.kt | 24 ++-- .../ui/downloads/ActiveDownloadsFragment.kt | 1 + .../ytdl/work/downloader/DownloadManager.kt | 122 +++++++++--------- app/src/main/res/layout/fragment_active.xml | 1 + .../fragment_download_queue_main_screen.xml | 3 +- 6 files changed, 78 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt b/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt index e4d6325d..9278bc19 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/dao/DownloadDao.kt @@ -26,7 +26,7 @@ interface DownloadDao { @Query("SELECT * FROM downloads WHERE status='Active'") fun getActiveDownloads() : Flow> - @Query("SELECT * FROM downloads WHERE status='Active' or status = 'Paused' ORDER BY id") + @Query("SELECT * FROM downloads WHERE status='Active' or status = 'Paused' ORDER BY id, CASE WHEN status='Active' THEN 0 ELSE 1 END") fun getActiveAndPausedDownloads() : Flow> @Query("SELECT * FROM downloads WHERE status='Paused'") @@ -115,7 +115,7 @@ interface DownloadDao { @Query(""" SELECT * FROM downloads - WHERE status in ('Active','Queued', 'Scheduled') AND downloadStartTime <= :currentTime + WHERE status in ('Active', 'Queued', 'Scheduled') AND downloadStartTime <= :currentTime ORDER BY CASE WHEN id in (:priorityItems) THEN 0 diff --git a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt index 864396af..e1f7090e 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/DownloadViewModel.kt @@ -1314,8 +1314,12 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel suspend fun pauseAllDownloads() { pausedAllDownloads.value = PausedAllDownloadsState.PROCESSING isPausingResuming = true + + withContext(Dispatchers.IO){ + downloadManager.cancelAll() + } + WorkManager.getInstance(application).cancelAllWorkByTag("download") - downloadManager.cancelAll() val activeDownloadsList = withContext(Dispatchers.IO){ getActiveDownloads() } @@ -1333,7 +1337,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel pausedAllDownloads.value = PausedAllDownloadsState.PROCESSING isPausingResuming = true WorkManager.getInstance(application).cancelAllWorkByTag("download") - downloadManager.cancelAll() + + withContext(Dispatchers.IO){ + downloadManager.cancelAll() + } + val paused = withContext(Dispatchers.IO) { dao.getPausedDownloadsList() } @@ -1359,15 +1367,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel } private suspend fun cancelAllDownloadsImpl() { - WorkManager.getInstance(application).cancelAllWorkByTag("download") - val activeAndQueued = withContext(Dispatchers.IO){ - repository.getActiveAndQueuedDownloadIDs() - } - activeAndQueued.forEach { id -> - YoutubeDL.getInstance().destroyProcessById(id.toString()) - notificationUtil.cancelDownloadNotification(id.toInt()) - } cancelActiveQueued() + withContext(Dispatchers.IO) { + downloadManager.cancelAll() + } + WorkManager.getInstance(application).cancelAllWorkByTag("download") } fun resumeDownload(itemID: Long) = viewModelScope.launch { diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/downloads/ActiveDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdl/ui/downloads/ActiveDownloadsFragment.kt index 74021e2b..5878bb33 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/downloads/ActiveDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/downloads/ActiveDownloadsFragment.kt @@ -201,6 +201,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis override fun onResumeClick(itemID: Long) { downloadViewModel.resumeDownload(itemID) + //activeRecyclerView.smoothScrollToPosition(0) } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdl/work/downloader/DownloadManager.kt b/app/src/main/java/com/deniscerri/ytdl/work/downloader/DownloadManager.kt index ae016888..6f2798c7 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/downloader/DownloadManager.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/downloader/DownloadManager.kt @@ -55,9 +55,9 @@ import java.util.Locale class DownloadManager private constructor() { private var notificationUtil: NotificationUtil = NotificationUtil(App.instance) private var sharedPreferences : SharedPreferences = PreferenceManager.getDefaultSharedPreferences(App.instance) + private var dbManager: DBManager = DBManager.getInstance(App.instance) + private var dao : DownloadDao = dbManager.downloadDao - private lateinit var dbManager: DBManager - private lateinit var dao : DownloadDao private lateinit var historyDao: HistoryDao private lateinit var commandTemplateDao: CommandTemplateDao private lateinit var logRepo: LogRepository @@ -75,37 +75,18 @@ class DownloadManager private constructor() { val isRunning get() = observeJob?.isActive == true - private fun getActiveDownloadsStore() : Set { - return sharedPreferences.getStringSet("ytdlp_active_downloads", setOf())!! - } - - private fun addIDToActiveDownloadsStore(id: Long) { - val new = mutableSetOf() - new.addAll(getActiveDownloadsStore()) - new.add(id.toString()) - - sharedPreferences.edit().putStringSet("ytdlp_active_downloads", new).apply() - } - - private fun removeIDFromActiveDownloadsStore(id: Long) { - val new = mutableSetOf() - new.addAll(getActiveDownloadsStore()) - new.remove(id.toString()) - - sharedPreferences.edit().putStringSet("ytdlp_active_downloads", new).apply() - } - fun cancelDownload(id: Long) { YoutubeDL.getInstance().destroyProcessById(id.toString()) notificationUtil.cancelDownloadNotification(id.toInt()) - removeIDFromActiveDownloadsStore(id) } fun cancelAll() { - getActiveDownloadsStore().map { it.toLong() }.forEach { - cancelDownload(it) - } observeJob?.cancel() + observeJob = null + val activeDownloads = dao.getActiveDownloadsList() + activeDownloads.forEach { + cancelDownload(it.id) + } } //only call from download worker @@ -163,53 +144,68 @@ class DownloadManager private constructor() { } observeJob = CoroutineScope(SupervisorJob() + Dispatchers.IO).launch { - queueState.distinctUntilChanged().collectLatest { queue -> - val runningCount = queue.asSequence() - .filter { it.status == DownloadRepository.Status.Active.toString() } - .count() + supervisorScope { + queueState.distinctUntilChanged().collectLatest { queue -> + val activeDownloads = queue + .asSequence() + .filter { it.status == DownloadRepository.Status.Active.toString() } + .map { it.id } - val queueItems = queue.asSequence() - .filter { it.status != DownloadRepository.Status.Active.toString() } + val activeDownloadsCount = activeDownloads.count() - val queueCount = queueItems.count() - if (queueCount == 0 && runningCount == 0) { - observeJob?.cancel() - return@collectLatest - } + val queueItems = queue + .asSequence() + .filter { it.status != DownloadRepository.Status.Active.toString() } - val useScheduler = sharedPreferences.getBoolean("use_scheduler", false) - if (useScheduler){ - if (queueItems.none{ it.downloadStartTime > 0L } && runningCount == 0 && !alarmScheduler.isDuringTheScheduledTime()) { + val queueCount = queueItems.count() + if (queueCount == 0 && activeDownloadsCount == 0) { observeJob?.cancel() return@collectLatest } - } - if (priorityItemIDs.isEmpty() && !continueAfterPriorityIds) { - observeJob?.cancel() - return@collectLatest - } + if (!isRunning) { + observeJob?.cancel() + return@collectLatest + } - val concurrentDownloads = sharedPreferences.getInt("concurrent_downloads", 1) - runningCount - if (concurrentDownloads > 0) { - //free spots are open - // Use supervisorScope to cancel child jobs when the downloader job is cancelled - supervisorScope { - val queuedDownloads = queueItems - .toList() - .take(concurrentDownloads) - - priorityItemIDs.removeAll(queuedDownloads.map { it.id }) - val downloadsToStart = queuedDownloads.filter { it.id.toString() !in getActiveDownloadsStore() } - downloadsToStart.forEach { downloadItem -> - val notification = notificationUtil.createDownloadServiceNotification(openDownloadQueue, downloadItem.title.ifEmpty { downloadItem.url }) - notificationUtil.notify(downloadItem.id.toInt(), notification) - launchDownloadJob(context, downloadItem) - addIDToActiveDownloadsStore(downloadItem.id) + val useScheduler = sharedPreferences.getBoolean("use_scheduler", false) + if (useScheduler){ + if (queueItems.none{ it.downloadStartTime > 0L } && activeDownloadsCount == 0 && !alarmScheduler.isDuringTheScheduledTime()) { + observeJob?.cancel() + return@collectLatest } } - } + val concurrentDownloads = sharedPreferences.getInt("concurrent_downloads", 1) - activeDownloadsCount + if (concurrentDownloads > 0) { + + supervisorScope { + //free spots are open + val queuedDownloads = if (priorityItemIDs.isNotEmpty() && !continueAfterPriorityIds) { + queueItems + .filter { priorityItemIDs.contains(it.id) } + .toList() + }else{ + queueItems.toList() + }.take(concurrentDownloads) + + + priorityItemIDs.removeAll(queuedDownloads.map { it.id }) + val downloadsToStart = queuedDownloads.filter { it.id !in activeDownloads } + downloadsToStart.forEach { downloadItem -> + val notification = notificationUtil.createDownloadServiceNotification(openDownloadQueue, downloadItem.title.ifEmpty { downloadItem.url }) + notificationUtil.notify(downloadItem.id.toInt(), notification) + launchDownloadJob(context, downloadItem) + } + } + } + + if (priorityItemIDs.isEmpty() && !continueAfterPriorityIds) { + observeJob?.cancel() + return@collectLatest + } + + } } } } @@ -288,7 +284,6 @@ class DownloadManager private constructor() { resultRepo.updateDownloadItem(downloadItem)?.apply { dao.updateWithoutUpsert(this) } - removeIDFromActiveDownloadsStore(downloadItem.id) //val wasQuickDownloaded = resultDao.getCountInt() == 0 runBlocking { var finalPaths = mutableListOf() @@ -414,7 +409,6 @@ class DownloadManager private constructor() { }.onFailure { FileUtil.deleteConfigFiles(request) - removeIDFromActiveDownloadsStore(downloadItem.id) withContext(Dispatchers.Main){ notificationUtil.cancelDownloadNotification(downloadItem.id.toInt()) } diff --git a/app/src/main/res/layout/fragment_active.xml b/app/src/main/res/layout/fragment_active.xml index 1c47c2ba..9c30abd1 100644 --- a/app/src/main/res/layout/fragment_active.xml +++ b/app/src/main/res/layout/fragment_active.xml @@ -10,6 +10,7 @@ android:layout_height="wrap_content" android:scrollbars="none" android:clipToPadding="false" + android:paddingBottom="100dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>