tmp
This commit is contained in:
parent
e1db3fa5e5
commit
fd151105ef
6 changed files with 78 additions and 77 deletions
|
|
@ -26,7 +26,7 @@ interface DownloadDao {
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active'")
|
||||||
fun getActiveDownloads() : Flow<List<DownloadItem>>
|
fun getActiveDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@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<List<DownloadItem>>
|
fun getActiveAndPausedDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Paused'")
|
@Query("SELECT * FROM downloads WHERE status='Paused'")
|
||||||
|
|
@ -115,7 +115,7 @@ interface DownloadDao {
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
SELECT * FROM downloads
|
SELECT * FROM downloads
|
||||||
WHERE status in ('Active','Queued', 'Scheduled') AND downloadStartTime <= :currentTime
|
WHERE status in ('Active', 'Queued', 'Scheduled') AND downloadStartTime <= :currentTime
|
||||||
ORDER BY
|
ORDER BY
|
||||||
CASE
|
CASE
|
||||||
WHEN id in (:priorityItems) THEN 0
|
WHEN id in (:priorityItems) THEN 0
|
||||||
|
|
|
||||||
|
|
@ -1314,8 +1314,12 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
suspend fun pauseAllDownloads() {
|
suspend fun pauseAllDownloads() {
|
||||||
pausedAllDownloads.value = PausedAllDownloadsState.PROCESSING
|
pausedAllDownloads.value = PausedAllDownloadsState.PROCESSING
|
||||||
isPausingResuming = true
|
isPausingResuming = true
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO){
|
||||||
|
downloadManager.cancelAll()
|
||||||
|
}
|
||||||
|
|
||||||
WorkManager.getInstance(application).cancelAllWorkByTag("download")
|
WorkManager.getInstance(application).cancelAllWorkByTag("download")
|
||||||
downloadManager.cancelAll()
|
|
||||||
val activeDownloadsList = withContext(Dispatchers.IO){
|
val activeDownloadsList = withContext(Dispatchers.IO){
|
||||||
getActiveDownloads()
|
getActiveDownloads()
|
||||||
}
|
}
|
||||||
|
|
@ -1333,7 +1337,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
pausedAllDownloads.value = PausedAllDownloadsState.PROCESSING
|
pausedAllDownloads.value = PausedAllDownloadsState.PROCESSING
|
||||||
isPausingResuming = true
|
isPausingResuming = true
|
||||||
WorkManager.getInstance(application).cancelAllWorkByTag("download")
|
WorkManager.getInstance(application).cancelAllWorkByTag("download")
|
||||||
downloadManager.cancelAll()
|
|
||||||
|
withContext(Dispatchers.IO){
|
||||||
|
downloadManager.cancelAll()
|
||||||
|
}
|
||||||
|
|
||||||
val paused = withContext(Dispatchers.IO) {
|
val paused = withContext(Dispatchers.IO) {
|
||||||
dao.getPausedDownloadsList()
|
dao.getPausedDownloadsList()
|
||||||
}
|
}
|
||||||
|
|
@ -1359,15 +1367,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun cancelAllDownloadsImpl() {
|
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()
|
cancelActiveQueued()
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
downloadManager.cancelAll()
|
||||||
|
}
|
||||||
|
WorkManager.getInstance(application).cancelAllWorkByTag("download")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resumeDownload(itemID: Long) = viewModelScope.launch {
|
fun resumeDownload(itemID: Long) = viewModelScope.launch {
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
|
|
||||||
override fun onResumeClick(itemID: Long) {
|
override fun onResumeClick(itemID: Long) {
|
||||||
downloadViewModel.resumeDownload(itemID)
|
downloadViewModel.resumeDownload(itemID)
|
||||||
|
//activeRecyclerView.smoothScrollToPosition(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -55,9 +55,9 @@ import java.util.Locale
|
||||||
class DownloadManager private constructor() {
|
class DownloadManager private constructor() {
|
||||||
private var notificationUtil: NotificationUtil = NotificationUtil(App.instance)
|
private var notificationUtil: NotificationUtil = NotificationUtil(App.instance)
|
||||||
private var sharedPreferences : SharedPreferences = PreferenceManager.getDefaultSharedPreferences(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 historyDao: HistoryDao
|
||||||
private lateinit var commandTemplateDao: CommandTemplateDao
|
private lateinit var commandTemplateDao: CommandTemplateDao
|
||||||
private lateinit var logRepo: LogRepository
|
private lateinit var logRepo: LogRepository
|
||||||
|
|
@ -75,37 +75,18 @@ class DownloadManager private constructor() {
|
||||||
|
|
||||||
val isRunning get() = observeJob?.isActive == true
|
val isRunning get() = observeJob?.isActive == true
|
||||||
|
|
||||||
private fun getActiveDownloadsStore() : Set<String> {
|
|
||||||
return sharedPreferences.getStringSet("ytdlp_active_downloads", setOf())!!
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addIDToActiveDownloadsStore(id: Long) {
|
|
||||||
val new = mutableSetOf<String>()
|
|
||||||
new.addAll(getActiveDownloadsStore())
|
|
||||||
new.add(id.toString())
|
|
||||||
|
|
||||||
sharedPreferences.edit().putStringSet("ytdlp_active_downloads", new).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeIDFromActiveDownloadsStore(id: Long) {
|
|
||||||
val new = mutableSetOf<String>()
|
|
||||||
new.addAll(getActiveDownloadsStore())
|
|
||||||
new.remove(id.toString())
|
|
||||||
|
|
||||||
sharedPreferences.edit().putStringSet("ytdlp_active_downloads", new).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancelDownload(id: Long) {
|
fun cancelDownload(id: Long) {
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
notificationUtil.cancelDownloadNotification(id.toInt())
|
notificationUtil.cancelDownloadNotification(id.toInt())
|
||||||
removeIDFromActiveDownloadsStore(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelAll() {
|
fun cancelAll() {
|
||||||
getActiveDownloadsStore().map { it.toLong() }.forEach {
|
|
||||||
cancelDownload(it)
|
|
||||||
}
|
|
||||||
observeJob?.cancel()
|
observeJob?.cancel()
|
||||||
|
observeJob = null
|
||||||
|
val activeDownloads = dao.getActiveDownloadsList()
|
||||||
|
activeDownloads.forEach {
|
||||||
|
cancelDownload(it.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//only call from download worker
|
//only call from download worker
|
||||||
|
|
@ -163,53 +144,68 @@ class DownloadManager private constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
observeJob = CoroutineScope(SupervisorJob() + Dispatchers.IO).launch {
|
observeJob = CoroutineScope(SupervisorJob() + Dispatchers.IO).launch {
|
||||||
queueState.distinctUntilChanged().collectLatest { queue ->
|
supervisorScope {
|
||||||
val runningCount = queue.asSequence()
|
queueState.distinctUntilChanged().collectLatest { queue ->
|
||||||
.filter { it.status == DownloadRepository.Status.Active.toString() }
|
val activeDownloads = queue
|
||||||
.count()
|
.asSequence()
|
||||||
|
.filter { it.status == DownloadRepository.Status.Active.toString() }
|
||||||
|
.map { it.id }
|
||||||
|
|
||||||
val queueItems = queue.asSequence()
|
val activeDownloadsCount = activeDownloads.count()
|
||||||
.filter { it.status != DownloadRepository.Status.Active.toString() }
|
|
||||||
|
|
||||||
val queueCount = queueItems.count()
|
val queueItems = queue
|
||||||
if (queueCount == 0 && runningCount == 0) {
|
.asSequence()
|
||||||
observeJob?.cancel()
|
.filter { it.status != DownloadRepository.Status.Active.toString() }
|
||||||
return@collectLatest
|
|
||||||
}
|
|
||||||
|
|
||||||
val useScheduler = sharedPreferences.getBoolean("use_scheduler", false)
|
val queueCount = queueItems.count()
|
||||||
if (useScheduler){
|
if (queueCount == 0 && activeDownloadsCount == 0) {
|
||||||
if (queueItems.none{ it.downloadStartTime > 0L } && runningCount == 0 && !alarmScheduler.isDuringTheScheduledTime()) {
|
|
||||||
observeJob?.cancel()
|
observeJob?.cancel()
|
||||||
return@collectLatest
|
return@collectLatest
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (priorityItemIDs.isEmpty() && !continueAfterPriorityIds) {
|
if (!isRunning) {
|
||||||
observeJob?.cancel()
|
observeJob?.cancel()
|
||||||
return@collectLatest
|
return@collectLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
val concurrentDownloads = sharedPreferences.getInt("concurrent_downloads", 1) - runningCount
|
val useScheduler = sharedPreferences.getBoolean("use_scheduler", false)
|
||||||
if (concurrentDownloads > 0) {
|
if (useScheduler){
|
||||||
//free spots are open
|
if (queueItems.none{ it.downloadStartTime > 0L } && activeDownloadsCount == 0 && !alarmScheduler.isDuringTheScheduledTime()) {
|
||||||
// Use supervisorScope to cancel child jobs when the downloader job is cancelled
|
observeJob?.cancel()
|
||||||
supervisorScope {
|
return@collectLatest
|
||||||
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 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 {
|
resultRepo.updateDownloadItem(downloadItem)?.apply {
|
||||||
dao.updateWithoutUpsert(this)
|
dao.updateWithoutUpsert(this)
|
||||||
}
|
}
|
||||||
removeIDFromActiveDownloadsStore(downloadItem.id)
|
|
||||||
//val wasQuickDownloaded = resultDao.getCountInt() == 0
|
//val wasQuickDownloaded = resultDao.getCountInt() == 0
|
||||||
runBlocking {
|
runBlocking {
|
||||||
var finalPaths = mutableListOf<String>()
|
var finalPaths = mutableListOf<String>()
|
||||||
|
|
@ -414,7 +409,6 @@ class DownloadManager private constructor() {
|
||||||
|
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
FileUtil.deleteConfigFiles(request)
|
FileUtil.deleteConfigFiles(request)
|
||||||
removeIDFromActiveDownloadsStore(downloadItem.id)
|
|
||||||
withContext(Dispatchers.Main){
|
withContext(Dispatchers.Main){
|
||||||
notificationUtil.cancelDownloadNotification(downloadItem.id.toInt())
|
notificationUtil.cancelDownloadNotification(downloadItem.id.toInt())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="100dp"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@
|
||||||
android:id="@+id/download_tablayout"
|
android:id="@+id/download_tablayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="10dp"
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
android:backgroundTint="@android:color/transparent"
|
android:backgroundTint="@android:color/transparent"
|
||||||
app:tabGravity="start"
|
app:tabGravity="start"
|
||||||
app:tabMinWidth="0dp"
|
app:tabMinWidth="0dp"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue