diff --git a/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json b/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json index 53448455..d6834da9 100644 --- a/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json +++ b/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "d658de0453c49534c5971583f41854db", + "identityHash": "e53569dbe0c02d62eda598075d73d5b1", "entities": [ { "tableName": "results", @@ -160,7 +160,7 @@ }, { "tableName": "downloads", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `workID` INTEGER NOT NULL)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued')", "fields": [ { "fieldPath": "id", @@ -265,12 +265,6 @@ "affinity": "TEXT", "notNull": true, "defaultValue": "'Queued'" - }, - { - "fieldPath": "workID", - "columnName": "workID", - "affinity": "INTEGER", - "notNull": true } ], "primaryKey": { @@ -318,7 +312,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd658de0453c49534c5971583f41854db')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e53569dbe0c02d62eda598075d73d5b1')" ] } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt index 9bc3cff6..ce99029a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt @@ -3,8 +3,6 @@ package com.deniscerri.ytdlnis.database.dao import androidx.lifecycle.LiveData import androidx.room.* import com.deniscerri.ytdlnis.database.models.DownloadItem -import com.deniscerri.ytdlnis.database.models.HistoryItem -import com.deniscerri.ytdlnis.util.FileUtil @Dao interface DownloadDao { @@ -21,9 +19,6 @@ interface DownloadDao { @Query("SELECT * FROM downloads WHERE status='Processing'") fun getProcessingDownloads() : LiveData> - @Query("SELECT * FROM downloads WHERE workID=:workID") - fun getDownloadByWorkId(workID: Long) : DownloadItem - @Query("SELECT * FROM downloads WHERE id=:id LIMIT 1") fun getDownloadById(id: Long) : DownloadItem @@ -50,4 +45,8 @@ interface DownloadDao { @Query("UPDATE downloads SET status='Queued' WHERE status='Processing'") suspend fun queueAllProcessing() + + + @Query("SELECT * FROM downloads WHERE url=:url AND (status='Error' OR status='Cancelled') LIMIT 1") + fun checkIfErrorOrCancelled(url: String) : DownloadItem } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt index ae34b0dd..36b6af22 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt @@ -25,6 +25,5 @@ data class DownloadItem( val addChapters: Boolean, val SaveThumb: Boolean, @ColumnInfo(defaultValue = "Queued") - var status: String, - var workID: Long + var status: String ) \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt index 62e3cf23..0813e8fc 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt @@ -1,9 +1,9 @@ package com.deniscerri.ytdlnis.database.repository -import android.util.Log import androidx.lifecycle.LiveData import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.ResultItem class DownloadRepository(private val downloadDao: DownloadDao) { val allDownloads : LiveData> = downloadDao.getAllDownloads() @@ -11,8 +11,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) { val queuedDownloads : LiveData> = downloadDao.getQueuedDownloads() val processingDownloads : LiveData> = downloadDao.getProcessingDownloads() - enum class status { - Active, Queued, Errored, Processing + enum class Status { + Active, Queued, Error, Processing, Cancelled } suspend fun insert(item: DownloadItem) : Long { @@ -27,12 +27,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) { downloadDao.update(item) } - fun getDownloadByWorkID(workID: Long) : DownloadItem{ - return downloadDao.getDownloadByWorkId(workID) - } - - suspend fun setDownloadStatus(item: DownloadItem, status: status){ + suspend fun setDownloadStatus(item: DownloadItem, status: Status){ item.status = status.toString() update(item); } @@ -52,4 +48,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) { suspend fun queueAllProcessing(){ downloadDao.queueAllProcessing() } + + fun checkIfPresent(item: ResultItem): DownloadItem{ + return downloadDao.checkIfErrorOrCancelled(item.url) + } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt index 7775140f..90f8f74d 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt @@ -3,10 +3,15 @@ package com.deniscerri.ytdlnis.database.viewmodel import android.app.Activity import android.app.Application import android.content.SharedPreferences +import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope +import androidx.work.Data +import androidx.work.ExistingWorkPolicy +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager import com.deniscerri.ytdlnis.App import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.DBManager @@ -14,6 +19,7 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdlnis.database.repository.DownloadRepository +import com.deniscerri.ytdlnis.work.DownloadWorker import com.google.gson.Gson import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -90,8 +96,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application resultItem.duration, type, getFormat(resultItem, type), false, - "", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, DownloadRepository.status.Processing.toString(), - 0 + "", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, DownloadRepository.Status.Processing.toString() ) } @@ -126,14 +131,23 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application return list } - fun putDownloadsForProcessing(items: List) : LiveData> { + fun putDownloadsForProcessing(items: List, downloadItems: List) : LiveData> { val result = MutableLiveData>() viewModelScope.launch(Dispatchers.IO){ val list : MutableList = mutableListOf() items.forEachIndexed { i, it -> - val tmpDownloadItem = createDownloadItemFromResult(it!!, "video") - val id = repository.insert(tmpDownloadItem) - list.add(id) + val tmpDownloadItem = downloadItems[i] + try { + val item = repository.checkIfPresent(it!!) + tmpDownloadItem.id = item.id + tmpDownloadItem.status = DownloadRepository.Status.Processing.toString() + repository.update(tmpDownloadItem) + list.add(tmpDownloadItem.id) + }catch (e: Exception){ + val id = repository.insert(tmpDownloadItem) + list.add(id) + } + } result.postValue(list) } @@ -153,7 +167,22 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application return Gson().fromJson(string, DownloadItem::class.java) } - fun queueAllProcessing()= viewModelScope.launch(Dispatchers.IO) { - repository.queueAllProcessing(); + fun queueDownloads(items: List)= viewModelScope.launch(Dispatchers.IO) { + val context = getApplication().applicationContext + items.forEach { + it.status = DownloadRepository.Status.Queued.toString() + repository.update(it) + + val workRequest = OneTimeWorkRequestBuilder() + .setInputData(Data.Builder().putLong("id", it.id).build()) + .addTag("download") + .build() + WorkManager.getInstance(context).beginUniqueWork( + it.id.toString(), + ExistingWorkPolicy.KEEP, + workRequest + ).enqueue() + } } + } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt b/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt index 64f09ae5..3110b5c1 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/CancelDownloadNotificationReceiver.kt @@ -1,14 +1,27 @@ package com.deniscerri.ytdlnis.receiver import android.content.* +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import androidx.work.WorkManager +import com.deniscerri.ytdlnis.database.DBManager +import com.deniscerri.ytdlnis.database.repository.DownloadRepository +import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel +import com.deniscerri.ytdlnis.util.NotificationUtil +import com.yausername.youtubedl_android.YoutubeDL +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking class CancelDownloadNotificationReceiver : BroadcastReceiver() { override fun onReceive(c: Context, intent: Intent) { val message = intent.getStringExtra("cancel") val id = intent.getIntExtra("workID", 0) if (message != null) { - WorkManager.getInstance(c).cancelAllWorkByTag(id.toString()) + val notificationUtil = NotificationUtil(c) + + YoutubeDL.getInstance().destroyProcessById(id.toString()); + WorkManager.getInstance(c).cancelUniqueWork(id.toString()) + notificationUtil.cancelDownloadNotification(id) } } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt index fe979640..199f964d 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -20,6 +20,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.work.WorkManager import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.adapter.HomeAdapter @@ -72,6 +73,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi private var sharedPreferences: SharedPreferences? = null private var _binding : FragmentHomeBinding? = null + private var workManager: WorkManager? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -188,6 +191,14 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi } else { resultViewModel.checkTrending() } + + WorkManager.getInstance(requireContext()) + .getWorkInfosByTagLiveData("download") + .observe(viewLifecycleOwner){ list -> + list.forEach { + //Toast.makeText(context, """${it.progress.getInt("progress", 0)} ${it.progress.getString("output")}""", Toast.LENGTH_SHORT).show() + } + } } private fun initMenu() { @@ -341,8 +352,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi private fun showSingleDownloadSheet(resultItem : ResultItem, type: String){ val downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, type) - downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) { - downloadItem.id = it + downloadViewModel.putDownloadsForProcessing(listOf(resultItem), listOf(downloadItem)).observe(viewLifecycleOwner) { + downloadItem.id = it[0] val bottomSheet = DownloadBottomSheetDialog(downloadItem) bottomSheet.show(parentFragmentManager, "downloadSingleSheet") } @@ -395,7 +406,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi if (viewIdName.isNotEmpty()) { if (viewIdName == "downloadSelected") { val downloadList = downloadViewModel.turnResultItemstoDownloadItems(selectedObjects!!) - downloadViewModel.putDownloadsForProcessing(selectedObjects!!).observe(viewLifecycleOwner) { + downloadViewModel.putDownloadsForProcessing(selectedObjects!!, downloadList).observe(viewLifecycleOwner) { it.forEachIndexed { i, itemID -> downloadList[i].id = itemID } @@ -405,7 +416,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi } if (viewIdName == "downloadAll") { val downloadList = downloadViewModel.turnResultItemstoDownloadItems(resultsList!!) - downloadViewModel.putDownloadsForProcessing(resultsList!!).observe(viewLifecycleOwner) { + downloadViewModel.putDownloadsForProcessing(resultsList!!, downloadList).observe(viewLifecycleOwner) { it.forEachIndexed { i, itemID -> downloadList[i].id = itemID } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt index e3fed8e1..5851f7dd 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt @@ -104,20 +104,7 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment( val download = view.findViewById