From af4294e0920c4bc7290f47ccfc53554cbdc4cce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C3=87erri?= <64997243+deniscerri@users.noreply.github.com> Date: Sat, 28 Jan 2023 00:47:53 +0100 Subject: [PATCH] fixes --- .../1.json | 18 +-- .../com/deniscerri/ytdlnis/MainActivity.kt | 8 +- .../ConfigureMultipleDownloadsAdapter.kt | 15 +- .../ytdlnis/database/dao/DownloadDao.kt | 4 +- .../ytdlnis/database/models/DownloadItem.kt | 2 - .../ytdlnis/database/models/Format.kt | 4 +- .../database/repository/DownloadRepository.kt | 2 +- .../database/viewmodel/DownloadViewModel.kt | 49 +++++- .../ConfigureDownloadBottomSheetDialog.kt | 145 ++++++++++++++++++ .../ui/downloadcard/DownloadAudioFragment.kt | 34 +--- .../downloadcard/DownloadBottomSheetDialog.kt | 46 +++++- .../downloadcard/DownloadFragmentAdapter.kt | 1 + .../DownloadMultipleBottomSheetDialog.kt | 12 +- .../ui/downloadcard/DownloadVideoFragment.kt | 45 ++---- .../deniscerri/ytdlnis/work/DownloadWorker.kt | 4 +- .../configure_download_bottom_sheet.xml | 86 +++++++++++ .../main/res/layout/download_bottom_sheet.xml | 47 +++++- app/src/main/res/layout/download_card.xml | 24 ++- .../res/layout/fragment_download_audio.xml | 51 +----- .../res/layout/fragment_download_command.xml | 46 ------ .../res/layout/fragment_download_video.xml | 46 ------ .../res/layout/home_download_settings.xml | 59 ------- 22 files changed, 445 insertions(+), 303 deletions(-) create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt create mode 100644 app/src/main/res/layout/configure_download_bottom_sheet.xml delete mode 100644 app/src/main/res/layout/home_download_settings.xml diff --git a/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json b/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json index f166f2e3..53448455 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": "eddd8d0408b9e321c902948a418e6c92", + "identityHash": "d658de0453c49534c5971583f41854db", "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, `ext` TEXT NOT NULL, `filesize` TEXT 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', `workID` INTEGER NOT NULL)", "fields": [ { "fieldPath": "id", @@ -259,18 +259,6 @@ "affinity": "INTEGER", "notNull": true }, - { - "fieldPath": "ext", - "columnName": "ext", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filesize", - "columnName": "filesize", - "affinity": "TEXT", - "notNull": true - }, { "fieldPath": "status", "columnName": "status", @@ -330,7 +318,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, 'eddd8d0408b9e321c902948a418e6c92')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd658de0453c49534c5971583f41854db')" ] } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt index 8931551c..1173a67f 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt @@ -280,7 +280,7 @@ class MainActivity : AppCompatActivity() { arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1 ) - }else{ + }else if (!checkNotificationPermission()){ ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), @@ -307,6 +307,7 @@ class MainActivity : AppCompatActivity() { ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) for (i in permissions.indices) { + if (permissions.contains(Manifest.permission.POST_NOTIFICATIONS)) break if (grantResults[i] == PackageManager.PERMISSION_DENIED) { createPermissionRequestDialog() }else{ @@ -325,6 +326,11 @@ class MainActivity : AppCompatActivity() { == PackageManager.PERMISSION_GRANTED) } + private fun checkNotificationPermission(): Boolean { + return (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) + == PackageManager.PERMISSION_GRANTED) + } + private fun createPermissionRequestDialog() { val dialog = MaterialAlertDialogBuilder(this) dialog.setTitle(getString(R.string.warning)) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/ConfigureMultipleDownloadsAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/ConfigureMultipleDownloadsAdapter.kt index 5e91d4e4..5432012d 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/ConfigureMultipleDownloadsAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/ConfigureMultipleDownloadsAdapter.kt @@ -19,18 +19,22 @@ import androidx.recyclerview.widget.RecyclerView import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.ResultItem +import com.deniscerri.ytdlnis.util.FileUtil import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.progressindicator.LinearProgressIndicator import com.squareup.picasso.Picasso +import java.util.* class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) { private val onItemClickListener: OnItemClickListener private val activity: Activity + private val fileUtil: FileUtil init { this.onItemClickListener = onItemClickListener this.activity = activity + this.fileUtil = FileUtil() } class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) { @@ -77,11 +81,16 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener // Container ---------------------------------- val container = card.findViewById(R.id.container) - container.text = item.ext + container.text = item.format.container.uppercase(Locale.getDefault()) // File Size val fileSize = card.findViewById(R.id.filesize) - fileSize.text = item.filesize + val formattedSize = fileUtil.convertFileSize(item.format.filesize) + fileSize.text = if (formattedSize == "?") "" else formattedSize.uppercase(Locale.getDefault()) + + // Quality + val quality = card.findViewById(R.id.quality) + quality.text = item.format.format_note // Type Icon Button val btn = card.findViewById(R.id.downloads_download_button_type) @@ -115,7 +124,7 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener } override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean { - return oldItem.url == newItem.url && oldItem.title == newItem.title && oldItem.author == newItem.author + return oldItem.url == newItem.url && oldItem.title == newItem.title && oldItem.author == newItem.author && oldItem.type == newItem.type && oldItem.format == newItem.format } } } 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 544e5ce9..3267c7b1 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 @@ -33,8 +33,8 @@ interface DownloadDao { @Query("DELETE FROM downloads") suspend fun deleteAll() - @Delete - suspend fun delete(item: DownloadItem) + @Query("DELETE FROM downloads WHERE id=:id") + suspend fun delete(id: Long) @Query("DELETE FROM downloads WHERE status='Processing'") suspend fun deleteProcessing() 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 5d4fd387..f5c0e7a6 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 @@ -24,8 +24,6 @@ data class DownloadItem( val embedSubs: Boolean, val addChapters: Boolean, val SaveThumb: Boolean, - var ext: String, - var filesize: String, @ColumnInfo(defaultValue = "Queued") var status: String, val workID: Int diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt index 99932091..8eac34ee 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt @@ -6,9 +6,9 @@ data class Format( @SerializedName(value = "format_id", alternate = ["itag"]) var format_id: String = "", @SerializedName(value = "ext", alternate = ["container"]) - val container: String = "", + var container: String = "", @SerializedName(value = "filesize", alternate = ["clen", "filesize_approx"]) - val filesize: Long = 0, + var filesize: Long = 0, @SerializedName(value = "format_note", alternate = ["resolution", "audioQuality"]) var format_note: 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 29d37622..10340ef3 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 @@ -19,7 +19,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) { } suspend fun delete(item: DownloadItem){ - downloadDao.delete(item) + downloadDao.delete(item.id) } suspend fun update(item: DownloadItem){ 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 1dc23fe0..404e0a0b 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 @@ -2,11 +2,13 @@ package com.deniscerri.ytdlnis.database.viewmodel import android.app.Activity import android.app.Application +import android.content.SharedPreferences import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.deniscerri.ytdlnis.App +import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.Format @@ -17,18 +19,33 @@ import kotlinx.coroutines.launch class DownloadViewModel(application: Application) : AndroidViewModel(application) { private val repository : DownloadRepository + private val sharedPreferences: SharedPreferences val allDownloads : LiveData> val queuedDownloads : LiveData> val activeDownloads : LiveData> val processingDownloads : LiveData> + private var bestVideoFormat: Format + init { val dao = DBManager.getInstance(application).downloadDao repository = DownloadRepository(dao) + sharedPreferences = + getApplication().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) + allDownloads = repository.allDownloads queuedDownloads = repository.queuedDownloads activeDownloads = repository.activeDownloads processingDownloads = repository.processingDownloads + + val format = getApplication().resources.getStringArray(R.array.video_formats) + val container = sharedPreferences.getString("video_format", "Default") + bestVideoFormat = Format( + format[format.lastIndex], + container!!, + 0, + format[format.lastIndex] + ) } fun startWork(items: List){ @@ -60,9 +77,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application } fun createDownloadItemFromResult(resultItem: ResultItem, type: String) : DownloadItem { - val sharedPreferences = - getApplication().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) - val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false) + val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false) val addChapters = sharedPreferences.getBoolean("add_chapters", false) val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false) @@ -73,13 +88,35 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application resultItem.thumb, resultItem.duration, type, - Format(), false, - "", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, "", - "", DownloadRepository.status.Processing.toString(), 0 + getFormat(resultItem, type), false, + "", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, DownloadRepository.status.Processing.toString(), + 0 ) } + private fun getFormat(resultItem: ResultItem, type: String) : Format { + when(type) { + "audio" -> { + return try { + resultItem.formats.last { it.format_note.contains("audio", ignoreCase = true) } + }catch (e: Exception){ + Format() + } + } + "video" -> { + return try { + resultItem.formats[resultItem.formats.lastIndex] + }catch (e: Exception){ + bestVideoFormat + } + } + else -> { + return Format() + } + } + } + fun turnResultItemstoDownloadItems(items: List) : List { val list : MutableList = mutableListOf() items.forEach { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt new file mode 100644 index 00000000..c8b2dd3b --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt @@ -0,0 +1,145 @@ +package com.deniscerri.ytdlnis.ui.downloadcard + +import android.annotation.SuppressLint +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.widget.Button +import androidx.fragment.app.FragmentTransaction +import androidx.fragment.app.findFragment +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import androidx.viewpager2.widget.ViewPager2 +import com.deniscerri.ytdlnis.R +import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel +import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.google.android.material.button.MaterialButton +import com.google.android.material.tabs.TabLayout +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class ConfigureDownloadBottomSheetDialog(private val downloadItem: DownloadItem) : BottomSheetDialogFragment() { + private lateinit var tabLayout: TabLayout + private lateinit var viewPager2: ViewPager2 + private lateinit var fragmentAdapter : DownloadFragmentAdapter + private val currentItem = downloadItem.copy() + + private lateinit var downloadViewModel: DownloadViewModel + private lateinit var resultViewModel: ResultViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] + resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val behavior = BottomSheetBehavior.from(view.parent as View) + behavior.state = BottomSheetBehavior.STATE_EXPANDED + } + + @SuppressLint("RestrictedApi") + override fun setupDialog(dialog: Dialog, style: Int) { + super.setupDialog(dialog, style) + val view = LayoutInflater.from(context).inflate(R.layout.configure_download_bottom_sheet, null) + dialog.setContentView(view) + //view.minimumHeight = resources.displayMetrics.heightPixels + + tabLayout = view.findViewById(R.id.download_tablayout) + viewPager2 = view.findViewById(R.id.download_viewpager) + + val fragmentManager = parentFragmentManager + fragmentAdapter = DownloadFragmentAdapter(downloadItem, fragmentManager, lifecycle) + viewPager2.adapter = fragmentAdapter + viewPager2.isSaveFromParentEnabled = false + + when(downloadItem.type) { + "audio" -> { + tabLayout.selectTab(tabLayout.getTabAt(0)) + viewPager2.setCurrentItem(0, false) + } + "video" -> { + tabLayout.selectTab(tabLayout.getTabAt(1)) + viewPager2.setCurrentItem(1, false) + } + "command" -> { + tabLayout.selectTab(tabLayout.getTabAt(2)) + viewPager2.setCurrentItem(2, false) + } + } + + + tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab?) { + viewPager2.currentItem = tab!!.position + } + + override fun onTabUnselected(tab: TabLayout.Tab?) { + } + + override fun onTabReselected(tab: TabLayout.Tab?) { + } + }) + + viewPager2.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + tabLayout.selectTab(tabLayout.getTabAt(position)) + } + }) + + + val cancelBtn = view.findViewById(R.id.bottomsheet_cancel_button) + cancelBtn.setOnClickListener{ + returnPreviousState(); + dismiss() + } + + val download = view.findViewById