This commit is contained in:
Denis Çerri 2023-01-28 00:47:53 +01:00
parent 9e5f0e5fab
commit af4294e092
No known key found for this signature in database
GPG key ID: 95C43D517D830350
22 changed files with 445 additions and 303 deletions

View file

@ -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')"
]
}
}

View file

@ -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))

View file

@ -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<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(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<TextView>(R.id.container)
container.text = item.ext
container.text = item.format.container.uppercase(Locale.getDefault())
// File Size
val fileSize = card.findViewById<TextView>(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<TextView>(R.id.quality)
quality.text = item.format.format_note
// Type Icon Button
val btn = card.findViewById<MaterialButton>(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
}
}
}

View file

@ -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()

View file

@ -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

View file

@ -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 = ""
)

View file

@ -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){

View file

@ -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<List<DownloadItem>>
val queuedDownloads : LiveData<List<DownloadItem>>
val activeDownloads : LiveData<List<DownloadItem>>
val processingDownloads : LiveData<List<DownloadItem>>
private var bestVideoFormat: Format
init {
val dao = DBManager.getInstance(application).downloadDao
repository = DownloadRepository(dao)
sharedPreferences =
getApplication<App>().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
allDownloads = repository.allDownloads
queuedDownloads = repository.queuedDownloads
activeDownloads = repository.activeDownloads
processingDownloads = repository.processingDownloads
val format = getApplication<App>().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<DownloadItem>){
@ -60,9 +77,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
}
fun createDownloadItemFromResult(resultItem: ResultItem, type: String) : DownloadItem {
val sharedPreferences =
getApplication<App>().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<ResultItem?>) : List<DownloadItem> {
val list : MutableList<DownloadItem> = mutableListOf()
items.forEach {

View file

@ -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<MaterialButton>(R.id.bottomsheet_cancel_button)
cancelBtn.setOnClickListener{
returnPreviousState();
dismiss()
}
val download = view.findViewById<Button>(R.id.bottom_sheet_ok)
download!!.setOnClickListener {
dismiss()
}
}
override fun onCancel(dialog: DialogInterface) {
super.onCancel(dialog)
returnPreviousState();
cleanUp()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
cleanUp()
}
private fun returnPreviousState(){
lifecycleScope.launch{
val result = withContext(Dispatchers.IO){
resultViewModel.getItemByURL(currentItem.url)
}
result.title = currentItem.title
result.author = currentItem.author
resultViewModel.update(result)
downloadViewModel.updateDownload(currentItem)
}
}
private fun cleanUp(){
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("configureDownloadSingleSheet")!!).commit()
for (i in 0 until viewPager2.adapter?.itemCount!!){
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
}
}
}
}

View file

@ -17,6 +17,7 @@ import androidx.lifecycle.lifecycleScope
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
@ -136,6 +137,7 @@ class DownloadAudioFragment(private val downloadItem: DownloadItem) : Fragment()
val format = view.findViewById<TextInputLayout>(R.id.format)
if (formats.isEmpty()) {
format.visibility = View.GONE
downloadItem.format = Format()
} else {
val formatTitles = formats.map {
if (it.format_note.contains("AUDIO_QUALITY_")) {
@ -166,6 +168,7 @@ class DownloadAudioFragment(private val downloadItem: DownloadItem) : Fragment()
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
downloadItem.format.format_note = formats[index].format_note
downloadItem.format.format_id = formats[index].format_id
downloadViewModel.updateDownload(downloadItem)
}
}
@ -187,36 +190,11 @@ class DownloadAudioFragment(private val downloadItem: DownloadItem) : Fragment()
containerAutoCompleteTextView!!.setText(selectedContainer, false)
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
downloadItem.ext = containers[index]
downloadItem.format.container = containers[index]
downloadViewModel.updateDownload(downloadItem)
}
val cancelBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_cancel_button)
cancelBtn.setOnClickListener{
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
}
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
download!!.setOnClickListener {
// for (i in selectedObjects!!.indices) {
// val vid = findVideo(
// selectedObjects!![i]!!.getURL()
// )
// vid!!.downloadedType = type
// updateDownloadingStatusOnResult(vid, type, true)
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
// downloadQueue!!.add(vid)
// }
// selectedObjects = ArrayList()
// homeAdapter!!.clearCheckedVideos()
// downloadFabs!!.visibility = View.GONE
// if (isStoragePermissionGranted) {
// mainActivity!!.startDownloadService(downloadQueue, listener)
// downloadQueue!!.clear()
// }
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
}
downloadViewModel.updateDownload(downloadItem)
}catch (e : Exception){
e.printStackTrace()
}

