From 3c5167f6eb8119c918eb6e4f73cdfa21bb55886a Mon Sep 17 00:00:00 2001 From: zaednasr <75589932+zaednasr@users.noreply.github.com> Date: Tue, 11 Jun 2024 22:57:59 +0200 Subject: [PATCH] 1.7.7 --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 6 - .../ytdl/database/dao/DownloadDao.kt | 20 +- .../database/repository/DownloadRepository.kt | 32 ++- .../database/viewmodel/DownloadViewModel.kt | 158 ++++++-------- .../viewmodel/SharedDownloadViewModel.kt | 5 +- .../ProcessDownloadsInBackgroundService.kt | 165 --------------- .../DownloadMultipleBottomSheetDialog.kt | 193 ++++++------------ .../downloadcard/SelectPlaylistItemsDialog.kt | 19 +- .../ui/downloads/DownloadQueueMainFragment.kt | 24 --- .../deniscerri/ytdl/util/NotificationUtil.kt | 31 --- .../main/res/layout/select_playlist_items.xml | 3 + app/src/main/res/values-vi/strings.xml | 3 +- app/src/main/res/xml/general_preferences.xml | 1 + .../android/en-US/changelogs/10770.txt | 8 + 15 files changed, 193 insertions(+), 477 deletions(-) delete mode 100644 app/src/main/java/com/deniscerri/ytdl/services/ProcessDownloadsInBackgroundService.kt create mode 100644 fastlane/metadata/android/en-US/changelogs/10770.txt diff --git a/app/build.gradle b/app/build.gradle index fb36918f..20b84cc7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ plugins { def properties = new Properties() def versionMajor = 1 def versionMinor = 7 -def versionPatch = 6 +def versionPatch = 7 def versionBuild = 0 // bump for dogfood builds, public betas, etc. def isBeta = false def versionExt = isBeta ? ".${versionBuild}-beta" : "" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a3592432..017d5f45 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,10 +18,6 @@ - - - - @@ -434,8 +430,6 @@ - - ) : List + fun getProcessingDownloadTypes() : List @Query("UPDATE downloads set status = 'Processing' WHERE id in (:ids)") @@ -56,6 +56,12 @@ interface DownloadDao { @Query("SELECT * FROM downloads WHERE status = 'Processing'") fun getProcessingDownloadsList() : List + @Query("UPDATE downloads set downloadStartTime=:time, status='Scheduled' WHERE status ='Processing'") + suspend fun updateProcessingDownloadTime(time: Long) + + @Query("UPDATE downloads set downloadPath=:path WHERE status ='Processing'") + suspend fun updateProcessingDownloadPath(path: String) + @Query("SELECT * FROM downloads WHERE status='Active'") suspend fun getActiveDownloadsList() : List @@ -126,12 +132,6 @@ interface DownloadDao { @Query("SELECT * FROM downloads WHERE id IN (:ids)") fun getDownloadsByIds(ids: List) : List - @Query("SELECT * FROM downloads WHERE status='Processing' AND id >=:id") - fun getProcessingItemsFromID(id: Long) : Flow> - - @Query("SELECT * FROM downloads WHERE status='Processing' AND id >=:id and id<=:id2") - fun getProcessingItemsBetweenIDs(id: Long, id2: Long) : List - @Query("SELECT * FROM downloads WHERE id IN (:ids)") fun getDownloadsByIdsFlow(ids: List) : Flow> @@ -231,8 +231,8 @@ interface DownloadDao { @Query("Update downloads SET status='Queued', downloadStartTime = 0 WHERE id in (:list)") suspend fun reQueueDownloadItems(list: List) - @Query("Update downloads SET status='Saved' WHERE status='Processing' and id in (:ids)") - fun updateProcessingtoSavedStatus(ids: List) + @Query("Update downloads SET status='Saved' WHERE status='Processing'") + suspend fun updateProcessingtoSavedStatus() @Transaction suspend fun putAtTopOfTheQueue(existingIDs: List){ diff --git a/app/src/main/java/com/deniscerri/ytdl/database/repository/DownloadRepository.kt b/app/src/main/java/com/deniscerri/ytdl/database/repository/DownloadRepository.kt index dca6a71e..2b73b38e 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/repository/DownloadRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/repository/DownloadRepository.kt @@ -3,8 +3,11 @@ package com.deniscerri.ytdl.database.repository import android.annotation.SuppressLint import android.content.Context import android.net.ConnectivityManager +import android.os.Handler import android.os.Looper +import android.text.format.DateFormat import android.widget.Toast +import androidx.core.os.postDelayed import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.preference.PreferenceManager @@ -28,6 +31,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import java.io.File +import java.text.SimpleDateFormat +import java.util.Locale import java.util.concurrent.TimeUnit @@ -109,14 +114,6 @@ class DownloadRepository(private val downloadDao: DownloadDao) { return downloadDao.getDownloadById(id) } - fun getProcessingItemsFromID(id: Long) : Flow> { - return downloadDao.getProcessingItemsFromID(id) - } - - fun getProcessingItemsBetweenIDs(first: Long, last:Long) : List { - return downloadDao.getProcessingItemsBetweenIDs(first, last) - } - fun getAllItemsByIDs(ids : List) : List{ return downloadDao.getDownloadsByIds(ids) } @@ -137,6 +134,10 @@ class DownloadRepository(private val downloadDao: DownloadDao) { return downloadDao.getActiveAndQueuedDownloadsList() } + suspend fun updateProcessingDownloadTime(time: Long) { + downloadDao.updateProcessingDownloadTime(time) + } + fun getActiveAndQueuedDownloadIDs() : List { return downloadDao.getActiveAndQueuedDownloadIDs() } @@ -258,12 +259,23 @@ class DownloadRepository(private val downloadDao: DownloadDao) { } + val handler = Handler(Looper.getMainLooper()) + val isCurrentNetworkMetered = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).isActiveNetworkMetered if (!allowMeteredNetworks && isCurrentNetworkMetered){ - Looper.prepare().run { + handler.postDelayed({ Toast.makeText(context, context.getString(R.string.metered_network_download_start_info), Toast.LENGTH_LONG).show() - } + }, 0) } + + val first = queuedItems.first() + if (first.downloadStartTime > 0L) { + val date = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(queuedItems.first().downloadStartTime) + handler.postDelayed({ + Toast.makeText(context, context.getString(R.string.download_rescheduled_to) + " " + date, Toast.LENGTH_LONG).show() + }, 0) + } + } } \ No newline at end of file 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 b3d6a71e..9d1882e6 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 @@ -9,11 +9,8 @@ import android.util.DisplayMetrics import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asFlow import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope -import androidx.media3.exoplayer.offline.Download import androidx.paging.PagingData import androidx.preference.PreferenceManager import androidx.work.Data @@ -46,21 +43,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.last -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.isActive import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import java.io.File import java.util.Locale @@ -75,8 +60,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel val allDownloads : Flow> val queuedDownloads : Flow> val activeDownloads : Flow> - val allProcessingDownloads : Flow> - var mostRecentProcessingDownloads: Flow> + val processingDownloads : Flow> val cancelledDownloads : Flow> val erroredDownloads : Flow> val savedDownloads : Flow> @@ -115,8 +99,6 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel auto, audio, video, command } - - val processingDownloads = MediatorLiveData>(listOf()) var processingItemsFlow : ProcessingItemsJob? = null var processingItems = MutableStateFlow(false) @@ -143,8 +125,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel allDownloads = repository.allDownloads.flow queuedDownloads = repository.queuedDownloads.flow activeDownloads = repository.activeDownloads - allProcessingDownloads = repository.processingDownloads - mostRecentProcessingDownloads = repository.getProcessingItemsFromID(0) + processingDownloads = repository.processingDownloads savedDownloads = repository.savedDownloads.flow scheduledDownloads = repository.scheduledDownloads.flow cancelledDownloads = repository.cancelledDownloads.flow @@ -385,6 +366,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel fun turnDownloadItemsToProcessingDownloads(itemIDs: List) = viewModelScope.launch(Dispatchers.IO){ updateProcessingJobData(ProcessingItemsJob(null, DownloadItem::class.java.toString(), itemIDs)) val job = viewModelScope.launch(Dispatchers.IO) { + repository.deleteProcessing() processingItems.emit(true) try { itemIDs.forEachIndexed { idx, it -> @@ -395,7 +377,6 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel item.status = DownloadRepository.Status.Processing.toString() processingItemsFlow?.apply { val id = repository.insert(item) - if (idx == 0) mostRecentProcessingDownloads = repository.getProcessingItemsFromID(id) processingDownloadItemIDs.add(id) updateProcessingJobData(this) } @@ -499,7 +480,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel repository.deleteProcessing() } - fun deleteAllWithID(ids: List) = viewModelScope.launch(Dispatchers.IO){ + suspend fun deleteAllWithID(ids: List) { repository.deleteAllWithIDs(ids) } @@ -618,6 +599,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel repository.startDownloadWorker(emptyList(), application) } + suspend fun queueProcessingDownloads(){ + val processingItems = repository.getProcessingDownloads() + queueDownloads(processingItems) + } + suspend fun queueDownloads(items: List, ign : Boolean = false) : List { val ids = sharedDownloadViewModel.queueDownloads(items, ign) return ids @@ -639,43 +625,33 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel return dbManager.downloadDao.getDownloadIDsNotPresentInList(items.ifEmpty { listOf(-1L) }, status.map { it.toString() }) } - fun moveProcessingToSavedCategory(ids: List){ - ids.chunked(100).forEach { - dao.updateProcessingtoSavedStatus(it) + suspend fun moveProcessingToSavedCategory(){ + dao.updateProcessingtoSavedStatus() + } + + suspend fun updateProcessingFormat(selectedFormats: List): List { + val items = repository.getProcessingDownloads() + items.forEachIndexed { index, i -> + selectedFormats[index].format?.apply { + i.format = this + } + if (i.type == Type.video) selectedFormats[index].audioFormats?.map { it.format_id }?.let { i.videoPreferences.audioFormatIDs.addAll(it) } + repository.update(i) + } + + return items.map { itm -> itm.format.filesize } + } + + suspend fun updateProcessingCommandFormat(format: Format){ + val items = repository.getProcessingDownloads() + items.forEach { + it.format = format + repository.update(it) } } - suspend fun updateProcessingFormat(ids: List, selectedFormats: List): List { - return ids.chunked(100).map { - val items = repository.getAllItemsByIDs(it) - items.forEachIndexed { index, i -> - selectedFormats[index].format?.apply { - i.format = this - } - if (i.type == Type.video) selectedFormats[index].audioFormats?.map { it.format_id }?.let { i.videoPreferences.audioFormatIDs.addAll(it) } - repository.update(i) - } - - items.map { itm -> itm.format.filesize } - }.flatten() - } - - suspend fun updateProcessingCommandFormat(ids: List, format: Format){ - ids.chunked(100).forEach { - repository.getAllItemsByIDs(it).forEach { i -> - i.format = format - repository.update(i) - } - } - } - - suspend fun updateProcessingDownloadPath(ids: List, path: String){ - ids.chunked(100).forEach { - repository.getAllItemsByIDs(it).forEach { i -> - i.downloadPath = path - repository.update(i) - } - } + suspend fun updateProcessingDownloadPath(path: String){ + dao.updateProcessingDownloadPath(path) } fun getProcessingDownloadsCount() : Int { @@ -687,42 +663,35 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel } - suspend fun updateProcessingAllFormats(ids: List, formatCollection: List>) { - ids.chunked(100).forEach { - val items = repository.getAllItemsByIDs(it) - items.forEachIndexed { index, i -> - i.allFormats.clear() - if (formatCollection.size == items.size && formatCollection[index].isNotEmpty()) { - runCatching { - i.allFormats.addAll(formatCollection[index]) - } + suspend fun updateProcessingAllFormats(formatCollection: List>) { + val items = repository.getProcessingDownloads() + items.forEachIndexed { index, i -> + i.allFormats.clear() + if (formatCollection.size == items.size && formatCollection[index].isNotEmpty()) { + runCatching { + i.allFormats.addAll(formatCollection[index]) } - i.format = getFormat(i.allFormats, i.type) - kotlin.runCatching { - dbManager.resultDao.getResultByURL(i.url)?.apply { - this.formats = formatCollection[index].toMutableList() - dbManager.resultDao.update(this) - } - } - repository.update(i) } + i.format = getFormat(i.allFormats, i.type) + kotlin.runCatching { + dbManager.resultDao.getResultByURL(i.url)?.apply { + this.formats = formatCollection[index].toMutableList() + dbManager.resultDao.update(this) + } + } + repository.update(i) } - } - suspend fun continueUpdatingFormatsOnBackground(itemIDs: List){ - itemIDs.chunked(100).forEach {list -> - repository.getAllItemsByIDs(list).onEach { - it.status = DownloadRepository.Status.Saved.toString() - repository.update(it) - } - } + suspend fun continueUpdatingFormatsOnBackground(){ + val ids = dao.getProcessingDownloadsList().map { it.id } + dao.updateProcessingtoSavedStatus() val id = System.currentTimeMillis().toInt() val workRequest = OneTimeWorkRequestBuilder() .setInputData( Data.Builder() - .putLongArray("ids", itemIDs.toLongArray()) + .putLongArray("ids", ids.toLongArray()) .putInt("id", id) .build()) .addTag("updateFormats") @@ -736,23 +705,22 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel } - suspend fun updateProcessingType(ids: List, newType: Type) { - ids.chunked(100).forEach { _ -> - repository.getAllItemsByIDs(ids).apply { - val new = switchDownloadType(this, newType) - new.forEach { - repository.update(it) - } + suspend fun updateProcessingType(newType: Type) { + val processing = repository.getProcessingDownloads() + processing.apply { + val new = switchDownloadType(this, newType) + new.forEach { + repository.update(it) } } } - fun checkIfAllProcessingItemsHaveSameType(ids: List) : Pair { - val types = mutableSetOf() - ids.chunked(100).forEach { - types.addAll(dao.getProcessingDownloadTypes(it)) - } + suspend fun updateProcessingDownloadTime(time: Long) { + repository.updateProcessingDownloadTime(time) + } + fun checkIfAllProcessingItemsHaveSameType() : Pair { + val types = dao.getProcessingDownloadTypes() return Pair(types.size == 1, Type.valueOf(types.first())) } diff --git a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/SharedDownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/SharedDownloadViewModel.kt index 2e71698a..907ae073 100644 --- a/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/SharedDownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdl/database/viewmodel/SharedDownloadViewModel.kt @@ -321,7 +321,7 @@ class SharedDownloadViewModel(private val context: Context) { val prefVideo = sharedPreferences.getString("format_importance_video", itemValues.joinToString(","))!! prefVideo.split(",").forEachIndexed { idx, s -> - val importance = (itemValues.size - idx) * 10 + var importance = (itemValues.size - idx) * 10 when(s) { "id" -> { @@ -345,8 +345,9 @@ class SharedDownloadViewModel(private val context: Context) { for(i in 0..preferenceIndex){ removeAt(0) } - add(0, preference) + requirements.add { it: Format -> if (it.format_note.contains(preference, ignoreCase = true)) importance else 0 } forEachIndexed { index, res -> + if (index >= 2) importance = 0 requirements.add { it: Format -> if (it.format_note.contains(res, ignoreCase = true)) (importance - index - 1) else 0 } } } diff --git a/app/src/main/java/com/deniscerri/ytdl/services/ProcessDownloadsInBackgroundService.kt b/app/src/main/java/com/deniscerri/ytdl/services/ProcessDownloadsInBackgroundService.kt deleted file mode 100644 index 23d8816c..00000000 --- a/app/src/main/java/com/deniscerri/ytdl/services/ProcessDownloadsInBackgroundService.kt +++ /dev/null @@ -1,165 +0,0 @@ -package com.deniscerri.ytdl.services - -import android.app.Service -import android.content.Intent -import android.os.Binder -import android.os.Build -import android.os.IBinder -import androidx.core.content.IntentCompat -import androidx.lifecycle.lifecycleScope -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.ResultRepository -import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel -import com.deniscerri.ytdl.database.viewmodel.SharedDownloadViewModel -import com.deniscerri.ytdl.util.NotificationUtil -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - - -class ProcessDownloadsInBackgroundService : Service() { - - private val binder: IBinder = LocalBinder() - private val queueProcessingDownloadsJobList = mutableListOf() - private lateinit var repository: DownloadRepository - private lateinit var resultRepository: ResultRepository - private lateinit var downloadViewModel: SharedDownloadViewModel - inner class LocalBinder: Binder() { - val service: ProcessDownloadsInBackgroundService - get() = this@ProcessDownloadsInBackgroundService - } - - override fun onCreate() { - super.onCreate() - val dbManager = DBManager.getInstance(this) - repository = DownloadRepository(dbManager.downloadDao) - resultRepository = ResultRepository(dbManager.resultDao, this) - downloadViewModel = SharedDownloadViewModel(this) - } - - - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - - val binding = intent.getBooleanExtra("binding", false) - if (binding) { - val cancel = intent.getBooleanExtra("cancel", false) - if (cancel) { - cancelAllProcessingJobs() - CoroutineScope(SupervisorJob()).launch(Dispatchers.IO){ - repository.deleteProcessing() - withContext(Dispatchers.Main){ - if (Build.VERSION.SDK_INT > 23){ - stopForeground(STOP_FOREGROUND_REMOVE) - }else{ - stopForeground(true) - } - stopSelf() - } - } - }else{ - return super.onStartCommand(intent, flags, startId) - } - } - - val notificationUtil = NotificationUtil(this) - startForeground(System.currentTimeMillis().toInt(), notificationUtil.createProcessingDownloads()) - - - val itemType = intent.getStringExtra("itemType")!! - val itemIDs = intent.getLongArrayExtra("itemIDs")!!.toList() - val processingItemIDs = intent.getLongArrayExtra("processingItemIDs")!!.toList() - val timeInMillis = intent.getLongExtra("timeInMillis", 0) - val processingFinished = intent.getBooleanExtra("processingFinished", true) - - val job = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) { - if (!processingFinished) { - when(itemType) { - ResultItem::class.java.toString() -> { - itemIDs.chunked(100).map { ids -> - resultRepository.getAllByIDs(ids).map { - downloadViewModel.createDownloadItemFromResult( - result = it, givenType = DownloadViewModel.Type.valueOf( - downloadViewModel.getDownloadType(url = it.url).toString() - ) - ) - }.apply { - if (timeInMillis > 0) { - this.forEach { - it.setAsScheduling(timeInMillis) - } - } - if (isActive){ - downloadViewModel.queueDownloads(this) - } - } - } - } - - DownloadItem::class.java.toString() -> { - itemIDs.chunked(100).map { ids -> - repository.getAllItemsByIDs(ids).apply { - if (timeInMillis > 0) { - this.forEach { - it.setAsScheduling(timeInMillis) - } - } - if (isActive){ - downloadViewModel.queueDownloads(this) - } - } - } - } - } - }else { - repository.getProcessingItemsBetweenIDs(processingItemIDs.first(), processingItemIDs.last()).apply { - this.chunked(100).map { - if (timeInMillis > 0){ - this.forEach { d -> - d.setAsScheduling(timeInMillis) - } - } - - if (isActive){ - downloadViewModel.queueDownloads(it) - } - } - - } - } - } - job.invokeOnCompletion { - queueProcessingDownloadsJobList.remove(job) - if (queueProcessingDownloadsJobList.isEmpty()){ - stopForeground(true) - stopSelf() - } - } - queueProcessingDownloadsJobList.add(job) - - return super.onStartCommand(intent, flags, startId) - } - - override fun onBind(intent: Intent): IBinder { - return binder - } - - private fun DownloadItem.setAsScheduling(timeInMillis: Long) { - status = DownloadRepository.Status.Scheduled.toString() - downloadStartTime = timeInMillis - } - - fun cancelAllProcessingJobs(){ - queueProcessingDownloadsJobList.onEach { it.cancel(CancellationException()) } - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt index c09bc448..e9b9232f 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt @@ -3,32 +3,23 @@ package com.deniscerri.ytdl.ui.downloadcard import android.annotation.SuppressLint import android.app.Activity import android.app.Dialog -import android.content.ComponentName -import android.content.Context import android.content.DialogInterface import android.content.Intent -import android.content.ServiceConnection import android.content.SharedPreferences import android.content.res.Configuration import android.graphics.Canvas import android.graphics.Color import android.os.Bundle -import android.os.IBinder -import android.text.format.DateFormat import android.util.DisplayMetrics -import android.util.Log import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.view.Window -import android.widget.Button import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.content.ContextCompat import androidx.core.view.children -import androidx.core.view.forEach import androidx.core.view.get import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider @@ -45,13 +36,11 @@ import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel -import com.deniscerri.ytdl.services.ProcessDownloadsInBackgroundService import com.deniscerri.ytdl.ui.adapter.ConfigureMultipleDownloadsAdapter import com.deniscerri.ytdl.util.Extensions.enableFastScroll import com.deniscerri.ytdl.util.FileUtil import com.deniscerri.ytdl.util.InfoUtil import com.deniscerri.ytdl.util.UiUtil -import com.facebook.shimmer.Shimmer import com.facebook.shimmer.ShimmerFrameLayout import com.google.android.material.bottomappbar.BottomAppBar import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -61,22 +50,14 @@ 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.elevation.SurfaceColors -import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.snackbar.Snackbar import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext -import java.text.SimpleDateFormat -import java.util.Locale -import java.util.function.Predicate class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener, ConfigureDownloadBottomSheetDialog.OnDownloadItemUpdateListener { @@ -91,6 +72,8 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure private lateinit var bottomAppBar: BottomAppBar private lateinit var filesize : TextView private lateinit var count : TextView + private lateinit var downloadBtn : MaterialButton + private lateinit var scheduleBtn : MaterialButton private lateinit var title: TextView private lateinit var subtitle: TextView private lateinit var shimmerTitle: ShimmerFrameLayout @@ -154,19 +137,14 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure itemTouchHelper.attachToRecyclerView(recyclerView) } - val scheduleBtn = view.findViewById(R.id.bottomsheet_schedule_button) - val download = view.findViewById