implemented fetching common formats for a playlist (WIP)
This commit is contained in:
parent
a91110d23e
commit
81a47c3407
18 changed files with 320 additions and 175 deletions
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.content.res.Resources
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
|
@ -24,7 +25,7 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class DownloadViewModel(application: Application) : AndroidViewModel(application) {
|
class DownloadViewModel(private val application: Application) : AndroidViewModel(application) {
|
||||||
private val repository : DownloadRepository
|
private val repository : DownloadRepository
|
||||||
private val sharedPreferences: SharedPreferences
|
private val sharedPreferences: SharedPreferences
|
||||||
private val commandTemplateDao: CommandTemplateDao
|
private val commandTemplateDao: CommandTemplateDao
|
||||||
|
|
@ -213,19 +214,39 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val c = commandTemplateDao.getFirst()
|
val c = commandTemplateDao.getFirst()
|
||||||
return Format(
|
return generateCommandFormat(c)
|
||||||
c.title,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
0,
|
|
||||||
c.content.replace("\n", " ")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generateCommandFormat(c: CommandTemplate) : Format {
|
||||||
|
return Format(
|
||||||
|
c.title,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
c.content.replace("\n", " ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGenericAudioFormats() : MutableList<Format>{
|
||||||
|
val audioFormats = application.resources.getStringArray(R.array.audio_formats)
|
||||||
|
val formats = mutableListOf<Format>()
|
||||||
|
val containerPreference = sharedPreferences.getString("audio_format", "Default")
|
||||||
|
audioFormats.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
|
||||||
|
return formats
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGenericVideoFormats() : MutableList<Format>{
|
||||||
|
val videoFormats = application.resources.getStringArray(R.array.video_formats)
|
||||||
|
val formats = mutableListOf<Format>()
|
||||||
|
val containerPreference = sharedPreferences.getString("video_format", "Default")
|
||||||
|
videoFormats.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
|
||||||
|
return formats
|
||||||
|
}
|
||||||
|
|
||||||
fun getLatestCommandTemplateAsFormat() : Format {
|
fun getLatestCommandTemplateAsFormat() : Format {
|
||||||
val t = commandTemplateDao.getFirst()
|
val t = commandTemplateDao.getFirst()
|
||||||
return Format(t.title, "", "", "", "", 0, t.content)
|
return Format(t.title, "", "", "", "", 0, t.content)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
private lateinit var onDownloadItemUpdateListener: OnDownloadItemUpdateListener
|
private lateinit var onDownloadItemUpdateListener: OnDownloadItemUpdateListener
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
|
@ -71,7 +70,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
behavior = BottomSheetBehavior.from(view.parent as View)
|
behavior = BottomSheetBehavior.from(view.parent as View)
|
||||||
val displayMetrics = DisplayMetrics()
|
val displayMetrics = DisplayMetrics()
|
||||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
behavior.peekHeight = displayMetrics.heightPixels - 700
|
behavior.peekHeight = displayMetrics.heightPixels - 400
|
||||||
}
|
}
|
||||||
|
|
||||||
tabLayout = view.findViewById(R.id.download_tablayout)
|
tabLayout = view.findViewById(R.id.download_tablayout)
|
||||||
|
|
@ -82,7 +81,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
overScrollMode = View.OVER_SCROLL_NEVER
|
overScrollMode = View.OVER_SCROLL_NEVER
|
||||||
}
|
}
|
||||||
|
|
||||||
val fragments = mutableListOf<Fragment>(DownloadAudioFragment(resultItem, downloadItem), DownloadVideoFragment(resultItem, downloadItem))
|
val fragments = mutableListOf(DownloadAudioFragment(resultItem, downloadItem), DownloadVideoFragment(resultItem, downloadItem))
|
||||||
var commandTemplateNr = 0
|
var commandTemplateNr = 0
|
||||||
lifecycleScope.launch{
|
lifecycleScope.launch{
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
|
|
@ -211,10 +210,12 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private fun cleanUp(){
|
private fun cleanUp(){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("configureDownloadSingleSheet")!!).commit()
|
kotlin.runCatching {
|
||||||
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("configureDownloadSingleSheet")!!).commit()
|
||||||
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
||||||
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -570,9 +570,11 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
|
|
||||||
|
|
||||||
private fun cleanUp(){
|
private fun cleanUp(){
|
||||||
player.stop()
|
kotlin.runCatching {
|
||||||
cache.release()
|
player.stop()
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("cutVideoSheet")!!).commit()
|
cache.release()
|
||||||
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("cutVideoSheet")!!).commit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,42 +123,40 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
|
|
||||||
var formats = mutableListOf<Format>()
|
var formats = mutableListOf<Format>()
|
||||||
formats.addAll(resultItem.formats.filter { it.format_note.contains("audio", ignoreCase = true) })
|
formats.addAll(resultItem.formats.filter { it.format_note.contains("audio", ignoreCase = true) })
|
||||||
val audioFormats = resources.getStringArray(R.array.audio_formats)
|
if (formats.isEmpty()) formats.addAll(downloadItem.allFormats.filter { it.format_note.contains("audio", ignoreCase = true) })
|
||||||
|
|
||||||
val containers = requireContext().resources.getStringArray(R.array.audio_containers)
|
val containers = requireContext().resources.getStringArray(R.array.audio_containers)
|
||||||
val containerPreference = sharedPreferences.getString("audio_format", getString(R.string.defaultValue))
|
val containerPreference = sharedPreferences.getString("audio_format", "Default")
|
||||||
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
||||||
val containerAutoCompleteTextView =
|
val containerAutoCompleteTextView =
|
||||||
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
||||||
|
|
||||||
if (formats.isEmpty()) {
|
if (formats.isEmpty()) formats = downloadViewModel.getGenericAudioFormats()
|
||||||
audioFormats.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val formatCard = view.findViewById<ConstraintLayout>(R.id.format_card_constraintLayout)
|
val formatCard = view.findViewById<ConstraintLayout>(R.id.format_card_constraintLayout)
|
||||||
val chosenFormat = downloadItem.format
|
val chosenFormat = downloadItem.format
|
||||||
uiUtil.populateFormatCard(formatCard, chosenFormat)
|
uiUtil.populateFormatCard(formatCard, chosenFormat)
|
||||||
val listener = object : OnFormatClickListener {
|
val listener = object : OnFormatClickListener {
|
||||||
override fun onFormatClick(allFormats: List<Format>, item: Format) {
|
override fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>) {
|
||||||
downloadItem.format = item
|
downloadItem.format = item.first()
|
||||||
uiUtil.populateFormatCard(formatCard, item)
|
uiUtil.populateFormatCard(formatCard, item.first())
|
||||||
if (containers.contains(item.container)){
|
if (containers.contains(item.first().container)){
|
||||||
downloadItem.format.container = item.container
|
downloadItem.format.container = item.first().container
|
||||||
containerAutoCompleteTextView.setText(item.container, false)
|
containerAutoCompleteTextView.setText(item.first().container, false)
|
||||||
}
|
}
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
resultItem.formats.removeAll(formats.toSet())
|
resultItem.formats.removeAll(formats.toSet())
|
||||||
resultItem.formats.addAll(allFormats)
|
resultItem.formats.addAll(allFormats.first())
|
||||||
resultViewModel.update(resultItem)
|
resultViewModel.update(resultItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formats = allFormats.toMutableList()
|
formats = allFormats.first().toMutableList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formatCard.setOnClickListener{_ ->
|
formatCard.setOnClickListener{_ ->
|
||||||
if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
||||||
val bottomSheet = FormatSelectionBottomSheetDialog(downloadItem, formats, listener)
|
val bottomSheet = FormatSelectionBottomSheetDialog(listOf(downloadItem), listOf(formats), listener)
|
||||||
bottomSheet.show(parentFragmentManager, "formatSheet")
|
bottomSheet.show(parentFragmentManager, "formatSheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.viewpager.widget.ViewPager
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.DBManager
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
|
|
@ -30,6 +31,8 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayout.TabLayoutOnPageChangeListener
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
@ -64,7 +67,7 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
behavior = BottomSheetBehavior.from(view.parent as View)
|
behavior = BottomSheetBehavior.from(view.parent as View)
|
||||||
val displayMetrics = DisplayMetrics()
|
val displayMetrics = DisplayMetrics()
|
||||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
behavior.peekHeight = displayMetrics.heightPixels - 700
|
behavior.peekHeight = displayMetrics.heightPixels - 400
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -158,7 +161,6 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
||||||
download!!.setOnClickListener {
|
download!!.setOnClickListener {
|
||||||
val item: DownloadItem = getDownloadItem();
|
val item: DownloadItem = getDownloadItem();
|
||||||
|
|
@ -208,14 +210,16 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
|
|
||||||
|
|
||||||
private fun cleanUp(){
|
private fun cleanUp(){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadSingleSheet")!!).commit()
|
kotlin.runCatching {
|
||||||
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadSingleSheet")!!).commit()
|
||||||
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
||||||
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activity is ShareActivity){
|
||||||
|
(activity as ShareActivity).finish()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (activity is ShareActivity){
|
|
||||||
(activity as ShareActivity).finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.core.view.get
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
|
@ -21,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.adapter.ConfigureMultipleDownloadsAdapter
|
import com.deniscerri.ytdlnis.adapter.ConfigureMultipleDownloadsAdapter
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
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.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
|
@ -34,7 +35,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.asFlow
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -51,6 +51,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
private lateinit var behavior: BottomSheetBehavior<View>
|
private lateinit var behavior: BottomSheetBehavior<View>
|
||||||
private lateinit var fileUtil: FileUtil
|
private lateinit var fileUtil: FileUtil
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
|
private lateinit var bottomAppBar: BottomAppBar
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -68,7 +69,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi", "NotifyDataSetChanged")
|
||||||
override fun setupDialog(dialog: Dialog, style: Int) {
|
override fun setupDialog(dialog: Dialog, style: Int) {
|
||||||
super.setupDialog(dialog, style)
|
super.setupDialog(dialog, style)
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.download_multiple_bottom_sheet, null)
|
val view = LayoutInflater.from(context).inflate(R.layout.download_multiple_bottom_sheet, null)
|
||||||
|
|
@ -116,7 +117,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
val bottomAppBar = view.findViewById<BottomAppBar>(R.id.bottomAppBar)
|
bottomAppBar = view.findViewById(R.id.bottomAppBar)
|
||||||
val preferredDownloadType = bottomAppBar.menu.findItem(R.id.preferred_download_type)
|
val preferredDownloadType = bottomAppBar.menu.findItem(R.id.preferred_download_type)
|
||||||
when(items.first().type){
|
when(items.first().type){
|
||||||
DownloadViewModel.Type.audio -> {
|
DownloadViewModel.Type.audio -> {
|
||||||
|
|
@ -131,7 +132,19 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomAppBar!!.setOnMenuItemClickListener { m: MenuItem ->
|
val formatListener = object : OnFormatClickListener {
|
||||||
|
override fun onFormatClick(allFormats: List<List<Format>>, selectedFormats: List<Format>) {
|
||||||
|
items.forEachIndexed { index, it ->
|
||||||
|
it.allFormats.clear()
|
||||||
|
it.allFormats.addAll(allFormats[index])
|
||||||
|
it.format = selectedFormats[index]
|
||||||
|
}
|
||||||
|
listAdapter.submitList(items.toList())
|
||||||
|
listAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bottomAppBar.setOnMenuItemClickListener { m: MenuItem ->
|
||||||
when (m.itemId) {
|
when (m.itemId) {
|
||||||
R.id.folder -> {
|
R.id.folder -> {
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
|
@ -166,6 +179,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
listAdapter.notifyDataSetChanged()
|
listAdapter.notifyDataSetChanged()
|
||||||
preferredDownloadType.setIcon(R.drawable.baseline_audio_file_24)
|
preferredDownloadType.setIcon(R.drawable.baseline_audio_file_24)
|
||||||
|
bottomAppBar.menu[2].icon?.alpha = 255
|
||||||
bottomSheet.cancel()
|
bottomSheet.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,6 +188,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
listAdapter.notifyDataSetChanged()
|
listAdapter.notifyDataSetChanged()
|
||||||
preferredDownloadType.setIcon(R.drawable.baseline_video_file_24)
|
preferredDownloadType.setIcon(R.drawable.baseline_video_file_24)
|
||||||
|
bottomAppBar.menu[2].icon?.alpha = 255
|
||||||
bottomSheet.cancel()
|
bottomSheet.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,11 +200,15 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
listAdapter.notifyDataSetChanged()
|
listAdapter.notifyDataSetChanged()
|
||||||
preferredDownloadType.setIcon(R.drawable.baseline_insert_drive_file_24)
|
preferredDownloadType.setIcon(R.drawable.baseline_insert_drive_file_24)
|
||||||
|
bottomAppBar.menu[2].icon?.alpha = 255
|
||||||
bottomSheet.cancel()
|
bottomSheet.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomSheet.show()
|
bottomSheet.show()
|
||||||
|
val displayMetrics = DisplayMetrics()
|
||||||
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
|
bottomSheet.behavior.peekHeight = displayMetrics.heightPixels
|
||||||
bottomSheet.window!!.setLayout(
|
bottomSheet.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
@ -198,47 +217,48 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
|
|
||||||
}
|
}
|
||||||
R.id.format -> {
|
R.id.format -> {
|
||||||
if (results.first()!!.formats.isEmpty()){
|
if (! items.all { it.type == items[0].type }){
|
||||||
|
Toast.makeText(requireContext(), getString(R.string.format_filtering_hint), Toast.LENGTH_SHORT).show()
|
||||||
|
}else{
|
||||||
|
if (items.first().type == DownloadViewModel.Type.command){
|
||||||
|
lifecycleScope.launch {
|
||||||
|
uiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel) {
|
||||||
|
val format = downloadViewModel.generateCommandFormat(it)
|
||||||
|
items.forEach { f ->
|
||||||
|
f.format = format
|
||||||
|
}
|
||||||
|
listAdapter.submitList(items.toList())
|
||||||
|
listAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val flatFormatCollection = items.map { it.allFormats }.flatten()
|
||||||
|
val commonFormats = withContext(Dispatchers.IO){
|
||||||
|
flatFormatCollection.groupingBy { it.format_id }.eachCount().filter { it.value == items.size }.mapValues { flatFormatCollection.first { f -> f.format_id == it.key } }.map { it.value }
|
||||||
|
}
|
||||||
|
|
||||||
|
val formats = if (commonFormats.isNotEmpty() && items.none{it.allFormats.isEmpty()}) {
|
||||||
|
items.map { it.allFormats }
|
||||||
|
}else{
|
||||||
|
when(items.first().type){
|
||||||
|
DownloadViewModel.Type.audio -> listOf<List<Format>>(downloadViewModel.getGenericAudioFormats())
|
||||||
|
else -> listOf<List<Format>>(downloadViewModel.getGenericVideoFormats())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val bottomSheet = FormatSelectionBottomSheetDialog(items, formats, formatListener)
|
||||||
|
bottomSheet.show(parentFragmentManager, "formatSheet")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// val formatListCollection = items.map { it.format }
|
|
||||||
// val commonFormats = getCommonFormats(formatListCollection)
|
|
||||||
//
|
|
||||||
// val listener = object : OnFormatClickListener {
|
|
||||||
// override fun onFormatClick(allFormats: List<Format>, item: Format) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
|
||||||
// val bottomSheet = FormatSelectionBottomSheetDialog(null, commonFormats.toList(), listener)
|
|
||||||
// bottomSheet.show(parentFragmentManager, "formatSheet")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
val itemsLiveData = items.asFlow()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun getCommonFormats(vararg lists: MutableList<List<Format>>): Set<Format> {
|
|
||||||
// val commons: MutableList<Format> = mutableListOf()
|
|
||||||
// commons.addAll(lists[1])
|
|
||||||
// {
|
|
||||||
// lists[1].forEach {
|
|
||||||
// commons.retainAll(it)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (numbers in list) {
|
|
||||||
// result = Sets.intersection(result, Sets.newHashSet(numbers))
|
|
||||||
// }
|
|
||||||
// return result
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
private var pathResultLauncher = registerForActivityResult(
|
private var pathResultLauncher = registerForActivityResult(
|
||||||
ActivityResultContracts.StartActivityForResult()
|
ActivityResultContracts.StartActivityForResult()
|
||||||
) { result ->
|
) { result ->
|
||||||
|
|
@ -268,9 +288,11 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cleanup(){
|
private fun cleanup(){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadMultipleSheet")!!).commit()
|
kotlin.runCatching {
|
||||||
if (parentFragmentManager.fragments.size == 1){
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadMultipleSheet")!!).commit()
|
||||||
(activity as ShareActivity).finish()
|
if (parentFragmentManager.fragments.size == 1){
|
||||||
|
(activity as ShareActivity).finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,7 +320,11 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
override fun onDownloadItemUpdate(resultItemID: Long, item: DownloadItem) {
|
override fun onDownloadItemUpdate(resultItemID: Long, item: DownloadItem) {
|
||||||
val i = items.indexOf(items.find { it.url == item.url })
|
val i = items.indexOf(items.find { it.url == item.url })
|
||||||
items[i] = item
|
items[i] = item
|
||||||
Log.e("aa", items.toList().toString())
|
if (! items.all { it.type == items[0].type }){
|
||||||
|
bottomAppBar.menu[2].icon?.alpha = 30
|
||||||
|
}else{
|
||||||
|
bottomAppBar.menu[2].icon?.alpha = 255
|
||||||
|
}
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,44 +129,42 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
|
|
||||||
var formats = mutableListOf<Format>()
|
var formats = mutableListOf<Format>()
|
||||||
formats.addAll(resultItem.formats.filter { !it.format_note.contains("audio", ignoreCase = true) })
|
formats.addAll(resultItem.formats.filter { !it.format_note.contains("audio", ignoreCase = true) })
|
||||||
val videoFormats = resources.getStringArray(R.array.video_formats)
|
if (formats.isEmpty()) formats.addAll(downloadItem.allFormats.filter { !it.format_note.contains("audio", ignoreCase = true) })
|
||||||
|
|
||||||
val containers = requireContext().resources.getStringArray(R.array.video_containers)
|
val containers = requireContext().resources.getStringArray(R.array.video_containers)
|
||||||
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
||||||
val containerAutoCompleteTextView =
|
val containerAutoCompleteTextView =
|
||||||
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
||||||
val containerPreference = sharedPreferences.getString("video_format", getString(R.string.defaultValue))
|
val containerPreference = sharedPreferences.getString("video_format", "Default")
|
||||||
|
|
||||||
if (formats.isEmpty()) {
|
if (formats.isEmpty()) formats = downloadViewModel.getGenericVideoFormats()
|
||||||
videoFormats.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val formatCard = view.findViewById<ConstraintLayout>(R.id.format_card_constraintLayout)
|
val formatCard = view.findViewById<ConstraintLayout>(R.id.format_card_constraintLayout)
|
||||||
|
|
||||||
val chosenFormat = downloadItem.format
|
val chosenFormat = downloadItem.format
|
||||||
uiUtil.populateFormatCard(formatCard, chosenFormat)
|
uiUtil.populateFormatCard(formatCard, chosenFormat)
|
||||||
val listener = object : OnFormatClickListener {
|
val listener = object : OnFormatClickListener {
|
||||||
override fun onFormatClick(allFormats: List<Format>, item: Format) {
|
override fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>) {
|
||||||
downloadItem.format = item
|
downloadItem.format = item.first()
|
||||||
|
|
||||||
if (containers.contains(item.container)){
|
if (containers.contains(item.first().container)){
|
||||||
downloadItem.format.container = item.container
|
downloadItem.format.container = item.first().container
|
||||||
containerAutoCompleteTextView.setText(item.container, false)
|
containerAutoCompleteTextView.setText(item.first().container, false)
|
||||||
}
|
}
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
resultItem.formats.removeAll(formats.toSet())
|
resultItem.formats.removeAll(formats.toSet())
|
||||||
resultItem.formats.addAll(allFormats)
|
resultItem.formats.addAll(allFormats.first())
|
||||||
resultViewModel.update(resultItem)
|
resultViewModel.update(resultItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formats = allFormats.toMutableList()
|
formats = allFormats.first().toMutableList()
|
||||||
uiUtil.populateFormatCard(formatCard, item)
|
uiUtil.populateFormatCard(formatCard, item.first())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formatCard.setOnClickListener{
|
formatCard.setOnClickListener{
|
||||||
if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
||||||
val bottomSheet = FormatSelectionBottomSheetDialog(downloadItem, formats, listener)
|
val bottomSheet = FormatSelectionBottomSheetDialog(listOf(downloadItem), listOf(formats), listener)
|
||||||
bottomSheet.show(parentFragmentManager, "formatSheet")
|
bottomSheet.show(parentFragmentManager, "formatSheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.app.Activity
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Looper
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
|
@ -27,20 +28,25 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
|
||||||
class FormatSelectionBottomSheetDialog(private val item: DownloadItem?, private var formats: List<Format>, private val listener: OnFormatClickListener) : BottomSheetDialogFragment() {
|
class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, private var formats: List<List<Format>>, private val listener: OnFormatClickListener) : BottomSheetDialogFragment() {
|
||||||
private lateinit var behavior: BottomSheetBehavior<View>
|
private lateinit var behavior: BottomSheetBehavior<View>
|
||||||
private lateinit var fileUtil: FileUtil
|
private lateinit var fileUtil: FileUtil
|
||||||
private lateinit var infoUtil: InfoUtil
|
private lateinit var infoUtil: InfoUtil
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
private lateinit var formatCollection: MutableList<List<Format>>
|
||||||
|
private lateinit var chosenFormats: List<Format>
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
fileUtil = FileUtil()
|
fileUtil = FileUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
uiUtil = UiUtil(fileUtil)
|
||||||
infoUtil = InfoUtil(requireActivity().applicationContext)
|
infoUtil = InfoUtil(requireActivity().applicationContext)
|
||||||
|
formatCollection = mutableListOf()
|
||||||
|
chosenFormats = listOf()
|
||||||
sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,10 +67,35 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem?, private
|
||||||
val linearLayout = view.findViewById<LinearLayout>(R.id.format_list_linear_layout)
|
val linearLayout = view.findViewById<LinearLayout>(R.id.format_list_linear_layout)
|
||||||
val shimmers = view.findViewById<ShimmerFrameLayout>(R.id.format_list_shimmer)
|
val shimmers = view.findViewById<ShimmerFrameLayout>(R.id.format_list_shimmer)
|
||||||
shimmers.visibility = View.GONE
|
shimmers.visibility = View.GONE
|
||||||
addFormatsToView(linearLayout)
|
|
||||||
|
if (items.size > 1){
|
||||||
|
val hasGenericFormats = when(items.first()!!.type){
|
||||||
|
Type.audio -> formats.flatten().size == resources.getStringArray(R.array.audio_formats).size
|
||||||
|
else -> formats.flatten().size == resources.getStringArray(R.array.video_formats).size
|
||||||
|
}
|
||||||
|
if (!hasGenericFormats){
|
||||||
|
formatCollection.addAll(formats)
|
||||||
|
val flattenFormats = formats.flatten()
|
||||||
|
val commonFormats = flattenFormats.groupingBy { it.format_id }.eachCount().filter { it.value == items.size }.mapValues { flattenFormats.first { f -> f.format_id == it.key } }.map { it.value }
|
||||||
|
commonFormats.forEach {
|
||||||
|
it.filesize =
|
||||||
|
flattenFormats.filter { f -> f.format_id == it.format_id }
|
||||||
|
.sumOf { itt -> itt.filesize }
|
||||||
|
}
|
||||||
|
chosenFormats = commonFormats
|
||||||
|
}else{
|
||||||
|
chosenFormats = formats.flatten()
|
||||||
|
}
|
||||||
|
addFormatsToView(linearLayout)
|
||||||
|
}else{
|
||||||
|
chosenFormats = formats.flatten()
|
||||||
|
addFormatsToView(linearLayout)
|
||||||
|
}
|
||||||
|
|
||||||
val refreshBtn = view.findViewById<Button>(R.id.format_refresh)
|
val refreshBtn = view.findViewById<Button>(R.id.format_refresh)
|
||||||
if (formats.none { it.filesize == 0L } || item == null) refreshBtn.visibility = View.GONE
|
if (formats.flatten().none { it.filesize == 0L } || items.isEmpty()) refreshBtn.visibility = View.GONE
|
||||||
|
|
||||||
|
|
||||||
refreshBtn.setOnClickListener {
|
refreshBtn.setOnClickListener {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
|
|
@ -73,15 +104,45 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem?, private
|
||||||
shimmers.visibility = View.VISIBLE
|
shimmers.visibility = View.VISIBLE
|
||||||
shimmers.startShimmer()
|
shimmers.startShimmer()
|
||||||
|
|
||||||
val res = withContext(Dispatchers.IO){
|
//simple download
|
||||||
infoUtil.getFormats(item!!.url)
|
if (items.size == 1){
|
||||||
|
val res = withContext(Dispatchers.IO){
|
||||||
|
infoUtil.getFormats(items.first()!!.url)
|
||||||
|
}
|
||||||
|
chosenFormats = res.formats.filter { it.filesize != 0L }
|
||||||
|
chosenFormats = when(items.first()?.type){
|
||||||
|
Type.audio -> chosenFormats.filter { it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
else -> chosenFormats.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
}
|
||||||
|
if (chosenFormats.isEmpty()) throw Exception()
|
||||||
|
//playlist format filtering
|
||||||
|
}else{
|
||||||
|
var progress = "0/${items.size}"
|
||||||
|
refreshBtn.text = progress
|
||||||
|
withContext(Dispatchers.IO){
|
||||||
|
infoUtil.getFormatsMultiple(items.map { it!!.url }) {
|
||||||
|
lifecycleScope.launch(Dispatchers.Main){
|
||||||
|
progress = "${formatCollection.size}/${items.size}"
|
||||||
|
refreshBtn.text = progress
|
||||||
|
}
|
||||||
|
formatCollection.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val flatFormatCollection = formatCollection.flatten()
|
||||||
|
val commonFormats = flatFormatCollection.groupingBy { it.format_id }.eachCount().filter { it.value == items.size }.mapValues { flatFormatCollection.first { f -> f.format_id == it.key } }.map { it.value }
|
||||||
|
chosenFormats = commonFormats.filter { it.filesize != 0L }.mapTo(mutableListOf()) {it.copy()}
|
||||||
|
chosenFormats = when(items.first()?.type){
|
||||||
|
Type.audio -> chosenFormats.filter { it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
else -> chosenFormats.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
}
|
||||||
|
if (chosenFormats.isEmpty()) throw Exception()
|
||||||
|
chosenFormats.forEach {
|
||||||
|
it.filesize =
|
||||||
|
flatFormatCollection.filter { f -> f.format_id == it.format_id }
|
||||||
|
.sumOf { itt -> itt.filesize }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
formats = res.formats.filter { it.filesize != 0L }
|
|
||||||
formats = when(item?.type){
|
|
||||||
Type.audio -> formats.filter { it.format_note.contains("audio", ignoreCase = true) }
|
|
||||||
else -> formats.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
|
||||||
}
|
|
||||||
if (formats.isEmpty()) throw Exception()
|
|
||||||
addFormatsToView(linearLayout)
|
addFormatsToView(linearLayout)
|
||||||
refreshBtn.visibility = View.GONE
|
refreshBtn.visibility = View.GONE
|
||||||
|
|
||||||
|
|
@ -90,6 +151,7 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem?, private
|
||||||
shimmers.stopShimmer()
|
shimmers.stopShimmer()
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
refreshBtn.isEnabled = true
|
refreshBtn.isEnabled = true
|
||||||
|
refreshBtn.text = getString(R.string.update_formats)
|
||||||
linearLayout.visibility = View.VISIBLE
|
linearLayout.visibility = View.VISIBLE
|
||||||
shimmers.visibility = View.GONE
|
shimmers.visibility = View.GONE
|
||||||
shimmers.stopShimmer()
|
shimmers.stopShimmer()
|
||||||
|
|
@ -99,20 +161,27 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem?, private
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sharedPreferences.getBoolean("update_formats", false) && refreshBtn.isVisible){
|
if (sharedPreferences.getBoolean("update_formats", false) && refreshBtn.isVisible && items.size == 1){
|
||||||
refreshBtn.performClick()
|
refreshBtn.performClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFormatsToView(linearLayout: LinearLayout){
|
private fun addFormatsToView(linearLayout: LinearLayout){
|
||||||
linearLayout.removeAllViews()
|
linearLayout.removeAllViews()
|
||||||
Log.e("aa", formats.toString())
|
Log.e("aa", chosenFormats.toString())
|
||||||
for (i in formats.lastIndex downTo 0){
|
for (i in chosenFormats.lastIndex downTo 0){
|
||||||
val format = formats[i]
|
val format = chosenFormats[i]
|
||||||
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
||||||
uiUtil.populateFormatCard(formatItem as ConstraintLayout, format)
|
uiUtil.populateFormatCard(formatItem as ConstraintLayout, format)
|
||||||
formatItem.setOnClickListener{_ ->
|
formatItem.setOnClickListener{_ ->
|
||||||
listener.onFormatClick(formats, format)
|
if (items.size == 1){
|
||||||
|
listener.onFormatClick(List(items.size){chosenFormats}, listOf(format))
|
||||||
|
}else{
|
||||||
|
val selectedFormats = mutableListOf<Format>()
|
||||||
|
formatCollection.forEach {
|
||||||
|
selectedFormats.add(it.first{ f -> f.format_id == format.format_id})
|
||||||
|
}
|
||||||
|
listener.onFormatClick(formatCollection, selectedFormats)
|
||||||
|
}
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
formatItem.setOnLongClickListener {
|
formatItem.setOnLongClickListener {
|
||||||
|
|
@ -141,10 +210,12 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem?, private
|
||||||
|
|
||||||
|
|
||||||
private fun cleanUp(){
|
private fun cleanUp(){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("formatSheet")!!).commit()
|
kotlin.runCatching {
|
||||||
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("formatSheet")!!).commit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnFormatClickListener{
|
interface OnFormatClickListener{
|
||||||
fun onFormatClick(allFormats: List<Format>, item: Format)
|
fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>)
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +179,11 @@ class SelectPlaylistItemsBottomSheetDialog(private val items: List<ResultItem?>,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cleanup(){
|
private fun cleanup(){
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadPlaylistSheet")!!).commit()
|
kotlin.runCatching {
|
||||||
if (parentFragmentManager.fragments.size == 1){
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadPlaylistSheet")!!).commit()
|
||||||
(activity as ShareActivity).finish()
|
if (parentFragmentManager.fragments.size == 1){
|
||||||
|
(activity as ShareActivity).finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
openFile.visibility = View.GONE
|
openFile.visibility = View.GONE
|
||||||
|
|
||||||
bottomSheet.show()
|
bottomSheet.show()
|
||||||
|
bottomSheet.behavior.peekHeight = 512
|
||||||
bottomSheet.window!!.setLayout(
|
bottomSheet.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
openFile.visibility = View.GONE
|
openFile.visibility = View.GONE
|
||||||
|
|
||||||
bottomSheet.show()
|
bottomSheet.show()
|
||||||
|
bottomSheet.behavior.peekHeight = 512
|
||||||
bottomSheet.window!!.setLayout(
|
bottomSheet.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
else redownload.visibility = GONE
|
else redownload.visibility = GONE
|
||||||
|
|
||||||
bottomSheet!!.show()
|
bottomSheet!!.show()
|
||||||
|
bottomSheet!!.behavior.peekHeight = 512
|
||||||
bottomSheet!!.window!!.setLayout(
|
bottomSheet!!.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
redownload!!.visibility = View.GONE
|
redownload!!.visibility = View.GONE
|
||||||
|
|
||||||
bottomSheet.show()
|
bottomSheet.show()
|
||||||
|
bottomSheet.behavior.peekHeight = 512
|
||||||
bottomSheet.window!!.setLayout(
|
bottomSheet.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.UiUtil
|
||||||
import com.deniscerri.ytdlnis.work.TerminalDownloadWorker
|
import com.deniscerri.ytdlnis.work.TerminalDownloadWorker
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.bottomappbar.BottomAppBar
|
import com.google.android.material.bottomappbar.BottomAppBar
|
||||||
|
|
@ -55,6 +57,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
private lateinit var downloadFile : File
|
private lateinit var downloadFile : File
|
||||||
private lateinit var observer: FileObserver
|
private lateinit var observer: FileObserver
|
||||||
private lateinit var imm : InputMethodManager
|
private lateinit var imm : InputMethodManager
|
||||||
|
private lateinit var uiUtil: UiUtil
|
||||||
var context: Context? = null
|
var context: Context? = null
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -65,6 +68,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
|
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
|
||||||
if (! downloadFile.exists()) downloadFile.createNewFile()
|
if (! downloadFile.exists()) downloadFile.createNewFile()
|
||||||
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
uiUtil = UiUtil(FileUtil())
|
||||||
|
|
||||||
context = baseContext
|
context = baseContext
|
||||||
scrollView = findViewById(R.id.custom_command_scrollview)
|
scrollView = findViewById(R.id.custom_command_scrollview)
|
||||||
|
|
@ -89,7 +93,17 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
bottomAppBar.setOnMenuItemClickListener {
|
bottomAppBar.setOnMenuItemClickListener {
|
||||||
when(it.itemId){
|
when(it.itemId){
|
||||||
R.id.command_templates -> showCommandTemplates()
|
R.id.command_templates -> {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
uiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template ->
|
||||||
|
input!!.text.insert(input!!.selectionStart, template.content + " ")
|
||||||
|
input!!.postDelayed({
|
||||||
|
input!!.requestFocus()
|
||||||
|
imm.showSoftInput(input!!, 0)
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
R.id.shortcuts -> showShortcuts()
|
R.id.shortcuts -> showShortcuts()
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
|
|
@ -210,41 +224,6 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
fab!!.setIconResource(R.drawable.ic_cancel)
|
fab!!.setIconResource(R.drawable.ic_cancel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showCommandTemplates(){
|
|
||||||
lifecycleScope.launch {
|
|
||||||
val bottomSheet = BottomSheetDialog(this@TerminalActivity)
|
|
||||||
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
|
||||||
bottomSheet.setContentView(R.layout.command_template_list)
|
|
||||||
|
|
||||||
val linearLayout = bottomSheet.findViewById<LinearLayout>(R.id.command_list_linear_layout)
|
|
||||||
val list = withContext(Dispatchers.IO){
|
|
||||||
commandTemplateViewModel.getAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
linearLayout!!.removeAllViews()
|
|
||||||
list.forEach {template ->
|
|
||||||
val item = layoutInflater.inflate(R.layout.command_template_item, linearLayout, false) as ConstraintLayout
|
|
||||||
item.findViewById<TextView>(R.id.title).text = template.title
|
|
||||||
item.findViewById<TextView>(R.id.content).text = template.content
|
|
||||||
item.setOnClickListener {
|
|
||||||
input!!.text.insert(input!!.selectionStart, template.content + " ")
|
|
||||||
bottomSheet.cancel()
|
|
||||||
input!!.postDelayed({
|
|
||||||
input!!.requestFocus()
|
|
||||||
imm.showSoftInput(input!!, 0)
|
|
||||||
}, 200)
|
|
||||||
}
|
|
||||||
linearLayout.addView(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
bottomSheet.show()
|
|
||||||
bottomSheet.window!!.setLayout(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showShortcuts() {
|
private fun showShortcuts() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val bottomSheet = BottomSheetDialog(this@TerminalActivity)
|
val bottomSheet = BottomSheetDialog(this@TerminalActivity)
|
||||||
|
|
|
||||||
|
|
@ -504,7 +504,7 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFormatsTest(urls: List<String>, progress: (progress: List<Format>) -> Unit){
|
fun getFormatsMultiple(urls: List<String>, progress: (progress: List<Format>) -> Unit){
|
||||||
init()
|
init()
|
||||||
val urlsFile = File(context.cacheDir, "urls.txt")
|
val urlsFile = File(context.cacheDir, "urls.txt")
|
||||||
urlsFile.delete()
|
urlsFile.delete()
|
||||||
|
|
@ -524,26 +524,30 @@ class InfoUtil(private val context: Context) {
|
||||||
request.addOption("--cookies", cookiesFile.absolutePath)
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request){ progress, _, line ->
|
YoutubeDL.getInstance().execute(request){ progress, _, line ->
|
||||||
val formats = mutableListOf<Format>()
|
try{
|
||||||
val listOfStrings = JSONArray(line)
|
val formats = mutableListOf<Format>()
|
||||||
for (f in 0 until listOfStrings.length()){
|
val listOfStrings = JSONArray(line)
|
||||||
val format = listOfStrings.get(f) as JSONObject
|
for (f in 0 until listOfStrings.length()){
|
||||||
try{
|
val format = listOfStrings.get(f) as JSONObject
|
||||||
if (format.getString("filesize") == "None") continue
|
try{
|
||||||
}catch (e: Exception) { continue }
|
if (format.getString("filesize") == "None") continue
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
}catch (e: Exception) { continue }
|
||||||
if (formatProper.filesize > 0){
|
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
if ( !formatProper.format_note.contains("audio only", true)) {
|
if (formatProper.filesize > 0){
|
||||||
formatProper.format_note = format.getString("format_note")
|
if ( !formatProper.format_note.contains("audio only", true)) {
|
||||||
}else{
|
formatProper.format_note = format.getString("format_note")
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
}else{
|
||||||
|
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||||
|
}
|
||||||
|
formatProper.container = format.getString("ext")
|
||||||
|
formats.add(formatProper)
|
||||||
}
|
}
|
||||||
formatProper.container = format.getString("ext")
|
|
||||||
formats.add(formatProper)
|
|
||||||
}
|
}
|
||||||
|
progress(formats)
|
||||||
|
}catch (e: Exception){
|
||||||
|
progress(emptyList())
|
||||||
}
|
}
|
||||||
progress(formats)
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Looper.prepare().run {
|
Looper.prepare().run {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
|
@ -21,6 +22,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.CommandTemplate
|
import com.deniscerri.ytdlnis.database.models.CommandTemplate
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
|
|
@ -35,6 +37,9 @@ import com.google.android.material.datepicker.MaterialDatePicker
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.google.android.material.timepicker.MaterialTimePicker
|
import com.google.android.material.timepicker.MaterialTimePicker
|
||||||
import com.google.android.material.timepicker.TimeFormat
|
import com.google.android.material.timepicker.TimeFormat
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
@ -282,4 +287,33 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
}
|
}
|
||||||
datePicker.show(fragmentManager, "datepicker")
|
datePicker.show(fragmentManager, "datepicker")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun showCommandTemplates(activity: Activity, commandTemplateViewModel: CommandTemplateViewModel, itemSelected: (itemSelected: CommandTemplate) -> Unit) {
|
||||||
|
val bottomSheet = BottomSheetDialog(activity)
|
||||||
|
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
bottomSheet.setContentView(R.layout.command_template_list)
|
||||||
|
|
||||||
|
val linearLayout = bottomSheet.findViewById<LinearLayout>(R.id.command_list_linear_layout)
|
||||||
|
val list = withContext(Dispatchers.IO){
|
||||||
|
commandTemplateViewModel.getAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
linearLayout!!.removeAllViews()
|
||||||
|
list.forEach {template ->
|
||||||
|
val item = activity.layoutInflater.inflate(R.layout.command_template_item, linearLayout, false) as ConstraintLayout
|
||||||
|
item.findViewById<TextView>(R.id.title).text = template.title
|
||||||
|
item.findViewById<TextView>(R.id.content).text = template.content
|
||||||
|
item.setOnClickListener {
|
||||||
|
itemSelected(template)
|
||||||
|
bottomSheet.cancel()
|
||||||
|
}
|
||||||
|
linearLayout.addView(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
bottomSheet.show()
|
||||||
|
bottomSheet.window!!.setLayout(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +145,7 @@ class DownloadWorker(
|
||||||
|
|
||||||
val ext = downloadItem.format.container
|
val ext = downloadItem.format.container
|
||||||
if (audioQualityId.isBlank() || ext == "Default") request.addOption("-x")
|
if (audioQualityId.isBlank() || ext == "Default") request.addOption("-x")
|
||||||
request.addOption("-f", audioQualityId)
|
else request.addOption("-f", audioQualityId)
|
||||||
|
|
||||||
if(ext != "webm"){
|
if(ext != "webm"){
|
||||||
val codec = when(downloadItem.format.container){
|
val codec = when(downloadItem.format.container){
|
||||||
|
|
|
||||||
|
|
@ -216,4 +216,5 @@
|
||||||
<string name="video_recommendations_summary">Get Recommended Youtube Videos on the Home Screen from Invidious</string>
|
<string name="video_recommendations_summary">Get Recommended Youtube Videos on the Home Screen from Invidious</string>
|
||||||
<string name="preferred_search_engine">Preferred Search Engine</string>
|
<string name="preferred_search_engine">Preferred Search Engine</string>
|
||||||
<string name="preferred_search_engine_summary">The search engine to use for in-app searches</string>
|
<string name="preferred_search_engine_summary">The search engine to use for in-app searches</string>
|
||||||
|
<string name="format_filtering_hint">All items must be of the same type to use this option</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in a new issue