View file

@ -7,6 +7,10 @@ import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.Adapter
import android.widget.Button
import android.widget.LinearLayout
import androidx.core.view.get
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.findFragment
import androidx.lifecycle.ViewModelProvider
@ -17,6 +21,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
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
class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment() {
@ -42,7 +47,6 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
super.setupDialog(dialog, style)
val view = LayoutInflater.from(context).inflate(R.layout.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)
@ -85,10 +89,46 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
tabLayout.selectTab(tabLayout.getTabAt(position))
}
})
val cancelBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_cancel_button)
cancelBtn.setOnClickListener{
dismiss()
}
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
download!!.setOnClickListener {
// for (i in selectedObjects!!.indices) {
// val vid = findVideo(
// selectedObjects!![i]!!.getURL()
// )
// vid!!.downloadedType = type
// updateDownloadingStatusOnResult(vid, type, true)
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
// downloadQueue!!.add(vid)
// }
// selectedObjects = ArrayList()
// homeAdapter!!.clearCheckedVideos()
// downloadFabs!!.visibility = View.GONE
// if (isStoragePermissionGranted) {
// mainActivity!!.startDownloadService(downloadQueue, listener)
// downloadQueue!!.clear()
// }
dismiss()
}
}
override fun onCancel(dialog: DialogInterface) {
super.onCancel(dialog)
cleanUp()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
cleanUp()
}
private fun cleanUp(){
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadSingleSheet")!!).commit()
for (i in 0 until viewPager2.adapter?.itemCount!!){
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
@ -98,9 +138,5 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
downloadViewModel.deleteDownload(downloadItem)
}
fun dismissSelf(){
this.dismiss()
}
}

View file

@ -31,6 +31,7 @@ class DownloadFragmentAdapter (item : DownloadItem, fragmentManager : FragmentMa
return DownloadCommandFragment(clone(downloadItem))
}
private fun clone(item: DownloadItem) : DownloadItem {
val stringItem = Gson().toJson(item, DownloadItem::class.java)
return Gson().fromJson(stringItem, DownloadItem::class.java)

View file

@ -12,6 +12,7 @@ import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.findFragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
@ -26,6 +27,9 @@ 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 DownloadMultipleBottomSheetDialog(private val items: List<DownloadItem>) : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener {
private lateinit var downloadViewModel: DownloadViewModel
@ -116,7 +120,13 @@ class DownloadMultipleBottomSheetDialog(private val items: List<DownloadItem>) :
}
override fun onCardClick(itemID: Long) {
TODO("Not yet implemented")
lifecycleScope.launch{
val downloadItem = withContext(Dispatchers.IO){
downloadViewModel.getItemByID(itemID)
}
val bottomSheet = ConfigureDownloadBottomSheetDialog(downloadItem)
bottomSheet.show(parentFragmentManager, "configureDownloadSingleSheet")
}
}
override fun onClick(p0: View?) {

View file

@ -5,6 +5,7 @@ import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -142,11 +143,7 @@ class DownloadVideoFragment(private val downloadItem: DownloadItem) : Fragment()
}
val formatTitles = formats.map {
if (it.format_note.contains("AUDIO_QUALITY_"))
it.format_note.replace("AUDIO_QUALITY_", "") +
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
else it.format_note +
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
it.format_note + if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
}
val format = view.findViewById<TextInputLayout>(R.id.format)
@ -166,6 +163,8 @@ class DownloadVideoFragment(private val downloadItem: DownloadItem) : Fragment()
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
downloadItem.format.format_note = formats[index].format_note
downloadItem.format.format_id = formats[index].format_id
downloadItem.format.filesize = formats[index].filesize
downloadViewModel.updateDownload(downloadItem)
}
val containers = requireContext().resources.getStringArray(R.array.video_containers)
@ -181,13 +180,15 @@ class DownloadVideoFragment(private val downloadItem: DownloadItem) : Fragment()
containers
)
)
val selectedContainer: String =
formats.find { downloadItem.format.format_note == it.format_note }?.container
?: sharedPreferences.getString("video_format", "DEFAULT")!!
var selectedContainer: String = downloadItem.format.container
if (selectedContainer.isEmpty()){
selectedContainer = sharedPreferences.getString("video_format", "Default")!!
}
containerAutoCompleteTextView!!.setText(selectedContainer, false)
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
downloadItem.ext = containers[index]
downloadItem.format.container = containers[index]
downloadViewModel.updateDownload(downloadItem)
}
val embedSubs = view.findViewById<Chip>(R.id.embed_subtitles)
@ -199,32 +200,6 @@ class DownloadVideoFragment(private val downloadItem: DownloadItem) : Fragment()
val saveThumbnail = view.findViewById<Chip>(R.id.save_thumbnail)
saveThumbnail!!.isChecked = sharedPreferences.getBoolean("write_thumbnail", false)
val cancel = view.findViewById<Button>(R.id.bottomsheet_cancel_button)
cancel!!.setOnClickListener {
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
}
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
download!!.setOnClickListener {
// for (i in selectedObjects!!.indices) {
// val vid = findVideo(
// selectedObjects!![i]!!.getURL()
// )
// vid!!.downloadedType = type
// updateDownloadingStatusOnResult(vid, type, true)
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
// downloadQueue!!.add(vid)
// }
// selectedObjects = ArrayList()
// homeAdapter!!.clearCheckedVideos()
// downloadFabs!!.visibility = View.GONE
// if (isStoragePermissionGranted) {
// mainActivity!!.startDownloadService(downloadQueue, listener)
// downloadQueue!!.clear()
// }
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
}
} catch (e: Exception) {
e.printStackTrace()
}

