Fixed quotes breaking command, removed format sorting by default, moved to advanced settings
This commit is contained in:
parent
1a4c515262
commit
0bb9d9d8fb
14 changed files with 326 additions and 203 deletions
|
|
@ -532,12 +532,19 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
|||
|
||||
|
||||
fun getFormat(formats: List<Format>, type: Type, url: String? = null) : Format {
|
||||
val sortFormats = sharedPreferences.getBoolean("use_format_sorting", false)
|
||||
|
||||
when(type) {
|
||||
Type.audio -> {
|
||||
return cloneFormat (
|
||||
try {
|
||||
val theFormats = formats.filter { it.vcodec.isBlank() || it.vcodec == "none" }
|
||||
FormatUtil(application).sortAudioFormats(theFormats).first()
|
||||
|
||||
if (sortFormats) {
|
||||
FormatUtil(application).sortAudioFormats(theFormats).first()
|
||||
}else {
|
||||
theFormats.first()
|
||||
}
|
||||
}catch (e: Exception){
|
||||
formatUtil.getGenericAudioFormats(resources).first()
|
||||
}
|
||||
|
|
@ -551,9 +558,11 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
|||
formatUtil.getGenericVideoFormats(resources).sortedByDescending { it.filesize }
|
||||
}
|
||||
|
||||
val sorted = FormatUtil(application).sortVideoFormats(theFormats)
|
||||
println(sorted.map { it.vcodec })
|
||||
sorted.first()
|
||||
if (sortFormats) {
|
||||
FormatUtil(application).sortVideoFormats(theFormats).first()
|
||||
}else {
|
||||
theFormats.first()
|
||||
}
|
||||
}catch (e: Exception){
|
||||
formatUtil.getGenericVideoFormats(resources).first()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.app.Activity
|
|||
import android.content.SharedPreferences
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.text.TextUtils
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
|
|
@ -23,6 +24,8 @@ import com.deniscerri.ytdl.database.models.CommandTemplate
|
|||
import com.deniscerri.ytdl.database.models.YoutubePlayerClientItem
|
||||
import com.deniscerri.ytdl.util.Extensions.popup
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
|
||||
class YoutubePlayerClientAdapter(onItemClickListener: OnItemClickListener, activity: Activity, private var itemTouchHelper: ItemTouchHelper) : ListAdapter<YoutubePlayerClientItem?, YoutubePlayerClientAdapter.ViewHolder>(AsyncDifferConfig.Builder(
|
||||
|
|
@ -61,21 +64,38 @@ class YoutubePlayerClientAdapter(onItemClickListener: OnItemClickListener, activ
|
|||
val title = card.findViewById<TextView>(R.id.title)
|
||||
title.text = item.playerClient
|
||||
|
||||
val content = card.findViewById<TextView>(R.id.content)
|
||||
content.isVisible = item.poTokens.isNotEmpty()
|
||||
if (item.poTokens.isNotEmpty()) {
|
||||
val text = item.poTokens.joinToString("\n") { "PO Token (${it.context}): ${it.token}" }
|
||||
content.text = text
|
||||
val content = card.findViewById<ChipGroup>(R.id.content)
|
||||
val chips = mutableListOf<TextView>()
|
||||
item.poTokens.forEach {
|
||||
val tmp = activity.layoutInflater.inflate(R.layout.textview_chip, content, false) as TextView
|
||||
tmp.maxWidth = 500
|
||||
tmp.maxLines = 1
|
||||
tmp.ellipsize = TextUtils.TruncateAt.END
|
||||
val text = "PO Token (${it.context}): ${it.token}"
|
||||
tmp.text = text
|
||||
chips.add(tmp)
|
||||
}
|
||||
|
||||
for (chip in chips.reversed()) {
|
||||
content.addView(chip, 0)
|
||||
}
|
||||
|
||||
if (item.urlRegex.isNotEmpty()) {
|
||||
val text = content.text.toString() + "\nURL Regex: " + item.urlRegex.joinToString(", ")
|
||||
content.text = text
|
||||
val text = "URL Regex: " + item.urlRegex.joinToString(", ")
|
||||
content.findViewById<TextView>(R.id.urlRegex).apply {
|
||||
isVisible = true
|
||||
setText(text)
|
||||
}
|
||||
}
|
||||
|
||||
title.alpha = if (item.enabled) 1f else 0.3f
|
||||
content.alpha = if (item.enabled) 1f else 0.3f
|
||||
|
||||
val switch = card.findViewById<MaterialSwitch>(R.id.materialSwitch)
|
||||
switch.isChecked = item.enabled
|
||||
switch.setOnClickListener {
|
||||
title.alpha = if (switch.isChecked) 1f else 0.3f
|
||||
content.alpha = if (switch.isChecked) 1f else 0.3f
|
||||
onItemClickListener.onStatusToggle(item, switch.isChecked, position)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ class ProcessingSettingsFragment : BaseSettingsFragment() {
|
|||
val preferredFormatID : EditTextPreference? = findPreference("format_id")
|
||||
val preferredFormatIDAudio : EditTextPreference? = findPreference("format_id_audio")
|
||||
val subtitleLanguages : Preference? = findPreference("subs_lang")
|
||||
val formatImportanceAudio: Preference? = findPreference("format_importance_audio")
|
||||
val formatImportanceVideo: Preference? = findPreference("format_importance_video")
|
||||
|
||||
|
||||
preferredFormatID?.title = "${getString(R.string.preferred_format_id)} [${getString(R.string.video)}]"
|
||||
preferredFormatID?.dialogTitle = "${getString(R.string.file_name_template)} [${getString(R.string.video)}]"
|
||||
|
|
@ -50,50 +49,6 @@ class ProcessingSettingsFragment : BaseSettingsFragment() {
|
|||
}
|
||||
|
||||
|
||||
formatImportanceAudio?.apply {
|
||||
title = "${getString(R.string.format_importance)} [${getString(R.string.audio)}]"
|
||||
val items = requireContext().getStringArray(R.array.format_importance_audio)
|
||||
val itemValues = requireContext().getStringArray(R.array.format_importance_audio_values).toSet()
|
||||
val prefVideo = prefs.getString("format_importance_audio", itemValues.joinToString(","))!!
|
||||
summary = prefVideo.split(",").mapIndexed { index, s -> "${index + 1}. ${items[itemValues.indexOf(s)]}" }.joinToString("\n")
|
||||
|
||||
setOnPreferenceClickListener {
|
||||
val pref = prefs.getString("format_importance_audio", itemValues.joinToString(","))!!
|
||||
val prefArr = pref.split(",")
|
||||
val itms = itemValues.sortedBy { prefArr.indexOf(it) }.map {
|
||||
Pair(it, items[itemValues.indexOf(it)])
|
||||
}.toMutableList()
|
||||
|
||||
showFormatImportanceDialog(title.toString(), itms) { new ->
|
||||
editor.putString("format_importance_audio", new.joinToString(",") { it.first }).apply()
|
||||
formatImportanceAudio.summary = new.map { it.second }.mapIndexed { index, s -> "${index + 1}. $s" }.joinToString("\n")
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
formatImportanceVideo?.apply {
|
||||
title = "${getString(R.string.format_importance)} [${getString(R.string.video)}]"
|
||||
val items = requireContext().getStringArray(R.array.format_importance_video)
|
||||
val itemValues = requireContext().getStringArray(R.array.format_importance_video_values).toSet()
|
||||
val prefVideo = prefs.getString("format_importance_video", itemValues.joinToString(","))!!
|
||||
summary = prefVideo.split(",").mapIndexed { index, s -> "${index + 1}. ${items[itemValues.indexOf(s)]}" }.joinToString("\n")
|
||||
|
||||
setOnPreferenceClickListener {
|
||||
val pref = prefs.getString("format_importance_video", itemValues.joinToString(","))!!
|
||||
val prefArr = pref.split(",")
|
||||
val itms = itemValues.sortedBy { prefArr.indexOf(it) }.map {
|
||||
Pair(it, items[itemValues.indexOf(it)])
|
||||
}.toMutableList()
|
||||
|
||||
showFormatImportanceDialog(title.toString(), itms) {new ->
|
||||
editor.putString("format_importance_video", new.joinToString(",") { it.first }).apply()
|
||||
formatImportanceVideo.summary = new.map { it.second }.mapIndexed { index, s -> "${index + 1}. $s" }.joinToString("\n")
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
findPreference<EditTextPreference>("format_id")?.apply {
|
||||
val s = getString(R.string.preferred_format_id_summary)
|
||||
summary = if (text.isNullOrBlank()) {
|
||||
|
|
@ -128,77 +83,4 @@ class ProcessingSettingsFragment : BaseSettingsFragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun showFormatImportanceDialog(t: String, items: MutableList<Pair<String, String>>, onChange: (items: List<Pair<String, String>>) -> Unit){
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
builder.setTitle(t)
|
||||
val adapter = SortableTextItemAdapter(items)
|
||||
val itemTouchCallback = object : ItemTouchHelper.Callback() {
|
||||
override fun getMovementFlags(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
): Int {
|
||||
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
|
||||
return makeMovementFlags(dragFlags, 0)
|
||||
}
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
val itemToMove = adapter.items[viewHolder.absoluteAdapterPosition]
|
||||
adapter.items.remove(itemToMove)
|
||||
adapter.items.add(target.absoluteAdapterPosition, itemToMove)
|
||||
|
||||
adapter.notifyItemMoved(
|
||||
viewHolder.absoluteAdapterPosition,
|
||||
target.absoluteAdapterPosition
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
val linear = LinearLayout(requireActivity())
|
||||
linear.orientation = LinearLayout.VERTICAL
|
||||
|
||||
val note = TextView(requireActivity())
|
||||
note.text = getString(R.string.format_importance_note)
|
||||
note.textSize = 16f
|
||||
note.setTypeface(note.typeface, Typeface.BOLD)
|
||||
note.setPadding(20,20,20,20)
|
||||
linear.addView(note)
|
||||
|
||||
val recycler = RecyclerView(requireContext())
|
||||
recycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
recycler.adapter = adapter
|
||||
|
||||
linear.addView(recycler)
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recycler)
|
||||
|
||||
|
||||
builder.setView(linear)
|
||||
builder.setPositiveButton(
|
||||
getString(android.R.string.ok)
|
||||
) { _: DialogInterface?, _: Int ->
|
||||
onChange(adapter.items)
|
||||
}
|
||||
|
||||
// handle the negative button of the alert dialog
|
||||
builder.setNegativeButton(
|
||||
getString(R.string.cancel)
|
||||
) { _: DialogInterface?, _: Int -> }
|
||||
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,13 +1,23 @@
|
|||
package com.deniscerri.ytdl.ui.more.settings.advanced
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdl.R
|
||||
import com.deniscerri.ytdl.ui.adapter.SortableTextItemAdapter
|
||||
import com.deniscerri.ytdl.ui.more.settings.BaseSettingsFragment
|
||||
import com.deniscerri.ytdl.util.UiUtil
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
|
||||
class AdvancedSettingsFragment : BaseSettingsFragment() {
|
||||
|
|
@ -15,9 +25,132 @@ class AdvancedSettingsFragment : BaseSettingsFragment() {
|
|||
@SuppressLint("RestrictedApi")
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.advanced_preferences, rootKey)
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
val editor = prefs.edit()
|
||||
|
||||
findPreference<Preference>("yt_player_client")?.setOnPreferenceClickListener {
|
||||
findNavController().navigate(R.id.youtubePlayerClientFragment)
|
||||
false
|
||||
}
|
||||
|
||||
val formatImportanceAudio: Preference? = findPreference("format_importance_audio")
|
||||
val formatImportanceVideo: Preference? = findPreference("format_importance_video")
|
||||
|
||||
formatImportanceAudio?.apply {
|
||||
title = "${getString(R.string.format_importance)} [${getString(R.string.audio)}]"
|
||||
val items = requireContext().getStringArray(R.array.format_importance_audio)
|
||||
val itemValues = requireContext().getStringArray(R.array.format_importance_audio_values).toSet()
|
||||
val prefVideo = prefs.getString("format_importance_audio", itemValues.joinToString(","))!!
|
||||
summary = prefVideo.split(",").mapIndexed { index, s -> "${index + 1}. ${items[itemValues.indexOf(s)]}" }.joinToString("\n")
|
||||
|
||||
setOnPreferenceClickListener {
|
||||
val pref = prefs.getString("format_importance_audio", itemValues.joinToString(","))!!
|
||||
val prefArr = pref.split(",")
|
||||
val itms = itemValues.sortedBy { prefArr.indexOf(it) }.map {
|
||||
Pair(it, items[itemValues.indexOf(it)])
|
||||
}.toMutableList()
|
||||
|
||||
showFormatImportanceDialog(title.toString(), itms) { new ->
|
||||
editor.putString("format_importance_audio", new.joinToString(",") { it.first }).apply()
|
||||
formatImportanceAudio.summary = new.map { it.second }.mapIndexed { index, s -> "${index + 1}. $s" }.joinToString("\n")
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
formatImportanceVideo?.apply {
|
||||
title = "${getString(R.string.format_importance)} [${getString(R.string.video)}]"
|
||||
val items = requireContext().getStringArray(R.array.format_importance_video)
|
||||
val itemValues = requireContext().getStringArray(R.array.format_importance_video_values).toSet()
|
||||
val prefVideo = prefs.getString("format_importance_video", itemValues.joinToString(","))!!
|
||||
summary = prefVideo.split(",").mapIndexed { index, s -> "${index + 1}. ${items[itemValues.indexOf(s)]}" }.joinToString("\n")
|
||||
|
||||
setOnPreferenceClickListener {
|
||||
val pref = prefs.getString("format_importance_video", itemValues.joinToString(","))!!
|
||||
val prefArr = pref.split(",")
|
||||
val itms = itemValues.sortedBy { prefArr.indexOf(it) }.map {
|
||||
Pair(it, items[itemValues.indexOf(it)])
|
||||
}.toMutableList()
|
||||
|
||||
showFormatImportanceDialog(title.toString(), itms) {new ->
|
||||
editor.putString("format_importance_video", new.joinToString(",") { it.first }).apply()
|
||||
formatImportanceVideo.summary = new.map { it.second }.mapIndexed { index, s -> "${index + 1}. $s" }.joinToString("\n")
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun showFormatImportanceDialog(t: String, items: MutableList<Pair<String, String>>, onChange: (items: List<Pair<String, String>>) -> Unit){
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
builder.setTitle(t)
|
||||
val adapter = SortableTextItemAdapter(items)
|
||||
val itemTouchCallback = object : ItemTouchHelper.Callback() {
|
||||
override fun getMovementFlags(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
): Int {
|
||||
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
|
||||
return makeMovementFlags(dragFlags, 0)
|
||||
}
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
val itemToMove = adapter.items[viewHolder.absoluteAdapterPosition]
|
||||
adapter.items.remove(itemToMove)
|
||||
adapter.items.add(target.absoluteAdapterPosition, itemToMove)
|
||||
|
||||
adapter.notifyItemMoved(
|
||||
viewHolder.absoluteAdapterPosition,
|
||||
target.absoluteAdapterPosition
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
val linear = LinearLayout(requireActivity())
|
||||
linear.orientation = LinearLayout.VERTICAL
|
||||
|
||||
val note = TextView(requireActivity())
|
||||
note.text = getString(R.string.format_importance_note)
|
||||
note.textSize = 16f
|
||||
note.setTypeface(note.typeface, Typeface.BOLD)
|
||||
note.setPadding(20,20,20,20)
|
||||
linear.addView(note)
|
||||
|
||||
val recycler = RecyclerView(requireContext())
|
||||
recycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
recycler.adapter = adapter
|
||||
|
||||
linear.addView(recycler)
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recycler)
|
||||
|
||||
|
||||
builder.setView(linear)
|
||||
builder.setPositiveButton(
|
||||
getString(android.R.string.ok)
|
||||
) { _: DialogInterface?, _: Int ->
|
||||
onChange(adapter.items)
|
||||
}
|
||||
|
||||
// handle the negative button of the alert dialog
|
||||
builder.setNegativeButton(
|
||||
getString(R.string.cancel)
|
||||
) { _: DialogInterface?, _: Int -> }
|
||||
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
|
|
@ -364,8 +364,8 @@ class TerminalFragment : Fragment() {
|
|||
.observe(viewLifecycleOwner, workerObserver)
|
||||
}
|
||||
|
||||
private val workerObserver = object: Observer<MutableList<WorkInfo>> {
|
||||
override fun onChanged(value: MutableList<WorkInfo>) {
|
||||
private val workerObserver = object: Observer<List<WorkInfo>> {
|
||||
override fun onChanged(value: List<WorkInfo>) {
|
||||
value.forEach { work ->
|
||||
if (listOf(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED).contains(work.state)) {
|
||||
requireActivity().runOnUiThread {
|
||||
|
|
|
|||
|
|
@ -1500,6 +1500,7 @@ object UiUtil {
|
|||
val cut = view.findViewById<Chip>(R.id.cut)
|
||||
if (items.size > 1 || items.first().url.isEmpty()) cut.isVisible = false
|
||||
else{
|
||||
cut.setOnClickListener(null)
|
||||
val invalidDuration = items[0].duration == "-1"
|
||||
if(items[0].duration.isNotEmpty() && !invalidDuration){
|
||||
val downloadItem = items[0]
|
||||
|
|
@ -1664,6 +1665,7 @@ object UiUtil {
|
|||
val cut = view.findViewById<Chip>(R.id.cut)
|
||||
if (items.size > 1 || items.first().url.isEmpty()) cut.isVisible = false
|
||||
else{
|
||||
cut.setOnClickListener(null)
|
||||
val downloadItem = items[0]
|
||||
val invalidDuration = downloadItem.duration == "-1"
|
||||
if (downloadItem.duration.isNotEmpty() && !invalidDuration){
|
||||
|
|
|
|||
|
|
@ -823,40 +823,49 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
}
|
||||
request.addOption("-x")
|
||||
|
||||
val formatSorting = mutableListOf("hasaud")
|
||||
val formatImportance = formatUtil.getAudioFormatImportance()
|
||||
for(order in formatImportance) {
|
||||
when(order) {
|
||||
"file_size" -> {
|
||||
formatSorting.add("size")
|
||||
}
|
||||
"language" -> {
|
||||
if (preferredLanguage.isNotBlank()) {
|
||||
formatSorting.add("lang:${preferredLanguage}")
|
||||
val formatSorting = mutableListOf<String>()
|
||||
if (sharedPreferences.getBoolean("use_format_sorting", false)) {
|
||||
formatSorting.add("hasaud")
|
||||
val formatImportance = formatUtil.getAudioFormatImportance()
|
||||
for(order in formatImportance) {
|
||||
when(order) {
|
||||
"file_size" -> {
|
||||
formatSorting.add("size")
|
||||
}
|
||||
}
|
||||
"codec" -> {
|
||||
if (aCodecPref.isNotBlank()){
|
||||
formatSorting.add("acodec:$aCodecPref")
|
||||
"language" -> {
|
||||
if (preferredLanguage.isNotBlank()) {
|
||||
formatSorting.add("lang:${preferredLanguage}")
|
||||
}
|
||||
}
|
||||
}
|
||||
"container" -> {
|
||||
if(ext.isNotBlank()){
|
||||
if(!ext.matches("(webm)|(Default)|(${context.getString(R.string.defaultValue)})".toRegex()) && supportedContainers.contains(ext)){
|
||||
request.addOption("--audio-format", ext)
|
||||
formatSorting.add("aext:$ext")
|
||||
"codec" -> {
|
||||
if (aCodecPref.isNotBlank()){
|
||||
formatSorting.add("acodec:$aCodecPref")
|
||||
}
|
||||
}
|
||||
"container" -> {
|
||||
if(ext.isNotBlank()){
|
||||
if(!ext.matches("(webm)|(Default)|(${context.getString(R.string.defaultValue)})".toRegex()) && supportedContainers.contains(ext)){
|
||||
request.addOption("--audio-format", ext)
|
||||
formatSorting.add("aext:$ext")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadItem.format.format_id == context.resources.getString(R.string.worst_quality) || downloadItem.format.format_id == "wa" || downloadItem.format.format_id == "worst") {
|
||||
if(formatSorting.contains("size")) {
|
||||
formatSorting.remove("size")
|
||||
}
|
||||
formatSorting.addAll(0,listOf("+br", "+res", "+fps"))
|
||||
}
|
||||
}else if (preferredLanguage.isNotBlank()) {
|
||||
formatSorting.add("lang:${preferredLanguage}")
|
||||
}
|
||||
|
||||
|
||||
if (downloadItem.format.format_id == context.resources.getString(R.string.worst_quality) || downloadItem.format.format_id == "wa" || downloadItem.format.format_id == "worst") {
|
||||
if(formatSorting.contains("size")) {
|
||||
formatSorting.remove("size")
|
||||
}
|
||||
formatSorting.addAll(0,listOf("+br", "+res", "+fps"))
|
||||
if (sharedPreferences.getBoolean("prefer_smaller_formats", false) && !formatSorting.contains("+size")) {
|
||||
formatSorting.remove("size")
|
||||
formatSorting.add(0, "+size")
|
||||
}
|
||||
|
||||
if (abrSort.isNotBlank()){
|
||||
|
|
@ -867,7 +876,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
request.addOption("-S", formatSorting.joinToString(","))
|
||||
}
|
||||
|
||||
|
||||
request.addOption("-P", downDir.absolutePath)
|
||||
|
||||
|
||||
|
|
@ -1119,38 +1127,41 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
val formatImportance = formatUtil.getVideoFormatImportance()
|
||||
val formatSorting = mutableListOf<String>()
|
||||
|
||||
for(order in formatImportance) {
|
||||
when(order) {
|
||||
"no_audio" -> {
|
||||
formatSorting.add("+hasaud")
|
||||
}
|
||||
"codec" -> {
|
||||
if (vCodecPref.isNotBlank()) formatSorting.add("vcodec:$vCodecPref")
|
||||
if (aCodecPref.isNotBlank()) formatSorting.add("acodec:$aCodecPref")
|
||||
}
|
||||
"resolution" -> {
|
||||
if (hasGenericResulutionFormat.isNotBlank()) {
|
||||
formatSorting.add("res:${hasGenericResulutionFormat}")
|
||||
if (sharedPreferences.getBoolean("use_format_sorting", false)) {
|
||||
for(order in formatImportance) {
|
||||
when(order) {
|
||||
"no_audio" -> {
|
||||
formatSorting.add("+hasaud")
|
||||
}
|
||||
"codec" -> {
|
||||
if (vCodecPref.isNotBlank()) formatSorting.add("vcodec:$vCodecPref")
|
||||
if (aCodecPref.isNotBlank()) formatSorting.add("acodec:$aCodecPref")
|
||||
}
|
||||
"resolution" -> {
|
||||
if (hasGenericResulutionFormat.isNotBlank()) {
|
||||
formatSorting.add("res:${hasGenericResulutionFormat}")
|
||||
}
|
||||
}
|
||||
"container" -> {
|
||||
if (cont.isNotBlank()) formatSorting.add("vext:$cont")
|
||||
if (acont.isNotBlank()) formatSorting.add("aext:$acont")
|
||||
}
|
||||
}
|
||||
"container" -> {
|
||||
if (cont.isNotBlank()) formatSorting.add("vext:$cont")
|
||||
if (acont.isNotBlank()) formatSorting.add("aext:$acont")
|
||||
}
|
||||
|
||||
if (downloadItem.format.format_id == context.resources.getString(R.string.worst_quality) || downloadItem.format.format_id == "worst") {
|
||||
formatSorting.addAll(0, listOf("+br","+res","+fps"))
|
||||
}else {
|
||||
if (sharedPreferences.getBoolean("prefer_smaller_formats", false)) {
|
||||
formatSorting.add(0, "+size")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadItem.format.format_id == context.resources.getString(R.string.worst_quality) || downloadItem.format.format_id == "worst") {
|
||||
formatSorting.addAll(0, listOf("+br","+res","+fps"))
|
||||
}else {
|
||||
if (sharedPreferences.getBoolean("prefer_smaller_formats", false)) {
|
||||
formatSorting.add(0, "+size")
|
||||
}else {
|
||||
formatSorting.add(0, "size")
|
||||
}
|
||||
if (sharedPreferences.getBoolean("prefer_smaller_formats", false) && !formatSorting.contains("+br")) {
|
||||
formatSorting.add(0, "+size")
|
||||
}
|
||||
|
||||
|
||||
if (abrSort.isNotBlank()) {
|
||||
formatSorting.add("abr~${abrSort}")
|
||||
}
|
||||
|
|
@ -1324,7 +1335,11 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
this.add(elements.first().toString())
|
||||
if (elements.size > 1) {
|
||||
for (el in elements.drop(1)) {
|
||||
this.add(""""$el"""")
|
||||
val arg = el.toString()
|
||||
.replace("\\", "\\\\")
|
||||
.replace("\"", "\\\"")
|
||||
|
||||
this.add("\"$arg\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
app/src/main/res/drawable/baseline_arrow_upward_24.xml
Normal file
5
app/src/main/res/drawable/baseline_arrow_upward_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="?android:colorAccent" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -49,17 +49,41 @@
|
|||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:textSize="14sp"
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
android:id="@+id/content"
|
||||
app:chipSpacing="0dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/urlRegex"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="URL Regex"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorAccent"
|
||||
android:clickable="false"
|
||||
android:gravity="center"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/materialSwitch"
|
||||
|
|
|
|||
19
app/src/main/res/layout/textview_chip.xml
Normal file
19
app/src/main/res/layout/textview_chip.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Primary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorTertiaryContainer"
|
||||
android:clickable="false"
|
||||
android:gravity="center"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
|
@ -464,4 +464,5 @@
|
|||
<string name="cache_directory">Cache Folder</string>
|
||||
<string name="cache_directory_warning">Changing the Cache Folder might cause unexpected issues. If the app cannot write to the configured path, it will resort to the default internal cache directory</string>
|
||||
<string name="app_icon_change">Icon could change and Application will close</string>
|
||||
<string name="use_format_sorting">Use Format Importance Ordering</string>
|
||||
</resources>
|
||||
|
|
@ -34,7 +34,29 @@
|
|||
android:title="@string/data_fetching_extra_command" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/downloading" android:enabled="false">
|
||||
<PreferenceCategory android:title="@string/format">
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
app:defaultValue="false"
|
||||
app:icon="@drawable/baseline_arrow_upward_24"
|
||||
app:key="use_format_sorting"
|
||||
app:title="@string/use_format_sorting" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_format"
|
||||
android:key="format_importance_video"
|
||||
android:dependency="use_format_sorting"
|
||||
app:title="@string/format_importance" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_format"
|
||||
android:key="format_importance_audio"
|
||||
android:dependency="use_format_sorting"
|
||||
app:title="@string/format_importance" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/downloading" android:enabled="false" app:isPreferenceVisible="false">
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
android:icon="@drawable/if_file_rename"
|
||||
|
|
|
|||
|
|
@ -285,15 +285,6 @@
|
|||
app:key="prefer_smaller_formats"
|
||||
app:title="@string/prefer_smaller_formats" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_format"
|
||||
android:key="format_importance_video"
|
||||
app:title="@string/format_importance" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_format"
|
||||
android:key="format_importance_audio"
|
||||
app:title="@string/format_importance" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ buildscript {
|
|||
youtubedlAndroidVerNoPyCrypto = "97bee6c0e8"
|
||||
youtubedlAndroidVerMine = "8831745ea3"
|
||||
oldytdlAndroidVer = "0.14.0"
|
||||
workVer = "2.9.1"
|
||||
workVer = "2.10.0"
|
||||
composeVer = '1.4.2'
|
||||
kotlinVer = "1.7.21"
|
||||
coroutineVer = '1.7.3'
|
||||
|
|
|
|||
Loading…
Reference in a new issue