From 4699cb46e1327d155f464b69cb12812afbdda008 Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Sun, 5 Oct 2025 22:31:50 +0200 Subject: [PATCH] random bug fixes --- .../ytdl/database/dao/HistoryDao.kt | 4 + .../database/repository/HistoryRepository.kt | 5 + .../repository/ObserveSourcesRepository.kt | 1 + .../database/viewmodel/DownloadViewModel.kt | 12 ++- .../database/viewmodel/FormatViewModel.kt | 2 +- .../ObserveSourcesBottomSheetDialog.kt | 7 +- .../com/deniscerri/ytdl/util/Extensions.kt | 2 +- .../ytdl/work/CleanUpLeftoverDownloads.kt | 2 +- .../ytdl/work/MoveCacheFilesWorker.kt | 2 +- .../ytdl/work/ObserveSourceWorker.kt | 99 ++++++++++--------- .../ytdl/work/TerminalDownloadWorker.kt | 2 +- .../UpdateMultipleDownloadsFormatsWorker.kt | 2 +- .../layout/observe_sources_bottom_sheet.xml | 2 + 13 files changed, 85 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/com/deniscerri/ytdl/database/dao/HistoryDao.kt b/app/src/main/java/com/deniscerri/ytdl/database/dao/HistoryDao.kt index 84dd3914..bf92ef81 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/dao/HistoryDao.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/dao/HistoryDao.kt @@ -9,6 +9,7 @@ import androidx.room.Update import com.deniscerri.ytdl.database.models.DownloadItem import com.deniscerri.ytdl.database.models.HistoryItem import com.deniscerri.ytdl.database.repository.HistoryRepository +import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel import kotlinx.coroutines.flow.Flow @Dao @@ -83,6 +84,9 @@ interface HistoryDao { @Query("SELECT * FROM history WHERE url=:url") fun getAllHistoryByURL(url: String) : List + @Query("SELECT * FROM history WHERE url=:url and type=:type") + fun getAllHistoryByURLAndType(url: String, type: DownloadViewModel.Type) : List + @Query("SELECT * FROM history WHERE id in (:ids)") fun getAllHistoryByIDs(ids: List) : List diff --git a/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt b/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt index 077da7f6..432ffb5b 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/repository/HistoryRepository.kt @@ -9,6 +9,7 @@ import androidx.paging.filter import com.deniscerri.ytdl.database.DBManager.SORTING import com.deniscerri.ytdl.database.dao.HistoryDao import com.deniscerri.ytdl.database.models.HistoryItem +import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel import com.deniscerri.ytdl.util.FileUtil import kotlinx.coroutines.flow.Flow @@ -37,6 +38,10 @@ class HistoryRepository(private val historyDao: HistoryDao) { return historyDao.getAllHistoryByURL(url) } + fun getAllByURLAndType(url: String, type: DownloadViewModel.Type) : List { + return historyDao.getAllHistoryByURLAndType(url, type) + } + fun getAllByIDs(ids: List) : List { return historyDao.getAllHistoryByIDs(ids) } diff --git a/app/src/main/java/com/deniscerri/ytdl/database/repository/ObserveSourcesRepository.kt b/app/src/main/java/com/deniscerri/ytdl/database/repository/ObserveSourcesRepository.kt index 2adef0f1..31b014f5 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/repository/ObserveSourcesRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/repository/ObserveSourcesRepository.kt @@ -11,6 +11,7 @@ import androidx.work.WorkManager import com.deniscerri.ytdl.R import com.deniscerri.ytdl.database.dao.ObserveSourcesDao import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem +import com.deniscerri.ytdl.util.Extensions.calculateNextTimeForObserving import com.deniscerri.ytdl.work.ObserveSourceWorker import kotlinx.coroutines.flow.Flow import java.util.Calendar 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 60d3c845..10922774 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 @@ -1002,11 +1002,13 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel val currentCommand = ytdlpUtil.buildYoutubeDLRequest(it) val parsedCurrentCommand = ytdlpUtil.parseYTDLRequestString(currentCommand) val existingDownload = activeAndQueuedDownloads.firstOrNull{d -> - d.id = 0 - d.logID = null - d.customFileNameTemplate = it.customFileNameTemplate - d.status = DownloadRepository.Status.Queued.toString() - d.toString() == it.toString() + val normalized = d.copy( + id = 0, + logID = null, + customFileNameTemplate = it.customFileNameTemplate, + status = DownloadRepository.Status.Queued.toString() + ) + normalized.toString() == it.toString() } if (existingDownload != null){ diff --git a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/FormatViewModel.kt b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/FormatViewModel.kt index 042dc1e0..91b4c8f5 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/FormatViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/FormatViewModel.kt @@ -255,7 +255,7 @@ class FormatViewModel(private val application: Application) : AndroidViewModel(a _noFreeSpace.emit(null) if (size > 10L) { File(FileUtil.formatPath(path)).apply { - if (size > this.freeSpace) { + if (size > this.freeSpace && this.freeSpace >= 10L) { val warningTxt = application.getString(R.string.no_free_space_warning) + "\n" + "${application.getString(R.string.file_size)}:\t${FileUtil.convertFileSize(size)}" + "\n" + "${application.getString(R.string.freespace)}:\t${FileUtil.convertFileSize(this.freeSpace)}" diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/ObserveSourcesBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/ObserveSourcesBottomSheetDialog.kt index fda3b1fc..3e1928f6 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/ObserveSourcesBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/ObserveSourcesBottomSheetDialog.kt @@ -18,6 +18,7 @@ import android.widget.RadioButton import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources +import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.edit import androidx.core.view.children import androidx.core.view.isVisible @@ -53,6 +54,7 @@ import com.google.android.material.tabs.TabLayout import com.google.android.material.textfield.TextInputLayout import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import java.text.SimpleDateFormat import java.util.Calendar @@ -471,7 +473,8 @@ class ObserveSourcesBottomSheetDialog : BottomSheetDialogFragment() { retryMissingDownloads.isChecked = currentItem?.retryMissingDownloads ?: false getOnlyNewUploads.isChecked = currentItem?.getOnlyNewUploads ?: false syncWithSource.isChecked = currentItem?.syncWithSource ?: false - resetProcessedLinks.isVisible = currentItem != null + + view.findViewById(R.id.resetProcessedLinksConstraint).isVisible = currentItem != null if (currentItem != null) okButton.text = getString(R.string.update) okButton.setOnClickListener { @@ -489,7 +492,7 @@ class ObserveSourcesBottomSheetDialog : BottomSheetDialogFragment() { endsAfterCount = endsAfterNr.editText!!.text.toString().toInt() } - val category = ObserveSourcesRepository.EveryCategory.values()[categoryAdapter.getPosition(everyCat.text.toString())] + val category = ObserveSourcesRepository.EveryCategory.entries[categoryAdapter.getPosition(everyCat.text.toString())] val observeItem = ObserveSourcesItem( id = currentItem?.id ?: 0, diff --git a/app/src/main/java/com/deniscerri/ytdl/util/Extensions.kt b/app/src/main/java/com/deniscerri/ytdl/util/Extensions.kt index b4919db1..07e4f6ff 100644 --- a/app/src/main/java/com/deniscerri/ytdl/util/Extensions.kt +++ b/app/src/main/java/com/deniscerri/ytdl/util/Extensions.kt @@ -297,7 +297,7 @@ object Extensions { val badge = BadgeDrawable.create(context).apply { number = nr backgroundColor = context.getColor(R.color.white) - verticalOffset = 30 + verticalOffset = 25 horizontalOffset = if (nr < 10) dp(App.instance.resources, 16f) else if (nr < 100) dp(App.instance.resources, 19f) diff --git a/app/src/main/java/com/deniscerri/ytdl/work/CleanUpLeftoverDownloads.kt b/app/src/main/java/com/deniscerri/ytdl/work/CleanUpLeftoverDownloads.kt index 9ca46769..9d3962d5 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/CleanUpLeftoverDownloads.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/CleanUpLeftoverDownloads.kt @@ -25,7 +25,7 @@ class CleanUpLeftoverDownloads( val id = System.currentTimeMillis().toInt() val notification = notificationUtil.createDeletingLeftoverDownloadsNotification() - if (Build.VERSION.SDK_INT > 33) { + if (Build.VERSION.SDK_INT >= 33) { setForegroundAsync(ForegroundInfo(id, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)) }else{ setForegroundAsync(ForegroundInfo(id, notification)) diff --git a/app/src/main/java/com/deniscerri/ytdl/work/MoveCacheFilesWorker.kt b/app/src/main/java/com/deniscerri/ytdl/work/MoveCacheFilesWorker.kt index fd2400c6..6ebc7c76 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/MoveCacheFilesWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/MoveCacheFilesWorker.kt @@ -41,7 +41,7 @@ class MoveCacheFilesWorker( val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) val notification = notificationUtil.createMoveCacheFilesNotification(pendingIntent, NotificationUtil.DOWNLOAD_MISC_CHANNEL_ID) - if (Build.VERSION.SDK_INT > 33) { + if (Build.VERSION.SDK_INT >= 33) { setForegroundAsync(ForegroundInfo(id, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)) }else{ setForegroundAsync(ForegroundInfo(id, notification)) diff --git a/app/src/main/java/com/deniscerri/ytdl/work/ObserveSourceWorker.kt b/app/src/main/java/com/deniscerri/ytdl/work/ObserveSourceWorker.kt index ba412ea1..842d38c6 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/ObserveSourceWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/ObserveSourceWorker.kt @@ -17,6 +17,7 @@ import androidx.work.WorkerParameters import com.deniscerri.ytdl.App import com.deniscerri.ytdl.database.DBManager import com.deniscerri.ytdl.database.models.DownloadItem +import com.deniscerri.ytdl.database.models.ResultItem import com.deniscerri.ytdl.database.repository.DownloadRepository import com.deniscerri.ytdl.database.repository.HistoryRepository import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository @@ -36,9 +37,10 @@ class ObserveSourceWorker( workerParams: WorkerParameters ) : CoroutineWorker(context, workerParams) { override suspend fun doWork(): Result { - val notificationUtil = NotificationUtil(App.instance) val sourceID = inputData.getLong("id", 0) - if (sourceID == 0L) return Result.failure() + if (sourceID == 0L) return Result.success() + + val notificationUtil = NotificationUtil(App.instance) val dbManager = DBManager.getInstance(context) val workManager = WorkManager.getInstance(context) val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) @@ -46,17 +48,18 @@ class ObserveSourceWorker( val historyRepo = HistoryRepository(dbManager.historyDao) val downloadRepo = DownloadRepository(dbManager.downloadDao) val commandTemplateDao = dbManager.commandTemplateDao - val ytdlpUtil = YTDLPUtil(context, commandTemplateDao) val resultRepository = ResultRepository(dbManager.resultDao, commandTemplateDao, context) + val ytdlpUtil = YTDLPUtil(context, commandTemplateDao) + val item = repo.getByID(sourceID) if (item.status == ObserveSourcesRepository.SourceStatus.STOPPED){ - return Result.failure() + return Result.success() } val workerID = System.currentTimeMillis().toInt() val notification = notificationUtil.createObserveSourcesNotification(item.name) - if (Build.VERSION.SDK_INT > 33) { + if (Build.VERSION.SDK_INT >= 33) { setForegroundAsync(ForegroundInfo(workerID, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)) }else{ setForegroundAsync(ForegroundInfo(workerID, notification)) @@ -68,7 +71,8 @@ class ObserveSourceWorker( Log.e("observe", it.toString()) }.getOrElse { listOf() } - if (list.isNotEmpty() && item.syncWithSource && item.alreadyProcessedLinks.isNotEmpty()){ + //delete downloaded items not present in source if sync is enabled + if (item.syncWithSource && item.alreadyProcessedLinks.isNotEmpty()){ val processedLinks = item.alreadyProcessedLinks val incomingLinks = list.map { it.url } @@ -81,37 +85,42 @@ class ObserveSourceWorker( } } - - val res = list - .filter { result -> - //if first run and get new items only is preferred then dont get anything on first run - if (item.getOnlyNewUploads && item.runCount == 0){ - item.ignoredLinks.add(result.url) - false - }else{ - true - } + val toProcess = mutableListOf() + //filter what results need to be downloaded, ignored + for (result in list) { + if (item.ignoredLinks.contains(result.url)) { + continue } - .filter { result -> - val history = historyRepo.getAllByURL(result.url) - !item.ignoredLinks.contains(result.url) && + // if first run and get only new items, ignore + if (item.getOnlyNewUploads && item.runCount == 0) { + item.ignoredLinks.add(result.url) + continue + } - if (item.retryMissingDownloads){ - //all items that are not present in history - history.none { hi -> hi.downloadPath.any { path -> FileUtil.exists(path) } } - }else{ - //all items that are not already processed - if(item.alreadyProcessedLinks.isEmpty()){ - !history.map { it.url }.contains(result.url) - }else{ - !item.alreadyProcessedLinks.contains(result.url) - } + val history = historyRepo.getAllByURLAndType(result.url, item.downloadItemTemplate.type) + //if history is empty or all history items are deleted, add for retry + if (item.retryMissingDownloads && (history.isEmpty() || history.none { hi -> hi.downloadPath.any { path -> FileUtil.exists(path) } })) { + toProcess.add(result) + continue + } + + if (item.alreadyProcessedLinks.isEmpty()) { + if (history.isEmpty()) { + toProcess.add(result) + continue } } - val items = mutableListOf() - res.forEach { + if (item.alreadyProcessedLinks.contains(result.url)) { + continue + } + + toProcess.add(result) + } + + val downloadItems = mutableListOf() + toProcess.forEach { val string = Gson().toJson(item.downloadItemTemplate, DownloadItem::class.java) val downloadItem = Gson().fromJson(string, DownloadItem::class.java) downloadItem.title = it.title @@ -125,12 +134,11 @@ class ObserveSourceWorker( downloadItem.playlistURL = it.playlistURL downloadItem.playlistIndex = it.playlistIndex downloadItem.id = 0L - items.add(downloadItem) + downloadItems.add(downloadItem) } - if (items.isNotEmpty()){ - + if (downloadItems.isNotEmpty()){ //QUEUE DOWNLOADS //COPY OF QUEUE DOWNLOADS IN DOWNLOAD VIEW MODEL. NEEDS TO BE UPDATED IF THAT IS UPDATED val context = App.instance @@ -146,16 +154,18 @@ class ObserveSourceWorker( // items.forEachIndexed { index, it -> it.playlistTitle = "Various[${index+1}]" } // } - items.forEach { + downloadItems.forEach { it.status = DownloadRepository.Status.Queued.toString() val currentCommand = ytdlpUtil.buildYoutubeDLRequest(it) val parsedCurrentCommand = ytdlpUtil.parseYTDLRequestString(currentCommand) val existingDownload = activeAndQueuedDownloads.firstOrNull{d -> - d.id = 0 - d.logID = null - d.customFileNameTemplate = it.customFileNameTemplate - d.status = DownloadRepository.Status.Queued.toString() - d.toString() == it.toString() + val normalized = d.copy( + id = 0, + logID = null, + customFileNameTemplate = it.customFileNameTemplate, + status = DownloadRepository.Status.Queued.toString() + ) + normalized.toString() == it.toString() } if (existingDownload != null) { it.id = existingDownload.id @@ -191,14 +201,15 @@ class ObserveSourceWorker( downloadRepo.startDownloadWorker(queuedItems, context) } - item.alreadyProcessedLinks.removeAll(items.map { it.url }) - item.alreadyProcessedLinks.addAll(items.map { it.url }) + item.alreadyProcessedLinks.addAll(downloadItems.map { it.url }) } item.runCount += 1 - val currentTime = System.currentTimeMillis() - val isFinished = (item.endsAfterCount > 0 && item.runCount >= item.endsAfterCount) || item.endsDate >= currentTime + val isFinished = + (item.endsAfterCount > 0 && item.runCount >= item.endsAfterCount) || + (item.endsDate > 0 && currentTime >= item.endsDate) + if (isFinished) { item.status = ObserveSourcesRepository.SourceStatus.STOPPED withContext(Dispatchers.IO){ diff --git a/app/src/main/java/com/deniscerri/ytdl/work/TerminalDownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdl/work/TerminalDownloadWorker.kt index dc4583b2..5715b476 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/TerminalDownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/TerminalDownloadWorker.kt @@ -52,7 +52,7 @@ class TerminalDownloadWorker( val intent = Intent(context, TerminalActivity::class.java) val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, command.take(65), NotificationUtil.DOWNLOAD_TERMINAL_RUNNING_NOTIFICATION_ID) - if (Build.VERSION.SDK_INT > 33) { + if (Build.VERSION.SDK_INT >= 33) { setForegroundAsync(ForegroundInfo(itemId, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)) }else{ setForegroundAsync(ForegroundInfo(itemId, notification)) diff --git a/app/src/main/java/com/deniscerri/ytdl/work/UpdateMultipleDownloadsFormatsWorker.kt b/app/src/main/java/com/deniscerri/ytdl/work/UpdateMultipleDownloadsFormatsWorker.kt index f1f544f6..ade63e30 100644 --- a/app/src/main/java/com/deniscerri/ytdl/work/UpdateMultipleDownloadsFormatsWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdl/work/UpdateMultipleDownloadsFormatsWorker.kt @@ -33,7 +33,7 @@ class UpdateMultipleDownloadsFormatsWorker( val notification = notificationUtil.createFormatsUpdateNotification() - if (Build.VERSION.SDK_INT > 33) { + if (Build.VERSION.SDK_INT >= 33) { setForegroundAsync(ForegroundInfo(workID, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)) }else{ setForegroundAsync(ForegroundInfo(workID, notification)) diff --git a/app/src/main/res/layout/observe_sources_bottom_sheet.xml b/app/src/main/res/layout/observe_sources_bottom_sheet.xml index 31354014..2a660816 100644 --- a/app/src/main/res/layout/observe_sources_bottom_sheet.xml +++ b/app/src/main/res/layout/observe_sources_bottom_sheet.xml @@ -224,6 +224,7 @@ app:chipSpacingVertical="0dp" android:paddingVertical="5dp" android:paddingHorizontal="10dp" + app:selectionRequired="true" android:layout_height="wrap_content">