View file

@ -93,7 +93,7 @@ class DownloadWorker(
request.addOption("-x")
var audioQualityId : String = downloadItem.format.format_id
if (audioQualityId == "0") audioQualityId = "ba"
var ext = downloadItem.ext
var ext = downloadItem.format.container
request.addOption("-f", audioQualityId)
request.addOption("--audio-format", ext)
request.addOption("--embed-metadata")
@ -140,7 +140,7 @@ class DownloadWorker(
val formatArgument = StringBuilder(videoFormatID)
formatArgument.append("+bestaudio/best")
request.addOption("-f", formatArgument.toString())
var format = downloadItem.ext
var format = downloadItem.format.container
if (format.isNotEmpty()) {
format = sharedPreferences.getString("video_format", "")!!
if (format != "DEFAULT") request.addOption("--merge-output-format", format)

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_height="match_parent">
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content"
android:textSize="25sp"
android:padding="20dp"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:text="@string/configure_download" />
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@android:color/transparent"
app:tabMode="scrollable"
app:tabGravity="center"
android:id="@+id/download_tablayout" >
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/audio" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/video" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/run_command" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/download_viewpager" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:padding="10dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_cancel" />
<Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottom_sheet_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok"
app:icon="@drawable/ic_check"
android:autoLink="all"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -43,7 +43,52 @@
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:id="@+id/download_viewpager" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:padding="10dp"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:id="@+id/bottomsheet_schedule_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_clock" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_cancel" />
<Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottomsheet_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/download"
app:icon="@drawable/ic_down"
android:autoLink="all"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -105,7 +105,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="Mp4"
android:textStyle="bold"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="1.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/filesize"
app:layout_constraintTop_toBottomOf="@+id/downloads_download_button_type" />
@ -115,6 +119,24 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textStyle="bold"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="1.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/quality" />
<TextView
android:id="@+id/quality"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textStyle="bold"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="1.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

View file

@ -93,65 +93,22 @@
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/outputPath"
style="@style/Widget.Material3.TextInputLayout.FilledBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true"
android:hint="@string/save_dir"
style="@style/Widget.Material3.TextInputLayout.FilledBox">
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:inputType="text"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="10dp"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:id="@+id/bottomsheet_schedule_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_clock" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_cancel" />
<Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottomsheet_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/download"
app:icon="@drawable/ic_down"
android:autoLink="all"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -147,52 +147,6 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="10dp"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:id="@+id/bottomsheet_schedule_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_clock" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_cancel" />
<Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottomsheet_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/download"
app:icon="@drawable/ic_down"
android:autoLink="all"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -164,52 +164,6 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="10dp"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:id="@+id/bottomsheet_schedule_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_clock" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_cancel" />
<Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottomsheet_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/download"
app:icon="@drawable/ic_down"
android:autoLink="all"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/history_element_bottom_sheet"
style="@style/Widget.Material3.BottomSheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="vertical"
>
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content"
android:textSize="25sp"
android:textColor="?attr/colorOnSurface"
android:layout_height="wrap_content"
android:text="@string/configure_download" />
<View style="@style/Divider.Horizontal"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="end"
android:orientation="horizontal">
<Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_schedule_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
app:icon="@drawable/ic_cancel"
android:text="@string/cancel" />
<Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottomsheet_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok"
app:icon="@drawable/ic_check"
android:autoLink="all"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>